cowstringopt.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. ////////////////////////////////////////////////////////////////////////////////
  2. // flex_string
  3. // Copyright (c) 2001 by Andrei Alexandrescu
  4. // Permission to use, copy, modify, distribute and sell this software for any
  5. // purpose is hereby granted without fee, provided that the above copyright
  6. // notice appear in all copies and that both that copyright notice and this
  7. // permission notice appear in supporting documentation.
  8. // The author makes no representations about the
  9. // suitability of this software for any purpose. It is provided "as is"
  10. // without express or implied warranty.
  11. ////////////////////////////////////////////////////////////////////////////////
  12. #ifndef DAHUA_COW_STRING_OPT_INC_
  13. #define DAHUA_COW_STRING_OPT_INC_
  14. // revision 1008
  15. ////////////////////////////////////////////////////////////////////////////////
  16. // class template CowStringOpt
  17. // Implements Copy on Write over any storage
  18. ////////////////////////////////////////////////////////////////////////////////
  19. /* This is the template for a storage policy
  20. ////////////////////////////////////////////////////////////////////////////////
  21. template <typename E, class A = @>
  22. class StoragePolicy
  23. {
  24. typedef E value_type;
  25. typedef @ iterator;
  26. typedef @ const_iterator;
  27. typedef A allocator_type;
  28. typedef @ size_type;
  29. StoragePolicy(const StoragePolicy& s);
  30. StoragePolicy(const A&);
  31. StoragePolicy(const E* s, size_type len, const A&);
  32. StoragePolicy(size_type len, E c, const A&);
  33. ~StoragePolicy();
  34. iterator begin();
  35. const_iterator begin() const;
  36. iterator end();
  37. const_iterator end() const;
  38. size_type size() const;
  39. size_type max_size() const;
  40. size_type capacity() const;
  41. void reserve(size_type res_arg);
  42. void append(const E* s, size_type sz);
  43. template <class InputIterator>
  44. void append(InputIterator b, InputIterator e);
  45. void resize(size_type newSize, E fill);
  46. void swap(StoragePolicy& rhs);
  47. const E* c_str() const;
  48. const E* data() const;
  49. A get_allocator() const;
  50. };
  51. ////////////////////////////////////////////////////////////////////////////////
  52. */
  53. #include <memory>
  54. #include <algorithm>
  55. #include <functional>
  56. #include <cassert>
  57. #include <limits>
  58. #include <stdexcept>
  59. #include "flex_string_details.h"
  60. namespace Dahua {
  61. namespace Infra {
  62. ////////////////////////////////////////////////////////////////////////////////
  63. // class template CowStringOpt
  64. // Implements Copy on Write over any storage
  65. ////////////////////////////////////////////////////////////////////////////////
  66. template <class Storage, typename Align = DAHUA_DEDUCED_TYPENAME Storage::value_type*>
  67. class CowStringOpt
  68. {
  69. typedef typename Storage::value_type E;
  70. typedef typename flex_string_details::get_unsigned<E>::result RefCountType;
  71. public:
  72. typedef E value_type;
  73. typedef typename Storage::iterator iterator;
  74. typedef typename Storage::const_iterator const_iterator;
  75. typedef typename Storage::allocator_type allocator_type;
  76. typedef typename allocator_type::size_type size_type;
  77. typedef typename Storage::reference reference;
  78. private:
  79. union
  80. {
  81. mutable char buf_[sizeof(Storage)];
  82. Align align_;
  83. };
  84. Storage& Data() const
  85. { return *reinterpret_cast<Storage*>(buf_); }
  86. RefCountType GetRefs() const
  87. {
  88. const Storage& d = Data();
  89. assert(d.size() > 0);
  90. assert(*d.begin() > 0);
  91. return *d.begin();
  92. }
  93. RefCountType& Refs()
  94. {
  95. Storage& d = Data();
  96. assert(d.size() > 0);
  97. return reinterpret_cast<RefCountType&>(*d.begin());
  98. }
  99. void MakeUnique() const
  100. {
  101. assert(GetRefs() >= 1);
  102. if (GetRefs() == 1) return;
  103. union
  104. {
  105. char buf_[sizeof(Storage)];
  106. Align align_;
  107. } temp;
  108. --(*Data().begin()); // Harmut Kaiser fix:
  109. // decrement the use count of the remaining object
  110. new(buf_) Storage(
  111. *new(temp.buf_) Storage(Data()),
  112. flex_string_details::Shallow());
  113. *Data().begin() = 1;
  114. }
  115. public:
  116. CowStringOpt(const CowStringOpt& s)
  117. {
  118. if (s.GetRefs() == (std::numeric_limits<RefCountType>::max)())
  119. {
  120. // must make a brand new copy
  121. new(buf_) Storage(s.Data()); // non shallow
  122. Refs() = 1;
  123. }
  124. else
  125. {
  126. new(buf_) Storage(s.Data(), flex_string_details::Shallow());
  127. ++Refs();
  128. }
  129. assert(Data().size() > 0);
  130. }
  131. CowStringOpt(const allocator_type& a)
  132. {
  133. new(buf_) Storage(1, 1, a);
  134. }
  135. CowStringOpt(const E* s, size_type len, const allocator_type& a)
  136. {
  137. // Warning - MSVC's debugger has trouble tracing through the code below.
  138. // It seems to be a const-correctness issue
  139. //
  140. new(buf_) Storage(a);
  141. Data().reserve(len + 1);
  142. Data().resize(1, 1);
  143. Data().append(s, s + len);
  144. }
  145. CowStringOpt(size_type len, E c, const allocator_type& a)
  146. {
  147. new(buf_) Storage(len + 1, c, a);
  148. Refs() = 1;
  149. }
  150. CowStringOpt& operator=(const CowStringOpt& rhs)
  151. {
  152. CowStringOpt(rhs).swap(*this);
  153. return *this;
  154. }
  155. ~CowStringOpt()
  156. {
  157. assert(Data().size() > 0);
  158. if (--Refs() == 0) Data().~Storage();
  159. }
  160. iterator begin()
  161. {
  162. assert(Data().size() > 0);
  163. MakeUnique();
  164. return Data().begin() + 1;
  165. }
  166. const_iterator begin() const
  167. {
  168. assert(Data().size() > 0);
  169. return Data().begin() + 1;
  170. }
  171. iterator end()
  172. {
  173. MakeUnique();
  174. return Data().end();
  175. }
  176. const_iterator end() const
  177. {
  178. return Data().end();
  179. }
  180. size_type size() const
  181. {
  182. assert(Data().size() > 0);
  183. return Data().size() - 1;
  184. }
  185. size_type max_size() const
  186. {
  187. assert(Data().max_size() > 0);
  188. return Data().max_size() - 1;
  189. }
  190. size_type capacity() const
  191. {
  192. assert(Data().capacity() > 0);
  193. return Data().capacity() - 1;
  194. }
  195. void resize(size_type n, E c)
  196. {
  197. assert(Data().size() > 0);
  198. MakeUnique();
  199. Data().resize(n + 1, c);
  200. }
  201. template <class FwdIterator>
  202. void append(FwdIterator b, FwdIterator e)
  203. {
  204. MakeUnique();
  205. Data().append(b, e);
  206. }
  207. void reserve(size_type res_arg)
  208. {
  209. if (capacity() > res_arg) return;
  210. MakeUnique();
  211. Data().reserve(res_arg + 1);
  212. }
  213. void swap(CowStringOpt& rhs)
  214. {
  215. Data().swap(rhs.Data());
  216. }
  217. const E* c_str() const
  218. {
  219. assert(Data().size() > 0);
  220. return Data().c_str() + 1;
  221. }
  222. const E* data() const
  223. {
  224. assert(Data().size() > 0);
  225. return Data().data() + 1;
  226. }
  227. allocator_type get_allocator() const
  228. {
  229. return Data().get_allocator();
  230. }
  231. };
  232. } // namespace Infra
  233. } // namespace Dahua
  234. #endif // DAHUA_COW_STRING_OPT_INC_