You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2707 lines
96 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/string/simple_string.hpp (originally MSString.h, ::SynesisDev)
  3. *
  4. * Purpose: basic_simple_string class template.
  5. *
  6. * Created: 19th March 1993
  7. * Updated: 6th September 2010
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 1993-2010, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file stlsoft/string/simple_string.hpp
  40. *
  41. * \brief [C++ only] Definition of the stlsoft::basic_simple_string class
  42. * template
  43. * (\ref group__library__string "String" Library).
  44. */
  45. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING
  46. #define STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define STLSOFT_VER_STLSOFT_STRING_HPP_SIMPLE_STRING_MAJOR 4
  49. # define STLSOFT_VER_STLSOFT_STRING_HPP_SIMPLE_STRING_MINOR 1
  50. # define STLSOFT_VER_STLSOFT_STRING_HPP_SIMPLE_STRING_REVISION 6
  51. # define STLSOFT_VER_STLSOFT_STRING_HPP_SIMPLE_STRING_EDIT 248
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Compatibility
  55. */
  56. /*
  57. [Incompatibilies-start]
  58. STLSOFT_COMPILER_IS_WATCOM:
  59. [Incompatibilies-end]
  60. */
  61. /* /////////////////////////////////////////////////////////////////////////
  62. * Includes
  63. */
  64. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  65. # include <stlsoft/stlsoft.h>
  66. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  67. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS
  68. # include <stlsoft/string/char_traits.hpp>
  69. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS */
  70. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TRAITS_FWD
  71. # include <stlsoft/string/string_traits_fwd.hpp>
  72. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TRAITS_FWD */
  73. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  74. # include <stlsoft/collections/util/collections.hpp>
  75. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  76. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_BASE
  77. # include <stlsoft/memory/allocator_base.hpp> // for STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  78. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_BASE */
  79. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR
  80. # include <stlsoft/memory/allocator_selector.hpp>
  81. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR */
  82. #ifndef STLSOFT_INCL_STLSOFT_HPP_MEMORY_AUTO_BUFFER
  83. # include <stlsoft/memory/auto_buffer.hpp>
  84. #endif /* !STLSOFT_INCL_STLSOFT_HPP_MEMORY_AUTO_BUFFER */
  85. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP
  86. # include <stlsoft/util/std_swap.hpp> // for stlsoft::std_swap()
  87. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP */
  88. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_GENERATORS
  89. # include <stlsoft/util/std/iterator_generators.hpp>
  90. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_GENERATORS */
  91. #ifndef STLSOFT_INCL_STLSOFT_ALGORITHMS_HPP_BOUNDED
  92. # include <stlsoft/algorithms/bounded.hpp> // for stlsoft::copy_n()
  93. #endif /* !STLSOFT_INCL_STLSOFT_ALGORITHMS_HPP_BOUNDED */
  94. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_MINMAX
  95. # include <stlsoft/util/minmax.hpp>
  96. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_MINMAX */
  97. #ifndef STLSOFT_INCL_STLSOFT_CONVERSION_HPP_SAP_CAST
  98. # include <stlsoft/conversion/sap_cast.hpp>
  99. #endif /* !STLSOFT_INCL_STLSOFT_CONVERSION_HPP_SAP_CAST */
  100. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  101. # include <stlsoft/util/std/iterator_helper.hpp>
  102. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  103. #if defined(__BORLANDC__) && \
  104. __BORLANDC__ > 0x0580 && \
  105. defined(_DEBUG)
  106. # include <stdio.h>
  107. #endif /* compiler */
  108. #ifdef STLSOFT_UNITTEST
  109. # include <stdio.h>
  110. # include <string>
  111. #endif /* STLSOFT_UNITTEST */
  112. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  113. # include <stdexcept> // for std::out_of_range
  114. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
  115. /* /////////////////////////////////////////////////////////////////////////
  116. *
  117. */
  118. #if defined(STLSOFT_COMPILER_IS_MSVC) && \
  119. _MSC_VER < 1200
  120. # define STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE
  121. #endif /* compiler */
  122. /* /////////////////////////////////////////////////////////////////////////
  123. * Namespace
  124. */
  125. #ifndef _STLSOFT_NO_NAMESPACE
  126. namespace stlsoft
  127. {
  128. #endif /* _STLSOFT_NO_NAMESPACE */
  129. /* /////////////////////////////////////////////////////////////////////////
  130. * Classes
  131. */
  132. /** \brief Simple string class
  133. *
  134. * \param C The character type
  135. * \param T The traits type. On translators that support default template arguments this is defaulted to char_traits<C>
  136. * \param A The allocator type. On translators that support default template arguments this is defaulted to allocator_selector<C>::allocator_type
  137. *
  138. * \ingroup group__library__string
  139. */
  140. template< ss_typename_param_k C
  141. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  142. , ss_typename_param_k T = stlsoft_char_traits<C>
  143. , ss_typename_param_k A = ss_typename_type_def_k allocator_selector<C>::allocator_type
  144. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  145. , ss_typename_param_k T /* = stlsoft_char_traits<C> */
  146. , ss_typename_param_k A /* = allocator_selector<C>::allocator_type */
  147. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  148. >
  149. // class basic_simple_string
  150. class basic_simple_string
  151. : public stl_collection_tag
  152. {
  153. /// \name Member Types
  154. /// @{
  155. public:
  156. /// The value type
  157. typedef C value_type;
  158. /// The traits type
  159. typedef T traits_type;
  160. /// The allocator type
  161. typedef A allocator_type;
  162. /// The current parameterisation of the type
  163. typedef basic_simple_string<C, T, A> class_type;
  164. /// The character type
  165. typedef value_type char_type;
  166. /// The pointer type
  167. typedef value_type* pointer;
  168. /// The non-mutable (const) pointer type
  169. typedef value_type const* const_pointer;
  170. /// The reference type
  171. typedef value_type& reference;
  172. /// The non-mutable (const) reference type
  173. typedef value_type const& const_reference;
  174. /// The size type
  175. typedef ss_size_t size_type;
  176. /// The difference type
  177. typedef ss_ptrdiff_t difference_type;
  178. /// The iterator type
  179. typedef
  180. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  181. ss_typename_type_k
  182. #endif /* compiler */
  183. pointer_iterator < value_type
  184. , pointer
  185. , reference
  186. >::type iterator;
  187. /// The non-mutating (const) iterator type
  188. typedef
  189. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  190. ss_typename_type_k
  191. #endif /* compiler */
  192. pointer_iterator < value_type const
  193. , const_pointer
  194. , const_reference
  195. >::type const_iterator;
  196. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  197. /// The mutating (non-const) reverse iterator type
  198. typedef ss_typename_type_k reverse_iterator_generator < iterator
  199. , value_type
  200. , reference
  201. , pointer
  202. , difference_type
  203. >::type reverse_iterator;
  204. /// The non-mutating (const) reverse iterator type
  205. typedef ss_typename_type_k const_reverse_iterator_generator < const_iterator
  206. , value_type
  207. , const_reference
  208. , const_pointer
  209. , difference_type
  210. >::type const_reverse_iterator;
  211. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  212. private:
  213. /// The allocator type for allocating bytes
  214. ///
  215. /// \note This has to be defined here, rather than on a use-by-use basis, because
  216. /// Borland gets very upset.
  217. #ifdef STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  218. typedef ss_typename_type_k A::ss_template_qual_k rebind<ss_byte_t>::other byte_ator_type;
  219. #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  220. typedef ss_typename_type_k allocator_selector<ss_byte_t>::allocator_type byte_ator_type;
  221. #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  222. /// @}
  223. /// \name Construction
  224. /// @{
  225. public:
  226. /// Default constructor
  227. basic_simple_string();
  228. /// Copy constructor
  229. basic_simple_string(class_type const& rhs);
  230. /// Construct from the given string at the specified position
  231. basic_simple_string(class_type const& s, size_type pos);
  232. /// Construct with \c cch characters from the given string at the specified position
  233. basic_simple_string(class_type const& s, size_type pos, size_type cch);
  234. /// Construct from the given character string
  235. basic_simple_string(char_type const* s); // Not, not explicit. Sigh
  236. /// Construct with \c cch characters from the given character string
  237. basic_simple_string(char_type const* s, size_type cch);
  238. /// Construct with \c cch characters each set to \c ch
  239. basic_simple_string(size_type cch, char_type ch);
  240. /// Construct from the range [first:last)
  241. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  242. basic_simple_string(char_type const* first, char_type const* last);
  243. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  244. template <ss_typename_param_k II>
  245. basic_simple_string(II first, II last)
  246. : m_buffer(NULL)
  247. {
  248. assign(first, last);
  249. }
  250. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  251. /// Destructor
  252. ~basic_simple_string() stlsoft_throw_0();
  253. /// @}
  254. /// \name Assignment
  255. /// @{
  256. public:
  257. /// Assigns from the given character string
  258. class_type& assign(char_type const* s);
  259. /// Assigns with \c cch characters from the given character string
  260. class_type& assign(char_type const* s, size_type cch);
  261. /// Assigns with \c cch characters from the given character string at the specified position
  262. class_type& assign(class_type const& str, size_type pos, size_type cch);
  263. /// Assigns from the given string
  264. class_type& assign(class_type const& str);
  265. /// Assigns \c cch characters with the value \c ch
  266. class_type& assign(size_type cch, char_type ch);
  267. /// Assigns from the range [first:last)
  268. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  269. class_type& assign(const_iterator first, const_iterator last);
  270. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  271. template <ss_typename_param_k II>
  272. class_type& assign(II first, II last)
  273. {
  274. # if ( defined(STLSOFT_COMPILER_IS_GCC) && \
  275. __GNUC__ < 3) || \
  276. ( defined(STLSOFT_COMPILER_IS_BORLAND) && \
  277. defined(STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_BORLAND))
  278. typedef ss_typename_type_k std::iterator_traits<II> traits_t;
  279. return assign_(first, last, traits_t::iterator_category());
  280. # elif defined(STLSOFT_COMPILER_IS_MWERKS) || \
  281. defined(STLSOFT_COMPILER_IS_DMC)
  282. return assign_(first, last, stlsoft_iterator_query_category_ptr(II, first));
  283. # else /* ? compiler */
  284. return assign_(first, last, stlsoft_iterator_query_category(II, first));
  285. # endif /* compiler */
  286. }
  287. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  288. /// Copy assignment operator
  289. class_type const& operator =(class_type const& rhs);
  290. /// Assignment operator
  291. class_type const& operator =(char_type const* s);
  292. /// Assignment operator
  293. class_type const& operator =(char_type ch);
  294. /// @}
  295. /// \name Appending
  296. /// @{
  297. public:
  298. /// Appends the given character string
  299. class_type& append(char_type const* s);
  300. /// Appends \c cch characters from the given character string
  301. class_type& append(char_type const* s, size_type cch);
  302. /// Assigns \c cch characters from the given character string at the specified position
  303. class_type& append(class_type const& str, size_type pos, size_type cch);
  304. /// Appends the given string
  305. class_type& append(class_type const& str);
  306. /// Appends \c cch characters with the value \c ch
  307. class_type& append(size_type cch, char_type ch);
  308. /// Appends the range [first:last)
  309. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  310. class_type& append(const_iterator first, const_iterator last);
  311. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  312. template <ss_typename_param_k II>
  313. class_type& append(II first, II last)
  314. {
  315. # if ( defined(STLSOFT_COMPILER_IS_GCC) && \
  316. __GNUC__ < 3) || \
  317. ( defined(STLSOFT_COMPILER_IS_BORLAND) && \
  318. defined(STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_BORLAND))
  319. typedef ss_typename_type_k std::iterator_traits<II> traits_t;
  320. return append_(first, last, traits_t::iterator_category());
  321. # elif defined(STLSOFT_COMPILER_IS_MWERKS) || \
  322. defined(STLSOFT_COMPILER_IS_DMC)
  323. return append_(first, last, stlsoft_iterator_query_category_ptr(II, first));
  324. # else /* ? compiler */
  325. return append_(first, last, stlsoft_iterator_query_category(II, first));
  326. # endif /* compiler */
  327. }
  328. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  329. /// Concatenation operator
  330. class_type& operator +=(char_type ch);
  331. /// Concatenation operator
  332. class_type& operator +=(char_type const* s);
  333. /// Concatenation operator
  334. class_type& operator +=(class_type const& rhs);
  335. /// Appends a single character
  336. void push_back(char_type ch);
  337. /// @}
  338. /// \name Operations
  339. /// @{
  340. public:
  341. /// Reserves at least cch characters
  342. void reserve(size_type cch);
  343. /// Swaps the contents between \c this and \c other
  344. void swap(class_type& other);
  345. /// Resizes the string
  346. ///
  347. /// \param cch The new size of the string
  348. /// \param ch The value with which to initialise additional items if the string is expanded
  349. void resize(size_type cch, value_type ch = value_type());
  350. /// Empties the string
  351. void clear();
  352. /// @}
  353. /// \name Attributes
  354. /// @{
  355. public:
  356. /// The number of elements in the string
  357. size_type size() const;
  358. /// The maximum number of elements that can be stored in the string
  359. size_type max_size() const;
  360. /// The number of elements in the string
  361. size_type length() const;
  362. /// The storage currently allocated by the string
  363. size_type capacity() const;
  364. /// Indicates whether the string is empty
  365. ss_bool_t empty() const;
  366. /// @}
  367. /// \name Comparison
  368. /// @{
  369. public:
  370. #if 0
  371. /// Compares \c this with the given string
  372. ss_sint_t equal(size_type pos, size_type cch, value_type const* s, size_type cchRhs) const;
  373. /// Compares \c this with the given string
  374. ss_sint_t equal(size_type pos, size_type cch, value_type const* s) const;
  375. /// Compares \c this with the given string
  376. ss_sint_t equal(value_type const* s) const;
  377. /// Compares \c this with the given string
  378. ss_sint_t equal(size_type pos, size_type cch, class_type const& rhs, size_type posRhs, size_type cchRhs) const;
  379. /// Compares \c this with the given string
  380. ss_sint_t equal(size_type pos, size_type cch, class_type const& rhs) const;
  381. /// Compares \c this with the given string
  382. ss_sint_t equal(class_type const& rhs) const;
  383. #endif /* 0 */
  384. /// Compares \c this with the given string
  385. ss_sint_t compare(size_type pos, size_type cch, value_type const* s, size_type cchRhs) const;
  386. /// Compares \c this with the given string
  387. ss_sint_t compare(size_type pos, size_type cch, value_type const* s) const;
  388. /// Compares \c this with the given string
  389. ss_sint_t compare(value_type const* s) const;
  390. /// Compares \c this with the given string
  391. ss_sint_t compare(size_type pos, size_type cch, class_type const& rhs, size_type posRhs, size_type cchRhs) const;
  392. /// Compares \c this with the given string
  393. ss_sint_t compare(size_type pos, size_type cch, class_type const& rhs) const;
  394. /// Compares \c this with the given string
  395. ss_sint_t compare(class_type const& rhs) const;
  396. /// @}
  397. /// \name Accessors
  398. /// @{
  399. public:
  400. /// Returns mutable reference at the given index
  401. reference operator [](size_type index);
  402. /// Returns non-mutable (const) reference at the given index
  403. const_reference operator [](size_type index) const;
  404. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  405. /// Returns mutable (non-const) reference at the given index
  406. ///
  407. /// \note Throws std::out_of_range if index >= size()
  408. reference at(size_type index);
  409. /// Returns non-mutable (const) reference at the given index
  410. ///
  411. /// \note Throws std::out_of_range if index >= size()
  412. const_reference at(size_type index) const;
  413. /// Returns a string of maximum length cch, from the position pos
  414. class_type substr(size_type pos, size_type cch) const;
  415. class_type substr(size_type pos) const;
  416. class_type substr() const;
  417. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
  418. /// Returns null-terminated non-mutable (const) pointer to string data
  419. value_type const* c_str() const;
  420. /// Returns non-mutable (const) pointer to string data
  421. value_type const* data() const;
  422. /// Returns the first character in the string
  423. ///
  424. /// \note It is us to the user to ensure that the string is not empty
  425. reference front();
  426. /// Returns the last character in the string
  427. ///
  428. /// \note It is us to the user to ensure that the string is not empty
  429. reference back();
  430. /// Returns the first character in the string
  431. ///
  432. /// \note It is us to the user to ensure that the string is not empty
  433. const_reference front() const;
  434. /// Returns the last character in the string
  435. ///
  436. /// \note It is us to the user to ensure that the string is not empty
  437. const_reference back() const;
  438. /// Copies elements into the given destination
  439. size_type copy(value_type* dest, size_type cch, size_type pos = 0) const;
  440. /// @}
  441. /// \name Iteration
  442. /// @{
  443. public:
  444. /// Begins the iteration
  445. ///
  446. /// \return A non-mutable (const) iterator representing the start of the sequence
  447. #ifdef STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE
  448. const_iterator begin() const
  449. {
  450. return const_cast<class_type*>(this)->begin_();
  451. }
  452. #else /* ? STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
  453. const_iterator begin() const;
  454. #endif /* STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
  455. /// Ends the iteration
  456. ///
  457. /// \return A non-mutable (const) iterator representing the end of the sequence
  458. #ifdef STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE
  459. const_iterator end() const
  460. {
  461. return const_cast<class_type*>(this)->end_();
  462. }
  463. #else /* ? STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
  464. const_iterator end() const;
  465. #endif /* STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
  466. /// Begins the iteration
  467. ///
  468. /// \return An iterator representing the start of the sequence
  469. iterator begin();
  470. /// Ends the iteration
  471. ///
  472. /// \return An iterator representing the end of the sequence
  473. iterator end();
  474. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  475. /// Begins the reverse iteration
  476. ///
  477. /// \return A non-mutable (const) iterator representing the start of the reverse sequence
  478. const_reverse_iterator rbegin() const;
  479. /// Ends the reverse iteration
  480. ///
  481. /// \return A non-mutable (const) iterator representing the end of the reverse sequence
  482. const_reverse_iterator rend() const;
  483. /// Begins the reverse iteration
  484. ///
  485. /// \return An iterator representing the start of the reverse sequence
  486. reverse_iterator rbegin();
  487. /// Ends the reverse iteration
  488. ///
  489. /// \return An iterator representing the end of the reverse sequence
  490. reverse_iterator rend();
  491. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  492. /// @}
  493. /// \name Implementation
  494. /// @{
  495. private:
  496. enum { alloc_quantum = 31 }; // Must be (2^n - 1)
  497. struct string_buffer
  498. {
  499. size_type capacity; // The number of char places in the buffer
  500. size_type length; // The number of chars in the string (<= capacity)
  501. char_type contents[1]; // The first element in the array
  502. };
  503. typedef auto_buffer_old<char_type
  504. , allocator_type
  505. > buffer_type_;
  506. #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
  507. typedef string_buffer* member_pointer;
  508. typedef string_buffer const* member_const_pointer;
  509. #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  510. typedef char_type* member_pointer;
  511. typedef char_type const* member_const_pointer;
  512. #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  513. // Conversion between member pointer and character pointer
  514. static char_type* char_pointer_from_member_pointer_(member_pointer );
  515. // Conversion between pointer and buffer
  516. static string_buffer* string_buffer_from_member_pointer_(member_pointer );
  517. static string_buffer const* string_buffer_from_member_pointer_(member_const_pointer );
  518. // Conversion between buffer and pointer
  519. static member_pointer member_pointer_from_string_buffer_(string_buffer*);
  520. // Creating buffer
  521. static member_pointer alloc_buffer_(char_type const* s, size_type capacity, size_type length);
  522. static member_pointer alloc_buffer_(char_type const* s, size_type cch);
  523. static member_pointer alloc_buffer_(char_type const* s);
  524. // Copying a buffer
  525. static member_pointer copy_buffer_(member_pointer );
  526. // Destroying buffer
  527. static void destroy_buffer_(string_buffer*);
  528. static void destroy_buffer_(char_type*);
  529. // Iteration
  530. pointer begin_();
  531. pointer end_();
  532. // Invariance
  533. ss_bool_t is_valid() const;
  534. // Empty string
  535. static char_type const* empty_string_();
  536. // Comparison
  537. static ss_sint_t compare_(char_type const* lhs, size_type lhs_len, char_type const* rhs, size_type rhs_len);
  538. // Assignment
  539. #if defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  540. template <ss_typename_param_k II>
  541. # if defined(STLSOFT_COMPILER_IS_MWERKS) || \
  542. defined(STLSOFT_COMPILER_IS_DMC)
  543. // There seems to be a bug in CodeWarrior that makes it have a cow with iterator tags by value, so we just use a ptr
  544. class_type& assign_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag) const*)
  545. # else /* ? compiler */
  546. class_type& assign_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag))
  547. # endif /* compiler */
  548. {
  549. stlsoft_ns_qual_std(copy)(first, last, stlsoft_ns_qual_std(back_inserter)(*this));
  550. STLSOFT_ASSERT(is_valid());
  551. return *this;
  552. }
  553. template <ss_typename_param_k II>
  554. # if defined(STLSOFT_COMPILER_IS_MWERKS) || \
  555. defined(STLSOFT_COMPILER_IS_DMC)
  556. // There seems to be a bug in CodeWarrior that makes it have a cow with iterator tags by value, so we just use a ptr
  557. class_type& assign_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag) const*)
  558. # else /* ? compiler */
  559. class_type& assign_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag))
  560. # endif /* compiler */
  561. {
  562. const ss_size_t n = static_cast<ss_size_t>(stlsoft_ns_qual_std(distance)(first, last));
  563. buffer_type_ buffer(n);
  564. copy_n(first, buffer.size(), &buffer[0]);
  565. assign(buffer.data(), buffer.size());
  566. STLSOFT_ASSERT(is_valid());
  567. return *this;
  568. }
  569. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  570. // Appending
  571. #if defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  572. template <ss_typename_param_k II>
  573. # if defined(STLSOFT_COMPILER_IS_MWERKS) || \
  574. defined(STLSOFT_COMPILER_IS_DMC)
  575. class_type& append_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag) const*)
  576. # else /* ? compiler */
  577. class_type& append_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag))
  578. # endif /* compiler */
  579. {
  580. stlsoft_ns_qual_std(copy)(first, last, stlsoft_ns_qual_std(back_inserter)(*this));
  581. STLSOFT_ASSERT(is_valid());
  582. return *this;
  583. }
  584. template <ss_typename_param_k II>
  585. # if defined(STLSOFT_COMPILER_IS_MWERKS) || \
  586. defined(STLSOFT_COMPILER_IS_DMC)
  587. class_type& append_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag) const*)
  588. # else /* ? compiler */
  589. class_type& append_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag))
  590. # endif /* compiler */
  591. {
  592. buffer_type_ buffer(static_cast<ss_size_t>(stlsoft_ns_qual_std(distance)(first, last)));
  593. std_copy(first, last, &buffer[0]);
  594. append(buffer.data(), buffer.size());
  595. STLSOFT_ASSERT(is_valid());
  596. return *this;
  597. }
  598. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  599. /// @}
  600. /// \name Members
  601. /// @{
  602. private:
  603. member_pointer m_buffer;
  604. /// @}
  605. };
  606. /* /////////////////////////////////////////////////////////////////////////
  607. * Typedefs
  608. */
  609. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  610. typedef basic_simple_string<ss_char_a_t> simple_string;
  611. typedef basic_simple_string<ss_char_w_t> simple_wstring;
  612. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  613. typedef basic_simple_string<ss_char_a_t
  614. , stlsoft_char_traits<ss_char_a_t>
  615. , allocator_selector<ss_char_a_t>::allocator_type
  616. > simple_string;
  617. typedef basic_simple_string<ss_char_w_t
  618. , stlsoft_char_traits<ss_char_w_t>
  619. , allocator_selector<ss_char_w_t>::allocator_type
  620. > simple_wstring;
  621. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  622. /* /////////////////////////////////////////////////////////////////////////
  623. * Traits
  624. */
  625. /** Specialisation for stlsoft::basic_simple_string<>
  626. */
  627. # ifdef STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
  628. template<
  629. ss_typename_param_k C
  630. , ss_typename_param_k T
  631. , ss_typename_param_k A
  632. >
  633. struct string_traits<
  634. basic_simple_string<C, T, A>
  635. >
  636. {
  637. // NOTE: Originally, what is string_type_ was defined as value_type, but
  638. // Borland objects to value_type::value_type.
  639. typedef basic_simple_string<C> string_type_;
  640. typedef ss_typename_type_k string_type_::value_type char_type;
  641. typedef ss_typename_type_k string_type_::size_type size_type;
  642. typedef char_type const const_char_type;
  643. typedef string_type_ string_type;
  644. typedef string_type_ value_type;
  645. typedef ss_typename_type_k string_type::pointer pointer;
  646. typedef ss_typename_type_k string_type::const_pointer const_pointer;
  647. typedef ss_typename_type_k string_type::iterator iterator;
  648. typedef ss_typename_type_k string_type::const_iterator const_iterator;
  649. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  650. typedef ss_typename_type_k string_type::reverse_iterator reverse_iterator;
  651. typedef ss_typename_type_k string_type::const_reverse_iterator const_reverse_iterator;
  652. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  653. enum
  654. {
  655. is_pointer = false
  656. , is_pointer_to_const = false
  657. , char_type_size = sizeof(char_type)
  658. };
  659. static string_type empty_string()
  660. {
  661. return string_type();
  662. }
  663. static string_type construct(string_type const& src, size_type pos, size_type len)
  664. {
  665. return string_type(src, pos, len);
  666. }
  667. # ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  668. template <ss_typename_param_k I>
  669. static string_type &assign_inplace(string_type &str, I first, I last)
  670. # else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  671. static string_type &assign_inplace(string_type &str, const_iterator first, const_iterator last)
  672. # endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  673. {
  674. // simple_string can assign in-place
  675. return str.assign(first, last);
  676. }
  677. };
  678. # else /* ? STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
  679. STLSOFT_TEMPLATE_SPECIALISATION
  680. struct string_traits<simple_string>
  681. {
  682. typedef basic_simple_string<ss_char_a_t> value_type;
  683. typedef value_type::value_type char_type;
  684. typedef value_type::size_type size_type;
  685. typedef char_type const const_char_type;
  686. typedef value_type string_type;
  687. typedef string_type::pointer pointer;
  688. typedef string_type::const_pointer const_pointer;
  689. typedef string_type::iterator iterator;
  690. typedef string_type::const_iterator const_iterator;
  691. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  692. typedef string_type::reverse_iterator reverse_iterator;
  693. typedef string_type::const_reverse_iterator const_reverse_iterator;
  694. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  695. enum
  696. {
  697. is_pointer = false
  698. , is_pointer_to_const = false
  699. , char_type_size = sizeof(char_type)
  700. };
  701. static string_type empty_string()
  702. {
  703. return string_type();
  704. }
  705. static string_type construct(string_type const& src, size_type pos, size_type len)
  706. {
  707. return string_type(src, pos, len);
  708. }
  709. # ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  710. template <ss_typename_param_k I>
  711. static string_type &assign_inplace(string_type &str, I first, I last)
  712. # else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  713. static string_type &assign_inplace(string_type &str, const_iterator first, const_iterator last)
  714. # endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  715. {
  716. // simple_string can assign in-place
  717. return str.assign(first, last);
  718. }
  719. };
  720. STLSOFT_TEMPLATE_SPECIALISATION
  721. struct string_traits<simple_wstring>
  722. {
  723. typedef basic_simple_string<ss_char_w_t> value_type;
  724. typedef value_type::value_type char_type;
  725. typedef value_type::size_type size_type;
  726. typedef char_type const const_char_type;
  727. typedef value_type string_type;
  728. typedef string_type::pointer pointer;
  729. typedef string_type::const_pointer const_pointer;
  730. typedef string_type::iterator iterator;
  731. typedef string_type::const_iterator const_iterator;
  732. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  733. typedef string_type::reverse_iterator reverse_iterator;
  734. typedef string_type::const_reverse_iterator const_reverse_iterator;
  735. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  736. enum
  737. {
  738. is_pointer = false
  739. , is_pointer_to_const = false
  740. , char_type_size = sizeof(char_type)
  741. };
  742. static string_type empty_string()
  743. {
  744. return string_type();
  745. }
  746. static string_type construct(string_type const& src, size_type pos, size_type len)
  747. {
  748. return string_type(src, pos, len);
  749. }
  750. # ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  751. template <ss_typename_param_k I>
  752. static string_type &assign_inplace(string_type &str, I first, I last)
  753. # else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  754. static string_type &assign_inplace(string_type &str, const_iterator first, const_iterator last)
  755. # endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  756. {
  757. // simple_string can assign in-place
  758. return str.assign(first, last);
  759. }
  760. };
  761. # endif /* STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
  762. /* /////////////////////////////////////////////////////////////////////////
  763. * Operators
  764. */
  765. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  766. // operator ==
  767. template< ss_typename_param_k C
  768. , ss_typename_param_k T
  769. , ss_typename_param_k A
  770. >
  771. inline ss_bool_t operator ==(basic_simple_string<C, T, A> const& lhs, basic_simple_string<C, T, A> const& rhs)
  772. {
  773. return 0 == lhs.compare(rhs);
  774. }
  775. template< ss_typename_param_k C
  776. , ss_typename_param_k T
  777. , ss_typename_param_k A
  778. >
  779. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  780. inline ss_bool_t operator ==(basic_simple_string<C, T, A> const& lhs, ss_typename_type_k basic_simple_string<C, T, A>::char_type const* rhs)
  781. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  782. inline ss_bool_t operator ==(basic_simple_string<C, T, A> const& lhs, C const* rhs)
  783. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  784. {
  785. return 0 == lhs.compare(rhs);
  786. }
  787. template< ss_typename_param_k C
  788. , ss_typename_param_k T
  789. , ss_typename_param_k A
  790. >
  791. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  792. inline ss_bool_t operator ==(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* lhs, basic_simple_string<C, T, A> const& rhs)
  793. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  794. inline ss_bool_t operator ==(C *lhs, basic_simple_string<C, T, A> const& rhs)
  795. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  796. {
  797. return 0 == rhs.compare(lhs);
  798. }
  799. // operator !=
  800. template< ss_typename_param_k C
  801. , ss_typename_param_k T
  802. , ss_typename_param_k A
  803. >
  804. inline ss_bool_t operator !=(basic_simple_string<C, T, A> const& lhs, basic_simple_string<C, T, A> const& rhs)
  805. {
  806. return 0 != lhs.compare(rhs);
  807. }
  808. template< ss_typename_param_k C
  809. , ss_typename_param_k T
  810. , ss_typename_param_k A
  811. >
  812. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  813. inline ss_bool_t operator !=(basic_simple_string<C, T, A> const& lhs, ss_typename_type_k basic_simple_string<C, T, A>::char_type const* rhs)
  814. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  815. inline ss_bool_t operator !=(basic_simple_string<C, T, A> const& lhs, C const* rhs)
  816. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  817. {
  818. return 0 != lhs.compare(rhs);
  819. }
  820. template< ss_typename_param_k C
  821. , ss_typename_param_k T
  822. , ss_typename_param_k A
  823. >
  824. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  825. inline ss_bool_t operator !=(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* lhs, basic_simple_string<C, T, A> const& rhs)
  826. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  827. inline ss_bool_t operator !=(C const* lhs, basic_simple_string<C, T, A> const& rhs)
  828. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  829. {
  830. return 0 != rhs.compare(lhs);
  831. }
  832. // operator <
  833. template< ss_typename_param_k C
  834. , ss_typename_param_k T
  835. , ss_typename_param_k A
  836. >
  837. inline ss_bool_t operator <(basic_simple_string<C, T, A> const& lhs, basic_simple_string<C, T, A> const& rhs)
  838. {
  839. return lhs.compare(rhs) < 0;
  840. }
  841. template< ss_typename_param_k C
  842. , ss_typename_param_k T
  843. , ss_typename_param_k A
  844. >
  845. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  846. inline ss_bool_t operator <(basic_simple_string<C, T, A> const& lhs, ss_typename_type_k basic_simple_string<C, T, A>::char_type const* rhs)
  847. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  848. inline ss_bool_t operator <(basic_simple_string<C, T, A> const& lhs, C const* rhs)
  849. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  850. {
  851. return lhs.compare(rhs) < 0;
  852. }
  853. template< ss_typename_param_k C
  854. , ss_typename_param_k T
  855. , ss_typename_param_k A
  856. >
  857. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  858. inline ss_bool_t operator <(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* lhs, basic_simple_string<C, T, A> const& rhs)
  859. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  860. inline ss_bool_t operator <(C const* lhs, basic_simple_string<C, T, A> const& rhs)
  861. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  862. {
  863. return rhs.compare(lhs) > 0;
  864. }
  865. // operator <=
  866. template< ss_typename_param_k C
  867. , ss_typename_param_k T
  868. , ss_typename_param_k A
  869. >
  870. inline ss_bool_t operator <=(basic_simple_string<C, T, A> const& lhs, basic_simple_string<C, T, A> const& rhs)
  871. {
  872. return lhs.compare(rhs) <= 0;
  873. }
  874. template< ss_typename_param_k C
  875. , ss_typename_param_k T
  876. , ss_typename_param_k A
  877. >
  878. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  879. inline ss_bool_t operator <=(basic_simple_string<C, T, A> const& lhs, ss_typename_type_k basic_simple_string<C, T, A>::char_type const* rhs)
  880. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  881. inline ss_bool_t operator <=(basic_simple_string<C, T, A> const& lhs, C const* rhs)
  882. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  883. {
  884. return lhs.compare(rhs) <= 0;
  885. }
  886. template< ss_typename_param_k C
  887. , ss_typename_param_k T
  888. , ss_typename_param_k A
  889. >
  890. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  891. inline ss_bool_t operator <=(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* lhs, basic_simple_string<C, T, A> const& rhs)
  892. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  893. inline ss_bool_t operator <=(C const* lhs, basic_simple_string<C, T, A> const& rhs)
  894. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  895. {
  896. return rhs.compare(lhs) >= 0;
  897. }
  898. // operator >
  899. template< ss_typename_param_k C
  900. , ss_typename_param_k T
  901. , ss_typename_param_k A
  902. >
  903. inline ss_bool_t operator >(basic_simple_string<C, T, A> const& lhs, basic_simple_string<C, T, A> const& rhs)
  904. {
  905. return lhs.compare(rhs) > 0;
  906. }
  907. template< ss_typename_param_k C
  908. , ss_typename_param_k T
  909. , ss_typename_param_k A
  910. >
  911. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  912. inline ss_bool_t operator >(basic_simple_string<C, T, A> const& lhs, ss_typename_type_k basic_simple_string<C, T, A>::char_type const* rhs)
  913. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  914. inline ss_bool_t operator >(basic_simple_string<C, T, A> const& lhs, C const* rhs)
  915. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  916. {
  917. return lhs.compare(rhs) > 0;
  918. }
  919. template< ss_typename_param_k C
  920. , ss_typename_param_k T
  921. , ss_typename_param_k A
  922. >
  923. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  924. inline ss_bool_t operator >(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* lhs, basic_simple_string<C, T, A> const& rhs)
  925. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  926. inline ss_bool_t operator >(C const* lhs, basic_simple_string<C, T, A> const& rhs)
  927. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  928. {
  929. return rhs.compare(lhs) < 0;
  930. }
  931. // operator >=
  932. template< ss_typename_param_k C
  933. , ss_typename_param_k T
  934. , ss_typename_param_k A
  935. >
  936. inline ss_bool_t operator >=(basic_simple_string<C, T, A> const& lhs, basic_simple_string<C, T, A> const& rhs)
  937. {
  938. return lhs.compare(rhs) >= 0;
  939. }
  940. template< ss_typename_param_k C
  941. , ss_typename_param_k T
  942. , ss_typename_param_k A
  943. >
  944. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  945. inline ss_bool_t operator >=(basic_simple_string<C, T, A> const& lhs, ss_typename_type_k basic_simple_string<C, T, A>::char_type const* rhs)
  946. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  947. inline ss_bool_t operator >=(basic_simple_string<C, T, A> const& lhs, C const* rhs)
  948. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  949. {
  950. return lhs.compare(rhs) >= 0;
  951. }
  952. template< ss_typename_param_k C
  953. , ss_typename_param_k T
  954. , ss_typename_param_k A
  955. >
  956. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  957. inline ss_bool_t operator >=(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* lhs, basic_simple_string<C, T, A> const& rhs)
  958. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  959. inline ss_bool_t operator >=(C const* lhs, basic_simple_string<C, T, A> const& rhs)
  960. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  961. {
  962. return rhs.compare(lhs) <= 0;
  963. }
  964. // operator +
  965. template< ss_typename_param_k C
  966. , ss_typename_param_k T
  967. , ss_typename_param_k A
  968. >
  969. inline basic_simple_string<C, T, A> operator +(basic_simple_string<C, T, A> const& lhs, basic_simple_string<C, T, A> const& rhs)
  970. {
  971. return basic_simple_string<C, T, A>(lhs) += rhs;
  972. }
  973. template< ss_typename_param_k C
  974. , ss_typename_param_k T
  975. , ss_typename_param_k A
  976. >
  977. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  978. inline basic_simple_string<C, T, A> operator +(basic_simple_string<C, T, A> const& lhs, ss_typename_type_k basic_simple_string<C, T, A>::char_type const* rhs)
  979. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  980. inline basic_simple_string<C, T, A> operator +(basic_simple_string<C, T, A> const& lhs, C const* rhs)
  981. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  982. {
  983. return basic_simple_string<C, T, A>(lhs) += rhs;
  984. }
  985. template< ss_typename_param_k C
  986. , ss_typename_param_k T
  987. , ss_typename_param_k A
  988. >
  989. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  990. inline basic_simple_string<C, T, A> operator +(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* lhs, basic_simple_string<C, T, A> const& rhs)
  991. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  992. inline basic_simple_string<C, T, A> operator +(C const* lhs, basic_simple_string<C, T, A> const& rhs)
  993. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  994. {
  995. return basic_simple_string<C, T, A>(lhs) += rhs;
  996. }
  997. template< ss_typename_param_k C
  998. , ss_typename_param_k T
  999. , ss_typename_param_k A
  1000. >
  1001. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  1002. inline basic_simple_string<C, T, A> operator +(basic_simple_string<C, T, A> const& lhs, ss_typename_type_k basic_simple_string<C, T, A>::char_type rhs)
  1003. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  1004. inline basic_simple_string<C, T, A> operator +(basic_simple_string<C, T, A> const& lhs, C rhs)
  1005. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  1006. {
  1007. return basic_simple_string<C, T, A>(lhs) += rhs;
  1008. }
  1009. template< ss_typename_param_k C
  1010. , ss_typename_param_k T
  1011. , ss_typename_param_k A
  1012. >
  1013. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  1014. inline basic_simple_string<C, T, A> operator +(ss_typename_type_k basic_simple_string<C, T, A>::char_type lhs, basic_simple_string<C, T, A> const& rhs)
  1015. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  1016. inline basic_simple_string<C, T, A> operator +(C lhs, basic_simple_string<C, T, A> const& rhs)
  1017. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  1018. {
  1019. return basic_simple_string<C, T, A>(1, lhs) += rhs;
  1020. }
  1021. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  1022. /* /////////////////////////////////////////////////////////////////////////
  1023. * Shims
  1024. */
  1025. /* c_str_ptr_null */
  1026. /** \brief Returns the corresponding C-string pointer of \c s, or a null pointer
  1027. *
  1028. * \ingroup group__library__string
  1029. */
  1030. template< ss_typename_param_k C
  1031. , ss_typename_param_k T
  1032. , ss_typename_param_k A
  1033. >
  1034. inline C const* c_str_ptr_null(basic_simple_string<C, T, A> const& s)
  1035. {
  1036. return (0 == s.length()) ? NULL : s.c_str();
  1037. }
  1038. /** \brief char variant of c_str_ptr_null for basic_simple_string specialisations
  1039. *
  1040. * \ingroup group__library__string
  1041. */
  1042. template<ss_typename_param_k T, ss_typename_param_k A>
  1043. inline ss_char_a_t const* c_str_ptr_null_a(basic_simple_string<ss_char_a_t, T, A> const& s)
  1044. {
  1045. return c_str_ptr_null(s);
  1046. }
  1047. /** \brief wchar_t variant of c_str_ptr_null for basic_simple_string specialisations
  1048. *
  1049. * \ingroup group__library__string
  1050. */
  1051. template<ss_typename_param_k T, ss_typename_param_k A>
  1052. inline ss_char_w_t const* c_str_ptr_null_w(basic_simple_string<ss_char_w_t, T, A> const& s)
  1053. {
  1054. return c_str_ptr_null(s);
  1055. }
  1056. /* c_str_ptr */
  1057. /** \brief Returns the corresponding C-string pointer of \c s
  1058. *
  1059. * \ingroup group__library__string
  1060. */
  1061. template< ss_typename_param_k C
  1062. , ss_typename_param_k T
  1063. , ss_typename_param_k A
  1064. >
  1065. inline C const* c_str_ptr(basic_simple_string<C, T, A> const& s)
  1066. {
  1067. return s.c_str();
  1068. }
  1069. /** \brief char variant of c_str_ptr for basic_simple_string specialisations
  1070. *
  1071. * \ingroup group__library__string
  1072. */
  1073. template<ss_typename_param_k T, ss_typename_param_k A>
  1074. inline ss_char_a_t const* c_str_ptr_a(basic_simple_string<ss_char_a_t, T, A> const& s)
  1075. {
  1076. return c_str_ptr(s);
  1077. }
  1078. /** \brief wchar_t variant of c_str_ptr for basic_simple_string specialisations
  1079. *
  1080. * \ingroup group__library__string
  1081. */
  1082. template<ss_typename_param_k T, ss_typename_param_k A>
  1083. inline ss_char_w_t const* c_str_ptr_w(basic_simple_string<ss_char_w_t, T, A> const& s)
  1084. {
  1085. return c_str_ptr(s);
  1086. }
  1087. /* c_str_data */
  1088. /** \brief Returns the corresponding C-string pointer of \c s
  1089. *
  1090. * \ingroup group__library__string
  1091. */
  1092. template< ss_typename_param_k C
  1093. , ss_typename_param_k T
  1094. , ss_typename_param_k A
  1095. >
  1096. inline C const* c_str_data(basic_simple_string<C, T, A> const& s)
  1097. {
  1098. return s.data();
  1099. }
  1100. /** \brief char variant of c_str_data for basic_simple_string specialisations
  1101. *
  1102. * \ingroup group__library__string
  1103. */
  1104. template<ss_typename_param_k T, ss_typename_param_k A>
  1105. inline ss_char_a_t const* c_str_data_a(basic_simple_string<ss_char_a_t, T, A> const& s)
  1106. {
  1107. return c_str_data(s);
  1108. }
  1109. /** \brief wchar_t variant of c_str_data for basic_simple_string specialisations
  1110. *
  1111. * \ingroup group__library__string
  1112. */
  1113. template<ss_typename_param_k T, ss_typename_param_k A>
  1114. inline ss_char_w_t const* c_str_data_w(basic_simple_string<ss_char_w_t, T, A> const& s)
  1115. {
  1116. return c_str_data(s);
  1117. }
  1118. /* c_str_ptr_len */
  1119. /** \brief Returns the length (in characters) of \c s, <b><i>not</i></b> including the null-terminating character
  1120. *
  1121. * \ingroup group__library__string
  1122. */
  1123. template< ss_typename_param_k C
  1124. , ss_typename_param_k T
  1125. , ss_typename_param_k A
  1126. >
  1127. inline ss_size_t c_str_len(basic_simple_string<C, T, A> const& s)
  1128. {
  1129. return s.length();
  1130. }
  1131. /** \brief char variant of c_str_len for basic_simple_string specialisations
  1132. *
  1133. * \ingroup group__library__string
  1134. */
  1135. template<ss_typename_param_k T, ss_typename_param_k A>
  1136. inline ss_size_t c_str_len_a(basic_simple_string<ss_char_a_t, T, A> const& s)
  1137. {
  1138. return c_str_len(s);
  1139. }
  1140. /** \brief wchar_t variant of c_str_len for basic_simple_string specialisations
  1141. *
  1142. * \ingroup group__library__string
  1143. */
  1144. template<ss_typename_param_k T, ss_typename_param_k A>
  1145. inline ss_size_t c_str_len_w(basic_simple_string<ss_char_w_t, T, A> const& s)
  1146. {
  1147. return c_str_len(s);
  1148. }
  1149. /* operator << */
  1150. template< ss_typename_param_k S
  1151. , ss_typename_param_k C
  1152. , ss_typename_param_k T
  1153. , ss_typename_param_k A
  1154. >
  1155. inline S& operator <<(S& s, basic_simple_string<C, T, A> const& str)
  1156. {
  1157. // This cast is needed because some silly old compilers treat it as a
  1158. // void*.
  1159. s << static_cast<C const*>(str.c_str());
  1160. return s;
  1161. }
  1162. /* /////////////////////////////////////////////////////////////////////////
  1163. * swapping
  1164. */
  1165. template< ss_typename_param_k C
  1166. , ss_typename_param_k T
  1167. , ss_typename_param_k A
  1168. >
  1169. inline void swap(basic_simple_string<C, T, A>& lhs, basic_simple_string<C, T, A>& rhs)
  1170. {
  1171. lhs.swap(rhs);
  1172. }
  1173. /* /////////////////////////////////////////////////////////////////////////
  1174. * Unit-testing
  1175. */
  1176. #ifdef STLSOFT_UNITTEST
  1177. # include "./unittest/simple_string_unittest_.h"
  1178. #endif /* STLSOFT_UNITTEST */
  1179. /* /////////////////////////////////////////////////////////////////////////
  1180. * Implementation
  1181. */
  1182. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  1183. // Implementation
  1184. template< ss_typename_param_k C
  1185. , ss_typename_param_k T
  1186. , ss_typename_param_k A
  1187. >
  1188. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::char_type* basic_simple_string<C, T, A>::char_pointer_from_member_pointer_(ss_typename_type_k basic_simple_string<C, T, A>::member_pointer m)
  1189. {
  1190. #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
  1191. return (NULL == m) ? NULL : m->contents;
  1192. #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  1193. return m;
  1194. #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  1195. }
  1196. template< ss_typename_param_k C
  1197. , ss_typename_param_k T
  1198. , ss_typename_param_k A
  1199. >
  1200. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::string_buffer* basic_simple_string<C, T, A>::string_buffer_from_member_pointer_(ss_typename_type_k basic_simple_string<C, T, A>::member_pointer m)
  1201. {
  1202. STLSOFT_MESSAGE_ASSERT("Attempt to convert a null string_buffer in basic_simple_string", NULL != m);
  1203. #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
  1204. return m;
  1205. #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  1206. return reinterpret_cast<string_buffer*>(const_cast<void*>(ptr_byte_offset(m, -static_cast<ss_ptrdiff_t>(STLSOFT_RAW_OFFSETOF(string_buffer, contents)))));
  1207. #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  1208. }
  1209. template< ss_typename_param_k C
  1210. , ss_typename_param_k T
  1211. , ss_typename_param_k A
  1212. >
  1213. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::string_buffer const* basic_simple_string<C, T, A>::string_buffer_from_member_pointer_(ss_typename_type_k basic_simple_string<C, T, A>::member_const_pointer m)
  1214. {
  1215. STLSOFT_MESSAGE_ASSERT("Attempt to convert a null string_buffer in basic_simple_string", NULL != m);
  1216. #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
  1217. return m;
  1218. #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  1219. return reinterpret_cast<string_buffer const*>(ptr_byte_offset(m, -static_cast<ss_ptrdiff_t>(STLSOFT_RAW_OFFSETOF(string_buffer, contents))));
  1220. #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  1221. }
  1222. template< ss_typename_param_k C
  1223. , ss_typename_param_k T
  1224. , ss_typename_param_k A
  1225. >
  1226. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::member_pointer basic_simple_string<C, T, A>::member_pointer_from_string_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::string_buffer* b)
  1227. {
  1228. #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
  1229. return b;
  1230. #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  1231. return b->contents;
  1232. #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
  1233. }
  1234. template< ss_typename_param_k C
  1235. , ss_typename_param_k T
  1236. , ss_typename_param_k A
  1237. >
  1238. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::member_pointer basic_simple_string<C, T, A>::alloc_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s
  1239. , ss_typename_type_k basic_simple_string<C, T, A>::size_type capacity
  1240. , ss_typename_type_k basic_simple_string<C, T, A>::size_type length)
  1241. {
  1242. // Pre-conditions
  1243. STLSOFT_ASSERT(length <= capacity);
  1244. STLSOFT_ASSERT(length >= traits_type::length_max_null(s, length));
  1245. const ss_size_t members = (STLSOFT_RAW_OFFSETOF(string_buffer, contents) + (sizeof(char_type) - 1)) / sizeof(char_type);
  1246. capacity += 1; // For null terminator
  1247. capacity += members; // Include the internal members.
  1248. capacity = (alloc_quantum + capacity) & ~alloc_quantum; // Round up to (alloc_quantum + 1)
  1249. byte_ator_type byte_ator;
  1250. void* raw_buffer = byte_ator.allocate(capacity * sizeof(char_type), NULL);
  1251. string_buffer* buffer = sap_cast<string_buffer*>(raw_buffer);
  1252. if(NULL != buffer)
  1253. {
  1254. if(NULL == s)
  1255. {
  1256. STLSOFT_ASSERT(0 == length);
  1257. buffer->contents[0] = traits_type::to_char_type(0);
  1258. }
  1259. else
  1260. {
  1261. traits_type::copy(buffer->contents, s, length);
  1262. buffer->contents[length] = traits_type::to_char_type(0);
  1263. }
  1264. buffer->length = length;
  1265. buffer->capacity = capacity - members;
  1266. return member_pointer_from_string_buffer_(buffer);
  1267. }
  1268. return NULL;
  1269. }
  1270. template< ss_typename_param_k C
  1271. , ss_typename_param_k T
  1272. , ss_typename_param_k A
  1273. >
  1274. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::member_pointer basic_simple_string<C, T, A>::alloc_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s
  1275. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch)
  1276. {
  1277. size_type length = traits_type::length_max_null(s, cch);
  1278. size_type capacity = cch;
  1279. if(cch < length)
  1280. {
  1281. length = cch;
  1282. }
  1283. return alloc_buffer_(s, capacity, length);
  1284. }
  1285. template< ss_typename_param_k C
  1286. , ss_typename_param_k T
  1287. , ss_typename_param_k A
  1288. >
  1289. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::member_pointer basic_simple_string<C, T, A>::alloc_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s)
  1290. {
  1291. member_pointer res;
  1292. if(NULL == s)
  1293. {
  1294. res = NULL;
  1295. }
  1296. else
  1297. {
  1298. size_type len = traits_type::length(s);
  1299. res = alloc_buffer_(s, len, len);
  1300. }
  1301. return res;
  1302. }
  1303. template< ss_typename_param_k C
  1304. , ss_typename_param_k T
  1305. , ss_typename_param_k A
  1306. >
  1307. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::member_pointer basic_simple_string<C, T, A>::copy_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::member_pointer m)
  1308. {
  1309. if(NULL != m)
  1310. {
  1311. byte_ator_type byte_ator;
  1312. string_buffer* buffer = string_buffer_from_member_pointer_(m);
  1313. ss_size_t cb = buffer->capacity * sizeof(char_type) + STLSOFT_RAW_OFFSETOF(string_buffer, contents);
  1314. void* raw_buffer = byte_ator.allocate(cb, NULL);
  1315. string_buffer* new_buffer = sap_cast<string_buffer*>(raw_buffer);
  1316. if(NULL != new_buffer)
  1317. {
  1318. memcpy(new_buffer, buffer, cb);
  1319. return member_pointer_from_string_buffer_(new_buffer);
  1320. }
  1321. }
  1322. return NULL;
  1323. }
  1324. template< ss_typename_param_k C
  1325. , ss_typename_param_k T
  1326. , ss_typename_param_k A
  1327. >
  1328. inline /* static */ void basic_simple_string<C, T, A>::destroy_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::string_buffer* buffer)
  1329. {
  1330. byte_ator_type byte_ator;
  1331. byte_ator.deallocate(sap_cast<ss_byte_t*>(buffer), 0);
  1332. }
  1333. template< ss_typename_param_k C
  1334. , ss_typename_param_k T
  1335. , ss_typename_param_k A
  1336. >
  1337. inline /* static */ void basic_simple_string<C, T, A>::destroy_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::char_type* s)
  1338. {
  1339. destroy_buffer_(string_buffer_from_member_pointer_(s));
  1340. }
  1341. template< ss_typename_param_k C
  1342. , ss_typename_param_k T
  1343. , ss_typename_param_k A
  1344. >
  1345. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::pointer basic_simple_string<C, T, A>::begin_()
  1346. {
  1347. return char_pointer_from_member_pointer_(m_buffer);
  1348. }
  1349. template< ss_typename_param_k C
  1350. , ss_typename_param_k T
  1351. , ss_typename_param_k A
  1352. >
  1353. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::pointer basic_simple_string<C, T, A>::end_()
  1354. {
  1355. return begin_() + length();
  1356. }
  1357. template< ss_typename_param_k C
  1358. , ss_typename_param_k T
  1359. , ss_typename_param_k A
  1360. >
  1361. inline ss_bool_t basic_simple_string<C, T, A>::is_valid() const
  1362. {
  1363. if(NULL != m_buffer)
  1364. {
  1365. string_buffer const* buffer = string_buffer_from_member_pointer_(m_buffer);
  1366. if(buffer->capacity < 1)
  1367. {
  1368. #if defined(STLSOFT_UNITTEST) || \
  1369. defined(STLSOFT_PRINT_CONTRACT_VIOLATION_DETAILS)
  1370. fprintf(stderr, "%08x: capacity (%u) < 1\n", static_cast<unsigned>(reinterpret_cast<ss_size_t>(this)), static_cast<unsigned>(buffer->capacity));
  1371. #endif /* STLSOFT_UNITTEST */
  1372. return false;
  1373. }
  1374. else if(buffer->capacity < buffer->length)
  1375. {
  1376. #if defined(STLSOFT_UNITTEST) || \
  1377. defined(STLSOFT_PRINT_CONTRACT_VIOLATION_DETAILS)
  1378. fprintf(stderr, "%08x: capacity (%u) < length (%u, %08x)\n", static_cast<unsigned>(reinterpret_cast<ss_size_t>(this)), static_cast<unsigned>(buffer->capacity), static_cast<unsigned>(buffer->length), static_cast<unsigned>(buffer->length));
  1379. #endif /* STLSOFT_UNITTEST */
  1380. return false;
  1381. }
  1382. else
  1383. {
  1384. size_type len = traits_type::length(buffer->contents);
  1385. if(buffer->length < len)
  1386. {
  1387. #if defined(STLSOFT_UNITTEST) || \
  1388. defined(STLSOFT_PRINT_CONTRACT_VIOLATION_DETAILS)
  1389. fprintf(stderr, "%08x: length (%u) < length() (%u, %08x)\n", static_cast<unsigned>(reinterpret_cast<ss_size_t>(this)), static_cast<unsigned>(buffer->length), static_cast<unsigned>(len), static_cast<unsigned>(len));
  1390. #endif /* STLSOFT_UNITTEST */
  1391. return false;
  1392. }
  1393. }
  1394. }
  1395. return true;
  1396. }
  1397. template< ss_typename_param_k C
  1398. , ss_typename_param_k T
  1399. , ss_typename_param_k A
  1400. >
  1401. inline /* static */ ss_typename_type_ret_k basic_simple_string<C, T, A>::char_type const* basic_simple_string<C, T, A>::empty_string_()
  1402. {
  1403. // This character array is initialised to 0, which conveniently happens to
  1404. // be the empty string, by the module/application load, so it is
  1405. // guaranteed to be valid, and there are no threading/race conditions
  1406. static char_type s_empty[1];
  1407. STLSOFT_ASSERT(s_empty[0] == '\0'); // Paranoid check
  1408. return s_empty;
  1409. }
  1410. // Construction
  1411. template< ss_typename_param_k C
  1412. , ss_typename_param_k T
  1413. , ss_typename_param_k A
  1414. >
  1415. inline basic_simple_string<C, T, A>::basic_simple_string()
  1416. : m_buffer(NULL)
  1417. {
  1418. STLSOFT_ASSERT(is_valid());
  1419. }
  1420. template< ss_typename_param_k C
  1421. , ss_typename_param_k T
  1422. , ss_typename_param_k A
  1423. >
  1424. inline basic_simple_string<C, T, A>::basic_simple_string(class_type const& rhs)
  1425. : m_buffer(copy_buffer_(rhs.m_buffer))
  1426. {
  1427. STLSOFT_ASSERT(rhs.is_valid());
  1428. STLSOFT_ASSERT(is_valid());
  1429. }
  1430. template< ss_typename_param_k C
  1431. , ss_typename_param_k T
  1432. , ss_typename_param_k A
  1433. >
  1434. inline basic_simple_string<C, T, A>::basic_simple_string( ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs
  1435. , ss_typename_type_k basic_simple_string<C, T, A>::size_type pos)
  1436. : m_buffer(alloc_buffer_(&rhs[pos]))
  1437. {
  1438. STLSOFT_ASSERT(is_valid());
  1439. }
  1440. template< ss_typename_param_k C
  1441. , ss_typename_param_k T
  1442. , ss_typename_param_k A
  1443. >
  1444. inline basic_simple_string<C, T, A>::basic_simple_string( ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs
  1445. , ss_typename_type_k basic_simple_string<C, T, A>::size_type pos
  1446. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch)
  1447. : m_buffer(alloc_buffer_(&rhs[pos], cch, minimum(cch, rhs.length() - pos)))
  1448. {
  1449. STLSOFT_ASSERT(is_valid());
  1450. }
  1451. template< ss_typename_param_k C
  1452. , ss_typename_param_k T
  1453. , ss_typename_param_k A
  1454. >
  1455. inline basic_simple_string<C, T, A>::basic_simple_string(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s) // No, not explicit. Sigh
  1456. : m_buffer(alloc_buffer_(s))
  1457. {
  1458. STLSOFT_ASSERT(is_valid());
  1459. }
  1460. template< ss_typename_param_k C
  1461. , ss_typename_param_k T
  1462. , ss_typename_param_k A
  1463. >
  1464. inline basic_simple_string<C, T, A>::basic_simple_string( ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s
  1465. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch)
  1466. : m_buffer(alloc_buffer_(s, cch))
  1467. {
  1468. STLSOFT_ASSERT(is_valid());
  1469. }
  1470. template< ss_typename_param_k C
  1471. , ss_typename_param_k T
  1472. , ss_typename_param_k A
  1473. >
  1474. inline basic_simple_string<C, T, A>::basic_simple_string( ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  1475. , ss_typename_type_k basic_simple_string<C, T, A>::char_type ch)
  1476. : m_buffer(NULL)
  1477. {
  1478. STLSOFT_ASSERT(is_valid());
  1479. assign(cch, ch);
  1480. }
  1481. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  1482. template< ss_typename_param_k C
  1483. , ss_typename_param_k T
  1484. , ss_typename_param_k A
  1485. >
  1486. inline basic_simple_string<C, T, A>::basic_simple_string( ss_typename_type_k basic_simple_string<C, T, A>::char_type const* first
  1487. , ss_typename_type_k basic_simple_string<C, T, A>::char_type const* last)
  1488. : m_buffer(alloc_buffer_(first, last - first))
  1489. {
  1490. STLSOFT_ASSERT(is_valid());
  1491. }
  1492. #endif /* !STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  1493. template< ss_typename_param_k C
  1494. , ss_typename_param_k T
  1495. , ss_typename_param_k A
  1496. >
  1497. inline basic_simple_string<C, T, A>::~basic_simple_string() stlsoft_throw_0()
  1498. {
  1499. #if defined(__BORLANDC__) && \
  1500. __BORLANDC__ > 0x0580 && \
  1501. defined(_DEBUG)
  1502. /* NOTE: this quite unbelievable call sequence is required with Borland
  1503. * 6.1 to prevent the class invariant assertion from firing. It first
  1504. * manifested in Pantheios' fe.WindowRegistry back-end unit-test.
  1505. */
  1506. if(!is_valid())
  1507. {
  1508. this->size();
  1509. }
  1510. else
  1511. {
  1512. this->size();
  1513. fprintf(stdin, "%.*s", int(this->size()), this->data());
  1514. }
  1515. #endif /* compiler */
  1516. STLSOFT_ASSERT(is_valid());
  1517. if(NULL != m_buffer)
  1518. {
  1519. destroy_buffer_(m_buffer);
  1520. }
  1521. }
  1522. // Comparison
  1523. template< ss_typename_param_k C
  1524. , ss_typename_param_k T
  1525. , ss_typename_param_k A
  1526. >
  1527. inline /* static */ ss_sint_t basic_simple_string<C, T, A>::compare_( ss_typename_type_k basic_simple_string<C, T, A>::value_type const* lhs
  1528. , ss_typename_type_k basic_simple_string<C, T, A>::size_type lhs_len
  1529. , ss_typename_type_k basic_simple_string<C, T, A>::value_type const* rhs
  1530. , ss_typename_type_k basic_simple_string<C, T, A>::size_type rhs_len)
  1531. {
  1532. size_type cmp_len = (lhs_len < rhs_len) ? lhs_len : rhs_len;
  1533. ss_int_t result = traits_type::compare(lhs, rhs, cmp_len);
  1534. if(0 == result)
  1535. {
  1536. result = static_cast<ss_int_t>(lhs_len) - static_cast<ss_int_t>(rhs_len);
  1537. }
  1538. return result;
  1539. }
  1540. template< ss_typename_param_k C
  1541. , ss_typename_param_k T
  1542. , ss_typename_param_k A
  1543. >
  1544. inline ss_sint_t basic_simple_string<C, T, A>::compare( ss_typename_type_k basic_simple_string<C, T, A>::size_type pos
  1545. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  1546. , ss_typename_type_k basic_simple_string<C, T, A>::value_type const* rhs
  1547. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cchRhs) const
  1548. {
  1549. size_type lhs_len = length();
  1550. if(!(pos < lhs_len))
  1551. {
  1552. pos = lhs_len;
  1553. }
  1554. else
  1555. {
  1556. lhs_len -= pos;
  1557. }
  1558. if(cch < lhs_len)
  1559. {
  1560. lhs_len = cch;
  1561. }
  1562. size_type rhs_len = (NULL == rhs) ? 0 : traits_type::length(rhs);
  1563. if(cchRhs < rhs_len)
  1564. {
  1565. rhs_len = cchRhs;
  1566. }
  1567. return compare_(char_pointer_from_member_pointer_(m_buffer) + pos, lhs_len, rhs, rhs_len);
  1568. }
  1569. template< ss_typename_param_k C
  1570. , ss_typename_param_k T
  1571. , ss_typename_param_k A
  1572. >
  1573. inline ss_sint_t basic_simple_string<C, T, A>::compare( ss_typename_type_k basic_simple_string<C, T, A>::size_type pos
  1574. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  1575. , ss_typename_type_k basic_simple_string<C, T, A>::value_type const* rhs) const
  1576. {
  1577. size_type lhs_len = length();
  1578. if(!(pos < lhs_len))
  1579. {
  1580. pos = lhs_len;
  1581. }
  1582. else
  1583. {
  1584. lhs_len -= pos;
  1585. }
  1586. if(cch < lhs_len)
  1587. {
  1588. lhs_len = cch;
  1589. }
  1590. size_type rhs_len = (NULL == rhs) ? 0 : traits_type::length(rhs);
  1591. return compare_(char_pointer_from_member_pointer_(m_buffer) + pos, lhs_len, rhs, rhs_len);
  1592. }
  1593. template< ss_typename_param_k C
  1594. , ss_typename_param_k T
  1595. , ss_typename_param_k A
  1596. >
  1597. inline ss_sint_t basic_simple_string<C, T, A>::compare(ss_typename_type_k basic_simple_string<C, T, A>::value_type const* rhs) const
  1598. {
  1599. size_type lhs_len = length();
  1600. size_type rhs_len = (NULL == rhs) ? 0 : traits_type::length(rhs);
  1601. return compare_(char_pointer_from_member_pointer_(m_buffer), lhs_len, rhs, rhs_len);
  1602. }
  1603. template< ss_typename_param_k C
  1604. , ss_typename_param_k T
  1605. , ss_typename_param_k A
  1606. >
  1607. inline ss_sint_t basic_simple_string<C, T, A>::compare( ss_typename_type_k basic_simple_string<C, T, A>::size_type pos
  1608. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  1609. , ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs
  1610. , ss_typename_type_k basic_simple_string<C, T, A>::size_type posRhs
  1611. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cchRhs) const
  1612. {
  1613. size_type lhs_len = length();
  1614. if(pos == lhs_len)
  1615. {
  1616. lhs_len = 0u;
  1617. }
  1618. else if(pos + cch > lhs_len)
  1619. {
  1620. lhs_len -= pos;
  1621. }
  1622. if(cch < lhs_len)
  1623. {
  1624. lhs_len = cch;
  1625. }
  1626. size_type rhs_len = rhs.length();
  1627. if(posRhs == rhs_len)
  1628. {
  1629. rhs_len = 0u;
  1630. }
  1631. else if(posRhs + cchRhs > rhs_len)
  1632. {
  1633. rhs_len -= posRhs;
  1634. }
  1635. if(cchRhs < rhs_len)
  1636. {
  1637. rhs_len = cchRhs;
  1638. }
  1639. return compare_(char_pointer_from_member_pointer_(m_buffer) + pos, lhs_len, char_pointer_from_member_pointer_(rhs.m_buffer) + posRhs, rhs_len);
  1640. }
  1641. template< ss_typename_param_k C
  1642. , ss_typename_param_k T
  1643. , ss_typename_param_k A
  1644. >
  1645. inline ss_sint_t basic_simple_string<C, T, A>::compare( ss_typename_type_k basic_simple_string<C, T, A>::size_type pos
  1646. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  1647. , ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs) const
  1648. {
  1649. size_type lhs_len = length();
  1650. if(!(pos < lhs_len))
  1651. {
  1652. pos = lhs_len;
  1653. }
  1654. else
  1655. {
  1656. lhs_len -= pos;
  1657. }
  1658. if(cch < lhs_len)
  1659. {
  1660. lhs_len = cch;
  1661. }
  1662. size_type rhs_len = rhs.length();
  1663. return compare_(char_pointer_from_member_pointer_(m_buffer) + pos, lhs_len, char_pointer_from_member_pointer_(rhs.m_buffer), rhs_len);
  1664. }
  1665. template< ss_typename_param_k C
  1666. , ss_typename_param_k T
  1667. , ss_typename_param_k A
  1668. >
  1669. inline ss_sint_t basic_simple_string<C, T, A>::compare(ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs) const
  1670. {
  1671. size_type lhs_len = length();
  1672. size_type rhs_len = rhs.length();
  1673. return compare_(char_pointer_from_member_pointer_(m_buffer), lhs_len, char_pointer_from_member_pointer_(rhs.m_buffer), rhs_len);
  1674. }
  1675. // Accessors
  1676. template< ss_typename_param_k C
  1677. , ss_typename_param_k T
  1678. , ss_typename_param_k A
  1679. >
  1680. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::reference basic_simple_string<C, T, A>::operator [](ss_typename_type_k basic_simple_string<C, T, A>::size_type index)
  1681. {
  1682. STLSOFT_MESSAGE_ASSERT("index access out of range in simple_string", index < length());
  1683. STLSOFT_ASSERT(is_valid());
  1684. return char_pointer_from_member_pointer_(m_buffer)[index];
  1685. }
  1686. template< ss_typename_param_k C
  1687. , ss_typename_param_k T
  1688. , ss_typename_param_k A
  1689. >
  1690. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::const_reference basic_simple_string<C, T, A>::operator [](ss_typename_type_k basic_simple_string<C, T, A>::size_type index) const
  1691. {
  1692. STLSOFT_MESSAGE_ASSERT("index access out of range in simple_string", index < length() + 1); // Valid to return (const) reference to nul-terminator
  1693. STLSOFT_ASSERT(is_valid());
  1694. return char_pointer_from_member_pointer_(m_buffer)[index];
  1695. }
  1696. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1697. template< ss_typename_param_k C
  1698. , ss_typename_param_k T
  1699. , ss_typename_param_k A
  1700. >
  1701. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::reference basic_simple_string<C, T, A>::at(ss_typename_type_k basic_simple_string<C, T, A>::size_type index)
  1702. {
  1703. STLSOFT_ASSERT(is_valid());
  1704. if(index >= size())
  1705. {
  1706. STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("index out of range"));
  1707. }
  1708. STLSOFT_ASSERT(is_valid());
  1709. return char_pointer_from_member_pointer_(m_buffer)[index];
  1710. }
  1711. template< ss_typename_param_k C
  1712. , ss_typename_param_k T
  1713. , ss_typename_param_k A
  1714. >
  1715. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::const_reference basic_simple_string<C, T, A>::at(ss_typename_type_k basic_simple_string<C, T, A>::size_type index) const
  1716. {
  1717. STLSOFT_ASSERT(is_valid());
  1718. if(index >= size())
  1719. {
  1720. STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("index out of range"));
  1721. }
  1722. STLSOFT_ASSERT(is_valid());
  1723. return char_pointer_from_member_pointer_(m_buffer)[index];
  1724. }
  1725. template< ss_typename_param_k C
  1726. , ss_typename_param_k T
  1727. , ss_typename_param_k A
  1728. >
  1729. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type basic_simple_string<C, T, A>::substr(ss_typename_type_k basic_simple_string<C, T, A>::size_type pos, ss_typename_type_k basic_simple_string<C, T, A>::size_type cch) const
  1730. {
  1731. STLSOFT_ASSERT(is_valid());
  1732. if(pos > size())
  1733. {
  1734. STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("index out of range"));
  1735. }
  1736. STLSOFT_ASSERT(is_valid());
  1737. if(cch > (this->length() - pos))
  1738. {
  1739. cch = this->length() - pos;
  1740. }
  1741. return class_type(this->data() + pos, cch);
  1742. }
  1743. template< ss_typename_param_k C
  1744. , ss_typename_param_k T
  1745. , ss_typename_param_k A
  1746. >
  1747. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type basic_simple_string<C, T, A>::substr(ss_typename_type_k basic_simple_string<C, T, A>::size_type pos) const
  1748. {
  1749. STLSOFT_ASSERT(is_valid());
  1750. if(pos > size())
  1751. {
  1752. STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("index out of range"));
  1753. }
  1754. STLSOFT_ASSERT(is_valid());
  1755. return class_type(this->data() + pos, this->length() - pos);
  1756. }
  1757. template< ss_typename_param_k C
  1758. , ss_typename_param_k T
  1759. , ss_typename_param_k A
  1760. >
  1761. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type basic_simple_string<C, T, A>::substr() const
  1762. {
  1763. return *this;
  1764. }
  1765. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
  1766. template< ss_typename_param_k C
  1767. , ss_typename_param_k T
  1768. , ss_typename_param_k A
  1769. >
  1770. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::value_type const* basic_simple_string<C, T, A>::c_str() const
  1771. {
  1772. return (NULL == m_buffer) ? empty_string_() : char_pointer_from_member_pointer_(m_buffer);
  1773. }
  1774. template< ss_typename_param_k C
  1775. , ss_typename_param_k T
  1776. , ss_typename_param_k A
  1777. >
  1778. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::value_type const* basic_simple_string<C, T, A>::data() const
  1779. {
  1780. return (NULL == m_buffer) ? empty_string_() : char_pointer_from_member_pointer_(m_buffer);
  1781. }
  1782. template< ss_typename_param_k C
  1783. , ss_typename_param_k T
  1784. , ss_typename_param_k A
  1785. >
  1786. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::reference basic_simple_string<C, T, A>::front()
  1787. {
  1788. return (*this)[0];
  1789. }
  1790. template< ss_typename_param_k C
  1791. , ss_typename_param_k T
  1792. , ss_typename_param_k A
  1793. >
  1794. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::reference basic_simple_string<C, T, A>::back()
  1795. {
  1796. return (*this)[length() - 1];
  1797. }
  1798. template< ss_typename_param_k C
  1799. , ss_typename_param_k T
  1800. , ss_typename_param_k A
  1801. >
  1802. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::const_reference basic_simple_string<C, T, A>::front() const
  1803. {
  1804. return (*this)[0];
  1805. }
  1806. template< ss_typename_param_k C
  1807. , ss_typename_param_k T
  1808. , ss_typename_param_k A
  1809. >
  1810. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::const_reference basic_simple_string<C, T, A>::back() const
  1811. {
  1812. return (*this)[length() - 1];
  1813. }
  1814. template< ss_typename_param_k C
  1815. , ss_typename_param_k T
  1816. , ss_typename_param_k A
  1817. >
  1818. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::size_type basic_simple_string<C, T, A>::copy( ss_typename_type_k basic_simple_string<C, T, A>::value_type* dest
  1819. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  1820. , ss_typename_type_k basic_simple_string<C, T, A>::size_type pos /* = 0 */) const
  1821. {
  1822. size_type len = length();
  1823. if(pos < len)
  1824. {
  1825. if(len < pos + cch)
  1826. {
  1827. cch = len - pos;
  1828. }
  1829. traits_type::copy(dest, data() + pos, cch);
  1830. }
  1831. else
  1832. {
  1833. cch = 0;
  1834. }
  1835. return cch;
  1836. }
  1837. // Iteration
  1838. #ifndef STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE
  1839. template< ss_typename_param_k C
  1840. , ss_typename_param_k T
  1841. , ss_typename_param_k A
  1842. >
  1843. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::const_iterator basic_simple_string<C, T, A>::begin() const
  1844. {
  1845. return const_cast<class_type*>(this)->begin_();
  1846. }
  1847. template< ss_typename_param_k C
  1848. , ss_typename_param_k T
  1849. , ss_typename_param_k A
  1850. >
  1851. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::const_iterator basic_simple_string<C, T, A>::end() const
  1852. {
  1853. return const_cast<class_type*>(this)->end_();
  1854. }
  1855. #endif /* !STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
  1856. template< ss_typename_param_k C
  1857. , ss_typename_param_k T
  1858. , ss_typename_param_k A
  1859. >
  1860. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::iterator basic_simple_string<C, T, A>::begin()
  1861. {
  1862. return begin_();
  1863. }
  1864. template< ss_typename_param_k C
  1865. , ss_typename_param_k T
  1866. , ss_typename_param_k A
  1867. >
  1868. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::iterator basic_simple_string<C, T, A>::end()
  1869. {
  1870. return end_();
  1871. }
  1872. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  1873. template< ss_typename_param_k C
  1874. , ss_typename_param_k T
  1875. , ss_typename_param_k A
  1876. >
  1877. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::const_reverse_iterator basic_simple_string<C, T, A>::rbegin() const
  1878. {
  1879. return const_reverse_iterator(end());
  1880. }
  1881. template< ss_typename_param_k C
  1882. , ss_typename_param_k T
  1883. , ss_typename_param_k A
  1884. >
  1885. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::const_reverse_iterator basic_simple_string<C, T, A>::rend() const
  1886. {
  1887. return const_reverse_iterator(begin());
  1888. }
  1889. template< ss_typename_param_k C
  1890. , ss_typename_param_k T
  1891. , ss_typename_param_k A
  1892. >
  1893. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::reverse_iterator basic_simple_string<C, T, A>::rbegin()
  1894. {
  1895. return reverse_iterator(end());
  1896. }
  1897. template< ss_typename_param_k C
  1898. , ss_typename_param_k T
  1899. , ss_typename_param_k A
  1900. >
  1901. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::reverse_iterator basic_simple_string<C, T, A>::rend()
  1902. {
  1903. return reverse_iterator(begin());
  1904. }
  1905. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  1906. // Assignment
  1907. template< ss_typename_param_k C
  1908. , ss_typename_param_k T
  1909. , ss_typename_param_k A
  1910. >
  1911. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::assign(
  1912. ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s
  1913. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  1914. )
  1915. {
  1916. STLSOFT_ASSERT(is_valid());
  1917. if(NULL == m_buffer)
  1918. {
  1919. if(cch == 0)
  1920. {
  1921. // Nothing to do
  1922. }
  1923. else
  1924. {
  1925. m_buffer = alloc_buffer_(s, cch);
  1926. }
  1927. }
  1928. else
  1929. {
  1930. if(NULL == s)
  1931. {
  1932. destroy_buffer_(m_buffer);
  1933. m_buffer = NULL;
  1934. }
  1935. else
  1936. {
  1937. // Here is an opportunity to optimise a bit. We will do more so in a
  1938. // later release, but for the moment we will reuse our existing
  1939. // buffer if its capacity is sufficient for our purposes
  1940. string_buffer* buffer = string_buffer_from_member_pointer_(m_buffer);
  1941. // If:
  1942. //
  1943. // - the required size fits, AND
  1944. // - the source string is not within the existing buffer
  1945. if( cch < buffer->capacity &&
  1946. ( s < &buffer->contents[0] ||
  1947. s > &buffer->contents[cch]))
  1948. {
  1949. traits_type::copy(buffer->contents, s, cch);
  1950. buffer->contents[cch] = 0;
  1951. buffer->length = cch;
  1952. }
  1953. else
  1954. {
  1955. member_pointer new_buffer = alloc_buffer_(s, cch, cch);
  1956. destroy_buffer_(m_buffer);
  1957. m_buffer = new_buffer;
  1958. }
  1959. }
  1960. }
  1961. STLSOFT_ASSERT(is_valid());
  1962. return *this;
  1963. }
  1964. template< ss_typename_param_k C
  1965. , ss_typename_param_k T
  1966. , ss_typename_param_k A
  1967. >
  1968. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::assign(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s)
  1969. {
  1970. return assign(s, (NULL == s) ? 0 : traits_type::length(s));
  1971. }
  1972. template< ss_typename_param_k C
  1973. , ss_typename_param_k T
  1974. , ss_typename_param_k A
  1975. >
  1976. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::assign( ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs
  1977. , ss_typename_type_k basic_simple_string<C, T, A>::size_type pos
  1978. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch)
  1979. {
  1980. char_type* s = char_pointer_from_member_pointer_(rhs.m_buffer);
  1981. size_type len = rhs.length();
  1982. if(len < pos)
  1983. {
  1984. pos = len;
  1985. }
  1986. if(len - pos < cch)
  1987. {
  1988. cch = len - pos;
  1989. }
  1990. if(NULL != s)
  1991. {
  1992. s += pos;
  1993. }
  1994. else
  1995. {
  1996. cch = 0;
  1997. }
  1998. return assign(s, cch);
  1999. }
  2000. template< ss_typename_param_k C
  2001. , ss_typename_param_k T
  2002. , ss_typename_param_k A
  2003. >
  2004. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::assign(ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs)
  2005. {
  2006. return assign(char_pointer_from_member_pointer_(rhs.m_buffer), rhs.length());
  2007. }
  2008. template< ss_typename_param_k C
  2009. , ss_typename_param_k T
  2010. , ss_typename_param_k A
  2011. >
  2012. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::assign( ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  2013. , ss_typename_type_k basic_simple_string<C, T, A>::char_type ch)
  2014. {
  2015. buffer_type_ buffer(cch);
  2016. static_cast<void>(stlsoft_ns_qual_std(fill)(buffer.begin(), buffer.end(), ch));
  2017. return assign(buffer.data(), buffer.size());
  2018. }
  2019. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  2020. template< ss_typename_param_k C
  2021. , ss_typename_param_k T
  2022. , ss_typename_param_k A
  2023. >
  2024. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::assign( ss_typename_type_k basic_simple_string<C, T, A>::const_iterator first
  2025. , ss_typename_type_k basic_simple_string<C, T, A>::const_iterator last)
  2026. {
  2027. // We have to use this strange appearing this, because of Visual C++ .NET's
  2028. // disgusting STL swill. Sigh!
  2029. return assign(&(*first), last - first);
  2030. }
  2031. #endif /* !STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  2032. template< ss_typename_param_k C
  2033. , ss_typename_param_k T
  2034. , ss_typename_param_k A
  2035. >
  2036. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type const& basic_simple_string<C, T, A>::operator =(ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs)
  2037. {
  2038. return assign(rhs);
  2039. }
  2040. template< ss_typename_param_k C
  2041. , ss_typename_param_k T
  2042. , ss_typename_param_k A
  2043. >
  2044. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type const& basic_simple_string<C, T, A>::operator =(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s)
  2045. {
  2046. return assign(s);
  2047. }
  2048. template< ss_typename_param_k C
  2049. , ss_typename_param_k T
  2050. , ss_typename_param_k A
  2051. >
  2052. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type const& basic_simple_string<C, T, A>::operator =(ss_typename_type_k basic_simple_string<C, T, A>::char_type ch)
  2053. {
  2054. char_type sz[2] = { ch, traits_type::to_char_type(0) };
  2055. return assign(sz);
  2056. }
  2057. // Appending
  2058. template< ss_typename_param_k C
  2059. , ss_typename_param_k T
  2060. , ss_typename_param_k A
  2061. >
  2062. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::append( ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s
  2063. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch)
  2064. {
  2065. STLSOFT_ASSERT(is_valid());
  2066. if(NULL == m_buffer)
  2067. {
  2068. assign(s, cch);
  2069. }
  2070. else
  2071. {
  2072. if( NULL == s ||
  2073. 0 == cch)
  2074. {
  2075. // Nothing to do
  2076. }
  2077. else
  2078. {
  2079. #if 1
  2080. // We're taking a length here, which may have been done already.
  2081. // This should be optimised out in a subsequent release
  2082. size_type len = traits_type::length_max(s, cch);
  2083. if(len < cch)
  2084. {
  2085. cch = len;
  2086. }
  2087. #endif /* 0 */
  2088. string_buffer* old_buffer = NULL;
  2089. string_buffer* buffer = string_buffer_from_member_pointer_(m_buffer);
  2090. size_type buf_len = buffer->length;
  2091. if(buffer->capacity - buf_len < 1 + cch)
  2092. {
  2093. // Allocate a new buffer of sufficient size
  2094. member_pointer new_buffer = alloc_buffer_(buffer->contents, buf_len + cch);
  2095. if(NULL == new_buffer) // Some allocators do not throw on failure!
  2096. {
  2097. cch = 0;
  2098. }
  2099. else
  2100. {
  2101. old_buffer = buffer; // Mark for destruction, but hold around in case appending from self
  2102. m_buffer = new_buffer;
  2103. buffer = string_buffer_from_member_pointer_(new_buffer);
  2104. }
  2105. }
  2106. traits_type::copy(buffer->contents + buf_len, s, cch);
  2107. buffer->length += cch;
  2108. buffer->contents[buffer->length] = traits_type::to_char_type(0);
  2109. if(NULL != old_buffer)
  2110. {
  2111. destroy_buffer_(old_buffer);
  2112. }
  2113. }
  2114. }
  2115. STLSOFT_ASSERT(is_valid());
  2116. return *this;
  2117. }
  2118. template< ss_typename_param_k C
  2119. , ss_typename_param_k T
  2120. , ss_typename_param_k A
  2121. >
  2122. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::append(ss_typename_type_k basic_simple_string<C, T, A>::char_type const* s)
  2123. {
  2124. return append(s, (NULL == s) ? 0 : traits_type::length(s));
  2125. }
  2126. template< ss_typename_param_k C
  2127. , ss_typename_param_k T
  2128. , ss_typename_param_k A
  2129. >
  2130. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::append( ss_typename_type_k basic_simple_string<C, T, A>::class_type const& rhs
  2131. , ss_typename_type_k basic_simple_string<C, T, A>::size_type pos
  2132. , ss_typename_type_k basic_simple_string<C, T, A>::size_type cch)
  2133. {
  2134. char_type* s = char_pointer_from_member_pointer_(rhs.m_buffer);
  2135. size_type len = rhs.length();
  2136. if(len < pos)
  2137. {
  2138. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  2139. STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("index out of range"));
  2140. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  2141. pos = len;
  2142. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  2143. }
  2144. if(len - pos < cch)
  2145. {
  2146. cch = len - pos;
  2147. }
  2148. if(NULL != s)
  2149. {
  2150. s += pos;
  2151. }
  2152. else
  2153. {
  2154. cch = 0;
  2155. }
  2156. return append(s, cch);
  2157. }
  2158. template< ss_typename_param_k C
  2159. , ss_typename_param_k T
  2160. , ss_typename_param_k A
  2161. >
  2162. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::append(ss_typename_type_k basic_simple_string<C, T, A>::class_type const& s)
  2163. {
  2164. return append(char_pointer_from_member_pointer_(s.m_buffer), s.length());
  2165. }
  2166. template< ss_typename_param_k C
  2167. , ss_typename_param_k T
  2168. , ss_typename_param_k A
  2169. >
  2170. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::append( ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  2171. , ss_typename_type_k basic_simple_string<C, T, A>::char_type ch)
  2172. {
  2173. if(NULL == m_buffer)
  2174. {
  2175. assign(cch, ch);
  2176. }
  2177. else
  2178. {
  2179. buffer_type_ buffer(cch);
  2180. static_cast<void>(stlsoft_ns_qual_std(fill)(buffer.begin(), buffer.end(), ch));
  2181. append(buffer.data(), buffer.size());
  2182. }
  2183. return *this;
  2184. }
  2185. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  2186. template< ss_typename_param_k C
  2187. , ss_typename_param_k T
  2188. , ss_typename_param_k A
  2189. >
  2190. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::append( ss_typename_type_k basic_simple_string<C, T, A>::const_iterator first
  2191. , ss_typename_type_k basic_simple_string<C, T, A>::const_iterator last)
  2192. {
  2193. // We have to use this strange appearing code because of Visual C++ .NET's
  2194. // disgusting STL swill. Sigh!
  2195. return append(&(*first), last - first);
  2196. }
  2197. #endif /* !STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  2198. template< ss_typename_param_k C
  2199. , ss_typename_param_k T
  2200. , ss_typename_param_k A
  2201. >
  2202. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::operator +=(ss_typename_type_k basic_simple_string<C, T, A>::char_type ch)
  2203. {
  2204. return append(1, ch);
  2205. }
  2206. template< ss_typename_param_k C
  2207. , ss_typename_param_k T
  2208. , ss_typename_param_k A
  2209. >
  2210. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::operator +=(const ss_typename_type_k basic_simple_string<C, T, A>::char_type* s)
  2211. {
  2212. return append(s);
  2213. }
  2214. template< ss_typename_param_k C
  2215. , ss_typename_param_k T
  2216. , ss_typename_param_k A
  2217. >
  2218. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::class_type& basic_simple_string<C, T, A>::operator +=(const ss_typename_type_k basic_simple_string<C, T, A>::class_type& rhs)
  2219. {
  2220. return append(rhs);
  2221. }
  2222. template< ss_typename_param_k C
  2223. , ss_typename_param_k T
  2224. , ss_typename_param_k A
  2225. >
  2226. inline void basic_simple_string<C, T, A>::push_back(ss_typename_type_k basic_simple_string<C, T, A>::char_type ch)
  2227. {
  2228. append(1, ch);
  2229. }
  2230. // Operations
  2231. template< ss_typename_param_k C
  2232. , ss_typename_param_k T
  2233. , ss_typename_param_k A
  2234. >
  2235. inline void basic_simple_string<C, T, A>::reserve(ss_typename_type_k basic_simple_string<C, T, A>::size_type cch)
  2236. {
  2237. if(length() < cch)
  2238. {
  2239. if(NULL == m_buffer)
  2240. {
  2241. m_buffer = alloc_buffer_(NULL, cch, 0);
  2242. }
  2243. else
  2244. {
  2245. if(cch <= string_buffer_from_member_pointer_(m_buffer)->capacity)
  2246. {
  2247. ; // Nothing to do
  2248. }
  2249. else
  2250. {
  2251. // Allocate a new buffer of sufficient size
  2252. member_pointer new_buffer = alloc_buffer_(c_str(), cch, length());
  2253. if(NULL != new_buffer) // Some allocators do not throw on failure!
  2254. {
  2255. destroy_buffer_(m_buffer);
  2256. m_buffer = new_buffer;
  2257. }
  2258. }
  2259. }
  2260. }
  2261. }
  2262. template< ss_typename_param_k C
  2263. , ss_typename_param_k T
  2264. , ss_typename_param_k A
  2265. >
  2266. inline void basic_simple_string<C, T, A>::swap(ss_typename_type_k basic_simple_string<C, T, A>::class_type& other)
  2267. {
  2268. STLSOFT_ASSERT(is_valid());
  2269. STLSOFT_ASSERT(other.is_valid());
  2270. std_swap(m_buffer, other.m_buffer);
  2271. }
  2272. template< ss_typename_param_k C
  2273. , ss_typename_param_k T
  2274. , ss_typename_param_k A
  2275. >
  2276. inline void basic_simple_string<C, T, A>::resize( ss_typename_type_k basic_simple_string<C, T, A>::size_type cch
  2277. , ss_typename_type_k basic_simple_string<C, T, A>::value_type ch)
  2278. {
  2279. STLSOFT_ASSERT(is_valid());
  2280. size_type const len = length();
  2281. if(len != cch)
  2282. {
  2283. if(len < cch)
  2284. {
  2285. /* Expand the string, using self-assignemt. */
  2286. assign(c_str(), cch);
  2287. traits_type::assign(char_pointer_from_member_pointer_(m_buffer) + len, cch - len, ch);
  2288. }
  2289. string_buffer* buffer = string_buffer_from_member_pointer_(m_buffer);
  2290. buffer->length = cch;
  2291. buffer->contents[buffer->length] = traits_type::to_char_type(0);
  2292. }
  2293. STLSOFT_ASSERT(is_valid());
  2294. }
  2295. template< ss_typename_param_k C
  2296. , ss_typename_param_k T
  2297. , ss_typename_param_k A
  2298. >
  2299. inline void basic_simple_string<C, T, A>::clear()
  2300. {
  2301. if(NULL != m_buffer)
  2302. {
  2303. string_buffer* buffer = string_buffer_from_member_pointer_(m_buffer);
  2304. buffer->length = 0;
  2305. buffer->contents[0] = traits_type::to_char_type(0);
  2306. }
  2307. }
  2308. // Attributes
  2309. template< ss_typename_param_k C
  2310. , ss_typename_param_k T
  2311. , ss_typename_param_k A
  2312. >
  2313. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::size_type basic_simple_string<C, T, A>::size() const
  2314. {
  2315. STLSOFT_ASSERT(is_valid());
  2316. return (NULL == m_buffer) ? 0 : string_buffer_from_member_pointer_(m_buffer)->length;
  2317. }
  2318. template< ss_typename_param_k C
  2319. , ss_typename_param_k T
  2320. , ss_typename_param_k A
  2321. >
  2322. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::size_type basic_simple_string<C, T, A>::max_size() const
  2323. {
  2324. STLSOFT_ASSERT(is_valid());
  2325. return static_cast<size_type>(-1) / sizeof(char_type);
  2326. }
  2327. template< ss_typename_param_k C
  2328. , ss_typename_param_k T
  2329. , ss_typename_param_k A
  2330. >
  2331. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::size_type basic_simple_string<C, T, A>::length() const
  2332. {
  2333. STLSOFT_ASSERT(is_valid());
  2334. return size();
  2335. }
  2336. template< ss_typename_param_k C
  2337. , ss_typename_param_k T
  2338. , ss_typename_param_k A
  2339. >
  2340. inline ss_typename_type_ret_k basic_simple_string<C, T, A>::size_type basic_simple_string<C, T, A>::capacity() const
  2341. {
  2342. STLSOFT_ASSERT(is_valid());
  2343. return (NULL == m_buffer) ? 0 : string_buffer_from_member_pointer_(m_buffer)->capacity;
  2344. }
  2345. template< ss_typename_param_k C
  2346. , ss_typename_param_k T
  2347. , ss_typename_param_k A
  2348. >
  2349. inline ss_bool_t basic_simple_string<C, T, A>::empty() const
  2350. {
  2351. STLSOFT_ASSERT(is_valid());
  2352. return 0 == length();
  2353. }
  2354. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  2355. /* ////////////////////////////////////////////////////////////////////// */
  2356. #ifndef _STLSOFT_NO_NAMESPACE
  2357. } // namespace stlsoft
  2358. #endif /* _STLSOFT_NO_NAMESPACE */
  2359. /* In the special case of Intel behaving as VC++ 7.0 or earlier on Win32, we
  2360. * illegally insert into the std namespace.
  2361. */
  2362. #if defined(STLSOFT_CF_std_NAMESPACE)
  2363. # if ( ( defined(STLSOFT_COMPILER_IS_INTEL) && \
  2364. defined(_MSC_VER))) && \
  2365. _MSC_VER < 1310
  2366. namespace std
  2367. {
  2368. template< ss_typename_param_k C
  2369. , ss_typename_param_k T
  2370. , ss_typename_param_k A
  2371. >
  2372. inline void swap(stlsoft_ns_qual(basic_simple_string)<C, T, A>& lhs, stlsoft_ns_qual(basic_simple_string)<C, T, A>& rhs)
  2373. {
  2374. lhs.swap(rhs);
  2375. }
  2376. } // namespace std
  2377. # endif /* INTEL && _MSC_VER < 1310 */
  2378. #endif /* STLSOFT_CF_std_NAMESPACE */
  2379. /* ////////////////////////////////////////////////////////////////////// */
  2380. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING */
  2381. /* ///////////////////////////// end of file //////////////////////////// */