1 //  (C) Copyright Gennadiy Rozental 2001-2014.
2 //  Distributed under the Boost Software License, Version 1.0.
3 //  (See accompanying file LICENSE_1_0.txt or copy at
4 //  http://www.boost.org/LICENSE_1_0.txt)
5 
6 //  See http://www.boost.org/libs/test for the library home page.
7 //
8 //  File        : $RCSfile$
9 //
10 //  Version     : $Revision$
11 //
12 //  Description : simple string class definition
13 // ***************************************************************************
14 
15 #ifndef  CONST_STRING_HPP
16 #define  CONST_STRING_HPP
17 
18 // STL
19 #include <iterator>
20 #include <string>
21 #include <cstring>
22 using std::string;
23 
24 namespace common_layer {
25 
26 // ************************************************************************** //
27 // **************                 const_string                 ************** //
28 // ************************************************************************** //
29 
30 class const_string {
31 public:
32     // Subtypes
33     typedef     char const*                     iterator;
34     typedef     char const*                     const_iterator;
35     typedef     std::reverse_iterator<iterator> reverse_iterator;
36     typedef     reverse_iterator                const_reverse_iterator;
37 
38     // Constructor
const_string()39     const_string()
40     : m_begin( "" ), m_end( m_begin )                      {}
41 
42     // Copy constructor is generated by compiler
43 
const_string(const std::string & s)44     const_string( const std::string& s )
45     : m_begin( s.c_str() ),
46       m_end( m_begin + s.length() )                        {}
47 
const_string(char const * s)48     const_string( char const* s )
49     : m_begin( s ? s : "" )
50     , m_end( s ? m_begin + std::strlen( s ) : m_begin )
51     {}
52 
const_string(char const * s,size_t length)53     const_string( char const* s, size_t length )
54     : m_begin( s ), m_end( m_begin + length )              { if( length == 0 ) erase(); }
55 
const_string(char const * first,char const * last)56     const_string( char const* first, char const* last )
57     : m_begin( first ), m_end( last )                      {}
58 
59     // data access methods
operator [](size_t index) const60     char            operator[]( size_t index ) const        { return m_begin[index]; }
at(size_t index) const61     char            at( size_t index ) const                { return m_begin[index]; }
62 
data() const63     char const*     data() const                            { return m_begin; }
64 
65     // length operators
length() const66     size_t          length() const                          { return m_end - m_begin; }
is_empty() const67     bool            is_empty() const                        { return m_end == m_begin; }
68 
erase()69     void            erase()                                 { m_begin = m_end = ""; }
resize(size_t new_len)70     void            resize( size_t new_len )                { if( m_begin + new_len < m_end ) m_end = m_begin + new_len; }
rshorten(size_t shift=1)71     void            rshorten( size_t shift = 1 )            { m_end  -= shift; if( m_end <= m_begin ) erase(); }
lshorten(size_t shift=1)72     void            lshorten( size_t shift = 1 )            { m_begin += shift; if( m_end <= m_begin ) erase(); }
73 
74     // Assignment operators
75     const_string&   operator=( const_string const& s );
operator =(string const & s)76     const_string&   operator=( string const& s )            { return *this = const_string( s ); }
operator =(char const * s)77     const_string&   operator=( char const* s )              { return *this = const_string( s ); }
78 
assign(const_string const & s)79     const_string&   assign( const_string const& s )         { return *this = s; }
assign(string const & s,size_t len)80     const_string&   assign( string const& s, size_t len )   { return *this = const_string( s.data(), len ); }
assign(string const & s)81     const_string&   assign( string const& s )               { return *this = const_string( s ); }
assign(char const * s)82     const_string&   assign( char const* s )                 { return *this = const_string( s ); }
assign(char const * s,size_t len)83     const_string&   assign( char const* s, size_t len )     { return *this = const_string( s, len ); }
assign(char const * f,char const * l)84     const_string&   assign( char const* f, char const* l )  { return *this = const_string( f, l ); }
85 
swap(const_string & s)86     void            swap( const_string& s )                 {
87        // do not want to include alogrithm
88         char const* tmp1 = m_begin;
89         char const* tmp2 = m_end;
90 
91         m_begin     = s.m_begin;
92         m_end       = s.m_end;
93 
94         s.m_begin   = tmp1;
95         s.m_end     = tmp2;
96     }
97 
98     // Comparison operators
operator ==(const_string const & s1,const_string const & s2)99     friend bool     operator==( const_string const& s1, const_string const& s2 )
100     {
101          return s1.length() == s2.length() && std::strncmp( s1.data(), s2.data(), s1.length() ) == 0;
102     }
operator ==(const_string const & s1,char const * s2)103     friend bool     operator==( const_string const& s1, char const* s2 )            { return s1 == const_string( s2 ); }
operator ==(const_string const & s1,const string & s2)104     friend bool     operator==( const_string const& s1, const string& s2 )          { return s1 == const_string( s2 ); }
105 
operator !=(const_string const & s1,const_string const & s2)106     friend bool     operator!=( const_string const& s1, const_string const& s2 )    { return !(s1 == s2); }
operator !=(const_string const & s1,char const * s2)107     friend bool     operator!=( const_string const& s1, char const* s2 )            { return !(s1 == s2); }
operator !=(const_string const & s1,const string & s2)108     friend bool     operator!=( const_string const& s1, const string& s2 )          { return !(s1 == s2); }
109 
operator ==(char const * s2,const_string const & s1)110     friend bool     operator==( char const* s2,         const_string const& s1 )    { return s1 == s2; }
operator ==(const string & s2,const_string const & s1)111     friend bool     operator==( const string& s2,       const_string const& s1 )    { return s1 == s2; }
112 
operator !=(char const * s2,const_string const & s1)113     friend bool     operator!=( char const* s2,         const_string const& s1 )    { return !(s1 == s2); }
operator !=(const string & s2,const_string const & s1)114     friend bool     operator!=( const string& s2,       const_string const& s1 )    { return !(s1 == s2); }
115 
116     // Iterators
begin() const117     iterator        begin() const                           { return m_begin; }
end() const118     iterator        end() const                             { return m_end;   }
rbegin() const119     reverse_iterator rbegin() const                         { return reverse_iterator( m_end );   }
rend() const120     reverse_iterator rend() const                           { return reverse_iterator( m_begin ); }
121 
122 private:
123 
124     // Data members
125     char const*     m_begin;
126     char const*     m_end;
127 };
128 
129 //____________________________________________________________________________//
130 
131 // first character
132 class first_char {
133 public:
operator ()(const_string source,char default_char='\\0') const134     char operator()( const_string source, char default_char = '\0' ) const {
135         return source.is_empty() ? default_char : *source.data();
136     }
137 };
138 
139 //____________________________________________________________________________//
140 
141 // last character
142 class last_char {
143 public:
operator ()(const_string source,char default_char='\\0') const144     char operator()( const_string source, char default_char = '\0' ) const {
145         return source.is_empty() ? default_char : *source.rbegin();
146     }
147 };
148 
149 //____________________________________________________________________________//
150 
151 inline const_string&
operator =(const_string const & s)152 const_string::operator=( const_string const& s ) {
153     if( &s != this ) {
154         m_begin = s.m_begin;
155         m_end  = s.m_end;
156     }
157 
158     return *this;
159 }
160 
161 //____________________________________________________________________________//
162 
163 typedef const_string const literal;
164 
165 //____________________________________________________________________________//
166 
167 inline std::ostream&
operator <<(std::ostream & os,const_string const & str)168 operator<<( std::ostream& os, const_string const& str )
169 {
170     os << std::string( str.begin(), str.length() );
171 
172     return os;
173 }
174 
175 //____________________________________________________________________________//
176 
177 }; // namespace common_layer
178 
179 #endif // CONST_STRING_HPP
180