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#include "../../include/fxcrt/fx_basic.h" 8static CFX_StringDataW* FX_AllocStringW(int nLen) 9{ 10 if (nLen == 0) { 11 return NULL; 12 } 13 CFX_StringDataW* pData = (CFX_StringDataW*)FX_Alloc(FX_BYTE, sizeof(long) * 3 + (nLen + 1) * sizeof(FX_WCHAR)); 14 if (!pData) { 15 return NULL; 16 } 17 pData->m_nAllocLength = nLen; 18 pData->m_nDataLength = nLen; 19 pData->m_nRefs = 1; 20 pData->m_String[nLen] = 0; 21 return pData; 22} 23static void FX_ReleaseStringW(CFX_StringDataW* pData) 24{ 25 if (pData == NULL) { 26 return; 27 } 28 pData->m_nRefs --; 29 if (pData->m_nRefs <= 0) { 30 FX_Free(pData); 31 } 32} 33CFX_WideString::~CFX_WideString() 34{ 35 if (m_pData == NULL) { 36 return; 37 } 38 m_pData->m_nRefs --; 39 if (m_pData->m_nRefs < 1) { 40 FX_Free(m_pData); 41 } 42} 43void CFX_WideString::InitStr(FX_LPCWSTR lpsz, FX_STRSIZE nLen) 44{ 45 if (nLen < 0) { 46 nLen = lpsz ? (FX_STRSIZE)FXSYS_wcslen(lpsz) : 0; 47 } 48 if (nLen) { 49 m_pData = FX_AllocStringW(nLen); 50 if (!m_pData) { 51 return; 52 } 53 FXSYS_memcpy32(m_pData->m_String, lpsz, nLen * sizeof(FX_WCHAR)); 54 } else { 55 m_pData = NULL; 56 } 57} 58CFX_WideString::CFX_WideString(const CFX_WideString& stringSrc) 59{ 60 if (stringSrc.m_pData == NULL) { 61 m_pData = NULL; 62 return; 63 } 64 if (stringSrc.m_pData->m_nRefs >= 0) { 65 m_pData = stringSrc.m_pData; 66 m_pData->m_nRefs ++; 67 } else { 68 m_pData = NULL; 69 *this = stringSrc; 70 } 71} 72CFX_WideString::CFX_WideString(FX_WCHAR ch) 73{ 74 m_pData = FX_AllocStringW(1); 75 if (m_pData) { 76 m_pData->m_String[0] = ch; 77 } 78} 79CFX_WideString::CFX_WideString(const CFX_WideStringC& str) 80{ 81 if (str.IsEmpty()) { 82 m_pData = NULL; 83 return; 84 } 85 m_pData = FX_AllocStringW(str.GetLength()); 86 if (m_pData) { 87 FXSYS_memcpy32(m_pData->m_String, str.GetPtr(), str.GetLength()*sizeof(FX_WCHAR)); 88 } 89} 90CFX_WideString::CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2) 91{ 92 m_pData = NULL; 93 int nNewLen = str1.GetLength() + str2.GetLength(); 94 if (nNewLen == 0) { 95 return; 96 } 97 m_pData = FX_AllocStringW(nNewLen); 98 if (m_pData) { 99 FXSYS_memcpy32(m_pData->m_String, str1.GetPtr(), str1.GetLength()*sizeof(FX_WCHAR)); 100 FXSYS_memcpy32(m_pData->m_String + str1.GetLength(), str2.GetPtr(), str2.GetLength()*sizeof(FX_WCHAR)); 101 } 102} 103void CFX_WideString::ReleaseBuffer(FX_STRSIZE nNewLength) 104{ 105 if (m_pData == NULL) { 106 return; 107 } 108 CopyBeforeWrite(); 109 if (nNewLength == -1) { 110 nNewLength = m_pData ? (FX_STRSIZE)FXSYS_wcslen(m_pData->m_String) : 0; 111 } 112 if (nNewLength == 0) { 113 Empty(); 114 return; 115 } 116 FXSYS_assert(nNewLength <= m_pData->m_nAllocLength); 117 m_pData->m_nDataLength = nNewLength; 118 m_pData->m_String[nNewLength] = 0; 119} 120const CFX_WideString& CFX_WideString::operator=(FX_LPCWSTR lpsz) 121{ 122 if (lpsz == NULL || lpsz[0] == 0) { 123 Empty(); 124 } else { 125 AssignCopy((FX_STRSIZE)FXSYS_wcslen(lpsz), lpsz); 126 } 127 return *this; 128} 129const CFX_WideString& CFX_WideString::operator=(const CFX_WideStringC& stringSrc) 130{ 131 if (stringSrc.IsEmpty()) { 132 Empty(); 133 } else { 134 AssignCopy(stringSrc.GetLength(), stringSrc.GetPtr()); 135 } 136 return *this; 137} 138const CFX_WideString& CFX_WideString::operator=(const CFX_WideString& stringSrc) 139{ 140 if (m_pData == stringSrc.m_pData) { 141 return *this; 142 } 143 if (stringSrc.IsEmpty()) { 144 Empty(); 145 } else if ((m_pData && m_pData->m_nRefs < 0) || 146 (stringSrc.m_pData && stringSrc.m_pData->m_nRefs < 0)) { 147 AssignCopy(stringSrc.m_pData->m_nDataLength, stringSrc.m_pData->m_String); 148 } else { 149 Empty(); 150 m_pData = stringSrc.m_pData; 151 if (m_pData) { 152 m_pData->m_nRefs ++; 153 } 154 } 155 return *this; 156} 157const CFX_WideString& CFX_WideString::operator+=(FX_WCHAR ch) 158{ 159 ConcatInPlace(1, &ch); 160 return *this; 161} 162const CFX_WideString& CFX_WideString::operator+=(FX_LPCWSTR lpsz) 163{ 164 if (lpsz) { 165 ConcatInPlace((FX_STRSIZE)FXSYS_wcslen(lpsz), lpsz); 166 } 167 return *this; 168} 169const CFX_WideString& CFX_WideString::operator+=(const CFX_WideString& string) 170{ 171 if (string.m_pData == NULL) { 172 return *this; 173 } 174 ConcatInPlace(string.m_pData->m_nDataLength, string.m_pData->m_String); 175 return *this; 176} 177const CFX_WideString& CFX_WideString::operator+=(const CFX_WideStringC& string) 178{ 179 if (string.IsEmpty()) { 180 return *this; 181 } 182 ConcatInPlace(string.GetLength(), string.GetPtr()); 183 return *this; 184} 185bool operator==(const CFX_WideString& s1, FX_LPCWSTR s2) 186{ 187 return s1.Equal(s2); 188} 189bool operator==(FX_LPCWSTR s1, const CFX_WideString& s2) 190{ 191 return s2.Equal(s1); 192} 193bool operator==(const CFX_WideString& s1, const CFX_WideString& s2) 194{ 195 return s1.Equal(s2); 196} 197bool operator==(const CFX_WideString& s1, const CFX_WideStringC& s2) 198{ 199 return s1.Equal(s2); 200} 201bool operator==(const CFX_WideStringC& s1, const CFX_WideString& s2) 202{ 203 return s2.Equal(s1); 204} 205bool operator != (const CFX_WideString& s1, FX_LPCWSTR s2) 206{ 207 return !s1.Equal(s2); 208} 209bool operator!=(const CFX_WideString& s1, const CFX_WideString& s2) 210{ 211 return !s1.Equal(s2); 212} 213bool operator!=(const CFX_WideString& s1, const CFX_WideStringC& s2) 214{ 215 return !s1.Equal(s2); 216} 217bool operator!=(const CFX_WideStringC& s1, const CFX_WideString& s2) 218{ 219 return !s2.Equal(s1); 220} 221bool CFX_WideString::Equal(const CFX_WideStringC& str) const 222{ 223 if (m_pData == NULL) { 224 return str.IsEmpty(); 225 } 226 return str.GetLength() == m_pData->m_nDataLength && 227 FXSYS_memcmp32(str.GetPtr(), m_pData->m_String, m_pData->m_nDataLength * sizeof(FX_WCHAR)) == 0; 228} 229void CFX_WideString::Empty() 230{ 231 if (m_pData == NULL) { 232 return; 233 } 234 if (m_pData->m_nRefs > 1) { 235 m_pData->m_nRefs --; 236 } else { 237 FX_Free(m_pData); 238 } 239 m_pData = NULL; 240} 241void CFX_WideString::ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData) 242{ 243 if (nSrcLen == 0 || lpszSrcData == NULL) { 244 return; 245 } 246 if (m_pData == NULL) { 247 m_pData = FX_AllocStringW(nSrcLen); 248 if (m_pData) { 249 FXSYS_memcpy32(m_pData->m_String, lpszSrcData, nSrcLen * sizeof(FX_WCHAR)); 250 } 251 return; 252 } 253 if (m_pData->m_nRefs > 1 || m_pData->m_nDataLength + nSrcLen > m_pData->m_nAllocLength) { 254 CFX_StringDataW* pOldData = m_pData; 255 ConcatCopy(m_pData->m_nDataLength, m_pData->m_String, nSrcLen, lpszSrcData); 256 FX_ReleaseStringW(pOldData); 257 } else { 258 FXSYS_memcpy32(m_pData->m_String + m_pData->m_nDataLength, lpszSrcData, nSrcLen * sizeof(FX_WCHAR)); 259 m_pData->m_nDataLength += nSrcLen; 260 m_pData->m_String[m_pData->m_nDataLength] = 0; 261 } 262} 263void CFX_WideString::ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCWSTR lpszSrc1Data, 264 FX_STRSIZE nSrc2Len, FX_LPCWSTR lpszSrc2Data) 265{ 266 FX_STRSIZE nNewLen = nSrc1Len + nSrc2Len; 267 if (nNewLen == 0) { 268 return; 269 } 270 m_pData = FX_AllocStringW(nNewLen); 271 if (m_pData) { 272 FXSYS_memcpy32(m_pData->m_String, lpszSrc1Data, nSrc1Len * sizeof(FX_WCHAR)); 273 FXSYS_memcpy32(m_pData->m_String + nSrc1Len, lpszSrc2Data, nSrc2Len * sizeof(FX_WCHAR)); 274 } 275} 276void CFX_WideString::CopyBeforeWrite() 277{ 278 if (m_pData == NULL || m_pData->m_nRefs <= 1) { 279 return; 280 } 281 CFX_StringDataW* pData = m_pData; 282 m_pData->m_nRefs --; 283 FX_STRSIZE nDataLength = pData->m_nDataLength; 284 m_pData = FX_AllocStringW(nDataLength); 285 if (m_pData != NULL) { 286 FXSYS_memcpy32(m_pData->m_String, pData->m_String, (nDataLength + 1) * sizeof(FX_WCHAR)); 287 } 288} 289void CFX_WideString::AllocBeforeWrite(FX_STRSIZE nLen) 290{ 291 if (m_pData && m_pData->m_nRefs <= 1 && m_pData->m_nAllocLength >= nLen) { 292 return; 293 } 294 Empty(); 295 m_pData = FX_AllocStringW(nLen); 296} 297void CFX_WideString::AssignCopy(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData) 298{ 299 AllocBeforeWrite(nSrcLen); 300 FXSYS_memcpy32(m_pData->m_String, lpszSrcData, nSrcLen * sizeof(FX_WCHAR)); 301 m_pData->m_nDataLength = nSrcLen; 302 m_pData->m_String[nSrcLen] = 0; 303} 304int CFX_WideString::Compare(FX_LPCWSTR lpsz) const 305{ 306 if (m_pData == NULL) { 307 return (lpsz == NULL || lpsz[0] == 0) ? 0 : -1; 308 } 309 return FXSYS_wcscmp(m_pData->m_String, lpsz); 310} 311CFX_ByteString CFX_WideString::UTF8Encode() const 312{ 313 return FX_UTF8Encode(*this); 314} 315CFX_ByteString CFX_WideString::UTF16LE_Encode(FX_BOOL bTerminate) const 316{ 317 if (m_pData == NULL) { 318 return bTerminate ? CFX_ByteString(FX_BSTRC("\0\0")) : CFX_ByteString(); 319 } 320 int len = m_pData->m_nDataLength; 321 CFX_ByteString result; 322 FX_LPSTR buffer = result.GetBuffer(len * 2 + (bTerminate ? 2 : 0)); 323 for (int i = 0; i < len; i ++) { 324 buffer[i * 2] = m_pData->m_String[i] & 0xff; 325 buffer[i * 2 + 1] = m_pData->m_String[i] >> 8; 326 } 327 if (bTerminate) { 328 buffer[len * 2] = 0; 329 buffer[len * 2 + 1] = 0; 330 result.ReleaseBuffer(len * 2 + 2); 331 } else { 332 result.ReleaseBuffer(len * 2); 333 } 334 return result; 335} 336void CFX_WideString::ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap) 337{ 338 if (pCharMap == NULL) { 339 pCharMap = CFX_CharMap::GetDefaultMapper(); 340 } 341 *this = pCharMap->m_GetWideString(pCharMap, str); 342} 343void CFX_WideString::Reserve(FX_STRSIZE len) 344{ 345 GetBuffer(len); 346 ReleaseBuffer(GetLength()); 347} 348FX_LPWSTR CFX_WideString::GetBuffer(FX_STRSIZE nMinBufLength) 349{ 350 if (m_pData == NULL && nMinBufLength == 0) { 351 return NULL; 352 } 353 if (m_pData && m_pData->m_nRefs <= 1 && m_pData->m_nAllocLength >= nMinBufLength) { 354 return m_pData->m_String; 355 } 356 if (m_pData == NULL) { 357 m_pData = FX_AllocStringW(nMinBufLength); 358 if (!m_pData) { 359 return NULL; 360 } 361 m_pData->m_nDataLength = 0; 362 m_pData->m_String[0] = 0; 363 return m_pData->m_String; 364 } 365 CFX_StringDataW* pOldData = m_pData; 366 FX_STRSIZE nOldLen = pOldData->m_nDataLength; 367 if (nMinBufLength < nOldLen) { 368 nMinBufLength = nOldLen; 369 } 370 m_pData = FX_AllocStringW(nMinBufLength); 371 if (!m_pData) { 372 return NULL; 373 } 374 FXSYS_memcpy32(m_pData->m_String, pOldData->m_String, (nOldLen + 1)*sizeof(FX_WCHAR)); 375 m_pData->m_nDataLength = nOldLen; 376 pOldData->m_nRefs --; 377 if (pOldData->m_nRefs <= 0) { 378 FX_Free(pOldData); 379 } 380 return m_pData->m_String; 381} 382CFX_WideString CFX_WideString::FromLocal(const char* str, FX_STRSIZE len) 383{ 384 CFX_WideString result; 385 result.ConvertFrom(CFX_ByteString(str, len)); 386 return result; 387} 388CFX_WideString CFX_WideString::FromUTF8(const char* str, FX_STRSIZE len) 389{ 390 if (!str) { 391 return CFX_WideString(); 392 } 393 if (len < 0) { 394 len = 0; 395 while (str[len]) { 396 len ++; 397 } 398 } 399 CFX_UTF8Decoder decoder; 400 for (FX_STRSIZE i = 0; i < len; i ++) { 401 decoder.Input(str[i]); 402 } 403 return decoder.GetResult(); 404} 405CFX_WideString CFX_WideString::FromUTF16LE(const unsigned short* wstr, FX_STRSIZE wlen) 406{ 407 if (!wstr || !wlen) { 408 return CFX_WideString(); 409 } 410 if (wlen < 0) { 411 wlen = 0; 412 while (wstr[wlen]) { 413 wlen ++; 414 } 415 } 416 CFX_WideString result; 417 FX_WCHAR* buf = result.GetBuffer(wlen); 418 for (int i = 0; i < wlen; i ++) { 419 buf[i] = wstr[i]; 420 } 421 result.ReleaseBuffer(wlen); 422 return result; 423} 424void CFX_WideString::AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex, 425 FX_STRSIZE nExtraLen) const 426{ 427 FX_STRSIZE nNewLen = nCopyLen + nExtraLen; 428 if (nNewLen == 0) { 429 return; 430 } 431 ASSERT(dest.m_pData == NULL); 432 dest.m_pData = FX_AllocStringW(nNewLen); 433 if (dest.m_pData) { 434 FXSYS_memcpy32(dest.m_pData->m_String, m_pData->m_String + nCopyIndex, nCopyLen * sizeof(FX_WCHAR)); 435 } 436} 437CFX_WideString CFX_WideString::Left(FX_STRSIZE nCount) const 438{ 439 if (m_pData == NULL) { 440 return CFX_WideString(); 441 } 442 if (nCount < 0) { 443 nCount = 0; 444 } 445 if (nCount >= m_pData->m_nDataLength) { 446 return *this; 447 } 448 CFX_WideString dest; 449 AllocCopy(dest, nCount, 0, 0); 450 return dest; 451} 452CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst) const 453{ 454 return Mid(nFirst, m_pData->m_nDataLength - nFirst); 455} 456CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const 457{ 458 if (m_pData == NULL) { 459 return CFX_WideString(); 460 } 461 if (nFirst < 0) { 462 nFirst = 0; 463 } 464 if (nCount < 0) { 465 nCount = 0; 466 } 467 if (nFirst + nCount > m_pData->m_nDataLength) { 468 nCount = m_pData->m_nDataLength - nFirst; 469 } 470 if (nFirst > m_pData->m_nDataLength) { 471 nCount = 0; 472 } 473 if (nFirst == 0 && nFirst + nCount == m_pData->m_nDataLength) { 474 return *this; 475 } 476 CFX_WideString dest; 477 AllocCopy(dest, nCount, nFirst, 0); 478 return dest; 479} 480CFX_WideString CFX_WideString::Right(FX_STRSIZE nCount) const 481{ 482 if (m_pData == NULL) { 483 return CFX_WideString(); 484 } 485 if (nCount < 0) { 486 nCount = 0; 487 } 488 if (nCount >= m_pData->m_nDataLength) { 489 return *this; 490 } 491 CFX_WideString dest; 492 AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount, 0); 493 return dest; 494} 495int CFX_WideString::CompareNoCase(FX_LPCWSTR lpsz) const 496{ 497 if (m_pData == NULL) { 498 return (lpsz == NULL || lpsz[0] == 0) ? 0 : -1; 499 } 500 return FXSYS_wcsicmp(m_pData->m_String, lpsz); 501} 502int CFX_WideString::Compare(const CFX_WideString& str) const 503{ 504 if (m_pData == NULL) { 505 if (str.m_pData == NULL) { 506 return 0; 507 } 508 return -1; 509 } else if (str.m_pData == NULL) { 510 return 1; 511 } 512 int this_len = m_pData->m_nDataLength; 513 int that_len = str.m_pData->m_nDataLength; 514 int min_len = this_len < that_len ? this_len : that_len; 515 for (int i = 0; i < min_len; i ++) { 516 if (m_pData->m_String[i] < str.m_pData->m_String[i]) { 517 return -1; 518 } else if (m_pData->m_String[i] > str.m_pData->m_String[i]) { 519 return 1; 520 } 521 } 522 if (this_len < that_len) { 523 return -1; 524 } else if (this_len > that_len) { 525 return 1; 526 } 527 return 0; 528} 529FX_LPWSTR CFX_WideString::LockBuffer() 530{ 531 if (m_pData == NULL) { 532 return NULL; 533 } 534 FX_LPWSTR lpsz = GetBuffer(0); 535 m_pData->m_nRefs = -1; 536 return lpsz; 537} 538void CFX_WideString::SetAt(FX_STRSIZE nIndex, FX_WCHAR ch) 539{ 540 if (m_pData == NULL) { 541 return; 542 } 543 ASSERT(nIndex >= 0); 544 ASSERT(nIndex < m_pData->m_nDataLength); 545 CopyBeforeWrite(); 546 m_pData->m_String[nIndex] = ch; 547} 548void CFX_WideString::MakeLower() 549{ 550 if (m_pData == NULL) { 551 return; 552 } 553 CopyBeforeWrite(); 554 if (GetLength() < 1) { 555 return; 556 } 557 FXSYS_wcslwr(m_pData->m_String); 558} 559void CFX_WideString::MakeUpper() 560{ 561 if (m_pData == NULL) { 562 return; 563 } 564 CopyBeforeWrite(); 565 if (GetLength() < 1) { 566 return; 567 } 568 FXSYS_wcsupr(m_pData->m_String); 569} 570FX_STRSIZE CFX_WideString::Find(FX_LPCWSTR lpszSub, FX_STRSIZE nStart) const 571{ 572 FX_STRSIZE nLength = GetLength(); 573 if (nLength < 1 || nStart > nLength) { 574 return -1; 575 } 576 FX_LPCWSTR lpsz = (FX_LPCWSTR)FXSYS_wcsstr(m_pData->m_String + nStart, lpszSub); 577 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String); 578} 579FX_STRSIZE CFX_WideString::Find(FX_WCHAR ch, FX_STRSIZE nStart) const 580{ 581 if (m_pData == NULL) { 582 return -1; 583 } 584 FX_STRSIZE nLength = m_pData->m_nDataLength; 585 if (nStart >= nLength) { 586 return -1; 587 } 588 FX_LPCWSTR lpsz = (FX_LPCWSTR)FXSYS_wcschr(m_pData->m_String + nStart, ch); 589 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String); 590} 591void CFX_WideString::TrimRight(FX_LPCWSTR lpszTargetList) 592{ 593 FXSYS_assert(lpszTargetList != NULL); 594 if (m_pData == NULL || *lpszTargetList == 0) { 595 return; 596 } 597 CopyBeforeWrite(); 598 FX_STRSIZE len = GetLength(); 599 if (len < 1) { 600 return; 601 } 602 FX_STRSIZE pos = len; 603 while (pos) { 604 if (FXSYS_wcschr(lpszTargetList, m_pData->m_String[pos - 1]) == NULL) { 605 break; 606 } 607 pos --; 608 } 609 if (pos < len) { 610 m_pData->m_String[pos] = 0; 611 m_pData->m_nDataLength = pos; 612 } 613} 614void CFX_WideString::TrimRight(FX_WCHAR chTarget) 615{ 616 FX_WCHAR str[2] = {chTarget, 0}; 617 TrimRight(str); 618} 619void CFX_WideString::TrimRight() 620{ 621 TrimRight(L"\x09\x0a\x0b\x0c\x0d\x20"); 622} 623void CFX_WideString::TrimLeft(FX_LPCWSTR lpszTargets) 624{ 625 FXSYS_assert(lpszTargets != NULL); 626 if (m_pData == NULL || *lpszTargets == 0) { 627 return; 628 } 629 CopyBeforeWrite(); 630 if (GetLength() < 1) { 631 return; 632 } 633 FX_LPCWSTR lpsz = m_pData->m_String; 634 while (*lpsz != 0) { 635 if (FXSYS_wcschr(lpszTargets, *lpsz) == NULL) { 636 break; 637 } 638 lpsz ++; 639 } 640 if (lpsz != m_pData->m_String) { 641 int nDataLength = m_pData->m_nDataLength - (FX_STRSIZE)(lpsz - m_pData->m_String); 642 FXSYS_memmove32(m_pData->m_String, lpsz, (nDataLength + 1)*sizeof(FX_WCHAR)); 643 m_pData->m_nDataLength = nDataLength; 644 } 645} 646void CFX_WideString::TrimLeft(FX_WCHAR chTarget) 647{ 648 FX_WCHAR str[2] = {chTarget, 0}; 649 TrimLeft(str); 650} 651void CFX_WideString::TrimLeft() 652{ 653 TrimLeft(L"\x09\x0a\x0b\x0c\x0d\x20"); 654} 655FX_STRSIZE CFX_WideString::Replace(FX_LPCWSTR lpszOld, FX_LPCWSTR lpszNew) 656{ 657 if (GetLength() < 1) { 658 return 0; 659 } 660 if (lpszOld == NULL) { 661 return 0; 662 } 663 FX_STRSIZE nSourceLen = (FX_STRSIZE)FXSYS_wcslen(lpszOld); 664 if (nSourceLen == 0) { 665 return 0; 666 } 667 FX_STRSIZE nReplacementLen = lpszNew ? (FX_STRSIZE)FXSYS_wcslen(lpszNew) : 0; 668 FX_STRSIZE nCount = 0; 669 FX_LPWSTR lpszStart = m_pData->m_String; 670 FX_LPWSTR lpszEnd = m_pData->m_String + m_pData->m_nDataLength; 671 FX_LPWSTR lpszTarget; 672 { 673 while ((lpszTarget = (FX_LPWSTR)FXSYS_wcsstr(lpszStart, lpszOld)) != NULL && lpszStart < lpszEnd) { 674 nCount++; 675 lpszStart = lpszTarget + nSourceLen; 676 } 677 } 678 if (nCount > 0) { 679 CopyBeforeWrite(); 680 FX_STRSIZE nOldLength = m_pData->m_nDataLength; 681 FX_STRSIZE nNewLength = nOldLength + (nReplacementLen - nSourceLen) * nCount; 682 if (m_pData->m_nAllocLength < nNewLength || m_pData->m_nRefs > 1) { 683 CFX_StringDataW* pOldData = m_pData; 684 FX_LPCWSTR pstr = m_pData->m_String; 685 m_pData = FX_AllocStringW(nNewLength); 686 if (!m_pData) { 687 return 0; 688 } 689 FXSYS_memcpy32(m_pData->m_String, pstr, pOldData->m_nDataLength * sizeof(FX_WCHAR)); 690 FX_ReleaseStringW(pOldData); 691 } 692 lpszStart = m_pData->m_String; 693 lpszEnd = m_pData->m_String + FX_MAX(m_pData->m_nDataLength, nNewLength); 694 { 695 while ((lpszTarget = (FX_LPWSTR)FXSYS_wcsstr(lpszStart, lpszOld)) != NULL && lpszStart < lpszEnd) { 696 FX_STRSIZE nBalance = nOldLength - (FX_STRSIZE)(lpszTarget - m_pData->m_String + nSourceLen); 697 FXSYS_memmove32(lpszTarget + nReplacementLen, lpszTarget + nSourceLen, nBalance * sizeof(FX_WCHAR)); 698 FXSYS_memcpy32(lpszTarget, lpszNew, nReplacementLen * sizeof(FX_WCHAR)); 699 lpszStart = lpszTarget + nReplacementLen; 700 lpszStart[nBalance] = 0; 701 nOldLength += (nReplacementLen - nSourceLen); 702 } 703 } 704 ASSERT(m_pData->m_String[nNewLength] == 0); 705 m_pData->m_nDataLength = nNewLength; 706 } 707 return nCount; 708} 709FX_STRSIZE CFX_WideString::Insert(FX_STRSIZE nIndex, FX_WCHAR ch) 710{ 711 CopyBeforeWrite(); 712 if (nIndex < 0) { 713 nIndex = 0; 714 } 715 FX_STRSIZE nNewLength = GetLength(); 716 if (nIndex > nNewLength) { 717 nIndex = nNewLength; 718 } 719 nNewLength++; 720 if (m_pData == NULL || m_pData->m_nAllocLength < nNewLength) { 721 CFX_StringDataW* pOldData = m_pData; 722 FX_LPCWSTR pstr = m_pData->m_String; 723 m_pData = FX_AllocStringW(nNewLength); 724 if (!m_pData) { 725 return 0; 726 } 727 if(pOldData != NULL) { 728 FXSYS_memmove32(m_pData->m_String, pstr, (pOldData->m_nDataLength + 1)*sizeof(FX_WCHAR)); 729 FX_ReleaseStringW(pOldData); 730 } else { 731 m_pData->m_String[0] = 0; 732 } 733 } 734 FXSYS_memmove32(m_pData->m_String + nIndex + 1, 735 m_pData->m_String + nIndex, (nNewLength - nIndex)*sizeof(FX_WCHAR)); 736 m_pData->m_String[nIndex] = ch; 737 m_pData->m_nDataLength = nNewLength; 738 return nNewLength; 739} 740FX_STRSIZE CFX_WideString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount) 741{ 742 if (GetLength() < 1) { 743 return 0; 744 } 745 if (nIndex < 0) { 746 nIndex = 0; 747 } 748 FX_STRSIZE nOldLength = m_pData->m_nDataLength; 749 if (nCount > 0 && nIndex < nOldLength) { 750 CopyBeforeWrite(); 751 int nBytesToCopy = nOldLength - (nIndex + nCount) + 1; 752 FXSYS_memmove32(m_pData->m_String + nIndex, 753 m_pData->m_String + nIndex + nCount, nBytesToCopy * sizeof(FX_WCHAR)); 754 m_pData->m_nDataLength = nOldLength - nCount; 755 } 756 return m_pData->m_nDataLength; 757} 758FX_STRSIZE CFX_WideString::Remove(FX_WCHAR chRemove) 759{ 760 if (m_pData == NULL) { 761 return 0; 762 } 763 CopyBeforeWrite(); 764 if (GetLength() < 1) { 765 return 0; 766 } 767 FX_LPWSTR pstrSource = m_pData->m_String; 768 FX_LPWSTR pstrDest = m_pData->m_String; 769 FX_LPWSTR pstrEnd = m_pData->m_String + m_pData->m_nDataLength; 770 while (pstrSource < pstrEnd) { 771 if (*pstrSource != chRemove) { 772 *pstrDest = *pstrSource; 773 pstrDest ++; 774 } 775 pstrSource ++; 776 } 777 *pstrDest = 0; 778 FX_STRSIZE nCount = (FX_STRSIZE)(pstrSource - pstrDest); 779 m_pData->m_nDataLength -= nCount; 780 return nCount; 781} 782#define FORCE_ANSI 0x10000 783#define FORCE_UNICODE 0x20000 784#define FORCE_INT64 0x40000 785void CFX_WideString::FormatV(FX_LPCWSTR lpszFormat, va_list argList) 786{ 787 va_list argListSave; 788#if defined(__ARMCC_VERSION) || (!defined(_MSC_VER) && (_FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ || _FX_CPU_ == _FX_ARM64_)) || defined(__native_client__) 789 va_copy(argListSave, argList); 790#else 791 argListSave = argList; 792#endif 793 int nMaxLen = 0; 794 for (FX_LPCWSTR lpsz = lpszFormat; *lpsz != 0; lpsz ++) { 795 if (*lpsz != '%' || *(lpsz = lpsz + 1) == '%') { 796 nMaxLen += (FX_STRSIZE)FXSYS_wcslen(lpsz); 797 continue; 798 } 799 int nItemLen = 0; 800 int nWidth = 0; 801 for (; *lpsz != 0; lpsz ++) { 802 if (*lpsz == '#') { 803 nMaxLen += 2; 804 } else if (*lpsz == '*') { 805 nWidth = va_arg(argList, int); 806 } else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' || 807 *lpsz == ' ') 808 ; 809 else { 810 break; 811 } 812 } 813 if (nWidth == 0) { 814 nWidth = FXSYS_wtoi(lpsz); 815 for (; *lpsz != 0 && (*lpsz) <= '9' && (*lpsz) >= '0'; lpsz ++) 816 ; 817 } 818 if (nWidth < 0 || nWidth > 128 * 1024) { 819 lpszFormat = (FX_LPCWSTR)L"Bad width"; 820 nMaxLen = 10; 821 break; 822 } 823 int nPrecision = 0; 824 if (*lpsz == '.') { 825 lpsz ++; 826 if (*lpsz == '*') { 827 nPrecision = va_arg(argList, int); 828 lpsz ++; 829 } else { 830 nPrecision = FXSYS_wtoi(lpsz); 831 for (; *lpsz != 0 && (*lpsz) >= '0' && (*lpsz) <= '9'; lpsz ++) 832 ; 833 } 834 } 835 if (nPrecision < 0 || nPrecision > 128 * 1024) { 836 lpszFormat = (FX_LPCWSTR)L"Bad precision"; 837 nMaxLen = 14; 838 break; 839 } 840 int nModifier = 0; 841 if (*lpsz == L'I' && *(lpsz + 1) == L'6' && *(lpsz + 2) == L'4') { 842 lpsz += 3; 843 nModifier = FORCE_INT64; 844 } else { 845 switch (*lpsz) { 846 case 'h': 847 nModifier = FORCE_ANSI; 848 lpsz ++; 849 break; 850 case 'l': 851 nModifier = FORCE_UNICODE; 852 lpsz ++; 853 break; 854 case 'F': 855 case 'N': 856 case 'L': 857 lpsz ++; 858 break; 859 } 860 } 861 switch (*lpsz | nModifier) { 862 case 'c': 863 case 'C': 864 nItemLen = 2; 865 va_arg(argList, int); 866 break; 867 case 'c'|FORCE_ANSI: 868 case 'C'|FORCE_ANSI: 869 nItemLen = 2; 870 va_arg(argList, int); 871 break; 872 case 'c'|FORCE_UNICODE: 873 case 'C'|FORCE_UNICODE: 874 nItemLen = 2; 875 va_arg(argList, int); 876 break; 877 case 's': { 878 FX_LPCWSTR pstrNextArg = va_arg(argList, FX_LPCWSTR); 879 if (pstrNextArg == NULL) { 880 nItemLen = 6; 881 } else { 882 nItemLen = (FX_STRSIZE)FXSYS_wcslen(pstrNextArg); 883 if (nItemLen < 1) { 884 nItemLen = 1; 885 } 886 } 887 } 888 break; 889 case 'S': { 890 FX_LPCSTR pstrNextArg = va_arg(argList, FX_LPCSTR); 891 if (pstrNextArg == NULL) { 892 nItemLen = 6; 893 } else { 894 nItemLen = (FX_STRSIZE)FXSYS_strlen(pstrNextArg); 895 if (nItemLen < 1) { 896 nItemLen = 1; 897 } 898 } 899 } 900 break; 901 case 's'|FORCE_ANSI: 902 case 'S'|FORCE_ANSI: { 903 FX_LPCSTR pstrNextArg = va_arg(argList, FX_LPCSTR); 904 if (pstrNextArg == NULL) { 905 nItemLen = 6; 906 } else { 907 nItemLen = (FX_STRSIZE)FXSYS_strlen(pstrNextArg); 908 if (nItemLen < 1) { 909 nItemLen = 1; 910 } 911 } 912 } 913 break; 914 case 's'|FORCE_UNICODE: 915 case 'S'|FORCE_UNICODE: { 916 FX_LPWSTR pstrNextArg = va_arg(argList, FX_LPWSTR); 917 if (pstrNextArg == NULL) { 918 nItemLen = 6; 919 } else { 920 nItemLen = (FX_STRSIZE)FXSYS_wcslen(pstrNextArg); 921 if (nItemLen < 1) { 922 nItemLen = 1; 923 } 924 } 925 } 926 break; 927 } 928 if (nItemLen != 0) { 929 if (nPrecision != 0 && nItemLen > nPrecision) { 930 nItemLen = nPrecision; 931 } 932 if (nItemLen < nWidth) { 933 nItemLen = nWidth; 934 } 935 } else { 936 switch (*lpsz) { 937 case 'd': 938 case 'i': 939 case 'u': 940 case 'x': 941 case 'X': 942 case 'o': 943 if (nModifier & FORCE_INT64) { 944 va_arg(argList, FX_INT64); 945 } else { 946 va_arg(argList, int); 947 } 948 nItemLen = 32; 949 if (nItemLen < nWidth + nPrecision) { 950 nItemLen = nWidth + nPrecision; 951 } 952 break; 953 case 'a': 954 case 'A': 955 case 'e': 956 case 'E': 957 case 'g': 958 case 'G': 959 va_arg(argList, double); 960 nItemLen = 128; 961 if (nItemLen < nWidth + nPrecision) { 962 nItemLen = nWidth + nPrecision; 963 } 964 break; 965 case 'f': 966 if (nWidth + nPrecision > 100) { 967 nItemLen = nPrecision + nWidth + 128; 968 } else { 969 double f; 970 char pszTemp[256]; 971 f = va_arg(argList, double); 972 FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, nPrecision + 6, f ); 973 nItemLen = (FX_STRSIZE)FXSYS_strlen(pszTemp); 974 } 975 break; 976 case 'p': 977 va_arg(argList, void*); 978 nItemLen = 32; 979 if (nItemLen < nWidth + nPrecision) { 980 nItemLen = nWidth + nPrecision; 981 } 982 break; 983 case 'n': 984 va_arg(argList, int*); 985 break; 986 } 987 } 988 nMaxLen += nItemLen; 989 } 990 GetBuffer(nMaxLen); 991 if (m_pData) { 992 FXSYS_vswprintf((wchar_t*)m_pData->m_String, nMaxLen + 1, (const wchar_t*)lpszFormat, argListSave); 993 ReleaseBuffer(); 994 } 995 va_end(argListSave); 996} 997void CFX_WideString::Format(FX_LPCWSTR lpszFormat, ...) 998{ 999 va_list argList; 1000 va_start(argList, lpszFormat); 1001 FormatV(lpszFormat, argList); 1002 va_end(argList); 1003} 1004FX_FLOAT FX_wtof(FX_LPCWSTR str, int len) 1005{ 1006 if (len == 0) { 1007 return 0.0; 1008 } 1009 int cc = 0; 1010 FX_BOOL bNegative = FALSE; 1011 if (str[0] == '+') { 1012 cc++; 1013 } else if (str[0] == '-') { 1014 bNegative = TRUE; 1015 cc++; 1016 } 1017 int integer = 0; 1018 while (cc < len) { 1019 if (str[cc] == '.') { 1020 break; 1021 } 1022 integer = integer * 10 + str[cc] - '0'; 1023 cc ++; 1024 } 1025 FX_FLOAT fraction = 0; 1026 if (str[cc] == '.') { 1027 cc ++; 1028 FX_FLOAT scale = 0.1f; 1029 while (cc < len) { 1030 fraction += scale * (str[cc] - '0'); 1031 scale *= 0.1f; 1032 cc ++; 1033 } 1034 } 1035 fraction += (FX_FLOAT)integer; 1036 return bNegative ? -fraction : fraction; 1037} 1038int CFX_WideString::GetInteger() const 1039{ 1040 if (m_pData == NULL) { 1041 return 0; 1042 } 1043 return FXSYS_wtoi(m_pData->m_String); 1044} 1045FX_FLOAT CFX_WideString::GetFloat() const 1046{ 1047 if (m_pData == NULL) { 1048 return 0.0; 1049 } 1050 return FX_wtof(m_pData->m_String, m_pData->m_nDataLength); 1051} 1052void CFX_WideStringL::Empty(IFX_Allocator* pAllocator) 1053{ 1054 if (m_Ptr) { 1055 FX_Allocator_Free(pAllocator, (FX_LPVOID)m_Ptr); 1056 } 1057 m_Ptr = NULL, m_Length = 0; 1058} 1059void CFX_WideStringL::Set(FX_WSTR src, IFX_Allocator* pAllocator) 1060{ 1061 Empty(pAllocator); 1062 if (src.GetPtr() != NULL && src.GetLength() > 0) { 1063 FX_LPWSTR str = FX_Allocator_Alloc(pAllocator, FX_WCHAR, src.GetLength() + 1); 1064 if (!str) { 1065 return; 1066 } 1067 FXSYS_memcpy32(str, src.GetPtr(), src.GetLength()*sizeof(FX_WCHAR)); 1068 str[src.GetLength()] = '\0'; 1069 *(FX_LPWSTR*)(&m_Ptr) = str; 1070 m_Length = src.GetLength(); 1071 } 1072} 1073int CFX_WideStringL::GetInteger() const 1074{ 1075 if (!m_Ptr) { 1076 return 0; 1077 } 1078 return FXSYS_wtoi(m_Ptr); 1079} 1080FX_FLOAT CFX_WideStringL::GetFloat() const 1081{ 1082 if (!m_Ptr) { 1083 return 0.0f; 1084 } 1085 return FX_wtof(m_Ptr, m_Length); 1086} 1087void CFX_WideStringL::TrimRight(FX_LPCWSTR lpszTargets) 1088{ 1089 if (!lpszTargets || *lpszTargets == 0 || !m_Ptr || m_Length < 1) { 1090 return; 1091 } 1092 FX_STRSIZE pos = m_Length; 1093 while (pos) { 1094 if (FXSYS_wcschr(lpszTargets, m_Ptr[pos - 1]) == NULL) { 1095 break; 1096 } 1097 pos --; 1098 } 1099 if (pos < m_Length) { 1100 (*(FX_LPWSTR*)(&m_Ptr))[pos] = 0; 1101 m_Length = pos; 1102 } 1103} 1104static CFX_ByteString _DefMap_GetByteString(CFX_CharMap* pCharMap, const CFX_WideString& widestr) 1105{ 1106 int src_len = widestr.GetLength(); 1107 int codepage = pCharMap->m_GetCodePage ? pCharMap->m_GetCodePage() : 0; 1108 int dest_len = FXSYS_WideCharToMultiByte(codepage, 0, widestr, src_len, NULL, 0, NULL, NULL); 1109 if (dest_len == 0) { 1110 return CFX_ByteString(); 1111 } 1112 CFX_ByteString bytestr; 1113 FX_LPSTR dest_buf = bytestr.GetBuffer(dest_len); 1114 FXSYS_WideCharToMultiByte(codepage, 0, widestr, src_len, dest_buf, dest_len, NULL, NULL); 1115 bytestr.ReleaseBuffer(dest_len); 1116 return bytestr; 1117} 1118static CFX_WideString _DefMap_GetWideString(CFX_CharMap* pCharMap, const CFX_ByteString& bytestr) 1119{ 1120 int src_len = bytestr.GetLength(); 1121 int codepage = pCharMap->m_GetCodePage ? pCharMap->m_GetCodePage() : 0; 1122 int dest_len = FXSYS_MultiByteToWideChar(codepage, 0, bytestr, src_len, NULL, 0); 1123 if (dest_len == 0) { 1124 return CFX_WideString(); 1125 } 1126 CFX_WideString widestr; 1127 FX_LPWSTR dest_buf = widestr.GetBuffer(dest_len); 1128 FXSYS_MultiByteToWideChar(codepage, 0, bytestr, src_len, dest_buf, dest_len); 1129 widestr.ReleaseBuffer(dest_len); 1130 return widestr; 1131} 1132static int _DefMap_GetGBKCodePage() 1133{ 1134 return 936; 1135} 1136static int _DefMap_GetUHCCodePage() 1137{ 1138 return 949; 1139} 1140static int _DefMap_GetJISCodePage() 1141{ 1142 return 932; 1143} 1144static int _DefMap_GetBig5CodePage() 1145{ 1146 return 950; 1147} 1148static const CFX_CharMap g_DefaultMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, NULL}; 1149static const CFX_CharMap g_DefaultGBKMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetGBKCodePage}; 1150static const CFX_CharMap g_DefaultJISMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetJISCodePage}; 1151static const CFX_CharMap g_DefaultUHCMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetUHCCodePage}; 1152static const CFX_CharMap g_DefaultBig5Mapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetBig5CodePage}; 1153CFX_CharMap* CFX_CharMap::GetDefaultMapper(FX_INT32 codepage) 1154{ 1155 switch (codepage) { 1156 case 0: 1157 return (CFX_CharMap*)&g_DefaultMapper; 1158 case 932: 1159 return (CFX_CharMap*)&g_DefaultJISMapper; 1160 case 936: 1161 return (CFX_CharMap*)&g_DefaultGBKMapper; 1162 case 949: 1163 return (CFX_CharMap*)&g_DefaultUHCMapper; 1164 case 950: 1165 return (CFX_CharMap*)&g_DefaultBig5Mapper; 1166 } 1167 return NULL; 1168} 1169