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