1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #ifndef CORE_INCLUDE_FXCRT_FX_STRING_H_ 8 #define CORE_INCLUDE_FXCRT_FX_STRING_H_ 9 10 #include <stdint.h> // For intptr_t. 11 #include <algorithm> 12 13 #include "fx_memory.h" 14 #include "fx_system.h" 15 16 class CFX_BinaryBuf; 17 class CFX_ByteString; 18 class CFX_WideString; 19 struct CFX_CharMap; 20 21 // An immutable string with caller-provided storage which must outlive the 22 // string itself. 23 class CFX_ByteStringC { 24 public: 25 typedef FX_CHAR value_type; 26 27 CFX_ByteStringC() { 28 m_Ptr = NULL; 29 m_Length = 0; 30 } 31 32 CFX_ByteStringC(const uint8_t* ptr, FX_STRSIZE size) { 33 m_Ptr = ptr; 34 m_Length = size; 35 } 36 37 CFX_ByteStringC(const FX_CHAR* ptr) { 38 m_Ptr = (const uint8_t*)ptr; 39 m_Length = ptr ? FXSYS_strlen(ptr) : 0; 40 } 41 42 // |ch| must be an lvalue that outlives the the CFX_ByteStringC. However, 43 // the use of char rvalues are not caught at compile time. They are 44 // implicitly promoted to CFX_ByteString (see below) and then the 45 // CFX_ByteStringC is constructed from the CFX_ByteString via the alternate 46 // constructor below. The CFX_ByteString then typically goes out of scope 47 // and |m_Ptr| may be left pointing to invalid memory. Beware. 48 // TODO(tsepez): Mark single-argument string constructors as explicit. 49 CFX_ByteStringC(FX_CHAR& ch) { 50 m_Ptr = (const uint8_t*)&ch; 51 m_Length = 1; 52 } 53 54 CFX_ByteStringC(const FX_CHAR* ptr, FX_STRSIZE len) { 55 m_Ptr = (const uint8_t*)ptr; 56 m_Length = (len == -1) ? FXSYS_strlen(ptr) : len; 57 } 58 59 CFX_ByteStringC(const CFX_ByteStringC& src) { 60 m_Ptr = src.m_Ptr; 61 m_Length = src.m_Length; 62 } 63 64 CFX_ByteStringC(const CFX_ByteString& src); 65 66 CFX_ByteStringC& operator=(const FX_CHAR* src) { 67 m_Ptr = (const uint8_t*)src; 68 m_Length = m_Ptr ? FXSYS_strlen(src) : 0; 69 return *this; 70 } 71 72 CFX_ByteStringC& operator=(const CFX_ByteStringC& src) { 73 m_Ptr = src.m_Ptr; 74 m_Length = src.m_Length; 75 return *this; 76 } 77 78 CFX_ByteStringC& operator=(const CFX_ByteString& src); 79 80 bool operator==(const char* ptr) const { 81 return FXSYS_strlen(ptr) == m_Length && 82 FXSYS_memcmp(ptr, m_Ptr, m_Length) == 0; 83 } 84 bool operator==(const CFX_ByteStringC& other) const { 85 return other.m_Length == m_Length && 86 FXSYS_memcmp(other.m_Ptr, m_Ptr, m_Length) == 0; 87 } 88 bool operator!=(const char* ptr) const { return !(*this == ptr); } 89 bool operator!=(const CFX_ByteStringC& other) const { 90 return !(*this == other); 91 } 92 93 FX_DWORD GetID(FX_STRSIZE start_pos = 0) const; 94 95 const uint8_t* GetPtr() const { return m_Ptr; } 96 97 const FX_CHAR* GetCStr() const { return (const FX_CHAR*)m_Ptr; } 98 99 FX_STRSIZE GetLength() const { return m_Length; } 100 101 bool IsEmpty() const { return m_Length == 0; } 102 103 uint8_t GetAt(FX_STRSIZE index) const { return m_Ptr[index]; } 104 105 CFX_ByteStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const { 106 if (index < 0) { 107 index = 0; 108 } 109 if (index > m_Length) { 110 return CFX_ByteStringC(); 111 } 112 if (count < 0 || count > m_Length - index) { 113 count = m_Length - index; 114 } 115 return CFX_ByteStringC(m_Ptr + index, count); 116 } 117 118 const uint8_t& operator[](size_t index) const { return m_Ptr[index]; } 119 120 bool operator<(const CFX_ByteStringC& that) const { 121 int result = memcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length)); 122 return result < 0 || (result == 0 && m_Length < that.m_Length); 123 } 124 125 protected: 126 const uint8_t* m_Ptr; 127 FX_STRSIZE m_Length; 128 129 private: 130 void* operator new(size_t) throw() { return NULL; } 131 }; 132 inline bool operator==(const char* lhs, const CFX_ByteStringC& rhs) { 133 return rhs == lhs; 134 } 135 inline bool operator!=(const char* lhs, const CFX_ByteStringC& rhs) { 136 return rhs != lhs; 137 } 138 #define FXBSTR_ID(c1, c2, c3, c4) ((c1 << 24) | (c2 << 16) | (c3 << 8) | (c4)) 139 140 // A mutable string with shared buffers using copy-on-write semantics that 141 // avoids the cost of std::string's iterator stability guarantees. 142 class CFX_ByteString { 143 public: 144 typedef FX_CHAR value_type; 145 146 CFX_ByteString() : m_pData(nullptr) {} 147 148 // Copy constructor. 149 CFX_ByteString(const CFX_ByteString& str); 150 151 // Move constructor. 152 inline CFX_ByteString(CFX_ByteString&& other) { 153 m_pData = other.m_pData; 154 other.m_pData = nullptr; 155 } 156 157 CFX_ByteString(char ch); 158 CFX_ByteString(const FX_CHAR* ptr) 159 : CFX_ByteString(ptr, ptr ? FXSYS_strlen(ptr) : 0) {} 160 161 CFX_ByteString(const FX_CHAR* ptr, FX_STRSIZE len); 162 CFX_ByteString(const uint8_t* ptr, FX_STRSIZE len); 163 164 CFX_ByteString(const CFX_ByteStringC& bstrc); 165 CFX_ByteString(const CFX_ByteStringC& bstrc1, const CFX_ByteStringC& bstrc2); 166 167 ~CFX_ByteString(); 168 169 static CFX_ByteString FromUnicode(const FX_WCHAR* ptr, FX_STRSIZE len = -1); 170 171 static CFX_ByteString FromUnicode(const CFX_WideString& str); 172 173 // Explicit conversion to raw string 174 const FX_CHAR* c_str() const { return m_pData ? m_pData->m_String : ""; } 175 176 // Implicit conversion to C-style string -- deprecated 177 operator const FX_CHAR*() const { return m_pData ? m_pData->m_String : ""; } 178 179 operator const uint8_t*() const { 180 return m_pData ? (const uint8_t*)m_pData->m_String : NULL; 181 } 182 183 FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } 184 185 bool IsEmpty() const { return !GetLength(); } 186 187 int Compare(const CFX_ByteStringC& str) const; 188 189 bool Equal(const char* ptr) const; 190 bool Equal(const CFX_ByteStringC& str) const; 191 bool Equal(const CFX_ByteString& other) const; 192 193 bool EqualNoCase(const CFX_ByteStringC& str) const; 194 195 bool operator==(const char* ptr) const { return Equal(ptr); } 196 bool operator==(const CFX_ByteStringC& str) const { return Equal(str); } 197 bool operator==(const CFX_ByteString& other) const { return Equal(other); } 198 199 bool operator!=(const char* ptr) const { return !(*this == ptr); } 200 bool operator!=(const CFX_ByteStringC& str) const { return !(*this == str); } 201 bool operator!=(const CFX_ByteString& other) const { 202 return !(*this == other); 203 } 204 205 bool operator<(const CFX_ByteString& str) const { 206 int result = FXSYS_memcmp(c_str(), str.c_str(), 207 std::min(GetLength(), str.GetLength())); 208 return result < 0 || (result == 0 && GetLength() < str.GetLength()); 209 } 210 211 void Empty(); 212 213 const CFX_ByteString& operator=(const FX_CHAR* str); 214 215 const CFX_ByteString& operator=(const CFX_ByteStringC& bstrc); 216 217 const CFX_ByteString& operator=(const CFX_ByteString& stringSrc); 218 219 const CFX_ByteString& operator=(const CFX_BinaryBuf& buf); 220 221 void Load(const uint8_t* str, FX_STRSIZE len); 222 223 const CFX_ByteString& operator+=(FX_CHAR ch); 224 225 const CFX_ByteString& operator+=(const FX_CHAR* str); 226 227 const CFX_ByteString& operator+=(const CFX_ByteString& str); 228 229 const CFX_ByteString& operator+=(const CFX_ByteStringC& bstrc); 230 231 uint8_t GetAt(FX_STRSIZE nIndex) const { 232 return m_pData ? m_pData->m_String[nIndex] : 0; 233 } 234 235 uint8_t operator[](FX_STRSIZE nIndex) const { 236 return m_pData ? m_pData->m_String[nIndex] : 0; 237 } 238 239 void SetAt(FX_STRSIZE nIndex, FX_CHAR ch); 240 241 FX_STRSIZE Insert(FX_STRSIZE index, FX_CHAR ch); 242 243 FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); 244 245 void Format(const FX_CHAR* lpszFormat, ...); 246 247 void FormatV(const FX_CHAR* lpszFormat, va_list argList); 248 249 void Reserve(FX_STRSIZE len); 250 251 FX_CHAR* GetBuffer(FX_STRSIZE len); 252 253 void ReleaseBuffer(FX_STRSIZE len = -1); 254 255 CFX_ByteString Mid(FX_STRSIZE first) const; 256 257 CFX_ByteString Mid(FX_STRSIZE first, FX_STRSIZE count) const; 258 259 CFX_ByteString Left(FX_STRSIZE count) const; 260 261 CFX_ByteString Right(FX_STRSIZE count) const; 262 263 FX_STRSIZE Find(const CFX_ByteStringC& lpszSub, FX_STRSIZE start = 0) const; 264 265 FX_STRSIZE Find(FX_CHAR ch, FX_STRSIZE start = 0) const; 266 267 FX_STRSIZE ReverseFind(FX_CHAR ch) const; 268 269 void MakeLower(); 270 271 void MakeUpper(); 272 273 void TrimRight(); 274 275 void TrimRight(FX_CHAR chTarget); 276 277 void TrimRight(const CFX_ByteStringC& lpszTargets); 278 279 void TrimLeft(); 280 281 void TrimLeft(FX_CHAR chTarget); 282 283 void TrimLeft(const CFX_ByteStringC& lpszTargets); 284 285 FX_STRSIZE Replace(const CFX_ByteStringC& lpszOld, 286 const CFX_ByteStringC& lpszNew); 287 288 FX_STRSIZE Remove(FX_CHAR ch); 289 290 CFX_WideString UTF8Decode() const; 291 292 void ConvertFrom(const CFX_WideString& str, CFX_CharMap* pCharMap = NULL); 293 294 FX_DWORD GetID(FX_STRSIZE start_pos = 0) const; 295 296 #define FXFORMAT_SIGNED 1 297 #define FXFORMAT_HEX 2 298 #define FXFORMAT_CAPITAL 4 299 300 static CFX_ByteString FormatInteger(int i, FX_DWORD flags = 0); 301 static CFX_ByteString FormatFloat(FX_FLOAT f, int precision = 0); 302 303 protected: 304 // To ensure ref counts do not overflow, consider the worst possible case: 305 // the entire address space contains nothing but pointers to this object. 306 // Since the count increments with each new pointer, the largest value is 307 // the number of pointers that can fit into the address space. The size of 308 // the address space itself is a good upper bound on it; we need not go 309 // larger. 310 class StringData { 311 public: 312 static StringData* Create(int nLen); 313 void Retain() { ++m_nRefs; } 314 void Release() { 315 if (--m_nRefs <= 0) 316 FX_Free(this); 317 } 318 319 intptr_t m_nRefs; // Would prefer ssize_t, but no windows support. 320 FX_STRSIZE m_nDataLength; 321 FX_STRSIZE m_nAllocLength; 322 FX_CHAR m_String[1]; 323 324 private: 325 StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen) 326 : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) { 327 FXSYS_assert(dataLen >= 0); 328 FXSYS_assert(allocLen >= 0); 329 FXSYS_assert(dataLen <= allocLen); 330 m_String[dataLen] = 0; 331 } 332 ~StringData() = delete; 333 }; 334 335 void AllocCopy(CFX_ByteString& dest, 336 FX_STRSIZE nCopyLen, 337 FX_STRSIZE nCopyIndex) const; 338 void AssignCopy(FX_STRSIZE nSrcLen, const FX_CHAR* lpszSrcData); 339 void ConcatCopy(FX_STRSIZE nSrc1Len, 340 const FX_CHAR* lpszSrc1Data, 341 FX_STRSIZE nSrc2Len, 342 const FX_CHAR* lpszSrc2Data); 343 void ConcatInPlace(FX_STRSIZE nSrcLen, const FX_CHAR* lpszSrcData); 344 void CopyBeforeWrite(); 345 void AllocBeforeWrite(FX_STRSIZE nLen); 346 347 StringData* m_pData; 348 friend class fxcrt_ByteStringConcatInPlace_Test; 349 }; 350 inline CFX_ByteStringC::CFX_ByteStringC(const CFX_ByteString& src) { 351 m_Ptr = (const uint8_t*)src; 352 m_Length = src.GetLength(); 353 } 354 inline CFX_ByteStringC& CFX_ByteStringC::operator=(const CFX_ByteString& src) { 355 m_Ptr = (const uint8_t*)src; 356 m_Length = src.GetLength(); 357 return *this; 358 } 359 360 inline bool operator==(const char* lhs, const CFX_ByteString& rhs) { 361 return rhs == lhs; 362 } 363 inline bool operator==(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { 364 return rhs == lhs; 365 } 366 inline bool operator!=(const char* lhs, const CFX_ByteString& rhs) { 367 return rhs != lhs; 368 } 369 inline bool operator!=(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { 370 return rhs != lhs; 371 } 372 373 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, 374 const CFX_ByteStringC& str2) { 375 return CFX_ByteString(str1, str2); 376 } 377 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, 378 const FX_CHAR* str2) { 379 return CFX_ByteString(str1, str2); 380 } 381 inline CFX_ByteString operator+(const FX_CHAR* str1, 382 const CFX_ByteStringC& str2) { 383 return CFX_ByteString(str1, str2); 384 } 385 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, FX_CHAR ch) { 386 return CFX_ByteString(str1, CFX_ByteStringC(ch)); 387 } 388 inline CFX_ByteString operator+(FX_CHAR ch, const CFX_ByteStringC& str2) { 389 return CFX_ByteString(ch, str2); 390 } 391 inline CFX_ByteString operator+(const CFX_ByteString& str1, 392 const CFX_ByteString& str2) { 393 return CFX_ByteString(str1, str2); 394 } 395 inline CFX_ByteString operator+(const CFX_ByteString& str1, FX_CHAR ch) { 396 return CFX_ByteString(str1, CFX_ByteStringC(ch)); 397 } 398 inline CFX_ByteString operator+(FX_CHAR ch, const CFX_ByteString& str2) { 399 return CFX_ByteString(ch, str2); 400 } 401 inline CFX_ByteString operator+(const CFX_ByteString& str1, 402 const FX_CHAR* str2) { 403 return CFX_ByteString(str1, str2); 404 } 405 inline CFX_ByteString operator+(const FX_CHAR* str1, 406 const CFX_ByteString& str2) { 407 return CFX_ByteString(str1, str2); 408 } 409 inline CFX_ByteString operator+(const CFX_ByteString& str1, 410 const CFX_ByteStringC& str2) { 411 return CFX_ByteString(str1, str2); 412 } 413 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, 414 const CFX_ByteString& str2) { 415 return CFX_ByteString(str1, str2); 416 } 417 class CFX_WideStringC { 418 public: 419 typedef FX_WCHAR value_type; 420 421 CFX_WideStringC() { 422 m_Ptr = NULL; 423 m_Length = 0; 424 } 425 426 CFX_WideStringC(const FX_WCHAR* ptr) { 427 m_Ptr = ptr; 428 m_Length = ptr ? FXSYS_wcslen(ptr) : 0; 429 } 430 431 CFX_WideStringC(FX_WCHAR& ch) { 432 m_Ptr = &ch; 433 m_Length = 1; 434 } 435 436 CFX_WideStringC(const FX_WCHAR* ptr, FX_STRSIZE len) { 437 m_Ptr = ptr; 438 m_Length = (len == -1) ? FXSYS_wcslen(ptr) : len; 439 } 440 441 CFX_WideStringC(const CFX_WideStringC& src) { 442 m_Ptr = src.m_Ptr; 443 m_Length = src.m_Length; 444 } 445 446 CFX_WideStringC(const CFX_WideString& src); 447 448 CFX_WideStringC& operator=(const FX_WCHAR* src) { 449 m_Ptr = src; 450 m_Length = FXSYS_wcslen(src); 451 return *this; 452 } 453 454 CFX_WideStringC& operator=(const CFX_WideStringC& src) { 455 m_Ptr = src.m_Ptr; 456 m_Length = src.m_Length; 457 return *this; 458 } 459 460 CFX_WideStringC& operator=(const CFX_WideString& src); 461 462 bool operator==(const wchar_t* ptr) const { 463 return FXSYS_wcslen(ptr) == m_Length && wmemcmp(ptr, m_Ptr, m_Length) == 0; 464 } 465 bool operator==(const CFX_WideStringC& str) const { 466 return str.m_Length == m_Length && wmemcmp(str.m_Ptr, m_Ptr, m_Length) == 0; 467 } 468 bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } 469 bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); } 470 471 const FX_WCHAR* GetPtr() const { return m_Ptr; } 472 473 FX_STRSIZE GetLength() const { return m_Length; } 474 475 bool IsEmpty() const { return m_Length == 0; } 476 477 FX_WCHAR GetAt(FX_STRSIZE index) const { return m_Ptr[index]; } 478 479 CFX_WideStringC Left(FX_STRSIZE count) const { 480 if (count < 1) { 481 return CFX_WideStringC(); 482 } 483 if (count > m_Length) { 484 count = m_Length; 485 } 486 return CFX_WideStringC(m_Ptr, count); 487 } 488 489 CFX_WideStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const { 490 if (index < 0) { 491 index = 0; 492 } 493 if (index > m_Length) { 494 return CFX_WideStringC(); 495 } 496 if (count < 0 || count > m_Length - index) { 497 count = m_Length - index; 498 } 499 return CFX_WideStringC(m_Ptr + index, count); 500 } 501 502 CFX_WideStringC Right(FX_STRSIZE count) const { 503 if (count < 1) { 504 return CFX_WideStringC(); 505 } 506 if (count > m_Length) { 507 count = m_Length; 508 } 509 return CFX_WideStringC(m_Ptr + m_Length - count, count); 510 } 511 512 const FX_WCHAR& operator[](size_t index) const { return m_Ptr[index]; } 513 514 bool operator<(const CFX_WideStringC& that) const { 515 int result = wmemcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length)); 516 return result < 0 || (result == 0 && m_Length < that.m_Length); 517 } 518 519 protected: 520 const FX_WCHAR* m_Ptr; 521 FX_STRSIZE m_Length; 522 523 private: 524 void* operator new(size_t) throw() { return NULL; } 525 }; 526 inline bool operator==(const wchar_t* lhs, const CFX_WideStringC& rhs) { 527 return rhs == lhs; 528 } 529 inline bool operator!=(const wchar_t* lhs, const CFX_WideStringC& rhs) { 530 return rhs != lhs; 531 } 532 #define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1) 533 534 // A mutable string with shared buffers using copy-on-write semantics that 535 // avoids the cost of std::string's iterator stability guarantees. 536 class CFX_WideString { 537 public: 538 typedef FX_WCHAR value_type; 539 540 CFX_WideString() : m_pData(nullptr) {} 541 542 // Copy constructor. 543 CFX_WideString(const CFX_WideString& str); 544 545 // Move constructor. 546 inline CFX_WideString(CFX_WideString&& other) { 547 m_pData = other.m_pData; 548 other.m_pData = nullptr; 549 } 550 551 CFX_WideString(const FX_WCHAR* ptr) 552 : CFX_WideString(ptr, ptr ? FXSYS_wcslen(ptr) : 0) {} 553 554 CFX_WideString(const FX_WCHAR* ptr, FX_STRSIZE len); 555 556 CFX_WideString(FX_WCHAR ch); 557 558 CFX_WideString(const CFX_WideStringC& str); 559 560 CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2); 561 562 ~CFX_WideString(); 563 564 static CFX_WideString FromLocal(const char* str, FX_STRSIZE len = -1); 565 566 static CFX_WideString FromUTF8(const char* str, FX_STRSIZE len); 567 568 static CFX_WideString FromUTF16LE(const unsigned short* str, FX_STRSIZE len); 569 570 static FX_STRSIZE WStringLength(const unsigned short* str); 571 572 // Explicit conversion to raw string 573 const FX_WCHAR* c_str() const { return m_pData ? m_pData->m_String : L""; } 574 575 // Implicit conversion to C-style wide string -- deprecated 576 operator const FX_WCHAR*() const { return m_pData ? m_pData->m_String : L""; } 577 578 void Empty(); 579 580 FX_BOOL IsEmpty() const { return !GetLength(); } 581 582 FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } 583 584 const CFX_WideString& operator=(const FX_WCHAR* str); 585 586 const CFX_WideString& operator=(const CFX_WideString& stringSrc); 587 588 const CFX_WideString& operator=(const CFX_WideStringC& stringSrc); 589 590 const CFX_WideString& operator+=(const FX_WCHAR* str); 591 592 const CFX_WideString& operator+=(FX_WCHAR ch); 593 594 const CFX_WideString& operator+=(const CFX_WideString& str); 595 596 const CFX_WideString& operator+=(const CFX_WideStringC& str); 597 598 bool operator==(const wchar_t* ptr) const { return Equal(ptr); } 599 bool operator==(const CFX_WideStringC& str) const { return Equal(str); } 600 bool operator==(const CFX_WideString& other) const { return Equal(other); } 601 602 bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } 603 bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); } 604 bool operator!=(const CFX_WideString& other) const { 605 return !(*this == other); 606 } 607 608 bool operator<(const CFX_WideString& str) const { 609 int result = 610 wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength())); 611 return result < 0 || (result == 0 && GetLength() < str.GetLength()); 612 } 613 614 FX_WCHAR GetAt(FX_STRSIZE nIndex) const { 615 return m_pData ? m_pData->m_String[nIndex] : 0; 616 } 617 618 FX_WCHAR operator[](FX_STRSIZE nIndex) const { 619 return m_pData ? m_pData->m_String[nIndex] : 0; 620 } 621 622 void SetAt(FX_STRSIZE nIndex, FX_WCHAR ch); 623 624 int Compare(const FX_WCHAR* str) const; 625 626 int Compare(const CFX_WideString& str) const; 627 628 int CompareNoCase(const FX_WCHAR* str) const; 629 630 bool Equal(const wchar_t* ptr) const; 631 bool Equal(const CFX_WideStringC& str) const; 632 bool Equal(const CFX_WideString& other) const; 633 634 CFX_WideString Mid(FX_STRSIZE first) const; 635 636 CFX_WideString Mid(FX_STRSIZE first, FX_STRSIZE count) const; 637 638 CFX_WideString Left(FX_STRSIZE count) const; 639 640 CFX_WideString Right(FX_STRSIZE count) const; 641 642 FX_STRSIZE Insert(FX_STRSIZE index, FX_WCHAR ch); 643 644 FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); 645 646 void Format(const FX_WCHAR* lpszFormat, ...); 647 648 void FormatV(const FX_WCHAR* lpszFormat, va_list argList); 649 650 void MakeLower(); 651 652 void MakeUpper(); 653 654 void TrimRight(); 655 656 void TrimRight(FX_WCHAR chTarget); 657 658 void TrimRight(const FX_WCHAR* lpszTargets); 659 660 void TrimLeft(); 661 662 void TrimLeft(FX_WCHAR chTarget); 663 664 void TrimLeft(const FX_WCHAR* lpszTargets); 665 666 void Reserve(FX_STRSIZE len); 667 668 FX_WCHAR* GetBuffer(FX_STRSIZE len); 669 670 void ReleaseBuffer(FX_STRSIZE len = -1); 671 672 int GetInteger() const; 673 674 FX_FLOAT GetFloat() const; 675 676 FX_STRSIZE Find(const FX_WCHAR* lpszSub, FX_STRSIZE start = 0) const; 677 678 FX_STRSIZE Find(FX_WCHAR ch, FX_STRSIZE start = 0) const; 679 680 FX_STRSIZE Replace(const FX_WCHAR* lpszOld, const FX_WCHAR* lpszNew); 681 682 FX_STRSIZE Remove(FX_WCHAR ch); 683 684 CFX_ByteString UTF8Encode() const; 685 686 CFX_ByteString UTF16LE_Encode() const; 687 688 void ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap = NULL); 689 690 protected: 691 class StringData { 692 public: 693 static StringData* Create(int nLen); 694 void Retain() { ++m_nRefs; } 695 void Release() { 696 if (--m_nRefs <= 0) 697 FX_Free(this); 698 } 699 700 intptr_t m_nRefs; // Would prefer ssize_t, but no windows support. 701 FX_STRSIZE m_nDataLength; 702 FX_STRSIZE m_nAllocLength; 703 FX_WCHAR m_String[1]; 704 705 private: 706 StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen) 707 : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) { 708 FXSYS_assert(dataLen >= 0); 709 FXSYS_assert(allocLen >= 0); 710 FXSYS_assert(dataLen <= allocLen); 711 m_String[dataLen] = 0; 712 } 713 ~StringData() = delete; 714 }; 715 716 void CopyBeforeWrite(); 717 void AllocBeforeWrite(FX_STRSIZE nLen); 718 void ConcatInPlace(FX_STRSIZE nSrcLen, const FX_WCHAR* lpszSrcData); 719 void ConcatCopy(FX_STRSIZE nSrc1Len, 720 const FX_WCHAR* lpszSrc1Data, 721 FX_STRSIZE nSrc2Len, 722 const FX_WCHAR* lpszSrc2Data); 723 void AssignCopy(FX_STRSIZE nSrcLen, const FX_WCHAR* lpszSrcData); 724 void AllocCopy(CFX_WideString& dest, 725 FX_STRSIZE nCopyLen, 726 FX_STRSIZE nCopyIndex) const; 727 728 StringData* m_pData; 729 friend class fxcrt_WideStringConcatInPlace_Test; 730 }; 731 inline CFX_WideStringC::CFX_WideStringC(const CFX_WideString& src) { 732 m_Ptr = src.c_str(); 733 m_Length = src.GetLength(); 734 } 735 inline CFX_WideStringC& CFX_WideStringC::operator=(const CFX_WideString& src) { 736 m_Ptr = src.c_str(); 737 m_Length = src.GetLength(); 738 return *this; 739 } 740 741 inline CFX_WideString operator+(const CFX_WideStringC& str1, 742 const CFX_WideStringC& str2) { 743 return CFX_WideString(str1, str2); 744 } 745 inline CFX_WideString operator+(const CFX_WideStringC& str1, 746 const FX_WCHAR* str2) { 747 return CFX_WideString(str1, str2); 748 } 749 inline CFX_WideString operator+(const FX_WCHAR* str1, 750 const CFX_WideStringC& str2) { 751 return CFX_WideString(str1, str2); 752 } 753 inline CFX_WideString operator+(const CFX_WideStringC& str1, FX_WCHAR ch) { 754 return CFX_WideString(str1, CFX_WideStringC(ch)); 755 } 756 inline CFX_WideString operator+(FX_WCHAR ch, const CFX_WideStringC& str2) { 757 return CFX_WideString(ch, str2); 758 } 759 inline CFX_WideString operator+(const CFX_WideString& str1, 760 const CFX_WideString& str2) { 761 return CFX_WideString(str1, str2); 762 } 763 inline CFX_WideString operator+(const CFX_WideString& str1, FX_WCHAR ch) { 764 return CFX_WideString(str1, CFX_WideStringC(ch)); 765 } 766 inline CFX_WideString operator+(FX_WCHAR ch, const CFX_WideString& str2) { 767 return CFX_WideString(ch, str2); 768 } 769 inline CFX_WideString operator+(const CFX_WideString& str1, 770 const FX_WCHAR* str2) { 771 return CFX_WideString(str1, str2); 772 } 773 inline CFX_WideString operator+(const FX_WCHAR* str1, 774 const CFX_WideString& str2) { 775 return CFX_WideString(str1, str2); 776 } 777 inline CFX_WideString operator+(const CFX_WideString& str1, 778 const CFX_WideStringC& str2) { 779 return CFX_WideString(str1, str2); 780 } 781 inline CFX_WideString operator+(const CFX_WideStringC& str1, 782 const CFX_WideString& str2) { 783 return CFX_WideString(str1, str2); 784 } 785 inline bool operator==(const wchar_t* lhs, const CFX_WideString& rhs) { 786 return rhs == lhs; 787 } 788 inline bool operator==(const CFX_WideStringC& lhs, const CFX_WideString& rhs) { 789 return rhs == lhs; 790 } 791 inline bool operator!=(const wchar_t* lhs, const CFX_WideString& rhs) { 792 return rhs != lhs; 793 } 794 inline bool operator!=(const CFX_WideStringC& lhs, const CFX_WideString& rhs) { 795 return rhs != lhs; 796 } 797 FX_FLOAT FX_atof(const CFX_ByteStringC& str); 798 void FX_atonum(const CFX_ByteStringC& str, FX_BOOL& bInteger, void* pData); 799 FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_CHAR* buf); 800 CFX_ByteString FX_UTF8Encode(const FX_WCHAR* pwsStr, FX_STRSIZE len); 801 inline CFX_ByteString FX_UTF8Encode(const CFX_WideStringC& wsStr) { 802 return FX_UTF8Encode(wsStr.GetPtr(), wsStr.GetLength()); 803 } 804 inline CFX_ByteString FX_UTF8Encode(const CFX_WideString& wsStr) { 805 return FX_UTF8Encode(wsStr.c_str(), wsStr.GetLength()); 806 } 807 808 #endif // CORE_INCLUDE_FXCRT_FX_STRING_H_ 809