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