1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <precomp.h>
25 #include <cosv/string.hxx>
26 
27 // NOT FULLY DECLARED SERVICES
28 #include <string.h>
29 #include <cosv/comfunc.hxx>
30 
31 
32 
33 
34 namespace csv
35 {
36 
37 
38 inline const char *
str_from_StringOffset(const String & i_rStr,str::size i_nOffset)39 str_from_StringOffset( const String &     i_rStr,
40                        str::size       i_nOffset )
41 {
42  	return i_nOffset < i_rStr.size()
43                 ?   i_rStr.c_str() + i_nOffset
44                 :   "";
45 }
46 
47 inline const char *
str_from_ptr(const char * i_str)48 str_from_ptr( const char * i_str )
49 {
50 
51     return valid_str(i_str);
52 }
53 
54 
55 //*********************     String::S_Data    **********************//
56 
57 inline String::
S_Data()58 S_Data::S_Data()
59     :   nCount(1)
60 {
61 }
62 
63 String::
S_Data(const char * i_sData,size_type i_nValidLength)64 S_Data::S_Data( const char *        i_sData,
65                 size_type           i_nValidLength )
66     :   aStr( str_from_ptr(i_sData),
67               (i_nValidLength != str::maxsize
68                     ?   i_nValidLength
69                     :   strlen(i_sData)) ),
70         nCount(1)
71 {
72 }
73 
74 String::
~S_Data()75 S_Data::~S_Data()
76 {
77     csv_assert( nCount == 0 );
78 }
79 
80 const String::S_Data *
81 String::
Acquire() const82 S_Data::Acquire() const
83 {
84 #ifdef CSV_NO_MUTABLE
85     ++ (const_cast< uintt& >(nCount));
86 #else
87     ++nCount;
88 #endif
89     return this;
90 }
91 
92 void
93 String::
Release() const94 S_Data::Release() const
95 {
96 #ifdef CSV_NO_MUTABLE
97     -- (const_cast< uintt& >(nCount));
98 #else
99     --nCount;
100 #endif
101     if (nCount == 0)
102         delete (const_cast< S_Data* >(this));
103 }
104 
105 
106 //**************************     String    **************************//
107 
108 
String()109 String::String()
110     :   pd( String::Null_().pd->Acquire() )
111 {
112 }
113 
String(const char * i_str)114 String::String( const char * i_str )
115     :   pd( new S_Data(i_str) )
116 {
117 }
118 
String(const char * i_str,size_type i_nLength)119 String::String( const char *        i_str,
120                 size_type           i_nLength )
121     :   pd( new S_Data(i_str, i_nLength) )
122 {
123 }
124 
125 /*  For efficiency see the previous c'tor.
126 */
String(const self & i_rStr,position_type i_nStartPosition,size_type i_nLength)127 String::String( const self &        i_rStr,
128                 position_type       i_nStartPosition,
129                 size_type           i_nLength )
130     :   pd( new S_Data(str_from_StringOffset(i_rStr, i_nStartPosition), i_nLength) )
131 {
132 }
133 
String(const_iterator i_itBegin,const_iterator i_itEnd)134 String::String( const_iterator i_itBegin,
135                 const_iterator i_itEnd )
136     :   pd( new S_Data(i_itBegin, size_type(i_itEnd - i_itBegin)) )
137 {
138 }
139 
String(const self & i_rStr)140 String::String( const self & i_rStr )
141     :   pd( i_rStr.pd->Acquire() )
142 {
143 }
144 
~String()145 String::~String()
146 {
147     pd->Release();
148 }
149 
150 
151 String &
operator =(const self & i_rStr)152 String::operator=( const self & i_rStr )
153 {
154     i_rStr.pd->Acquire();
155     pd->Release();
156     pd = i_rStr.pd;
157 
158     return *this;
159 }
160 
161 String &
operator =(const char * i_str)162 String::operator=( const char * i_str )
163 {
164     const S_Data *
165         pTemp = new S_Data(i_str);
166     pd->Release();
167     pd = pTemp;
168 
169     return *this;
170 }
171 
172 void
swap(self & i_rStr)173 String::swap( self & i_rStr )
174 {
175     const S_Data * pTemp = pd;
176     pd = i_rStr.pd;
177     i_rStr.pd = pTemp;
178 }
179 
180 void
assign(const self & i_rStr,position_type i_nStartPosition,size_type i_nLength)181 String::assign( const self &        i_rStr,
182                 position_type       i_nStartPosition,
183                 size_type           i_nLength )
184 {
185     const S_Data *
186         pTemp = new S_Data( str_from_StringOffset(i_rStr, i_nStartPosition),
187                             i_nLength );
188     pd->Release();
189     pd = pTemp;
190 }
191 
192 void
assign(const char * i_str)193 String::assign( const char *        i_str )
194 {
195     const S_Data *
196         pTemp = new S_Data( i_str );
197     pd->Release();
198     pd = pTemp;
199 }
200 
201 void
assign(const char * i_str,size_type i_nLength)202 String::assign( const char *        i_str,
203                 size_type           i_nLength )
204 {
205     const S_Data *
206         pTemp = new S_Data( i_str, i_nLength );
207     pd->Release();
208     pd = pTemp;
209 }
210 
211 void
assign(const_iterator i_itBegin,const_iterator i_itEnd)212 String::assign( const_iterator      i_itBegin,
213                 const_iterator      i_itEnd )
214 {
215     const S_Data *
216         pTemp = new S_Data( i_itBegin,
217                             size_type(i_itEnd - i_itBegin) );
218     pd->Release();
219     pd = pTemp;
220 }
221 
222 
223 int
compare(const self & i_rStr) const224 String::compare( const self & i_rStr ) const
225 {
226     return strcmp( c_str(), i_rStr.c_str() );
227 }
228 
229 int
compare(const CharOrder_Table & i_rOrder,const self & i_rStr) const230 String::compare( const CharOrder_Table & i_rOrder,
231                  const self &            i_rStr ) const
232 {
233     return csv::compare( i_rOrder, c_str(), i_rStr.c_str() );
234 }
235 
236 String
substr(position_type i_nStartPosition,size_type i_nLength) const237 String::substr( position_type       i_nStartPosition,
238                 size_type           i_nLength ) const
239 {
240     size_type nSize = size();
241 
242     if ( i_nStartPosition < nSize )
243     {
244         if ( i_nLength == str::maxsize
245              OR i_nLength >= nSize - i_nStartPosition )
246      	    return String( c_str() + i_nStartPosition );
247         else
248             return String( c_str() + i_nStartPosition,
249                                  i_nLength );
250     }
251 
252     return Null_();
253 }
254 
255 String::position_type
find(const char * i_strToSearch,position_type i_nSearchStartPosition) const256 String::find( const char *        i_strToSearch,
257               position_type       i_nSearchStartPosition ) const
258 {
259     csv_assert(i_strToSearch != 0);
260 
261     if ( i_nSearchStartPosition < length()
262          AND
263          *i_strToSearch != '\0' )
264     {
265         const char * p = strstr(c_str() + i_nSearchStartPosition, i_strToSearch);
266         if (p != 0)
267             return static_cast<position_type>(p - c_str());
268     }
269     return str::position(str::npos);
270 }
271 
272 String::position_type
find(char i_charToSearch,position_type i_nSearchStartPosition) const273 String::find( char                i_charToSearch,
274               position_type       i_nSearchStartPosition ) const
275 {
276     if (i_nSearchStartPosition <= length())
277     {
278         const char * p = strchr(c_str() + i_nSearchStartPosition, i_charToSearch);
279         if (p != 0)
280             return static_cast<position_type>(p - c_str());
281     }
282     return str::position(str::npos);
283 }
284 
285 const String &
Null_()286 String::Null_()
287 {
288     // Must not use the default constructor! Because that one calls
289     //   this function, which would create a circular dependency.
290     static const String aNull_("");
291     return aNull_;
292 }
293 
294 const char &
Nulch_()295 String::Nulch_()
296 {
297     static const char cNull_ = '\0';
298     return cNull_;
299 }
300 
301 
302 int
compare(const String & i_s1,csv::str::position i_nStartPosition1,const char * i_s2,csv::str::size i_nLength)303 compare( const String &      i_s1,
304          csv::str::position        i_nStartPosition1,
305          const char *              i_s2,
306          csv::str::size            i_nLength )
307 {
308     const char * pS1 = str_from_StringOffset( i_s1, i_nStartPosition1 );
309 
310     if ( i_nLength != csv::str::maxsize )
311         return strncmp( pS1,
312                         i_s2,
313                         i_nLength );
314     else
315         return strcmp( pS1,
316                        i_s2 );
317 }
318 
319 int
compare(const char * i_s1,const String & i_s2,csv::str::position i_nStartPosition2,csv::str::size i_nLength)320 compare( const char *              i_s1,
321          const String &      i_s2,
322          csv::str::position        i_nStartPosition2,
323          csv::str::size            i_nLength )
324 {
325     const char * pS2 = str_from_StringOffset( i_s2, i_nStartPosition2 );
326 
327     if ( i_nLength != csv::str::maxsize )
328         return strncmp( i_s1,
329                         pS2,
330                         i_nLength );
331     else
332         return strcmp( i_s1,
333                        pS2 );
334 }
335 
336 int
compare(const CharOrder_Table & i_rOrder,const char * i_s1,const char * i_s2)337 compare( const CharOrder_Table &            i_rOrder,
338          const char *                       i_s1,
339          const char *                       i_s2 )
340 {
341     const char * it1 = i_s1;
342     const char * it2 = i_s2;
343     for ( ; i_rOrder(*it1) == i_rOrder(*it2) AND *it1 != '\0'; ++it1, ++it2 )
344     {}
345     return int( i_rOrder(*it1) - i_rOrder(*it2) );
346 }
347 
348 int
compare(const CharOrder_Table & i_rOrder,const String & i_s1,csv::str::position i_nStartPosition1,const char * i_s2,csv::str::size i_nLength)349 compare( const CharOrder_Table &   i_rOrder,
350          const String &      i_s1,
351          csv::str::position        i_nStartPosition1,
352          const char *              i_s2,
353          csv::str::size            i_nLength )
354 {
355     const char * pS1 = str_from_StringOffset( i_s1, i_nStartPosition1 );
356 
357     if ( i_nLength != csv::str::maxsize )
358         return compare( i_rOrder,
359                         pS1,
360                         i_s2,
361                         i_nLength );
362     else
363         return compare( i_rOrder,
364                         pS1,
365                         i_s2 );
366 }
367 
368 int
compare(const CharOrder_Table & i_rOrder,const char * i_s1,const String & i_s2,csv::str::position i_nStartPosition2,csv::str::size i_nLength)369 compare( const CharOrder_Table &   i_rOrder,
370          const char *              i_s1,
371          const String &            i_s2,
372          csv::str::position        i_nStartPosition2,
373          csv::str::size                 i_nLength )
374 {
375     const char * pS2 = str_from_StringOffset( i_s2, i_nStartPosition2 );
376 
377     if ( i_nLength != csv::str::maxsize )
378         return compare( i_rOrder,
379                         i_s1,
380                         pS2,
381                         i_nLength );
382     else
383         return compare( i_rOrder,
384                         i_s1,
385                         pS2 );
386 }
387 
388 int
compare(const CharOrder_Table & i_rOrder,const char * i_s1,const char * i_s2,csv::str::size i_nLength)389 compare( const CharOrder_Table &            i_rOrder,
390          const char *                       i_s1,
391          const char *                       i_s2,
392          csv::str::size                     i_nLength )
393 {
394     const char * sEnd = i_s1 + i_nLength;
395 
396     const char * it1 = i_s1;
397     const char * it2 = i_s2;
398     for ( ; i_rOrder(*it1) == i_rOrder(*it2) AND *it1 != '\0' AND it1 != sEnd; ++it1, ++it2 )
399     {}
400 
401     if ( it1 != sEnd )
402         return int( i_rOrder(*it1) - i_rOrder(*it2) );
403     else
404         return 0;
405 }
406 
407 
408 
409 
410 }   // namespace csv
411