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.

2124 lines
69 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/string/static_string.hpp (originally MStkStr.h, ::SynesisDev)
  3. *
  4. * Purpose: basic_static_string class template.
  5. *
  6. * Created: 11th June 1994
  7. * Updated: 10th August 2009
  8. *
  9. * Thanks: To Cludio Albuquerque for supplying the pop_back() member.
  10. *
  11. * Home: http://stlsoft.org/
  12. *
  13. * Copyright (c) 1994-2009, Matthew Wilson and Synesis Software
  14. * All rights reserved.
  15. *
  16. * Redistribution and use in source and binary forms, with or without
  17. * modification, are permitted provided that the following conditions are met:
  18. *
  19. * - Redistributions of source code must retain the above copyright notice, this
  20. * list of conditions and the following disclaimer.
  21. * - Redistributions in binary form must reproduce the above copyright notice,
  22. * this list of conditions and the following disclaimer in the documentation
  23. * and/or other materials provided with the distribution.
  24. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  25. * any contributors may be used to endorse or promote products derived from
  26. * this software without specific prior written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  29. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  34. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  35. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  37. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * ////////////////////////////////////////////////////////////////////// */
  41. /** \file stlsoft/string/static_string.hpp
  42. *
  43. * [C++ only] Definition of the stlsoft::basic_static_string class
  44. * template
  45. * (\ref group__library__string "String" Library).
  46. */
  47. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STATIC_STRING
  48. #define STLSOFT_INCL_STLSOFT_STRING_HPP_STATIC_STRING
  49. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  50. # define STLSOFT_VER_STLSOFT_STRING_HPP_STATIC_STRING_MAJOR 4
  51. # define STLSOFT_VER_STLSOFT_STRING_HPP_STATIC_STRING_MINOR 3
  52. # define STLSOFT_VER_STLSOFT_STRING_HPP_STATIC_STRING_REVISION 2
  53. # define STLSOFT_VER_STLSOFT_STRING_HPP_STATIC_STRING_EDIT 198
  54. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  55. /* /////////////////////////////////////////////////////////////////////////
  56. * Compatibility
  57. */
  58. /*
  59. [Incompatibilies-start]
  60. STLSOFT_COMPILER_IS_DMC: __DMC__<0x0839
  61. STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1200
  62. STLSOFT_COMPILER_IS_WATCOM:
  63. [Incompatibilies-end]
  64. */
  65. /* /////////////////////////////////////////////////////////////////////////
  66. * Includes
  67. */
  68. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  69. # include <stlsoft/stlsoft.h>
  70. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  71. #if defined(STLSOFT_COMPILER_IS_DMC) && \
  72. __DMC__ < 0x0839
  73. # error stlsoft/string/static_string.hpp is not compatible with Digital Mars C/C++ 3.38 or earlier
  74. #endif /* compiler */
  75. #if defined(STLSOFT_COMPILER_IS_MSVC) && \
  76. _MSC_VER < 1200
  77. # error stlsoft/string/static_string.hpp is not compatible with Visual C++ 5.0 or earlier
  78. #endif /* compiler */
  79. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS
  80. # include <stlsoft/string/char_traits.hpp>
  81. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS */
  82. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  83. # include <stlsoft/collections/util/collections.hpp>
  84. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  85. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  86. # include <stlsoft/memory/auto_buffer.hpp>
  87. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  88. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR
  89. # include <stlsoft/memory/allocator_selector.hpp>
  90. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR */
  91. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP
  92. # include <stlsoft/util/std_swap.hpp>
  93. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP */
  94. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_GENERATORS
  95. # include <stlsoft/util/std/iterator_generators.hpp>
  96. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_GENERATORS */
  97. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  98. # include <stlsoft/util/std/iterator_helper.hpp>
  99. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  100. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  101. # include <stdexcept> // for std::out_of_range
  102. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
  103. #ifdef STLSOFT_UNITTEST
  104. # include <string>
  105. # include <stdio.h>
  106. #endif /* STLSOFT_UNITTEST */
  107. /* /////////////////////////////////////////////////////////////////////////
  108. * Namespace
  109. */
  110. #ifndef _STLSOFT_NO_NAMESPACE
  111. namespace stlsoft
  112. {
  113. #endif /* _STLSOFT_NO_NAMESPACE */
  114. /* /////////////////////////////////////////////////////////////////////////
  115. * Classes
  116. */
  117. /** Simple string class using fixed-size static-based storage
  118. *
  119. * \param C The character type
  120. * \param CCH The number of characters in the fixed-side buffer, not including the null-terminator
  121. * \param T The traits type. On translators that support default template arguments this is defaulted to char_traits<C>
  122. *
  123. * \ingroup group__library__string
  124. */
  125. template< ss_typename_param_k C
  126. , ss_size_t CCH
  127. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  128. , ss_typename_param_k T = char_traits<C>
  129. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  130. , ss_typename_param_k T = /* char_traits<C> */
  131. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  132. >
  133. // class static_string
  134. class basic_static_string
  135. : public stl_collection_tag
  136. {
  137. private:
  138. enum { internalSize = CCH };
  139. /// \name Types
  140. /// @{
  141. public:
  142. /// The value type
  143. typedef C value_type;
  144. /// The traits type
  145. typedef T traits_type;
  146. /// The allocator type
  147. typedef ss_typename_type_k allocator_selector<C>::allocator_type allocator_type;
  148. /// The current parameterisation of the type
  149. typedef basic_static_string<C, CCH, T> class_type;
  150. /// The character type
  151. typedef value_type char_type;
  152. /// The pointer type
  153. typedef value_type* pointer;
  154. /// The non-mutable (const) pointer type
  155. typedef value_type const* const_pointer;
  156. /// The reference type
  157. typedef value_type& reference;
  158. /// The non-mutable (const) reference type
  159. typedef value_type const& const_reference;
  160. /// The size type
  161. typedef ss_size_t size_type;
  162. /// The difference type
  163. typedef ss_ptrdiff_t difference_type;
  164. /// The iterator type
  165. typedef
  166. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  167. ss_typename_type_k
  168. #endif /* compiler */
  169. pointer_iterator < value_type
  170. , pointer
  171. , reference
  172. >::type iterator;
  173. /// The non-mutating (const) iterator type
  174. typedef
  175. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  176. ss_typename_type_k
  177. #endif /* compiler */
  178. pointer_iterator < value_type const
  179. , const_pointer
  180. , const_reference
  181. >::type const_iterator;
  182. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  183. /// The mutating (non-const) reverse iterator type
  184. typedef ss_typename_type_k reverse_iterator_generator < iterator
  185. , value_type
  186. , reference
  187. , pointer
  188. , difference_type
  189. >::type reverse_iterator;
  190. /// The non-mutating (const) reverse iterator type
  191. typedef ss_typename_type_k const_reverse_iterator_generator < const_iterator
  192. , value_type
  193. , const_reference
  194. , const_pointer
  195. , difference_type
  196. >::type const_reverse_iterator;
  197. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  198. private:
  199. typedef auto_buffer_old<char_type
  200. , allocator_type
  201. > buffer_type_;
  202. /// @}
  203. /// \name Construction
  204. /// @{
  205. public:
  206. /// Default constructor
  207. basic_static_string();
  208. /// Copy constructor
  209. basic_static_string(class_type const& rhs);
  210. /// Construct from the given string at the specified position
  211. basic_static_string(class_type const& s, size_type pos);
  212. /// Construct with \c n characters from the given string at the specified position
  213. basic_static_string(class_type const& s, size_type pos, size_type n);
  214. /// Construct from the given character string
  215. basic_static_string(char_type const* s);
  216. /// Construct with \c n characters from the given character string
  217. basic_static_string(char_type const* s, size_type n);
  218. /// Construct with \c n characters each set to \c ch
  219. basic_static_string(size_type n, char_type ch);
  220. /// Construct from the range [first:last)
  221. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  222. basic_static_string(char_type const* f, char_type const* t);
  223. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  224. template <ss_typename_param_k II>
  225. basic_static_string(II first, II last)
  226. : m_length(static_cast<ss_size_t>(stlsoft_ns_qual_std(distance)(first, last)))
  227. {
  228. STLSOFT_MESSAGE_ASSERT("incident string too large for static_string construction", !(max_size() < m_length));
  229. buffer_type_ buffer(m_length);
  230. stlsoft_ns_qual_std(copy)(first, last, buffer.begin());
  231. traits_type::copy(&m_buffer[0], buffer.data(), buffer.size());
  232. m_buffer[m_length] = '\0';
  233. m_buffer[max_size()] = '\0';
  234. }
  235. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  236. /// Destructor
  237. ~basic_static_string() stlsoft_throw_0();
  238. /// @}
  239. /// \name Assignment
  240. /// @{
  241. public:
  242. /// Assigns from the given character string
  243. class_type& assign(char_type const* s);
  244. /// Assigns with \c n characters from the given character string
  245. class_type& assign(char_type const* s, size_type n);
  246. /// Assigns with \c n characters from the given character string at the specified position
  247. class_type& assign(class_type const& str, size_type pos, size_type n);
  248. /// Assigns from the given string
  249. class_type& assign(class_type const& str);
  250. /// Assigns \c n characters with the value \c ch
  251. class_type& assign(size_type n, char_type c);
  252. /// Assigns from the range [first:last)
  253. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  254. class_type& assign(const_iterator first, const_iterator last);
  255. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  256. template <ss_typename_param_k II>
  257. class_type& assign(II first, II last)
  258. {
  259. # if defined(STLSOFT_COMPILER_IS_GCC) && \
  260. __GNUC__ < 3
  261. typedef ss_typename_type_k std::iterator_traits<II> traits_t;
  262. return assign_(first, last, traits_t::iterator_category());
  263. # elif defined(STLSOFT_COMPILER_IS_MWERKS) || \
  264. defined(STLSOFT_COMPILER_IS_DMC)
  265. return assign_(first, last, stlsoft_iterator_query_category_ptr(II, first));
  266. # else /* ? compiler */
  267. return assign_(first, last, stlsoft_iterator_query_category(II, first));
  268. # endif /* compiler */
  269. }
  270. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  271. /// Copy assignment operator
  272. class_type const& operator =(class_type const& rhs);
  273. /// Assignment operator
  274. class_type const& operator =(char_type const* s);
  275. /// Assignment operator
  276. class_type const& operator =(char_type ch);
  277. /// @}
  278. /// \name Appending
  279. /// @{
  280. public:
  281. /// Appends the given character string
  282. class_type& append(char_type const* s);
  283. /// Appends \c cch characters from the given character string
  284. class_type& append(char_type const* s, size_type cch);
  285. /// Assigns \c cch characters from the given character string at the specified position
  286. class_type& append(class_type const& str, size_type pos, size_type cch);
  287. /// Appends the given string
  288. class_type& append(class_type const& str);
  289. /// Appends \c cch characters with the value \c ch
  290. class_type& append(size_type cch, char_type ch);
  291. /// Appends the range [first:last)
  292. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  293. class_type& append(const_iterator first, const_iterator last);
  294. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  295. template <ss_typename_param_k II>
  296. class_type& append(II first, II last)
  297. {
  298. # if defined(STLSOFT_COMPILER_IS_GCC) && \
  299. __GNUC__ < 3
  300. typedef ss_typename_type_k std::iterator_traits<II> traits_t;
  301. return append_(first, last, traits_t::iterator_category());
  302. # elif defined(STLSOFT_COMPILER_IS_MWERKS) || \
  303. defined(STLSOFT_COMPILER_IS_DMC)
  304. return append_(first, last, stlsoft_iterator_query_category_ptr(II, first));
  305. # else /* ? compiler */
  306. return append_(first, last, stlsoft_iterator_query_category(II, first));
  307. # endif /* compiler */
  308. }
  309. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  310. /// Concatenation operator
  311. class_type& operator +=(char_type ch);
  312. /// Concatenation operator
  313. class_type& operator +=(char_type const* s);
  314. /// Concatenation operator
  315. class_type& operator +=(class_type const& rhs);
  316. /// Appends a single character
  317. void push_back(char_type ch);
  318. /// Removes the last character
  319. void pop_back();
  320. /// @}
  321. /// \name Operations
  322. /// @{
  323. public:
  324. /// Reserves at least n characters
  325. void reserve(size_type n);
  326. /// Swaps the contents between \c this and \c other
  327. void swap(class_type& other);
  328. /// Resizes the string
  329. ///
  330. /// \param n The new size of the string
  331. /// \param ch The value with which to initialise additional items if the string is expanded
  332. void resize(size_type n, value_type ch = value_type());
  333. /// Empties the string
  334. void clear();
  335. /// @}
  336. /// \name Attributes
  337. /// @{
  338. public:
  339. /// The number of elements in the string
  340. size_type size() const;
  341. /// The maximum number of elements that can be stored in the string
  342. static size_type max_size();
  343. /// The number of elements in the string
  344. size_type length() const;
  345. /// The storage currently allocated by the string
  346. size_type capacity() const;
  347. /// Indicates whether the string is empty
  348. ss_bool_t empty() const;
  349. /// @}
  350. /// \name Comparison
  351. /// @{
  352. public:
  353. /// Compares \c this with the given string
  354. ss_sint_t compare(size_type pos, size_type n, value_type const* s, size_type cchRhs) const;
  355. /// Compares \c this with the given string
  356. ss_sint_t compare(size_type pos, size_type n, value_type const* s) const;
  357. /// Compares \c this with the given string
  358. ss_sint_t compare(value_type const* s) const;
  359. /// Compares \c this with the given string
  360. ss_sint_t compare(size_type pos, size_type n, class_type const& rhs, size_type posRhs, size_type cchRhs) const;
  361. /// Compares \c this with the given string
  362. ss_sint_t compare(size_type pos, size_type n, class_type const& rhs) const;
  363. /// Compares \c this with the given string
  364. ss_sint_t compare(class_type const& rhs) const;
  365. /// @}
  366. /// \name Accessors
  367. /// @{
  368. public:
  369. /// Returns mutable reference at the given index
  370. reference operator [](size_type index);
  371. /// Returns non-mutable (const) reference at the given index
  372. const_reference operator [](size_type index) const;
  373. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  374. /// Returns mutable (non-const) reference at the given index
  375. ///
  376. /// \note Throws std::out_of_range if index >= size()
  377. reference at(size_type index);
  378. /// Returns non-mutable (const) reference at the given index
  379. ///
  380. /// \note Throws std::out_of_range if index >= size()
  381. const_reference at(size_type index) const;
  382. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
  383. /// Returns null-terminated non-mutable (const) pointer to string data
  384. value_type const *c_str() const;
  385. /// Returns non-mutable (const) pointer to string data
  386. value_type const *data() const;
  387. /// Copies elements into the given destination
  388. size_type copy(value_type *dest, size_type cch_, size_type pos = 0) const;
  389. /// @}
  390. /// \name Iteration
  391. /// @{
  392. public:
  393. /// Begins the iteration
  394. ///
  395. /// \return A non-mutable (const) iterator representing the start of the sequence
  396. const_iterator begin() const;
  397. /// Ends the iteration
  398. ///
  399. /// \return A non-mutable (const) iterator representing the end of the sequence
  400. const_iterator end() const;
  401. /// Begins the iteration
  402. ///
  403. /// \return An iterator representing the start of the sequence
  404. iterator begin();
  405. /// Ends the iteration
  406. ///
  407. /// \return An iterator representing the end of the sequence
  408. iterator end();
  409. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  410. /// Begins the reverse iteration
  411. ///
  412. /// \return A non-mutable (const) iterator representing the start of the reverse sequence
  413. const_reverse_iterator rbegin() const;
  414. /// Ends the reverse iteration
  415. ///
  416. /// \return A non-mutable (const) iterator representing the end of the reverse sequence
  417. const_reverse_iterator rend() const;
  418. /// Begins the reverse iteration
  419. ///
  420. /// \return An iterator representing the start of the reverse sequence
  421. reverse_iterator rbegin();
  422. /// Ends the reverse iteration
  423. ///
  424. /// \return An iterator representing the end of the reverse sequence
  425. reverse_iterator rend();
  426. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  427. /// @}
  428. /// \name Implementation
  429. /// @{
  430. private:
  431. // Length
  432. size_type length_() const;
  433. // Invariance
  434. ss_bool_t is_valid() const;
  435. // Comparison
  436. static ss_sint_t compare_(char_type const* lhs, size_type lhs_len, char_type const* rhs, size_type rhs_len);
  437. // Assignment
  438. #if defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  439. template <ss_typename_param_k II>
  440. # if defined(STLSOFT_COMPILER_IS_MWERKS) || \
  441. defined(STLSOFT_COMPILER_IS_DMC)
  442. // 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
  443. class_type& assign_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag) const*)
  444. # else /* ? compiler */
  445. class_type& assign_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag))
  446. # endif /* compiler */
  447. {
  448. stlsoft_ns_qual_std(copy)(first, last, stlsoft_ns_qual_std(back_inserter)(*this));
  449. return *this;
  450. }
  451. template <ss_typename_param_k II>
  452. # if defined(STLSOFT_COMPILER_IS_MWERKS) || \
  453. defined(STLSOFT_COMPILER_IS_DMC)
  454. // 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
  455. class_type& assign_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag) const*)
  456. # else /* ? compiler */
  457. class_type& assign_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag))
  458. # endif /* compiler */
  459. {
  460. buffer_type_ buffer(static_cast<ss_size_t>(stlsoft_ns_qual_std(distance)(first, last)));
  461. stlsoft_ns_qual_std(copy)(first, last, buffer.begin());
  462. assign(buffer.data(), buffer.size());
  463. return *this;
  464. }
  465. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  466. // Appending
  467. #if defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  468. template <ss_typename_param_k II>
  469. # if defined(STLSOFT_COMPILER_IS_MWERKS) || \
  470. defined(STLSOFT_COMPILER_IS_DMC)
  471. class_type& append_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag) const*)
  472. # else /* ? compiler */
  473. class_type& append_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag))
  474. # endif /* compiler */
  475. {
  476. stlsoft_ns_qual_std(copy)(first, last, stlsoft_ns_qual_std(back_inserter)(*this));
  477. STLSOFT_ASSERT(is_valid());
  478. return *this;
  479. }
  480. template <ss_typename_param_k II>
  481. # if defined(STLSOFT_COMPILER_IS_MWERKS) || \
  482. defined(STLSOFT_COMPILER_IS_DMC)
  483. class_type& append_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag) const*)
  484. # else /* ? compiler */
  485. class_type& append_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag))
  486. # endif /* compiler */
  487. {
  488. buffer_type_ buffer(static_cast<ss_size_t>(stlsoft_ns_qual_std(distance)(first, last)));
  489. stlsoft_ns_qual_std(copy)(first, last, &buffer[0]);
  490. append(buffer.data(), buffer.size());
  491. STLSOFT_ASSERT(is_valid());
  492. return *this;
  493. }
  494. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  495. /// @}
  496. /// \name Members
  497. /// @{
  498. private:
  499. value_type m_buffer[internalSize + 1];
  500. ss_size_t m_length;
  501. /// @}
  502. };
  503. /* /////////////////////////////////////////////////////////////////////////
  504. * Operators
  505. */
  506. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  507. // operator ==
  508. template< ss_typename_param_k C
  509. , ss_size_t CCH
  510. , ss_typename_param_k T
  511. >
  512. inline ss_bool_t operator ==(basic_static_string<C, CCH, T> const& lhs, basic_static_string<C, CCH, T> const& rhs)
  513. {
  514. #ifdef _DEBUG
  515. // printf("lhs(%s); rhs(%s); lhs.compare(rhs)=%d\n", lhs.c_str(), lhs.c_str(), lhs.compare(rhs));
  516. #endif /* _DEBUG */
  517. return lhs.compare(rhs) == 0;
  518. }
  519. template< ss_typename_param_k C
  520. , ss_size_t CCH
  521. , ss_typename_param_k T
  522. >
  523. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  524. inline ss_bool_t operator ==(basic_static_string<C, CCH, T> const& lhs, ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* rhs)
  525. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  526. inline ss_bool_t operator ==(basic_static_string<C, CCH, T> const& lhs, C const* rhs)
  527. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  528. {
  529. return lhs.compare(rhs) == 0;
  530. }
  531. template< ss_typename_param_k C
  532. , ss_size_t CCH
  533. , ss_typename_param_k T
  534. >
  535. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  536. inline ss_bool_t operator ==(ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* lhs, basic_static_string<C, CCH, T> const& rhs)
  537. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  538. inline ss_bool_t operator ==(C *lhs, basic_static_string<C, CCH, T> const& rhs)
  539. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  540. {
  541. return rhs.compare(lhs) == 0;
  542. }
  543. // operator !=
  544. template< ss_typename_param_k C
  545. , ss_size_t CCH
  546. , ss_typename_param_k T
  547. >
  548. inline ss_bool_t operator !=(basic_static_string<C, CCH, T> const& lhs, basic_static_string<C, CCH, T> const& rhs)
  549. {
  550. return lhs.compare(rhs) != 0;
  551. }
  552. template< ss_typename_param_k C
  553. , ss_size_t CCH
  554. , ss_typename_param_k T
  555. >
  556. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  557. inline ss_bool_t operator !=(basic_static_string<C, CCH, T> const& lhs, ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* rhs)
  558. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  559. inline ss_bool_t operator !=(basic_static_string<C, CCH, T> const& lhs, C const* rhs)
  560. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  561. {
  562. return lhs.compare(rhs) != 0;
  563. }
  564. template< ss_typename_param_k C
  565. , ss_size_t CCH
  566. , ss_typename_param_k T
  567. >
  568. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  569. inline ss_bool_t operator !=(ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* lhs, basic_static_string<C, CCH, T> const& rhs)
  570. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  571. inline ss_bool_t operator !=(C const* lhs, basic_static_string<C, CCH, T> const& rhs)
  572. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  573. {
  574. return rhs.compare(lhs) != 0;
  575. }
  576. // operator <
  577. template< ss_typename_param_k C
  578. , ss_size_t CCH
  579. , ss_typename_param_k T
  580. >
  581. inline ss_bool_t operator <(basic_static_string<C, CCH, T> const& lhs, basic_static_string<C, CCH, T> const& rhs)
  582. {
  583. return lhs.compare(rhs) < 0;
  584. }
  585. template< ss_typename_param_k C
  586. , ss_size_t CCH
  587. , ss_typename_param_k T
  588. >
  589. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  590. inline ss_bool_t operator <(basic_static_string<C, CCH, T> const& lhs, ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* rhs)
  591. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  592. inline ss_bool_t operator <(basic_static_string<C, CCH, T> const& lhs, C const* rhs)
  593. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  594. {
  595. return lhs.compare(rhs) < 0;
  596. }
  597. template< ss_typename_param_k C
  598. , ss_size_t CCH
  599. , ss_typename_param_k T
  600. >
  601. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  602. inline ss_bool_t operator <(ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* lhs, basic_static_string<C, CCH, T> const& rhs)
  603. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  604. inline ss_bool_t operator <(C const* lhs, basic_static_string<C, CCH, T> const& rhs)
  605. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  606. {
  607. return rhs.compare(lhs) > 0;
  608. }
  609. // operator <=
  610. template< ss_typename_param_k C
  611. , ss_size_t CCH
  612. , ss_typename_param_k T
  613. >
  614. inline ss_bool_t operator <=(basic_static_string<C, CCH, T> const& lhs, basic_static_string<C, CCH, T> const& rhs)
  615. {
  616. return lhs.compare(rhs) <= 0;
  617. }
  618. template< ss_typename_param_k C
  619. , ss_size_t CCH
  620. , ss_typename_param_k T
  621. >
  622. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  623. inline ss_bool_t operator <=(basic_static_string<C, CCH, T> const& lhs, ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* rhs)
  624. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  625. inline ss_bool_t operator <=(basic_static_string<C, CCH, T> const& lhs, C const* rhs)
  626. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  627. {
  628. return lhs.compare(rhs) <= 0;
  629. }
  630. template< ss_typename_param_k C
  631. , ss_size_t CCH
  632. , ss_typename_param_k T
  633. >
  634. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  635. inline ss_bool_t operator <=(ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* lhs, basic_static_string<C, CCH, T> const& rhs)
  636. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  637. inline ss_bool_t operator <=(C const* lhs, basic_static_string<C, CCH, T> const& rhs)
  638. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  639. {
  640. return rhs.compare(lhs) >= 0;
  641. }
  642. // operator >
  643. template< ss_typename_param_k C
  644. , ss_size_t CCH
  645. , ss_typename_param_k T
  646. >
  647. inline ss_bool_t operator >(basic_static_string<C, CCH, T> const& lhs, basic_static_string<C, CCH, T> const& rhs)
  648. {
  649. return lhs.compare(rhs) > 0;
  650. }
  651. template< ss_typename_param_k C
  652. , ss_size_t CCH
  653. , ss_typename_param_k T
  654. >
  655. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  656. inline ss_bool_t operator >(basic_static_string<C, CCH, T> const& lhs, ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* rhs)
  657. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  658. inline ss_bool_t operator >(basic_static_string<C, CCH, T> const& lhs, C const* rhs)
  659. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  660. {
  661. return lhs.compare(rhs) > 0;
  662. }
  663. template< ss_typename_param_k C
  664. , ss_size_t CCH
  665. , ss_typename_param_k T
  666. >
  667. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  668. inline ss_bool_t operator >(ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* lhs, basic_static_string<C, CCH, T> const& rhs)
  669. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  670. inline ss_bool_t operator >(C const* lhs, basic_static_string<C, CCH, T> const& rhs)
  671. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  672. {
  673. return rhs.compare(lhs) < 0;
  674. }
  675. // operator >=
  676. template< ss_typename_param_k C
  677. , ss_size_t CCH
  678. , ss_typename_param_k T
  679. >
  680. inline ss_bool_t operator >=(basic_static_string<C, CCH, T> const& lhs, basic_static_string<C, CCH, T> const& rhs)
  681. {
  682. return lhs.compare(rhs) >= 0;
  683. }
  684. template< ss_typename_param_k C
  685. , ss_size_t CCH
  686. , ss_typename_param_k T
  687. >
  688. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  689. inline ss_bool_t operator >=(basic_static_string<C, CCH, T> const& lhs, ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* rhs)
  690. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  691. inline ss_bool_t operator >=(basic_static_string<C, CCH, T> const& lhs, C const* rhs)
  692. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  693. {
  694. return lhs.compare(rhs) >= 0;
  695. }
  696. template< ss_typename_param_k C
  697. , ss_size_t CCH
  698. , ss_typename_param_k T
  699. >
  700. #ifdef STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
  701. inline ss_bool_t operator >=(ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* lhs, basic_static_string<C, CCH, T> const& rhs)
  702. #else /* ? STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  703. inline ss_bool_t operator >=(C const* lhs, basic_static_string<C, CCH, T> const& rhs)
  704. #endif /* STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
  705. {
  706. return rhs.compare(lhs) <= 0;
  707. }
  708. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  709. /* /////////////////////////////////////////////////////////////////////////
  710. * swapping
  711. */
  712. template< ss_typename_param_k C
  713. , ss_size_t CCH
  714. , ss_typename_param_k T
  715. >
  716. inline void swap(basic_static_string<C, CCH, T>& lhs, basic_static_string<C, CCH, T>& rhs)
  717. {
  718. lhs.swap(rhs);
  719. }
  720. /* /////////////////////////////////////////////////////////////////////////
  721. * Shims
  722. */
  723. #ifndef STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED
  724. // c_str_ptr_null
  725. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  726. template <ss_size_t CCH, ss_typename_param_k T >
  727. inline ss_char_a_t const* c_str_ptr_null_a(stlsoft_ns_qual(basic_static_string)<ss_char_a_t, CCH, T> const& s)
  728. {
  729. return (0 != s.length()) ? s.c_str() : NULL;
  730. }
  731. template <ss_size_t CCH, ss_typename_param_k T >
  732. inline ss_char_w_t const* c_str_ptr_null_w(stlsoft_ns_qual(basic_static_string)<ss_char_w_t, CCH, T> const& s)
  733. {
  734. return (0 != s.length()) ? s.c_str() : NULL;
  735. }
  736. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  737. /** \ref group__concept__shim__string_access__c_str_ptr_null for stlsoft::basic_static_string
  738. *
  739. * \ingroup group__concept__shim__string_access
  740. */
  741. template< ss_typename_param_k C
  742. , ss_size_t CCH
  743. , ss_typename_param_k T
  744. >
  745. inline C const* c_str_ptr_null(stlsoft_ns_qual(basic_static_string)<C, CCH, T> const& s)
  746. {
  747. return (0 != s.length()) ? s.c_str() : NULL;
  748. }
  749. // c_str_ptr
  750. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  751. template <ss_size_t CCH, ss_typename_param_k T >
  752. inline ss_char_a_t const* c_str_ptr_a(stlsoft_ns_qual(basic_static_string)<ss_char_a_t, CCH, T> const& s)
  753. {
  754. return s.c_str();
  755. }
  756. template <ss_size_t CCH, ss_typename_param_k T >
  757. inline ss_char_w_t const* c_str_ptr_w(stlsoft_ns_qual(basic_static_string)<ss_char_w_t, CCH, T> const& s)
  758. {
  759. return s.c_str();
  760. }
  761. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  762. /** \ref group__concept__shim__string_access__c_str_ptr for stlsoft::basic_static_string
  763. *
  764. * \ingroup group__concept__shim__string_access
  765. */
  766. template< ss_typename_param_k C
  767. , ss_size_t CCH
  768. , ss_typename_param_k T
  769. >
  770. inline C const* c_str_ptr(stlsoft_ns_qual(basic_static_string)<C, CCH, T> const& s)
  771. {
  772. return s.c_str();
  773. }
  774. // c_str_data
  775. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  776. template <ss_size_t CCH, ss_typename_param_k T >
  777. inline ss_char_a_t const* c_str_data_a(stlsoft_ns_qual(basic_static_string)<ss_char_a_t, CCH, T> const& s)
  778. {
  779. return s.data();
  780. }
  781. template <ss_size_t CCH, ss_typename_param_k T >
  782. inline ss_char_w_t const* c_str_data_w(stlsoft_ns_qual(basic_static_string)<ss_char_w_t, CCH, T> const& s)
  783. {
  784. return s.data();
  785. }
  786. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  787. /** \ref group__concept__shim__string_access__c_str_data for stlsoft::basic_static_string
  788. *
  789. * \ingroup group__concept__shim__string_access
  790. */
  791. template< ss_typename_param_k C
  792. , ss_size_t CCH
  793. , ss_typename_param_k T
  794. >
  795. inline C const* c_str_data(stlsoft_ns_qual(basic_static_string)<C, CCH, T> const& s)
  796. {
  797. return s.data();
  798. }
  799. // c_str_len
  800. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  801. template <ss_size_t CCH, ss_typename_param_k T >
  802. inline ss_size_t c_str_len_a(stlsoft_ns_qual(basic_static_string)<ss_char_a_t, CCH, T> const& s)
  803. {
  804. return s.length();
  805. }
  806. template <ss_size_t CCH, ss_typename_param_k T >
  807. inline ss_size_t c_str_len_w(stlsoft_ns_qual(basic_static_string)<ss_char_w_t, CCH, T> const& s)
  808. {
  809. return s.length();
  810. }
  811. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  812. /** \ref group__concept__shim__string_access__c_str_len for stlsoft::basic_static_string
  813. *
  814. * \ingroup group__concept__shim__string_access
  815. */
  816. template< ss_typename_param_k C
  817. , ss_size_t CCH
  818. , ss_typename_param_k T
  819. >
  820. inline ss_size_t c_str_len(stlsoft_ns_qual(basic_static_string)<C, CCH, T> const& s)
  821. {
  822. return s.length();
  823. }
  824. #endif /* !STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED */
  825. /** \ref group__concept__shim__stream_insertion "stream insertion shim" for stlsoft::basic_static_string
  826. *
  827. * \ingroup group__concept__shim__stream_insertion
  828. */
  829. template< ss_typename_param_k S
  830. , ss_typename_param_k C
  831. , ss_size_t CCH
  832. , ss_typename_param_k T
  833. >
  834. inline S& operator <<(S& s, stlsoft_ns_qual(basic_static_string)<C, CCH, T> const& str)
  835. {
  836. s << str.c_str();
  837. return s;
  838. }
  839. /* /////////////////////////////////////////////////////////////////////////
  840. * Unit-testing
  841. */
  842. #ifdef STLSOFT_UNITTEST
  843. # include "./unittest/static_string_unittest_.h"
  844. #endif /* STLSOFT_UNITTEST */
  845. /* /////////////////////////////////////////////////////////////////////////
  846. * Implementation
  847. */
  848. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  849. template< ss_typename_param_k C
  850. , ss_size_t CCH
  851. , ss_typename_param_k T
  852. >
  853. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::size_type basic_static_string<C, CCH, T>::length_() const
  854. {
  855. if(m_length == static_cast<ss_size_t>(-1))
  856. {
  857. ss_size_t &_m_length = const_cast<class_type *>(this)->m_length;
  858. _m_length = traits_type::length(m_buffer);
  859. }
  860. return m_length;
  861. }
  862. template< ss_typename_param_k C
  863. , ss_size_t CCH
  864. , ss_typename_param_k T
  865. >
  866. inline ss_bool_t basic_static_string<C, CCH, T>::is_valid() const
  867. {
  868. char_type const* b = &m_buffer[0];
  869. char_type const* const e = &m_buffer[STLSOFT_NUM_ELEMENTS(m_buffer) - 1];
  870. for(; b != e && '\0' != *b; ++b)
  871. {}
  872. if(b == e)
  873. {
  874. #ifdef STLSOFT_UNITTEST
  875. printf("%08x: string contents have been overwritten! Contents=[%*s]\n", static_cast<unsigned>(reinterpret_cast<ss_size_t>(this)), static_cast<int>(max_size()), &m_buffer[0]);
  876. #endif /* STLSOFT_UNITTEST */
  877. return false;
  878. }
  879. else if(m_length != static_cast<ss_size_t>(-1) &&
  880. m_length > max_size())
  881. {
  882. #ifdef STLSOFT_UNITTEST
  883. printf("%08x: length (%ld) greater than maximum allowed (%ld)\n", static_cast<unsigned>(reinterpret_cast<ss_size_t>(this)), static_cast<long>(m_length), static_cast<long>(max_size()));
  884. #endif /* STLSOFT_UNITTEST */
  885. return false;
  886. }
  887. else if(m_length != static_cast<ss_size_t>(-1) &&
  888. '\0' != m_buffer[m_length])
  889. {
  890. #ifdef STLSOFT_UNITTEST
  891. printf("%08x: string not nul-terminated at index (%ld); maximum allowed (%ld)\n", static_cast<unsigned>(reinterpret_cast<ss_size_t>(this)), static_cast<long>(m_length), static_cast<long>(max_size()));
  892. #endif /* STLSOFT_UNITTEST */
  893. return false;
  894. }
  895. return true;
  896. }
  897. template< ss_typename_param_k C
  898. , ss_size_t CCH
  899. , ss_typename_param_k T
  900. >
  901. inline basic_static_string<C, CCH, T>::basic_static_string()
  902. : m_length(static_cast<ss_size_t>(-1))
  903. {
  904. m_buffer[0] = '\0';
  905. m_buffer[max_size()] = '\0';
  906. STLSOFT_ASSERT(is_valid());
  907. }
  908. template< ss_typename_param_k C
  909. , ss_size_t CCH
  910. , ss_typename_param_k T
  911. >
  912. inline basic_static_string<C, CCH, T>::basic_static_string(class_type const& rhs)
  913. : m_length(rhs.length())
  914. {
  915. traits_type::copy(m_buffer, rhs.m_buffer, rhs.length());
  916. m_buffer[m_length] = '\0';
  917. m_buffer[max_size()] = '\0';
  918. STLSOFT_ASSERT(is_valid());
  919. #ifdef _DEBUG
  920. //printf("*this(%s, %d)\n", &m_buffer[0], m_length);
  921. #endif /* _DEBUG */
  922. }
  923. template< ss_typename_param_k C
  924. , ss_size_t CCH
  925. , ss_typename_param_k T
  926. >
  927. inline basic_static_string<C, CCH, T>::basic_static_string(class_type const& rhs, size_type pos)
  928. : m_length(rhs.length() - pos)
  929. {
  930. traits_type::copy(m_buffer, rhs.m_buffer + pos, m_length);
  931. m_buffer[m_length] = '\0';
  932. m_buffer[max_size()] = '\0';
  933. STLSOFT_ASSERT(is_valid());
  934. }
  935. template< ss_typename_param_k C
  936. , ss_size_t CCH
  937. , ss_typename_param_k T
  938. >
  939. inline basic_static_string<C, CCH, T>::basic_static_string(class_type const& rhs, size_type pos, size_type n)
  940. : m_length(n)
  941. {
  942. STLSOFT_MESSAGE_ASSERT("incident string too large for static_string construction", !(max_size() < n));
  943. //printf("ctor(%s, %d, %d = %.*s)\n", rhs.c_str(), pos, n, n, rhs.c_str() + pos);
  944. traits_type::copy(m_buffer, rhs.m_buffer + pos, n);
  945. m_buffer[m_length] = '\0';
  946. m_buffer[max_size()] = '\0';
  947. STLSOFT_ASSERT(is_valid());
  948. }
  949. template< ss_typename_param_k C
  950. , ss_size_t CCH
  951. , ss_typename_param_k T
  952. >
  953. inline basic_static_string<C, CCH, T>::basic_static_string(char_type const* s)
  954. : m_length((NULL != s) ? traits_type::length(s) : 0)
  955. {
  956. STLSOFT_MESSAGE_ASSERT("incident string too large for static_string construction", !(max_size() < m_length));
  957. //printf("Length: %u\n", m_length);
  958. traits_type::copy(m_buffer, s, m_length);
  959. m_buffer[m_length] = '\0';
  960. m_buffer[max_size()] = '\0';
  961. STLSOFT_ASSERT(is_valid());
  962. }
  963. template< ss_typename_param_k C
  964. , ss_size_t CCH
  965. , ss_typename_param_k T
  966. >
  967. inline basic_static_string<C, CCH, T>::basic_static_string(char_type const* s, size_type n)
  968. : m_length(n)
  969. {
  970. STLSOFT_MESSAGE_ASSERT("incident string too large for static_string construction", !(max_size() < n));
  971. traits_type::copy(m_buffer, s, n);
  972. m_buffer[m_length] = '\0';
  973. m_buffer[max_size()] = '\0';
  974. STLSOFT_ASSERT(is_valid());
  975. }
  976. template< ss_typename_param_k C
  977. , ss_size_t CCH
  978. , ss_typename_param_k T
  979. >
  980. inline basic_static_string<C, CCH, T>::basic_static_string(size_type n, char_type c)
  981. : m_length(n)
  982. {
  983. traits_type::assign(m_buffer, n, c);
  984. m_buffer[m_length] = '\0';
  985. m_buffer[max_size()] = '\0';
  986. STLSOFT_ASSERT(is_valid());
  987. }
  988. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  989. template< ss_typename_param_k C
  990. , ss_size_t CCH
  991. , ss_typename_param_k T
  992. >
  993. inline basic_static_string<C, CCH, T>::basic_static_string(char_type const* f, char_type const* t)
  994. : m_length(t - f)
  995. {
  996. STLSOFT_MESSAGE_ASSERT("incident string too large for static_string construction", !(max_size() < m_length));
  997. traits_type::copy(m_buffer, f, m_length);
  998. m_buffer[m_length] = '\0';
  999. m_buffer[max_size()] = '\0';
  1000. STLSOFT_ASSERT(is_valid());
  1001. }
  1002. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  1003. template< ss_typename_param_k C
  1004. , ss_size_t CCH
  1005. , ss_typename_param_k T
  1006. >
  1007. inline basic_static_string<C, CCH, T>::~basic_static_string() stlsoft_throw_0()
  1008. {
  1009. STLSOFT_ASSERT(is_valid());
  1010. }
  1011. // Assignment
  1012. template< ss_typename_param_k C
  1013. , ss_size_t CCH
  1014. , ss_typename_param_k T
  1015. >
  1016. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::assign(const ss_typename_type_k basic_static_string<C, CCH, T>::char_type *s)
  1017. {
  1018. STLSOFT_ASSERT(is_valid());
  1019. #if 0
  1020. m_length = static_cast<ss_size_t>(-1);
  1021. traits_type::copy(m_buffer, s, CCH);
  1022. m_buffer[max_size()] = '\0';
  1023. #else /* ? 0 */
  1024. class_type t(s);
  1025. t.swap(*this);
  1026. #endif /* 0 */
  1027. STLSOFT_ASSERT(is_valid());
  1028. return *this;
  1029. }
  1030. template< ss_typename_param_k C
  1031. , ss_size_t CCH
  1032. , ss_typename_param_k T
  1033. >
  1034. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::assign(const ss_typename_type_k basic_static_string<C, CCH, T>::char_type *s, ss_typename_type_k basic_static_string<C, CCH, T>::size_type n)
  1035. {
  1036. STLSOFT_MESSAGE_ASSERT("incident string too large for static_string assignment", !(max_size() < n));
  1037. STLSOFT_ASSERT(is_valid());
  1038. #if 0
  1039. traits_type::copy(m_buffer, s, n);
  1040. m_length = n;
  1041. m_buffer[m_length] = '\0';
  1042. m_buffer[max_size()] = '\0';
  1043. #else /* ? 0 */
  1044. class_type t(s, n);
  1045. t.swap(*this);
  1046. #endif /* 0 */
  1047. STLSOFT_ASSERT(is_valid());
  1048. return *this;
  1049. }
  1050. template< ss_typename_param_k C
  1051. , ss_size_t CCH
  1052. , ss_typename_param_k T
  1053. >
  1054. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::assign( ss_typename_type_k basic_static_string<C, CCH, T>::class_type const& rhs
  1055. , ss_typename_type_k basic_static_string<C, CCH, T>::size_type pos
  1056. , ss_typename_type_k basic_static_string<C, CCH, T>::size_type n)
  1057. {
  1058. STLSOFT_MESSAGE_ASSERT("incident string too large for static_string assignment", !(max_size() < n));
  1059. STLSOFT_ASSERT(is_valid());
  1060. #if 0
  1061. traits_type::copy(m_buffer, rhs.m_buffer + pos, n);
  1062. m_length = n;
  1063. m_buffer[m_length] = '\0';
  1064. m_buffer[max_size()] = '\0';
  1065. #else /* ? 0 */
  1066. class_type t(rhs, pos, n);
  1067. t.swap(*this);
  1068. #endif /* 0 */
  1069. STLSOFT_ASSERT(is_valid());
  1070. return *this;
  1071. }
  1072. template< ss_typename_param_k C
  1073. , ss_size_t CCH
  1074. , ss_typename_param_k T
  1075. >
  1076. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::assign(ss_typename_type_k basic_static_string<C, CCH, T>::class_type const& rhs)
  1077. {
  1078. STLSOFT_ASSERT(is_valid());
  1079. //printf("1\n");
  1080. #ifdef _DEBUG
  1081. const class_type result(rhs);
  1082. #endif /* _DEBUG */
  1083. //printf("2\n");
  1084. //printf("assign(%s, %d)\n", rhs.c_str(), rhs.length());
  1085. class_type t(rhs);
  1086. //printf("3\n");
  1087. t.swap(*this);
  1088. //printf("4\n");
  1089. //printf("5\n");
  1090. #ifdef _DEBUG
  1091. //printf("result(%s, %d); rhs(%s, %d); t(%s, %d), *this(%s, %d)\n", result.c_str(), result.length(), rhs.c_str(), rhs.length(), t.c_str(), t.length(), c_str(), length());
  1092. STLSOFT_ASSERT(result == *this);
  1093. #endif /* _DEBUG */
  1094. //printf("6\n");
  1095. STLSOFT_ASSERT(is_valid());
  1096. //printf("7\n");
  1097. return *this;
  1098. }
  1099. template< ss_typename_param_k C
  1100. , ss_size_t CCH
  1101. , ss_typename_param_k T
  1102. >
  1103. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::assign( ss_typename_type_k basic_static_string<C, CCH, T>::size_type n
  1104. , ss_typename_type_k basic_static_string<C, CCH, T>::char_type c)
  1105. {
  1106. STLSOFT_MESSAGE_ASSERT("incident string too large for static_string assignment", !(max_size() < n));
  1107. STLSOFT_ASSERT(is_valid());
  1108. #if 0
  1109. traits_type::assign(m_buffer, n, c);
  1110. m_length = n;
  1111. m_buffer[m_length] = '\0';
  1112. m_buffer[max_size()] = '\0';
  1113. #else /* ? 0 */
  1114. class_type t(n, c);
  1115. t.swap(*this);
  1116. #endif /* 0 */
  1117. STLSOFT_ASSERT(is_valid());
  1118. return *this;
  1119. }
  1120. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  1121. template< ss_typename_param_k C
  1122. , ss_size_t CCH
  1123. , ss_typename_param_k T
  1124. >
  1125. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::assign(ss_typename_type_k basic_static_string<C, CCH, T>::const_iterator first, ss_typename_type_k basic_static_string<C, CCH, T>::const_iterator last)
  1126. {
  1127. STLSOFT_ASSERT(is_valid());
  1128. // We have to use this strange appearing this, because of Visual C++ .NET's
  1129. // disgusting STL swill. Sigh!
  1130. return assign(&(*first), last - first);
  1131. }
  1132. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  1133. template< ss_typename_param_k C
  1134. , ss_size_t CCH
  1135. , ss_typename_param_k T
  1136. >
  1137. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type const& basic_static_string<C, CCH, T>::operator =(ss_typename_type_k basic_static_string<C, CCH, T>::class_type const& rhs)
  1138. {
  1139. STLSOFT_ASSERT(is_valid());
  1140. return assign(rhs);
  1141. }
  1142. template< ss_typename_param_k C
  1143. , ss_size_t CCH
  1144. , ss_typename_param_k T
  1145. >
  1146. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type const& basic_static_string<C, CCH, T>::operator =(ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* s)
  1147. {
  1148. STLSOFT_ASSERT(is_valid());
  1149. return assign(s);
  1150. }
  1151. template< ss_typename_param_k C
  1152. , ss_size_t CCH
  1153. , ss_typename_param_k T
  1154. >
  1155. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type const& basic_static_string<C, CCH, T>::operator =(ss_typename_type_k basic_static_string<C, CCH, T>::char_type c)
  1156. {
  1157. STLSOFT_ASSERT(is_valid());
  1158. m_length = 1;
  1159. m_buffer[0] = c;
  1160. m_buffer[1] = c;
  1161. STLSOFT_ASSERT(is_valid());
  1162. return *this;
  1163. }
  1164. template< ss_typename_param_k C
  1165. , ss_size_t CCH
  1166. , ss_typename_param_k T
  1167. >
  1168. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::size_type basic_static_string<C, CCH, T>::size() const
  1169. {
  1170. return class_type::length();
  1171. }
  1172. template< ss_typename_param_k C
  1173. , ss_size_t CCH
  1174. , ss_typename_param_k T
  1175. >
  1176. inline /* static */ ss_typename_type_ret_k basic_static_string<C, CCH, T>::size_type basic_static_string<C, CCH, T>::max_size()
  1177. {
  1178. return internalSize;
  1179. }
  1180. template< ss_typename_param_k C
  1181. , ss_size_t CCH
  1182. , ss_typename_param_k T
  1183. >
  1184. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::size_type basic_static_string<C, CCH, T>::length() const
  1185. {
  1186. STLSOFT_ASSERT(is_valid());
  1187. return length_();
  1188. }
  1189. template< ss_typename_param_k C
  1190. , ss_size_t CCH
  1191. , ss_typename_param_k T
  1192. >
  1193. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::size_type basic_static_string<C, CCH, T>::capacity() const
  1194. {
  1195. STLSOFT_ASSERT(is_valid());
  1196. return class_type::max_size();
  1197. }
  1198. template< ss_typename_param_k C
  1199. , ss_size_t CCH
  1200. , ss_typename_param_k T
  1201. >
  1202. inline ss_bool_t basic_static_string<C, CCH, T>::empty() const
  1203. {
  1204. STLSOFT_ASSERT(is_valid());
  1205. return m_buffer[0] == 0;
  1206. }
  1207. template< ss_typename_param_k C
  1208. , ss_size_t CCH
  1209. , ss_typename_param_k T
  1210. >
  1211. inline /* static */ ss_sint_t basic_static_string<C, CCH, T>::compare_( ss_typename_type_k basic_static_string<C, CCH, T>::value_type const* lhs
  1212. , ss_typename_type_k basic_static_string<C, CCH, T>::size_type lhs_len
  1213. , ss_typename_type_k basic_static_string<C, CCH, T>::value_type const* rhs
  1214. , ss_typename_type_k basic_static_string<C, CCH, T>::size_type rhs_len)
  1215. {
  1216. size_type cmp_len = (lhs_len < rhs_len) ? lhs_len : rhs_len;
  1217. ss_int_t result = traits_type::compare(lhs, rhs, cmp_len);
  1218. if(result == 0)
  1219. {
  1220. result = static_cast<ss_int_t>(lhs_len) - static_cast<ss_int_t>(rhs_len);
  1221. }
  1222. #ifdef _DEBUG
  1223. //printf("compare_(\"%*s\",%d\n ,\"%*s\",%d) == %d\n", lhs_len, lhs, lhs_len, rhs_len, rhs, rhs_len, result);
  1224. #endif /* _DEBUG */
  1225. return result;
  1226. }
  1227. template< ss_typename_param_k C
  1228. , ss_size_t CCH
  1229. , ss_typename_param_k T
  1230. >
  1231. inline ss_sint_t basic_static_string<C, CCH, T>::compare(ss_typename_type_k basic_static_string<C, CCH, T>::size_type pos, ss_typename_type_k basic_static_string<C, CCH, T>::size_type cch, ss_typename_type_k basic_static_string<C, CCH, T>::value_type const* s, ss_typename_type_k basic_static_string<C, CCH, T>::size_type cchRhs) const
  1232. {
  1233. STLSOFT_ASSERT(is_valid());
  1234. size_type lhs_len = length();
  1235. if(!(pos < lhs_len))
  1236. {
  1237. pos = lhs_len;
  1238. }
  1239. else
  1240. {
  1241. lhs_len -= pos;
  1242. }
  1243. if(cch < lhs_len)
  1244. {
  1245. lhs_len = cch;
  1246. }
  1247. size_type rhs_len = (s == 0) ? 0 : traits_type::length(s);
  1248. if(cchRhs < rhs_len)
  1249. {
  1250. rhs_len = cchRhs;
  1251. }
  1252. STLSOFT_ASSERT(is_valid());
  1253. return compare_(m_buffer + pos, lhs_len, s, rhs_len);
  1254. }
  1255. template< ss_typename_param_k C
  1256. , ss_size_t CCH
  1257. , ss_typename_param_k T
  1258. >
  1259. inline ss_sint_t basic_static_string<C, CCH, T>::compare(ss_typename_type_k basic_static_string<C, CCH, T>::size_type pos, ss_typename_type_k basic_static_string<C, CCH, T>::size_type cch, ss_typename_type_k basic_static_string<C, CCH, T>::value_type const* s) const
  1260. {
  1261. STLSOFT_ASSERT(is_valid());
  1262. size_type lhs_len = length();
  1263. if(!(pos < lhs_len))
  1264. {
  1265. pos = lhs_len;
  1266. }
  1267. else
  1268. {
  1269. lhs_len -= pos;
  1270. }
  1271. if(cch < lhs_len)
  1272. {
  1273. lhs_len = cch;
  1274. }
  1275. size_type rhs_len = (s == 0) ? 0 : traits_type::length(s);
  1276. STLSOFT_ASSERT(is_valid());
  1277. return compare_(m_buffer + pos, lhs_len, s, rhs_len);
  1278. }
  1279. template< ss_typename_param_k C
  1280. , ss_size_t CCH
  1281. , ss_typename_param_k T
  1282. >
  1283. inline ss_sint_t basic_static_string<C, CCH, T>::compare(ss_typename_type_k basic_static_string<C, CCH, T>::value_type const* s) const
  1284. {
  1285. STLSOFT_ASSERT(is_valid());
  1286. size_type lhs_len = length();
  1287. size_type rhs_len = (s == 0) ? 0 : traits_type::length(s);
  1288. STLSOFT_ASSERT(is_valid());
  1289. return compare_(m_buffer, lhs_len, s, rhs_len);
  1290. }
  1291. template< ss_typename_param_k C
  1292. , ss_size_t CCH
  1293. , ss_typename_param_k T
  1294. >
  1295. inline ss_sint_t basic_static_string<C, CCH, T>::compare(ss_typename_type_k basic_static_string<C, CCH, T>::size_type pos, ss_typename_type_k basic_static_string<C, CCH, T>::size_type cch, ss_typename_type_k basic_static_string<C, CCH, T>::class_type const& rhs, ss_typename_type_k basic_static_string<C, CCH, T>::size_type posRhs, ss_typename_type_k basic_static_string<C, CCH, T>::size_type cchRhs) const
  1296. {
  1297. STLSOFT_ASSERT(is_valid());
  1298. size_type lhs_len = length();
  1299. if(!(pos < lhs_len))
  1300. {
  1301. pos = lhs_len;
  1302. }
  1303. else
  1304. {
  1305. lhs_len -= pos;
  1306. }
  1307. if(cch < lhs_len)
  1308. {
  1309. lhs_len = cch;
  1310. }
  1311. size_type rhs_len = rhs.length();
  1312. if(!(posRhs < rhs_len))
  1313. {
  1314. posRhs = rhs_len;
  1315. }
  1316. else
  1317. {
  1318. rhs_len -= posRhs;
  1319. }
  1320. if(cchRhs < rhs_len)
  1321. {
  1322. rhs_len = cchRhs;
  1323. }
  1324. STLSOFT_ASSERT(is_valid());
  1325. return compare_(m_buffer + pos, lhs_len, rhs.m_buffer + posRhs, rhs_len);
  1326. }
  1327. template< ss_typename_param_k C
  1328. , ss_size_t CCH
  1329. , ss_typename_param_k T
  1330. >
  1331. inline ss_sint_t basic_static_string<C, CCH, T>::compare(ss_typename_type_k basic_static_string<C, CCH, T>::size_type pos, ss_typename_type_k basic_static_string<C, CCH, T>::size_type cch, ss_typename_type_k basic_static_string<C, CCH, T>::class_type const& rhs) const
  1332. {
  1333. STLSOFT_ASSERT(is_valid());
  1334. size_type lhs_len = length();
  1335. if(!(pos < lhs_len))
  1336. {
  1337. pos = lhs_len;
  1338. }
  1339. else
  1340. {
  1341. lhs_len -= pos;
  1342. }
  1343. if(cch < lhs_len)
  1344. {
  1345. lhs_len = cch;
  1346. }
  1347. size_type rhs_len = rhs.length();
  1348. STLSOFT_ASSERT(is_valid());
  1349. return compare_(m_buffer + pos, lhs_len, rhs.m_buffer, rhs_len);
  1350. }
  1351. template< ss_typename_param_k C
  1352. , ss_size_t CCH
  1353. , ss_typename_param_k T
  1354. >
  1355. inline ss_sint_t basic_static_string<C, CCH, T>::compare(ss_typename_type_k basic_static_string<C, CCH, T>::class_type const& rhs) const
  1356. {
  1357. STLSOFT_ASSERT(is_valid());
  1358. size_type lhs_len = length();
  1359. size_type rhs_len = rhs.length();
  1360. STLSOFT_ASSERT(is_valid());
  1361. #ifdef _DEBUG
  1362. //printf("Comparing (\"%*s\",%d; \"%*s\",%d)\n", lhs_len, &m_buffer[0], lhs_len, rhs_len, &rhs.m_buffer[0], rhs_len);
  1363. #endif /* _DEBUG */
  1364. return compare_(&m_buffer[0], lhs_len, &rhs.m_buffer[0], rhs_len);
  1365. }
  1366. template< ss_typename_param_k C
  1367. , ss_size_t CCH
  1368. , ss_typename_param_k T
  1369. >
  1370. inline void basic_static_string<C, CCH, T>::resize( ss_typename_type_k basic_static_string<C, CCH, T>::size_type n
  1371. , ss_typename_type_k basic_static_string<C, CCH, T>::value_type ch /* = value_type() */)
  1372. {
  1373. STLSOFT_MESSAGE_ASSERT("resize request too large for static_string", !(max_size() < n));
  1374. STLSOFT_ASSERT(is_valid());
  1375. size_type const len = length();
  1376. if(len != n)
  1377. {
  1378. if(len < n)
  1379. {
  1380. traits_type::assign(m_buffer + len, n - len, ch);
  1381. }
  1382. m_length = n;
  1383. m_buffer[n] = 0;
  1384. }
  1385. STLSOFT_ASSERT(is_valid());
  1386. }
  1387. template< ss_typename_param_k C
  1388. , ss_size_t CCH
  1389. , ss_typename_param_k T
  1390. >
  1391. inline void basic_static_string<C, CCH, T>::clear()
  1392. {
  1393. STLSOFT_ASSERT(is_valid());
  1394. m_length = static_cast<ss_size_t>(-1);
  1395. m_buffer[0] = 0;
  1396. STLSOFT_ASSERT(is_valid());
  1397. }
  1398. template< ss_typename_param_k C
  1399. , ss_size_t CCH
  1400. , ss_typename_param_k T
  1401. >
  1402. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::reference basic_static_string<C, CCH, T>::operator [](ss_typename_type_k basic_static_string<C, CCH, T>::size_type index)
  1403. {
  1404. STLSOFT_MESSAGE_ASSERT("index access out of range in static_string", index < size());
  1405. STLSOFT_ASSERT(is_valid());
  1406. return m_buffer[index];
  1407. }
  1408. template< ss_typename_param_k C
  1409. , ss_size_t CCH
  1410. , ss_typename_param_k T
  1411. >
  1412. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::const_reference basic_static_string<C, CCH, T>::operator [](ss_typename_type_k basic_static_string<C, CCH, T>::size_type index) const
  1413. {
  1414. STLSOFT_MESSAGE_ASSERT("index access out of range in static_string", index < size() + 1); // Valid to return (const) reference to nul-terminator
  1415. STLSOFT_ASSERT(is_valid());
  1416. return m_buffer[index];
  1417. }
  1418. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1419. template< ss_typename_param_k C
  1420. , ss_size_t CCH
  1421. , ss_typename_param_k T
  1422. >
  1423. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::reference basic_static_string<C, CCH, T>::at(ss_typename_type_k basic_static_string<C, CCH, T>::size_type index)
  1424. {
  1425. STLSOFT_ASSERT(is_valid());
  1426. if(index >= size())
  1427. {
  1428. STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("index out of range"));
  1429. }
  1430. STLSOFT_ASSERT(is_valid());
  1431. return m_buffer[index];
  1432. }
  1433. template< ss_typename_param_k C
  1434. , ss_size_t CCH
  1435. , ss_typename_param_k T
  1436. >
  1437. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::const_reference basic_static_string<C, CCH, T>::at(ss_typename_type_k basic_static_string<C, CCH, T>::size_type index) const
  1438. {
  1439. STLSOFT_ASSERT(is_valid());
  1440. if(index > size())
  1441. {
  1442. STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("index out of range"));
  1443. }
  1444. STLSOFT_ASSERT(is_valid());
  1445. return m_buffer[index];
  1446. }
  1447. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
  1448. template< ss_typename_param_k C
  1449. , ss_size_t CCH
  1450. , ss_typename_param_k T
  1451. >
  1452. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::value_type const* basic_static_string<C, CCH, T>::c_str() const
  1453. {
  1454. STLSOFT_ASSERT(is_valid());
  1455. return m_buffer;
  1456. }
  1457. // Appending
  1458. template< ss_typename_param_k C
  1459. , ss_size_t CCH
  1460. , ss_typename_param_k T
  1461. >
  1462. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::append( ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* s
  1463. , ss_typename_type_k basic_static_string<C, CCH, T>::size_type n)
  1464. {
  1465. STLSOFT_MESSAGE_ASSERT("resize request too large for static_string", !(max_size() < n + length()));
  1466. STLSOFT_ASSERT(is_valid());
  1467. if(0 != n)
  1468. {
  1469. traits_type::copy(m_buffer + m_length, s, n);
  1470. m_length += n;
  1471. m_buffer[m_length] = 0;
  1472. }
  1473. STLSOFT_ASSERT(is_valid());
  1474. return *this;
  1475. }
  1476. template< ss_typename_param_k C
  1477. , ss_size_t CCH
  1478. , ss_typename_param_k T
  1479. >
  1480. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::append(ss_typename_type_k basic_static_string<C, CCH, T>::char_type const* s)
  1481. {
  1482. STLSOFT_ASSERT(is_valid());
  1483. return append(s, (NULL == s) ? 0 : traits_type::length(s));
  1484. }
  1485. template< ss_typename_param_k C
  1486. , ss_size_t CCH
  1487. , ss_typename_param_k T
  1488. >
  1489. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::append( ss_typename_type_k basic_static_string<C, CCH, T>::class_type const& rhs
  1490. , ss_typename_type_k basic_static_string<C, CCH, T>::size_type pos
  1491. , ss_typename_type_k basic_static_string<C, CCH, T>::size_type cch)
  1492. {
  1493. STLSOFT_ASSERT(is_valid());
  1494. char_type const* s = rhs.m_buffer;
  1495. size_type len = rhs.length();
  1496. if(len < pos)
  1497. {
  1498. pos = len;
  1499. }
  1500. if(len - pos < cch)
  1501. {
  1502. cch = len - pos;
  1503. }
  1504. if(NULL != s)
  1505. {
  1506. s += pos;
  1507. }
  1508. else
  1509. {
  1510. cch = 0;
  1511. }
  1512. STLSOFT_ASSERT(is_valid());
  1513. return append(s, cch);
  1514. }
  1515. template< ss_typename_param_k C
  1516. , ss_size_t CCH
  1517. , ss_typename_param_k T
  1518. >
  1519. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::append(ss_typename_type_k basic_static_string<C, CCH, T>::class_type const& s)
  1520. {
  1521. STLSOFT_ASSERT(is_valid());
  1522. return append(s.m_buffer, s.length());
  1523. }
  1524. template< ss_typename_param_k C
  1525. , ss_size_t CCH
  1526. , ss_typename_param_k T
  1527. >
  1528. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::append( ss_typename_type_k basic_static_string<C, CCH, T>::size_type n
  1529. , ss_typename_type_k basic_static_string<C, CCH, T>::char_type ch)
  1530. {
  1531. STLSOFT_MESSAGE_ASSERT("resize request too large for static_string", !(max_size() < n + length()));
  1532. //printf("append(pre): *this(%*s)\n", m_length, &m_buffer[0]);
  1533. STLSOFT_ASSERT(is_valid());
  1534. if(0 != n)
  1535. {
  1536. traits_type::assign(m_buffer + m_length, n, ch);
  1537. m_length += n;
  1538. m_buffer[m_length] = 0;
  1539. }
  1540. //printf("append(post): *this(%*s)\n", m_length, &m_buffer[0]);
  1541. STLSOFT_ASSERT(is_valid());
  1542. return *this;
  1543. }
  1544. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
  1545. template< ss_typename_param_k C
  1546. , ss_size_t CCH
  1547. , ss_typename_param_k T
  1548. >
  1549. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::append( ss_typename_type_k basic_static_string<C, CCH, T>::const_iterator first
  1550. , ss_typename_type_k basic_static_string<C, CCH, T>::const_iterator last)
  1551. {
  1552. STLSOFT_ASSERT(is_valid());
  1553. // We have to use this strange appearing form, because of Visual C++ .NET's
  1554. // disgusting STL swill. Sigh!
  1555. return append(&(*first), last - first);
  1556. }
  1557. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
  1558. template< ss_typename_param_k C
  1559. , ss_size_t CCH
  1560. , ss_typename_param_k T
  1561. >
  1562. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::operator +=(ss_typename_type_k basic_static_string<C, CCH, T>::char_type ch)
  1563. {
  1564. STLSOFT_ASSERT(is_valid());
  1565. return append(1, ch);
  1566. }
  1567. template< ss_typename_param_k C
  1568. , ss_size_t CCH
  1569. , ss_typename_param_k T
  1570. >
  1571. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::operator +=(const ss_typename_type_k basic_static_string<C, CCH, T>::char_type *s)
  1572. {
  1573. STLSOFT_ASSERT(is_valid());
  1574. return append(s);
  1575. }
  1576. template< ss_typename_param_k C
  1577. , ss_size_t CCH
  1578. , ss_typename_param_k T
  1579. >
  1580. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::class_type& basic_static_string<C, CCH, T>::operator +=(const ss_typename_type_k basic_static_string<C, CCH, T>::class_type& rhs)
  1581. {
  1582. STLSOFT_ASSERT(is_valid());
  1583. return append(rhs);
  1584. }
  1585. template< ss_typename_param_k C
  1586. , ss_size_t CCH
  1587. , ss_typename_param_k T
  1588. >
  1589. inline void basic_static_string<C, CCH, T>::push_back(ss_typename_type_k basic_static_string<C, CCH, T>::char_type ch)
  1590. {
  1591. STLSOFT_ASSERT(is_valid());
  1592. append(1, ch);
  1593. }
  1594. template< ss_typename_param_k C
  1595. , ss_size_t CCH
  1596. , ss_typename_param_k T
  1597. >
  1598. inline void basic_static_string<C, CCH, T>::pop_back()
  1599. {
  1600. STLSOFT_ASSERT(is_valid());
  1601. if (m_length != 0) {
  1602. m_buffer[--m_length] = 0;
  1603. }
  1604. }
  1605. template< ss_typename_param_k C
  1606. , ss_size_t CCH
  1607. , ss_typename_param_k T
  1608. >
  1609. inline void basic_static_string<C, CCH, T>::reserve(ss_typename_type_k basic_static_string<C, CCH, T>::size_type n)
  1610. {
  1611. STLSOFT_ASSERT(is_valid());
  1612. STLSOFT_MESSAGE_ASSERT("reserve request out of range in static_string", !(max_size() < n));
  1613. STLSOFT_SUPPRESS_UNUSED(n);
  1614. }
  1615. template< ss_typename_param_k C
  1616. , ss_size_t CCH
  1617. , ss_typename_param_k T
  1618. >
  1619. inline void basic_static_string<C, CCH, T>::swap(ss_typename_type_k basic_static_string<C, CCH, T>::class_type& other)
  1620. {
  1621. //printf("swap-1\n");
  1622. STLSOFT_ASSERT(is_valid());
  1623. //printf("swap-2\n");
  1624. value_type buffer[internalSize];
  1625. //printf("swap-3\n");
  1626. traits_type::copy( buffer, other.m_buffer, 1 + other.m_length);
  1627. traits_type::copy(other.m_buffer, m_buffer, 1 + m_length);
  1628. traits_type::copy( m_buffer, buffer, 1 + other.m_length);
  1629. //printf("swap-4\n");
  1630. std_swap(m_length, other.m_length);
  1631. //printf("swap-5\n");
  1632. STLSOFT_ASSERT(is_valid());
  1633. }
  1634. template< ss_typename_param_k C
  1635. , ss_size_t CCH
  1636. , ss_typename_param_k T
  1637. >
  1638. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::value_type const* basic_static_string<C, CCH, T>::data() const
  1639. {
  1640. STLSOFT_ASSERT(is_valid());
  1641. return m_buffer;
  1642. }
  1643. template< ss_typename_param_k C
  1644. , ss_size_t CCH
  1645. , ss_typename_param_k T
  1646. >
  1647. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::size_type basic_static_string<C, CCH, T>::copy(ss_typename_type_k basic_static_string<C, CCH, T>::value_type *dest, ss_typename_type_k basic_static_string<C, CCH, T>::size_type cch_, ss_typename_type_k basic_static_string<C, CCH, T>::size_type pos /* = 0 */) const
  1648. {
  1649. STLSOFT_ASSERT(is_valid());
  1650. size_type len = length();
  1651. if(pos < len)
  1652. {
  1653. if(len < pos + cch_)
  1654. {
  1655. cch_ = len - pos;
  1656. }
  1657. traits_type::copy(dest, data() + pos, cch_);
  1658. }
  1659. else
  1660. {
  1661. cch_ = 0;
  1662. }
  1663. STLSOFT_ASSERT(is_valid());
  1664. return cch_;
  1665. }
  1666. template< ss_typename_param_k C
  1667. , ss_size_t CCH
  1668. , ss_typename_param_k T
  1669. >
  1670. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::const_iterator basic_static_string<C, CCH, T>::begin() const
  1671. {
  1672. STLSOFT_ASSERT(is_valid());
  1673. return m_buffer;
  1674. }
  1675. template< ss_typename_param_k C
  1676. , ss_size_t CCH
  1677. , ss_typename_param_k T
  1678. >
  1679. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::const_iterator basic_static_string<C, CCH, T>::end() const
  1680. {
  1681. STLSOFT_ASSERT(is_valid());
  1682. return m_buffer + length_();
  1683. }
  1684. template< ss_typename_param_k C
  1685. , ss_size_t CCH
  1686. , ss_typename_param_k T
  1687. >
  1688. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::iterator basic_static_string<C, CCH, T>::begin()
  1689. {
  1690. STLSOFT_ASSERT(is_valid());
  1691. return m_buffer;
  1692. }
  1693. template< ss_typename_param_k C
  1694. , ss_size_t CCH
  1695. , ss_typename_param_k T
  1696. >
  1697. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::iterator basic_static_string<C, CCH, T>::end()
  1698. {
  1699. STLSOFT_ASSERT(is_valid());
  1700. return m_buffer + length_();
  1701. }
  1702. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  1703. template< ss_typename_param_k C
  1704. , ss_size_t CCH
  1705. , ss_typename_param_k T
  1706. >
  1707. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::const_reverse_iterator basic_static_string<C, CCH, T>::rbegin() const
  1708. {
  1709. STLSOFT_ASSERT(is_valid());
  1710. return const_reverse_iterator(end());
  1711. }
  1712. template< ss_typename_param_k C
  1713. , ss_size_t CCH
  1714. , ss_typename_param_k T
  1715. >
  1716. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::const_reverse_iterator basic_static_string<C, CCH, T>::rend() const
  1717. {
  1718. STLSOFT_ASSERT(is_valid());
  1719. return const_reverse_iterator(begin());
  1720. }
  1721. template< ss_typename_param_k C
  1722. , ss_size_t CCH
  1723. , ss_typename_param_k T
  1724. >
  1725. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::reverse_iterator basic_static_string<C, CCH, T>::rbegin()
  1726. {
  1727. STLSOFT_ASSERT(is_valid());
  1728. return reverse_iterator(end());
  1729. }
  1730. template< ss_typename_param_k C
  1731. , ss_size_t CCH
  1732. , ss_typename_param_k T
  1733. >
  1734. inline ss_typename_type_ret_k basic_static_string<C, CCH, T>::reverse_iterator basic_static_string<C, CCH, T>::rend()
  1735. {
  1736. STLSOFT_ASSERT(is_valid());
  1737. return reverse_iterator(begin());
  1738. }
  1739. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  1740. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  1741. /* ////////////////////////////////////////////////////////////////////// */
  1742. #ifndef _STLSOFT_NO_NAMESPACE
  1743. } // namespace stlsoft
  1744. #endif /* _STLSOFT_NO_NAMESPACE */
  1745. /* In the special case of Intel behaving as VC++ 7.0 or earlier on Win32, we
  1746. * illegally insert into the std namespace.
  1747. */
  1748. #if defined(STLSOFT_CF_std_NAMESPACE)
  1749. # if ( ( defined(STLSOFT_COMPILER_IS_INTEL) && \
  1750. defined(_MSC_VER))) && \
  1751. _MSC_VER < 1310
  1752. namespace std
  1753. {
  1754. template< ss_typename_param_k C
  1755. , stlsoft_ns_qual(ss_size_t) CCH
  1756. , ss_typename_param_k T
  1757. >
  1758. inline void swap(stlsoft_ns_qual(basic_static_string)<C, CCH, T>& lhs, stlsoft_ns_qual(basic_static_string)<C, CCH, T>& rhs)
  1759. {
  1760. lhs.swap(rhs);
  1761. }
  1762. } // namespace std
  1763. # endif /* INTEL && _MSC_VER < 1310 */
  1764. #endif /* STLSOFT_CF_std_NAMESPACE */
  1765. /* ////////////////////////////////////////////////////////////////////// */
  1766. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_STATIC_STRING */
  1767. /* ///////////////////////////// end of file //////////////////////////// */