|
From: <jfb...@us...> - 2009-03-05 22:05:00
|
Revision: 1001
http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1001&view=rev
Author: jfbastien
Date: 2009-03-05 22:04:56 +0000 (Thu, 05 Mar 2009)
Log Message:
-----------
Bug #2666059: cap buffer size to 126.
Modified Paths:
--------------
trunk/include/loki/flex/smallstringopt.h
Modified: trunk/include/loki/flex/smallstringopt.h
===================================================================
--- trunk/include/loki/flex/smallstringopt.h 2009-03-05 21:12:02 UTC (rev 1000)
+++ trunk/include/loki/flex/smallstringopt.h 2009-03-05 22:04:56 UTC (rev 1001)
@@ -31,7 +31,7 @@
typedef @ const_iterator;
typedef A allocator_type;
typedef @ size_type;
-
+
StoragePolicy(const StoragePolicy& s);
StoragePolicy(const A&);
StoragePolicy(const E* s, size_type len, const A&);
@@ -42,7 +42,7 @@
const_iterator begin() const;
iterator end();
const_iterator end() const;
-
+
size_type size() const;
size_type max_size() const;
size_type capacity() const;
@@ -50,17 +50,17 @@
void reserve(size_type res_arg);
void append(const E* s, size_type sz);
-
+
template <class InputIterator>
void append(InputIterator b, InputIterator e);
void resize(size_type newSize, E fill);
void swap(StoragePolicy& rhs);
-
+
const E* c_str() const;
const E* data() const;
-
+
A get_allocator() const;
};
////////////////////////////////////////////////////////////////////////////////
@@ -74,12 +74,24 @@
#include <stdexcept>
#include "flex_string_details.h"
+namespace SmallStringOptImpl
+{
+ // The threshold for SmallStringOpt cannot be greater than 126. See Loki bug #2666059 for more details:
+ // https://sourceforge.net/tracker2/?func=detail&aid=2666059&group_id=29557&atid=396644
+ template<int Expression> struct BufferSizeCannotBeGreaterThan126;
+ template<> struct BufferSizeCannotBeGreaterThan126<true> { };
+
+#define LOKI_FLEX_STRING_BUFFERSIZECANNOTBEGREATERTHAN126(expression) \
+ { SmallStringOptImpl::BufferSizeCannotBeGreaterThan126<((expression) != 0)> \
+ bufferSizeCannotBeGreaterThan126; (void)bufferSizeCannotBeGreaterThan126; }
+}
+
////////////////////////////////////////////////////////////////////////////////
// class template SmallStringOpt
// Builds the small string optimization over any other storage
////////////////////////////////////////////////////////////////////////////////
-template <class Storage, unsigned int threshold,
+template <class Storage, unsigned int threshold,
typename Align = typename Storage::value_type*>
class SmallStringOpt
{
@@ -90,54 +102,56 @@
typedef typename Storage::allocator_type allocator_type;
typedef typename allocator_type::size_type size_type;
typedef typename Storage::reference reference;
-
+
private:
- enum { temp1 = threshold * sizeof(value_type) > sizeof(Storage)
- ? threshold * sizeof(value_type)
+ enum { temp1 = threshold * sizeof(value_type) > sizeof(Storage)
+ ? threshold * sizeof(value_type)
: sizeof(Storage) };
-
+
enum { temp2 = temp1 > sizeof(Align) ? temp1 : sizeof(Align) };
public:
- enum { maxSmallString =
+ enum { maxSmallString =
(temp2 + sizeof(value_type) - 1) / sizeof(value_type) };
-
+
private:
enum { magic = maxSmallString + 1 };
-
+
union
{
mutable value_type buf_[maxSmallString + 1];
Align align_;
};
-
+
Storage& GetStorage()
{
assert(buf_[maxSmallString] == magic);
Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
return *p;
}
-
+
const Storage& GetStorage() const
{
assert(buf_[maxSmallString] == magic);
const Storage *p = reinterpret_cast<const Storage*>(&buf_[0]);
return *p;
}
-
+
bool Small() const
{
return buf_[maxSmallString] != magic;
}
-
+
public:
- SmallStringOpt(const SmallStringOpt& s)
+ SmallStringOpt(const SmallStringOpt& s)
{
+ LOKI_FLEX_STRING_BUFFERSIZECANNOTBEGREATERTHAN126(maxSmallString <= 126)
+
if (s.Small())
{
flex_string_details::pod_copy(
- s.buf_,
- s.buf_ + s.size(),
+ s.buf_,
+ s.buf_ + s.size(),
buf_);
}
else
@@ -146,12 +160,12 @@
}
buf_[maxSmallString] = s.buf_[maxSmallString];
}
-
+
SmallStringOpt(const allocator_type&)
{
buf_[maxSmallString] = maxSmallString;
}
-
+
SmallStringOpt(const value_type* s, size_type len, const allocator_type& a)
{
if (len <= maxSmallString)
@@ -179,7 +193,7 @@
buf_[maxSmallString] = magic;
}
}
-
+
// Fix suggested by Andrew Barnert on 07/03/2007
SmallStringOpt& operator=(const SmallStringOpt& rhs)
{
@@ -228,32 +242,32 @@
iterator begin()
{
if (Small()) return buf_;
- return &*GetStorage().begin();
+ return &*GetStorage().begin();
}
-
+
const_iterator begin() const
{
if (Small()) return buf_;
- return &*GetStorage().begin();
+ return &*GetStorage().begin();
}
-
+
iterator end()
{
if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
- return &*GetStorage().end();
+ return &*GetStorage().end();
}
-
+
const_iterator end() const
{
if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
- return &*GetStorage().end();
+ return &*GetStorage().end();
}
-
+
size_type size() const
{
assert(!Small() || maxSmallString >= buf_[maxSmallString]);
- return Small()
- ? maxSmallString - buf_[maxSmallString]
+ return Small()
+ ? maxSmallString - buf_[maxSmallString]
: GetStorage().size();
}
@@ -270,7 +284,7 @@
if (res_arg <= maxSmallString) return;
SmallStringOpt temp(*this);
this->~SmallStringOpt();
- new(buf_) Storage(temp.data(), temp.size(),
+ new(buf_) Storage(temp.data(), temp.size(),
temp.get_allocator());
buf_[maxSmallString] = magic;
GetStorage().reserve(res_arg);
@@ -281,7 +295,7 @@
}
assert(capacity() >= res_arg);
}
-
+
template <class FwdIterator>
void append(FwdIterator b, FwdIterator e)
{
@@ -292,7 +306,7 @@
else
{
// append to a small string
- const size_type
+ const size_type
sz = std::distance(b, e),
neededCapacity = maxSmallString - buf_[maxSmallString] + sz;
@@ -325,7 +339,7 @@
// Small string resized to big string
SmallStringOpt temp(*this); // can't throw
// 11-17-2001: correct exception safety bug
- Storage newString(temp.data(), temp.size(),
+ Storage newString(temp.data(), temp.size(),
temp.get_allocator());
newString.resize(n, c);
// We make the reasonable assumption that an empty Storage
@@ -379,7 +393,7 @@
if (rhs.Small())
{
// Small swapped with small
- std::swap_ranges(buf_, buf_ + maxSmallString + 1,
+ std::swap_ranges(buf_, buf_ + maxSmallString + 1,
rhs.buf_);
}
else
@@ -415,17 +429,17 @@
}
}
}
-
+
const value_type* c_str() const
- {
- if (!Small()) return GetStorage().c_str();
+ {
+ if (!Small()) return GetStorage().c_str();
buf_[maxSmallString - buf_[maxSmallString]] = value_type();
return buf_;
}
const value_type* data() const
{ return Small() ? buf_ : GetStorage().data(); }
-
+
allocator_type get_allocator() const
{ return allocator_type(); }
};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|