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