Ticket #1595: BString.2.diff
File BString.2.diff, 81.8 KB (added by , 17 years ago) |
---|
-
headers/os/support/String.h
1 1 /* 2 * Copyright 2001-2007, Haiku Inc. All Rights Reserved.3 4 2 * Copyright 2001-2008, Haiku Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 5 #ifndef __BSTRING__ 6 6 #define __BSTRING__ 7 7 … … 11 11 #include <string.h> 12 12 13 13 14 class BString { 15 public: 16 BString(); 17 BString(const char* string); 18 BString(const BString& string); 19 BString(const char* string, int32 maxLength); 20 ~BString(); 14 class BStringRef; 21 15 22 // Access23 const char* String() const;24 16 25 int32 Length() const; 26 // length of corresponding string 27 int32 CountChars() const; 28 // returns number of UTF8 characters in string 17 class BString 18 { 19 public: 20 BString(); 21 BString(const char* string); 22 BString(const BString& string); 23 BString(const char* string, int32 maxLength); 24 ~BString(); 29 25 30 // Assignment 31 BString& operator=(const BString& string); 32 BString& operator=(const char* string); 33 BString& operator=(char c); 26 // Access 27 const char* String() const; 28 int32 Length() const; 29 int32 CountChars() const; 30 int32 ReferenceCount() const; 34 31 35 BString& SetTo(const char* string); 36 BString& SetTo(const char* string, int32 maxLength); 32 // Assignment 33 BString& operator=(const BString& string); 34 BString& operator=(const char* string); 35 BString& operator=(char c); 37 36 38 BString& SetTo(const BString&string);39 BString& Adopt(BString& from);37 BString& SetTo(const char* string); 38 BString& SetTo(const char* string, int32 maxLength); 40 39 41 BString& SetTo(const BString& string, int32 maxLength);42 BString& Adopt(BString& from, int32 maxLength);40 BString& SetTo(const BString& string); 41 BString& Adopt(BString& from); 43 42 44 BString& SetTo(char c, int32 count); 43 BString& SetTo(const BString& string, int32 maxLength); 44 BString& Adopt(BString& from, int32 maxLength); 45 45 46 // Substring copying 47 BString& CopyInto(BString& into, int32 fromOffset, 48 int32 length) const; 49 void CopyInto(char* into, int32 fromOffset, 50 int32 length) const; 46 BString& SetTo(char c, int32 count); 51 47 52 // Appending 53 BString& operator+=(const BString& string); 54 BString& operator+=(const char* string); 55 BString& operator+=(char c); 48 // Substring copying 49 BString& CopyInto(BString& into, int32 fromOffset, int32 length) const; 50 void CopyInto(char* into, int32 fromOffset, int32 length) const; 56 51 57 BString& Append(const BString& string); 58 BString& Append(const char* string); 52 // Appending 53 BString& operator+=(const BString& string); 54 BString& operator+=(const char* string); 55 BString& operator+=(char c); 59 56 60 BString& Append(const BString& string, int32 length); 61 BString& Append(const char* string, int32 length); 62 BString& Append(char c, int32 count); 57 BString& Append(const BString& string); 58 BString& Append(const char* string); 63 59 64 // Prepending 65 BString& Prepend(const char* string); 66 BString& Prepend(const BString& string); 67 BString& Prepend(const char* string, int32 length); 68 BString& Prepend(const BString& string, int32 length); 69 BString& Prepend(char c, int32 count); 60 BString& Append(const BString& string, int32 length); 61 BString& Append(const char* string, int32 length); 62 BString& Append(char c, int32 count); 70 63 71 // Inserting 72 BString& Insert(const char* string, int32 pos); 73 BString& Insert(const char* string, int32 length, int32 pos); 74 BString& Insert(const char* string, int32 fromOffset, 75 int32 length, int32 pos); 64 // Prepending 65 BString& Prepend(const char* string); 66 BString& Prepend(const BString& string); 67 BString& Prepend(const char* string, int32 length); 68 BString& Prepend(const BString& string, int32 length); 69 BString& Prepend(char c, int32 count); 76 70 77 BString& Insert(const BString& string, int32 pos); 78 BString& Insert(const BString& string, int32 length, int32 pos); 79 BString& Insert(const BString& string, int32 fromOffset, 80 int32 length, int32 pos); 81 BString& Insert(char, int32 count, int32 pos); 71 // Inserting 72 BString& Insert(const char* string, int32 position); 73 BString& Insert(const char* string, int32 length, int32 position); 74 BString& Insert(const char* string, int32 fromOffset, int32 length, 75 int32 position); 76 BString& Insert(const BString& string, int32 position); 77 BString& Insert(const BString& string, int32 length, int32 position); 78 BString& Insert(const BString& string, int32 fromOffset, int32 length, 79 int32 position); 80 BString& Insert(char c, int32 count, int32 position); 82 81 83 84 BString&Truncate(int32 newLength, bool lazy = true);85 BString&Remove(int32 from, int32 length);82 // Removing 83 BString& Truncate(int32 newLength, bool lazy = true); 84 BString& Remove(int32 from, int32 length); 86 85 87 BString&RemoveFirst(const BString& string);88 BString&RemoveLast(const BString& string);89 BString&RemoveAll(const BString& string);86 BString& RemoveFirst(const BString& string); 87 BString& RemoveLast(const BString& string); 88 BString& RemoveAll(const BString& string); 90 89 91 BString&RemoveFirst(const char* string);92 BString&RemoveLast(const char* string);93 BString&RemoveAll(const char* string);90 BString& RemoveFirst(const char* string); 91 BString& RemoveLast(const char* string); 92 BString& RemoveAll(const char* string); 94 93 95 BString&RemoveSet(const char* setOfCharsToRemove);94 BString& RemoveSet(const char* setOfCharsToRemove); 96 95 97 BString&MoveInto(BString& into, int32 from, int32 length);98 voidMoveInto(char* into, int32 from, int32 length);96 BString& MoveInto(BString& into, int32 from, int32 length); 97 void MoveInto(char* into, int32 from, int32 length); 99 98 100 101 booloperator<(const BString& string) const;102 booloperator<=(const BString& string) const;103 booloperator==(const BString& string) const;104 booloperator>=(const BString& string) const;105 booloperator>(const BString& string) const;106 booloperator!=(const BString& string) const;99 // Compare functions 100 bool operator<(const BString& string) const; 101 bool operator<=(const BString& string) const; 102 bool operator==(const BString& string) const; 103 bool operator>=(const BString& string) const; 104 bool operator>(const BString& string) const; 105 bool operator!=(const BString& string) const; 107 106 108 booloperator<(const char* string) const;109 booloperator<=(const char* string) const;110 booloperator==(const char* string) const;111 booloperator>=(const char* string) const;112 booloperator>(const char* string) const;113 booloperator!=(const char* string) const;107 bool operator<(const char* string) const; 108 bool operator<=(const char* string) const; 109 bool operator==(const char* string) const; 110 bool operator>=(const char* string) const; 111 bool operator>(const char* string) const; 112 bool operator!=(const char* string) const; 114 113 115 116 intCompare(const BString& string) const;117 intCompare(const char* string) const;118 intCompare(const BString& string, int32 length) const;119 intCompare(const char* string, int32 length) const;120 intICompare(const BString& string) const;121 intICompare(const char* string) const;122 intICompare(const BString& string, int32 length) const;123 intICompare(const char* string, int32 length) const;114 // strcmp()-style compare functions 115 int Compare(const BString& string) const; 116 int Compare(const char* string) const; 117 int Compare(const BString& string, int32 length) const; 118 int Compare(const char* string, int32 length) const; 119 int ICompare(const BString& string) const; 120 int ICompare(const char* string) const; 121 int ICompare(const BString& string, int32 length) const; 122 int ICompare(const char* string, int32 length) const; 124 123 125 126 int32FindFirst(const BString& string) const;127 int32FindFirst(const char* string) const;128 int32FindFirst(const BString& string, int32 fromOffset) const;129 int32FindFirst(const char* string, int32 fromOffset) const;130 int32FindFirst(char c) const;131 int32FindFirst(char c, int32 fromOffset) const;124 // Searching 125 int32 FindFirst(const BString& string) const; 126 int32 FindFirst(const char* string) const; 127 int32 FindFirst(const BString& string, int32 fromOffset) const; 128 int32 FindFirst(const char* string, int32 fromOffset) const; 129 int32 FindFirst(char c) const; 130 int32 FindFirst(char c, int32 fromOffset) const; 132 131 133 int32FindLast(const BString& string) const;134 int32FindLast(const char* string) const;135 int32FindLast(const BString& string, int32 beforeOffset) const;136 int32FindLast(const char* string, int32 beforeOffset) const;137 int32FindLast(char c) const;138 int32FindLast(char c, int32 beforeOffset) const;132 int32 FindLast(const BString& string) const; 133 int32 FindLast(const char* string) const; 134 int32 FindLast(const BString& string, int32 beforeOffset) const; 135 int32 FindLast(const char* string, int32 beforeOffset) const; 136 int32 FindLast(char c) const; 137 int32 FindLast(char c, int32 beforeOffset) const; 139 138 140 int32IFindFirst(const BString& string) const;141 int32IFindFirst(const char* string) const;142 int32IFindFirst(const BString& string, int32 fromOffset) const;143 int32IFindFirst(const char* string, int32 fromOffset) const;139 int32 IFindFirst(const BString& string) const; 140 int32 IFindFirst(const char* string) const; 141 int32 IFindFirst(const BString& string, int32 fromOffset) const; 142 int32 IFindFirst(const char* string, int32 fromOffset) const; 144 143 145 int32IFindLast(const BString& string) const;146 int32IFindLast(const char* string) const;147 int32IFindLast(const BString& string, int32 beforeOffset) const;148 int32IFindLast(const char* string, int32 beforeOffset) const;144 int32 IFindLast(const BString& string) const; 145 int32 IFindLast(const char* string) const; 146 int32 IFindLast(const BString& string, int32 beforeOffset) const; 147 int32 IFindLast(const char* string, int32 beforeOffset) const; 149 148 150 // Replacing 151 BString& ReplaceFirst(char replaceThis, char withThis); 152 BString& ReplaceLast(char replaceThis, char withThis); 153 BString& ReplaceAll(char replaceThis, char withThis, 154 int32 fromOffset = 0); 155 BString& Replace(char replaceThis, char withThis, 156 int32 maxReplaceCount, int32 fromOffset = 0); 157 BString& ReplaceFirst(const char* replaceThis, 158 const char* withThis); 159 BString& ReplaceLast(const char* replaceThis, 160 const char* withThis); 161 BString& ReplaceAll(const char* replaceThis, 162 const char* withThis, int32 fromOffset = 0); 163 BString& Replace(const char* replaceThis, const char* withThis, 164 int32 maxReplaceCount, int32 fromOffset = 0); 149 // Replacing 150 BString& ReplaceFirst(char replaceThis, char withThis); 151 BString& ReplaceLast(char replaceThis, char withThis); 152 BString& ReplaceAll(char replaceThis, char withThis, int32 fromOffset = 0); 153 BString& Replace(char replaceThis, char withThis, int32 maxReplaceCount, 154 int32 fromOffset = 0); 155 BString& ReplaceFirst(const char* replaceThis, const char* withThis); 156 BString& ReplaceLast(const char* replaceThis, const char* withThis); 157 BString& ReplaceAll(const char* replaceThis, const char* withThis, 158 int32 fromOffset = 0); 159 BString& Replace(const char* replaceThis, const char* withThis, 160 int32 maxReplaceCount, int32 fromOffset = 0); 165 161 166 BString& IReplaceFirst(char replaceThis, char withThis); 167 BString& IReplaceLast(char replaceThis, char withThis); 168 BString& IReplaceAll(char replaceThis, char withThis, 169 int32 fromOffset = 0); 170 BString& IReplace(char replaceThis, char withThis, 171 int32 maxReplaceCount, int32 fromOffset = 0); 172 BString& IReplaceFirst(const char* replaceThis, 173 const char* withThis); 174 BString& IReplaceLast(const char* replaceThis, 175 const char* withThis); 176 BString& IReplaceAll(const char* replaceThis, 177 const char* withThis, int32 fromOffset = 0); 178 BString& IReplace(const char* replaceThis, const char* withThis, 179 int32 maxReplaceCount, int32 fromOffset = 0); 162 BString& IReplaceFirst(char replaceThis, char withThis); 163 BString& IReplaceLast(char replaceThis, char withThis); 164 BString& IReplaceAll(char replaceThis, char withThis, int32 fromOffset = 0); 165 BString& IReplace(char replaceThis, char withThis, int32 maxReplaceCount, 166 int32 fromOffset = 0); 167 BString& IReplaceFirst(const char* replaceThis, const char* withThis); 168 BString& IReplaceLast(const char* replaceThis, const char* withThis); 169 BString& IReplaceAll(const char* replaceThis, const char* withThis, 170 int32 fromOffset = 0); 171 BString& IReplace(const char* replaceThis, const char* withThis, 172 int32 maxReplaceCount, int32 fromOffset = 0); 180 173 181 BString&ReplaceSet(const char* setOfChars, char with);182 BString& ReplaceSet(const char* setOfChars, const char *with);174 BString& ReplaceSet(const char* setOfChars, char with); 175 BString& ReplaceSet(const char* setOfChars, const char* with); 183 176 184 // Unchecked char access 185 char operator[](int32 index) const; 186 char& operator[](int32 index); 177 // Unchecked char access 178 char operator[](int32 index) const; 187 179 188 // Checked char access 189 char ByteAt(int32 index) const; 180 #if __GNUC__ > 3 181 BStringRef operator[](int32 index); 182 #else 183 char& operator[](int32 index); 184 #endif 190 185 191 // Fast low-level manipulation 192 char* LockBuffer(int32 maxLength); 193 BString& UnlockBuffer(int32 length = -1); 186 // Checked char access 187 char ByteAt(int32 index) const; 194 188 195 // Upercase <-> Lowercase196 BString& ToLower();197 BString& ToUpper();189 // Fast low-level manipulation 190 char* LockBuffer(int32 maxLength); 191 BString& UnlockBuffer(int32 length = -1); 198 192 199 BString& Capitalize(); 200 BString& CapitalizeEachWord(); 193 // Upercase <-> Lowercase 194 BString& ToLower(); 195 BString& ToUpper(); 201 196 202 // Escaping and De-escaping 203 BString& CharacterEscape(const char* original, 204 const char* setOfCharsToEscape, char escapeWith); 205 BString& CharacterEscape(const char* setOfCharsToEscape, 206 char escapeWith); 197 BString& Capitalize(); 198 BString& CapitalizeEachWord(); 207 199 208 BString& CharacterDeescape(const char* original, char escapeChar); 209 BString& CharacterDeescape(char escapeChar); 200 // Escaping and De-escaping 201 BString& CharacterEscape(const char* original, const char* setOfCharsToEscape, 202 char escapeWith); 203 BString& CharacterEscape(const char* setOfCharsToEscape, char escapeWith); 204 BString& CharacterDeescape(const char* original, char escapeChar); 205 BString& CharacterDeescape(char escapeChar); 210 206 211 // Slower than sprintf() but type and overflow safe212 BString&operator<<(const char* string);213 BString&operator<<(const BString& string);214 BString&operator<<(char c);215 BString&operator<<(int value);216 BString&operator<<(unsigned int value);217 BString&operator<<(uint32 value);218 BString&operator<<(int32 value);219 BString&operator<<(uint64 value);220 BString&operator<<(int64 value);221 BString& operator<<(float value);222 // float output hardcodes %.2f style formatting207 // Insert 208 BString& operator<<(const char* string); 209 BString& operator<<(const BString& string); 210 BString& operator<<(char c); 211 BString& operator<<(int value); 212 BString& operator<<(unsigned int value); 213 BString& operator<<(uint32 value); 214 BString& operator<<(int32 value); 215 BString& operator<<(uint64 value); 216 BString& operator<<(int64 value); 217 // float output hardcodes %.2f style formatting 218 BString& operator<<(float value); 223 219 224 private: 225 void _Init(const char *, int32); 226 void _DoAssign(const char *, int32); 227 void _DoAppend(const char *, int32); 228 char* _GrowBy(int32); 229 char* _OpenAtBy(int32, int32); 230 char* _ShrinkAtBy(int32, int32); 231 void _DoPrepend(const char *, int32); 220 private: 221 class PosVect; 222 friend class BStringRef; 232 223 233 int32 _FindAfter(const char *, int32, int32) const;234 int32 _IFindAfter(const char *, int32, int32) const;235 int32 _ShortFindAfter(const char *, int32) const;236 int32 _FindBefore(const char *, int32, int32) const;237 int32 _IFindBefore(const char *, int32, int32) const;238 BString& _DoReplace(const char *, const char *, int32, int32,239 bool);240 void _SetLength(int32);224 // Management 225 status_t _Detach(); 226 char* _Realloc(int32 length); 227 void _Init(const char* src, int32 length); 228 char* _Clone(const char* data, int32 length); 229 char* _OpenAtBy(int32 offset, int32 length); 230 char* _ShrinkAtBy(int32 offset, int32 length); 231 status_t _DetachWith(const char* string, int32 length); 241 232 242 #if DEBUG 243 void _SetUsingAsCString(bool); 244 void _AssertNotUsingAsCString() const; 245 #else 246 void _SetUsingAsCString(bool) {} 247 void _AssertNotUsingAsCString() const {} 248 #endif 233 // Data 234 void _SetLength(int32 length); 235 void _SetReferenceCount(int32 count); 236 bool _DoAppend(const char* string, int32 length); 237 bool _DoPrepend(const char* string, int32 length); 238 bool _DoInsert(const char* string, int32 offset, int32 length); 249 239 250 char* _Alloc(int32 size); 240 // Search 241 int32 _ShortFindAfter(const char* string, int32 len) const; 242 int32 _FindAfter(const char* string, int32 offset, int32 strlen) const; 243 int32 _IFindAfter(const char* string, int32 offset, int32 strlen) const; 251 244 252 class PosVect; 253 void _ReplaceAtPositions(const PosVect* positions, 254 int32 searchLength, const char* with, int32 withLen); 245 int32 _FindBefore(const char* string, int32 offset, int32 strlen) const; 246 int32 _IFindBefore(const char* string, int32 offset, int32 strlen) const; 255 247 256 protected: 257 char* fPrivateData; 248 // Escape 249 BString& _DoCharacterEscape(const char* string, 250 const char *setOfCharsToEscape, char escapeChar); 251 BString& _DoCharacterDeescape(const char* string, char escapeChar); 252 253 // Replace 254 BString& _DoReplace(const char* findThis, const char* replaceWith, 255 int32 maxReplaceCount, int32 fromOffset, bool ignoreCase); 256 void _ReplaceAtPositions(const PosVect* positions, int32 searchLen, 257 const char* with, int32 withLen); 258 259 private: 260 char* fPrivateData; 258 261 }; 259 262 263 260 264 // Commutative compare operators 261 265 bool operator<(const char* a, const BString& b); 262 266 bool operator<=(const char* a, const BString& b); … … 265 269 bool operator>=(const char* a, const BString& b); 266 270 bool operator!=(const char* a, const BString& b); 267 271 272 268 273 // Non-member compare for sorting, etc. 269 274 int Compare(const BString& a, const BString& b); 270 275 int ICompare(const BString& a, const BString& b); … … 272 277 int ICompare(const BString* a, const BString* b); 273 278 274 279 275 inline int32 280 inline int32 276 281 BString::Length() const 277 282 { 278 return fPrivateData ? (*((int32 *)fPrivateData - 1) & 0x7fffffff) : 0; 279 /* the most significant bit is reserved; accessing 280 * it in any way will cause the computer to explode 281 */ 283 // the most significant bit is reserved; accessing 284 // it in any way will cause the computer to explode 285 return fPrivateData ? (*(((int32 *)fPrivateData) - 1) & 0x7fffffff) : 0; 282 286 } 283 287 284 inline const char * 288 289 inline const char* 285 290 BString::String() const 286 291 { 287 292 if (!fPrivateData) … … 289 294 return fPrivateData; 290 295 } 291 296 297 298 inline int32 299 BString::ReferenceCount() const 300 { 301 return fPrivateData ? (*(((int32 *)fPrivateData) - 2)) : 1; 302 } 303 304 292 305 inline BString & 293 BString::SetTo(const char *string)306 BString::SetTo(const char* string) 294 307 { 295 308 return operator=(string); 296 309 } 297 310 298 inline char 311 312 inline char 299 313 BString::operator[](int32 index) const 300 314 { 301 315 return fPrivateData[index]; 302 316 } 303 317 304 inline char 318 319 inline char 305 320 BString::ByteAt(int32 index) const 306 321 { 307 322 if (!fPrivateData || index < 0 || index > Length()) … … 309 324 return fPrivateData[index]; 310 325 } 311 326 327 312 328 inline BString & 313 329 BString::operator+=(const BString &string) 314 330 { … … 316 332 return *this; 317 333 } 318 334 335 319 336 inline BString & 320 337 BString::Append(const BString &string) 321 338 { … … 323 340 return *this; 324 341 } 325 342 343 326 344 inline BString & 327 BString::Append(const char *str)345 BString::Append(const char* string) 328 346 { 329 return operator+=(str );347 return operator+=(string); 330 348 } 331 349 332 inline bool 350 351 inline bool 333 352 BString::operator==(const BString &string) const 334 353 { 335 354 return strcmp(String(), string.String()) == 0; 336 355 } 337 356 338 inline bool 357 358 inline bool 339 359 BString::operator<(const BString &string) const 340 360 { 341 361 return strcmp(String(), string.String()) < 0; 342 362 } 343 363 344 inline bool 364 365 inline bool 345 366 BString::operator<=(const BString &string) const 346 367 { 347 368 return strcmp(String(), string.String()) <= 0; 348 369 } 349 370 350 inline bool 371 372 inline bool 351 373 BString::operator>=(const BString &string) const 352 374 { 353 375 return strcmp(String(), string.String()) >= 0; 354 376 } 355 377 356 inline bool 378 379 inline bool 357 380 BString::operator>(const BString &string) const 358 381 { 359 382 return strcmp(String(), string.String()) > 0; 360 383 } 361 384 362 inline bool 385 386 inline bool 363 387 BString::operator!=(const BString &string) const 364 388 { 365 389 return strcmp(String(), string.String()) != 0; 366 390 } 367 391 368 inline bool 369 BString::operator!=(const char *str) const 392 393 inline bool 394 BString::operator!=(const char* string) const 370 395 { 371 return !operator==(str );396 return !operator==(string); 372 397 } 373 398 374 inline bool 399 400 inline bool 375 401 operator<(const char *str, const BString &string) 376 402 { 377 403 return string > str; 378 404 } 379 405 380 inline bool 406 407 inline bool 381 408 operator<=(const char *str, const BString &string) 382 409 { 383 410 return string >= str; 384 411 } 385 412 386 inline bool 413 414 inline bool 387 415 operator==(const char *str, const BString &string) 388 416 { 389 417 return string == str; 390 418 } 391 419 392 inline bool 420 421 inline bool 393 422 operator>(const char *str, const BString &string) 394 423 { 395 424 return string < str; 396 425 } 397 426 398 inline bool 427 428 inline bool 399 429 operator>=(const char *str, const BString &string) 400 430 { 401 431 return string <= str; 402 432 } 403 433 404 inline bool 434 435 inline bool 405 436 operator!=(const char *str, const BString &string) 406 437 { 407 438 return string != str; 408 439 } 409 440 410 #endif /* __BSTRING__ */ 441 442 // #pragma mark - BStringRef 443 444 445 class BStringRef 446 { 447 public: 448 BStringRef(BString& string, int32 position); 449 ~BStringRef() {} 450 451 operator char() const; 452 453 char* operator&(); 454 const char* operator&() const; 455 456 BStringRef& operator=(char c); 457 BStringRef &operator=(const BStringRef &rc); 458 459 private: 460 BString& fString; 461 int32 fPosition; 462 }; 463 464 #endif // __BSTRING__ -
src/kits/support/String.cpp
1 1 /* 2 * Copyright 2001-2007, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Stefano Ceccherini (burton666@libero.it) 8 * Oliver Tappe (openbeos@hirschkaefer.de) 9 * Axel Dörfler, axeld@pinc-software.de 10 */ 2 * Copyright 2001-2008, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Stefano Ceccherini (burton666@libero.it) 8 * Oliver Tappe (openbeos@hirschkaefer.de) 9 * Axel Dörfler, axeld@pinc-software.de 10 * Julun <host.haiku@gmx.de> 11 */ 11 12 12 13 /* String class supporting common string operations. */ 13 14 … … 31 32 #define REPLACE_ALL 0x7FFFFFFF 32 33 33 34 34 // helper macro that is used to fall into debugger if a given param check fails:35 #ifdef DEBUG36 #define CHECK_PARAM( expr, msg) \37 if (!(expr)) \38 debugger( msg)39 40 #define CHECK_PARAM_RET( expr, msg, retval) \41 if (!(expr)) \42 debugger( msg)43 44 #define CHECK_PARAM_VOID( expr, msg) \45 if (!(expr)) \46 debugger( msg)47 #else48 #define CHECK_PARAM( expr, msg) \49 if (!(expr)) \50 return *this51 52 #define CHECK_PARAM_RET( expr, msg, retval) \53 if (!(expr)) \54 return (retval);55 56 #define CHECK_PARAM_VOID( expr, msg)57 #endif58 59 60 //! helper class for BString::_ReplaceAtPositions():61 class BString::PosVect {62 public:63 PosVect();64 ~PosVect();65 66 bool Add(int32 pos);67 68 inline int32 ItemAt(int32 index) const69 { return fBuffer[index]; }70 inline int32 CountItems() const71 { return fSize; }72 73 private:74 int32 fSize;75 int32 fBufferSize;76 int32* fBuffer;77 };78 79 80 35 const char *B_EMPTY_STRING = ""; 81 36 82 37 83 38 // helper function, returns minimum of two given values (but clamps to 0): 84 39 static inline int32 85 min_clamp0(int32 num1, int32 num2) 86 { 40 min_clamp0(int32 num1, int32 num2) 41 { 87 42 if (num1 < num2) 88 43 return num1 > 0 ? num1 : 0; 89 44 … … 93 48 94 49 //! helper function, returns length of given string (but clamps to given maximum): 95 50 static inline int32 96 strlen_clamp(const char* str, int32 max) 51 strlen_clamp(const char* str, int32 max) 97 52 { 98 53 // this should yield 0 for max<0: 99 54 int32 length = 0; … … 105 60 106 61 107 62 //! helper function, massages given pointer into a legal c-string: 108 static inline const char * 109 safestr(const char* str) 63 static inline const char * 64 safestr(const char* str) 110 65 { 111 66 return str ? str : ""; 112 67 } 113 68 114 69 115 // #pragma mark - 70 // #pragma mark - PosVect 116 71 117 72 118 BString::PosVect::PosVect() 119 : 120 fSize(0), 121 fBufferSize(20), 122 fBuffer(NULL) 73 class BString::PosVect { 74 public: 75 PosVect() 76 : fSize(0), 77 fBufferSize(20), 78 fBuffer(NULL) { } 79 80 ~PosVect() 81 { 82 free(fBuffer); 83 } 84 85 bool Add(int32 pos) 86 { 87 if (fBuffer == NULL || fSize == fBufferSize) { 88 if (fBuffer != NULL) 89 fBufferSize *= 2; 90 91 int32* newBuffer = NULL; 92 newBuffer = (int32 *)realloc(fBuffer, fBufferSize * sizeof(int32)); 93 if (newBuffer == NULL) 94 return false; 95 96 fBuffer = newBuffer; 97 } 98 99 fBuffer[fSize++] = pos; 100 return true; 101 } 102 103 inline int32 ItemAt(int32 index) const 104 { return fBuffer[index]; } 105 inline int32 CountItems() const 106 { return fSize; } 107 108 private: 109 int32 fSize; 110 int32 fBufferSize; 111 int32* fBuffer; 112 }; 113 114 115 // #pragma mark - BStringRef 116 117 118 BStringRef::BStringRef(BString& string, int32 position) 119 : fString(string), fPosition(position) 123 120 { 124 121 } 125 122 126 123 127 BString ::PosVect::~PosVect()124 BStringRef::operator char() const 128 125 { 129 free(fBuffer);126 return fPosition < fString.Length() ? fString.fPrivateData[fPosition] : 0; 130 127 } 131 128 132 129 133 bool 134 BString ::PosVect::Add(int32 pos)130 BStringRef& 131 BStringRef::operator=(char c) 135 132 { 136 if (fBuffer == NULL || fSize == fBufferSize) { 137 if (fBuffer != NULL) 138 fBufferSize *= 2; 133 fString._Detach(); 134 fString.fPrivateData[fPosition] = c; 135 return *this; 136 } 139 137 140 int32* newBuffer = (int32 *)realloc(fBuffer, fBufferSize * sizeof(int32));141 if (newBuffer == NULL)142 return false;143 138 144 fBuffer = newBuffer; 145 } 139 BStringRef& 140 BStringRef::operator=(const BStringRef &rc) 141 { 142 return operator=(rc.fString.fPrivateData[rc.fPosition]); 143 } 146 144 147 fBuffer[fSize++] = pos; 148 return true; 145 146 const char* 147 BStringRef::operator&() const 148 { 149 return &(fString.fPrivateData[fPosition]); 149 150 } 150 151 151 152 153 char* 154 BStringRef::operator&() 155 { 156 fString._Detach(); 157 fString._SetReferenceCount(-1); 158 return &(fString.fPrivateData[fPosition]); 159 } 160 161 152 162 // #pragma mark - BString 153 163 154 164 155 165 BString::BString() 156 : fPrivateData(NULL) 166 : fPrivateData(NULL) 157 167 { 168 _Init("", 0); 158 169 } 159 170 160 171 161 172 BString::BString(const char* string) 162 173 : fPrivateData(NULL) 163 174 { 164 if (string != NULL) 165 _Init(string, strlen(string)); 175 _Init(string, strlen(safestr(string))); 166 176 } 167 177 168 178 169 BString::BString(const BString &string)170 : fPrivateData(NULL) 179 BString::BString(const BString& string) 180 : fPrivateData(NULL) 171 181 { 172 _Init(string.String(), string.Length()); 182 // check if source is sharable - if so, share else clone 183 if (atomic_get(&(*(((vint32*)string.fPrivateData) - 2))) >= 0) { 184 fPrivateData = string.fPrivateData; 185 atomic_add(&(*(((vint32*)fPrivateData) - 2)), 1); 186 } else 187 fPrivateData = _Clone(string.fPrivateData, string.Length()); 173 188 } 174 189 175 190 176 BString::BString(const char *string, int32 maxLength)177 : fPrivateData(NULL) 191 BString::BString(const char* string, int32 maxLength) 192 : fPrivateData(NULL) 178 193 { 179 if (string != NULL) 180 _Init(string, strlen_clamp(string, maxLength)); 194 _Init(string, strlen_clamp(safestr(string), maxLength)); 181 195 } 182 196 183 197 184 198 BString::~BString() 185 199 { 186 if ( fPrivateData)187 free(fPrivateData - sizeof(int32));200 if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1) 201 free(fPrivateData - (2 * sizeof(int32))); 188 202 } 189 203 190 204 191 205 // #pragma mark - Access 192 206 193 207 194 208 int32 195 209 BString::CountChars() const 196 210 { … … 214 228 215 229 216 230 BString& 217 BString::operator=(const BString &string)231 BString::operator=(const BString& string) 218 232 { 219 if (&string != this) // Avoid auto-assignment 220 _DoAssign(string.String(), string.Length()); 221 return *this; 233 return SetTo(string); 222 234 } 223 235 224 236 225 237 BString& 226 BString::operator=(const char *str)238 BString::operator=(const char* string) 227 239 { 228 if (str != NULL) 229 _DoAssign(str, strlen(str)); 230 else 231 _Alloc(0); 232 240 if (string) 241 SetTo(string, strlen(string)); 233 242 return *this; 234 243 } 235 244 … … 237 246 BString& 238 247 BString::operator=(char c) 239 248 { 240 _DoAssign(&c, 1); 241 return *this; 249 return SetTo(c, 1); 242 250 } 243 251 244 252 245 253 BString& 246 BString::SetTo(const char *str, int32 maxLength)254 BString::SetTo(const char* string, int32 maxLength) 247 255 { 248 if (str != NULL) 249 _DoAssign(str, strlen_clamp(str, maxLength)); 250 else 251 _Alloc(0); 256 maxLength = strlen_clamp(safestr(string), maxLength); 257 if (_DetachWith("", maxLength) == B_OK) 258 memcpy(fPrivateData, string, maxLength); 252 259 253 260 return *this; 254 261 } 255 262 256 263 257 264 BString& 258 BString::SetTo(const BString &from)265 BString::SetTo(const BString& string) 259 266 { 260 if (&from != this) { 261 // Avoid auto-assignment 262 _DoAssign(from.String(), from.Length()); 267 // we share the information already 268 if (fPrivateData == string.fPrivateData) 269 return *this; 270 271 // check if we are shared by someone else 272 if (atomic_get(&(*(((vint32*)fPrivateData) - 2))) > 1) { 273 // we share our data with someone else 274 if (atomic_add(&(*((vint32*)fPrivateData - 2)), -1) < 1) { 275 // someone else decrement, we are the last owner 276 free(fPrivateData - (2 * sizeof(int32))); 277 } else { 278 ; // there is still someone who shares our data 279 } 280 } else { 281 // we don't share our data with someone else 282 // or we are marked as unsharable, but this will go away 283 free(fPrivateData - (2 * sizeof(int32))); 263 284 } 285 286 // if source is sharable share, otherwise clone 287 if (atomic_get(&(*(((vint32*)string.fPrivateData) - 2))) >= 0) { 288 fPrivateData = string.fPrivateData; 289 atomic_add(&(*(((vint32*)fPrivateData) - 2)), 1); 290 } else 291 fPrivateData = _Clone(string.fPrivateData, string.Length()); 292 264 293 return *this; 265 294 } 266 295 267 296 268 297 BString& 269 BString::Adopt(BString &from)298 BString::Adopt(BString& from) 270 299 { 271 if (&from == this) { 272 // Avoid auto-adoption 273 return *this; 274 } 300 SetTo(from); 301 from.SetTo(""); 275 302 276 if (fPrivateData)277 free(fPrivateData - sizeof(int32));278 279 /* "steal" the data from the given BString */280 fPrivateData = from.fPrivateData;281 from.fPrivateData = NULL;282 283 303 return *this; 284 304 } 285 305 286 306 287 307 BString& 288 BString::SetTo(const BString &string, int32 length)308 BString::SetTo(const BString& string, int32 maxLength) 289 309 { 290 if (&string != this) // Avoid auto-assignment 291 _DoAssign(string.String(), min_clamp0(length, string.Length())); 310 if (fPrivateData != string.fPrivateData 311 // make sure we reassing in case length is different 312 || (fPrivateData == string.fPrivateData && Length() != maxLength)) { 313 maxLength = min_clamp0(maxLength, string.Length()); 314 if (_DetachWith("", maxLength) == B_OK) 315 memcpy(fPrivateData, string.fPrivateData, maxLength); 316 } 292 317 return *this; 293 318 } 294 319 295 320 296 321 BString& 297 BString::Adopt(BString &from, int32 length)322 BString::Adopt(BString& from, int32 maxLength) 298 323 { 299 if (&from == this) // Avoid auto-adoption300 return *this;324 SetTo(from, maxLength); 325 from.SetTo(""); 301 326 302 int32 len = min_clamp0(length, from.Length());303 304 if (fPrivateData)305 free(fPrivateData - sizeof(int32));306 307 /* "steal" the data from the given BString */308 fPrivateData = from.fPrivateData;309 from.fPrivateData = NULL;310 311 if (len < Length())312 _Alloc(len);313 314 327 return *this; 315 328 } 316 329 … … 320 333 { 321 334 if (count < 0) 322 335 count = 0; 323 int32 curLen = Length(); 324 325 if (curLen == count || _GrowBy(count - curLen)) 336 337 if (_DetachWith("", count) == B_OK) 326 338 memset(fPrivateData, c, count); 327 return *this; 339 return *this; 328 340 } 329 341 330 342 331 343 // #pragma mark - Substring copying 332 344 333 345 334 BString & 335 BString::CopyInto(BString &into, int32 fromOffset, int32 length) const 346 BString& 347 BString::CopyInto(BString& into, int32 fromOffset, 348 int32 length) const 336 349 { 337 if (&into != this) { 338 CHECK_PARAM_RET(fromOffset >= 0, "'fromOffset' must not be negative!", 339 into); 340 CHECK_PARAM_RET(fromOffset <= Length(), "'fromOffset' exceeds length!", 341 into); 342 into.SetTo(String() + fromOffset, length); 343 } 350 if (this != &into) 351 into.SetTo(fPrivateData + fromOffset, length); 344 352 return into; 345 353 } 346 354 347 355 348 356 void 349 BString::CopyInto(char *into, int32 fromOffset, int32 length) const357 BString::CopyInto(char* into, int32 fromOffset, int32 length) const 350 358 { 351 if (into != NULL) { 352 CHECK_PARAM_VOID(fromOffset >= 0, "'fromOffset' must not be negative!"); 353 CHECK_PARAM_VOID(fromOffset <= Length(), "'fromOffset' exceeds length!"); 354 int32 len = min_clamp0(length, Length() - fromOffset); 355 memcpy(into, fPrivateData + fromOffset, len); 359 if (into) { 360 length = min_clamp0(length, Length() - fromOffset); 361 memcpy(into, fPrivateData + fromOffset, length); 356 362 } 357 363 } 358 364 … … 361 367 362 368 363 369 BString& 364 BString::operator+=(const char *str)370 BString::operator+=(const char* string) 365 371 { 366 if (str != NULL)367 _DoAppend(str , strlen(str));372 if (string) 373 _DoAppend(string, strlen(string)); 368 374 return *this; 369 375 } 370 376 … … 378 384 379 385 380 386 BString& 381 BString::Append(const BString &string, int32 length)387 BString::Append(const BString& string, int32 length) 382 388 { 383 _DoAppend(string. String(), min_clamp0(length, string.Length()));389 _DoAppend(string.fPrivateData, min_clamp0(length, string.Length())); 384 390 return *this; 385 391 } 386 392 387 393 388 394 BString& 389 BString::Append(const char *str, int32 length)395 BString::Append(const char* string, int32 length) 390 396 { 391 if (str != NULL) { 392 int32 len = strlen_clamp(str, length); 393 _DoAppend(str, len); 394 } 397 if (string) 398 _DoAppend(string, strlen_clamp(string, length)); 395 399 return *this; 396 400 } 397 401 … … 400 404 BString::Append(char c, int32 count) 401 405 { 402 406 int32 len = Length(); 403 if (count > 0 && _ GrowBy(count))407 if (count > 0 && _DoAppend("", count)) 404 408 memset(fPrivateData + len, c, count); 405 406 409 return *this; 407 410 } 408 411 … … 411 414 412 415 413 416 BString& 414 BString::Prepend(const char *str)417 BString::Prepend(const char* string) 415 418 { 416 if (str != NULL)417 _DoPrepend(str , strlen(str));419 if (string) 420 _DoPrepend(string, strlen(string)); 418 421 return *this; 419 422 } 420 423 421 424 422 // Prepend423 425 BString& 424 BString::Prepend(const BString &string)426 BString::Prepend(const BString& string) 425 427 { 426 if ( &string != this)427 _DoPrepend(string. String(), string.Length());428 if (fPrivateData != string.fPrivateData) 429 _DoPrepend(string.fPrivateData, string.Length()); 428 430 return *this; 429 431 } 430 432 431 433 432 // Prepend433 434 BString& 434 BString::Prepend(const char *str, int32 length)435 BString::Prepend(const char* string, int32 length) 435 436 { 436 if (str != NULL) { 437 int32 len = strlen_clamp(str, length); 438 _DoPrepend(str, len); 439 } 437 if (string) 438 _DoPrepend(string, strlen_clamp(string, length)); 440 439 return *this; 441 440 } 442 441 443 442 444 // Prepend445 443 BString& 446 BString::Prepend(const BString &string, int32 len)444 BString::Prepend(const BString& string, int32 length) 447 445 { 448 if ( &string != this)449 _DoPrepend(string. String(), min_clamp0(len, string.Length()));446 if (fPrivateData != string.fPrivateData) 447 _DoPrepend(string.fPrivateData, min_clamp0(length, string.Length())); 450 448 return *this; 451 449 } 452 450 453 451 454 // Prepend455 452 BString& 456 453 BString::Prepend(char c, int32 count) 457 454 { 458 if (count > 0 && _ OpenAtBy(0, count))455 if (count > 0 && _DoPrepend("", count)) 459 456 memset(fPrivateData, c, count); 460 461 457 return *this; 462 458 } 463 459 … … 466 462 467 463 468 464 BString& 469 BString::Insert(const char *str, int32 pos)465 BString::Insert(const char* string, int32 position) 470 466 { 471 if (str != NULL) { 472 CHECK_PARAM(pos <= Length(), "'pos' exceeds length!"); 473 int32 len = (int32)strlen(str); 474 if (pos < 0) { 475 int32 skipLen = min_clamp0(-1 * pos, len); 476 str += skipLen; 467 if (string && position <= Length()) { 468 int32 len = int32(strlen(string)); 469 if (position < 0) { 470 int32 skipLen = min_clamp0(-1 * position, len); 471 string += skipLen; 477 472 len -= skipLen; 478 pos = 0;479 } else 480 pos = min_clamp0(pos, Length());481 if (_OpenAtBy(pos, len))482 memcpy(fPrivateData + pos, str, len);473 position = 0; 474 } else { 475 position = min_clamp0(position, Length()); 476 } 477 _DoInsert(string, position, len); 483 478 } 484 479 return *this; 485 480 } 486 481 487 482 488 // Insert489 483 BString& 490 BString::Insert(const char *str, int32 length, int32 pos)484 BString::Insert(const char* string, int32 length, int32 position) 491 485 { 492 if (str != NULL) { 493 CHECK_PARAM(pos <= Length(), "'pos' exceeds length!"); 494 int32 len = strlen_clamp(str, length); 495 if (pos < 0) { 496 int32 skipLen = min_clamp0(-1 * pos, len); 497 str += skipLen; 486 if (string && position <= Length()) { 487 int32 len = strlen_clamp(string, length); 488 if (position < 0) { 489 int32 skipLen = min_clamp0(-1 * position, len); 490 string += skipLen; 498 491 len -= skipLen; 499 pos = 0;500 } else 501 pos = min_clamp0(pos, Length());502 if (_OpenAtBy(pos, len))503 memcpy(fPrivateData + pos, str, len);492 position = 0; 493 } else { 494 position = min_clamp0(position, Length()); 495 } 496 _DoInsert(string, position, len); 504 497 } 505 498 return *this; 506 499 } 507 500 508 501 509 // Insert510 502 BString& 511 BString::Insert(const char *str, int32 fromOffset, int32 length, int32 pos) 503 BString::Insert(const char* string, int32 fromOffset, int32 length, 504 int32 position) 512 505 { 513 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!"); 514 return Insert(str + fromOffset, length, pos); 506 if (string) 507 Insert(string + fromOffset, length, position); 508 return *this; 515 509 } 516 510 517 511 518 // Insert519 512 BString& 520 BString::Insert(const BString &string, int32 pos)513 BString::Insert(const BString& string, int32 position) 521 514 { 522 if ( &string != this)523 Insert(string. String(), pos); //TODO: Optimize524 return *this; 515 if ((fPrivateData != string.fPrivateData) && string.Length() > 0) 516 Insert(string.fPrivateData, position); 517 return *this; 525 518 } 526 519 527 520 528 // Insert529 521 BString& 530 BString::Insert(const BString &string, int32 length, int32 pos) 522 BString::Insert(const BString& string, int32 length, 523 int32 position) 531 524 { 532 if ( &string != this)533 Insert(string.String(), length, pos ); //TODO: Optimize525 if ((fPrivateData != string.fPrivateData) && string.Length() > 0) 526 Insert(string.String(), length, position); 534 527 return *this; 535 528 } 536 529 537 530 538 // Insert539 531 BString& 540 BString::Insert(const BString &string, int32 fromOffset, int32 length, int32 pos) 532 BString::Insert(const BString& string, int32 fromOffset, 533 int32 length, int32 position) 541 534 { 542 if (&string != this) { 543 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!"); 544 Insert(string.String() + fromOffset, length, pos); 545 } 535 if ((fPrivateData != string.fPrivateData) && string.Length() > 0) 536 Insert(string.String() + fromOffset, length, position); 546 537 return *this; 547 538 } 548 539 549 540 550 // Insert551 541 BString& 552 BString::Insert(char c, int32 count, int32 pos )542 BString::Insert(char c, int32 count, int32 position) 553 543 { 554 CHECK_PARAM(pos <= Length(), "'pos' exceeds length!"); 555 if (pos < 0) { 556 count = max_c(count + pos, 0); 557 pos = 0; 544 if (position < 0) { 545 count = MAX(count + position, 0); 546 position = 0; 558 547 } else 559 pos = min_clamp0(pos, Length());560 561 if (count > 0 && _ OpenAtBy(pos, count))562 memset(fPrivateData + pos , c, count);563 548 position = min_clamp0(position, Length()); 549 550 if (count > 0 && _DoInsert("", position, count)) 551 memset(fPrivateData + position, c, count); 552 564 553 return *this; 565 554 } 566 555 … … 574 563 if (newLength < 0) 575 564 newLength = 0; 576 565 577 int32 curLen = Length(); 566 if (newLength < Length()) 567 // ignore lazy, since we might detach 568 _DetachWith(fPrivateData, newLength); 578 569 579 if (newLength < curLen) {580 if (lazy) {581 // don't free memory yet, just set new length582 _SetLength(newLength);583 fPrivateData[newLength] = '\0';584 } else585 _Alloc(newLength);586 }587 588 570 return *this; 589 571 } 590 572 591 573 592 // Remove593 574 BString& 594 575 BString::Remove(int32 from, int32 length) 595 576 { 596 int32 len = Length(); 597 if (from < 0) { 598 int32 skipLen = min_clamp0(from, len); 599 len -= skipLen; 600 from = 0; 601 } else 602 from = min_clamp0(from, len); 603 _ShrinkAtBy(from, min_clamp0(length, len - from)); 577 if (length > 0 && from < Length()) 578 _ShrinkAtBy(from, min_clamp0(length, (Length() - from))); 604 579 return *this; 605 580 } 606 581 607 582 608 // Remove609 583 BString& 610 BString::RemoveFirst(const BString &string)584 BString::RemoveFirst(const BString& string) 611 585 { 612 586 if (string.Length() > 0) { 613 587 int32 pos = _ShortFindAfter(string.String(), string.Length()); … … 618 592 } 619 593 620 594 621 // Remove622 595 BString& 623 BString::RemoveLast(const BString &string)596 BString::RemoveLast(const BString& string) 624 597 { 625 598 int32 pos = _FindBefore(string.String(), Length(), string.Length()); 626 599 if (pos >= 0) … … 630 603 } 631 604 632 605 633 // Remove634 606 BString& 635 BString::RemoveAll(const BString &string)607 BString::RemoveAll(const BString& string) 636 608 { 609 if (string.Length() == 0 || Length() == 0 || FindFirst(string) < 0) 610 return *this; 611 612 if (_Detach() != B_OK) 613 return *this; 614 637 615 return _DoReplace(string.String(), "", REPLACE_ALL, 0, KEEP_CASE); 638 616 } 639 617 640 618 641 // Remove642 619 BString& 643 BString::RemoveFirst(const char *string)620 BString::RemoveFirst(const char* string) 644 621 { 645 622 int32 length = string ? strlen(string) : 0; 646 623 if (length > 0) { … … 652 629 } 653 630 654 631 655 // Remove656 632 BString& 657 BString::RemoveLast(const char *string)633 BString::RemoveLast(const char* string) 658 634 { 659 635 int32 length = string ? strlen(string) : 0; 660 636 if (length > 0) { … … 666 642 } 667 643 668 644 669 // Remove670 645 BString& 671 BString::RemoveAll(const char *str)646 BString::RemoveAll(const char* string) 672 647 { 673 return _DoReplace(str, "", REPLACE_ALL, 0, KEEP_CASE); 648 if (!string || Length() == 0 || FindFirst(string) < 0) 649 return *this; 650 651 if (_Detach() != B_OK) 652 return *this; 653 654 return _DoReplace(string, "", REPLACE_ALL, 0, KEEP_CASE); 674 655 } 675 656 676 657 677 // Remove678 658 BString& 679 BString::RemoveSet(const char *setOfCharsToRemove)659 BString::RemoveSet(const char* setOfCharsToRemove) 680 660 { 681 661 return ReplaceSet(setOfCharsToRemove, ""); 682 662 } 683 663 684 664 685 // MoveInto686 665 BString& 687 BString::MoveInto(BString &into, int32 from, int32 length)666 BString::MoveInto(BString& into, int32 from, int32 length) 688 667 { 689 CHECK_PARAM_RET(from >= 0, "'from' must not be negative!", into); 690 CHECK_PARAM_RET(from <= Length(), "'from' exceeds length!", into); 691 int32 len = min_clamp0(length, Length() - from); 692 if (&into == this) { 693 /* TODO: [zooey]: to be activated later (>R1): 694 // strings are identical, just move the data: 695 if (from>0 && fPrivateData) 696 memmove( fPrivateData, fPrivateData+from, len); 697 Truncate( len); 698 */ 699 return *this; 668 if (length) { 669 CopyInto(into, from, length); 670 Remove(from, length); 700 671 } 701 into.SetTo(String() + from, len);702 _ShrinkAtBy(from, len);703 704 672 return into; 705 673 } 706 674 707 675 708 // MoveInto709 676 void 710 BString::MoveInto(char *into, int32 from, int32 length)677 BString::MoveInto(char* into, int32 from, int32 length) 711 678 { 712 if (into != NULL) { 713 CHECK_PARAM_VOID(from >= 0, "'from' must not be negative!"); 714 CHECK_PARAM_VOID(from <= Length(), "'from' exceeds length!"); 715 int32 len = min_clamp0(length, Length() - from); 716 memcpy(into, String() + from, len); 717 into[len] = '\0'; 718 _ShrinkAtBy(from, len); 679 if (into) { 680 CopyInto(into, from, length); 681 Remove(from, length); 719 682 } 720 683 } 721 684 722 685 723 /*---- Compare functions ---------------------------------------------------*/ 686 // #pragma mark - Compare functions 687 688 724 689 bool 725 BString::operator<(const char *string) const690 BString::operator<(const char* string) const 726 691 { 727 692 return strcmp(String(), safestr(string)) < 0; 728 693 } 729 694 730 695 731 696 bool 732 BString::operator<=(const char *string) const697 BString::operator<=(const char* string) const 733 698 { 734 699 return strcmp(String(), safestr(string)) <= 0; 735 700 } 736 701 737 702 738 703 bool 739 BString::operator==(const char *string) const704 BString::operator==(const char* string) const 740 705 { 741 706 return strcmp(String(), safestr(string)) == 0; 742 707 } 743 708 744 709 745 710 bool 746 BString::operator>=(const char *string) const711 BString::operator>=(const char* string) const 747 712 { 748 713 return strcmp(String(), safestr(string)) >= 0; 749 714 } 750 715 751 716 752 717 bool 753 BString::operator>(const char *string) const718 BString::operator>(const char* string) const 754 719 { 755 720 return strcmp(String(), safestr(string)) > 0; 756 721 } 757 722 758 723 759 // #pragma mark - Comparison724 // #pragma mark - strcmp()-style compare functions 760 725 761 726 762 727 int 763 BString::Compare(const BString &string) const728 BString::Compare(const BString& string) const 764 729 { 765 730 return strcmp(String(), string.String()); 766 731 } 767 732 768 733 769 734 int 770 BString::Compare(const char *string) const735 BString::Compare(const char* string) const 771 736 { 772 737 return strcmp(String(), safestr(string)); 773 738 } 774 739 775 740 776 741 int 777 BString::Compare(const BString &string, int32 n) const742 BString::Compare(const BString& string, int32 length) const 778 743 { 779 return strncmp(String(), string.String(), n);744 return strncmp(String(), string.String(), length); 780 745 } 781 746 782 747 783 748 int 784 BString::Compare(const char *string, int32 n) const749 BString::Compare(const char* string, int32 length) const 785 750 { 786 return strncmp(String(), safestr(string), n);751 return strncmp(String(), safestr(string), length); 787 752 } 788 753 789 754 790 755 int 791 BString::ICompare(const BString &string) const756 BString::ICompare(const BString& string) const 792 757 { 793 758 return strcasecmp(String(), string.String()); 794 759 } 795 760 796 761 797 762 int 798 BString::ICompare(const char *str) const763 BString::ICompare(const char* string) const 799 764 { 800 return strcasecmp(String(), safestr(str ));765 return strcasecmp(String(), safestr(string)); 801 766 } 802 767 803 768 804 769 int 805 BString::ICompare(const BString &string, int32 n) const770 BString::ICompare(const BString& string, int32 length) const 806 771 { 807 return strncasecmp(String(), string.String(), n);772 return strncasecmp(String(), string.String(), length); 808 773 } 809 774 810 775 811 776 int 812 BString::ICompare(const char *str, int32 n) const777 BString::ICompare(const char* string, int32 length) const 813 778 { 814 return strncasecmp(String(), safestr(str ), n);779 return strncasecmp(String(), safestr(string), length); 815 780 } 816 781 817 782 … … 819 784 820 785 821 786 int32 822 BString::FindFirst(const BString &string) const787 BString::FindFirst(const BString& string) const 823 788 { 824 789 return _ShortFindAfter(string.String(), string.Length()); 825 790 } 826 791 827 792 828 // FindFirst829 793 int32 830 BString::FindFirst(const char *string) const794 BString::FindFirst(const char* string) const 831 795 { 832 796 if (string == NULL) 833 797 return B_BAD_VALUE; … … 836 800 } 837 801 838 802 839 // FindFirst840 803 int32 841 BString::FindFirst(const BString &string, int32 fromOffset) const804 BString::FindFirst(const BString& string, int32 fromOffset) const 842 805 { 843 806 if (fromOffset < 0) 844 807 return B_ERROR; … … 848 811 } 849 812 850 813 851 // FindFirst852 814 int32 853 BString::FindFirst(const char *string, int32 fromOffset) const815 BString::FindFirst(const char* string, int32 fromOffset) const 854 816 { 855 817 if (string == NULL) 856 818 return B_BAD_VALUE; 819 857 820 if (fromOffset < 0) 858 821 return B_ERROR; 859 822 860 823 return _FindAfter(string, min_clamp0(fromOffset, Length()), 861 strlen(s tring));824 strlen(safestr(string))); 862 825 } 863 826 864 827 865 // FindFirst866 828 int32 867 829 BString::FindFirst(char c) const 868 { 830 { 869 831 const char *start = String(); 870 832 const char *end = String() + Length(); 871 833 872 / * Scans the string until we find the character, */873 / * or we hit the string's end */834 // Scans the string until we found the 835 // character, or we reach the string's start 874 836 while (start != end && *start != c) { 875 837 start++; 876 838 } … … 882 844 } 883 845 884 846 885 // FindFirst886 847 int32 887 848 BString::FindFirst(char c, int32 fromOffset) const 888 849 { … … 892 853 const char *start = String() + min_clamp0(fromOffset, Length()); 893 854 const char *end = String() + Length(); 894 855 895 / * Scans the string until we found the character, */896 / * or we hit the string's end */856 // Scans the string until we found the 857 // character, or we reach the string's start 897 858 while (start < end && *start != c) { 898 859 start++; 899 860 } … … 905 866 } 906 867 907 868 908 // FindLast909 869 int32 910 BString::FindLast(const BString &string) const870 BString::FindLast(const BString& string) const 911 871 { 912 872 return _FindBefore(string.String(), Length(), string.Length()); 913 873 } 914 874 915 875 916 // FindLast917 876 int32 918 BString::FindLast(const char *string) const877 BString::FindLast(const char* string) const 919 878 { 920 879 if (string == NULL) 921 880 return B_BAD_VALUE; 922 881 923 return _FindBefore(string, Length(), strlen(s tring));882 return _FindBefore(string, Length(), strlen(safestr(string))); 924 883 } 925 884 926 885 927 // FindLast928 886 int32 929 BString::FindLast(const BString &string, int32 beforeOffset) const887 BString::FindLast(const BString& string, int32 beforeOffset) const 930 888 { 931 889 if (beforeOffset < 0) 932 890 return B_ERROR; 933 891 934 return _FindBefore(string.String(), min_clamp0(beforeOffset, Length()), 935 string.Length()); 892 return _FindBefore(string.String(), min_clamp0(beforeOffset, Length()), 893 string.Length()); 936 894 } 937 895 938 896 939 // FindLast940 897 int32 941 BString::FindLast(const char *string, int32 beforeOffset) const898 BString::FindLast(const char* string, int32 beforeOffset) const 942 899 { 943 900 if (string == NULL) 944 901 return B_BAD_VALUE; 902 945 903 if (beforeOffset < 0) 946 904 return B_ERROR; 947 905 948 return _FindBefore(string, min_clamp0(beforeOffset, Length()), strlen(string)); 906 return _FindBefore(string, min_clamp0(beforeOffset, Length()), 907 strlen(safestr(string))); 949 908 } 950 909 951 910 952 // FindLast953 911 int32 954 912 BString::FindLast(char c) const 955 913 { 956 914 const char *start = String(); 957 915 const char *end = String() + Length(); 958 916 959 / * Scans the string backwards until we found the character, */960 / * or we reach the string's start */917 // Scans the string backwards until we found 918 // the character, or we reach the string's start 961 919 while (end != start && *end != c) { 962 920 end--; 963 921 } … … 969 927 } 970 928 971 929 972 // FindLast973 930 int32 974 931 BString::FindLast(char c, int32 beforeOffset) const 975 932 { … … 979 936 const char *start = String(); 980 937 const char *end = String() + min_clamp0(beforeOffset, Length()); 981 938 982 / * Scans the string backwards until we found the character, */983 / * or we reach the string's start */939 // Scans the string backwards until we found 940 // the character, or we reach the string's start 984 941 while (end > start && *end != c) { 985 942 end--; 986 943 } … … 993 950 994 951 995 952 int32 996 BString::IFindFirst(const BString &string) const953 BString::IFindFirst(const BString& string) const 997 954 { 998 955 return _IFindAfter(string.String(), 0, string.Length()); 999 956 } 1000 957 1001 958 1002 959 int32 1003 BString::IFindFirst(const char *string) const960 BString::IFindFirst(const char* string) const 1004 961 { 1005 962 if (string == NULL) 1006 963 return B_BAD_VALUE; 1007 964 1008 return _IFindAfter(string, 0, strlen(s tring));965 return _IFindAfter(string, 0, strlen(safestr(string))); 1009 966 } 1010 967 1011 968 1012 969 int32 1013 BString::IFindFirst(const BString &string, int32 fromOffset) const970 BString::IFindFirst(const BString& string, int32 fromOffset) const 1014 971 { 1015 972 if (fromOffset < 0) 1016 973 return B_ERROR; 1017 974 1018 return _IFindAfter(string.String(), min_clamp0(fromOffset, Length()), 975 return _IFindAfter(string.String(), min_clamp0(fromOffset, Length()), 1019 976 string.Length()); 1020 977 } 1021 978 1022 979 1023 980 int32 1024 BString::IFindFirst(const char *string, int32 fromOffset) const981 BString::IFindFirst(const char* string, int32 fromOffset) const 1025 982 { 1026 983 if (string == NULL) 1027 984 return B_BAD_VALUE; 985 1028 986 if (fromOffset < 0) 1029 987 return B_ERROR; 1030 988 1031 return _IFindAfter(string, min_clamp0(fromOffset,Length()), strlen(string)); 989 return _IFindAfter(string, min_clamp0(fromOffset,Length()), 990 strlen(safestr(string))); 1032 991 } 1033 992 1034 993 1035 994 int32 1036 BString::IFindLast(const BString &string) const995 BString::IFindLast(const BString& string) const 1037 996 { 1038 997 return _IFindBefore(string.String(), Length(), string.Length()); 1039 998 } 1040 999 1041 1000 1042 1001 int32 1043 BString::IFindLast(const char *string) const1002 BString::IFindLast(const char* string) const 1044 1003 { 1045 1004 if (string == NULL) 1046 1005 return B_BAD_VALUE; 1047 1006 1048 return _IFindBefore(string, Length(), strlen(s tring));1007 return _IFindBefore(string, Length(), strlen(safestr(string))); 1049 1008 } 1050 1009 1051 1010 1052 1011 int32 1053 BString::IFindLast(const BString &string, int32 beforeOffset) const1012 BString::IFindLast(const BString& string, int32 beforeOffset) const 1054 1013 { 1055 1014 if (beforeOffset < 0) 1056 1015 return B_ERROR; 1057 1016 1058 return _IFindBefore(string.String(), min_clamp0(beforeOffset, Length()), 1017 return _IFindBefore(string.String(), min_clamp0(beforeOffset, Length()), 1059 1018 string.Length()); 1060 1019 } 1061 1020 1062 1021 1063 1022 int32 1064 BString::IFindLast(const char *string, int32 beforeOffset) const1023 BString::IFindLast(const char* string, int32 beforeOffset) const 1065 1024 { 1066 1025 if (string == NULL) 1067 1026 return B_BAD_VALUE; 1027 1068 1028 if (beforeOffset < 0) 1069 1029 return B_ERROR; 1070 1030 1071 1031 return _IFindBefore(string, min_clamp0(beforeOffset, Length()), 1072 strlen(s tring));1032 strlen(safestr(string))); 1073 1033 } 1074 1034 1075 1035 … … 1080 1040 BString::ReplaceFirst(char replaceThis, char withThis) 1081 1041 { 1082 1042 int32 pos = FindFirst(replaceThis); 1083 if (pos >= 0 )1043 if (pos >= 0 && _Detach() == B_OK) 1084 1044 fPrivateData[pos] = withThis; 1085 1086 1045 return *this; 1087 1046 } 1088 1047 … … 1091 1050 BString::ReplaceLast(char replaceThis, char withThis) 1092 1051 { 1093 1052 int32 pos = FindLast(replaceThis); 1094 if (pos >= 0 )1053 if (pos >= 0 && _Detach() == B_OK) 1095 1054 fPrivateData[pos] = withThis; 1096 1097 1055 return *this; 1098 1056 } 1099 1057 … … 1101 1059 BString& 1102 1060 BString::ReplaceAll(char replaceThis, char withThis, int32 fromOffset) 1103 1061 { 1104 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");1105 for (int32 pos = min_clamp0(fromOffset, Length());;) {1106 pos = FindFirst(replaceThis, pos); 1107 if (pos < 0)1108 break;1062 fromOffset = min_clamp0(fromOffset, Length()); 1063 int32 pos = FindFirst(replaceThis, fromOffset); 1064 1065 // detach and set first match 1066 if (pos >= 0 && _Detach() == B_OK) { 1109 1067 fPrivateData[pos] = withThis; 1068 for (pos = pos;;) { 1069 pos = FindFirst(replaceThis, pos); 1070 if (pos < 0) 1071 break; 1072 fPrivateData[pos] = withThis; 1073 } 1110 1074 } 1111 1112 1075 return *this; 1113 1076 } 1114 1077 1115 1078 1116 1079 BString& 1117 BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount, int32 fromOffset) 1080 BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount, 1081 int32 fromOffset) 1118 1082 { 1119 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!"); 1120 if (maxReplaceCount > 0) { 1121 for (int32 pos = min_clamp0(fromOffset, Length()); 1122 maxReplaceCount > 0; maxReplaceCount--) { 1083 fromOffset = min_clamp0(fromOffset, Length()); 1084 int32 pos = FindFirst(replaceThis, fromOffset); 1085 1086 if (maxReplaceCount > 0 && pos >= 0 && _Detach() == B_OK) { 1087 maxReplaceCount--; 1088 fPrivateData[pos] = withThis; 1089 for (pos = pos; maxReplaceCount > 0; maxReplaceCount--) { 1123 1090 pos = FindFirst(replaceThis, pos); 1124 1091 if (pos < 0) 1125 1092 break; … … 1131 1098 1132 1099 1133 1100 BString& 1134 BString::ReplaceFirst(const char *replaceThis, const char *withThis)1101 BString::ReplaceFirst(const char* replaceThis, const char* withThis) 1135 1102 { 1136 return _DoReplace( replaceThis, withThis, 1, 0, KEEP_CASE); 1103 if (!replaceThis || !withThis || FindFirst(replaceThis) < 0) 1104 return *this; 1105 1106 if (_Detach() != B_OK) 1107 return *this; 1108 1109 return _DoReplace(replaceThis, withThis, 1, 0, KEEP_CASE); 1137 1110 } 1138 1111 1139 1112 1140 1113 BString& 1141 BString::ReplaceLast(const char *replaceThis, const char *withThis)1114 BString::ReplaceLast(const char* replaceThis, const char* withThis) 1142 1115 { 1143 if ( replaceThis == NULL)1116 if (!replaceThis || !withThis) 1144 1117 return *this; 1145 1146 int32 firstStringLength = strlen(replaceThis);1147 int32 pos = _FindBefore(replaceThis, Length(), firstStringLength);1148 1118 1119 int32 replaceThisLength = strlen(replaceThis); 1120 int32 pos = _FindBefore(replaceThis, Length(), replaceThisLength); 1121 1149 1122 if (pos >= 0) { 1150 int32 len = (withThis ? strlen(withThis) : 0);1151 int32 difference = len - firstStringLength;1152 1123 int32 withThisLength = strlen(withThis); 1124 int32 difference = withThisLength - replaceThisLength; 1125 1153 1126 if (difference > 0) { 1154 1127 if (!_OpenAtBy(pos, difference)) 1155 1128 return *this; 1156 1129 } else if (difference < 0) { 1157 1130 if (!_ShrinkAtBy(pos, -difference)) 1158 1131 return *this; 1132 } else { 1133 if (_Detach() != B_OK) 1134 return *this; 1159 1135 } 1160 memcpy(fPrivateData + pos, withThis, len);1136 memcpy(fPrivateData + pos, withThis, withThisLength); 1161 1137 } 1162 1138 1163 1139 return *this; 1164 1140 } 1165 1141 1166 1142 1167 1143 BString& 1168 BString::ReplaceAll(const char *replaceThis, const char *withThis, int32 fromOffset) 1144 BString::ReplaceAll(const char* replaceThis, const char* withThis, 1145 int32 fromOffset) 1169 1146 { 1170 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!"); 1147 if (!replaceThis || !withThis || FindFirst(replaceThis) < 0) 1148 return *this; 1149 1150 if (_Detach() != B_OK) 1151 return *this; 1152 1171 1153 return _DoReplace(replaceThis, withThis, REPLACE_ALL, 1172 min_clamp0(fromOffset, Length()), KEEP_CASE);1154 min_clamp0(fromOffset, Length()), KEEP_CASE); 1173 1155 } 1174 1156 1175 1157 1176 1158 BString& 1177 BString::Replace(const char *replaceThis, const char *withThis, int32 maxReplaceCount, int32 fromOffset) 1159 BString::Replace(const char* replaceThis, const char* withThis, 1160 int32 maxReplaceCount, int32 fromOffset) 1178 1161 { 1179 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!"); 1162 if (!replaceThis || !withThis || maxReplaceCount <= 0 1163 || FindFirst(replaceThis) < 0) 1164 return *this; 1165 1166 if (_Detach() != B_OK) 1167 return *this; 1168 1180 1169 return _DoReplace(replaceThis, withThis, maxReplaceCount, 1181 min_clamp0(fromOffset, Length()), KEEP_CASE);1170 min_clamp0(fromOffset, Length()), KEEP_CASE); 1182 1171 } 1183 1172 1184 1173 … … 1188 1177 char tmp[2] = { replaceThis, '\0' }; 1189 1178 1190 1179 int32 pos = _IFindAfter(tmp, 0, 1); 1191 if (pos >= 0 )1180 if (pos >= 0 && _Detach() == B_OK) 1192 1181 fPrivateData[pos] = withThis; 1193 1194 1182 return *this; 1195 1183 } 1196 1184 … … 1201 1189 char tmp[2] = { replaceThis, '\0' }; 1202 1190 1203 1191 int32 pos = _IFindBefore(tmp, Length(), 1); 1204 if (pos >= 0 )1192 if (pos >= 0 && _Detach() == B_OK) 1205 1193 fPrivateData[pos] = withThis; 1206 1207 1194 return *this; 1208 1195 } 1209 1196 … … 1211 1198 BString& 1212 1199 BString::IReplaceAll(char replaceThis, char withThis, int32 fromOffset) 1213 1200 { 1214 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");1215 1216 1201 char tmp[2] = { replaceThis, '\0' }; 1202 fromOffset = min_clamp0(fromOffset, Length()); 1203 int32 pos = _IFindAfter(tmp, fromOffset, 1); 1217 1204 1218 for (int32 pos = min_clamp0(fromOffset, Length());;) { 1219 pos = _IFindAfter(tmp, pos, 1); 1220 if (pos < 0) 1221 break; 1205 if (pos >= 0 && _Detach() == B_OK) { 1222 1206 fPrivateData[pos] = withThis; 1207 for (pos = pos;;) { 1208 pos = _IFindAfter(tmp, pos, 1); 1209 if (pos < 0) 1210 break; 1211 fPrivateData[pos] = withThis; 1212 } 1223 1213 } 1224 1214 return *this; 1225 1215 } 1226 1216 1227 1217 1228 1218 BString& 1229 BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount, int32 fromOffset) 1219 BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount, 1220 int32 fromOffset) 1230 1221 { 1231 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!"); 1222 char tmp[2] = { replaceThis, '\0' }; 1223 fromOffset = min_clamp0(fromOffset, Length()); 1224 int32 pos = _IFindAfter(tmp, fromOffset, 1); 1232 1225 1233 char tmp[2] = { replaceThis, '\0' }; 1234 1235 if (fPrivateData == NULL) 1236 return *this; 1237 1238 for (int32 pos = min_clamp0(fromOffset,Length()); 1239 maxReplaceCount > 0; maxReplaceCount--) { 1240 pos = _IFindAfter(tmp, pos, 1); 1241 if (pos < 0) 1242 break; 1226 if (maxReplaceCount > 0 && pos >= 0 && _Detach() == B_OK) { 1243 1227 fPrivateData[pos] = withThis; 1228 maxReplaceCount--; 1229 for (pos = pos; maxReplaceCount > 0; maxReplaceCount--) { 1230 pos = _IFindAfter(tmp, pos, 1); 1231 if (pos < 0) 1232 break; 1233 fPrivateData[pos] = withThis; 1234 } 1244 1235 } 1236 1245 1237 return *this; 1246 1238 } 1247 1239 1248 1240 1249 1241 BString& 1250 BString::IReplaceFirst(const char *replaceThis, const char *withThis)1242 BString::IReplaceFirst(const char* replaceThis, const char* withThis) 1251 1243 { 1244 if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0) 1245 return *this; 1246 1247 if (_Detach() != B_OK) 1248 return *this; 1252 1249 return _DoReplace(replaceThis, withThis, 1, 0, IGNORE_CASE); 1253 1250 } 1254 1251 1255 1252 1256 1253 BString& 1257 BString::IReplaceLast(const char *replaceThis, const char *withThis)1254 BString::IReplaceLast(const char* replaceThis, const char* withThis) 1258 1255 { 1259 if ( replaceThis == NULL)1256 if (!replaceThis || !withThis) 1260 1257 return *this; 1261 1258 1262 int32 firstStringLength = strlen(replaceThis);1263 int32 pos = _IFindBefore(replaceThis, Length(), firstStringLength);1259 int32 replaceThisLength = strlen(replaceThis); 1260 int32 pos = _IFindBefore(replaceThis, Length(), replaceThisLength); 1264 1261 1265 1262 if (pos >= 0) { 1266 int32 len = (withThis ? strlen(withThis) : 0);1267 int32 difference = len - firstStringLength;1263 int32 withThisLength = strlen(withThis); 1264 int32 difference = withThisLength - replaceThisLength; 1268 1265 1269 1266 if (difference > 0) { 1270 1267 if (!_OpenAtBy(pos, difference)) … … 1272 1269 } else if (difference < 0) { 1273 1270 if (!_ShrinkAtBy(pos, -difference)) 1274 1271 return *this; 1272 } else { 1273 if (_Detach() != B_OK) 1274 return *this; 1275 1275 } 1276 memcpy(fPrivateData + pos, withThis, len);1276 memcpy(fPrivateData + pos, withThis, withThisLength); 1277 1277 } 1278 1278 1279 1279 return *this; … … 1281 1281 1282 1282 1283 1283 BString& 1284 BString::IReplaceAll(const char *replaceThis, const char *withThis, int32 fromOffset) 1284 BString::IReplaceAll(const char* replaceThis, const char* withThis, 1285 int32 fromOffset) 1285 1286 { 1286 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!"); 1287 if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0) 1288 return *this; 1289 1290 if (_Detach() != B_OK) 1291 return *this; 1292 1287 1293 return _DoReplace(replaceThis, withThis, REPLACE_ALL, 1288 1294 min_clamp0(fromOffset, Length()), IGNORE_CASE); 1289 1295 } 1290 1296 1291 1297 1292 1298 BString& 1293 BString::IReplace(const char *replaceThis, const char *withThis,1294 int32 maxReplaceCount, int32 fromOffset)1299 BString::IReplace(const char* replaceThis, const char* withThis, 1300 int32 maxReplaceCount, int32 fromOffset) 1295 1301 { 1296 CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!"); 1302 if (!replaceThis || !withThis || maxReplaceCount <= 0 1303 || FindFirst(replaceThis) < 0) 1304 return *this; 1305 1306 if (_Detach() != B_OK) 1307 return *this; 1308 1297 1309 return _DoReplace(replaceThis, withThis, maxReplaceCount, 1298 1310 min_clamp0(fromOffset, Length()), IGNORE_CASE); 1299 1311 } 1300 1312 1301 1313 1302 1314 BString& 1303 BString::ReplaceSet(const char *setOfChars, char with)1315 BString::ReplaceSet(const char* setOfChars, char with) 1304 1316 { 1305 if ( setOfChars == NULL)1317 if (!setOfChars || strcspn(fPrivateData, setOfChars) >= uint32(Length())) 1306 1318 return *this; 1307 1319 1320 if (_Detach() != B_OK) 1321 return *this; 1322 1308 1323 int32 offset = 0; 1309 1324 int32 length = Length(); 1310 1311 1325 for (int32 pos;;) { 1312 pos = strcspn( String()+ offset, setOfChars);1326 pos = strcspn(fPrivateData + offset, setOfChars); 1313 1327 1314 1328 offset += pos; 1315 1329 if (offset >= length) … … 1324 1338 1325 1339 1326 1340 BString& 1327 BString::ReplaceSet(const char *setOfChars, const char *with)1341 BString::ReplaceSet(const char* setOfChars, const char* with) 1328 1342 { 1329 int32 withLen = with ? strlen(with) : 0; 1330 if (withLen == 1) { 1331 // delegate simple case: 1343 if (!setOfChars || !with 1344 || strcspn(fPrivateData, setOfChars) >= uint32(Length())) 1345 return *this; 1346 1347 // delegate simple case 1348 int32 withLen = strlen(with); 1349 if (withLen == 1) 1332 1350 return ReplaceSet(setOfChars, *with); 1333 }1334 1351 1335 if ( setOfChars == NULL || fPrivateData == NULL)1352 if (_Detach() != B_OK) 1336 1353 return *this; 1337 1354 1338 PosVect positions; 1339 1355 int32 pos = 0; 1340 1356 int32 searchLen = 1; 1341 1357 int32 len = Length(); 1342 int32 pos = 0; 1343 for (int32 offset = 0; offset < len; offset += (pos+searchLen)) { 1358 1359 PosVect positions; 1360 for (int32 offset = 0; offset < len; offset += (pos + searchLen)) { 1344 1361 pos = strcspn(fPrivateData + offset, setOfChars); 1345 1362 if (pos + offset >= len) 1346 1363 break; … … 1348 1365 return *this; 1349 1366 } 1350 1367 1351 _ReplaceAtPositions(&positions, searchLen, with, withLen); 1368 _ReplaceAtPositions(&positions, searchLen, with, withLen); 1352 1369 return *this; 1353 1370 } 1354 1371 1355 1372 1356 / *---- Unchecked char access -----------------------------------------------*/1373 // #pragma mark - Unchecked char access 1357 1374 1358 // operator[] 1359 char & 1375 1376 #if __GNUC__ > 3 1377 BStringRef 1360 1378 BString::operator[](int32 index) 1361 1379 { 1380 return BStringRef(*this, index); 1381 } 1382 #else 1383 char& 1384 BString::operator[](int32 index) 1385 { 1386 _Detach(); 1387 _SetReferenceCount(-1); 1388 1362 1389 return fPrivateData[index]; 1363 1390 } 1391 #endif 1364 1392 1365 1393 1366 /*---- Fast low-level manipulation -----------------------------------------*/ 1394 // #pragma mark - Fast low-level manipulation 1395 1396 1367 1397 char* 1368 1398 BString::LockBuffer(int32 maxLength) 1369 1399 { 1370 _SetUsingAsCString(true); 1400 int32 length = Length(); 1401 if (maxLength > length) 1402 length += maxLength - length; 1371 1403 1372 int32 len = Length(); 1373 1374 if (maxLength > len) { 1375 if (!_GrowBy(maxLength - len)) 1376 return NULL; 1377 if (!len && fPrivateData) 1378 // if string was empty before call to LockBuffer(), we make sure the 1379 // buffer represents an empty c-string: 1380 *fPrivateData = '\0'; 1381 } else if (!maxLength && !len) { 1382 // special case for unallocated string, we return an empty c-string: 1383 return const_cast<char*>(String()); 1384 } 1385 1404 _DetachWith(fPrivateData, length); 1386 1405 return fPrivateData; 1387 1406 } 1388 1407 … … 1390 1409 BString& 1391 1410 BString::UnlockBuffer(int32 length) 1392 1411 { 1393 _SetUsingAsCString(false); 1394 1395 if (length < 0) 1412 if (length > 0) { 1413 if (length) 1414 length = min_clamp0(length, Length()); 1415 } else { 1396 1416 length = (fPrivateData == NULL) ? 0 : strlen(fPrivateData); 1417 } 1397 1418 1398 if (length != Length())1399 _GrowBy(length - Length());1419 _Realloc(length); 1420 fPrivateData[length] = '\0'; 1400 1421 1401 1422 return *this; 1402 1423 } 1403 1424 1404 1425 1405 /*---- Uppercase<->Lowercase ------------------------------------------------*/ 1406 // ToLower 1426 // #pragma mark - Uppercase <-> Lowercase 1427 1428 1407 1429 BString& 1408 1430 BString::ToLower() 1409 1431 { 1410 1432 int32 length = Length(); 1411 for (int32 count = 0; count < length; count++) { 1412 fPrivateData[count] = tolower(fPrivateData[count]); 1433 if (length > 0 && _Detach() == B_OK) { 1434 for (int32 count = 0; count < length; count++) 1435 fPrivateData[count] = tolower(fPrivateData[count]); 1413 1436 } 1414 1415 1437 return *this; 1416 1438 } 1417 1439 1418 1440 1419 // ToUpper1420 1441 BString& 1421 1442 BString::ToUpper() 1422 { 1443 { 1423 1444 int32 length = Length(); 1424 for (int32 count = 0; count < length; count++) { 1425 fPrivateData[count] = toupper(fPrivateData[count]); 1445 if (length > 0 && _Detach() == B_OK) { 1446 for (int32 count = 0; count < length; count++) 1447 fPrivateData[count] = toupper(fPrivateData[count]); 1426 1448 } 1427 1428 1449 return *this; 1429 1450 } 1430 1451 1431 1452 1432 // Capitalize1433 1453 BString& 1434 1454 BString::Capitalize() 1435 1455 { 1436 if (fPrivateData == NULL)1437 return *this;1438 1439 fPrivateData[0] = toupper(fPrivateData[0]);1440 1456 int32 length = Length(); 1441 1457 1442 for (int32 count = 1; count < length; count++) { 1443 fPrivateData[count] = tolower(fPrivateData[count]); 1458 if (length > 0 && _Detach() == B_OK) { 1459 fPrivateData[0] = toupper(fPrivateData[0]); 1460 for (int32 count = 1; count < length; count++) 1461 fPrivateData[count] = tolower(fPrivateData[count]); 1444 1462 } 1445 1446 1463 return *this; 1447 1464 } 1448 1465 1449 1466 1450 // CapitalizeEachWord1451 1467 BString& 1452 1468 BString::CapitalizeEachWord() 1453 1469 { 1454 if (fPrivateData == NULL)1455 return *this;1456 1457 int32 count = 0;1458 1470 int32 length = Length(); 1459 1460 do { 1461 // Find the first alphabetical character... 1462 for (; count < length; count++) { 1463 if (isalpha(fPrivateData[count])) { 1464 // ...found! Convert it to uppercase. 1465 fPrivateData[count] = toupper(fPrivateData[count]); 1466 count++; 1467 break; 1471 1472 if (length > 0 && _Detach() == B_OK) { 1473 int32 count = 0; 1474 do { 1475 // Find the first alphabetical character... 1476 for (; count < length; count++) { 1477 if (isalpha(fPrivateData[count])) { 1478 // ...found! Convert it to uppercase. 1479 fPrivateData[count] = toupper(fPrivateData[count]); 1480 count++; 1481 break; 1482 } 1468 1483 } 1469 }1470 1484 1471 // Now find the first non-alphabetical character,1472 // and meanwhile, turn to lowercase all the alphabetical ones1473 for (; count < length; count++) {1474 if (isalpha(fPrivateData[count]))1475 fPrivateData[count] = tolower(fPrivateData[count]);1476 else1477 break;1478 }1479 } while (count < length);1480 1485 // Now find the first non-alphabetical character, 1486 // and meanwhile, turn to lowercase all the alphabetical ones 1487 for (; count < length; count++) { 1488 if (isalpha(fPrivateData[count])) 1489 fPrivateData[count] = tolower(fPrivateData[count]); 1490 else 1491 break; 1492 } 1493 } while (count < length); 1494 } 1481 1495 return *this; 1482 1496 } 1483 1497 1484 1498 1485 /*----- Escaping and Deescaping --------------------------------------------*/ 1499 // #pragma mark - Escaping and De-escaping 1500 1501 1486 1502 BString& 1487 BString::CharacterEscape(const char *original, const char *setOfCharsToEscape,1488 char escapeWith)1503 BString::CharacterEscape(const char* original, 1504 const char* setOfCharsToEscape, char escapeWith) 1489 1505 { 1490 SetTo(original); 1491 CharacterEscape(setOfCharsToEscape, escapeWith); 1492 1506 if (setOfCharsToEscape) 1507 _DoCharacterEscape(original, setOfCharsToEscape, escapeWith); 1493 1508 return *this; 1494 1509 } 1495 1510 1496 1511 1497 1512 BString& 1498 BString::CharacterEscape(const char *setOfCharsToEscape, char escapeWith)1513 BString::CharacterEscape(const char* setOfCharsToEscape, char escapeWith) 1499 1514 { 1500 if (setOfCharsToEscape == NULL || fPrivateData == NULL) 1501 return *this; 1502 1503 PosVect positions; 1504 int32 len = Length(); 1505 int32 pos = 0; 1506 for (int32 offset = 0; offset < len; offset += pos + 1) { 1507 if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape)) < len - offset) { 1508 if (!positions.Add(offset + pos)) 1509 return *this; 1510 } 1511 } 1512 1513 uint32 count = positions.CountItems(); 1514 int32 newLength = len + count; 1515 if (!newLength) { 1516 _Alloc(0); 1517 return *this; 1518 } 1519 1520 int32 lastPos = 0; 1521 char* oldAdr = fPrivateData; 1522 char* newData = (char*)malloc(newLength + sizeof(int32) + 1); 1523 if (newData) { 1524 newData += sizeof(int32); 1525 char* newAdr = newData; 1526 for (uint32 i = 0; i < count; ++i) { 1527 pos = positions.ItemAt( i); 1528 len = pos-lastPos; 1529 if (len > 0) { 1530 memcpy(newAdr, oldAdr, len); 1531 oldAdr += len; 1532 newAdr += len; 1533 } 1534 *newAdr++ = escapeWith; 1535 *newAdr++ = *oldAdr++; 1536 lastPos = pos + 1; 1537 } 1538 len = Length() + 1 - lastPos; 1539 if (len > 0) 1540 memcpy(newAdr, oldAdr, len); 1541 1542 free(fPrivateData - sizeof(int32)); 1543 fPrivateData = newData; 1544 fPrivateData[newLength] = 0; 1545 _SetLength( newLength); 1546 } 1547 1515 if (setOfCharsToEscape && Length() > 0) 1516 _DoCharacterEscape(fPrivateData, setOfCharsToEscape, escapeWith); 1548 1517 return *this; 1549 1518 } 1550 1519 1551 1520 1552 1521 BString& 1553 BString::CharacterDeescape(const char *original, char escapeChar)1522 BString::CharacterDeescape(const char* original, char escapeChar) 1554 1523 { 1555 SetTo(original); 1556 CharacterDeescape(escapeChar); 1557 1558 return *this; 1524 return _DoCharacterDeescape(original, escapeChar); 1559 1525 } 1560 1526 1561 1527 1562 1528 BString& 1563 1529 BString::CharacterDeescape(char escapeChar) 1564 1530 { 1565 const char temp[2] = {escapeChar, 0}; 1566 return _DoReplace(temp, "", REPLACE_ALL, 0, KEEP_CASE); 1531 if (Length() > 0) 1532 _DoCharacterDeescape(fPrivateData, escapeChar); 1533 return *this; 1567 1534 } 1568 1535 1569 1536 1570 /*---- Simple sprintf replacement calls ------------------------------------*/ 1571 /*---- Slower than sprintf but type and overflow safe ----------------------*/ 1537 // #pragma mark - Insert 1538 1539 1572 1540 BString& 1573 BString::operator<<(const char *str)1541 BString::operator<<(const char* string) 1574 1542 { 1575 if (str != NULL)1576 _DoAppend(str , strlen(str));1577 return *this; 1543 if (string != NULL) 1544 _DoAppend(string, strlen(string)); 1545 return *this; 1578 1546 } 1579 1547 1580 1548 1581 1549 BString& 1582 BString::operator<<(const BString &string)1550 BString::operator<<(const BString& string) 1583 1551 { 1584 _DoAppend(string.String(), string.Length()); 1552 if (string.Length() > 0) 1553 _DoAppend(string.String(), string.Length()); 1585 1554 return *this; 1586 1555 } 1587 1556 … … 1589 1558 BString& 1590 1559 BString::operator<<(char c) 1591 1560 { 1592 _DoAppend(&c, 1); 1561 _DoAppend(&c, 1); 1593 1562 return *this; 1594 1563 } 1595 1564 … … 1674 1643 // #pragma mark - Private or reserved 1675 1644 1676 1645 1677 char * 1678 BString::_ Alloc(int32 dataLength)1646 status_t 1647 BString::_Detach() 1679 1648 { 1680 char *dataPtr = fPrivateData ? fPrivateData - sizeof(int32) : NULL; 1681 if (dataLength <= 0) { 1682 // release buffer 1683 #if 0 1684 free(dataPtr); 1685 fPrivateData = NULL; 1686 return NULL; 1687 #else 1688 // TODO: think about removing this work-around again; it lets 1689 // BeOS R5 NetPositive run on Haiku - this is obviously ignoring 1690 // the fact, that fPrivateData could be NULL at one point 1691 // (while building the menus from resources). 1692 dataLength = 0; 1693 #endif 1649 char* newData = fPrivateData; 1650 if (atomic_get(&(*(((vint32*)fPrivateData - 2)))) > 1) { 1651 // we share our data with someone else 1652 if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1) { 1653 ; // someone else decrement, we are the last owner 1654 } else { 1655 // there is still someone who shares our data 1656 newData = _Clone(fPrivateData, Length()); 1657 } 1658 } else { 1659 ; // we don't share our data with someone else 1694 1660 } 1695 1661 1696 int32 allocLength = dataLength + sizeof(int32) + 1; 1697 dataPtr = (char *)realloc(dataPtr, allocLength); 1662 if (newData) 1663 fPrivateData = newData; 1664 return newData != NULL ? B_OK : B_NO_MEMORY; 1665 } 1666 1667 1668 char* 1669 BString::_Realloc(int32 length) 1670 { 1671 if (length == Length()) 1672 return fPrivateData; 1673 1674 int32 offset = 2 * sizeof(int32); 1675 char *dataPtr = fPrivateData ? fPrivateData - offset : NULL; 1676 if (length < 0) 1677 length = 0; 1678 1679 dataPtr = (char*)realloc(dataPtr, length + offset + 1); 1698 1680 if (dataPtr) { 1699 dataPtr += sizeof(int32); 1681 dataPtr += offset; 1682 1700 1683 fPrivateData = dataPtr; 1684 fPrivateData[length] = '\0'; 1701 1685 1702 _SetLength( dataLength);1703 fPrivateData[dataLength] = '\0';1686 _SetLength(length); 1687 _SetReferenceCount(1); 1704 1688 } 1705 1706 1689 return dataPtr; 1707 }1708 1709 void1710 BString::_Init(const char *str, int32 len)1711 {1712 if (_Alloc(len))1713 memcpy(fPrivateData, str, len);1714 1690 } 1715 1691 1716 1692 1717 #if ENABLE_INLINES1718 inline1719 #endif1720 1693 void 1721 BString::_ DoAssign(const char *str, int32 len)1694 BString::_Init(const char* src, int32 length) 1722 1695 { 1723 int32 curLen = Length(); 1696 fPrivateData = _Clone(src, length); 1697 if (!fPrivateData) { 1698 int32 offset = 2 * sizeof(int32); 1699 fPrivateData = (char *)realloc(fPrivateData, offset + 1); 1724 1700 1725 if (len == curLen || _GrowBy(len - curLen)) 1726 memcpy(fPrivateData, str, len); 1701 fPrivateData += offset; 1702 fPrivateData[0] = '\0'; 1703 1704 _SetLength(0); 1705 _SetReferenceCount(1); 1706 } 1727 1707 } 1728 1708 1729 1709 1730 #if ENABLE_INLINES 1731 inline 1732 #endif 1733 void 1734 BString::_DoAppend(const char *str, int32 len) 1710 char* 1711 BString::_Clone(const char* data, int32 length) 1735 1712 { 1736 int32 length = Length(); 1737 if (_GrowBy(len)) 1738 memcpy(fPrivateData + length, str, len); 1739 } 1713 char* newData = NULL; 1714 int32 offset = 2 * sizeof(int32); 1715 newData = (char *)realloc(newData, length + offset + 1); 1740 1716 1717 if (newData) { 1718 newData += offset; 1719 newData[length] = '\0'; 1741 1720 1742 char* 1743 BString::_GrowBy(int32 size) 1744 { 1745 return _Alloc(Length() + size); 1721 *(((vint32*)newData) - 2) = 1; 1722 *(((int32*)newData) - 1) = length & 0x7fffffff; 1723 1724 if (data && length) 1725 memcpy(newData, data, length); 1726 } 1727 return newData; 1746 1728 } 1747 1729 1748 1730 … … 1751 1733 { 1752 1734 int32 oldLength = Length(); 1753 1735 1754 char* newData = _Alloc(oldLength + length); 1755 if (newData != NULL) { 1756 memmove(fPrivateData + offset + length, fPrivateData + offset, 1757 oldLength - offset); 1758 } 1736 if (_Detach() != B_OK) 1737 return NULL; 1759 1738 1760 return newData; 1739 memmove(fPrivateData + offset + length, fPrivateData + offset, 1740 oldLength - offset); 1741 return _Realloc(oldLength + length); 1761 1742 } 1762 1743 1763 1744 1764 1745 char* 1765 1746 BString::_ShrinkAtBy(int32 offset, int32 length) 1766 { 1767 if (!fPrivateData) 1747 { 1748 int32 oldLength = Length(); 1749 if (_Detach() != B_OK) 1768 1750 return NULL; 1769 1751 1770 int32 oldLength = Length();1771 1772 1752 memmove(fPrivateData + offset, fPrivateData + offset + length, 1773 1753 oldLength - offset - length); 1754 return _Realloc(oldLength - length); 1755 } 1774 1756 1775 // the following actually should never fail, since we are reducing the size... 1776 return _Alloc(oldLength - length); 1757 1758 status_t 1759 BString::_DetachWith(const char* string, int32 length) 1760 { 1761 char* newData = NULL; 1762 if (atomic_get(&(*(((vint32*)fPrivateData) - 2))) > 1) { 1763 // we share our data with someone else 1764 if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1) { 1765 // someone else decrement, we are the last owner 1766 newData = _Realloc(length); 1767 } else { 1768 // there is still someone who shares our data 1769 newData = _Clone(string, length); 1770 } 1771 } else { 1772 // we don't share our data with someone else 1773 newData = _Realloc(length); 1774 } 1775 1776 if (newData) 1777 fPrivateData = newData; 1778 return newData != NULL ? B_OK : B_NO_MEMORY; 1777 1779 } 1778 1780 1779 1781 1780 #if ENABLE_INLINES1781 inline1782 #endif1783 1782 void 1784 BString::_ DoPrepend(const char *str, int32 count)1783 BString::_SetLength(int32 length) 1785 1784 { 1786 if (_OpenAtBy(0, count)) 1787 memcpy(fPrivateData, str, count); 1785 *(((int32*)fPrivateData) - 1) = length & 0x7fffffff; 1788 1786 } 1789 1787 1790 1788 1791 /* XXX: These could be inlined too, if they are too slow */ 1789 void 1790 BString::_SetReferenceCount(int32 count) 1791 { 1792 *(((vint32*)fPrivateData) - 2) = count; 1793 } 1794 1795 1796 bool 1797 BString::_DoAppend(const char* string, int32 length) 1798 { 1799 int32 len = Length(); 1800 if (_DetachWith(fPrivateData, len + length) == B_OK) { 1801 if (string && length) 1802 memcpy(fPrivateData + len, string, length); 1803 return true; 1804 } 1805 return false; 1806 } 1807 1808 1809 bool 1810 BString::_DoPrepend(const char* string, int32 length) 1811 { 1812 int32 len = Length(); 1813 if (_DetachWith(fPrivateData, len + length) == B_OK) { 1814 memmove(fPrivateData + length, fPrivateData, len); 1815 if (string && length) 1816 memcpy(fPrivateData, string, length); 1817 return true; 1818 } 1819 return false; 1820 } 1821 1822 1823 bool 1824 BString::_DoInsert(const char* string, int32 offset, int32 length) 1825 { 1826 int32 len = Length(); 1827 if (_DetachWith(fPrivateData, len + length) == B_OK) { 1828 memmove(fPrivateData + offset + length, fPrivateData + offset, len - offset); 1829 if (string && length) 1830 memcpy(fPrivateData + offset, string, length); 1831 return true; 1832 } 1833 return false; 1834 } 1835 1836 1792 1837 int32 1793 BString::_ FindAfter(const char *str, int32 offset, int32 strlen) const1794 { 1795 c har *ptr = strstr(String() + offset, str);1838 BString::_ShortFindAfter(const char* string, int32 len) const 1839 { 1840 const char *ptr = strstr(String(), string); 1796 1841 1797 1842 if (ptr != NULL) 1798 1843 return ptr - String(); 1799 1844 1800 1845 return B_ERROR; 1801 1846 } 1802 1847 1803 1848 1804 1849 int32 1805 BString::_ IFindAfter(const char *str, int32 offset, int32 strlen) const1850 BString::_FindAfter(const char* string, int32 offset, int32 strlen) const 1806 1851 { 1807 c har *ptr = strcasestr(String() + offset, str);1852 const char *ptr = strstr(String() + offset, string); 1808 1853 1809 1854 if (ptr != NULL) 1810 1855 return ptr - String(); … … 1814 1859 1815 1860 1816 1861 int32 1817 BString::_ ShortFindAfter(const char *str, int32len) const1862 BString::_IFindAfter(const char* string, int32 offset, int32 strlen) const 1818 1863 { 1819 c har *ptr = strstr(String(), str);1820 1864 const char *ptr = strcasestr(String() + offset, string); 1865 1821 1866 if (ptr != NULL) 1822 1867 return ptr - String(); 1823 1868 1824 1869 return B_ERROR; 1825 1870 } 1826 1871 1827 1872 1828 1873 int32 1829 BString::_FindBefore(const char *str, int32 offset, int32 strlen) const1874 BString::_FindBefore(const char* string, int32 offset, int32 strlen) const 1830 1875 { 1831 1876 if (fPrivateData) { 1832 1877 const char *ptr = fPrivateData + offset - strlen; 1833 1834 while (ptr >= fPrivateData) { 1835 if (!memcmp(ptr, str , strlen))1836 return ptr - fPrivateData; 1878 1879 while (ptr >= fPrivateData) { 1880 if (!memcmp(ptr, string, strlen)) 1881 return ptr - fPrivateData; 1837 1882 ptr--; 1838 1883 } 1839 1884 } … … 1842 1887 1843 1888 1844 1889 int32 1845 BString::_IFindBefore(const char *str, int32 offset, int32 strlen) const1890 BString::_IFindBefore(const char* string, int32 offset, int32 strlen) const 1846 1891 { 1847 1892 if (fPrivateData) { 1848 1893 char *ptr1 = fPrivateData + offset - strlen; 1849 1894 1850 1895 while (ptr1 >= fPrivateData) { 1851 if (!strncasecmp(ptr1, str , strlen))1852 return ptr1 - fPrivateData; 1896 if (!strncasecmp(ptr1, string, strlen)) 1897 return ptr1 - fPrivateData; 1853 1898 ptr1--; 1854 1899 } 1855 1900 } … … 1858 1903 1859 1904 1860 1905 BString& 1861 BString::_Do Replace(const char *findThis, const char *replaceWith,1862 int32 maxReplaceCount, int32 fromOffset, bool ignoreCase)1906 BString::_DoCharacterEscape(const char* string, 1907 const char *setOfCharsToEscape, char escapeChar) 1863 1908 { 1864 if (findThis == NULL || maxReplaceCount <= 0 1909 if (_DetachWith(string, strlen(safestr(string))) != B_OK) 1910 return *this; 1911 1912 memcpy(fPrivateData, string, Length()); 1913 1914 PosVect positions; 1915 int32 len = Length(); 1916 int32 pos = 0; 1917 for (int32 offset = 0; offset < len; offset += pos + 1) { 1918 if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape)) < len - offset) { 1919 if (!positions.Add(offset + pos)) 1920 return *this; 1921 } 1922 } 1923 1924 uint32 count = positions.CountItems(); 1925 int32 newLength = len + count; 1926 if (!newLength) { 1927 _Realloc(0); 1928 return *this; 1929 } 1930 1931 int32 lastPos = 0; 1932 char* oldAdr = fPrivateData; 1933 int32 offset = 2 * sizeof(int32); 1934 1935 char* newData = (char*)malloc(newLength + offset + 1); 1936 if (newData) { 1937 newData += offset; 1938 char* newAdr = newData; 1939 for (uint32 i = 0; i < count; ++i) { 1940 pos = positions.ItemAt(i); 1941 len = pos - lastPos; 1942 if (len > 0) { 1943 memcpy(newAdr, oldAdr, len); 1944 oldAdr += len; 1945 newAdr += len; 1946 } 1947 *newAdr++ = escapeChar; 1948 *newAdr++ = *oldAdr++; 1949 lastPos = pos + 1; 1950 } 1951 len = Length() + 1 - lastPos; 1952 if (len > 0) 1953 memcpy(newAdr, oldAdr, len); 1954 1955 free(fPrivateData - offset); 1956 1957 fPrivateData = newData; 1958 _SetLength(newLength); 1959 fPrivateData[newLength] = '\0'; 1960 } 1961 return *this; 1962 } 1963 1964 1965 BString& 1966 BString::_DoCharacterDeescape(const char* string, char escapeChar) 1967 { 1968 if (_DetachWith(string, strlen(safestr(string))) != B_OK) 1969 return *this; 1970 1971 memcpy(fPrivateData, string, Length()); 1972 const char temp[2] = { escapeChar, '\0' }; 1973 return _DoReplace(temp, "", REPLACE_ALL, 0, KEEP_CASE); 1974 } 1975 1976 1977 BString& 1978 BString::_DoReplace(const char* findThis, const char* replaceWith, 1979 int32 maxReplaceCount, int32 fromOffset, bool ignoreCase) 1980 { 1981 if (findThis == NULL || maxReplaceCount <= 0 1865 1982 || fromOffset < 0 || fromOffset >= Length()) 1866 1983 return *this; 1867 1984 1868 typedef int32 (BString::*TFindMethod)(const char *, int32, int32) const; 1869 TFindMethod findMethod = ignoreCase ? &BString::_IFindAfter : &BString::_FindAfter; 1985 typedef int32 (BString::*TFindMethod)(const char*, int32, int32) const; 1986 TFindMethod findMethod = ignoreCase ? &BString::_IFindAfter 1987 : &BString::_FindAfter; 1870 1988 int32 findLen = strlen(findThis); 1871 1989 1872 1990 if (!replaceWith) … … 1875 1993 int32 replaceLen = strlen(replaceWith); 1876 1994 int32 lastSrcPos = fromOffset; 1877 1995 PosVect positions; 1878 for(int32 srcPos = 0; 1879 maxReplaceCount > 0 1880 && (srcPos = (this->*findMethod)(findThis, lastSrcPos, findLen)) >= 0; 1881 maxReplaceCount-- ) { 1996 for (int32 srcPos = 0; maxReplaceCount > 0 1997 && (srcPos = (this->*findMethod)(findThis, lastSrcPos, findLen)) >= 0; 1998 maxReplaceCount--) { 1882 1999 positions.Add(srcPos); 1883 2000 lastSrcPos = srcPos + findLen; 1884 2001 } … … 1888 2005 1889 2006 1890 2007 void 1891 BString::_ReplaceAtPositions(const PosVect* positions, 1892 int32 searchLen,const char* with, int32 withLen)2008 BString::_ReplaceAtPositions(const PosVect* positions, int32 searchLen, 2009 const char* with, int32 withLen) 1893 2010 { 1894 2011 int32 len = Length(); 1895 2012 uint32 count = positions->CountItems(); 1896 2013 int32 newLength = len + count * (withLen - searchLen); 1897 2014 if (!newLength) { 1898 _ Alloc(0);2015 _Realloc(0); 1899 2016 return; 1900 2017 } 1901 2018 1902 2019 int32 pos; 1903 2020 int32 lastPos = 0; 1904 2021 char *oldAdr = fPrivateData; 1905 char *newData = (char *)malloc(newLength + sizeof(int32) + 1); 2022 2023 int32 offset = 2 * sizeof(int32); 2024 char *newData = (char *)malloc(newLength + offset + 1); 1906 2025 if (newData) { 1907 newData += sizeof(int32);2026 newData += offset; 1908 2027 char *newAdr = newData; 1909 for (uint32 i = 0; i < count; ++i) {2028 for (uint32 i = 0; i < count; ++i) { 1910 2029 pos = positions->ItemAt(i); 1911 2030 len = pos - lastPos; 1912 2031 if (len > 0) { … … 1923 2042 if (len > 0) 1924 2043 memcpy(newAdr, oldAdr, len); 1925 2044 1926 free(fPrivateData - sizeof(int32)); 2045 free(fPrivateData - offset); 2046 1927 2047 fPrivateData = newData; 1928 fPrivateData[newLength] = 0;1929 _SetLength( newLength);2048 _SetLength(newLength); 2049 fPrivateData[newLength] = '\0'; 1930 2050 } 1931 2051 } 1932 2052 1933 2053 1934 #if ENABLE_INLINES1935 inline1936 #endif1937 void1938 BString::_SetLength(int32 length)1939 {1940 *((int32*)fPrivateData - 1) = length & 0x7fffffff;1941 }1942 1943 1944 #if DEBUG1945 // AFAIK, these are not implemented in BeOS R51946 // XXX : Test these puppies1947 void1948 BString::_SetUsingAsCString(bool state)1949 {1950 //TODO: Implement ?1951 }1952 1953 1954 void1955 BString::_AssertNotUsingAsCString() const1956 {1957 //TODO: Implement ?1958 }1959 #endif1960 1961 1962 2054 // #pragma mark - backwards compatibility 1963 2055 1964 2056 … … 2002 2094 { 2003 2095 return strcasecmp(string1->String(), string2->String()); 2004 2096 } 2005