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