| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588 |
- /*=============================================================================
- Boost.Wave: A Standard compliant C++ preprocessor library
- http://www.boost.org/
- Copyright (c) 2001 by Andrei Alexandrescu. Distributed under the Boost
- Software License, Version 1.0. (See accompanying file
- LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- =============================================================================*/
- // This code is taken from:
- // Andrei Alexandrescu, Generic<Programming>: A Policy-Based basic_string
- // Implementation. http://www.cuj.com/documents/s=7994/cujcexp1906alexandr/
- //
- // #HK030306:
- // - Moved into the namespace boost::wave::util
- // - Added a bunch of missing typename(s)
- // - Integrated with boost config
- // - Added a missing header include
- // - Added special constructors and operator= to allow CowString to be
- // a real COW-string (removed unnecessary data copying)
- // - Fixed a string terminating bug in append
- //
- // #HK040109:
- // - Incorporated the changes from Andrei's latest version of this class
- //
- // #HK070307:
- // - Once again incorporated the changes from Andrei's latest version of
- // this class
- //
- // #HK090523:
- // - Incorporated the changes from latest version of flex_string as
- // maintained in Loki
- //
- // #HK130910:
- // - Removed the getline implementation which was borrowed from the SGI
- // STL as the license for this code is not compatible with Boost.
- #ifndef BOOST_FLEX_STRING_INC_
- #define BOOST_FLEX_STRING_INC_
- /*
- ////////////////////////////////////////////////////////////////////////////////
- template <typename E, class A = @>
- class StoragePolicy
- {
- typedef E value_type;
- typedef @ iterator;
- 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&);
- StoragePolicy(size_type len, E c, const A&);
- ~StoragePolicy();
- iterator begin();
- const_iterator begin() const;
- iterator end();
- const_iterator end() const;
- size_type size() const;
- size_type max_size() const;
- size_type capacity() const;
- 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;
- };
- ////////////////////////////////////////////////////////////////////////////////
- */
- #include <boost/config.hpp>
- #include <boost/assert.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/core/allocator_access.hpp>
- #include <boost/iterator/reverse_iterator.hpp>
- #include <boost/wave/wave_config.hpp>
- #if BOOST_WAVE_SERIALIZATION != 0
- #include <boost/serialization/serialization.hpp>
- #include <boost/serialization/split_free.hpp>
- #include <boost/serialization/collections_save_imp.hpp>
- #include <boost/serialization/collections_load_imp.hpp>
- #define BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK 1
- #endif
- #include <memory>
- #include <new>
- #include <vector>
- #include <algorithm>
- #include <functional>
- #include <limits>
- #include <stdexcept>
- #include <ios>
- #include <cstddef>
- #include <cstring>
- #include <cstdlib>
- // this must occur after all of the includes and before any code appears
- #ifdef BOOST_HAS_ABI_HEADERS
- #include BOOST_ABI_PREFIX
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost {
- namespace wave {
- namespace util {
- namespace flex_string_details
- {
- template <class InIt, class OutIt>
- OutIt copy_n(InIt b,
- typename std::iterator_traits<InIt>::difference_type n, OutIt d)
- {
- for (/**/; n != 0; --n, ++b, ++d)
- {
- *d = *b;
- }
- return d;
- }
- template <class Pod, class T>
- inline void pod_fill(Pod* b, Pod* e, T c)
- {
- switch ((e - b) & 7)
- {
- case 0:
- while (b != e)
- {
- *b = c; ++b; BOOST_FALLTHROUGH;
- case 7: *b = c; ++b; BOOST_FALLTHROUGH;
- case 6: *b = c; ++b; BOOST_FALLTHROUGH;
- case 5: *b = c; ++b; BOOST_FALLTHROUGH;
- case 4: *b = c; ++b; BOOST_FALLTHROUGH;
- case 3: *b = c; ++b; BOOST_FALLTHROUGH;
- case 2: *b = c; ++b; BOOST_FALLTHROUGH;
- case 1: *b = c; ++b;
- }
- }
- }
- template <class Pod>
- inline void pod_move(const Pod* b, const Pod* e, Pod* d)
- {
- using namespace std;
- memmove(d, b, (e - b) * sizeof(*b));
- }
- template <class Pod>
- inline Pod* pod_copy(const Pod* b, const Pod* e, Pod* d)
- {
- const std::size_t s = e - b;
- using namespace std;
- memcpy(d, b, s * sizeof(*b));
- return d + s;
- }
- template <typename T> struct get_unsigned
- {
- typedef T result;
- };
- template <> struct get_unsigned<char>
- {
- typedef unsigned char result;
- };
- template <> struct get_unsigned<signed char>
- {
- typedef unsigned char result;
- };
- template <> struct get_unsigned<short int>
- {
- typedef unsigned short int result;
- };
- template <> struct get_unsigned<int>
- {
- typedef unsigned int result;
- };
- template <> struct get_unsigned<long int>
- {
- typedef unsigned long int result;
- };
- enum Shallow {};
- }
- template <class T> class mallocator
- {
- public:
- typedef T value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef std::size_t size_type;
- //typedef unsigned int size_type;
- //typedef std::ptrdiff_t difference_type;
- typedef int difference_type;
- template <class U>
- struct rebind { typedef mallocator<U> other; };
- mallocator() {}
- mallocator(const mallocator&) {}
- //template <class U>
- //mallocator(const mallocator<U>&) {}
- ~mallocator() {}
- pointer address(reference x) const { return &x; }
- const_pointer address(const_reference x) const
- {
- return x;
- }
- pointer allocate(size_type n, const_pointer = 0)
- {
- using namespace std;
- void* p = malloc(n * sizeof(T));
- if (!p) boost::throw_exception(std::bad_alloc());
- return static_cast<pointer>(p);
- }
- void deallocate(pointer p, size_type)
- {
- using namespace std;
- free(p);
- }
- size_type max_size() const
- {
- return static_cast<size_type>(-1) / sizeof(T);
- }
- void construct(pointer p, const value_type& x)
- {
- new(p) value_type(x);
- }
- void destroy(pointer p)
- {
- p->~value_type();
- }
- private:
- void operator=(const mallocator&);
- };
- template<> class mallocator<void>
- {
- typedef void value_type;
- typedef void* pointer;
- typedef const void* const_pointer;
- template <class U>
- struct rebind { typedef mallocator<U> other; };
- };
- template <class T>
- inline bool operator==(const mallocator<T>&,
- const mallocator<T>&) {
- return true;
- }
- template <class T>
- inline bool operator!=(const mallocator<T>&,
- const mallocator<T>&) {
- return false;
- }
- #if defined(BOOST_GCC) && BOOST_GCC >= 40700
- // gcc 11.2 fails to deduce below that pData_ never points to emptyString_ if capacity() == 0 and emits warnings like these:
- // 'operator delete(void*, unsigned long)' called on unallocated object 'boost::wave::util::SimpleStringStorage<char, std::allocator<char> >::emptyString_' [-Wfree-nonheap-object]
- // Unfortunately, suppressing this warning doesn't work, so we have to use __builtin_unreachable() to assert that this never happens.
- // __builtin_unreachable is supported since gcc 4.6, -Wfree-nonheap-object is supported since 4.7.
- #define BOOST_WAVE_COMPILE_TIME_ASSERT(x) if (!(x)) __builtin_unreachable()
- #else
- #define BOOST_WAVE_COMPILE_TIME_ASSERT(x)
- #endif
- ////////////////////////////////////////////////////////////////////////////////
- // class template SimpleStringStorage
- // Allocates memory with malloc
- ////////////////////////////////////////////////////////////////////////////////
- template <typename E, class A = std::allocator<E> >
- class SimpleStringStorage
- {
- // The "public" below exists because MSVC can't do template typedefs
- public:
- struct Data
- {
- Data() : pEnd_(buffer_), pEndOfMem_(buffer_) { buffer_[0] = E(0); }
- E* pEnd_;
- E* pEndOfMem_;
- E buffer_[1];
- };
- static const Data emptyString_;
- typedef typename boost::allocator_size_type<A>::type size_type;
- private:
- Data* pData_;
- void Init(size_type size, size_type capacity)
- {
- BOOST_ASSERT(size <= capacity);
- if (capacity == 0)
- {
- pData_ = const_cast<Data*>(&emptyString_);
- }
- else
- {
- // 11-17-2000: comment added:
- // No need to allocate (capacity + 1) to
- // accommodate the terminating 0, because Data already
- // has one character in there
- pData_ = static_cast<Data*>(
- malloc(sizeof(Data) + capacity * sizeof(E)));
- if (!pData_) boost::throw_exception(std::bad_alloc());
- pData_->pEnd_ = pData_->buffer_ + size;
- pData_->pEndOfMem_ = pData_->buffer_ + capacity;
- }
- }
- private:
- // Warning - this doesn't initialize pData_. Used in reserve()
- SimpleStringStorage()
- { }
- public:
- typedef E value_type;
- typedef E* iterator;
- typedef const E* const_iterator;
- typedef A allocator_type;
- SimpleStringStorage(const SimpleStringStorage& rhs)
- {
- const size_type sz = rhs.size();
- Init(sz, sz);
- if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
- }
- SimpleStringStorage(const SimpleStringStorage& s,
- flex_string_details::Shallow)
- : pData_(s.pData_)
- {
- }
- SimpleStringStorage(const A&)
- { pData_ = const_cast<Data*>(&emptyString_); }
- SimpleStringStorage(const E* s, size_type len, const A&)
- {
- Init(len, len);
- flex_string_details::pod_copy(s, s + len, begin());
- }
- SimpleStringStorage(size_type len, E c, const A&)
- {
- Init(len, len);
- flex_string_details::pod_fill(begin(), end(), c);
- }
- SimpleStringStorage& operator=(const SimpleStringStorage& rhs)
- {
- const size_type sz = rhs.size();
- reserve(sz);
- flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
- pData_->pEnd_ = &*begin() + sz;
- return *this;
- }
- ~SimpleStringStorage()
- {
- BOOST_ASSERT(begin() <= end());
- if (capacity() > 0)
- {
- BOOST_WAVE_COMPILE_TIME_ASSERT(pData_ != &emptyString_);
- free(pData_);
- }
- }
- iterator begin()
- { return pData_->buffer_; }
- const_iterator begin() const
- { return pData_->buffer_; }
- iterator end()
- { return pData_->pEnd_; }
- const_iterator end() const
- { return pData_->pEnd_; }
- size_type size() const
- { return pData_->pEnd_ - pData_->buffer_; }
- size_type max_size() const
- { return std::size_t(-1) / sizeof(E) - sizeof(Data) - 1; }
- size_type capacity() const
- { return pData_->pEndOfMem_ - pData_->buffer_; }
- void reserve(size_type res_arg)
- {
- size_type cap = capacity();
- if (res_arg <= cap)
- {
- // @@@ insert shrinkage here if you wish
- return;
- }
- if (cap == 0)
- {
- Init(0, res_arg);
- }
- else
- {
- const size_type sz = size();
- void* p = realloc(pData_,
- sizeof(Data) + res_arg * sizeof(E));
- if (!p) boost::throw_exception(std::bad_alloc());
- if (p != pData_)
- {
- pData_ = static_cast<Data*>(p);
- pData_->pEnd_ = pData_->buffer_ + sz;
- }
- pData_->pEndOfMem_ = pData_->buffer_ + res_arg;
- }
- }
- void append(const E* s, size_type sz)
- {
- const size_type neededCapacity = size() + sz;
- if (capacity() < neededCapacity)
- {
- const iterator b = begin();
- static std::less_equal<const E*> le;
- if (le(b, s) && le(s, end()))
- {
- // aliased
- const size_type offset = s - b;
- reserve(neededCapacity);
- s = begin() + offset;
- }
- else
- {
- reserve(neededCapacity);
- }
- }
- flex_string_details::pod_copy(s, s + sz, end());
- pData_->pEnd_ += sz;
- }
- template <class InputIterator>
- void append(InputIterator b, InputIterator e)
- {
- // @@@ todo: optimize this depending on iterator type
- for (; b != e; ++b)
- {
- *this += *b;
- }
- }
- void resize(size_type newSize, E fill)
- {
- const int delta = int(newSize - size());
- if (delta == 0) return;
- if (delta > 0)
- {
- if (newSize > capacity())
- {
- reserve(newSize);
- }
- E* e = &*end();
- flex_string_details::pod_fill(e, e + delta, fill);
- }
- pData_->pEnd_ = pData_->buffer_ + newSize;
- }
- void swap(SimpleStringStorage& rhs)
- {
- std::swap(pData_, rhs.pData_);
- }
- const E* c_str() const
- {
- if (capacity() > 0) *pData_->pEnd_ = E();
- return pData_->buffer_;
- }
- const E* data() const
- { return pData_->buffer_; }
- A get_allocator() const
- { return A(); }
- };
- template <typename E, class A>
- const typename SimpleStringStorage<E, A>::Data
- SimpleStringStorage<E, A>::emptyString_ =
- typename SimpleStringStorage<E, A>::Data();
- ////////////////////////////////////////////////////////////////////////////////
- // class template AllocatorStringStorage
- // Allocates with your allocator
- // Takes advantage of the Empty Base Optimization if available
- ////////////////////////////////////////////////////////////////////////////////
- template <typename E, class A = std::allocator<E> >
- class AllocatorStringStorage : public A
- {
- typedef typename boost::allocator_size_type<A>::type size_type;
- typedef typename SimpleStringStorage<E, A>::Data Data;
- void* Alloc(size_type sz, const void* p = 0)
- {
- return boost::allocator_allocate(static_cast<A&>(*this), 1 + (sz - 1) / sizeof(E),
- static_cast<const char*>(p));
- }
- void Free(void* p, size_type sz)
- {
- boost::allocator_deallocate(static_cast<A&>(*this), static_cast<E*>(p), sz);
- }
- Data* pData_;
- void Init(size_type size, size_type cap)
- {
- BOOST_ASSERT(size <= cap);
- if (cap == 0)
- {
- pData_ = const_cast<Data*>(
- &SimpleStringStorage<E, A>::emptyString_);
- }
- else
- {
- pData_ = static_cast<Data*>(Alloc(
- cap * sizeof(E) + sizeof(Data)));
- pData_->pEnd_ = pData_->buffer_ + size;
- pData_->pEndOfMem_ = pData_->buffer_ + cap;
- }
- }
- public:
- typedef E value_type;
- typedef E* iterator;
- typedef const E* const_iterator;
- typedef A allocator_type;
- AllocatorStringStorage()
- : A(), pData_(0)
- {
- }
- AllocatorStringStorage(const AllocatorStringStorage& rhs)
- : A(rhs.get_allocator())
- {
- const size_type sz = rhs.size();
- Init(sz, sz);
- if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
- }
- AllocatorStringStorage(const AllocatorStringStorage& s,
- flex_string_details::Shallow)
- : A(s.get_allocator())
- {
- pData_ = s.pData_;
- }
- AllocatorStringStorage(const A& a) : A(a)
- {
- pData_ = const_cast<Data*>(
- &SimpleStringStorage<E, A>::emptyString_);
- }
- AllocatorStringStorage(const E* s, size_type len, const A& a)
- : A(a)
- {
- Init(len, len);
- flex_string_details::pod_copy(s, s + len, begin());
- }
- AllocatorStringStorage(size_type len, E c, const A& a)
- : A(a)
- {
- Init(len, len);
- flex_string_details::pod_fill(&*begin(), &*end(), c);
- }
- AllocatorStringStorage& operator=(const AllocatorStringStorage& rhs)
- {
- const size_type sz = rhs.size();
- reserve(sz);
- flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
- pData_->pEnd_ = &*begin() + rhs.size();
- return *this;
- }
- ~AllocatorStringStorage()
- {
- if (capacity())
- {
- BOOST_WAVE_COMPILE_TIME_ASSERT(pData_ != (&SimpleStringStorage<E, A>::emptyString_));
- Free(pData_,
- sizeof(Data) + capacity() * sizeof(E));
- }
- }
- iterator begin()
- { return pData_->buffer_; }
- const_iterator begin() const
- { return pData_->buffer_; }
- iterator end()
- { return pData_->pEnd_; }
- const_iterator end() const
- { return pData_->pEnd_; }
- size_type size() const
- { return size_type(end() - begin()); }
- size_type max_size() const
- { return boost::allocator_max_size(static_cast<const A&>(*this)); }
- size_type capacity() const
- { return size_type(pData_->pEndOfMem_ - pData_->buffer_); }
- void resize(size_type n, E c)
- {
- reserve(n);
- iterator newEnd = begin() + n;
- iterator oldEnd = end();
- if (newEnd > oldEnd)
- {
- // Copy the characters
- flex_string_details::pod_fill(oldEnd, newEnd, c);
- }
- if (capacity()) pData_->pEnd_ = newEnd;
- }
- void reserve(size_type res_arg)
- {
- if (res_arg <= capacity())
- {
- // @@@ shrink to fit here
- return;
- }
- A& myAlloc = *this;
- AllocatorStringStorage newStr(myAlloc);
- newStr.Init(size(), res_arg);
- flex_string_details::pod_copy(begin(), end(), newStr.begin());
- swap(newStr);
- }
- template <class ForwardIterator>
- void append(ForwardIterator b, ForwardIterator e)
- {
- const size_type
- sz = std::distance(b, e),
- neededCapacity = size() + sz;
- if (capacity() < neededCapacity)
- {
- // typedef std::less_equal<const E*> le_type;
- // BOOST_ASSERT(!(le_type()(begin(), &*b) && le_type()(&*b, end())));
- reserve(neededCapacity);
- }
- std::copy(b, e, end());
- pData_->pEnd_ += sz;
- }
- void swap(AllocatorStringStorage& rhs)
- {
- // @@@ The following line is commented due to a bug in MSVC
- //std::swap(lhsAlloc, rhsAlloc);
- std::swap(pData_, rhs.pData_);
- }
- const E* c_str() const
- {
- if (capacity() > 0)
- {
- *pData_->pEnd_ = E();
- }
- return &*begin();
- }
- const E* data() const
- { return &*begin(); }
- A get_allocator() const
- { return *this; }
- };
- ////////////////////////////////////////////////////////////////////////////////
- // class template VectorStringStorage
- // Uses std::vector
- // Takes advantage of the Empty Base Optimization if available
- ////////////////////////////////////////////////////////////////////////////////
- template <typename E, class A = std::allocator<E> >
- class VectorStringStorage : protected std::vector<E, A>
- {
- typedef std::vector<E, A> base;
- public: // protected:
- typedef E value_type;
- typedef typename base::iterator iterator;
- typedef typename base::const_iterator const_iterator;
- typedef A allocator_type;
- typedef typename boost::allocator_size_type<A>::type size_type;
- VectorStringStorage(const VectorStringStorage& s) : base(s)
- { }
- VectorStringStorage(const A& a) : base(1, E(), a)
- { }
- VectorStringStorage(const E* s, size_type len, const A& a)
- : base(a)
- {
- base::reserve(len + 1);
- base::insert(base::end(), s, s + len);
- // Terminating zero
- base::insert(base::end(), E());
- }
- VectorStringStorage(size_type len, E c, const A& a)
- : base(len + 1, c, a)
- {
- // Terminating zero
- base::back() = E();
- }
- VectorStringStorage& operator=(const VectorStringStorage& rhs)
- {
- base& v = *this;
- v = rhs;
- return *this;
- }
- iterator begin()
- { return base::begin(); }
- const_iterator begin() const
- { return base::begin(); }
- iterator end()
- { return base::end() - 1; }
- const_iterator end() const
- { return base::end() - 1; }
- size_type size() const
- { return base::size() - 1; }
- size_type max_size() const
- { return base::max_size() - 1; }
- size_type capacity() const
- { return base::capacity() - 1; }
- void reserve(size_type res_arg)
- {
- BOOST_ASSERT(res_arg < max_size());
- base::reserve(res_arg + 1);
- }
- void append(const E* s, size_type sz)
- {
- // Check for aliasing because std::vector doesn't do it.
- static std::less_equal<const E*> le;
- if (!base::empty())
- {
- const E* start = &base::front();
- if (le(start, s) && le(s, start + size()))
- {
- // aliased
- const size_type offset = s - start;
- reserve(size() + sz);
- s = &base::front() + offset;
- }
- }
- base::insert(end(), s, s + sz);
- }
- template <class InputIterator>
- void append(InputIterator b, InputIterator e)
- {
- base::insert(end(), b, e);
- }
- void resize(size_type n, E c)
- {
- base::reserve(n + 1);
- base::back() = c;
- base::resize(n + 1, c);
- base::back() = E();
- }
- void swap(VectorStringStorage& rhs)
- { base::swap(rhs); }
- const E* c_str() const
- { return &*begin(); }
- const E* data() const
- { return &*begin(); }
- A get_allocator() const
- { return base::get_allocator(); }
- };
- ////////////////////////////////////////////////////////////////////////////////
- // class template SmallStringOpt
- // Builds the small string optimization over any other storage
- ////////////////////////////////////////////////////////////////////////////////
- template <class Storage, unsigned int threshold,
- typename Align = typename Storage::value_type*>
- class SmallStringOpt
- {
- public:
- typedef typename Storage::value_type value_type;
- typedef value_type* iterator;
- typedef const value_type* const_iterator;
- typedef typename Storage::allocator_type allocator_type;
- typedef typename boost::allocator_size_type<allocator_type>::type size_type;
- private:
- 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 =
- (temp2 + sizeof(value_type) - 1) / sizeof(value_type) };
- private:
- enum { magic = maxSmallString + 1 };
- union
- {
- mutable value_type buf_[maxSmallString + 1];
- Align align_;
- };
- Storage& GetStorage()
- {
- BOOST_ASSERT(buf_[maxSmallString] == magic);
- Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
- return *p;
- }
- const Storage& GetStorage() const
- {
- BOOST_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)
- {
- if (s.Small())
- {
- flex_string_details::pod_copy(
- s.buf_,
- s.buf_ + s.size(),
- buf_);
- }
- else
- {
- new(buf_) Storage(s.GetStorage());
- }
- 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)
- {
- flex_string_details::pod_copy(s, s + len, buf_);
- buf_[maxSmallString] = value_type(maxSmallString - len);
- }
- else
- {
- new(buf_) Storage(s, len, a);
- buf_[maxSmallString] = magic;
- }
- }
- SmallStringOpt(size_type len, value_type c, const allocator_type& a)
- {
- if (len <= maxSmallString)
- {
- flex_string_details::pod_fill(buf_, buf_ + len, c);
- buf_[maxSmallString] = value_type(maxSmallString - len);
- }
- else
- {
- new(buf_) Storage(len, c, a);
- buf_[maxSmallString] = magic;
- }
- }
- SmallStringOpt& operator=(const SmallStringOpt& rhs)
- {
- reserve(rhs.size());
- resize(0, 0);
- append(rhs.data(), rhs.size());
- return *this;
- }
- ~SmallStringOpt()
- {
- if (!Small()) GetStorage().~Storage();
- }
- iterator begin()
- {
- if (Small()) return buf_;
- return &*GetStorage().begin();
- }
- const_iterator begin() const
- {
- if (Small()) return buf_;
- return &*GetStorage().begin();
- }
- iterator end()
- {
- if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
- return &*GetStorage().end();
- }
- const_iterator end() const
- {
- if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
- return &*GetStorage().end();
- }
- size_type size() const
- {
- BOOST_ASSERT(!Small() || maxSmallString >= buf_[maxSmallString]);
- return Small()
- ? maxSmallString - buf_[maxSmallString]
- : GetStorage().size();
- }
- size_type max_size() const
- { return boost::allocator_max_size(get_allocator()); }
- size_type capacity() const
- { return Small() ? maxSmallString : GetStorage().capacity(); }
- void reserve(size_type res_arg)
- {
- if (Small())
- {
- if (res_arg <= maxSmallString) return;
- SmallStringOpt temp(*this);
- this->~SmallStringOpt();
- new(buf_) Storage(temp.data(), temp.size(),
- temp.get_allocator());
- buf_[maxSmallString] = magic;
- GetStorage().reserve(res_arg);
- }
- else
- {
- GetStorage().reserve(res_arg);
- }
- BOOST_ASSERT(capacity() >= res_arg);
- }
- void append(const value_type* s, size_type sz)
- {
- if (!Small())
- {
- GetStorage().append(s, sz);
- }
- else
- {
- // append to a small string
- const size_type neededCapacity =
- maxSmallString - buf_[maxSmallString] + sz;
- if (maxSmallString < neededCapacity)
- {
- // need to change storage strategy
- allocator_type alloc;
- Storage temp(alloc);
- temp.reserve(neededCapacity);
- temp.append(buf_, maxSmallString - buf_[maxSmallString]);
- temp.append(s, sz);
- buf_[maxSmallString] = magic;
- new(buf_) Storage(temp.get_allocator());
- GetStorage().swap(temp);
- }
- else
- {
- flex_string_details::pod_move(s, s + sz,
- buf_ + maxSmallString - buf_[maxSmallString]);
- buf_[maxSmallString] -= value_type(sz);
- }
- }
- }
- template <class InputIterator>
- void append(InputIterator b, InputIterator e)
- {
- // @@@ todo: optimize this depending on iterator type
- for (; b != e; ++b)
- {
- *this += *b;
- }
- }
- void resize(size_type n, value_type c)
- {
- if (Small())
- {
- if (n > maxSmallString)
- {
- // 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(),
- temp.get_allocator());
- newString.resize(n, c);
- // We make the reasonable assumption that an empty Storage
- // constructor won't throw
- this->~SmallStringOpt();
- new(&buf_[0]) Storage(temp.get_allocator());
- buf_[maxSmallString] = value_type(magic);
- GetStorage().swap(newString);
- }
- else
- {
- // Small string resized to small string
- // 11-17-2001: bug fix: terminating zero not copied
- size_type toFill = n > size() ? n - size() : 0;
- flex_string_details::pod_fill(end(), end() + toFill, c);
- buf_[maxSmallString] = value_type(maxSmallString - n);
- }
- }
- else
- {
- if (n > maxSmallString)
- {
- // Big string resized to big string
- GetStorage().resize(n, c);
- }
- else
- {
- // Big string resized to small string
- // 11-17=2001: bug fix in the BOOST_ASSERTion below
- BOOST_ASSERT(capacity() > n);
- SmallStringOpt newObj(data(), n, get_allocator());
- newObj.swap(*this);
- }
- }
- }
- void swap(SmallStringOpt& rhs)
- {
- if (Small())
- {
- if (rhs.Small())
- {
- // Small swapped with small
- std::swap_ranges(buf_, buf_ + maxSmallString + 1,
- rhs.buf_);
- }
- else
- {
- // Small swapped with big
- // Make a copy of myself - can't throw
- SmallStringOpt temp(*this);
- // Nuke myself
- this->~SmallStringOpt();
- // Make an empty storage for myself (likely won't throw)
- new(buf_) Storage(0, value_type(), rhs.get_allocator());
- buf_[maxSmallString] = magic;
- // Recurse to this same function
- swap(rhs);
- // Nuke rhs
- rhs.~SmallStringOpt();
- // Build the new small string into rhs
- new(&rhs) SmallStringOpt(temp);
- }
- }
- else
- {
- if (rhs.Small())
- {
- // Big swapped with small
- // Already implemented, recurse with reversed args
- rhs.swap(*this);
- }
- else
- {
- // Big swapped with big
- GetStorage().swap(rhs.GetStorage());
- }
- }
- }
- const value_type* c_str() const
- {
- 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(); }
- };
- ////////////////////////////////////////////////////////////////////////////////
- // class template CowString
- // Implements Copy on Write over any storage
- ////////////////////////////////////////////////////////////////////////////////
- template <
- typename Storage,
- typename Align = BOOST_DEDUCED_TYPENAME Storage::value_type*
- >
- class CowString
- {
- typedef typename Storage::value_type E;
- typedef typename flex_string_details::get_unsigned<E>::result RefCountType;
- public:
- typedef E value_type;
- typedef typename Storage::iterator iterator;
- typedef typename Storage::const_iterator const_iterator;
- typedef typename Storage::allocator_type allocator_type;
- typedef typename boost::allocator_size_type<allocator_type>::type size_type;
- typedef typename Storage::value_type& reference;
- private:
- union
- {
- mutable char buf_[sizeof(Storage)];
- Align align_;
- };
- Storage& Data() const
- {
- Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
- return *p;
- }
- RefCountType GetRefs() const
- {
- const Storage& d = Data();
- BOOST_ASSERT(d.size() > 0);
- BOOST_ASSERT(static_cast<RefCountType>(*d.begin()) != 0);
- return *d.begin();
- }
- RefCountType& Refs()
- {
- Storage& d = Data();
- BOOST_ASSERT(d.size() > 0);
- return reinterpret_cast<RefCountType&>(*d.begin());
- }
- void MakeUnique() const
- {
- BOOST_ASSERT(GetRefs() >= 1);
- if (GetRefs() == 1) return;
- union
- {
- char buf_[sizeof(Storage)];
- Align align_;
- } temp;
- --(*Data().begin()); // decrement the use count of the remaining object
- Storage* p = reinterpret_cast<Storage*>(&temp.buf_[0]);
- new(buf_) Storage(
- *new(p) Storage(Data()),
- flex_string_details::Shallow());
- *Data().begin() = 1;
- }
- public:
- CowString(const CowString& s)
- {
- if (s.GetRefs() == (std::numeric_limits<RefCountType>::max)())
- {
- // must make a brand new copy
- new(buf_) Storage(s.Data()); // non shallow
- Refs() = 1;
- }
- else
- {
- new(buf_) Storage(s.Data(), flex_string_details::Shallow());
- ++Refs();
- }
- BOOST_ASSERT(Data().size() > 0);
- }
- CowString(const allocator_type& a)
- {
- new(buf_) Storage(1, 1, a);
- }
- CowString(const E* s, size_type len, const allocator_type& a)
- {
- // Warning - MSVC's debugger has trouble tracing through the code below.
- // It seems to be a const-correctness issue
- //
- new(buf_) Storage(a);
- Data().reserve(len + 1);
- Data().resize(1, 1);
- Data().append(s, s + len);
- }
- CowString(size_type len, E c, const allocator_type& a)
- {
- new(buf_) Storage(len + 1, c, a);
- Refs() = 1;
- }
- CowString& operator=(const CowString& rhs)
- {
- // CowString(rhs).swap(*this);
- if (--Refs() == 0)
- Data().~Storage();
- if (rhs.GetRefs() == (std::numeric_limits<RefCountType>::max)())
- {
- // must make a brand new copy
- new(buf_) Storage(rhs.Data()); // non shallow
- Refs() = 1;
- }
- else
- {
- new(buf_) Storage(rhs.Data(), flex_string_details::Shallow());
- ++Refs();
- }
- BOOST_ASSERT(Data().size() > 0);
- return *this;
- }
- ~CowString()
- {
- BOOST_ASSERT(Data().size() > 0);
- if (--Refs() == 0)
- Data().~Storage();
- }
- iterator begin()
- {
- BOOST_ASSERT(Data().size() > 0);
- MakeUnique();
- return Data().begin() + 1;
- }
- const_iterator begin() const
- {
- BOOST_ASSERT(Data().size() > 0);
- return Data().begin() + 1;
- }
- iterator end()
- {
- MakeUnique();
- return Data().end();
- }
- const_iterator end() const
- {
- return Data().end();
- }
- size_type size() const
- {
- BOOST_ASSERT(Data().size() > 0);
- return Data().size() - 1;
- }
- size_type max_size() const
- {
- BOOST_ASSERT(Data().max_size() > 0);
- return Data().max_size() - 1;
- }
- size_type capacity() const
- {
- BOOST_ASSERT(Data().capacity() > 0);
- return Data().capacity() - 1;
- }
- void resize(size_type n, E c)
- {
- BOOST_ASSERT(Data().size() > 0);
- MakeUnique();
- Data().resize(n + 1, c);
- }
- template <class FwdIterator>
- void append(FwdIterator b, FwdIterator e)
- {
- MakeUnique();
- Data().append(b, e);
- }
- void reserve(size_type res_arg)
- {
- if (capacity() > res_arg) return;
- MakeUnique();
- Data().reserve(res_arg + 1);
- }
- void swap(CowString& rhs)
- {
- Data().swap(rhs.Data());
- }
- const E* c_str() const
- {
- BOOST_ASSERT(Data().size() > 0);
- return Data().c_str() + 1;
- }
- const E* data() const
- {
- BOOST_ASSERT(Data().size() > 0);
- return Data().data() + 1;
- }
- allocator_type get_allocator() const
- {
- return Data().get_allocator();
- }
- };
- ////////////////////////////////////////////////////////////////////////////////
- // class template flex_string
- // a std::basic_string compatible implementation
- // Uses a Storage policy
- ////////////////////////////////////////////////////////////////////////////////
- template <typename E,
- class T = std::char_traits<E>,
- class A = std::allocator<E>,
- class Storage = AllocatorStringStorage<E, A> >
- class flex_string : private Storage
- {
- #if defined(BOOST_WAVE_FLEXSTRING_THROW_ON_ENFORCE)
- template <typename Exception>
- static void Enforce(bool condition, Exception*, const char* msg)
- { if (!condition) boost::throw_exception(Exception(msg)); }
- #else
- template <typename Exception>
- static inline void Enforce(bool condition, Exception*, const char* msg)
- { BOOST_VERIFY(condition && msg); }
- #endif // defined(BOOST_WAVE_FLEXSTRING_THROW_ON_ENFORCE)
- #ifndef NDEBUG
- bool Sane() const
- {
- return
- begin() <= end() &&
- empty() == (size() == 0) &&
- empty() == (begin() == end()) &&
- size() <= max_size() &&
- capacity() <= max_size() &&
- size() <= capacity();
- }
- struct Invariant;
- friend struct Invariant;
- struct Invariant
- {
- Invariant(const flex_string& s) : s_(s)
- {
- BOOST_ASSERT(s_.Sane());
- }
- ~Invariant()
- {
- BOOST_ASSERT(s_.Sane());
- }
- private:
- const flex_string& s_;
- Invariant& operator=(const Invariant&);
- };
- #endif
- public:
- // types
- typedef T traits_type;
- typedef typename traits_type::char_type value_type;
- typedef A allocator_type;
- typedef typename boost::allocator_value_type<A>::type& reference;
- typedef typename boost::allocator_value_type<A>::type const& const_reference;
- typedef typename boost::allocator_pointer<A>::type pointer;
- typedef typename boost::allocator_const_pointer<A>::type const_pointer;
- typedef typename boost::allocator_size_type<A>::type size_type;
- typedef typename Storage::iterator iterator;
- typedef typename Storage::const_iterator const_iterator;
- typedef boost::reverse_iterator<iterator> reverse_iterator;
- typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
- static const size_type npos; // = size_type(-1)
- private:
- static size_type Min(size_type lhs, size_type rhs)
- { return lhs < rhs ? lhs : rhs; }
- static void Procust(size_type& n, size_type nmax)
- { if (n > nmax) n = nmax; }
- public:
- // 21.3.1 construct/copy/destroy
- explicit flex_string(const A& a = A())
- : Storage(a)
- {}
- flex_string(const flex_string& str)
- : Storage(str)
- {
- }
- flex_string(const flex_string& str, size_type pos,
- size_type n = npos, const A& a = A())
- : Storage(a)
- {
- Enforce(pos <= str.size(), (std::out_of_range*)0, "");
- assign(str, pos, n);
- }
- flex_string(const value_type* s, const A& a = A())
- : Storage(s, traits_type::length(s), a)
- {}
- flex_string(const value_type* s, size_type n, const A& a = A())
- : Storage(s, n, a)
- {}
- flex_string(size_type n, value_type c, const A& a = A())
- : Storage(n, c, a)
- {}
- template <class InputIterator>
- flex_string(InputIterator begin, InputIterator end, const A& a = A())
- : Storage(a)
- {
- assign(begin, end);
- }
- ~flex_string()
- {}
- flex_string& operator=(const flex_string& str)
- {
- if (this != &str) {
- Storage& s = *this;
- s = str;
- }
- return *this;
- }
- flex_string& operator=(const value_type* s)
- {
- assign(s);
- return *this;
- }
- flex_string& operator=(value_type c)
- {
- assign(1, c);
- return *this;
- }
- // 21.3.2 iterators:
- iterator begin()
- { return Storage::begin(); }
- const_iterator begin() const
- { return Storage::begin(); }
- iterator end()
- { return Storage::end(); }
- const_iterator end() const
- { return Storage::end(); }
- reverse_iterator rbegin()
- { return reverse_iterator(end()); }
- const_reverse_iterator rbegin() const
- { return const_reverse_iterator(end()); }
- reverse_iterator rend()
- { return reverse_iterator(begin()); }
- const_reverse_iterator rend() const
- { return const_reverse_iterator(begin()); }
- #if BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK != 0
- // temporary hack to make it easier to serialize flex_string's using
- // the Boost.Serialization library
- value_type & back() { return *(begin()+size()-1); }
- value_type const& back() const { return *(begin()+size()-1); }
- #endif
- // 21.3.3 capacity:
- size_type size() const
- { return Storage::size(); }
- size_type length() const
- { return size(); }
- size_type max_size() const
- { return Storage::max_size(); }
- void resize(size_type n, value_type c)
- { Storage::resize(n, c); }
- void resize(size_type n)
- { resize(n, value_type()); }
- size_type capacity() const
- { return Storage::capacity(); }
- void reserve(size_type res_arg = 0)
- {
- Enforce(res_arg <= max_size(), (std::length_error*)0, "");
- Storage::reserve(res_arg);
- }
- void clear()
- { resize(0); }
- bool empty() const
- { return size() == 0; }
- // 21.3.4 element access:
- const_reference operator[](size_type pos) const
- { return *(begin() + pos); }
- reference operator[](size_type pos)
- { return *(begin() + pos); }
- const_reference at(size_type n) const
- {
- Enforce(n < size(), (std::out_of_range*)0, "");
- return (*this)[n];
- }
- reference at(size_type n)
- {
- Enforce(n < size(), (std::out_of_range*)0, "");
- return (*this)[n];
- }
- // 21.3.5 modifiers:
- flex_string& operator+=(const flex_string& str)
- { return append(str); }
- flex_string& operator+=(const value_type* s)
- { return append(s); }
- flex_string& operator+=(value_type c)
- {
- push_back(c);
- return *this;
- }
- flex_string& append(const flex_string& str)
- { return append(str, 0, npos); }
- flex_string& append(const flex_string& str, const size_type pos,
- size_type n)
- {
- const size_type sz = str.size();
- Enforce(pos <= sz, (std::out_of_range*)0, "");
- Procust(n, sz - pos);
- return append(str.c_str() + pos, n);
- }
- flex_string& append(const value_type* s, const size_type n)
- {
- #ifndef NDEBUG
- Invariant checker(*this);
- #endif
- if (IsAliasedRange(s, s + n))
- {
- const size_type offset = s - &*begin();
- Storage::reserve(size() + n);
- s = &*begin() + offset;
- }
- Storage::append(s, s+ n);
- return *this;
- }
- flex_string& append(const value_type* s)
- { return append(s, traits_type::length(s)); }
- flex_string& append(size_type n, value_type c)
- {
- resize(size() + n, c);
- return *this;
- }
- template<class InputIterator>
- flex_string& append(InputIterator first, InputIterator last)
- {
- insert(end(), first, last);
- return *this;
- }
- void push_back(value_type c)
- {
- const size_type cap = capacity();
- if (size() == cap)
- {
- reserve(cap << 1u);
- }
- Storage::append(&c, &c + 1);
- }
- flex_string& assign(const flex_string& str)
- {
- if (&str == this) return *this;
- return assign(str.data(), str.size());
- }
- flex_string& assign(const flex_string& str, size_type pos,
- size_type n)
- {
- const size_type sz = str.size();
- Enforce(pos <= str.size(), (std::out_of_range*)0, "");
- Procust(n, sz - pos);
- return assign(str.data() + pos, n);
- }
- flex_string& assign(const value_type* s, size_type n)
- {
- #ifndef NDEBUG
- Invariant checker(*this);
- #endif
- if (size() >= n)
- {
- std::copy(s, s + n, begin());
- resize(n);
- }
- else
- {
- const value_type *const s2 = s + size();
- std::copy(s, s2, begin());
- append(s2, n - size());
- }
- return *this;
- }
- flex_string& assign(const value_type* s)
- { return assign(s, traits_type::length(s)); }
- template <class ItOrLength, class ItOrChar>
- flex_string& assign(ItOrLength first_or_n, ItOrChar last_or_c)
- { return replace(begin(), end(), first_or_n, last_or_c); }
- flex_string& insert(size_type pos1, const flex_string& str)
- { return insert(pos1, str.data(), str.size()); }
- flex_string& insert(size_type pos1, const flex_string& str,
- size_type pos2, size_type n)
- {
- Enforce(pos2 <= str.length(), (std::out_of_range*)0, "");
- Procust(n, str.length() - pos2);
- return insert(pos1, str.data() + pos2, n);
- }
- flex_string& insert(size_type pos, const value_type* s, size_type n)
- {
- Enforce(pos <= length(), (std::out_of_range*)0, "");
- insert(begin() + pos, s, s + n);
- return *this;
- }
- flex_string& insert(size_type pos, const value_type* s)
- { return insert(pos, s, traits_type::length(s)); }
- flex_string& insert(size_type pos, size_type n, value_type c)
- {
- Enforce(pos <= length(), (std::out_of_range*)0, "");
- insert(begin() + pos, n, c);
- return *this;
- }
- iterator insert(iterator p, value_type c = value_type())
- {
- const size_type pos = p - begin();
- insert(pos, &c, 1);
- return begin() + pos;
- }
- private:
- // Care must be taken when dereferencing some iterator types.
- //
- // Users can implement this function in their namespace if their storage
- // uses a special iterator type, the function will be found through ADL.
- template<class Iterator>
- const typename std::iterator_traits<Iterator>::value_type*
- DereferenceValidIterator(Iterator it) const
- {
- return &*it;
- }
- // Care must be taken when dereferencing a reverse iterators, hence this
- // special case. This isn't in the std namespace so as not to pollute it or
- // create name clashes.
- template<typename Iterator>
- const typename std::iterator_traits<Iterator>::value_type*
- DereferenceValidIterator(std::reverse_iterator<Iterator> it) const
- {
- return &*--it;
- }
- // Determine if the range aliases the current string.
- //
- // This method cannot be const because calling begin/end on copy-on-write
- // implementations must have side effects.
- // A const version wouldn't make the string unique through this call.
- template<class Iterator>
- bool IsAliasedRange(Iterator beginIterator, Iterator endIterator)
- {
- if(!empty() && beginIterator != endIterator)
- {
- typedef const typename std::iterator_traits<Iterator>::value_type *
- value_pointer;
- value_pointer myBegin(&*begin());
- value_pointer myEnd(&*begin() + size());
- value_pointer rangeBegin(DereferenceValidIterator(beginIterator));
- const std::less_equal<value_pointer> less_equal = std::less_equal<value_pointer>();
- if(less_equal(myBegin, rangeBegin) && less_equal(rangeBegin, myEnd))
- return true;
- }
- return false;
- }
- template <int i> class Selector {};
- flex_string& InsertImplDiscr(iterator p,
- size_type n, value_type c, Selector<1>)
- {
- #ifndef NDEBUG
- Invariant checker(*this);
- #endif
- BOOST_ASSERT(begin() <= p && p <= end());
- const size_type insertOffset(p - begin());
- const size_type originalSize(size());
- if(n < originalSize - insertOffset)
- {
- // The new characters fit within the original string.
- // The characters that are pushed back need to be moved because
- // they're aliased.
- // The appended characters will all be overwritten by the move.
- append(n, value_type(0));
- value_type* begin(&*begin());
- flex_string_details::pod_move(begin + insertOffset,
- begin + originalSize, begin + insertOffset + n);
- std::fill(begin + insertOffset, begin + insertOffset + n, c);
- }
- else
- {
- // The new characters exceed the original string.
- // The characters that are pushed back can simply be copied since
- // they aren't aliased.
- // The appended characters will partly be overwritten by the copy.
- append(n, c);
- value_type* begin(&*begin());
- flex_string_details::pod_copy(begin + insertOffset,
- begin + originalSize, begin + insertOffset + n);
- std::fill(begin + insertOffset, begin + originalSize, c);
- }
- return *this;
- }
- template<class InputIterator>
- flex_string& InsertImplDiscr(iterator i,
- InputIterator b, InputIterator e, Selector<0>)
- {
- InsertImpl(i, b, e,
- typename std::iterator_traits<InputIterator>::iterator_category());
- return *this;
- }
- template <class FwdIterator>
- void InsertImpl(iterator i,
- FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
- {
- if(s1 == s2)
- {
- // Insert an empty range.
- return;
- }
- if(IsAliasedRange(s1, s2))
- {
- // The source range is contained in the current string, copy it
- // and recurse.
- const flex_string temporary(s1, s2);
- InsertImpl(i, temporary.begin(), temporary.end(),
- typename std::iterator_traits<FwdIterator>::iterator_category());
- return;
- }
- #ifndef NDEBUG
- Invariant checker(*this);
- #endif
- const size_type pos = i - begin();
- const typename std::iterator_traits<FwdIterator>::difference_type n2 =
- std::distance(s1, s2);
- BOOST_ASSERT(n2 >= 0);
- using namespace flex_string_details;
- BOOST_ASSERT(pos <= size());
- const typename std::iterator_traits<FwdIterator>::difference_type maxn2 =
- capacity() - size();
- if (maxn2 < n2)
- {
- // Reallocate the string.
- BOOST_ASSERT(!IsAliasedRange(s1, s2));
- reserve(size() + n2);
- i = begin() + pos;
- }
- if (pos + n2 <= size())
- {
- const iterator tailBegin = end() - n2;
- Storage::append(tailBegin, tailBegin + n2);
- std::copy(reverse_iterator(tailBegin), reverse_iterator(i),
- reverse_iterator(tailBegin + n2));
- std::copy(s1, s2, i);
- }
- else
- {
- FwdIterator t = s1;
- const size_type old_size = size();
- std::advance(t, old_size - pos);
- BOOST_ASSERT(std::distance(t, s2) >= 0);
- Storage::append(t, s2);
- Storage::append(data() + pos, data() + old_size);
- std::copy(s1, t, i);
- }
- }
- template <class InputIterator>
- void InsertImpl(iterator insertPosition,
- InputIterator inputBegin, InputIterator inputEnd,
- std::input_iterator_tag)
- {
- flex_string temporary(begin(), insertPosition);
- for (; inputBegin != inputEnd; ++inputBegin)
- {
- temporary.push_back(*inputBegin);
- }
- temporary.append(insertPosition, end());
- swap(temporary);
- }
- public:
- template <class ItOrLength, class ItOrChar>
- void insert(iterator p, ItOrLength first_or_n, ItOrChar last_or_c)
- {
- Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
- InsertImplDiscr(p, first_or_n, last_or_c, sel);
- }
- flex_string& erase(size_type pos = 0, size_type n = npos)
- {
- #ifndef NDEBUG
- Invariant checker(*this);
- #endif
- Enforce(pos <= length(), (std::out_of_range*)0, "");
- Procust(n, length() - pos);
- std::copy(begin() + pos + n, end(), begin() + pos);
- resize(length() - n);
- return *this;
- }
- iterator erase(iterator position)
- {
- const size_type pos(position - begin());
- erase(pos, 1);
- return begin() + pos;
- }
- iterator erase(iterator first, iterator last)
- {
- const size_type pos(first - begin());
- erase(pos, last - first);
- return begin() + pos;
- }
- // Replaces at most n1 chars of *this, starting with pos1 with the content of str
- flex_string& replace(size_type pos1, size_type n1, const flex_string& str)
- { return replace(pos1, n1, str, 0, npos); }
- // Replaces at most n1 chars of *this, starting with pos1,
- // with at most n2 chars of str starting with pos2
- flex_string& replace(size_type pos1, size_type n1, const flex_string& str,
- size_type pos2, size_type n2)
- {
- Enforce(pos2 <= str.length(), (std::out_of_range*)0, "");
- return replace(pos1, n1, str.data() + pos2,
- Min(n2, str.size() - pos2));
- }
- // Replaces at most n1 chars of *this, starting with pos, with chars from s
- flex_string& replace(size_type pos, size_type n1, const value_type* s)
- { return replace(pos, n1, s, traits_type::length(s)); }
- // Replaces at most n1 chars of *this, starting with pos, with n2 occurrences of c
- // consolidated with
- // Replaces at most n1 chars of *this, starting with pos,
- // with at most n2 chars of str.
- // str must have at least n2 chars.
- template <class StrOrLength, class NumOrChar>
- flex_string& replace(size_type pos, size_type n1,
- StrOrLength s_or_n2, NumOrChar n_or_c)
- {
- #ifndef NDEBUG
- Invariant checker(*this);
- #endif
- Enforce(pos <= size(), (std::out_of_range*)0, "");
- Procust(n1, length() - pos);
- const iterator b = begin() + pos;
- return replace(b, b + n1, s_or_n2, n_or_c);
- }
- flex_string& replace(iterator i1, iterator i2, const flex_string& str)
- { return replace(i1, i2, str.c_str(), str.length()); }
- flex_string& replace(iterator i1, iterator i2, const value_type* s)
- { return replace(i1, i2, s, traits_type::length(s)); }
- private:
- flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
- const value_type* s, size_type n, Selector<2>)
- {
- BOOST_ASSERT(i1 <= i2);
- BOOST_ASSERT(begin() <= i1 && i1 <= end());
- BOOST_ASSERT(begin() <= i2 && i2 <= end());
- return replace(i1, i2, s, s + n);
- }
- flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
- size_type n2, value_type c, Selector<1>)
- {
- const size_type n1 = i2 - i1;
- if (n1 > n2)
- {
- std::fill(i1, i1 + n2, c);
- erase(i1 + n2, i2);
- }
- else
- {
- std::fill(i1, i2, c);
- insert(i2, n2 - n1, c);
- }
- return *this;
- }
- template <class InputIterator>
- flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
- InputIterator b, InputIterator e, Selector<0>)
- {
- ReplaceImpl(i1, i2, b, e,
- typename std::iterator_traits<InputIterator>::iterator_category());
- return *this;
- }
- template <class FwdIterator>
- void ReplaceImpl(iterator i1, iterator i2,
- FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
- {
- #ifndef NDEBUG
- Invariant checker(*this);
- #endif
- const typename std::iterator_traits<iterator>::difference_type n1 =
- i2 - i1;
- BOOST_ASSERT(n1 >= 0);
- const typename std::iterator_traits<FwdIterator>::difference_type n2 =
- std::distance(s1, s2);
- BOOST_ASSERT(n2 >= 0);
- if (IsAliasedRange(s1, s2))
- {
- // Aliased replace, copy to new string.
- flex_string temporary;
- temporary.reserve(size() - n1 + n2);
- temporary.append(begin(), i1).append(s1, s2).append(i2, end());
- swap(temporary);
- return;
- }
- if (n1 > n2)
- {
- // Shrinks
- std::copy(s1, s2, i1);
- erase(i1 + n2, i2);
- }
- else
- {
- // Grows
- flex_string_details::copy_n(s1, n1, i1);
- std::advance(s1, n1);
- insert(i2, s1, s2);
- }
- }
- template <class InputIterator>
- void ReplaceImpl(iterator i1, iterator i2,
- InputIterator b, InputIterator e, std::input_iterator_tag)
- {
- flex_string temp(begin(), i1);
- temp.append(b, e).append(i2, end());
- swap(temp);
- }
- public:
- template <class T1, class T2>
- flex_string& replace(iterator i1, iterator i2,
- T1 first_or_n_or_s, T2 last_or_c_or_n)
- {
- const bool
- num1 = std::numeric_limits<T1>::is_specialized,
- num2 = std::numeric_limits<T2>::is_specialized;
- return ReplaceImplDiscr(i1, i2, first_or_n_or_s, last_or_c_or_n,
- Selector<num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>());
- }
- size_type copy(value_type* s, size_type n, size_type pos = 0) const
- {
- Enforce(pos <= size(), (std::out_of_range*)0, "");
- n = Min(n, size() - pos);
- flex_string_details::pod_copy(
- &*begin() + pos,
- &*begin() + pos + n,
- s);
- return n;
- }
- void swap(flex_string& rhs)
- {
- Storage& srhs = rhs;
- this->Storage::swap(srhs);
- }
- // 21.3.6 string operations:
- const value_type* c_str() const
- { return Storage::c_str(); }
- const value_type* data() const
- { return Storage::data(); }
- allocator_type get_allocator() const
- { return Storage::get_allocator(); }
- size_type find(const flex_string& str, size_type pos = 0) const
- { return find(str.data(), pos, str.length()); }
- size_type find (const value_type* s, size_type pos, size_type n) const
- {
- const size_type size_(size());
- if (n + pos > size_)
- return npos;
- for (; pos < size_; ++pos)
- {
- if (traits_type::compare(&*begin() + pos, s, n) == 0)
- {
- return pos;
- }
- }
- return npos;
- }
- size_type find (const value_type* s, size_type pos = 0) const
- { return find(s, pos, traits_type::length(s)); }
- size_type find (value_type c, size_type pos = 0) const
- { return find(&c, pos, 1); }
- size_type rfind(const flex_string& str, size_type pos = npos) const
- { return rfind(str.c_str(), pos, str.length()); }
- size_type rfind(const value_type* s, size_type pos, size_type n) const
- {
- if (n > length()) return npos;
- pos = Min(pos, length() - n);
- if (n == 0) return pos;
- const_iterator i(begin() + pos);
- for (; ; --i)
- {
- if (traits_type::eq(*i, *s)
- && traits_type::compare(&*i, s, n) == 0)
- {
- return i - begin();
- }
- if (i == begin()) break;
- }
- return npos;
- }
- size_type rfind(const value_type* s, size_type pos = npos) const
- { return rfind(s, pos, traits_type::length(s)); }
- size_type rfind(value_type c, size_type pos = npos) const
- { return rfind(&c, pos, 1); }
- size_type find_first_of(const flex_string& str, size_type pos = 0) const
- { return find_first_of(str.c_str(), pos, str.length()); }
- size_type find_first_of(const value_type* s,
- size_type pos, size_type n) const
- {
- if (pos > length() || n == 0) return npos;
- const_iterator i(begin() + pos),
- finish(end());
- for (; i != finish; ++i)
- {
- if (traits_type::find(s, n, *i) != 0)
- {
- return i - begin();
- }
- }
- return npos;
- }
- size_type find_first_of(const value_type* s, size_type pos = 0) const
- { return find_first_of(s, pos, traits_type::length(s)); }
- size_type find_first_of(value_type c, size_type pos = 0) const
- { return find_first_of(&c, pos, 1); }
- size_type find_last_of (const flex_string& str,
- size_type pos = npos) const
- { return find_last_of(str.c_str(), pos, str.length()); }
- size_type find_last_of (const value_type* s, size_type pos,
- size_type n) const
- {
- if (!empty() && n > 0)
- {
- pos = Min(pos, length() - 1);
- const_iterator i(begin() + pos);
- for (;; --i)
- {
- if (traits_type::find(s, n, *i) != 0)
- {
- return i - begin();
- }
- if (i == begin()) break;
- }
- }
- return npos;
- }
- size_type find_last_of (const value_type* s,
- size_type pos = npos) const
- { return find_last_of(s, pos, traits_type::length(s)); }
- size_type find_last_of (value_type c, size_type pos = npos) const
- { return find_last_of(&c, pos, 1); }
- size_type find_first_not_of(const flex_string& str,
- size_type pos = 0) const
- { return find_first_not_of(str.data(), pos, str.size()); }
- size_type find_first_not_of(const value_type* s, size_type pos,
- size_type n) const
- {
- if (pos < length())
- {
- const_iterator
- i(begin() + pos),
- finish(end());
- for (; i != finish; ++i)
- {
- if (traits_type::find(s, n, *i) == 0)
- {
- return i - begin();
- }
- }
- }
- return npos;
- }
- size_type find_first_not_of(const value_type* s,
- size_type pos = 0) const
- { return find_first_not_of(s, pos, traits_type::length(s)); }
- size_type find_first_not_of(value_type c, size_type pos = 0) const
- { return find_first_not_of(&c, pos, 1); }
- size_type find_last_not_of(const flex_string& str,
- size_type pos = npos) const
- { return find_last_not_of(str.c_str(), pos, str.length()); }
- size_type find_last_not_of(const value_type* s, size_type pos,
- size_type n) const
- {
- if (!empty())
- {
- pos = Min(pos, size() - 1);
- const_iterator i(begin() + pos);
- for (;; --i)
- {
- if (traits_type::find(s, n, *i) == 0)
- {
- return i - begin();
- }
- if (i == begin()) break;
- }
- }
- return npos;
- }
- size_type find_last_not_of(const value_type* s,
- size_type pos = npos) const
- { return find_last_not_of(s, pos, traits_type::length(s)); }
- size_type find_last_not_of (value_type c, size_type pos = npos) const
- { return find_last_not_of(&c, pos, 1); }
- flex_string substr(size_type pos = 0, size_type n = npos) const
- {
- Enforce(pos <= size(), (std::out_of_range*)0, "");
- return flex_string(data() + pos, Min(n, size() - pos));
- }
- std::ptrdiff_t compare(const flex_string& str) const
- {
- // FIX due to Goncalo N M de Carvalho July 18, 2005
- return compare(0, size(), str);
- }
- std::ptrdiff_t compare(size_type pos1, size_type n1,
- const flex_string& str) const
- { return compare(pos1, n1, str.data(), str.size()); }
- // FIX to compare: added the TC
- // (http://www.comeaucomputing.com/iso/lwg-defects.html number 5)
- // Thanks to Caleb Epstein for the fix
- std::ptrdiff_t compare(size_type pos1, size_type n1,
- const value_type* s) const
- {
- return compare(pos1, n1, s, traits_type::length(s));
- }
- std::ptrdiff_t compare(size_type pos1, size_type n1,
- const value_type* s, size_type n2) const
- {
- Enforce(pos1 <= size(), (std::out_of_range*)0, "");
- Procust(n1, size() - pos1);
- const int r = traits_type::compare(pos1 + data(), s, Min(n1, n2));
- return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
- }
- std::ptrdiff_t compare(size_type pos1, size_type n1,
- const flex_string& str,
- size_type pos2, size_type n2) const
- {
- Enforce(pos2 <= str.size(), (std::out_of_range*)0, "");
- return compare(pos1, n1, str.data() + pos2, Min(n2, str.size() - pos2));
- }
- std::ptrdiff_t compare(const value_type* s) const
- {
- // Could forward to compare(0, size(), s, traits_type::length(s))
- // but that does two extra checks
- const size_type n1(size()), n2(traits_type::length(s));
- const int r = traits_type::compare(data(), s, Min(n1, n2));
- return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
- }
- };
- // non-member functions
- template <typename E, class T, class A, class S>
- flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
- const flex_string<E, T, A, S>& rhs)
- {
- flex_string<E, T, A, S> result;
- result.reserve(lhs.size() + rhs.size());
- result.append(lhs).append(rhs);
- return result;
- }
- template <typename E, class T, class A, class S>
- flex_string<E, T, A, S> operator+(const typename flex_string<E, T, A, S>::value_type* lhs,
- const flex_string<E, T, A, S>& rhs)
- {
- flex_string<E, T, A, S> result;
- const typename flex_string<E, T, A, S>::size_type len =
- flex_string<E, T, A, S>::traits_type::length(lhs);
- result.reserve(len + rhs.size());
- result.append(lhs, len).append(rhs);
- return result;
- }
- template <typename E, class T, class A, class S>
- flex_string<E, T, A, S> operator+(
- typename flex_string<E, T, A, S>::value_type lhs,
- const flex_string<E, T, A, S>& rhs)
- {
- flex_string<E, T, A, S> result;
- result.reserve(1 + rhs.size());
- result.push_back(lhs);
- result.append(rhs);
- return result;
- }
- template <typename E, class T, class A, class S>
- flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
- const typename flex_string<E, T, A, S>::value_type* rhs)
- {
- typedef typename flex_string<E, T, A, S>::size_type size_type;
- typedef typename flex_string<E, T, A, S>::traits_type traits_type;
- flex_string<E, T, A, S> result;
- const size_type len = traits_type::length(rhs);
- result.reserve(lhs.size() + len);
- result.append(lhs).append(rhs, len);
- return result;
- }
- template <typename E, class T, class A, class S>
- flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
- typename flex_string<E, T, A, S>::value_type rhs)
- {
- flex_string<E, T, A, S> result;
- result.reserve(lhs.size() + 1);
- result.append(lhs);
- result.push_back(rhs);
- return result;
- }
- template <typename E, class T, class A, class S>
- inline bool operator==(const flex_string<E, T, A, S>& lhs,
- const flex_string<E, T, A, S>& rhs)
- { return lhs.compare(rhs) == 0; }
- template <typename E, class T, class A, class S>
- inline bool operator==(const typename flex_string<E, T, A, S>::value_type* lhs,
- const flex_string<E, T, A, S>& rhs)
- { return rhs == lhs; }
- template <typename E, class T, class A, class S>
- inline bool operator==(const flex_string<E, T, A, S>& lhs,
- const typename flex_string<E, T, A, S>::value_type* rhs)
- { return lhs.compare(rhs) == 0; }
- template <typename E, class T, class A, class S>
- inline bool operator!=(const flex_string<E, T, A, S>& lhs,
- const flex_string<E, T, A, S>& rhs)
- { return !(lhs == rhs); }
- template <typename E, class T, class A, class S>
- inline bool operator!=(const typename flex_string<E, T, A, S>::value_type* lhs,
- const flex_string<E, T, A, S>& rhs)
- { return !(lhs == rhs); }
- template <typename E, class T, class A, class S>
- inline bool operator!=(const flex_string<E, T, A, S>& lhs,
- const typename flex_string<E, T, A, S>::value_type* rhs)
- { return !(lhs == rhs); }
- template <typename E, class T, class A, class S>
- inline bool operator<(const flex_string<E, T, A, S>& lhs,
- const flex_string<E, T, A, S>& rhs)
- { return lhs.compare(rhs) < 0; }
- template <typename E, class T, class A, class S>
- inline bool operator<(const flex_string<E, T, A, S>& lhs,
- const typename flex_string<E, T, A, S>::value_type* rhs)
- { return lhs.compare(rhs) < 0; }
- template <typename E, class T, class A, class S>
- inline bool operator<(const typename flex_string<E, T, A, S>::value_type* lhs,
- const flex_string<E, T, A, S>& rhs)
- { return rhs.compare(lhs) > 0; }
- template <typename E, class T, class A, class S>
- inline bool operator>(const flex_string<E, T, A, S>& lhs,
- const flex_string<E, T, A, S>& rhs)
- { return rhs < lhs; }
- template <typename E, class T, class A, class S>
- inline bool operator>(const flex_string<E, T, A, S>& lhs,
- const typename flex_string<E, T, A, S>::value_type* rhs)
- { return rhs < lhs; }
- template <typename E, class T, class A, class S>
- bool operator>(const typename flex_string<E, T, A, S>::value_type* lhs,
- const flex_string<E, T, A, S>& rhs)
- { return rhs < lhs; }
- template <typename E, class T, class A, class S>
- inline bool operator<=(const flex_string<E, T, A, S>& lhs,
- const flex_string<E, T, A, S>& rhs)
- { return !(rhs < lhs); }
- template <typename E, class T, class A, class S>
- inline bool operator<=(const flex_string<E, T, A, S>& lhs,
- const typename flex_string<E, T, A, S>::value_type* rhs)
- { return !(rhs < lhs); }
- template <typename E, class T, class A, class S>
- bool operator<=(const typename flex_string<E, T, A, S>::value_type* lhs,
- const flex_string<E, T, A, S>& rhs)
- { return !(rhs < lhs); }
- template <typename E, class T, class A, class S>
- bool operator>=(const flex_string<E, T, A, S>& lhs,
- const flex_string<E, T, A, S>& rhs)
- { return !(lhs < rhs); }
- template <typename E, class T, class A, class S>
- bool operator>=(const flex_string<E, T, A, S>& lhs,
- const typename flex_string<E, T, A, S>::value_type* rhs)
- { return !(lhs < rhs); }
- template <typename E, class T, class A, class S>
- inline bool operator>=(const typename flex_string<E, T, A, S>::value_type* lhs,
- const flex_string<E, T, A, S>& rhs)
- { return !(lhs < rhs); }
- template <typename E, class T, class A, class S>
- void swap(flex_string<E, T, A, S>& lhs, flex_string<E, T, A, S>& rhs)
- {
- // subclause 21.3.7.8:
- lhs.swap(rhs);
- }
- template <typename E, class T, class A, class S>
- inline std::basic_istream<typename flex_string<E, T, A, S>::value_type,
- typename flex_string<E, T, A, S>::traits_type>&
- operator>>(
- std::basic_istream<typename flex_string<E, T, A, S>::value_type,
- typename flex_string<E, T, A, S>::traits_type>& is,
- flex_string<E, T, A, S>& str);
- template <typename E, class T, class A, class S>
- std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
- typename flex_string<E, T, A, S>::traits_type>&
- operator<<(
- std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
- typename flex_string<E, T, A, S>::traits_type>& os,
- const flex_string<E, T, A, S>& str)
- { return os << str.c_str(); }
- template <typename E1, class T, class A, class S>
- const typename flex_string<E1, T, A, S>::size_type
- flex_string<E1, T, A, S>::npos = (typename flex_string<E1, T, A, S>::size_type)(-1);
- ///////////////////////////////////////////////////////////////////////////////
- } // namespace util
- } // namespace wave
- } // namespace boost
- #if BOOST_WAVE_SERIALIZATION != 0
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace serialization {
- #if !defined(BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK)
- // FIXME: This doesn't work because of the missing flex_string::operator>>()
- template <typename E, class T, class A, class S>
- struct implementation_level<boost::wave::util::flex_string<E, T, A, S> >
- {
- typedef mpl::integral_c_tag tag;
- typedef mpl::int_<boost::serialization::primitive_type> type;
- BOOST_STATIC_CONSTANT(
- int,
- value = implementation_level::type::value
- );
- };
- #else
- // We serialize flex_strings as vectors of char's for now
- template<class Archive, typename E, class T, class A, class S>
- inline void save(Archive & ar,
- boost::wave::util::flex_string<E, T, A, S> const &t,
- const unsigned int file_version)
- {
- boost::serialization::stl::save_collection<
- Archive, wave::util::flex_string<E, T, A, S> >(ar, t);
- }
- template<class Archive, typename E, class T, class A, class S>
- inline void load(Archive & ar, boost::wave::util::flex_string<E, T, A, S> &t,
- const unsigned int file_version)
- {
- boost::serialization::stl::load_collection<
- Archive, boost::wave::util::flex_string<E, T, A, S>,
- boost::serialization::stl::archive_input_seq<
- Archive, boost::wave::util::flex_string<E, T, A, S> >,
- boost::serialization::stl::reserve_imp<
- boost::wave::util::flex_string<E, T, A, S> >
- >(ar, t);
- }
- // split non-intrusive serialization function member into separate
- // non intrusive save/load member functions
- template<class Archive, typename E, class T, class A, class S>
- inline void serialize(Archive & ar, boost::wave::util::flex_string<E, T, A, S> &t,
- const unsigned int file_version)
- {
- boost::serialization::split_free(ar, t, file_version);
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- }} // boost::serialization
- #endif
- // the suffix header occurs after all of the code
- #ifdef BOOST_HAS_ABI_HEADERS
- #include BOOST_ABI_SUFFIX
- #endif
- #endif // BOOST_FLEX_STRING_INC_
|