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" 8 static 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 } 23 static 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 } 33 CFX_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 } 43 void 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 } 58 CFX_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 } 72 CFX_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 } 79 CFX_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 } 90 CFX_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 } 103 void 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 } 120 const 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 } 129 const 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 } 138 const 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 } 157 const CFX_WideString& CFX_WideString::operator+=(FX_WCHAR ch) 158 { 159 ConcatInPlace(1, &ch); 160 return *this; 161 } 162 const 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 } 169 const 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 } 177 const 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 } 185 bool operator==(const CFX_WideString& s1, FX_LPCWSTR s2) 186 { 187 return s1.Equal(s2); 188 } 189 bool operator==(FX_LPCWSTR s1, const CFX_WideString& s2) 190 { 191 return s2.Equal(s1); 192 } 193 bool operator==(const CFX_WideString& s1, const CFX_WideString& s2) 194 { 195 return s1.Equal(s2); 196 } 197 bool operator==(const CFX_WideString& s1, const CFX_WideStringC& s2) 198 { 199 return s1.Equal(s2); 200 } 201 bool operator==(const CFX_WideStringC& s1, const CFX_WideString& s2) 202 { 203 return s2.Equal(s1); 204 } 205 bool operator != (const CFX_WideString& s1, FX_LPCWSTR s2) 206 { 207 return !s1.Equal(s2); 208 } 209 bool operator!=(const CFX_WideString& s1, const CFX_WideString& s2) 210 { 211 return !s1.Equal(s2); 212 } 213 bool operator!=(const CFX_WideString& s1, const CFX_WideStringC& s2) 214 { 215 return !s1.Equal(s2); 216 } 217 bool operator!=(const CFX_WideStringC& s1, const CFX_WideString& s2) 218 { 219 return !s2.Equal(s1); 220 } 221 bool 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 } 229 void 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 } 241 void 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 } 263 void 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 } 276 void 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 } 289 void 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 } 297 void 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 } 304 int 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 } 311 CFX_ByteString CFX_WideString::UTF8Encode() const 312 { 313 return FX_UTF8Encode(*this); 314 } 315 CFX_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 } 336 void 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 } 343 void CFX_WideString::Reserve(FX_STRSIZE len) 344 { 345 GetBuffer(len); 346 ReleaseBuffer(GetLength()); 347 } 348 FX_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 } 382 CFX_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 } 388 CFX_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 } 405 CFX_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 } 424 void 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 } 437 CFX_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 } 452 CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst) const 453 { 454 return Mid(nFirst, m_pData->m_nDataLength - nFirst); 455 } 456 CFX_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 } 480 CFX_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 } 495 int 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 } 502 int 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 } 529 FX_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 } 538 void 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 } 548 void 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 } 559 void 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 } 570 FX_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 } 579 FX_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 } 591 void 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 } 614 void CFX_WideString::TrimRight(FX_WCHAR chTarget) 615 { 616 FX_WCHAR str[2] = {chTarget, 0}; 617 TrimRight(str); 618 } 619 void CFX_WideString::TrimRight() 620 { 621 TrimRight(L"\x09\x0a\x0b\x0c\x0d\x20"); 622 } 623 void 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 } 646 void CFX_WideString::TrimLeft(FX_WCHAR chTarget) 647 { 648 FX_WCHAR str[2] = {chTarget, 0}; 649 TrimLeft(str); 650 } 651 void CFX_WideString::TrimLeft() 652 { 653 TrimLeft(L"\x09\x0a\x0b\x0c\x0d\x20"); 654 } 655 FX_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 } 709 FX_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 } 740 FX_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 } 758 FX_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 785 void 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 } 997 void 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 } 1004 FX_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 } 1038 int CFX_WideString::GetInteger() const 1039 { 1040 if (m_pData == NULL) { 1041 return 0; 1042 } 1043 return FXSYS_wtoi(m_pData->m_String); 1044 } 1045 FX_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 } 1052 void 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 } 1059 void 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 } 1073 int CFX_WideStringL::GetInteger() const 1074 { 1075 if (!m_Ptr) { 1076 return 0; 1077 } 1078 return FXSYS_wtoi(m_Ptr); 1079 } 1080 FX_FLOAT CFX_WideStringL::GetFloat() const 1081 { 1082 if (!m_Ptr) { 1083 return 0.0f; 1084 } 1085 return FX_wtof(m_Ptr, m_Length); 1086 } 1087 void 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 } 1104 static 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 } 1118 static 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 } 1132 static int _DefMap_GetGBKCodePage() 1133 { 1134 return 936; 1135 } 1136 static int _DefMap_GetUHCCodePage() 1137 { 1138 return 949; 1139 } 1140 static int _DefMap_GetJISCodePage() 1141 { 1142 return 932; 1143 } 1144 static int _DefMap_GetBig5CodePage() 1145 { 1146 return 950; 1147 } 1148 static const CFX_CharMap g_DefaultMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, NULL}; 1149 static const CFX_CharMap g_DefaultGBKMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetGBKCodePage}; 1150 static const CFX_CharMap g_DefaultJISMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetJISCodePage}; 1151 static const CFX_CharMap g_DefaultUHCMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetUHCCodePage}; 1152 static const CFX_CharMap g_DefaultBig5Mapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetBig5CodePage}; 1153 CFX_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