flex_string.hpp 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. http://www.boost.org/
  4. Copyright (c) 2001 by Andrei Alexandrescu. Distributed under the Boost
  5. Software License, Version 1.0. (See accompanying file
  6. LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. // This code is taken from:
  9. // Andrei Alexandrescu, Generic<Programming>: A Policy-Based basic_string
  10. // Implementation. http://www.cuj.com/documents/s=7994/cujcexp1906alexandr/
  11. //
  12. // #HK030306:
  13. // - Moved into the namespace boost::wave::util
  14. // - Added a bunch of missing typename(s)
  15. // - Integrated with boost config
  16. // - Added a missing header include
  17. // - Added special constructors and operator= to allow CowString to be
  18. // a real COW-string (removed unnecessary data copying)
  19. // - Fixed a string terminating bug in append
  20. //
  21. // #HK040109:
  22. // - Incorporated the changes from Andrei's latest version of this class
  23. //
  24. // #HK070307:
  25. // - Once again incorporated the changes from Andrei's latest version of
  26. // this class
  27. //
  28. // #HK090523:
  29. // - Incorporated the changes from latest version of flex_string as
  30. // maintained in Loki
  31. //
  32. // #HK130910:
  33. // - Removed the getline implementation which was borrowed from the SGI
  34. // STL as the license for this code is not compatible with Boost.
  35. #ifndef BOOST_FLEX_STRING_INC_
  36. #define BOOST_FLEX_STRING_INC_
  37. /*
  38. ////////////////////////////////////////////////////////////////////////////////
  39. template <typename E, class A = @>
  40. class StoragePolicy
  41. {
  42. typedef E value_type;
  43. typedef @ iterator;
  44. typedef @ const_iterator;
  45. typedef A allocator_type;
  46. typedef @ size_type;
  47. StoragePolicy(const StoragePolicy& s);
  48. StoragePolicy(const A&);
  49. StoragePolicy(const E* s, size_type len, const A&);
  50. StoragePolicy(size_type len, E c, const A&);
  51. ~StoragePolicy();
  52. iterator begin();
  53. const_iterator begin() const;
  54. iterator end();
  55. const_iterator end() const;
  56. size_type size() const;
  57. size_type max_size() const;
  58. size_type capacity() const;
  59. void reserve(size_type res_arg);
  60. void append(const E* s, size_type sz);
  61. template <class InputIterator>
  62. void append(InputIterator b, InputIterator e);
  63. void resize(size_type newSize, E fill);
  64. void swap(StoragePolicy& rhs);
  65. const E* c_str() const;
  66. const E* data() const;
  67. A get_allocator() const;
  68. };
  69. ////////////////////////////////////////////////////////////////////////////////
  70. */
  71. #include <boost/config.hpp>
  72. #include <boost/assert.hpp>
  73. #include <boost/throw_exception.hpp>
  74. #include <boost/core/allocator_access.hpp>
  75. #include <boost/iterator/reverse_iterator.hpp>
  76. #include <boost/wave/wave_config.hpp>
  77. #if BOOST_WAVE_SERIALIZATION != 0
  78. #include <boost/serialization/serialization.hpp>
  79. #include <boost/serialization/split_free.hpp>
  80. #include <boost/serialization/collections_save_imp.hpp>
  81. #include <boost/serialization/collections_load_imp.hpp>
  82. #define BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK 1
  83. #endif
  84. #include <memory>
  85. #include <new>
  86. #include <vector>
  87. #include <algorithm>
  88. #include <functional>
  89. #include <limits>
  90. #include <stdexcept>
  91. #include <ios>
  92. #include <cstddef>
  93. #include <cstring>
  94. #include <cstdlib>
  95. // this must occur after all of the includes and before any code appears
  96. #ifdef BOOST_HAS_ABI_HEADERS
  97. #include BOOST_ABI_PREFIX
  98. #endif
  99. ///////////////////////////////////////////////////////////////////////////////
  100. namespace boost {
  101. namespace wave {
  102. namespace util {
  103. namespace flex_string_details
  104. {
  105. template <class InIt, class OutIt>
  106. OutIt copy_n(InIt b,
  107. typename std::iterator_traits<InIt>::difference_type n, OutIt d)
  108. {
  109. for (/**/; n != 0; --n, ++b, ++d)
  110. {
  111. *d = *b;
  112. }
  113. return d;
  114. }
  115. template <class Pod, class T>
  116. inline void pod_fill(Pod* b, Pod* e, T c)
  117. {
  118. switch ((e - b) & 7)
  119. {
  120. case 0:
  121. while (b != e)
  122. {
  123. *b = c; ++b; BOOST_FALLTHROUGH;
  124. case 7: *b = c; ++b; BOOST_FALLTHROUGH;
  125. case 6: *b = c; ++b; BOOST_FALLTHROUGH;
  126. case 5: *b = c; ++b; BOOST_FALLTHROUGH;
  127. case 4: *b = c; ++b; BOOST_FALLTHROUGH;
  128. case 3: *b = c; ++b; BOOST_FALLTHROUGH;
  129. case 2: *b = c; ++b; BOOST_FALLTHROUGH;
  130. case 1: *b = c; ++b;
  131. }
  132. }
  133. }
  134. template <class Pod>
  135. inline void pod_move(const Pod* b, const Pod* e, Pod* d)
  136. {
  137. using namespace std;
  138. memmove(d, b, (e - b) * sizeof(*b));
  139. }
  140. template <class Pod>
  141. inline Pod* pod_copy(const Pod* b, const Pod* e, Pod* d)
  142. {
  143. const std::size_t s = e - b;
  144. using namespace std;
  145. memcpy(d, b, s * sizeof(*b));
  146. return d + s;
  147. }
  148. template <typename T> struct get_unsigned
  149. {
  150. typedef T result;
  151. };
  152. template <> struct get_unsigned<char>
  153. {
  154. typedef unsigned char result;
  155. };
  156. template <> struct get_unsigned<signed char>
  157. {
  158. typedef unsigned char result;
  159. };
  160. template <> struct get_unsigned<short int>
  161. {
  162. typedef unsigned short int result;
  163. };
  164. template <> struct get_unsigned<int>
  165. {
  166. typedef unsigned int result;
  167. };
  168. template <> struct get_unsigned<long int>
  169. {
  170. typedef unsigned long int result;
  171. };
  172. enum Shallow {};
  173. }
  174. template <class T> class mallocator
  175. {
  176. public:
  177. typedef T value_type;
  178. typedef value_type* pointer;
  179. typedef const value_type* const_pointer;
  180. typedef value_type& reference;
  181. typedef const value_type& const_reference;
  182. typedef std::size_t size_type;
  183. //typedef unsigned int size_type;
  184. //typedef std::ptrdiff_t difference_type;
  185. typedef int difference_type;
  186. template <class U>
  187. struct rebind { typedef mallocator<U> other; };
  188. mallocator() {}
  189. mallocator(const mallocator&) {}
  190. //template <class U>
  191. //mallocator(const mallocator<U>&) {}
  192. ~mallocator() {}
  193. pointer address(reference x) const { return &x; }
  194. const_pointer address(const_reference x) const
  195. {
  196. return x;
  197. }
  198. pointer allocate(size_type n, const_pointer = 0)
  199. {
  200. using namespace std;
  201. void* p = malloc(n * sizeof(T));
  202. if (!p) boost::throw_exception(std::bad_alloc());
  203. return static_cast<pointer>(p);
  204. }
  205. void deallocate(pointer p, size_type)
  206. {
  207. using namespace std;
  208. free(p);
  209. }
  210. size_type max_size() const
  211. {
  212. return static_cast<size_type>(-1) / sizeof(T);
  213. }
  214. void construct(pointer p, const value_type& x)
  215. {
  216. new(p) value_type(x);
  217. }
  218. void destroy(pointer p)
  219. {
  220. p->~value_type();
  221. }
  222. private:
  223. void operator=(const mallocator&);
  224. };
  225. template<> class mallocator<void>
  226. {
  227. typedef void value_type;
  228. typedef void* pointer;
  229. typedef const void* const_pointer;
  230. template <class U>
  231. struct rebind { typedef mallocator<U> other; };
  232. };
  233. template <class T>
  234. inline bool operator==(const mallocator<T>&,
  235. const mallocator<T>&) {
  236. return true;
  237. }
  238. template <class T>
  239. inline bool operator!=(const mallocator<T>&,
  240. const mallocator<T>&) {
  241. return false;
  242. }
  243. #if defined(BOOST_GCC) && BOOST_GCC >= 40700
  244. // gcc 11.2 fails to deduce below that pData_ never points to emptyString_ if capacity() == 0 and emits warnings like these:
  245. // 'operator delete(void*, unsigned long)' called on unallocated object 'boost::wave::util::SimpleStringStorage<char, std::allocator<char> >::emptyString_' [-Wfree-nonheap-object]
  246. // Unfortunately, suppressing this warning doesn't work, so we have to use __builtin_unreachable() to assert that this never happens.
  247. // __builtin_unreachable is supported since gcc 4.6, -Wfree-nonheap-object is supported since 4.7.
  248. #define BOOST_WAVE_COMPILE_TIME_ASSERT(x) if (!(x)) __builtin_unreachable()
  249. #else
  250. #define BOOST_WAVE_COMPILE_TIME_ASSERT(x)
  251. #endif
  252. ////////////////////////////////////////////////////////////////////////////////
  253. // class template SimpleStringStorage
  254. // Allocates memory with malloc
  255. ////////////////////////////////////////////////////////////////////////////////
  256. template <typename E, class A = std::allocator<E> >
  257. class SimpleStringStorage
  258. {
  259. // The "public" below exists because MSVC can't do template typedefs
  260. public:
  261. struct Data
  262. {
  263. Data() : pEnd_(buffer_), pEndOfMem_(buffer_) { buffer_[0] = E(0); }
  264. E* pEnd_;
  265. E* pEndOfMem_;
  266. E buffer_[1];
  267. };
  268. static const Data emptyString_;
  269. typedef typename boost::allocator_size_type<A>::type size_type;
  270. private:
  271. Data* pData_;
  272. void Init(size_type size, size_type capacity)
  273. {
  274. BOOST_ASSERT(size <= capacity);
  275. if (capacity == 0)
  276. {
  277. pData_ = const_cast<Data*>(&emptyString_);
  278. }
  279. else
  280. {
  281. // 11-17-2000: comment added:
  282. // No need to allocate (capacity + 1) to
  283. // accommodate the terminating 0, because Data already
  284. // has one character in there
  285. pData_ = static_cast<Data*>(
  286. malloc(sizeof(Data) + capacity * sizeof(E)));
  287. if (!pData_) boost::throw_exception(std::bad_alloc());
  288. pData_->pEnd_ = pData_->buffer_ + size;
  289. pData_->pEndOfMem_ = pData_->buffer_ + capacity;
  290. }
  291. }
  292. private:
  293. // Warning - this doesn't initialize pData_. Used in reserve()
  294. SimpleStringStorage()
  295. { }
  296. public:
  297. typedef E value_type;
  298. typedef E* iterator;
  299. typedef const E* const_iterator;
  300. typedef A allocator_type;
  301. SimpleStringStorage(const SimpleStringStorage& rhs)
  302. {
  303. const size_type sz = rhs.size();
  304. Init(sz, sz);
  305. if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
  306. }
  307. SimpleStringStorage(const SimpleStringStorage& s,
  308. flex_string_details::Shallow)
  309. : pData_(s.pData_)
  310. {
  311. }
  312. SimpleStringStorage(const A&)
  313. { pData_ = const_cast<Data*>(&emptyString_); }
  314. SimpleStringStorage(const E* s, size_type len, const A&)
  315. {
  316. Init(len, len);
  317. flex_string_details::pod_copy(s, s + len, begin());
  318. }
  319. SimpleStringStorage(size_type len, E c, const A&)
  320. {
  321. Init(len, len);
  322. flex_string_details::pod_fill(begin(), end(), c);
  323. }
  324. SimpleStringStorage& operator=(const SimpleStringStorage& rhs)
  325. {
  326. const size_type sz = rhs.size();
  327. reserve(sz);
  328. flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
  329. pData_->pEnd_ = &*begin() + sz;
  330. return *this;
  331. }
  332. ~SimpleStringStorage()
  333. {
  334. BOOST_ASSERT(begin() <= end());
  335. if (capacity() > 0)
  336. {
  337. BOOST_WAVE_COMPILE_TIME_ASSERT(pData_ != &emptyString_);
  338. free(pData_);
  339. }
  340. }
  341. iterator begin()
  342. { return pData_->buffer_; }
  343. const_iterator begin() const
  344. { return pData_->buffer_; }
  345. iterator end()
  346. { return pData_->pEnd_; }
  347. const_iterator end() const
  348. { return pData_->pEnd_; }
  349. size_type size() const
  350. { return pData_->pEnd_ - pData_->buffer_; }
  351. size_type max_size() const
  352. { return std::size_t(-1) / sizeof(E) - sizeof(Data) - 1; }
  353. size_type capacity() const
  354. { return pData_->pEndOfMem_ - pData_->buffer_; }
  355. void reserve(size_type res_arg)
  356. {
  357. size_type cap = capacity();
  358. if (res_arg <= cap)
  359. {
  360. // @@@ insert shrinkage here if you wish
  361. return;
  362. }
  363. if (cap == 0)
  364. {
  365. Init(0, res_arg);
  366. }
  367. else
  368. {
  369. const size_type sz = size();
  370. void* p = realloc(pData_,
  371. sizeof(Data) + res_arg * sizeof(E));
  372. if (!p) boost::throw_exception(std::bad_alloc());
  373. if (p != pData_)
  374. {
  375. pData_ = static_cast<Data*>(p);
  376. pData_->pEnd_ = pData_->buffer_ + sz;
  377. }
  378. pData_->pEndOfMem_ = pData_->buffer_ + res_arg;
  379. }
  380. }
  381. void append(const E* s, size_type sz)
  382. {
  383. const size_type neededCapacity = size() + sz;
  384. if (capacity() < neededCapacity)
  385. {
  386. const iterator b = begin();
  387. static std::less_equal<const E*> le;
  388. if (le(b, s) && le(s, end()))
  389. {
  390. // aliased
  391. const size_type offset = s - b;
  392. reserve(neededCapacity);
  393. s = begin() + offset;
  394. }
  395. else
  396. {
  397. reserve(neededCapacity);
  398. }
  399. }
  400. flex_string_details::pod_copy(s, s + sz, end());
  401. pData_->pEnd_ += sz;
  402. }
  403. template <class InputIterator>
  404. void append(InputIterator b, InputIterator e)
  405. {
  406. // @@@ todo: optimize this depending on iterator type
  407. for (; b != e; ++b)
  408. {
  409. *this += *b;
  410. }
  411. }
  412. void resize(size_type newSize, E fill)
  413. {
  414. const int delta = int(newSize - size());
  415. if (delta == 0) return;
  416. if (delta > 0)
  417. {
  418. if (newSize > capacity())
  419. {
  420. reserve(newSize);
  421. }
  422. E* e = &*end();
  423. flex_string_details::pod_fill(e, e + delta, fill);
  424. }
  425. pData_->pEnd_ = pData_->buffer_ + newSize;
  426. }
  427. void swap(SimpleStringStorage& rhs)
  428. {
  429. std::swap(pData_, rhs.pData_);
  430. }
  431. const E* c_str() const
  432. {
  433. if (capacity() > 0) *pData_->pEnd_ = E();
  434. return pData_->buffer_;
  435. }
  436. const E* data() const
  437. { return pData_->buffer_; }
  438. A get_allocator() const
  439. { return A(); }
  440. };
  441. template <typename E, class A>
  442. const typename SimpleStringStorage<E, A>::Data
  443. SimpleStringStorage<E, A>::emptyString_ =
  444. typename SimpleStringStorage<E, A>::Data();
  445. ////////////////////////////////////////////////////////////////////////////////
  446. // class template AllocatorStringStorage
  447. // Allocates with your allocator
  448. // Takes advantage of the Empty Base Optimization if available
  449. ////////////////////////////////////////////////////////////////////////////////
  450. template <typename E, class A = std::allocator<E> >
  451. class AllocatorStringStorage : public A
  452. {
  453. typedef typename boost::allocator_size_type<A>::type size_type;
  454. typedef typename SimpleStringStorage<E, A>::Data Data;
  455. void* Alloc(size_type sz, const void* p = 0)
  456. {
  457. return boost::allocator_allocate(static_cast<A&>(*this), 1 + (sz - 1) / sizeof(E),
  458. static_cast<const char*>(p));
  459. }
  460. void Free(void* p, size_type sz)
  461. {
  462. boost::allocator_deallocate(static_cast<A&>(*this), static_cast<E*>(p), sz);
  463. }
  464. Data* pData_;
  465. void Init(size_type size, size_type cap)
  466. {
  467. BOOST_ASSERT(size <= cap);
  468. if (cap == 0)
  469. {
  470. pData_ = const_cast<Data*>(
  471. &SimpleStringStorage<E, A>::emptyString_);
  472. }
  473. else
  474. {
  475. pData_ = static_cast<Data*>(Alloc(
  476. cap * sizeof(E) + sizeof(Data)));
  477. pData_->pEnd_ = pData_->buffer_ + size;
  478. pData_->pEndOfMem_ = pData_->buffer_ + cap;
  479. }
  480. }
  481. public:
  482. typedef E value_type;
  483. typedef E* iterator;
  484. typedef const E* const_iterator;
  485. typedef A allocator_type;
  486. AllocatorStringStorage()
  487. : A(), pData_(0)
  488. {
  489. }
  490. AllocatorStringStorage(const AllocatorStringStorage& rhs)
  491. : A(rhs.get_allocator())
  492. {
  493. const size_type sz = rhs.size();
  494. Init(sz, sz);
  495. if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
  496. }
  497. AllocatorStringStorage(const AllocatorStringStorage& s,
  498. flex_string_details::Shallow)
  499. : A(s.get_allocator())
  500. {
  501. pData_ = s.pData_;
  502. }
  503. AllocatorStringStorage(const A& a) : A(a)
  504. {
  505. pData_ = const_cast<Data*>(
  506. &SimpleStringStorage<E, A>::emptyString_);
  507. }
  508. AllocatorStringStorage(const E* s, size_type len, const A& a)
  509. : A(a)
  510. {
  511. Init(len, len);
  512. flex_string_details::pod_copy(s, s + len, begin());
  513. }
  514. AllocatorStringStorage(size_type len, E c, const A& a)
  515. : A(a)
  516. {
  517. Init(len, len);
  518. flex_string_details::pod_fill(&*begin(), &*end(), c);
  519. }
  520. AllocatorStringStorage& operator=(const AllocatorStringStorage& rhs)
  521. {
  522. const size_type sz = rhs.size();
  523. reserve(sz);
  524. flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
  525. pData_->pEnd_ = &*begin() + rhs.size();
  526. return *this;
  527. }
  528. ~AllocatorStringStorage()
  529. {
  530. if (capacity())
  531. {
  532. BOOST_WAVE_COMPILE_TIME_ASSERT(pData_ != (&SimpleStringStorage<E, A>::emptyString_));
  533. Free(pData_,
  534. sizeof(Data) + capacity() * sizeof(E));
  535. }
  536. }
  537. iterator begin()
  538. { return pData_->buffer_; }
  539. const_iterator begin() const
  540. { return pData_->buffer_; }
  541. iterator end()
  542. { return pData_->pEnd_; }
  543. const_iterator end() const
  544. { return pData_->pEnd_; }
  545. size_type size() const
  546. { return size_type(end() - begin()); }
  547. size_type max_size() const
  548. { return boost::allocator_max_size(static_cast<const A&>(*this)); }
  549. size_type capacity() const
  550. { return size_type(pData_->pEndOfMem_ - pData_->buffer_); }
  551. void resize(size_type n, E c)
  552. {
  553. reserve(n);
  554. iterator newEnd = begin() + n;
  555. iterator oldEnd = end();
  556. if (newEnd > oldEnd)
  557. {
  558. // Copy the characters
  559. flex_string_details::pod_fill(oldEnd, newEnd, c);
  560. }
  561. if (capacity()) pData_->pEnd_ = newEnd;
  562. }
  563. void reserve(size_type res_arg)
  564. {
  565. if (res_arg <= capacity())
  566. {
  567. // @@@ shrink to fit here
  568. return;
  569. }
  570. A& myAlloc = *this;
  571. AllocatorStringStorage newStr(myAlloc);
  572. newStr.Init(size(), res_arg);
  573. flex_string_details::pod_copy(begin(), end(), newStr.begin());
  574. swap(newStr);
  575. }
  576. template <class ForwardIterator>
  577. void append(ForwardIterator b, ForwardIterator e)
  578. {
  579. const size_type
  580. sz = std::distance(b, e),
  581. neededCapacity = size() + sz;
  582. if (capacity() < neededCapacity)
  583. {
  584. // typedef std::less_equal<const E*> le_type;
  585. // BOOST_ASSERT(!(le_type()(begin(), &*b) && le_type()(&*b, end())));
  586. reserve(neededCapacity);
  587. }
  588. std::copy(b, e, end());
  589. pData_->pEnd_ += sz;
  590. }
  591. void swap(AllocatorStringStorage& rhs)
  592. {
  593. // @@@ The following line is commented due to a bug in MSVC
  594. //std::swap(lhsAlloc, rhsAlloc);
  595. std::swap(pData_, rhs.pData_);
  596. }
  597. const E* c_str() const
  598. {
  599. if (capacity() > 0)
  600. {
  601. *pData_->pEnd_ = E();
  602. }
  603. return &*begin();
  604. }
  605. const E* data() const
  606. { return &*begin(); }
  607. A get_allocator() const
  608. { return *this; }
  609. };
  610. ////////////////////////////////////////////////////////////////////////////////
  611. // class template VectorStringStorage
  612. // Uses std::vector
  613. // Takes advantage of the Empty Base Optimization if available
  614. ////////////////////////////////////////////////////////////////////////////////
  615. template <typename E, class A = std::allocator<E> >
  616. class VectorStringStorage : protected std::vector<E, A>
  617. {
  618. typedef std::vector<E, A> base;
  619. public: // protected:
  620. typedef E value_type;
  621. typedef typename base::iterator iterator;
  622. typedef typename base::const_iterator const_iterator;
  623. typedef A allocator_type;
  624. typedef typename boost::allocator_size_type<A>::type size_type;
  625. VectorStringStorage(const VectorStringStorage& s) : base(s)
  626. { }
  627. VectorStringStorage(const A& a) : base(1, E(), a)
  628. { }
  629. VectorStringStorage(const E* s, size_type len, const A& a)
  630. : base(a)
  631. {
  632. base::reserve(len + 1);
  633. base::insert(base::end(), s, s + len);
  634. // Terminating zero
  635. base::insert(base::end(), E());
  636. }
  637. VectorStringStorage(size_type len, E c, const A& a)
  638. : base(len + 1, c, a)
  639. {
  640. // Terminating zero
  641. base::back() = E();
  642. }
  643. VectorStringStorage& operator=(const VectorStringStorage& rhs)
  644. {
  645. base& v = *this;
  646. v = rhs;
  647. return *this;
  648. }
  649. iterator begin()
  650. { return base::begin(); }
  651. const_iterator begin() const
  652. { return base::begin(); }
  653. iterator end()
  654. { return base::end() - 1; }
  655. const_iterator end() const
  656. { return base::end() - 1; }
  657. size_type size() const
  658. { return base::size() - 1; }
  659. size_type max_size() const
  660. { return base::max_size() - 1; }
  661. size_type capacity() const
  662. { return base::capacity() - 1; }
  663. void reserve(size_type res_arg)
  664. {
  665. BOOST_ASSERT(res_arg < max_size());
  666. base::reserve(res_arg + 1);
  667. }
  668. void append(const E* s, size_type sz)
  669. {
  670. // Check for aliasing because std::vector doesn't do it.
  671. static std::less_equal<const E*> le;
  672. if (!base::empty())
  673. {
  674. const E* start = &base::front();
  675. if (le(start, s) && le(s, start + size()))
  676. {
  677. // aliased
  678. const size_type offset = s - start;
  679. reserve(size() + sz);
  680. s = &base::front() + offset;
  681. }
  682. }
  683. base::insert(end(), s, s + sz);
  684. }
  685. template <class InputIterator>
  686. void append(InputIterator b, InputIterator e)
  687. {
  688. base::insert(end(), b, e);
  689. }
  690. void resize(size_type n, E c)
  691. {
  692. base::reserve(n + 1);
  693. base::back() = c;
  694. base::resize(n + 1, c);
  695. base::back() = E();
  696. }
  697. void swap(VectorStringStorage& rhs)
  698. { base::swap(rhs); }
  699. const E* c_str() const
  700. { return &*begin(); }
  701. const E* data() const
  702. { return &*begin(); }
  703. A get_allocator() const
  704. { return base::get_allocator(); }
  705. };
  706. ////////////////////////////////////////////////////////////////////////////////
  707. // class template SmallStringOpt
  708. // Builds the small string optimization over any other storage
  709. ////////////////////////////////////////////////////////////////////////////////
  710. template <class Storage, unsigned int threshold,
  711. typename Align = typename Storage::value_type*>
  712. class SmallStringOpt
  713. {
  714. public:
  715. typedef typename Storage::value_type value_type;
  716. typedef value_type* iterator;
  717. typedef const value_type* const_iterator;
  718. typedef typename Storage::allocator_type allocator_type;
  719. typedef typename boost::allocator_size_type<allocator_type>::type size_type;
  720. private:
  721. enum { temp1 = threshold * sizeof(value_type) > sizeof(Storage)
  722. ? threshold * sizeof(value_type)
  723. : sizeof(Storage) };
  724. enum { temp2 = temp1 > sizeof(Align) ? temp1 : sizeof(Align) };
  725. public:
  726. enum { maxSmallString =
  727. (temp2 + sizeof(value_type) - 1) / sizeof(value_type) };
  728. private:
  729. enum { magic = maxSmallString + 1 };
  730. union
  731. {
  732. mutable value_type buf_[maxSmallString + 1];
  733. Align align_;
  734. };
  735. Storage& GetStorage()
  736. {
  737. BOOST_ASSERT(buf_[maxSmallString] == magic);
  738. Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
  739. return *p;
  740. }
  741. const Storage& GetStorage() const
  742. {
  743. BOOST_ASSERT(buf_[maxSmallString] == magic);
  744. const Storage *p = reinterpret_cast<const Storage*>(&buf_[0]);
  745. return *p;
  746. }
  747. bool Small() const
  748. {
  749. return buf_[maxSmallString] != magic;
  750. }
  751. public:
  752. SmallStringOpt(const SmallStringOpt& s)
  753. {
  754. if (s.Small())
  755. {
  756. flex_string_details::pod_copy(
  757. s.buf_,
  758. s.buf_ + s.size(),
  759. buf_);
  760. }
  761. else
  762. {
  763. new(buf_) Storage(s.GetStorage());
  764. }
  765. buf_[maxSmallString] = s.buf_[maxSmallString];
  766. }
  767. SmallStringOpt(const allocator_type&)
  768. {
  769. buf_[maxSmallString] = maxSmallString;
  770. }
  771. SmallStringOpt(const value_type* s, size_type len, const allocator_type& a)
  772. {
  773. if (len <= maxSmallString)
  774. {
  775. flex_string_details::pod_copy(s, s + len, buf_);
  776. buf_[maxSmallString] = value_type(maxSmallString - len);
  777. }
  778. else
  779. {
  780. new(buf_) Storage(s, len, a);
  781. buf_[maxSmallString] = magic;
  782. }
  783. }
  784. SmallStringOpt(size_type len, value_type c, const allocator_type& a)
  785. {
  786. if (len <= maxSmallString)
  787. {
  788. flex_string_details::pod_fill(buf_, buf_ + len, c);
  789. buf_[maxSmallString] = value_type(maxSmallString - len);
  790. }
  791. else
  792. {
  793. new(buf_) Storage(len, c, a);
  794. buf_[maxSmallString] = magic;
  795. }
  796. }
  797. SmallStringOpt& operator=(const SmallStringOpt& rhs)
  798. {
  799. reserve(rhs.size());
  800. resize(0, 0);
  801. append(rhs.data(), rhs.size());
  802. return *this;
  803. }
  804. ~SmallStringOpt()
  805. {
  806. if (!Small()) GetStorage().~Storage();
  807. }
  808. iterator begin()
  809. {
  810. if (Small()) return buf_;
  811. return &*GetStorage().begin();
  812. }
  813. const_iterator begin() const
  814. {
  815. if (Small()) return buf_;
  816. return &*GetStorage().begin();
  817. }
  818. iterator end()
  819. {
  820. if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
  821. return &*GetStorage().end();
  822. }
  823. const_iterator end() const
  824. {
  825. if (Small()) return buf_ + maxSmallString - buf_[maxSmallString];
  826. return &*GetStorage().end();
  827. }
  828. size_type size() const
  829. {
  830. BOOST_ASSERT(!Small() || maxSmallString >= buf_[maxSmallString]);
  831. return Small()
  832. ? maxSmallString - buf_[maxSmallString]
  833. : GetStorage().size();
  834. }
  835. size_type max_size() const
  836. { return boost::allocator_max_size(get_allocator()); }
  837. size_type capacity() const
  838. { return Small() ? maxSmallString : GetStorage().capacity(); }
  839. void reserve(size_type res_arg)
  840. {
  841. if (Small())
  842. {
  843. if (res_arg <= maxSmallString) return;
  844. SmallStringOpt temp(*this);
  845. this->~SmallStringOpt();
  846. new(buf_) Storage(temp.data(), temp.size(),
  847. temp.get_allocator());
  848. buf_[maxSmallString] = magic;
  849. GetStorage().reserve(res_arg);
  850. }
  851. else
  852. {
  853. GetStorage().reserve(res_arg);
  854. }
  855. BOOST_ASSERT(capacity() >= res_arg);
  856. }
  857. void append(const value_type* s, size_type sz)
  858. {
  859. if (!Small())
  860. {
  861. GetStorage().append(s, sz);
  862. }
  863. else
  864. {
  865. // append to a small string
  866. const size_type neededCapacity =
  867. maxSmallString - buf_[maxSmallString] + sz;
  868. if (maxSmallString < neededCapacity)
  869. {
  870. // need to change storage strategy
  871. allocator_type alloc;
  872. Storage temp(alloc);
  873. temp.reserve(neededCapacity);
  874. temp.append(buf_, maxSmallString - buf_[maxSmallString]);
  875. temp.append(s, sz);
  876. buf_[maxSmallString] = magic;
  877. new(buf_) Storage(temp.get_allocator());
  878. GetStorage().swap(temp);
  879. }
  880. else
  881. {
  882. flex_string_details::pod_move(s, s + sz,
  883. buf_ + maxSmallString - buf_[maxSmallString]);
  884. buf_[maxSmallString] -= value_type(sz);
  885. }
  886. }
  887. }
  888. template <class InputIterator>
  889. void append(InputIterator b, InputIterator e)
  890. {
  891. // @@@ todo: optimize this depending on iterator type
  892. for (; b != e; ++b)
  893. {
  894. *this += *b;
  895. }
  896. }
  897. void resize(size_type n, value_type c)
  898. {
  899. if (Small())
  900. {
  901. if (n > maxSmallString)
  902. {
  903. // Small string resized to big string
  904. SmallStringOpt temp(*this); // can't throw
  905. // 11-17-2001: correct exception safety bug
  906. Storage newString(temp.data(), temp.size(),
  907. temp.get_allocator());
  908. newString.resize(n, c);
  909. // We make the reasonable assumption that an empty Storage
  910. // constructor won't throw
  911. this->~SmallStringOpt();
  912. new(&buf_[0]) Storage(temp.get_allocator());
  913. buf_[maxSmallString] = value_type(magic);
  914. GetStorage().swap(newString);
  915. }
  916. else
  917. {
  918. // Small string resized to small string
  919. // 11-17-2001: bug fix: terminating zero not copied
  920. size_type toFill = n > size() ? n - size() : 0;
  921. flex_string_details::pod_fill(end(), end() + toFill, c);
  922. buf_[maxSmallString] = value_type(maxSmallString - n);
  923. }
  924. }
  925. else
  926. {
  927. if (n > maxSmallString)
  928. {
  929. // Big string resized to big string
  930. GetStorage().resize(n, c);
  931. }
  932. else
  933. {
  934. // Big string resized to small string
  935. // 11-17=2001: bug fix in the BOOST_ASSERTion below
  936. BOOST_ASSERT(capacity() > n);
  937. SmallStringOpt newObj(data(), n, get_allocator());
  938. newObj.swap(*this);
  939. }
  940. }
  941. }
  942. void swap(SmallStringOpt& rhs)
  943. {
  944. if (Small())
  945. {
  946. if (rhs.Small())
  947. {
  948. // Small swapped with small
  949. std::swap_ranges(buf_, buf_ + maxSmallString + 1,
  950. rhs.buf_);
  951. }
  952. else
  953. {
  954. // Small swapped with big
  955. // Make a copy of myself - can't throw
  956. SmallStringOpt temp(*this);
  957. // Nuke myself
  958. this->~SmallStringOpt();
  959. // Make an empty storage for myself (likely won't throw)
  960. new(buf_) Storage(0, value_type(), rhs.get_allocator());
  961. buf_[maxSmallString] = magic;
  962. // Recurse to this same function
  963. swap(rhs);
  964. // Nuke rhs
  965. rhs.~SmallStringOpt();
  966. // Build the new small string into rhs
  967. new(&rhs) SmallStringOpt(temp);
  968. }
  969. }
  970. else
  971. {
  972. if (rhs.Small())
  973. {
  974. // Big swapped with small
  975. // Already implemented, recurse with reversed args
  976. rhs.swap(*this);
  977. }
  978. else
  979. {
  980. // Big swapped with big
  981. GetStorage().swap(rhs.GetStorage());
  982. }
  983. }
  984. }
  985. const value_type* c_str() const
  986. {
  987. if (!Small()) return GetStorage().c_str();
  988. buf_[maxSmallString - buf_[maxSmallString]] = value_type();
  989. return buf_;
  990. }
  991. const value_type* data() const
  992. { return Small() ? buf_ : GetStorage().data(); }
  993. allocator_type get_allocator() const
  994. { return allocator_type(); }
  995. };
  996. ////////////////////////////////////////////////////////////////////////////////
  997. // class template CowString
  998. // Implements Copy on Write over any storage
  999. ////////////////////////////////////////////////////////////////////////////////
  1000. template <
  1001. typename Storage,
  1002. typename Align = BOOST_DEDUCED_TYPENAME Storage::value_type*
  1003. >
  1004. class CowString
  1005. {
  1006. typedef typename Storage::value_type E;
  1007. typedef typename flex_string_details::get_unsigned<E>::result RefCountType;
  1008. public:
  1009. typedef E value_type;
  1010. typedef typename Storage::iterator iterator;
  1011. typedef typename Storage::const_iterator const_iterator;
  1012. typedef typename Storage::allocator_type allocator_type;
  1013. typedef typename boost::allocator_size_type<allocator_type>::type size_type;
  1014. typedef typename Storage::value_type& reference;
  1015. private:
  1016. union
  1017. {
  1018. mutable char buf_[sizeof(Storage)];
  1019. Align align_;
  1020. };
  1021. Storage& Data() const
  1022. {
  1023. Storage* p = reinterpret_cast<Storage*>(&buf_[0]);
  1024. return *p;
  1025. }
  1026. RefCountType GetRefs() const
  1027. {
  1028. const Storage& d = Data();
  1029. BOOST_ASSERT(d.size() > 0);
  1030. BOOST_ASSERT(static_cast<RefCountType>(*d.begin()) != 0);
  1031. return *d.begin();
  1032. }
  1033. RefCountType& Refs()
  1034. {
  1035. Storage& d = Data();
  1036. BOOST_ASSERT(d.size() > 0);
  1037. return reinterpret_cast<RefCountType&>(*d.begin());
  1038. }
  1039. void MakeUnique() const
  1040. {
  1041. BOOST_ASSERT(GetRefs() >= 1);
  1042. if (GetRefs() == 1) return;
  1043. union
  1044. {
  1045. char buf_[sizeof(Storage)];
  1046. Align align_;
  1047. } temp;
  1048. --(*Data().begin()); // decrement the use count of the remaining object
  1049. Storage* p = reinterpret_cast<Storage*>(&temp.buf_[0]);
  1050. new(buf_) Storage(
  1051. *new(p) Storage(Data()),
  1052. flex_string_details::Shallow());
  1053. *Data().begin() = 1;
  1054. }
  1055. public:
  1056. CowString(const CowString& s)
  1057. {
  1058. if (s.GetRefs() == (std::numeric_limits<RefCountType>::max)())
  1059. {
  1060. // must make a brand new copy
  1061. new(buf_) Storage(s.Data()); // non shallow
  1062. Refs() = 1;
  1063. }
  1064. else
  1065. {
  1066. new(buf_) Storage(s.Data(), flex_string_details::Shallow());
  1067. ++Refs();
  1068. }
  1069. BOOST_ASSERT(Data().size() > 0);
  1070. }
  1071. CowString(const allocator_type& a)
  1072. {
  1073. new(buf_) Storage(1, 1, a);
  1074. }
  1075. CowString(const E* s, size_type len, const allocator_type& a)
  1076. {
  1077. // Warning - MSVC's debugger has trouble tracing through the code below.
  1078. // It seems to be a const-correctness issue
  1079. //
  1080. new(buf_) Storage(a);
  1081. Data().reserve(len + 1);
  1082. Data().resize(1, 1);
  1083. Data().append(s, s + len);
  1084. }
  1085. CowString(size_type len, E c, const allocator_type& a)
  1086. {
  1087. new(buf_) Storage(len + 1, c, a);
  1088. Refs() = 1;
  1089. }
  1090. CowString& operator=(const CowString& rhs)
  1091. {
  1092. // CowString(rhs).swap(*this);
  1093. if (--Refs() == 0)
  1094. Data().~Storage();
  1095. if (rhs.GetRefs() == (std::numeric_limits<RefCountType>::max)())
  1096. {
  1097. // must make a brand new copy
  1098. new(buf_) Storage(rhs.Data()); // non shallow
  1099. Refs() = 1;
  1100. }
  1101. else
  1102. {
  1103. new(buf_) Storage(rhs.Data(), flex_string_details::Shallow());
  1104. ++Refs();
  1105. }
  1106. BOOST_ASSERT(Data().size() > 0);
  1107. return *this;
  1108. }
  1109. ~CowString()
  1110. {
  1111. BOOST_ASSERT(Data().size() > 0);
  1112. if (--Refs() == 0)
  1113. Data().~Storage();
  1114. }
  1115. iterator begin()
  1116. {
  1117. BOOST_ASSERT(Data().size() > 0);
  1118. MakeUnique();
  1119. return Data().begin() + 1;
  1120. }
  1121. const_iterator begin() const
  1122. {
  1123. BOOST_ASSERT(Data().size() > 0);
  1124. return Data().begin() + 1;
  1125. }
  1126. iterator end()
  1127. {
  1128. MakeUnique();
  1129. return Data().end();
  1130. }
  1131. const_iterator end() const
  1132. {
  1133. return Data().end();
  1134. }
  1135. size_type size() const
  1136. {
  1137. BOOST_ASSERT(Data().size() > 0);
  1138. return Data().size() - 1;
  1139. }
  1140. size_type max_size() const
  1141. {
  1142. BOOST_ASSERT(Data().max_size() > 0);
  1143. return Data().max_size() - 1;
  1144. }
  1145. size_type capacity() const
  1146. {
  1147. BOOST_ASSERT(Data().capacity() > 0);
  1148. return Data().capacity() - 1;
  1149. }
  1150. void resize(size_type n, E c)
  1151. {
  1152. BOOST_ASSERT(Data().size() > 0);
  1153. MakeUnique();
  1154. Data().resize(n + 1, c);
  1155. }
  1156. template <class FwdIterator>
  1157. void append(FwdIterator b, FwdIterator e)
  1158. {
  1159. MakeUnique();
  1160. Data().append(b, e);
  1161. }
  1162. void reserve(size_type res_arg)
  1163. {
  1164. if (capacity() > res_arg) return;
  1165. MakeUnique();
  1166. Data().reserve(res_arg + 1);
  1167. }
  1168. void swap(CowString& rhs)
  1169. {
  1170. Data().swap(rhs.Data());
  1171. }
  1172. const E* c_str() const
  1173. {
  1174. BOOST_ASSERT(Data().size() > 0);
  1175. return Data().c_str() + 1;
  1176. }
  1177. const E* data() const
  1178. {
  1179. BOOST_ASSERT(Data().size() > 0);
  1180. return Data().data() + 1;
  1181. }
  1182. allocator_type get_allocator() const
  1183. {
  1184. return Data().get_allocator();
  1185. }
  1186. };
  1187. ////////////////////////////////////////////////////////////////////////////////
  1188. // class template flex_string
  1189. // a std::basic_string compatible implementation
  1190. // Uses a Storage policy
  1191. ////////////////////////////////////////////////////////////////////////////////
  1192. template <typename E,
  1193. class T = std::char_traits<E>,
  1194. class A = std::allocator<E>,
  1195. class Storage = AllocatorStringStorage<E, A> >
  1196. class flex_string : private Storage
  1197. {
  1198. #if defined(BOOST_WAVE_FLEXSTRING_THROW_ON_ENFORCE)
  1199. template <typename Exception>
  1200. static void Enforce(bool condition, Exception*, const char* msg)
  1201. { if (!condition) boost::throw_exception(Exception(msg)); }
  1202. #else
  1203. template <typename Exception>
  1204. static inline void Enforce(bool condition, Exception*, const char* msg)
  1205. { BOOST_ASSERT(condition && msg); }
  1206. #endif // defined(BOOST_WAVE_FLEXSTRING_THROW_ON_ENFORCE)
  1207. #ifndef NDEBUG
  1208. bool Sane() const
  1209. {
  1210. return
  1211. begin() <= end() &&
  1212. empty() == (size() == 0) &&
  1213. empty() == (begin() == end()) &&
  1214. size() <= max_size() &&
  1215. capacity() <= max_size() &&
  1216. size() <= capacity();
  1217. }
  1218. struct Invariant;
  1219. friend struct Invariant;
  1220. struct Invariant
  1221. {
  1222. Invariant(const flex_string& s) : s_(s)
  1223. {
  1224. BOOST_ASSERT(s_.Sane());
  1225. }
  1226. ~Invariant()
  1227. {
  1228. BOOST_ASSERT(s_.Sane());
  1229. }
  1230. private:
  1231. const flex_string& s_;
  1232. Invariant& operator=(const Invariant&);
  1233. };
  1234. #endif
  1235. public:
  1236. // types
  1237. typedef T traits_type;
  1238. typedef typename traits_type::char_type value_type;
  1239. typedef A allocator_type;
  1240. typedef typename boost::allocator_value_type<A>::type& reference;
  1241. typedef typename boost::allocator_value_type<A>::type const& const_reference;
  1242. typedef typename boost::allocator_pointer<A>::type pointer;
  1243. typedef typename boost::allocator_const_pointer<A>::type const_pointer;
  1244. typedef typename boost::allocator_size_type<A>::type size_type;
  1245. typedef typename Storage::iterator iterator;
  1246. typedef typename Storage::const_iterator const_iterator;
  1247. typedef boost::reverse_iterator<iterator> reverse_iterator;
  1248. typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
  1249. static const size_type npos; // = size_type(-1)
  1250. private:
  1251. static size_type Min(size_type lhs, size_type rhs)
  1252. { return lhs < rhs ? lhs : rhs; }
  1253. static void Procust(size_type& n, size_type nmax)
  1254. { if (n > nmax) n = nmax; }
  1255. public:
  1256. // 21.3.1 construct/copy/destroy
  1257. explicit flex_string(const A& a = A())
  1258. : Storage(a)
  1259. {}
  1260. flex_string(const flex_string& str)
  1261. : Storage(str)
  1262. {
  1263. }
  1264. flex_string(const flex_string& str, size_type pos,
  1265. size_type n = npos, const A& a = A())
  1266. : Storage(a)
  1267. {
  1268. Enforce(pos <= str.size(), (std::out_of_range*)0, "");
  1269. assign(str, pos, n);
  1270. }
  1271. flex_string(const value_type* s, const A& a = A())
  1272. : Storage(s, traits_type::length(s), a)
  1273. {}
  1274. flex_string(const value_type* s, size_type n, const A& a = A())
  1275. : Storage(s, n, a)
  1276. {}
  1277. flex_string(size_type n, value_type c, const A& a = A())
  1278. : Storage(n, c, a)
  1279. {}
  1280. template <class InputIterator>
  1281. flex_string(InputIterator begin, InputIterator end, const A& a = A())
  1282. : Storage(a)
  1283. {
  1284. assign(begin, end);
  1285. }
  1286. ~flex_string()
  1287. {}
  1288. flex_string& operator=(const flex_string& str)
  1289. {
  1290. if (this != &str) {
  1291. Storage& s = *this;
  1292. s = str;
  1293. }
  1294. return *this;
  1295. }
  1296. flex_string& operator=(const value_type* s)
  1297. {
  1298. assign(s);
  1299. return *this;
  1300. }
  1301. flex_string& operator=(value_type c)
  1302. {
  1303. assign(1, c);
  1304. return *this;
  1305. }
  1306. // 21.3.2 iterators:
  1307. iterator begin()
  1308. { return Storage::begin(); }
  1309. const_iterator begin() const
  1310. { return Storage::begin(); }
  1311. iterator end()
  1312. { return Storage::end(); }
  1313. const_iterator end() const
  1314. { return Storage::end(); }
  1315. reverse_iterator rbegin()
  1316. { return reverse_iterator(end()); }
  1317. const_reverse_iterator rbegin() const
  1318. { return const_reverse_iterator(end()); }
  1319. reverse_iterator rend()
  1320. { return reverse_iterator(begin()); }
  1321. const_reverse_iterator rend() const
  1322. { return const_reverse_iterator(begin()); }
  1323. #if BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK != 0
  1324. // temporary hack to make it easier to serialize flex_string's using
  1325. // the Boost.Serialization library
  1326. value_type & back() { return *(begin()+size()-1); }
  1327. value_type const& back() const { return *(begin()+size()-1); }
  1328. #endif
  1329. // 21.3.3 capacity:
  1330. size_type size() const
  1331. { return Storage::size(); }
  1332. size_type length() const
  1333. { return size(); }
  1334. size_type max_size() const
  1335. { return Storage::max_size(); }
  1336. void resize(size_type n, value_type c)
  1337. { Storage::resize(n, c); }
  1338. void resize(size_type n)
  1339. { resize(n, value_type()); }
  1340. size_type capacity() const
  1341. { return Storage::capacity(); }
  1342. void reserve(size_type res_arg = 0)
  1343. {
  1344. Enforce(res_arg <= max_size(), (std::length_error*)0, "");
  1345. Storage::reserve(res_arg);
  1346. }
  1347. void clear()
  1348. { resize(0); }
  1349. bool empty() const
  1350. { return size() == 0; }
  1351. // 21.3.4 element access:
  1352. const_reference operator[](size_type pos) const
  1353. { return *(begin() + pos); }
  1354. reference operator[](size_type pos)
  1355. { return *(begin() + pos); }
  1356. const_reference at(size_type n) const
  1357. {
  1358. Enforce(n < size(), (std::out_of_range*)0, "");
  1359. return (*this)[n];
  1360. }
  1361. reference at(size_type n)
  1362. {
  1363. Enforce(n < size(), (std::out_of_range*)0, "");
  1364. return (*this)[n];
  1365. }
  1366. // 21.3.5 modifiers:
  1367. flex_string& operator+=(const flex_string& str)
  1368. { return append(str); }
  1369. flex_string& operator+=(const value_type* s)
  1370. { return append(s); }
  1371. flex_string& operator+=(value_type c)
  1372. {
  1373. push_back(c);
  1374. return *this;
  1375. }
  1376. flex_string& append(const flex_string& str)
  1377. { return append(str, 0, npos); }
  1378. flex_string& append(const flex_string& str, const size_type pos,
  1379. size_type n)
  1380. {
  1381. const size_type sz = str.size();
  1382. Enforce(pos <= sz, (std::out_of_range*)0, "");
  1383. Procust(n, sz - pos);
  1384. return append(str.c_str() + pos, n);
  1385. }
  1386. flex_string& append(const value_type* s, const size_type n)
  1387. {
  1388. #ifndef NDEBUG
  1389. Invariant checker(*this);
  1390. #endif
  1391. if (IsAliasedRange(s, s + n))
  1392. {
  1393. const size_type offset = s - &*begin();
  1394. Storage::reserve(size() + n);
  1395. s = &*begin() + offset;
  1396. }
  1397. Storage::append(s, s+ n);
  1398. return *this;
  1399. }
  1400. flex_string& append(const value_type* s)
  1401. { return append(s, traits_type::length(s)); }
  1402. flex_string& append(size_type n, value_type c)
  1403. {
  1404. resize(size() + n, c);
  1405. return *this;
  1406. }
  1407. template<class InputIterator>
  1408. flex_string& append(InputIterator first, InputIterator last)
  1409. {
  1410. insert(end(), first, last);
  1411. return *this;
  1412. }
  1413. void push_back(value_type c)
  1414. {
  1415. const size_type cap = capacity();
  1416. if (size() == cap)
  1417. {
  1418. reserve(cap << 1u);
  1419. }
  1420. Storage::append(&c, &c + 1);
  1421. }
  1422. flex_string& assign(const flex_string& str)
  1423. {
  1424. if (&str == this) return *this;
  1425. return assign(str.data(), str.size());
  1426. }
  1427. flex_string& assign(const flex_string& str, size_type pos,
  1428. size_type n)
  1429. {
  1430. const size_type sz = str.size();
  1431. Enforce(pos <= str.size(), (std::out_of_range*)0, "");
  1432. Procust(n, sz - pos);
  1433. return assign(str.data() + pos, n);
  1434. }
  1435. flex_string& assign(const value_type* s, size_type n)
  1436. {
  1437. #ifndef NDEBUG
  1438. Invariant checker(*this);
  1439. #endif
  1440. if (size() >= n)
  1441. {
  1442. std::copy(s, s + n, begin());
  1443. resize(n);
  1444. }
  1445. else
  1446. {
  1447. const value_type *const s2 = s + size();
  1448. std::copy(s, s2, begin());
  1449. append(s2, n - size());
  1450. }
  1451. return *this;
  1452. }
  1453. flex_string& assign(const value_type* s)
  1454. { return assign(s, traits_type::length(s)); }
  1455. template <class ItOrLength, class ItOrChar>
  1456. flex_string& assign(ItOrLength first_or_n, ItOrChar last_or_c)
  1457. { return replace(begin(), end(), first_or_n, last_or_c); }
  1458. flex_string& insert(size_type pos1, const flex_string& str)
  1459. { return insert(pos1, str.data(), str.size()); }
  1460. flex_string& insert(size_type pos1, const flex_string& str,
  1461. size_type pos2, size_type n)
  1462. {
  1463. Enforce(pos2 <= str.length(), (std::out_of_range*)0, "");
  1464. Procust(n, str.length() - pos2);
  1465. return insert(pos1, str.data() + pos2, n);
  1466. }
  1467. flex_string& insert(size_type pos, const value_type* s, size_type n)
  1468. {
  1469. Enforce(pos <= length(), (std::out_of_range*)0, "");
  1470. insert(begin() + pos, s, s + n);
  1471. return *this;
  1472. }
  1473. flex_string& insert(size_type pos, const value_type* s)
  1474. { return insert(pos, s, traits_type::length(s)); }
  1475. flex_string& insert(size_type pos, size_type n, value_type c)
  1476. {
  1477. Enforce(pos <= length(), (std::out_of_range*)0, "");
  1478. insert(begin() + pos, n, c);
  1479. return *this;
  1480. }
  1481. iterator insert(iterator p, value_type c = value_type())
  1482. {
  1483. const size_type pos = p - begin();
  1484. insert(pos, &c, 1);
  1485. return begin() + pos;
  1486. }
  1487. private:
  1488. // Care must be taken when dereferencing some iterator types.
  1489. //
  1490. // Users can implement this function in their namespace if their storage
  1491. // uses a special iterator type, the function will be found through ADL.
  1492. template<class Iterator>
  1493. const typename std::iterator_traits<Iterator>::value_type*
  1494. DereferenceValidIterator(Iterator it) const
  1495. {
  1496. return &*it;
  1497. }
  1498. // Care must be taken when dereferencing a reverse iterators, hence this
  1499. // special case. This isn't in the std namespace so as not to pollute it or
  1500. // create name clashes.
  1501. template<typename Iterator>
  1502. const typename std::iterator_traits<Iterator>::value_type*
  1503. DereferenceValidIterator(std::reverse_iterator<Iterator> it) const
  1504. {
  1505. return &*--it;
  1506. }
  1507. // Determine if the range aliases the current string.
  1508. //
  1509. // This method cannot be const because calling begin/end on copy-on-write
  1510. // implementations must have side effects.
  1511. // A const version wouldn't make the string unique through this call.
  1512. template<class Iterator>
  1513. bool IsAliasedRange(Iterator beginIterator, Iterator endIterator)
  1514. {
  1515. if(!empty() && beginIterator != endIterator)
  1516. {
  1517. typedef const typename std::iterator_traits<Iterator>::value_type *
  1518. value_pointer;
  1519. value_pointer myBegin(&*begin());
  1520. value_pointer myEnd(&*begin() + size());
  1521. value_pointer rangeBegin(DereferenceValidIterator(beginIterator));
  1522. const std::less_equal<value_pointer> less_equal = std::less_equal<value_pointer>();
  1523. if(less_equal(myBegin, rangeBegin) && less_equal(rangeBegin, myEnd))
  1524. return true;
  1525. }
  1526. return false;
  1527. }
  1528. template <int i> class Selector {};
  1529. flex_string& InsertImplDiscr(iterator p,
  1530. size_type n, value_type c, Selector<1>)
  1531. {
  1532. #ifndef NDEBUG
  1533. Invariant checker(*this);
  1534. #endif
  1535. BOOST_ASSERT(begin() <= p && p <= end());
  1536. const size_type insertOffset(p - begin());
  1537. const size_type originalSize(size());
  1538. if(n < originalSize - insertOffset)
  1539. {
  1540. // The new characters fit within the original string.
  1541. // The characters that are pushed back need to be moved because
  1542. // they're aliased.
  1543. // The appended characters will all be overwritten by the move.
  1544. append(n, value_type(0));
  1545. value_type* begin(&*begin());
  1546. flex_string_details::pod_move(begin + insertOffset,
  1547. begin + originalSize, begin + insertOffset + n);
  1548. std::fill(begin + insertOffset, begin + insertOffset + n, c);
  1549. }
  1550. else
  1551. {
  1552. // The new characters exceed the original string.
  1553. // The characters that are pushed back can simply be copied since
  1554. // they aren't aliased.
  1555. // The appended characters will partly be overwritten by the copy.
  1556. append(n, c);
  1557. value_type* begin(&*begin());
  1558. flex_string_details::pod_copy(begin + insertOffset,
  1559. begin + originalSize, begin + insertOffset + n);
  1560. std::fill(begin + insertOffset, begin + originalSize, c);
  1561. }
  1562. return *this;
  1563. }
  1564. template<class InputIterator>
  1565. flex_string& InsertImplDiscr(iterator i,
  1566. InputIterator b, InputIterator e, Selector<0>)
  1567. {
  1568. InsertImpl(i, b, e,
  1569. typename std::iterator_traits<InputIterator>::iterator_category());
  1570. return *this;
  1571. }
  1572. template <class FwdIterator>
  1573. void InsertImpl(iterator i,
  1574. FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
  1575. {
  1576. if(s1 == s2)
  1577. {
  1578. // Insert an empty range.
  1579. return;
  1580. }
  1581. if(IsAliasedRange(s1, s2))
  1582. {
  1583. // The source range is contained in the current string, copy it
  1584. // and recurse.
  1585. const flex_string temporary(s1, s2);
  1586. InsertImpl(i, temporary.begin(), temporary.end(),
  1587. typename std::iterator_traits<FwdIterator>::iterator_category());
  1588. return;
  1589. }
  1590. #ifndef NDEBUG
  1591. Invariant checker(*this);
  1592. #endif
  1593. const size_type pos = i - begin();
  1594. const typename std::iterator_traits<FwdIterator>::difference_type n2 =
  1595. std::distance(s1, s2);
  1596. BOOST_ASSERT(n2 >= 0);
  1597. using namespace flex_string_details;
  1598. BOOST_ASSERT(pos <= size());
  1599. const typename std::iterator_traits<FwdIterator>::difference_type maxn2 =
  1600. capacity() - size();
  1601. if (maxn2 < n2)
  1602. {
  1603. // Reallocate the string.
  1604. BOOST_ASSERT(!IsAliasedRange(s1, s2));
  1605. reserve(size() + n2);
  1606. i = begin() + pos;
  1607. }
  1608. if (pos + n2 <= size())
  1609. {
  1610. const iterator tailBegin = end() - n2;
  1611. Storage::append(tailBegin, tailBegin + n2);
  1612. std::copy(reverse_iterator(tailBegin), reverse_iterator(i),
  1613. reverse_iterator(tailBegin + n2));
  1614. std::copy(s1, s2, i);
  1615. }
  1616. else
  1617. {
  1618. FwdIterator t = s1;
  1619. const size_type old_size = size();
  1620. std::advance(t, old_size - pos);
  1621. BOOST_ASSERT(std::distance(t, s2) >= 0);
  1622. Storage::append(t, s2);
  1623. Storage::append(data() + pos, data() + old_size);
  1624. std::copy(s1, t, i);
  1625. }
  1626. }
  1627. template <class InputIterator>
  1628. void InsertImpl(iterator insertPosition,
  1629. InputIterator inputBegin, InputIterator inputEnd,
  1630. std::input_iterator_tag)
  1631. {
  1632. flex_string temporary(begin(), insertPosition);
  1633. for (; inputBegin != inputEnd; ++inputBegin)
  1634. {
  1635. temporary.push_back(*inputBegin);
  1636. }
  1637. temporary.append(insertPosition, end());
  1638. swap(temporary);
  1639. }
  1640. public:
  1641. template <class ItOrLength, class ItOrChar>
  1642. void insert(iterator p, ItOrLength first_or_n, ItOrChar last_or_c)
  1643. {
  1644. Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
  1645. InsertImplDiscr(p, first_or_n, last_or_c, sel);
  1646. }
  1647. flex_string& erase(size_type pos = 0, size_type n = npos)
  1648. {
  1649. #ifndef NDEBUG
  1650. Invariant checker(*this);
  1651. #endif
  1652. Enforce(pos <= length(), (std::out_of_range*)0, "");
  1653. Procust(n, length() - pos);
  1654. std::copy(begin() + pos + n, end(), begin() + pos);
  1655. resize(length() - n);
  1656. return *this;
  1657. }
  1658. iterator erase(iterator position)
  1659. {
  1660. const size_type pos(position - begin());
  1661. erase(pos, 1);
  1662. return begin() + pos;
  1663. }
  1664. iterator erase(iterator first, iterator last)
  1665. {
  1666. const size_type pos(first - begin());
  1667. erase(pos, last - first);
  1668. return begin() + pos;
  1669. }
  1670. // Replaces at most n1 chars of *this, starting with pos1 with the content of str
  1671. flex_string& replace(size_type pos1, size_type n1, const flex_string& str)
  1672. { return replace(pos1, n1, str, 0, npos); }
  1673. // Replaces at most n1 chars of *this, starting with pos1,
  1674. // with at most n2 chars of str starting with pos2
  1675. flex_string& replace(size_type pos1, size_type n1, const flex_string& str,
  1676. size_type pos2, size_type n2)
  1677. {
  1678. Enforce(pos2 <= str.length(), (std::out_of_range*)0, "");
  1679. return replace(pos1, n1, str.data() + pos2,
  1680. Min(n2, str.size() - pos2));
  1681. }
  1682. // Replaces at most n1 chars of *this, starting with pos, with chars from s
  1683. flex_string& replace(size_type pos, size_type n1, const value_type* s)
  1684. { return replace(pos, n1, s, traits_type::length(s)); }
  1685. // Replaces at most n1 chars of *this, starting with pos, with n2 occurrences of c
  1686. // consolidated with
  1687. // Replaces at most n1 chars of *this, starting with pos,
  1688. // with at most n2 chars of str.
  1689. // str must have at least n2 chars.
  1690. template <class StrOrLength, class NumOrChar>
  1691. flex_string& replace(size_type pos, size_type n1,
  1692. StrOrLength s_or_n2, NumOrChar n_or_c)
  1693. {
  1694. #ifndef NDEBUG
  1695. Invariant checker(*this);
  1696. #endif
  1697. Enforce(pos <= size(), (std::out_of_range*)0, "");
  1698. Procust(n1, length() - pos);
  1699. const iterator b = begin() + pos;
  1700. return replace(b, b + n1, s_or_n2, n_or_c);
  1701. }
  1702. flex_string& replace(iterator i1, iterator i2, const flex_string& str)
  1703. { return replace(i1, i2, str.c_str(), str.length()); }
  1704. flex_string& replace(iterator i1, iterator i2, const value_type* s)
  1705. { return replace(i1, i2, s, traits_type::length(s)); }
  1706. private:
  1707. flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
  1708. const value_type* s, size_type n, Selector<2>)
  1709. {
  1710. BOOST_ASSERT(i1 <= i2);
  1711. BOOST_ASSERT(begin() <= i1 && i1 <= end());
  1712. BOOST_ASSERT(begin() <= i2 && i2 <= end());
  1713. return replace(i1, i2, s, s + n);
  1714. }
  1715. flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
  1716. size_type n2, value_type c, Selector<1>)
  1717. {
  1718. const size_type n1 = i2 - i1;
  1719. if (n1 > n2)
  1720. {
  1721. std::fill(i1, i1 + n2, c);
  1722. erase(i1 + n2, i2);
  1723. }
  1724. else
  1725. {
  1726. std::fill(i1, i2, c);
  1727. insert(i2, n2 - n1, c);
  1728. }
  1729. return *this;
  1730. }
  1731. template <class InputIterator>
  1732. flex_string& ReplaceImplDiscr(iterator i1, iterator i2,
  1733. InputIterator b, InputIterator e, Selector<0>)
  1734. {
  1735. ReplaceImpl(i1, i2, b, e,
  1736. typename std::iterator_traits<InputIterator>::iterator_category());
  1737. return *this;
  1738. }
  1739. template <class FwdIterator>
  1740. void ReplaceImpl(iterator i1, iterator i2,
  1741. FwdIterator s1, FwdIterator s2, std::forward_iterator_tag)
  1742. {
  1743. #ifndef NDEBUG
  1744. Invariant checker(*this);
  1745. #endif
  1746. const typename std::iterator_traits<iterator>::difference_type n1 =
  1747. i2 - i1;
  1748. BOOST_ASSERT(n1 >= 0);
  1749. const typename std::iterator_traits<FwdIterator>::difference_type n2 =
  1750. std::distance(s1, s2);
  1751. BOOST_ASSERT(n2 >= 0);
  1752. if (IsAliasedRange(s1, s2))
  1753. {
  1754. // Aliased replace, copy to new string.
  1755. flex_string temporary;
  1756. temporary.reserve(size() - n1 + n2);
  1757. temporary.append(begin(), i1).append(s1, s2).append(i2, end());
  1758. swap(temporary);
  1759. return;
  1760. }
  1761. if (n1 > n2)
  1762. {
  1763. // Shrinks
  1764. std::copy(s1, s2, i1);
  1765. erase(i1 + n2, i2);
  1766. }
  1767. else
  1768. {
  1769. // Grows
  1770. flex_string_details::copy_n(s1, n1, i1);
  1771. std::advance(s1, n1);
  1772. insert(i2, s1, s2);
  1773. }
  1774. }
  1775. template <class InputIterator>
  1776. void ReplaceImpl(iterator i1, iterator i2,
  1777. InputIterator b, InputIterator e, std::input_iterator_tag)
  1778. {
  1779. flex_string temp(begin(), i1);
  1780. temp.append(b, e).append(i2, end());
  1781. swap(temp);
  1782. }
  1783. public:
  1784. template <class T1, class T2>
  1785. flex_string& replace(iterator i1, iterator i2,
  1786. T1 first_or_n_or_s, T2 last_or_c_or_n)
  1787. {
  1788. const bool
  1789. num1 = std::numeric_limits<T1>::is_specialized,
  1790. num2 = std::numeric_limits<T2>::is_specialized;
  1791. return ReplaceImplDiscr(i1, i2, first_or_n_or_s, last_or_c_or_n,
  1792. Selector<num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>());
  1793. }
  1794. size_type copy(value_type* s, size_type n, size_type pos = 0) const
  1795. {
  1796. Enforce(pos <= size(), (std::out_of_range*)0, "");
  1797. n = Min(n, size() - pos);
  1798. flex_string_details::pod_copy(
  1799. &*begin() + pos,
  1800. &*begin() + pos + n,
  1801. s);
  1802. return n;
  1803. }
  1804. void swap(flex_string& rhs)
  1805. {
  1806. Storage& srhs = rhs;
  1807. this->Storage::swap(srhs);
  1808. }
  1809. // 21.3.6 string operations:
  1810. const value_type* c_str() const
  1811. { return Storage::c_str(); }
  1812. const value_type* data() const
  1813. { return Storage::data(); }
  1814. allocator_type get_allocator() const
  1815. { return Storage::get_allocator(); }
  1816. size_type find(const flex_string& str, size_type pos = 0) const
  1817. { return find(str.data(), pos, str.length()); }
  1818. size_type find (const value_type* s, size_type pos, size_type n) const
  1819. {
  1820. const size_type size_(size());
  1821. if (n + pos > size_)
  1822. return npos;
  1823. for (; pos < size_; ++pos)
  1824. {
  1825. if (traits_type::compare(&*begin() + pos, s, n) == 0)
  1826. {
  1827. return pos;
  1828. }
  1829. }
  1830. return npos;
  1831. }
  1832. size_type find (const value_type* s, size_type pos = 0) const
  1833. { return find(s, pos, traits_type::length(s)); }
  1834. size_type find (value_type c, size_type pos = 0) const
  1835. { return find(&c, pos, 1); }
  1836. size_type rfind(const flex_string& str, size_type pos = npos) const
  1837. { return rfind(str.c_str(), pos, str.length()); }
  1838. size_type rfind(const value_type* s, size_type pos, size_type n) const
  1839. {
  1840. if (n > length()) return npos;
  1841. pos = Min(pos, length() - n);
  1842. if (n == 0) return pos;
  1843. const_iterator i(begin() + pos);
  1844. for (; ; --i)
  1845. {
  1846. if (traits_type::eq(*i, *s)
  1847. && traits_type::compare(&*i, s, n) == 0)
  1848. {
  1849. return i - begin();
  1850. }
  1851. if (i == begin()) break;
  1852. }
  1853. return npos;
  1854. }
  1855. size_type rfind(const value_type* s, size_type pos = npos) const
  1856. { return rfind(s, pos, traits_type::length(s)); }
  1857. size_type rfind(value_type c, size_type pos = npos) const
  1858. { return rfind(&c, pos, 1); }
  1859. size_type find_first_of(const flex_string& str, size_type pos = 0) const
  1860. { return find_first_of(str.c_str(), pos, str.length()); }
  1861. size_type find_first_of(const value_type* s,
  1862. size_type pos, size_type n) const
  1863. {
  1864. if (pos > length() || n == 0) return npos;
  1865. const_iterator i(begin() + pos),
  1866. finish(end());
  1867. for (; i != finish; ++i)
  1868. {
  1869. if (traits_type::find(s, n, *i) != 0)
  1870. {
  1871. return i - begin();
  1872. }
  1873. }
  1874. return npos;
  1875. }
  1876. size_type find_first_of(const value_type* s, size_type pos = 0) const
  1877. { return find_first_of(s, pos, traits_type::length(s)); }
  1878. size_type find_first_of(value_type c, size_type pos = 0) const
  1879. { return find_first_of(&c, pos, 1); }
  1880. size_type find_last_of (const flex_string& str,
  1881. size_type pos = npos) const
  1882. { return find_last_of(str.c_str(), pos, str.length()); }
  1883. size_type find_last_of (const value_type* s, size_type pos,
  1884. size_type n) const
  1885. {
  1886. if (!empty() && n > 0)
  1887. {
  1888. pos = Min(pos, length() - 1);
  1889. const_iterator i(begin() + pos);
  1890. for (;; --i)
  1891. {
  1892. if (traits_type::find(s, n, *i) != 0)
  1893. {
  1894. return i - begin();
  1895. }
  1896. if (i == begin()) break;
  1897. }
  1898. }
  1899. return npos;
  1900. }
  1901. size_type find_last_of (const value_type* s,
  1902. size_type pos = npos) const
  1903. { return find_last_of(s, pos, traits_type::length(s)); }
  1904. size_type find_last_of (value_type c, size_type pos = npos) const
  1905. { return find_last_of(&c, pos, 1); }
  1906. size_type find_first_not_of(const flex_string& str,
  1907. size_type pos = 0) const
  1908. { return find_first_not_of(str.data(), pos, str.size()); }
  1909. size_type find_first_not_of(const value_type* s, size_type pos,
  1910. size_type n) const
  1911. {
  1912. if (pos < length())
  1913. {
  1914. const_iterator
  1915. i(begin() + pos),
  1916. finish(end());
  1917. for (; i != finish; ++i)
  1918. {
  1919. if (traits_type::find(s, n, *i) == 0)
  1920. {
  1921. return i - begin();
  1922. }
  1923. }
  1924. }
  1925. return npos;
  1926. }
  1927. size_type find_first_not_of(const value_type* s,
  1928. size_type pos = 0) const
  1929. { return find_first_not_of(s, pos, traits_type::length(s)); }
  1930. size_type find_first_not_of(value_type c, size_type pos = 0) const
  1931. { return find_first_not_of(&c, pos, 1); }
  1932. size_type find_last_not_of(const flex_string& str,
  1933. size_type pos = npos) const
  1934. { return find_last_not_of(str.c_str(), pos, str.length()); }
  1935. size_type find_last_not_of(const value_type* s, size_type pos,
  1936. size_type n) const
  1937. {
  1938. if (!empty())
  1939. {
  1940. pos = Min(pos, size() - 1);
  1941. const_iterator i(begin() + pos);
  1942. for (;; --i)
  1943. {
  1944. if (traits_type::find(s, n, *i) == 0)
  1945. {
  1946. return i - begin();
  1947. }
  1948. if (i == begin()) break;
  1949. }
  1950. }
  1951. return npos;
  1952. }
  1953. size_type find_last_not_of(const value_type* s,
  1954. size_type pos = npos) const
  1955. { return find_last_not_of(s, pos, traits_type::length(s)); }
  1956. size_type find_last_not_of (value_type c, size_type pos = npos) const
  1957. { return find_last_not_of(&c, pos, 1); }
  1958. flex_string substr(size_type pos = 0, size_type n = npos) const
  1959. {
  1960. Enforce(pos <= size(), (std::out_of_range*)0, "");
  1961. return flex_string(data() + pos, Min(n, size() - pos));
  1962. }
  1963. std::ptrdiff_t compare(const flex_string& str) const
  1964. {
  1965. // FIX due to Goncalo N M de Carvalho July 18, 2005
  1966. return compare(0, size(), str);
  1967. }
  1968. std::ptrdiff_t compare(size_type pos1, size_type n1,
  1969. const flex_string& str) const
  1970. { return compare(pos1, n1, str.data(), str.size()); }
  1971. // FIX to compare: added the TC
  1972. // (http://www.comeaucomputing.com/iso/lwg-defects.html number 5)
  1973. // Thanks to Caleb Epstein for the fix
  1974. std::ptrdiff_t compare(size_type pos1, size_type n1,
  1975. const value_type* s) const
  1976. {
  1977. return compare(pos1, n1, s, traits_type::length(s));
  1978. }
  1979. std::ptrdiff_t compare(size_type pos1, size_type n1,
  1980. const value_type* s, size_type n2) const
  1981. {
  1982. Enforce(pos1 <= size(), (std::out_of_range*)0, "");
  1983. Procust(n1, size() - pos1);
  1984. const int r = traits_type::compare(pos1 + data(), s, Min(n1, n2));
  1985. return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
  1986. }
  1987. std::ptrdiff_t compare(size_type pos1, size_type n1,
  1988. const flex_string& str,
  1989. size_type pos2, size_type n2) const
  1990. {
  1991. Enforce(pos2 <= str.size(), (std::out_of_range*)0, "");
  1992. return compare(pos1, n1, str.data() + pos2, Min(n2, str.size() - pos2));
  1993. }
  1994. std::ptrdiff_t compare(const value_type* s) const
  1995. {
  1996. // Could forward to compare(0, size(), s, traits_type::length(s))
  1997. // but that does two extra checks
  1998. const size_type n1(size()), n2(traits_type::length(s));
  1999. const int r = traits_type::compare(data(), s, Min(n1, n2));
  2000. return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
  2001. }
  2002. };
  2003. // non-member functions
  2004. template <typename E, class T, class A, class S>
  2005. flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
  2006. const flex_string<E, T, A, S>& rhs)
  2007. {
  2008. flex_string<E, T, A, S> result;
  2009. result.reserve(lhs.size() + rhs.size());
  2010. result.append(lhs).append(rhs);
  2011. return result;
  2012. }
  2013. template <typename E, class T, class A, class S>
  2014. flex_string<E, T, A, S> operator+(const typename flex_string<E, T, A, S>::value_type* lhs,
  2015. const flex_string<E, T, A, S>& rhs)
  2016. {
  2017. flex_string<E, T, A, S> result;
  2018. const typename flex_string<E, T, A, S>::size_type len =
  2019. flex_string<E, T, A, S>::traits_type::length(lhs);
  2020. result.reserve(len + rhs.size());
  2021. result.append(lhs, len).append(rhs);
  2022. return result;
  2023. }
  2024. template <typename E, class T, class A, class S>
  2025. flex_string<E, T, A, S> operator+(
  2026. typename flex_string<E, T, A, S>::value_type lhs,
  2027. const flex_string<E, T, A, S>& rhs)
  2028. {
  2029. flex_string<E, T, A, S> result;
  2030. result.reserve(1 + rhs.size());
  2031. result.push_back(lhs);
  2032. result.append(rhs);
  2033. return result;
  2034. }
  2035. template <typename E, class T, class A, class S>
  2036. flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
  2037. const typename flex_string<E, T, A, S>::value_type* rhs)
  2038. {
  2039. typedef typename flex_string<E, T, A, S>::size_type size_type;
  2040. typedef typename flex_string<E, T, A, S>::traits_type traits_type;
  2041. flex_string<E, T, A, S> result;
  2042. const size_type len = traits_type::length(rhs);
  2043. result.reserve(lhs.size() + len);
  2044. result.append(lhs).append(rhs, len);
  2045. return result;
  2046. }
  2047. template <typename E, class T, class A, class S>
  2048. flex_string<E, T, A, S> operator+(const flex_string<E, T, A, S>& lhs,
  2049. typename flex_string<E, T, A, S>::value_type rhs)
  2050. {
  2051. flex_string<E, T, A, S> result;
  2052. result.reserve(lhs.size() + 1);
  2053. result.append(lhs);
  2054. result.push_back(rhs);
  2055. return result;
  2056. }
  2057. template <typename E, class T, class A, class S>
  2058. inline bool operator==(const flex_string<E, T, A, S>& lhs,
  2059. const flex_string<E, T, A, S>& rhs)
  2060. { return lhs.compare(rhs) == 0; }
  2061. template <typename E, class T, class A, class S>
  2062. inline bool operator==(const typename flex_string<E, T, A, S>::value_type* lhs,
  2063. const flex_string<E, T, A, S>& rhs)
  2064. { return rhs == lhs; }
  2065. template <typename E, class T, class A, class S>
  2066. inline bool operator==(const flex_string<E, T, A, S>& lhs,
  2067. const typename flex_string<E, T, A, S>::value_type* rhs)
  2068. { return lhs.compare(rhs) == 0; }
  2069. template <typename E, class T, class A, class S>
  2070. inline bool operator!=(const flex_string<E, T, A, S>& lhs,
  2071. const flex_string<E, T, A, S>& rhs)
  2072. { return !(lhs == rhs); }
  2073. template <typename E, class T, class A, class S>
  2074. inline bool operator!=(const typename flex_string<E, T, A, S>::value_type* lhs,
  2075. const flex_string<E, T, A, S>& rhs)
  2076. { return !(lhs == rhs); }
  2077. template <typename E, class T, class A, class S>
  2078. inline bool operator!=(const flex_string<E, T, A, S>& lhs,
  2079. const typename flex_string<E, T, A, S>::value_type* rhs)
  2080. { return !(lhs == rhs); }
  2081. template <typename E, class T, class A, class S>
  2082. inline bool operator<(const flex_string<E, T, A, S>& lhs,
  2083. const flex_string<E, T, A, S>& rhs)
  2084. { return lhs.compare(rhs) < 0; }
  2085. template <typename E, class T, class A, class S>
  2086. inline bool operator<(const flex_string<E, T, A, S>& lhs,
  2087. const typename flex_string<E, T, A, S>::value_type* rhs)
  2088. { return lhs.compare(rhs) < 0; }
  2089. template <typename E, class T, class A, class S>
  2090. inline bool operator<(const typename flex_string<E, T, A, S>::value_type* lhs,
  2091. const flex_string<E, T, A, S>& rhs)
  2092. { return rhs.compare(lhs) > 0; }
  2093. template <typename E, class T, class A, class S>
  2094. inline bool operator>(const flex_string<E, T, A, S>& lhs,
  2095. const flex_string<E, T, A, S>& rhs)
  2096. { return rhs < lhs; }
  2097. template <typename E, class T, class A, class S>
  2098. inline bool operator>(const flex_string<E, T, A, S>& lhs,
  2099. const typename flex_string<E, T, A, S>::value_type* rhs)
  2100. { return rhs < lhs; }
  2101. template <typename E, class T, class A, class S>
  2102. bool operator>(const typename flex_string<E, T, A, S>::value_type* lhs,
  2103. const flex_string<E, T, A, S>& rhs)
  2104. { return rhs < lhs; }
  2105. template <typename E, class T, class A, class S>
  2106. inline bool operator<=(const flex_string<E, T, A, S>& lhs,
  2107. const flex_string<E, T, A, S>& rhs)
  2108. { return !(rhs < lhs); }
  2109. template <typename E, class T, class A, class S>
  2110. inline bool operator<=(const flex_string<E, T, A, S>& lhs,
  2111. const typename flex_string<E, T, A, S>::value_type* rhs)
  2112. { return !(rhs < lhs); }
  2113. template <typename E, class T, class A, class S>
  2114. bool operator<=(const typename flex_string<E, T, A, S>::value_type* lhs,
  2115. const flex_string<E, T, A, S>& rhs)
  2116. { return !(rhs < lhs); }
  2117. template <typename E, class T, class A, class S>
  2118. bool operator>=(const flex_string<E, T, A, S>& lhs,
  2119. const flex_string<E, T, A, S>& rhs)
  2120. { return !(lhs < rhs); }
  2121. template <typename E, class T, class A, class S>
  2122. bool operator>=(const flex_string<E, T, A, S>& lhs,
  2123. const typename flex_string<E, T, A, S>::value_type* rhs)
  2124. { return !(lhs < rhs); }
  2125. template <typename E, class T, class A, class S>
  2126. inline bool operator>=(const typename flex_string<E, T, A, S>::value_type* lhs,
  2127. const flex_string<E, T, A, S>& rhs)
  2128. { return !(lhs < rhs); }
  2129. template <typename E, class T, class A, class S>
  2130. void swap(flex_string<E, T, A, S>& lhs, flex_string<E, T, A, S>& rhs)
  2131. {
  2132. // subclause 21.3.7.8:
  2133. lhs.swap(rhs);
  2134. }
  2135. template <typename E, class T, class A, class S>
  2136. inline std::basic_istream<typename flex_string<E, T, A, S>::value_type,
  2137. typename flex_string<E, T, A, S>::traits_type>&
  2138. operator>>(
  2139. std::basic_istream<typename flex_string<E, T, A, S>::value_type,
  2140. typename flex_string<E, T, A, S>::traits_type>& is,
  2141. flex_string<E, T, A, S>& str);
  2142. template <typename E, class T, class A, class S>
  2143. std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
  2144. typename flex_string<E, T, A, S>::traits_type>&
  2145. operator<<(
  2146. std::basic_ostream<typename flex_string<E, T, A, S>::value_type,
  2147. typename flex_string<E, T, A, S>::traits_type>& os,
  2148. const flex_string<E, T, A, S>& str)
  2149. { return os << str.c_str(); }
  2150. template <typename E1, class T, class A, class S>
  2151. const typename flex_string<E1, T, A, S>::size_type
  2152. flex_string<E1, T, A, S>::npos = (typename flex_string<E1, T, A, S>::size_type)(-1);
  2153. ///////////////////////////////////////////////////////////////////////////////
  2154. } // namespace util
  2155. } // namespace wave
  2156. } // namespace boost
  2157. #if BOOST_WAVE_SERIALIZATION != 0
  2158. ///////////////////////////////////////////////////////////////////////////////
  2159. namespace boost { namespace serialization {
  2160. #if !defined(BOOST_WAVE_FLEX_STRING_SERIALIZATION_HACK)
  2161. // FIXME: This doesn't work because of the missing flex_string::operator>>()
  2162. template <typename E, class T, class A, class S>
  2163. struct implementation_level<boost::wave::util::flex_string<E, T, A, S> >
  2164. {
  2165. typedef mpl::integral_c_tag tag;
  2166. typedef mpl::int_<boost::serialization::primitive_type> type;
  2167. BOOST_STATIC_CONSTANT(
  2168. int,
  2169. value = implementation_level::type::value
  2170. );
  2171. };
  2172. #else
  2173. // We serialize flex_strings as vectors of char's for now
  2174. template<class Archive, typename E, class T, class A, class S>
  2175. inline void save(Archive & ar,
  2176. boost::wave::util::flex_string<E, T, A, S> const &t,
  2177. const unsigned int file_version)
  2178. {
  2179. boost::serialization::stl::save_collection<
  2180. Archive, wave::util::flex_string<E, T, A, S> >(ar, t);
  2181. }
  2182. template<class Archive, typename E, class T, class A, class S>
  2183. inline void load(Archive & ar, boost::wave::util::flex_string<E, T, A, S> &t,
  2184. const unsigned int file_version)
  2185. {
  2186. boost::serialization::stl::load_collection<
  2187. Archive, boost::wave::util::flex_string<E, T, A, S>,
  2188. boost::serialization::stl::archive_input_seq<
  2189. Archive, boost::wave::util::flex_string<E, T, A, S> >,
  2190. boost::serialization::stl::reserve_imp<
  2191. boost::wave::util::flex_string<E, T, A, S> >
  2192. >(ar, t);
  2193. }
  2194. // split non-intrusive serialization function member into separate
  2195. // non intrusive save/load member functions
  2196. template<class Archive, typename E, class T, class A, class S>
  2197. inline void serialize(Archive & ar, boost::wave::util::flex_string<E, T, A, S> &t,
  2198. const unsigned int file_version)
  2199. {
  2200. boost::serialization::split_free(ar, t, file_version);
  2201. }
  2202. #endif
  2203. ///////////////////////////////////////////////////////////////////////////////
  2204. }} // boost::serialization
  2205. #endif
  2206. // the suffix header occurs after all of the code
  2207. #ifdef BOOST_HAS_ABI_HEADERS
  2208. #include BOOST_ABI_SUFFIX
  2209. #endif
  2210. #endif // BOOST_FLEX_STRING_INC_