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 * 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 * 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:: 58 S_Data::S_Data() 59 : nCount(1) 60 { 61 } 62 63 String:: 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:: 75 S_Data::~S_Data() 76 { 77 csv_assert( nCount == 0 ); 78 } 79 80 const String::S_Data * 81 String:: 82 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:: 94 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 109 String::String() 110 : pd( String::Null_().pd->Acquire() ) 111 { 112 } 113 114 String::String( const char * i_str ) 115 : pd( new S_Data(i_str) ) 116 { 117 } 118 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 */ 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 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 140 String::String( const self & i_rStr ) 141 : pd( i_rStr.pd->Acquire() ) 142 { 143 } 144 145 String::~String() 146 { 147 pd->Release(); 148 } 149 150 151 String & 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 & 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 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 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 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 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 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 224 String::compare( const self & i_rStr ) const 225 { 226 return strcmp( c_str(), i_rStr.c_str() ); 227 } 228 229 int 230 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 237 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 256 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 273 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 & 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 & 295 String::Nulch_() 296 { 297 static const char cNull_ = '\0'; 298 return cNull_; 299 } 300 301 302 int 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 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 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 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 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 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