STLSoft - ... Robust, Lightweight, Cross-platform, Template Software ... ATLSTL - Template Software for the Active Template Library COMSTL - The Standard Template Library meets the Component Object Model .netSTL - Standard Template Library meets the Microsoft.NET Common Language Runtime InetSTL - The Standard Template Library meets WinInet MFCSTL - Template Software for the Microsoft Foundation Classes UNIXSTL - Template Software for the UNIX Operating System WinSTL - where the Standard Template Library meets the Win32 API

Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

stlsoft_simple_string.h

Go to the documentation of this file.
00001 /* 
00002  * File:        stlsoft_simple_string.h (formerly MSString.h, ::SynesisDev)
00003  *
00004  * Purpose:     simple_string class.
00005  *
00006  * Created:     19th March 1993
00007  * Updated:     11th September 2004
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 1993-2004, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer.
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * 
00039 
00040 
00044 
00045 #ifndef STLSOFT_INCL_H_STLSOFT_SIMPLE_STRING
00046 #define STLSOFT_INCL_H_STLSOFT_SIMPLE_STRING
00047 
00048 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00049 # define STLSOFT_VER_H_STLSOFT_SIMPLE_STRING_MAJOR     2
00050 # define STLSOFT_VER_H_STLSOFT_SIMPLE_STRING_MINOR     0
00051 # define STLSOFT_VER_H_STLSOFT_SIMPLE_STRING_REVISION  1
00052 # define STLSOFT_VER_H_STLSOFT_SIMPLE_STRING_EDIT      152
00053 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00054 
00055 /* 
00056  * Includes
00057  */
00058 
00059 #ifndef STLSOFT_INCL_H_STLSOFT
00060 # include "stlsoft.h"                   // Include the STLSoft root header
00061 #endif /* !STLSOFT_INCL_H_STLSOFT */
00062 #ifndef STLSOFT_INCL_H_STLSOFT_NEW_ALLOCATOR
00063 # include "stlsoft_new_allocator.h"     // stlsoft::new_allocator
00064 #endif /* !STLSOFT_INCL_H_STLSOFT_NEW_ALLOCATOR */
00065 #ifndef STLSOFT_INCL_H_STLSOFT_CHAR_TRAITS
00066 # include "stlsoft_char_traits.h"      // stlsoft::char_traits
00067 #endif /* !STLSOFT_INCL_H_STLSOFT_CHAR_TRAITS */
00068 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00069 # include "stlsoft_iterator.h"          // stlsoft iterator bases
00070 #endif /* !STLSOFT_INCL_H_STLSOFT_ITERATOR */
00071 #ifndef STLSOFT_INCL_H_STLSOFT_AUTO_BUFFER
00072 # include "stlsoft_auto_buffer.h"       // stlsoft::auto_buffer
00073 #endif /* !STLSOFT_INCL_H_STLSOFT_AUTO_BUFFER */
00074 #ifndef STLSOFT_INCL_H_STLSOFT_SIMPLE_ALGORITHMS
00075 # include "stlsoft_simple_algorithms.h" // stlsoft::for_each_set_value
00076 #endif /* !STLSOFT_INCL_H_STLSOFT_SIMPLE_ALGORITHMS */
00077 #ifndef STLSOFT_INCL_H_STLSOFT_SAP_CAST
00078 # include "stlsoft_sap_cast.h"          // stlsoft::sap_cast
00079 #endif /* !STLSOFT_INCL_H_STLSOFT_SAP_CAST */
00080 
00081 /* 
00082  *
00083  */
00084 
00085 #if defined(__STLSOFT_COMPILER_IS_MSVC) && \
00086     _MSC_VER < 1200
00087 # define STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE
00088 #endif /* compiler */
00089 
00090 /* 
00091  * Namespace
00092  */
00093 
00094 #ifndef _STLSOFT_NO_NAMESPACE
00095 namespace stlsoft
00096 {
00097 #endif /* _STLSOFT_NO_NAMESPACE */
00098 
00099 /* 
00100 
00103 
00107 
00112 
00113 /* 
00114  * Classes
00115  */
00116 
00117 // class basic_simple_string
00123 template<   ss_typename_param_k C
00124 #ifdef __STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
00125         ,   ss_typename_param_k T = stlsoft_char_traits<C>
00126         ,   ss_typename_param_k A = new_allocator<C>
00127 #else
00128         ,   ss_typename_param_k T /* = stlsoft_char_traits<C> */
00129         ,   ss_typename_param_k A /* = new_allocator<C> */
00130 #endif /* __STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
00131         >
00132 class basic_simple_string
00133 {
00134 public:
00136     typedef C                               value_type;
00138     typedef T                               traits_type;
00140     typedef A                               allocator_type;
00142     typedef basic_simple_string<C, T, A>    class_type;
00144     typedef value_type                      char_type;
00146     typedef value_type                      *pointer;
00148     typedef value_type const                *const_pointer;
00150     typedef value_type                      &reference;
00152     typedef value_type const                &const_reference;
00154     typedef ss_size_t                       size_type;
00156     typedef ss_ptrdiff_t                    difference_type;
00157 
00159     typedef
00160 #if !defined(__STLSOFT_COMPILER_IS_BORLAND)
00161            ss_typename_type_k
00162 #endif /* __STLSOFT_COMPILER_IS_BORLAND */
00163                        pointer_iterator <   value_type
00164                                         ,   pointer
00165                                         ,   reference
00166                                         >::iterator_type    iterator;
00168     typedef
00169 #if !defined(__STLSOFT_COMPILER_IS_BORLAND)
00170          ss_typename_type_k
00171 #endif /* __STLSOFT_COMPILER_IS_BORLAND */
00172                        pointer_iterator <   value_type const
00173                                         ,   const_pointer
00174                                         ,   const_reference
00175                                         >::iterator_type    const_iterator;
00176 
00177 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00178 
00179     typedef reverse_iterator_base       <   iterator
00180                                         ,   value_type
00181                                         ,   reference
00182                                         ,   pointer
00183                                         ,   difference_type
00184                                         >                   reverse_iterator;
00185 
00187     typedef const_reverse_iterator_base <   const_iterator
00188                                         ,   value_type const
00189                                         ,   const_reference
00190                                         ,   const_pointer
00191                                         ,   difference_type
00192                                         >                   const_reverse_iterator;
00193 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00194 
00196 
00197 public:
00199     basic_simple_string();
00201     basic_simple_string(class_type const &rhs);
00203     basic_simple_string(class_type const &s, size_type pos);
00205     basic_simple_string(class_type const &s, size_type pos, size_type cch);
00207     basic_simple_string(char_type const *s); // Not, not explicit. Sigh
00209     basic_simple_string(char_type const *s, size_type cch);
00211     basic_simple_string(size_type cch, char_type ch);
00213 #if !defined(__STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
00214     basic_simple_string(char_type const *first, char_type const *last);
00215 #else
00216     template <ss_typename_param_k II>
00217     basic_simple_string(II first, II last)
00218         : m_buffer(NULL)
00219     {
00220         assign(first, last);
00221     }
00222 #endif /* __STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
00223 
00224     ~basic_simple_string();
00226 
00228 
00229 public:
00231     class_type &assign(char_type const *s);
00233     class_type &assign(char_type const *s, size_type cch);
00235     class_type &assign(class_type const &str, size_type pos, size_type cch);
00237     class_type &assign(class_type const &str);
00239     class_type &assign(size_type cch, char_type ch);
00241 #if !defined(__STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
00242     class_type &assign(const_iterator first, const_iterator last);
00243 #else
00244     template <ss_typename_param_k II>
00245     class_type &assign(II first, II last)
00246     {
00247 # if defined(__STLSOFT_COMPILER_IS_GCC) && \
00248      __GNUC__ < 3
00249         typedef ss_typename_type_k std::iterator_traits<II> traits_t;
00250 
00251         return assign_(first, last, traits_t::iterator_category());
00252 # else
00253         return assign_(first, last, stlsoft_iterator_query_category(II, first));
00254 # endif /* GCC < 3 */
00255     }
00256 #endif /* __STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
00257 
00259     class_type const &operator =(class_type const &rhs);
00261     class_type const &operator =(char_type const *s);
00263     class_type const &operator =(char_type ch);
00265 
00267 
00268 public:
00270     class_type &append(char_type const *s);
00272     class_type &append(char_type const *s, size_type cch);
00274     class_type &append(class_type const &str, size_type pos, size_type cch);
00276     class_type &append(class_type const &str);
00278     class_type &append(size_type cch, char_type ch);
00280 #if !defined(__STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
00281     class_type &append(const_iterator first, const_iterator last);
00282 #else
00283     template <ss_typename_param_k II>
00284     class_type &append(II first, II last)
00285     {
00286 # if defined(__STLSOFT_COMPILER_IS_GCC) && \
00287      __GNUC__ < 3
00288         typedef ss_typename_type_k std::iterator_traits<II> traits_t;
00289 
00290         return append_(first, last, traits_t::iterator_category());
00291 # else
00292         return append_(first, last, stlsoft_iterator_query_category(II, first));
00293 # endif /* GCC < 3 */
00294     }
00295 #endif /* __STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
00296 
00298     class_type &operator +=(char_type ch);
00300     class_type &operator +=(char_type const *s);
00302     class_type &operator +=(class_type const &rhs);
00303 
00305     void push_back(char_type ch);
00307 
00309 
00310 public:
00312     void reserve(size_type cch);
00314     void swap(class_type &other);
00315 
00320     void resize(size_type cch, value_type ch = value_type());
00321 
00323     void clear();
00325 
00327 
00328 public:
00330     size_type size() const;
00332     size_type max_size() const;
00334     size_type length() const;
00336     size_type capacity() const;
00338     ss_bool_t empty() const;
00340 
00342 
00343 public:
00345     ss_sint_t compare(size_type pos, size_type cch, value_type const *s, size_type cchRhs) const;
00347     ss_sint_t compare(size_type pos, size_type cch, value_type const *s) const;
00349     ss_sint_t compare(value_type const *s) const;
00351     ss_sint_t compare(size_type pos, size_type cch, class_type const &rhs, size_type posRhs, size_type cchRhs) const;
00353     ss_sint_t compare(size_type pos, size_type cch, class_type const &rhs) const;
00355     ss_sint_t compare(class_type const &rhs) const;
00357 
00359 
00360 public:
00362     reference       operator [](size_type index);
00364     const_reference operator [](size_type index) const;
00365 
00367     value_type const    *c_str() const;
00369     value_type const    *data() const;
00370 
00374     reference               front();
00378     reference               back();
00382     const_reference         front() const;
00386     const_reference         back() const;
00387 
00389     size_type copy(value_type *dest, size_type cch, size_type pos = 0) const;
00391 
00393 
00394 public:
00398 #ifdef STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE
00399     const_iterator          begin() const
00400     {
00401         return const_cast<class_type*>(this)->begin_();
00402     }
00403 #else /* ? STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
00404     const_iterator          begin() const;
00405 #endif /* STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
00409 #ifdef STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE
00410     const_iterator          end() const
00411     {
00412         return const_cast<class_type*>(this)->end_();
00413     }
00414 #else /* ? STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
00415     const_iterator          end() const;
00416 #endif /* STLSOFT_SIMPLE_STRING_ITERATOR_METHODS_INLINE */
00420     iterator                begin();
00424     iterator                end();
00425 
00426 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00430     const_reverse_iterator  rbegin() const;
00434     const_reverse_iterator  rend() const;
00438     reverse_iterator        rbegin();
00442     reverse_iterator        rend();
00443 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00444 
00445 
00447 
00448 private:
00449     enum { alloc_quantum = 31 };    // Must be (2^n - 1)
00450 
00451     struct string_buffer
00452     {
00453         size_type   capacity;       // The number of char places in the buffer
00454         size_type   length;         // The number of chars in the string (<= capacity)
00455         char_type   contents[1];    // The first element in the array
00456     };
00457 
00458 #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
00459     typedef string_buffer       *member_pointer;
00460     typedef string_buffer const *member_const_pointer;
00461 #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
00462     typedef char_type           *member_pointer;
00463     typedef char_type const     *member_const_pointer;
00464 #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
00465 
00466     // Conversion between member pointer and character pointer
00467     static char_type            *char_pointer_from_member_pointer_(member_pointer );
00468 
00469     // Conversion between pointer and buffer
00470     static string_buffer        *string_buffer_from_member_pointer_(member_pointer );
00471     static string_buffer const  *string_buffer_from_member_pointer_(member_const_pointer );
00472 
00473     // Conversion between buffer and pointer
00474     static member_pointer       member_pointer_from_string_buffer_(string_buffer *);
00475 
00476     // Creating buffer
00477     static member_pointer       alloc_buffer_(char_type const *s, size_type capacity, size_type length);
00478     static member_pointer       alloc_buffer_(char_type const *s, size_type cch);
00479     static member_pointer       alloc_buffer_(char_type const *s);
00480 
00481     // Copying a buffer
00482     static member_pointer       copy_buffer_(member_pointer );
00483 
00484     // Destroying buffer
00485     static void                 destroy_buffer_(string_buffer *);
00486     static void                 destroy_buffer_(char_type *);
00487 
00488     // Iteration
00489     pointer                     begin_();
00490     pointer                     end_();
00491 
00492     // Invariance
00493     ss_bool_t is_valid_() const;
00494 
00495     // Empty string
00496     static char_type const *empty_string_();
00497 
00498     // Comparison
00499     static ss_sint_t compare_(char_type const *lhs, size_type lhs_len, char_type const *rhs, size_type rhs_len);
00500 
00501     // Assignment
00502 #if defined(__STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
00503     template <ss_typename_param_k II>
00504     class_type &assign_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag))
00505     {
00506         stlsoft_ns_qual_std(copy)(first, last, stlsoft_ns_qual_std(back_inserter)(*this));
00507 
00508         stlsoft_assert(is_valid_());
00509         return *this;
00510     }
00511     template <ss_typename_param_k II>
00512     class_type &assign_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag))
00513     {
00514         typedef auto_buffer<char_type, allocator_type>  buffer_t;
00515 
00516         buffer_t    buffer(stlsoft_ns_qual_std(distance)(first, last));
00517 
00518         stlsoft_ns_qual_std(copy)(first, last, buffer.begin());
00519         assign(buffer, buffer.size());
00520 
00521         stlsoft_assert(is_valid_());
00522         return *this;
00523     }
00524 #endif /* __STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
00525 
00526     // Appending
00527 #if defined(__STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
00528     template <ss_typename_param_k II>
00529     class_type &append_(II first, II last, stlsoft_ns_qual_std(input_iterator_tag))
00530     {
00531         stlsoft_ns_qual_std(copy)(first, last, stlsoft_ns_qual_std(back_inserter)(*this));
00532 
00533         stlsoft_assert(is_valid_());
00534         return *this;
00535     }
00536     template <ss_typename_param_k II>
00537     class_type &append_(II first, II last, stlsoft_ns_qual_std(forward_iterator_tag))
00538     {
00539         typedef auto_buffer<char_type, allocator_type>  buffer_t;
00540 
00541         buffer_t    buffer(stlsoft_ns_qual_std(distance)(first, last));
00542 
00543         stlsoft_ns_qual_std(copy)(first, last, buffer.begin());
00544         append(buffer, buffer.size());
00545 
00546         stlsoft_assert(is_valid_());
00547         return *this;
00548     }
00549 #endif /* __STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
00550 
00551 
00553 
00554 private:
00555     member_pointer  m_buffer;
00557 };
00558 
00559 /* 
00560  * Operators
00561  */
00562 
00563 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00564 
00565 // operator ==
00566 
00567 template<   ss_typename_param_k C
00568         ,   ss_typename_param_k T
00569         ,   ss_typename_param_k A
00570         >
00571 inline ss_bool_t operator ==(basic_simple_string<C, T, A> const &lhs, basic_simple_string<C, T, A> const &rhs)
00572 {
00573     return 0 == lhs.compare(rhs);
00574 }
00575 
00576 template<   ss_typename_param_k C
00577         ,   ss_typename_param_k T
00578         ,   ss_typename_param_k A
00579         >
00580 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00581 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)
00582 #else
00583 inline ss_bool_t operator ==(basic_simple_string<C, T, A> const &lhs, C const *rhs)
00584 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00585 {
00586     return 0 == lhs.compare(rhs);
00587 }
00588 
00589 template<   ss_typename_param_k C
00590         ,   ss_typename_param_k T
00591         ,   ss_typename_param_k A
00592         >
00593 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00594 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)
00595 #else
00596 inline ss_bool_t operator ==(C *lhs, basic_simple_string<C, T, A> const &rhs)
00597 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00598 {
00599     return 0 == rhs.compare(lhs);
00600 }
00601 
00602 // operator !=
00603 
00604 template<   ss_typename_param_k C
00605         ,   ss_typename_param_k T
00606         ,   ss_typename_param_k A
00607         >
00608 inline ss_bool_t operator !=(basic_simple_string<C, T, A> const &lhs, basic_simple_string<C, T, A> const &rhs)
00609 {
00610     return 0 != lhs.compare(rhs);
00611 }
00612 template<   ss_typename_param_k C
00613         ,   ss_typename_param_k T
00614         ,   ss_typename_param_k A
00615         >
00616 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00617 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)
00618 #else
00619 inline ss_bool_t operator !=(basic_simple_string<C, T, A> const &lhs, C const *rhs)
00620 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00621 {
00622     return 0 != lhs.compare(rhs);
00623 }
00624 template<   ss_typename_param_k C
00625         ,   ss_typename_param_k T
00626         ,   ss_typename_param_k A
00627         >
00628 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00629 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)
00630 #else
00631 inline ss_bool_t operator !=(C const *lhs, basic_simple_string<C, T, A> const &rhs)
00632 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00633 {
00634     return 0 != rhs.compare(lhs);
00635 }
00636 
00637 // operator <
00638 
00639 template<   ss_typename_param_k C
00640         ,   ss_typename_param_k T
00641         ,   ss_typename_param_k A
00642         >
00643 inline ss_bool_t operator <(basic_simple_string<C, T, A> const &lhs, basic_simple_string<C, T, A> const &rhs)
00644 {
00645     return lhs.compare(rhs) < 0;
00646 }
00647 
00648 template<   ss_typename_param_k C
00649         ,   ss_typename_param_k T
00650         ,   ss_typename_param_k A
00651         >
00652 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00653 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)
00654 #else
00655 inline ss_bool_t operator <(basic_simple_string<C, T, A> const &lhs, C const *rhs)
00656 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00657 {
00658     return lhs.compare(rhs) < 0;
00659 }
00660 
00661 template<   ss_typename_param_k C
00662         ,   ss_typename_param_k T
00663         ,   ss_typename_param_k A
00664         >
00665 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00666 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)
00667 #else
00668 inline ss_bool_t operator <(C const *lhs, basic_simple_string<C, T, A> const &rhs)
00669 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00670 {
00671     return rhs.compare(lhs) > 0;
00672 }
00673 
00674 // operator <=
00675 
00676 template<   ss_typename_param_k C
00677         ,   ss_typename_param_k T
00678         ,   ss_typename_param_k A
00679         >
00680 inline ss_bool_t operator <=(basic_simple_string<C, T, A> const &lhs, basic_simple_string<C, T, A> const &rhs)
00681 {
00682     return lhs.compare(rhs) <= 0;
00683 }
00684 template<   ss_typename_param_k C
00685         ,   ss_typename_param_k T
00686         ,   ss_typename_param_k A
00687         >
00688 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00689 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)
00690 #else
00691 inline ss_bool_t operator <=(basic_simple_string<C, T, A> const &lhs, C const *rhs)
00692 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00693 {
00694     return lhs.compare(rhs) <= 0;
00695 }
00696 template<   ss_typename_param_k C
00697         ,   ss_typename_param_k T
00698         ,   ss_typename_param_k A
00699         >
00700 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00701 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)
00702 #else
00703 inline ss_bool_t operator <=(C const *lhs, basic_simple_string<C, T, A> const &rhs)
00704 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00705 {
00706     return rhs.compare(lhs) >= 0;
00707 }
00708 
00709 // operator >
00710 
00711 template<   ss_typename_param_k C
00712         ,   ss_typename_param_k T
00713         ,   ss_typename_param_k A
00714         >
00715 inline ss_bool_t operator >(basic_simple_string<C, T, A> const &lhs, basic_simple_string<C, T, A> const &rhs)
00716 {
00717     return lhs.compare(rhs) > 0;
00718 }
00719 template<   ss_typename_param_k C
00720         ,   ss_typename_param_k T
00721         ,   ss_typename_param_k A
00722         >
00723 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00724 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)
00725 #else
00726 inline ss_bool_t operator >(basic_simple_string<C, T, A> const &lhs, C const *rhs)
00727 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00728 {
00729     return lhs.compare(rhs) > 0;
00730 }
00731 template<   ss_typename_param_k C
00732         ,   ss_typename_param_k T
00733         ,   ss_typename_param_k A
00734         >
00735 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00736 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)
00737 #else
00738 inline ss_bool_t operator >(C const *lhs, basic_simple_string<C, T, A> const &rhs)
00739 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00740 {
00741     return rhs.compare(lhs) < 0;
00742 }
00743 
00744 // operator >=
00745 
00746 template<   ss_typename_param_k C
00747         ,   ss_typename_param_k T
00748         ,   ss_typename_param_k A
00749         >
00750 inline ss_bool_t operator >=(basic_simple_string<C, T, A> const &lhs, basic_simple_string<C, T, A> const &rhs)
00751 {
00752     return lhs.compare(rhs) >= 0;
00753 }
00754 template<   ss_typename_param_k C
00755         ,   ss_typename_param_k T
00756         ,   ss_typename_param_k A
00757         >
00758 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00759 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)
00760 #else
00761 inline ss_bool_t operator >=(basic_simple_string<C, T, A> const &lhs, C const *rhs)
00762 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00763 {
00764     return lhs.compare(rhs) >= 0;
00765 }
00766 template<   ss_typename_param_k C
00767         ,   ss_typename_param_k T
00768         ,   ss_typename_param_k A
00769         >
00770 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00771 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)
00772 #else
00773 inline ss_bool_t operator >=(C const *lhs, basic_simple_string<C, T, A> const &rhs)
00774 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00775 {
00776     return rhs.compare(lhs) <= 0;
00777 }
00778 
00779 // operator +
00780 
00781 template<   ss_typename_param_k C
00782         ,   ss_typename_param_k T
00783         ,   ss_typename_param_k A
00784         >
00785 inline basic_simple_string<C, T, A> operator +(basic_simple_string<C, T, A> const &lhs, basic_simple_string<C, T, A> const &rhs)
00786 {
00787     return basic_simple_string<C, T, A>(lhs) += rhs;
00788 }
00789 template<   ss_typename_param_k C
00790         ,   ss_typename_param_k T
00791         ,   ss_typename_param_k A
00792         >
00793 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00794 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)
00795 #else
00796 inline basic_simple_string<C, T, A> operator +(basic_simple_string<C, T, A> const &lhs, C const *rhs)
00797 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00798 {
00799     return basic_simple_string<C, T, A>(lhs) += rhs;
00800 }
00801 template<   ss_typename_param_k C
00802         ,   ss_typename_param_k T
00803         ,   ss_typename_param_k A
00804         >
00805 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00806 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)
00807 #else
00808 inline basic_simple_string<C, T, A> operator +(C const *lhs, basic_simple_string<C, T, A> const &rhs)
00809 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00810 {
00811     return basic_simple_string<C, T, A>(lhs) += rhs;
00812 }
00813 template<   ss_typename_param_k C
00814         ,   ss_typename_param_k T
00815         ,   ss_typename_param_k A
00816         >
00817 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00818 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)
00819 #else
00820 inline basic_simple_string<C, T, A> operator +(basic_simple_string<C, T, A> const &lhs, C rhs)
00821 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00822 {
00823     return basic_simple_string<C, T, A>(lhs) += rhs;
00824 }
00825 template<   ss_typename_param_k C
00826         ,   ss_typename_param_k T
00827         ,   ss_typename_param_k A
00828         >
00829 #ifdef __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT
00830 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)
00831 #else
00832 inline basic_simple_string<C, T, A> operator +(C lhs, basic_simple_string<C, T, A> const &rhs)
00833 #endif /* __STLSOFT_CF_TEMPLATE_OUTOFCLASSFN_QUALIFIED_TYPE_SUPPORT */
00834 {
00835     return basic_simple_string<C, T, A>(1, lhs) += rhs;
00836 }
00837 
00838 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00839 
00840 /* 
00841  * Shims
00842  */
00843 
00844 /* c_str_ptr_null */
00845 
00847 template<   ss_typename_param_k C
00848         ,   ss_typename_param_k T
00849         ,   ss_typename_param_k A
00850         >
00851 inline C const *c_str_ptr_null(basic_simple_string<C, T, A> const &s)
00852 {
00853     return (0 == s.length()) ? NULL : s.c_str();
00854 }
00855 
00856 /* c_str_ptr */
00857 
00859 template<   ss_typename_param_k C
00860         ,   ss_typename_param_k T
00861         ,   ss_typename_param_k A
00862         >
00863 inline C const *c_str_ptr(basic_simple_string<C, T, A> const &s)
00864 {
00865     return s.c_str();
00866 }
00867 
00869 template<   ss_typename_param_k T
00870         ,   ss_typename_param_k A
00871         >
00872 inline ss_char_a_t const *c_str_ptr_a(basic_simple_string<ss_char_a_t, T, A> const &s)
00873 {
00874     return s.c_str();
00875 }
00876 
00878 template<   ss_typename_param_k T
00879         ,   ss_typename_param_k A
00880         >
00881 inline ss_char_w_t const *c_str_ptr_w(basic_simple_string<ss_char_w_t, T, A> const &s)
00882 {
00883     return s.c_str();
00884 }
00885 
00886 /* c_str_ptr_len */
00887 
00889 template<   ss_typename_param_k C
00890         ,   ss_typename_param_k T
00891         ,   ss_typename_param_k A
00892         >
00893 inline ss_size_t c_str_len(basic_simple_string<C, T, A> const &s)
00894 {
00895     return s.length();
00896 }
00897 
00898 /* c_str_ptr_size */
00899 
00901 template<   ss_typename_param_k C
00902         ,   ss_typename_param_k T
00903         ,   ss_typename_param_k A
00904         >
00905 inline ss_size_t c_str_size(basic_simple_string<C, T, A> const &s)
00906 {
00907     return c_str_len(s) * sizeof(C);
00908 }
00909 
00910 /* operator << */
00911 template<   ss_typename_param_k S
00912         ,   ss_typename_param_k C
00913         ,   ss_typename_param_k T
00914         ,   ss_typename_param_k A
00915         >
00916 inline S &operator <<(S & s, basic_simple_string<C, T, A> const &str)
00917 {
00918     s << str.c_str();
00919 
00920     return s;
00921 }
00922 
00923 /* 
00924  * Unit-testing
00925  */
00926 
00927 #ifdef STLSOFT_UNITTEST
00928 
00929 namespace unittest
00930 {
00931     ss_bool_t test_stlsoft_simple_string(unittest_reporter *r)
00932     {
00933         ss_bool_t               bSuccess    =   true;
00934 
00935         unittest_initialiser    init(r, "STLSoft", "basic_simple_string", __FILE__);
00936 
00937         typedef basic_simple_string<char
00938                                 ,   stlsoft_char_traits<char>
00939                                 ,   new_allocator<char>
00940                                 >                               string_t;
00941 
00942         if(string_t("abc") != "abc")
00943         {
00944             r->report("construction failed ", __LINE__);
00945             bSuccess = false;
00946         }
00947 
00948         if(string_t("abc") >= "def")
00949         {
00950             r->report("comparison failed ", __LINE__);
00951             bSuccess = false;
00952         }
00953 
00954         // Self assignment
00955         string_t const  s3("abcdefghijklm");
00956         string_t        s4;
00957 
00958         s4 = s3;    // setup
00959         s4 = s4;    // action
00960         if(s3 != s4)
00961         {
00962             r->report("self-assignment (1) failed ", __LINE__);
00963             bSuccess = false;
00964         }
00965 
00966         s4 = s3;            // setup
00967         s4.assign(&s4[2]);  // action
00968         if("abcdefghijklm" + 2 != s4)
00969         {
00970             r->report("self-assignment (2) failed ", __LINE__);
00971             bSuccess = false;
00972         }
00973 
00974         s4 = s3;                // setup
00975         s4.append(&s4[2], 4);   // action
00976         if("abcdefghijklmcdef" != s4)
00977         {
00978             r->report("self-append (1) failed ", __LINE__);
00979             bSuccess = false;
00980         }
00981 
00982         s4 = s3;            // setup
00983         s4.append(&s4[1]);  // action
00984         if("abcdefghijklmbcdefghijklm" != s4)
00985         {
00986             r->report("self-append (2) failed ", __LINE__);
00987             bSuccess = false;
00988         }
00989 
00990         return bSuccess;
00991     }
00992 
00993     unittest_registrar    unittest_stlsoft_simple_string(test_stlsoft_simple_string);
00994 
00995 } // namespace winstl_test
00996 
00997 #endif /* STLSOFT_UNITTEST */
00998 
00999 /* 
01000  * Implementation
01001  */
01002 
01003 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
01004 
01005 // Implementation
01006 
01007 template<   ss_typename_param_k C
01008         ,   ss_typename_param_k T
01009         ,   ss_typename_param_k A
01010         >
01011 inline /* static */ ss_typename_type_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)
01012 {
01013 #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
01014     return (NULL == m) ? NULL : m->contents;
01015 #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
01016     return m;
01017 #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
01018 }
01019 
01020 
01021 template<   ss_typename_param_k C
01022         ,   ss_typename_param_k T
01023         ,   ss_typename_param_k A
01024         >
01025 inline /* static */ ss_typename_type_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)
01026 {
01027     stlsoft_message_assert("Attempt to convert a null string_buffer in basic_simple_string", NULL != m);
01028 
01029 #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
01030     return m;
01031 #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
01032     return reinterpret_cast<string_buffer*>(const_cast<void*>(ptr_byte_offset(m, -static_cast<ss_ptrdiff_t>(stlsoft_raw_offsetof(string_buffer, contents)))));
01033 #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
01034 }
01035 
01036 template<   ss_typename_param_k C
01037         ,   ss_typename_param_k T
01038         ,   ss_typename_param_k A
01039         >
01040 inline /* static */ ss_typename_type_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)
01041 {
01042     stlsoft_message_assert("Attempt to convert a null string_buffer in basic_simple_string", NULL != m);
01043 
01044 #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
01045     return m;
01046 #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
01047     return reinterpret_cast<string_buffer const*>(ptr_byte_offset(m, -static_cast<ss_ptrdiff_t>(stlsoft_raw_offsetof(string_buffer, contents))));
01048 #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
01049 }
01050 
01051 template<   ss_typename_param_k C
01052         ,   ss_typename_param_k T
01053         ,   ss_typename_param_k A
01054         >
01055 inline /* static */ ss_typename_type_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)
01056 {
01057 #ifdef STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST
01058     return b;
01059 #else /* ? STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
01060     return b->contents;
01061 #endif /* STLSOFT_SIMPLE_STRING_NO_PTR_ADJUST */
01062 }
01063 
01064 template<   ss_typename_param_k C
01065         ,   ss_typename_param_k T
01066         ,   ss_typename_param_k A
01067         >
01068 inline /* static */ ss_typename_type_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
01069                                                                                                                             ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          capacity
01070                                                                                                                             ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          length)
01071 {
01072     // Pre-conditions
01073     stlsoft_assert(length <= capacity);
01074     stlsoft_assert(length >= traits_type::length_max_null(s, length));
01075 
01076     const ss_size_t members = (stlsoft_raw_offsetof(string_buffer, contents) + (sizeof(char_type) - 1)) / sizeof(char_type);
01077 
01078     capacity += 1;                                              // For null terminator
01079     capacity += members;                                        // Include the internal members.
01080     capacity = (alloc_quantum + capacity) & ~alloc_quantum;     // Round up to (alloc_quantum + 1)
01081 
01082 
01083 #ifdef STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT
01084 # ifdef STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT
01085     ss_typename_type_k allocator_type::template rebind<ss_byte_t>::other    byte_ator;
01086 # else /* ? STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT */
01087     ss_typename_type_k allocator_type::rebind<ss_byte_t>::other             byte_ator;
01088 # endif /* STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT */
01089 #else /* ? STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT */
01090     new_allocator<ss_byte_t>                                                byte_ator;
01091 #endif /* STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT */
01092 
01093     ss_byte_t       *raw_buffer =   byte_ator.allocate(capacity * sizeof(char_type));
01094     string_buffer   *buffer     =   sap_cast<string_buffer*>(raw_buffer);
01095 
01096     if(NULL != buffer)
01097     {
01098         if(NULL == s)
01099         {
01100             stlsoft_assert(0 == length);
01101 
01102             buffer->contents[0] = traits_type::to_char_type(0);
01103         }
01104         else
01105         {
01106             traits_type::copy(buffer->contents, s, length);
01107             buffer->contents[length] = traits_type::to_char_type(0);
01108         }
01109 
01110         buffer->length      =   length;
01111         buffer->capacity    =   capacity - members;
01112 
01113         return member_pointer_from_string_buffer_(buffer);
01114     }
01115 
01116     return NULL;
01117 }
01118 
01119 template<   ss_typename_param_k C
01120         ,   ss_typename_param_k T
01121         ,   ss_typename_param_k A
01122         >
01123 inline /* static */ ss_typename_type_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
01124                                                                                                                             ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          cch)
01125 {
01126     size_type   length      =   traits_type::length_max_null(s, cch);
01127     size_type   capacity    =   cch;
01128 
01129     if(cch < length)
01130     {
01131         length = cch;
01132     }
01133 
01134     return alloc_buffer_(s, capacity, length);
01135 }
01136 
01137 template<   ss_typename_param_k C
01138         ,   ss_typename_param_k T
01139         ,   ss_typename_param_k A
01140         >
01141 inline /* static */ ss_typename_type_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)
01142 {
01143     member_pointer  res;
01144 
01145     if(NULL == s)
01146     {
01147         res = NULL;
01148     }
01149     else
01150     {
01151         size_type   len =   traits_type::length(s);
01152 
01153         res = alloc_buffer_(s, len, len);
01154     }
01155 
01156     return res;
01157 }
01158 
01159 template<   ss_typename_param_k C
01160         ,   ss_typename_param_k T
01161         ,   ss_typename_param_k A
01162         >
01163 inline /* static */ ss_typename_type_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)
01164 {
01165     if(NULL != m)
01166     {
01167 #ifdef STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT
01168 # ifdef STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT
01169         ss_typename_type_k allocator_type::template rebind<ss_byte_t>::other    byte_ator;
01170 # else /* ? STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT */
01171         ss_typename_type_k allocator_type::rebind<ss_byte_t>::other             byte_ator;
01172 # endif /* STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT */
01173 #else /* ? STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT */
01174         new_allocator<ss_byte_t>                                                byte_ator;
01175 #endif /* STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT */
01176 
01177         string_buffer   *buffer     =   string_buffer_from_member_pointer_(m);
01178         ss_size_t       cb          =   buffer->capacity * sizeof(char_type) + stlsoft_raw_offsetof(string_buffer, contents);
01179         ss_byte_t       *raw_buffer =   byte_ator.allocate(cb);
01180         string_buffer   *new_buffer =   sap_cast<string_buffer*>(raw_buffer);
01181 
01182         if(NULL != new_buffer)
01183         {
01184             memcpy(new_buffer, buffer, cb);
01185 
01186             return member_pointer_from_string_buffer_(new_buffer);
01187         }
01188     }
01189 
01190     return NULL;
01191 }
01192 
01193 template<   ss_typename_param_k C
01194         ,   ss_typename_param_k T
01195         ,   ss_typename_param_k A
01196         >
01197 inline /* static */ void basic_simple_string<C, T, A>::destroy_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::string_buffer *buffer)
01198 {
01199 #ifdef STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT
01200 # ifdef STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT
01201     ss_typename_type_k allocator_type::template rebind<ss_byte_t>::other    byte_ator;
01202 # else /* ? STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT */
01203     ss_typename_type_k allocator_type::rebind<ss_byte_t>::other             byte_ator;
01204 # endif /* STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT */
01205 #else /* ? STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT */
01206     new_allocator<ss_byte_t>                                                byte_ator;
01207 #endif /* STLSOFT_CF_ALLOCATOR_REBIND_SUPPORT */
01208 
01209 #ifdef STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT
01210 #else /* ? STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT */
01211 #endif /* STLSOFT_CF_TEMPLATE_QUALIFIER_KEYWORD_SUPPORT */
01212 
01213     byte_ator.deallocate(sap_cast<ss_byte_t*>(buffer), 0);
01214 }
01215 
01216 template<   ss_typename_param_k C
01217         ,   ss_typename_param_k T
01218         ,   ss_typename_param_k A
01219         >
01220 inline /* static */ void basic_simple_string<C, T, A>::destroy_buffer_(ss_typename_type_k basic_simple_string<C, T, A>::char_type *s)
01221 {
01222     destroy_buffer_(string_buffer_from_member_pointer_(s));
01223 }
01224 
01225 template<   ss_typename_param_k C
01226         ,   ss_typename_param_k T
01227         ,   ss_typename_param_k A
01228         >
01229 inline ss_typename_type_k basic_simple_string<C, T, A>::pointer basic_simple_string<C, T, A>::begin_()
01230 {
01231     return char_pointer_from_member_pointer_(m_buffer);
01232 }
01233 
01234 template<   ss_typename_param_k C
01235         ,   ss_typename_param_k T
01236         ,   ss_typename_param_k A
01237         >
01238 inline ss_typename_type_k basic_simple_string<C, T, A>::pointer basic_simple_string<C, T, A>::end_()
01239 {
01240     return begin_() + length();
01241 }
01242 
01243 template<   ss_typename_param_k C
01244         ,   ss_typename_param_k T
01245         ,   ss_typename_param_k A
01246         >
01247 inline ss_bool_t basic_simple_string<C, T, A>::is_valid_() const
01248 {
01249     if(NULL != m_buffer)
01250     {
01251         string_buffer const *buffer =   string_buffer_from_member_pointer_(m_buffer);
01252 
01253         if(buffer->capacity < 1)
01254         {
01255             return false;
01256         }
01257         else if(buffer->capacity < buffer->length)
01258         {
01259             return false;
01260         }
01261         else
01262         {
01263             size_type   len =   traits_type::length(buffer->contents);
01264 
01265             if(buffer->length != len)
01266             {
01267                 return false;
01268             }
01269         }
01270     }
01271 
01272     return true;
01273 }
01274 
01275 template<   ss_typename_param_k C
01276         ,   ss_typename_param_k T
01277         ,   ss_typename_param_k A
01278         >
01279 inline /* static */ ss_typename_type_k basic_simple_string<C, T, A>::char_type const *basic_simple_string<C, T, A>::empty_string_()
01280 {
01281     // This character array is initialised to 0, which conveniently happens to
01282     // be the empty string, by the module/application load, so it is
01283     // guaranteed to be valid, and there are no threading/race conditions
01284     static char_type    s_empty[1];
01285 
01286     stlsoft_assert(s_empty[0] == '\0'); // Paranoid check
01287 
01288     return s_empty;
01289 }
01290 
01291 // Construction
01292 
01293 template<   ss_typename_param_k C
01294         ,   ss_typename_param_k T
01295         ,   ss_typename_param_k A
01296         >
01297 inline basic_simple_string<C, T, A>::basic_simple_string()
01298     : m_buffer(NULL)
01299 {
01300     stlsoft_assert(is_valid_());
01301 }
01302 
01303 template<   ss_typename_param_k C
01304         ,   ss_typename_param_k T
01305         ,   ss_typename_param_k A
01306         >
01307 inline basic_simple_string<C, T, A>::basic_simple_string(class_type const &rhs)
01308     : m_buffer(copy_buffer_(rhs.m_buffer))
01309 {
01310     stlsoft_assert(is_valid_());
01311 }
01312 
01313 template<   ss_typename_param_k C
01314         ,   ss_typename_param_k T
01315         ,   ss_typename_param_k A
01316         >
01317 inline basic_simple_string<C, T, A>::basic_simple_string(   ss_typename_type_k basic_simple_string<C, T, A>::class_type const   &rhs
01318                                                         ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          pos)
01319     : m_buffer(alloc_buffer_(&rhs[pos]))
01320 {
01321     stlsoft_assert(is_valid_());
01322 }
01323 
01324 template<   ss_typename_param_k C
01325         ,   ss_typename_param_k T
01326         ,   ss_typename_param_k A
01327         >
01328 inline basic_simple_string<C, T, A>::basic_simple_string(   ss_typename_type_k basic_simple_string<C, T, A>::class_type const   &rhs
01329                                                         ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          pos
01330                                                         ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          cch)
01331     : m_buffer(alloc_buffer_(&rhs[pos], cch, cch))
01332 {
01333     stlsoft_assert(is_valid_());
01334 }
01335 
01336 template<   ss_typename_param_k C
01337         ,   ss_typename_param_k T
01338         ,   ss_typename_param_k A
01339         >
01340 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
01341     : m_buffer(alloc_buffer_(s))
01342 {
01343     stlsoft_assert(is_valid_());
01344 }
01345 
01346 template<   ss_typename_param_k C
01347         ,   ss_typename_param_k T
01348         ,   ss_typename_param_k A
01349         >
01350 inline basic_simple_string<C, T, A>::basic_simple_string(   ss_typename_type_k basic_simple_string<C, T, A>::char_type const    *s
01351                                                         ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          cch)
01352     : m_buffer(alloc_buffer_(s, cch))
01353 {
01354     stlsoft_assert(is_valid_());
01355 }
01356 
01357 template<   ss_typename_param_k C
01358         ,   ss_typename_param_k T
01359         ,   ss_typename_param_k A
01360         >
01361 inline basic_simple_string<C, T, A>::basic_simple_string(   ss_typename_type_k basic_simple_string<C, T, A>::size_type  cch
01362                                                         ,   ss_typename_type_k basic_simple_string<C, T, A>::char_type  ch)
01363     : m_buffer(NULL)
01364 {
01365     stlsoft_assert(is_valid_());
01366 
01367     assign(cch, ch);
01368 }
01369 
01370 #if !defined(__STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT)
01371 template<   ss_typename_param_k C
01372         ,   ss_typename_param_k T
01373         ,   ss_typename_param_k A
01374         >
01375 inline basic_simple_string<C, T, A>::basic_simple_string(   ss_typename_type_k basic_simple_string<C, T, A>::char_type const    *first
01376                                                         ,   ss_typename_type_k basic_simple_string<C, T, A>::char_type const    *last)
01377     : m_buffer(alloc_buffer_(first, last - first))
01378 {
01379     stlsoft_assert(is_valid_());
01380 }
01381 #endif /* !__STLSOFT_CF_MEMBER_TEMPLATE_RANGE_METHOD_SUPPORT */
01382 
01383 template<   ss_typename_param_k C
01384         ,   ss_typename_param_k T
01385         ,   ss_typename_param_k A
01386         >
01387 inline basic_simple_string<C, T, A>::~basic_simple_string()
01388 {
01389     stlsoft_assert(is_valid_());
01390 
01391     if(NULL != m_buffer)
01392     {
01393         destroy_buffer_(m_buffer);
01394     }
01395 }
01396 
01397 // Comparison
01398 
01399 template<   ss_typename_param_k C
01400         ,   ss_typename_param_k T
01401         ,   ss_typename_param_k A
01402         >
01403 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
01404                                                                     ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          lhs_len
01405                                                                     ,   ss_typename_type_k basic_simple_string<C, T, A>::value_type const   *rhs
01406                                                                     ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          rhs_len)
01407 {
01408     size_type   cmp_len =   (lhs_len < rhs_len) ? lhs_len : rhs_len;
01409     ss_int_t    result  =   traits_type::compare(lhs, rhs, cmp_len);
01410 
01411     if(0 == result)
01412     {
01413         result = static_cast<ss_int_t>(lhs_len) - static_cast<ss_int_t>(rhs_len);
01414     }
01415 
01416     return result;
01417 }
01418 
01419 template<   ss_typename_param_k C
01420         ,   ss_typename_param_k T
01421         ,   ss_typename_param_k A
01422         >
01423 inline ss_sint_t basic_simple_string<C, T, A>::compare( ss_typename_type_k basic_simple_string<C, T, A>::size_type          pos
01424                                                     ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          cch
01425                                                     ,   ss_typename_type_k basic_simple_string<C, T, A>::value_type const   *rhs
01426                                                     ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          cchRhs) const
01427 {
01428     size_type   lhs_len =   length();
01429 
01430     if(!(pos < lhs_len))
01431     {
01432         pos = lhs_len;
01433     }
01434     else
01435     {
01436         lhs_len -= pos;
01437     }
01438 
01439     if(cch < lhs_len)
01440     {
01441         lhs_len = cch;
01442     }
01443 
01444     size_type   rhs_len =   (NULL == rhs) ? 0 : traits_type::length(rhs);
01445 
01446     if(cchRhs < rhs_len)
01447     {
01448         rhs_len = cchRhs;
01449     }
01450 
01451     return compare_(char_pointer_from_member_pointer_(m_buffer) + pos, lhs_len, rhs, rhs_len);
01452 }
01453 
01454 template<   ss_typename_param_k C
01455         ,   ss_typename_param_k T
01456         ,   ss_typename_param_k A
01457         >
01458 inline ss_sint_t basic_simple_string<C, T, A>::compare( ss_typename_type_k basic_simple_string<C, T, A>::size_type          pos
01459                                                     ,   ss_typename_type_k basic_simple_string<C, T, A>::size_type          cch
01460                                                     ,   ss_typename_type_k basic_simple_string<C, T, A>::value_type const   *rhs) const
01461 {
01462     size_type   lhs_len =   length();
01463 
01464     if(!(pos < lhs_len))
01465     {
01466         pos = lhs_len;
01467     }
01468     else
01469     {
01470         lhs_len -= pos;
01471     }
01472 
01473     if(cch < lhs_len)
01474     {
01475         lhs_len = cch;
01476     }
01477 
01478     size_type   rhs_len =   (NULL == rhs) ? 0 : traits_type::length(rhs);
01479 
01480     return compare_(char_pointer_from_member_pointer_(m_buffer) + pos, lhs_len, rhs, rhs_len);
01481 }
01482 
01483 template<   ss_typename_param_k C
01484         ,   ss_typename_param_k T
01485         ,   ss_typename_param_k A
01486         >
01487 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
01488 {
01489     size_type   lhs_len =   length();
01490     size_type   rhs_len =   (NULL == rhs) ? 0 : traits_type::length(rhs);
01491 
01492     return compare_(char_pointer_from_member_pointer_(m_buffer), lhs_len, rhs, rhs_len);
01493 }
01494 
01495 template<   ss_typename_param_k C
01496         ,