K. Moon | 832a694 | 2022-10-31 20:11:31 +0000 | [diff] [blame] | 1 | // Copyright 2014 The PDFium Authors |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
Bo Xu | 3522876 | 2014-07-08 15:30:46 -0700 | [diff] [blame] | 4 | |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 5 | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 7 | #include "core/fxcrt/widestring.h" |
Tom Sepez | fcdb2df | 2017-03-31 10:32:07 -0700 | [diff] [blame] | 8 | |
Dan Sinclair | 3ebd121 | 2016-03-09 09:59:23 -0500 | [diff] [blame] | 9 | #include <stddef.h> |
Lei Zhang | bd35360 | 2021-06-30 04:24:07 +0000 | [diff] [blame] | 10 | #include <string.h> |
Lei Zhang | 375a864 | 2016-01-11 11:59:17 -0800 | [diff] [blame] | 11 | |
| 12 | #include <algorithm> |
Tom Sepez | 15c1e6a | 2021-11-16 21:02:27 +0000 | [diff] [blame] | 13 | #include <sstream> |
Tom Sepez | 0b36bb4 | 2015-05-01 16:12:48 -0700 | [diff] [blame] | 14 | |
Dan Sinclair | c0aefd4 | 2017-05-04 10:17:51 -0400 | [diff] [blame] | 15 | #include "core/fxcrt/fx_codepage.h" |
Dan Sinclair | cfb1944 | 2017-04-20 13:13:04 -0400 | [diff] [blame] | 16 | #include "core/fxcrt/fx_extension.h" |
Tom Sepez | 746c287 | 2017-04-07 16:35:13 -0700 | [diff] [blame] | 17 | #include "core/fxcrt/fx_safe_types.h" |
Lei Zhang | bd35360 | 2021-06-30 04:24:07 +0000 | [diff] [blame] | 18 | #include "core/fxcrt/fx_system.h" |
Dan Sinclair | 8e9e3d8 | 2017-09-21 16:49:32 -0400 | [diff] [blame] | 19 | #include "core/fxcrt/string_pool_template.h" |
Tom Sepez | 49f0932 | 2021-01-26 22:13:55 +0000 | [diff] [blame] | 20 | #include "third_party/base/check.h" |
Lei Zhang | 4582920 | 2021-04-16 16:42:11 +0000 | [diff] [blame] | 21 | #include "third_party/base/check_op.h" |
Lei Zhang | efd4423 | 2021-07-30 17:04:57 +0000 | [diff] [blame] | 22 | #include "third_party/base/cxx17_backports.h" |
Lei Zhang | 8241df7 | 2015-11-06 14:38:48 -0800 | [diff] [blame] | 23 | #include "third_party/base/numerics/safe_math.h" |
Chris Palmer | 30f2ff1 | 2014-07-08 13:27:00 -0700 | [diff] [blame] | 24 | |
Dan Sinclair | 20a1755 | 2017-09-21 16:35:56 -0400 | [diff] [blame] | 25 | template class fxcrt::StringDataTemplate<wchar_t>; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 26 | template class fxcrt::StringViewTemplate<wchar_t>; |
Dan Sinclair | 8e9e3d8 | 2017-09-21 16:49:32 -0400 | [diff] [blame] | 27 | template class fxcrt::StringPoolTemplate<WideString>; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 28 | template struct std::hash<WideString>; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 29 | |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 30 | #define FORCE_ANSI 0x10000 |
| 31 | #define FORCE_UNICODE 0x20000 |
| 32 | #define FORCE_INT64 0x40000 |
| 33 | |
Lei Zhang | 11d3336 | 2016-02-19 14:26:46 -0800 | [diff] [blame] | 34 | namespace { |
| 35 | |
Lei Zhang | 7981d15 | 2018-01-11 14:26:01 +0000 | [diff] [blame] | 36 | constexpr wchar_t kWideTrimChars[] = L"\x09\x0a\x0b\x0c\x0d\x20"; |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 37 | |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 38 | const wchar_t* FX_wcsstr(const wchar_t* haystack, |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 39 | size_t haystack_len, |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 40 | const wchar_t* needle, |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 41 | size_t needle_len) { |
| 42 | if (needle_len > haystack_len || needle_len == 0) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 43 | return nullptr; |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 44 | |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 45 | const wchar_t* end_ptr = haystack + haystack_len - needle_len; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 46 | while (haystack <= end_ptr) { |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 47 | size_t i = 0; |
Anton Bikineev | 7ac1334 | 2022-01-24 21:25:15 +0000 | [diff] [blame] | 48 | while (true) { |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 49 | if (haystack[i] != needle[i]) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 50 | break; |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 51 | |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 52 | i++; |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 53 | if (i == needle_len) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 54 | return haystack; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 55 | } |
| 56 | haystack++; |
| 57 | } |
| 58 | return nullptr; |
| 59 | } |
| 60 | |
Lei Zhang | 2c49530 | 2021-10-07 23:13:30 +0000 | [diff] [blame] | 61 | absl::optional<size_t> GuessSizeForVSWPrintf(const wchar_t* pFormat, |
| 62 | va_list argList) { |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 63 | size_t nMaxLen = 0; |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 64 | for (const wchar_t* pStr = pFormat; *pStr != 0; pStr++) { |
| 65 | if (*pStr != '%' || *(pStr = pStr + 1) == '%') { |
Tom Sepez | 3efc067 | 2017-03-30 15:28:23 -0700 | [diff] [blame] | 66 | ++nMaxLen; |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 67 | continue; |
| 68 | } |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 69 | int iWidth = 0; |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 70 | for (; *pStr != 0; pStr++) { |
| 71 | if (*pStr == '#') { |
| 72 | nMaxLen += 2; |
| 73 | } else if (*pStr == '*') { |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 74 | iWidth = va_arg(argList, int); |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 75 | } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' && *pStr != ' ') { |
| 76 | break; |
| 77 | } |
| 78 | } |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 79 | if (iWidth == 0) { |
| 80 | iWidth = FXSYS_wtoi(pStr); |
Lei Zhang | 4609c5d | 2018-12-07 20:10:54 +0000 | [diff] [blame] | 81 | while (FXSYS_IsDecimalDigit(*pStr)) |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 82 | ++pStr; |
| 83 | } |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 84 | if (iWidth < 0 || iWidth > 128 * 1024) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 85 | return absl::nullopt; |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 86 | uint32_t nWidth = static_cast<uint32_t>(iWidth); |
| 87 | int iPrecision = 0; |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 88 | if (*pStr == '.') { |
| 89 | pStr++; |
| 90 | if (*pStr == '*') { |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 91 | iPrecision = va_arg(argList, int); |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 92 | pStr++; |
| 93 | } else { |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 94 | iPrecision = FXSYS_wtoi(pStr); |
Lei Zhang | 4609c5d | 2018-12-07 20:10:54 +0000 | [diff] [blame] | 95 | while (FXSYS_IsDecimalDigit(*pStr)) |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 96 | ++pStr; |
| 97 | } |
| 98 | } |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 99 | if (iPrecision < 0 || iPrecision > 128 * 1024) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 100 | return absl::nullopt; |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 101 | uint32_t nPrecision = static_cast<uint32_t>(iPrecision); |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 102 | int nModifier = 0; |
| 103 | if (*pStr == L'I' && *(pStr + 1) == L'6' && *(pStr + 2) == L'4') { |
| 104 | pStr += 3; |
| 105 | nModifier = FORCE_INT64; |
| 106 | } else { |
| 107 | switch (*pStr) { |
| 108 | case 'h': |
| 109 | nModifier = FORCE_ANSI; |
| 110 | pStr++; |
| 111 | break; |
| 112 | case 'l': |
| 113 | nModifier = FORCE_UNICODE; |
| 114 | pStr++; |
| 115 | break; |
| 116 | case 'F': |
| 117 | case 'N': |
| 118 | case 'L': |
| 119 | pStr++; |
| 120 | break; |
| 121 | } |
| 122 | } |
Tom Sepez | ad00459 | 2021-11-05 22:19:18 +0000 | [diff] [blame] | 123 | size_t nItemLen = 0; |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 124 | switch (*pStr | nModifier) { |
| 125 | case 'c': |
| 126 | case 'C': |
| 127 | nItemLen = 2; |
| 128 | va_arg(argList, int); |
| 129 | break; |
| 130 | case 'c' | FORCE_ANSI: |
| 131 | case 'C' | FORCE_ANSI: |
| 132 | nItemLen = 2; |
| 133 | va_arg(argList, int); |
| 134 | break; |
| 135 | case 'c' | FORCE_UNICODE: |
| 136 | case 'C' | FORCE_UNICODE: |
| 137 | nItemLen = 2; |
| 138 | va_arg(argList, int); |
| 139 | break; |
| 140 | case 's': { |
| 141 | const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*); |
| 142 | if (pstrNextArg) { |
Ryan Harrison | 8b1408e | 2017-09-27 11:07:51 -0400 | [diff] [blame] | 143 | nItemLen = wcslen(pstrNextArg); |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 144 | if (nItemLen < 1) { |
| 145 | nItemLen = 1; |
| 146 | } |
| 147 | } else { |
| 148 | nItemLen = 6; |
| 149 | } |
| 150 | } break; |
| 151 | case 'S': { |
| 152 | const char* pstrNextArg = va_arg(argList, const char*); |
| 153 | if (pstrNextArg) { |
Ryan Harrison | 8b1408e | 2017-09-27 11:07:51 -0400 | [diff] [blame] | 154 | nItemLen = strlen(pstrNextArg); |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 155 | if (nItemLen < 1) { |
| 156 | nItemLen = 1; |
| 157 | } |
| 158 | } else { |
| 159 | nItemLen = 6; |
| 160 | } |
| 161 | } break; |
| 162 | case 's' | FORCE_ANSI: |
| 163 | case 'S' | FORCE_ANSI: { |
| 164 | const char* pstrNextArg = va_arg(argList, const char*); |
| 165 | if (pstrNextArg) { |
Ryan Harrison | 8b1408e | 2017-09-27 11:07:51 -0400 | [diff] [blame] | 166 | nItemLen = strlen(pstrNextArg); |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 167 | if (nItemLen < 1) { |
| 168 | nItemLen = 1; |
| 169 | } |
| 170 | } else { |
| 171 | nItemLen = 6; |
| 172 | } |
| 173 | } break; |
| 174 | case 's' | FORCE_UNICODE: |
| 175 | case 'S' | FORCE_UNICODE: { |
| 176 | const wchar_t* pstrNextArg = va_arg(argList, wchar_t*); |
| 177 | if (pstrNextArg) { |
Ryan Harrison | 8b1408e | 2017-09-27 11:07:51 -0400 | [diff] [blame] | 178 | nItemLen = wcslen(pstrNextArg); |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 179 | if (nItemLen < 1) { |
| 180 | nItemLen = 1; |
| 181 | } |
| 182 | } else { |
| 183 | nItemLen = 6; |
| 184 | } |
| 185 | } break; |
| 186 | } |
| 187 | if (nItemLen != 0) { |
| 188 | if (nPrecision != 0 && nItemLen > nPrecision) { |
| 189 | nItemLen = nPrecision; |
| 190 | } |
| 191 | if (nItemLen < nWidth) { |
| 192 | nItemLen = nWidth; |
| 193 | } |
| 194 | } else { |
| 195 | switch (*pStr) { |
| 196 | case 'd': |
| 197 | case 'i': |
| 198 | case 'u': |
| 199 | case 'x': |
| 200 | case 'X': |
| 201 | case 'o': |
| 202 | if (nModifier & FORCE_INT64) { |
| 203 | va_arg(argList, int64_t); |
| 204 | } else { |
| 205 | va_arg(argList, int); |
| 206 | } |
| 207 | nItemLen = 32; |
| 208 | if (nItemLen < nWidth + nPrecision) { |
| 209 | nItemLen = nWidth + nPrecision; |
| 210 | } |
| 211 | break; |
| 212 | case 'a': |
| 213 | case 'A': |
| 214 | case 'e': |
| 215 | case 'E': |
| 216 | case 'g': |
| 217 | case 'G': |
| 218 | va_arg(argList, double); |
| 219 | nItemLen = 128; |
| 220 | if (nItemLen < nWidth + nPrecision) { |
| 221 | nItemLen = nWidth + nPrecision; |
| 222 | } |
| 223 | break; |
| 224 | case 'f': |
| 225 | if (nWidth + nPrecision > 100) { |
| 226 | nItemLen = nPrecision + nWidth + 128; |
| 227 | } else { |
| 228 | double f; |
| 229 | char pszTemp[256]; |
| 230 | f = va_arg(argList, double); |
| 231 | FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, |
| 232 | nPrecision + 6, f); |
Ryan Harrison | 8b1408e | 2017-09-27 11:07:51 -0400 | [diff] [blame] | 233 | nItemLen = strlen(pszTemp); |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 234 | } |
| 235 | break; |
| 236 | case 'p': |
| 237 | va_arg(argList, void*); |
| 238 | nItemLen = 32; |
| 239 | if (nItemLen < nWidth + nPrecision) { |
| 240 | nItemLen = nWidth + nPrecision; |
| 241 | } |
| 242 | break; |
| 243 | case 'n': |
| 244 | va_arg(argList, int*); |
| 245 | break; |
| 246 | } |
| 247 | } |
| 248 | nMaxLen += nItemLen; |
| 249 | } |
Tom Sepez | 3efc067 | 2017-03-30 15:28:23 -0700 | [diff] [blame] | 250 | nMaxLen += 32; // Fudge factor. |
Daniel Hosseinian | 338637d | 2019-10-19 00:37:45 +0000 | [diff] [blame] | 251 | return nMaxLen; |
Tom Sepez | bf9104d | 2017-03-30 13:51:31 -0700 | [diff] [blame] | 252 | } |
| 253 | |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 254 | // Returns string unless we ran out of space. |
Lei Zhang | 2c49530 | 2021-10-07 23:13:30 +0000 | [diff] [blame] | 255 | absl::optional<WideString> TryVSWPrintf(size_t size, |
| 256 | const wchar_t* pFormat, |
| 257 | va_list argList) { |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 258 | if (!size) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 259 | return absl::nullopt; |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 260 | |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 261 | WideString str; |
| 262 | { |
| 263 | // Span's lifetime must end before ReleaseBuffer() below. |
| 264 | pdfium::span<wchar_t> buffer = str.GetBuffer(size); |
| 265 | |
| 266 | // In the following two calls, there's always space in the WideString |
| 267 | // for a terminating NUL that's not included in the span. |
| 268 | // For vswprintf(), MSAN won't untaint the buffer on a truncated write's |
| 269 | // -1 return code even though the buffer is written. Probably just as well |
| 270 | // not to trust the vendor's implementation to write anything anyways. |
| 271 | // See https://crbug.com/705912. |
| 272 | memset(buffer.data(), 0, (size + 1) * sizeof(wchar_t)); |
| 273 | int ret = vswprintf(buffer.data(), size + 1, pFormat, argList); |
| 274 | |
| 275 | bool bSufficientBuffer = ret >= 0 || buffer[size - 1] == 0; |
| 276 | if (!bSufficientBuffer) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 277 | return absl::nullopt; |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 278 | } |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 279 | str.ReleaseBuffer(str.GetStringLength()); |
Tom Sepez | b1bd2ea | 2021-06-05 00:22:21 +0000 | [diff] [blame] | 280 | return str; |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 281 | } |
| 282 | |
Lei Zhang | 11d3336 | 2016-02-19 14:26:46 -0800 | [diff] [blame] | 283 | } // namespace |
| 284 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 285 | namespace fxcrt { |
| 286 | |
| 287 | static_assert(sizeof(WideString) <= sizeof(wchar_t*), |
tsepez | 3343194 | 2016-04-21 11:17:22 -0700 | [diff] [blame] | 288 | "Strings must not require more space than pointers"); |
| 289 | |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 290 | // static |
Tom Sepez | cb74374 | 2022-04-22 21:04:00 +0000 | [diff] [blame] | 291 | WideString WideString::FormatInteger(int i) { |
| 292 | wchar_t wbuf[32]; |
| 293 | swprintf(wbuf, std::size(wbuf), L"%d", i); |
| 294 | return WideString(wbuf); |
| 295 | } |
| 296 | |
| 297 | // static |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 298 | WideString WideString::FormatV(const wchar_t* format, va_list argList) { |
| 299 | va_list argListCopy; |
| 300 | va_copy(argListCopy, argList); |
Lei Zhang | 2bd5d57 | 2023-04-18 20:33:37 +0000 | [diff] [blame] | 301 | auto guess = GuessSizeForVSWPrintf(format, argListCopy); |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 302 | va_end(argListCopy); |
| 303 | |
Lei Zhang | 2bd5d57 | 2023-04-18 20:33:37 +0000 | [diff] [blame] | 304 | if (!guess.has_value()) { |
| 305 | return WideString(); |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 306 | } |
Lei Zhang | 2bd5d57 | 2023-04-18 20:33:37 +0000 | [diff] [blame] | 307 | int maxLen = pdfium::base::checked_cast<int>(guess.value()); |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 308 | |
| 309 | while (maxLen < 32 * 1024) { |
| 310 | va_copy(argListCopy, argList); |
Lei Zhang | 2c49530 | 2021-10-07 23:13:30 +0000 | [diff] [blame] | 311 | absl::optional<WideString> ret = |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 312 | TryVSWPrintf(static_cast<size_t>(maxLen), format, argListCopy); |
| 313 | va_end(argListCopy); |
Tom Sepez | e708129 | 2021-06-04 23:44:21 +0000 | [diff] [blame] | 314 | if (ret.has_value()) |
Tom Sepez | 685fad3 | 2021-06-05 01:04:27 +0000 | [diff] [blame] | 315 | return ret.value(); |
| 316 | |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 317 | maxLen *= 2; |
| 318 | } |
Tom Sepez | 890eac2 | 2018-12-03 20:35:51 +0000 | [diff] [blame] | 319 | return WideString(); |
Dan Sinclair | 3f1c832 | 2017-11-16 21:45:18 +0000 | [diff] [blame] | 320 | } |
| 321 | |
| 322 | // static |
| 323 | WideString WideString::Format(const wchar_t* pFormat, ...) { |
| 324 | va_list argList; |
| 325 | va_start(argList, pFormat); |
| 326 | WideString ret = FormatV(pFormat, argList); |
| 327 | va_end(argList); |
| 328 | return ret; |
| 329 | } |
| 330 | |
Lei Zhang | 4affe8b | 2020-10-13 20:01:23 +0000 | [diff] [blame] | 331 | WideString::WideString() = default; |
weili | f4bb580 | 2016-06-14 17:21:14 -0700 | [diff] [blame] | 332 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 333 | WideString::WideString(const WideString& other) : m_pData(other.m_pData) {} |
weili | f4bb580 | 2016-06-14 17:21:14 -0700 | [diff] [blame] | 334 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 335 | WideString::WideString(WideString&& other) noexcept { |
weili | f4bb580 | 2016-06-14 17:21:14 -0700 | [diff] [blame] | 336 | m_pData.Swap(other.m_pData); |
| 337 | } |
| 338 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 339 | WideString::WideString(const wchar_t* pStr, size_t nLen) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 340 | if (nLen) |
| 341 | m_pData.Reset(StringData::Create(pStr, nLen)); |
| 342 | } |
Tom Sepez | 7f840ae | 2015-04-30 15:46:34 -0700 | [diff] [blame] | 343 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 344 | WideString::WideString(wchar_t ch) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 345 | m_pData.Reset(StringData::Create(1)); |
| 346 | m_pData->m_String[0] = ch; |
| 347 | } |
| 348 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 349 | WideString::WideString(const wchar_t* ptr) |
Ryan Harrison | 8b1408e | 2017-09-27 11:07:51 -0400 | [diff] [blame] | 350 | : WideString(ptr, ptr ? wcslen(ptr) : 0) {} |
weili | f4bb580 | 2016-06-14 17:21:14 -0700 | [diff] [blame] | 351 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 352 | WideString::WideString(WideStringView stringSrc) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 353 | if (!stringSrc.IsEmpty()) { |
Tom Sepez | 33b42e4 | 2017-07-19 13:19:12 -0700 | [diff] [blame] | 354 | m_pData.Reset(StringData::Create(stringSrc.unterminated_c_str(), |
| 355 | stringSrc.GetLength())); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 356 | } |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 357 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 358 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 359 | WideString::WideString(WideStringView str1, WideStringView str2) { |
Ryan Harrison | bacf75e | 2017-09-27 10:58:52 -0400 | [diff] [blame] | 360 | FX_SAFE_SIZE_T nSafeLen = str1.GetLength(); |
Tom Sepez | 746c287 | 2017-04-07 16:35:13 -0700 | [diff] [blame] | 361 | nSafeLen += str2.GetLength(); |
| 362 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 363 | size_t nNewLen = nSafeLen.ValueOrDie(); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 364 | if (nNewLen == 0) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 365 | return; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 366 | |
| 367 | m_pData.Reset(StringData::Create(nNewLen)); |
Tom Sepez | 33b42e4 | 2017-07-19 13:19:12 -0700 | [diff] [blame] | 368 | m_pData->CopyContents(str1.unterminated_c_str(), str1.GetLength()); |
| 369 | m_pData->CopyContentsAt(str1.GetLength(), str2.unterminated_c_str(), |
| 370 | str2.GetLength()); |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 371 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 372 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 373 | WideString::WideString(const std::initializer_list<WideStringView>& list) { |
Ryan Harrison | bacf75e | 2017-09-27 10:58:52 -0400 | [diff] [blame] | 374 | FX_SAFE_SIZE_T nSafeLen = 0; |
Tom Sepez | 746c287 | 2017-04-07 16:35:13 -0700 | [diff] [blame] | 375 | for (const auto& item : list) |
| 376 | nSafeLen += item.GetLength(); |
| 377 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 378 | size_t nNewLen = nSafeLen.ValueOrDie(); |
Tom Sepez | 746c287 | 2017-04-07 16:35:13 -0700 | [diff] [blame] | 379 | if (nNewLen == 0) |
| 380 | return; |
| 381 | |
| 382 | m_pData.Reset(StringData::Create(nNewLen)); |
| 383 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 384 | size_t nOffset = 0; |
Tom Sepez | 746c287 | 2017-04-07 16:35:13 -0700 | [diff] [blame] | 385 | for (const auto& item : list) { |
Tom Sepez | 33b42e4 | 2017-07-19 13:19:12 -0700 | [diff] [blame] | 386 | m_pData->CopyContentsAt(nOffset, item.unterminated_c_str(), |
| 387 | item.GetLength()); |
Tom Sepez | 746c287 | 2017-04-07 16:35:13 -0700 | [diff] [blame] | 388 | nOffset += item.GetLength(); |
| 389 | } |
| 390 | } |
| 391 | |
Lei Zhang | 0e744a2 | 2020-06-02 00:44:28 +0000 | [diff] [blame] | 392 | WideString::~WideString() = default; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 393 | |
Tom Sepez | 2246a53 | 2021-12-17 00:35:35 +0000 | [diff] [blame] | 394 | void WideString::clear() { |
| 395 | if (m_pData && m_pData->CanOperateInPlace(0)) { |
| 396 | m_pData->m_nDataLength = 0; |
| 397 | return; |
| 398 | } |
| 399 | m_pData.Reset(); |
| 400 | } |
| 401 | |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 402 | WideString& WideString::operator=(const wchar_t* str) { |
| 403 | if (!str || !str[0]) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 404 | clear(); |
| 405 | else |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 406 | AssignCopy(str, wcslen(str)); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 407 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 408 | return *this; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 409 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 410 | |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 411 | WideString& WideString::operator=(WideStringView str) { |
| 412 | if (str.IsEmpty()) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 413 | clear(); |
| 414 | else |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 415 | AssignCopy(str.unterminated_c_str(), str.GetLength()); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 416 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 417 | return *this; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 418 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 419 | |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 420 | WideString& WideString::operator=(const WideString& that) { |
Tom Sepez | a1ea427 | 2018-06-19 14:37:12 +0000 | [diff] [blame] | 421 | if (m_pData != that.m_pData) |
| 422 | m_pData = that.m_pData; |
| 423 | |
| 424 | return *this; |
| 425 | } |
| 426 | |
Tom Sepez | 8a47b82 | 2020-09-10 23:16:30 +0000 | [diff] [blame] | 427 | WideString& WideString::operator=(WideString&& that) noexcept { |
Tom Sepez | a1ea427 | 2018-06-19 14:37:12 +0000 | [diff] [blame] | 428 | if (m_pData != that.m_pData) |
| 429 | m_pData = std::move(that.m_pData); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 430 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 431 | return *this; |
| 432 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 433 | |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 434 | WideString& WideString::operator+=(const wchar_t* str) { |
| 435 | if (str) |
| 436 | Concat(str, wcslen(str)); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 437 | |
| 438 | return *this; |
| 439 | } |
| 440 | |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 441 | WideString& WideString::operator+=(wchar_t ch) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 442 | Concat(&ch, 1); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 443 | return *this; |
| 444 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 445 | |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 446 | WideString& WideString::operator+=(const WideString& str) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 447 | if (str.m_pData) |
| 448 | Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); |
| 449 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 450 | return *this; |
| 451 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 452 | |
Andrew Weintraub | 50710e7 | 2019-06-24 21:11:55 +0000 | [diff] [blame] | 453 | WideString& WideString::operator+=(WideStringView str) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 454 | if (!str.IsEmpty()) |
Tom Sepez | 33b42e4 | 2017-07-19 13:19:12 -0700 | [diff] [blame] | 455 | Concat(str.unterminated_c_str(), str.GetLength()); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 456 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 457 | return *this; |
| 458 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 459 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 460 | bool WideString::operator==(const wchar_t* ptr) const { |
tsepez | 9f2970c | 2016-04-01 10:23:04 -0700 | [diff] [blame] | 461 | if (!m_pData) |
| 462 | return !ptr || !ptr[0]; |
| 463 | |
| 464 | if (!ptr) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 465 | return m_pData->m_nDataLength == 0; |
tsepez | 9f2970c | 2016-04-01 10:23:04 -0700 | [diff] [blame] | 466 | |
Ryan Harrison | 81f9eee | 2017-09-05 15:33:18 -0400 | [diff] [blame] | 467 | return wcslen(ptr) == m_pData->m_nDataLength && |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 468 | wmemcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; |
| 469 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 470 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 471 | bool WideString::operator==(WideStringView str) const { |
tsepez | 9f2970c | 2016-04-01 10:23:04 -0700 | [diff] [blame] | 472 | if (!m_pData) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 473 | return str.IsEmpty(); |
tsepez | 9f2970c | 2016-04-01 10:23:04 -0700 | [diff] [blame] | 474 | |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 475 | return m_pData->m_nDataLength == str.GetLength() && |
Tom Sepez | 33b42e4 | 2017-07-19 13:19:12 -0700 | [diff] [blame] | 476 | wmemcmp(m_pData->m_String, str.unterminated_c_str(), |
| 477 | str.GetLength()) == 0; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 478 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 479 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 480 | bool WideString::operator==(const WideString& other) const { |
tsepez | 3d70488 | 2016-09-13 18:10:22 -0700 | [diff] [blame] | 481 | if (m_pData == other.m_pData) |
| 482 | return true; |
| 483 | |
tsepez | 9f2970c | 2016-04-01 10:23:04 -0700 | [diff] [blame] | 484 | if (IsEmpty()) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 485 | return other.IsEmpty(); |
tsepez | 9f2970c | 2016-04-01 10:23:04 -0700 | [diff] [blame] | 486 | |
| 487 | if (other.IsEmpty()) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 488 | return false; |
tsepez | 9f2970c | 2016-04-01 10:23:04 -0700 | [diff] [blame] | 489 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 490 | return other.m_pData->m_nDataLength == m_pData->m_nDataLength && |
| 491 | wmemcmp(other.m_pData->m_String, m_pData->m_String, |
| 492 | m_pData->m_nDataLength) == 0; |
| 493 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 494 | |
Lei Zhang | d7a3f98 | 2017-11-06 19:00:21 +0000 | [diff] [blame] | 495 | bool WideString::operator<(const wchar_t* ptr) const { |
Lei Zhang | f3a7edc | 2017-12-12 18:42:18 +0000 | [diff] [blame] | 496 | return Compare(ptr) < 0; |
Lei Zhang | d7a3f98 | 2017-11-06 19:00:21 +0000 | [diff] [blame] | 497 | } |
| 498 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 499 | bool WideString::operator<(WideStringView str) const { |
Lei Zhang | d7a3f98 | 2017-11-06 19:00:21 +0000 | [diff] [blame] | 500 | if (!m_pData && !str.unterminated_c_str()) |
| 501 | return false; |
| 502 | if (c_str() == str.unterminated_c_str()) |
| 503 | return false; |
| 504 | |
| 505 | size_t len = GetLength(); |
| 506 | size_t other_len = str.GetLength(); |
tsepez | 8f53f54 | 2016-09-15 11:55:00 -0700 | [diff] [blame] | 507 | int result = |
Lei Zhang | d7a3f98 | 2017-11-06 19:00:21 +0000 | [diff] [blame] | 508 | wmemcmp(c_str(), str.unterminated_c_str(), std::min(len, other_len)); |
| 509 | return result < 0 || (result == 0 && len < other_len); |
| 510 | } |
| 511 | |
| 512 | bool WideString::operator<(const WideString& other) const { |
Lei Zhang | f3a7edc | 2017-12-12 18:42:18 +0000 | [diff] [blame] | 513 | return Compare(other) < 0; |
tsepez | 8f53f54 | 2016-09-15 11:55:00 -0700 | [diff] [blame] | 514 | } |
| 515 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 516 | void WideString::AssignCopy(const wchar_t* pSrcData, size_t nSrcLen) { |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 517 | AllocBeforeWrite(nSrcLen); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 518 | m_pData->CopyContents(pSrcData, nSrcLen); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 519 | m_pData->m_nDataLength = nSrcLen; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 520 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 521 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 522 | void WideString::ReallocBeforeWrite(size_t nNewLength) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 523 | if (m_pData && m_pData->CanOperateInPlace(nNewLength)) |
| 524 | return; |
| 525 | |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 526 | if (nNewLength == 0) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 527 | clear(); |
| 528 | return; |
| 529 | } |
| 530 | |
Dan Sinclair | 0b95042 | 2017-09-21 15:49:49 -0400 | [diff] [blame] | 531 | RetainPtr<StringData> pNewData(StringData::Create(nNewLength)); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 532 | if (m_pData) { |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 533 | size_t nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 534 | pNewData->CopyContents(m_pData->m_String, nCopyLength); |
| 535 | pNewData->m_nDataLength = nCopyLength; |
| 536 | } else { |
| 537 | pNewData->m_nDataLength = 0; |
| 538 | } |
| 539 | pNewData->m_String[pNewData->m_nDataLength] = 0; |
| 540 | m_pData.Swap(pNewData); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 541 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 542 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 543 | void WideString::AllocBeforeWrite(size_t nNewLength) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 544 | if (m_pData && m_pData->CanOperateInPlace(nNewLength)) |
| 545 | return; |
| 546 | |
Ryan Harrison | 81f9eee | 2017-09-05 15:33:18 -0400 | [diff] [blame] | 547 | if (nNewLength == 0) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 548 | clear(); |
| 549 | return; |
| 550 | } |
| 551 | |
| 552 | m_pData.Reset(StringData::Create(nNewLength)); |
| 553 | } |
| 554 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 555 | void WideString::ReleaseBuffer(size_t nNewLength) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 556 | if (!m_pData) |
| 557 | return; |
| 558 | |
tsepez | 518fd4c | 2016-04-26 12:13:16 -0700 | [diff] [blame] | 559 | nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 560 | if (nNewLength == 0) { |
| 561 | clear(); |
| 562 | return; |
| 563 | } |
| 564 | |
Lei Zhang | 4582920 | 2021-04-16 16:42:11 +0000 | [diff] [blame] | 565 | DCHECK_EQ(m_pData->m_nRefs, 1); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 566 | m_pData->m_nDataLength = nNewLength; |
| 567 | m_pData->m_String[nNewLength] = 0; |
tsepez | 518fd4c | 2016-04-26 12:13:16 -0700 | [diff] [blame] | 568 | if (m_pData->m_nAllocLength - nNewLength >= 32) { |
| 569 | // Over arbitrary threshold, so pay the price to relocate. Force copy to |
| 570 | // always occur by holding a second reference to the string. |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 571 | WideString preserve(*this); |
tsepez | 518fd4c | 2016-04-26 12:13:16 -0700 | [diff] [blame] | 572 | ReallocBeforeWrite(nNewLength); |
| 573 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 574 | } |
| 575 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 576 | void WideString::Reserve(size_t len) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 577 | GetBuffer(len); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 578 | } |
| 579 | |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 580 | pdfium::span<wchar_t> WideString::GetBuffer(size_t nMinBufLength) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 581 | if (!m_pData) { |
| 582 | if (nMinBufLength == 0) |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 583 | return pdfium::span<wchar_t>(); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 584 | |
| 585 | m_pData.Reset(StringData::Create(nMinBufLength)); |
| 586 | m_pData->m_nDataLength = 0; |
| 587 | m_pData->m_String[0] = 0; |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 588 | return pdfium::span<wchar_t>(m_pData->m_String, m_pData->m_nAllocLength); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 589 | } |
| 590 | |
| 591 | if (m_pData->CanOperateInPlace(nMinBufLength)) |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 592 | return pdfium::span<wchar_t>(m_pData->m_String, m_pData->m_nAllocLength); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 593 | |
| 594 | nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); |
| 595 | if (nMinBufLength == 0) |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 596 | return pdfium::span<wchar_t>(); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 597 | |
Dan Sinclair | 0b95042 | 2017-09-21 15:49:49 -0400 | [diff] [blame] | 598 | RetainPtr<StringData> pNewData(StringData::Create(nMinBufLength)); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 599 | pNewData->CopyContents(*m_pData); |
| 600 | pNewData->m_nDataLength = m_pData->m_nDataLength; |
| 601 | m_pData.Swap(pNewData); |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 602 | return pdfium::span<wchar_t>(m_pData->m_String, m_pData->m_nAllocLength); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 603 | } |
| 604 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 605 | size_t WideString::Delete(size_t index, size_t count) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 606 | if (!m_pData) |
| 607 | return 0; |
| 608 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 609 | size_t old_length = m_pData->m_nDataLength; |
Lei Zhang | 10a8fea | 2018-12-05 23:15:53 +0000 | [diff] [blame] | 610 | if (count == 0 || index != pdfium::clamp<size_t>(index, 0, old_length)) |
Ryan Harrison | 0811da8 | 2017-08-02 16:16:18 -0400 | [diff] [blame] | 611 | return old_length; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 612 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 613 | size_t removal_length = index + count; |
Ryan Harrison | 0811da8 | 2017-08-02 16:16:18 -0400 | [diff] [blame] | 614 | if (removal_length > old_length) |
| 615 | return old_length; |
| 616 | |
| 617 | ReallocBeforeWrite(old_length); |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 618 | size_t chars_to_copy = old_length - removal_length + 1; |
Ryan Harrison | 0811da8 | 2017-08-02 16:16:18 -0400 | [diff] [blame] | 619 | wmemmove(m_pData->m_String + index, m_pData->m_String + removal_length, |
| 620 | chars_to_copy); |
| 621 | m_pData->m_nDataLength = old_length - count; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 622 | return m_pData->m_nDataLength; |
| 623 | } |
| 624 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 625 | void WideString::Concat(const wchar_t* pSrcData, size_t nSrcLen) { |
Ryan Harrison | 81f9eee | 2017-09-05 15:33:18 -0400 | [diff] [blame] | 626 | if (!pSrcData || nSrcLen == 0) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 627 | return; |
| 628 | |
| 629 | if (!m_pData) { |
| 630 | m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); |
| 631 | return; |
| 632 | } |
| 633 | |
| 634 | if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { |
| 635 | m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); |
| 636 | m_pData->m_nDataLength += nSrcLen; |
| 637 | return; |
| 638 | } |
| 639 | |
Lei Zhang | 5d6714e | 2018-12-11 18:53:31 +0000 | [diff] [blame] | 640 | size_t nConcatLen = std::max(m_pData->m_nDataLength / 2, nSrcLen); |
Dan Sinclair | 0b95042 | 2017-09-21 15:49:49 -0400 | [diff] [blame] | 641 | RetainPtr<StringData> pNewData( |
Lei Zhang | 5d6714e | 2018-12-11 18:53:31 +0000 | [diff] [blame] | 642 | StringData::Create(m_pData->m_nDataLength + nConcatLen)); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 643 | pNewData->CopyContents(*m_pData); |
| 644 | pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); |
Lei Zhang | 5d6714e | 2018-12-11 18:53:31 +0000 | [diff] [blame] | 645 | pNewData->m_nDataLength = m_pData->m_nDataLength + nSrcLen; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 646 | m_pData.Swap(pNewData); |
| 647 | } |
| 648 | |
Tom Sepez | a1ea427 | 2018-06-19 14:37:12 +0000 | [diff] [blame] | 649 | intptr_t WideString::ReferenceCountForTesting() const { |
| 650 | return m_pData ? m_pData->m_nRefs : 0; |
| 651 | } |
| 652 | |
Tom Sepez | adb9e70 | 2018-11-27 18:43:10 +0000 | [diff] [blame] | 653 | ByteString WideString::ToASCII() const { |
| 654 | ByteString result; |
| 655 | result.Reserve(GetLength()); |
| 656 | for (wchar_t wc : *this) |
| 657 | result.InsertAtBack(static_cast<char>(wc & 0x7f)); |
| 658 | return result; |
| 659 | } |
| 660 | |
Lei Zhang | ebac96b | 2019-01-14 20:20:28 +0000 | [diff] [blame] | 661 | ByteString WideString::ToLatin1() const { |
| 662 | ByteString result; |
| 663 | result.Reserve(GetLength()); |
| 664 | for (wchar_t wc : *this) |
| 665 | result.InsertAtBack(static_cast<char>(wc & 0xff)); |
| 666 | return result; |
| 667 | } |
| 668 | |
Tom Sepez | 34dab07 | 2018-08-08 17:49:02 +0000 | [diff] [blame] | 669 | ByteString WideString::ToDefANSI() const { |
Tom Sepez | 662e7a8 | 2021-08-04 18:02:18 +0000 | [diff] [blame] | 670 | size_t dest_len = |
| 671 | FX_WideCharToMultiByte(FX_CodePage::kDefANSI, AsStringView(), {}); |
Tom Sepez | 34dab07 | 2018-08-08 17:49:02 +0000 | [diff] [blame] | 672 | if (!dest_len) |
| 673 | return ByteString(); |
| 674 | |
| 675 | ByteString bstr; |
| 676 | { |
| 677 | // Span's lifetime must end before ReleaseBuffer() below. |
| 678 | pdfium::span<char> dest_buf = bstr.GetBuffer(dest_len); |
Tom Sepez | 662e7a8 | 2021-08-04 18:02:18 +0000 | [diff] [blame] | 679 | FX_WideCharToMultiByte(FX_CodePage::kDefANSI, AsStringView(), dest_buf); |
Tom Sepez | 34dab07 | 2018-08-08 17:49:02 +0000 | [diff] [blame] | 680 | } |
| 681 | bstr.ReleaseBuffer(dest_len); |
| 682 | return bstr; |
| 683 | } |
| 684 | |
Tom Sepez | b4c95fe | 2018-11-27 01:09:44 +0000 | [diff] [blame] | 685 | ByteString WideString::ToUTF8() const { |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 686 | return FX_UTF8Encode(AsStringView()); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 687 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 688 | |
Tom Sepez | b4c95fe | 2018-11-27 01:09:44 +0000 | [diff] [blame] | 689 | ByteString WideString::ToUTF16LE() const { |
Tom Sepez | 1dbfe99 | 2018-04-17 17:19:30 +0000 | [diff] [blame] | 690 | if (!m_pData) |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 691 | return ByteString("\0\0", 2); |
Tom Sepez | 1dbfe99 | 2018-04-17 17:19:30 +0000 | [diff] [blame] | 692 | |
Tom Sepez | 3d523e3 | 2018-04-16 17:28:17 +0000 | [diff] [blame] | 693 | ByteString result; |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 694 | size_t len = m_pData->m_nDataLength; |
Tom Sepez | 1dbfe99 | 2018-04-17 17:19:30 +0000 | [diff] [blame] | 695 | { |
| 696 | // Span's lifetime must end before ReleaseBuffer() below. |
| 697 | pdfium::span<char> buffer = result.GetBuffer(len * 2 + 2); |
Tom Sepez | a5d8fa1 | 2021-11-05 19:29:08 +0000 | [diff] [blame] | 698 | for (size_t i = 0; i < len; i++) { |
Tom Sepez | 1dbfe99 | 2018-04-17 17:19:30 +0000 | [diff] [blame] | 699 | buffer[i * 2] = m_pData->m_String[i] & 0xff; |
| 700 | buffer[i * 2 + 1] = m_pData->m_String[i] >> 8; |
| 701 | } |
| 702 | buffer[len * 2] = 0; |
| 703 | buffer[len * 2 + 1] = 0; |
Tom Sepez | 3d523e3 | 2018-04-16 17:28:17 +0000 | [diff] [blame] | 704 | } |
Oliver Chang | 35e68a5 | 2015-12-09 12:44:33 -0800 | [diff] [blame] | 705 | result.ReleaseBuffer(len * 2 + 2); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 706 | return result; |
| 707 | } |
Lei Zhang | 31c7b73 | 2016-02-19 10:53:24 -0800 | [diff] [blame] | 708 | |
Tom Sepez | 3a9cc6d | 2020-07-20 23:50:36 +0000 | [diff] [blame] | 709 | WideString WideString::EncodeEntities() const { |
| 710 | WideString ret = *this; |
| 711 | ret.Replace(L"&", L"&"); |
| 712 | ret.Replace(L"<", L"<"); |
| 713 | ret.Replace(L">", L">"); |
| 714 | ret.Replace(L"\'", L"'"); |
| 715 | ret.Replace(L"\"", L"""); |
| 716 | return ret; |
| 717 | } |
| 718 | |
Tom Sepez | 3172257 | 2021-11-03 23:58:40 +0000 | [diff] [blame] | 719 | WideString WideString::Substr(size_t offset) const { |
Tom Sepez | d0b53bd | 2021-11-04 20:05:45 +0000 | [diff] [blame] | 720 | // Unsigned underflow is well-defined and out-of-range is handled by Substr(). |
Tom Sepez | 3172257 | 2021-11-03 23:58:40 +0000 | [diff] [blame] | 721 | return Substr(offset, GetLength() - offset); |
| 722 | } |
| 723 | |
Daniel Hosseinian | 39516a5 | 2020-01-27 22:10:50 +0000 | [diff] [blame] | 724 | WideString WideString::Substr(size_t first, size_t count) const { |
tsepez | de0d852 | 2016-03-31 14:40:29 -0700 | [diff] [blame] | 725 | if (!m_pData) |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 726 | return WideString(); |
tsepez | de0d852 | 2016-03-31 14:40:29 -0700 | [diff] [blame] | 727 | |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 728 | if (!IsValidIndex(first)) |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 729 | return WideString(); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 730 | |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 731 | if (count == 0 || !IsValidLength(count)) |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 732 | return WideString(); |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 733 | |
| 734 | if (!IsValidIndex(first + count - 1)) |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 735 | return WideString(); |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 736 | |
| 737 | if (first == 0 && count == GetLength()) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 738 | return *this; |
tsepez | de0d852 | 2016-03-31 14:40:29 -0700 | [diff] [blame] | 739 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 740 | WideString dest; |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 741 | AllocCopy(dest, count, first); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 742 | return dest; |
| 743 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 744 | |
Daniel Hosseinian | a9a704e | 2020-01-28 19:52:32 +0000 | [diff] [blame] | 745 | WideString WideString::First(size_t count) const { |
Daniel Hosseinian | 39516a5 | 2020-01-27 22:10:50 +0000 | [diff] [blame] | 746 | return Substr(0, count); |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 747 | } |
| 748 | |
Daniel Hosseinian | a9a704e | 2020-01-28 19:52:32 +0000 | [diff] [blame] | 749 | WideString WideString::Last(size_t count) const { |
Lei Zhang | 6df96bd | 2021-07-02 03:12:01 +0000 | [diff] [blame] | 750 | // Unsigned underflow is well-defined and out-of-range is handled by Substr(). |
Daniel Hosseinian | 39516a5 | 2020-01-27 22:10:50 +0000 | [diff] [blame] | 751 | return Substr(GetLength() - count, count); |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 752 | } |
| 753 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 754 | void WideString::AllocCopy(WideString& dest, |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 755 | size_t nCopyLen, |
| 756 | size_t nCopyIndex) const { |
Ryan Harrison | 81f9eee | 2017-09-05 15:33:18 -0400 | [diff] [blame] | 757 | if (nCopyLen == 0) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 758 | return; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 759 | |
Dan Sinclair | 0b95042 | 2017-09-21 15:49:49 -0400 | [diff] [blame] | 760 | RetainPtr<StringData> pNewData( |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 761 | StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); |
| 762 | dest.m_pData.Swap(pNewData); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 763 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 764 | |
Andrew Weintraub | 43d760a | 2019-06-24 17:45:20 +0000 | [diff] [blame] | 765 | size_t WideString::Insert(size_t index, wchar_t ch) { |
Lei Zhang | 10a8fea | 2018-12-05 23:15:53 +0000 | [diff] [blame] | 766 | const size_t cur_length = GetLength(); |
Andrew Weintraub | 43d760a | 2019-06-24 17:45:20 +0000 | [diff] [blame] | 767 | if (!IsValidLength(index)) |
Ryan Harrison | db14532 | 2017-08-02 14:44:17 -0400 | [diff] [blame] | 768 | return cur_length; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 769 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 770 | const size_t new_length = cur_length + 1; |
Ryan Harrison | db14532 | 2017-08-02 14:44:17 -0400 | [diff] [blame] | 771 | ReallocBeforeWrite(new_length); |
Andrew Weintraub | 43d760a | 2019-06-24 17:45:20 +0000 | [diff] [blame] | 772 | wmemmove(m_pData->m_String + index + 1, m_pData->m_String + index, |
| 773 | new_length - index); |
| 774 | m_pData->m_String[index] = ch; |
Ryan Harrison | db14532 | 2017-08-02 14:44:17 -0400 | [diff] [blame] | 775 | m_pData->m_nDataLength = new_length; |
| 776 | return new_length; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 777 | } |
| 778 | |
Lei Zhang | 2c49530 | 2021-10-07 23:13:30 +0000 | [diff] [blame] | 779 | absl::optional<size_t> WideString::Find(wchar_t ch, size_t start) const { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 780 | if (!m_pData) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 781 | return absl::nullopt; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 782 | |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 783 | if (!IsValidIndex(start)) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 784 | return absl::nullopt; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 785 | |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 786 | const wchar_t* pStr = |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 787 | wmemchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start); |
Lei Zhang | 2c49530 | 2021-10-07 23:13:30 +0000 | [diff] [blame] | 788 | return pStr ? absl::optional<size_t>( |
| 789 | static_cast<size_t>(pStr - m_pData->m_String)) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 790 | : absl::nullopt; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 791 | } |
| 792 | |
Lei Zhang | 2c49530 | 2021-10-07 23:13:30 +0000 | [diff] [blame] | 793 | absl::optional<size_t> WideString::Find(WideStringView subStr, |
| 794 | size_t start) const { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 795 | if (!m_pData) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 796 | return absl::nullopt; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 797 | |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 798 | if (!IsValidIndex(start)) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 799 | return absl::nullopt; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 800 | |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 801 | const wchar_t* pStr = |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 802 | FX_wcsstr(m_pData->m_String + start, m_pData->m_nDataLength - start, |
| 803 | subStr.unterminated_c_str(), subStr.GetLength()); |
Lei Zhang | 2c49530 | 2021-10-07 23:13:30 +0000 | [diff] [blame] | 804 | return pStr ? absl::optional<size_t>( |
| 805 | static_cast<size_t>(pStr - m_pData->m_String)) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 806 | : absl::nullopt; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 807 | } |
| 808 | |
Lei Zhang | 2c49530 | 2021-10-07 23:13:30 +0000 | [diff] [blame] | 809 | absl::optional<size_t> WideString::ReverseFind(wchar_t ch) const { |
Daniel Hosseinian | bf9cfd7 | 2019-10-19 00:34:35 +0000 | [diff] [blame] | 810 | if (!m_pData) |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 811 | return absl::nullopt; |
Daniel Hosseinian | bf9cfd7 | 2019-10-19 00:34:35 +0000 | [diff] [blame] | 812 | |
| 813 | size_t nLength = m_pData->m_nDataLength; |
| 814 | while (nLength--) { |
| 815 | if (m_pData->m_String[nLength] == ch) |
| 816 | return nLength; |
| 817 | } |
Lei Zhang | a3a739d | 2021-10-07 20:46:31 +0000 | [diff] [blame] | 818 | return absl::nullopt; |
Daniel Hosseinian | bf9cfd7 | 2019-10-19 00:34:35 +0000 | [diff] [blame] | 819 | } |
| 820 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 821 | void WideString::MakeLower() { |
Tom Sepez | bafc408 | 2021-12-15 21:33:15 +0000 | [diff] [blame] | 822 | if (IsEmpty()) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 823 | return; |
| 824 | |
| 825 | ReallocBeforeWrite(m_pData->m_nDataLength); |
| 826 | FXSYS_wcslwr(m_pData->m_String); |
| 827 | } |
| 828 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 829 | void WideString::MakeUpper() { |
Tom Sepez | bafc408 | 2021-12-15 21:33:15 +0000 | [diff] [blame] | 830 | if (IsEmpty()) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 831 | return; |
| 832 | |
| 833 | ReallocBeforeWrite(m_pData->m_nDataLength); |
| 834 | FXSYS_wcsupr(m_pData->m_String); |
| 835 | } |
| 836 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 837 | size_t WideString::Remove(wchar_t chRemove) { |
Tom Sepez | bafc408 | 2021-12-15 21:33:15 +0000 | [diff] [blame] | 838 | if (IsEmpty()) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 839 | return 0; |
| 840 | |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 841 | wchar_t* pstrSource = m_pData->m_String; |
| 842 | wchar_t* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 843 | while (pstrSource < pstrEnd) { |
tsepez | e09c1e4 | 2016-04-11 18:01:13 -0700 | [diff] [blame] | 844 | if (*pstrSource == chRemove) |
| 845 | break; |
| 846 | pstrSource++; |
| 847 | } |
| 848 | if (pstrSource == pstrEnd) |
| 849 | return 0; |
| 850 | |
| 851 | ptrdiff_t copied = pstrSource - m_pData->m_String; |
| 852 | ReallocBeforeWrite(m_pData->m_nDataLength); |
| 853 | pstrSource = m_pData->m_String + copied; |
| 854 | pstrEnd = m_pData->m_String + m_pData->m_nDataLength; |
| 855 | |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 856 | wchar_t* pstrDest = pstrSource; |
tsepez | e09c1e4 | 2016-04-11 18:01:13 -0700 | [diff] [blame] | 857 | while (pstrSource < pstrEnd) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 858 | if (*pstrSource != chRemove) { |
| 859 | *pstrDest = *pstrSource; |
| 860 | pstrDest++; |
| 861 | } |
| 862 | pstrSource++; |
| 863 | } |
tsepez | e09c1e4 | 2016-04-11 18:01:13 -0700 | [diff] [blame] | 864 | |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 865 | *pstrDest = 0; |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 866 | size_t count = static_cast<size_t>(pstrSource - pstrDest); |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 867 | m_pData->m_nDataLength -= count; |
| 868 | return count; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 869 | } |
| 870 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 871 | size_t WideString::Replace(WideStringView pOld, WideStringView pNew) { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 872 | if (!m_pData || pOld.IsEmpty()) |
| 873 | return 0; |
| 874 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 875 | size_t nSourceLen = pOld.GetLength(); |
| 876 | size_t nReplacementLen = pNew.GetLength(); |
| 877 | size_t count = 0; |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 878 | const wchar_t* pStart = m_pData->m_String; |
| 879 | wchar_t* pEnd = m_pData->m_String + m_pData->m_nDataLength; |
Anton Bikineev | 7ac1334 | 2022-01-24 21:25:15 +0000 | [diff] [blame] | 880 | while (true) { |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 881 | const wchar_t* pTarget = |
| 882 | FX_wcsstr(pStart, static_cast<size_t>(pEnd - pStart), |
| 883 | pOld.unterminated_c_str(), nSourceLen); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 884 | if (!pTarget) |
| 885 | break; |
| 886 | |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 887 | count++; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 888 | pStart = pTarget + nSourceLen; |
| 889 | } |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 890 | if (count == 0) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 891 | return 0; |
| 892 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 893 | size_t nNewLength = |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 894 | m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * count; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 895 | |
| 896 | if (nNewLength == 0) { |
| 897 | clear(); |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 898 | return count; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 899 | } |
| 900 | |
Dan Sinclair | 0b95042 | 2017-09-21 15:49:49 -0400 | [diff] [blame] | 901 | RetainPtr<StringData> pNewData(StringData::Create(nNewLength)); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 902 | pStart = m_pData->m_String; |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 903 | wchar_t* pDest = pNewData->m_String; |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 904 | for (size_t i = 0; i < count; i++) { |
| 905 | const wchar_t* pTarget = |
| 906 | FX_wcsstr(pStart, static_cast<size_t>(pEnd - pStart), |
| 907 | pOld.unterminated_c_str(), nSourceLen); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 908 | wmemcpy(pDest, pStart, pTarget - pStart); |
| 909 | pDest += pTarget - pStart; |
Tom Sepez | 33b42e4 | 2017-07-19 13:19:12 -0700 | [diff] [blame] | 910 | wmemcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength()); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 911 | pDest += pNew.GetLength(); |
| 912 | pStart = pTarget + nSourceLen; |
| 913 | } |
| 914 | wmemcpy(pDest, pStart, pEnd - pStart); |
| 915 | m_pData.Swap(pNewData); |
Ryan Harrison | ed48c1a | 2017-08-25 15:34:41 -0400 | [diff] [blame] | 916 | return count; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 917 | } |
| 918 | |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 919 | // static |
Tom Sepez | c839ac7 | 2018-12-14 20:34:11 +0000 | [diff] [blame] | 920 | WideString WideString::FromASCII(ByteStringView bstr) { |
Tom Sepez | adb9e70 | 2018-11-27 18:43:10 +0000 | [diff] [blame] | 921 | WideString result; |
| 922 | result.Reserve(bstr.GetLength()); |
| 923 | for (char c : bstr) |
| 924 | result.InsertAtBack(static_cast<wchar_t>(c & 0x7f)); |
| 925 | return result; |
| 926 | } |
| 927 | |
| 928 | // static |
Lei Zhang | ebac96b | 2019-01-14 20:20:28 +0000 | [diff] [blame] | 929 | WideString WideString::FromLatin1(ByteStringView bstr) { |
| 930 | WideString result; |
| 931 | result.Reserve(bstr.GetLength()); |
| 932 | for (char c : bstr) |
| 933 | result.InsertAtBack(static_cast<wchar_t>(c & 0xff)); |
| 934 | return result; |
| 935 | } |
| 936 | |
| 937 | // static |
Tom Sepez | c839ac7 | 2018-12-14 20:34:11 +0000 | [diff] [blame] | 938 | WideString WideString::FromDefANSI(ByteStringView bstr) { |
Tom Sepez | 662e7a8 | 2021-08-04 18:02:18 +0000 | [diff] [blame] | 939 | size_t dest_len = FX_MultiByteToWideChar(FX_CodePage::kDefANSI, bstr, {}); |
Tom Sepez | f765805 | 2018-08-08 22:20:29 +0000 | [diff] [blame] | 940 | if (!dest_len) |
| 941 | return WideString(); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 942 | |
Tom Sepez | f765805 | 2018-08-08 22:20:29 +0000 | [diff] [blame] | 943 | WideString wstr; |
| 944 | { |
| 945 | // Span's lifetime must end before ReleaseBuffer() below. |
| 946 | pdfium::span<wchar_t> dest_buf = wstr.GetBuffer(dest_len); |
Tom Sepez | 662e7a8 | 2021-08-04 18:02:18 +0000 | [diff] [blame] | 947 | FX_MultiByteToWideChar(FX_CodePage::kDefANSI, bstr, dest_buf); |
Tom Sepez | f765805 | 2018-08-08 22:20:29 +0000 | [diff] [blame] | 948 | } |
| 949 | wstr.ReleaseBuffer(dest_len); |
| 950 | return wstr; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 951 | } |
| 952 | |
| 953 | // static |
Tom Sepez | c839ac7 | 2018-12-14 20:34:11 +0000 | [diff] [blame] | 954 | WideString WideString::FromUTF8(ByteStringView str) { |
Tom Sepez | fd7cede | 2018-08-09 21:32:47 +0000 | [diff] [blame] | 955 | return FX_UTF8Decode(str); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 956 | } |
| 957 | |
| 958 | // static |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 959 | WideString WideString::FromUTF16LE(const unsigned short* wstr, size_t wlen) { |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 960 | if (!wstr || wlen == 0) |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 961 | return WideString(); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 962 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 963 | WideString result; |
Tom Sepez | b7973bb | 2018-04-17 16:41:28 +0000 | [diff] [blame] | 964 | { |
| 965 | // Span's lifetime must end before ReleaseBuffer() below. |
| 966 | pdfium::span<wchar_t> buf = result.GetBuffer(wlen); |
| 967 | for (size_t i = 0; i < wlen; i++) |
| 968 | buf[i] = wstr[i]; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 969 | } |
| 970 | result.ReleaseBuffer(wlen); |
| 971 | return result; |
| 972 | } |
| 973 | |
Patrik Weiskircher | 6b4a235 | 2019-12-06 20:05:35 +0000 | [diff] [blame] | 974 | WideString WideString::FromUTF16BE(const unsigned short* wstr, size_t wlen) { |
| 975 | if (!wstr || wlen == 0) |
| 976 | return WideString(); |
| 977 | |
| 978 | WideString result; |
| 979 | { |
| 980 | // Span's lifetime must end before ReleaseBuffer() below. |
| 981 | pdfium::span<wchar_t> buf = result.GetBuffer(wlen); |
| 982 | for (size_t i = 0; i < wlen; i++) { |
| 983 | auto wch = wstr[i]; |
| 984 | wch = (wch >> 8) | (wch << 8); |
| 985 | buf[i] = wch; |
| 986 | } |
| 987 | } |
| 988 | result.ReleaseBuffer(wlen); |
| 989 | return result; |
| 990 | } |
| 991 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 992 | void WideString::SetAt(size_t index, wchar_t c) { |
Tom Sepez | 49f0932 | 2021-01-26 22:13:55 +0000 | [diff] [blame] | 993 | DCHECK(IsValidIndex(index)); |
Ryan Harrison | 8a1758b | 2017-08-15 10:37:59 -0400 | [diff] [blame] | 994 | ReallocBeforeWrite(m_pData->m_nDataLength); |
| 995 | m_pData->m_String[index] = c; |
| 996 | } |
| 997 | |
Andrew Weintraub | 43d760a | 2019-06-24 17:45:20 +0000 | [diff] [blame] | 998 | int WideString::Compare(const wchar_t* str) const { |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 999 | if (m_pData) |
Andrew Weintraub | 43d760a | 2019-06-24 17:45:20 +0000 | [diff] [blame] | 1000 | return str ? wcscmp(m_pData->m_String, str) : 1; |
| 1001 | return (!str || str[0] == 0) ? 0 : -1; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1002 | } |
| 1003 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1004 | int WideString::Compare(const WideString& str) const { |
Lei Zhang | d7a3f98 | 2017-11-06 19:00:21 +0000 | [diff] [blame] | 1005 | if (!m_pData) |
| 1006 | return str.m_pData ? -1 : 0; |
| 1007 | if (!str.m_pData) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1008 | return 1; |
Lei Zhang | d7a3f98 | 2017-11-06 19:00:21 +0000 | [diff] [blame] | 1009 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 1010 | size_t this_len = m_pData->m_nDataLength; |
| 1011 | size_t that_len = str.m_pData->m_nDataLength; |
| 1012 | size_t min_len = std::min(this_len, that_len); |
Lei Zhang | f3a7edc | 2017-12-12 18:42:18 +0000 | [diff] [blame] | 1013 | int result = wmemcmp(m_pData->m_String, str.m_pData->m_String, min_len); |
| 1014 | if (result != 0) |
| 1015 | return result; |
| 1016 | if (this_len == that_len) |
| 1017 | return 0; |
Lei Zhang | 40c223e | 2018-03-14 18:08:36 +0000 | [diff] [blame] | 1018 | return this_len < that_len ? -1 : 1; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1019 | } |
| 1020 | |
Andrew Weintraub | 43d760a | 2019-06-24 17:45:20 +0000 | [diff] [blame] | 1021 | int WideString::CompareNoCase(const wchar_t* str) const { |
Lei Zhang | d7a3f98 | 2017-11-06 19:00:21 +0000 | [diff] [blame] | 1022 | if (m_pData) |
Andrew Weintraub | 43d760a | 2019-06-24 17:45:20 +0000 | [diff] [blame] | 1023 | return str ? FXSYS_wcsicmp(m_pData->m_String, str) : 1; |
| 1024 | return (!str || str[0] == 0) ? 0 : -1; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1025 | } |
| 1026 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 1027 | size_t WideString::WStringLength(const unsigned short* str) { |
| 1028 | size_t len = 0; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1029 | if (str) |
| 1030 | while (str[len]) |
| 1031 | len++; |
| 1032 | return len; |
| 1033 | } |
| 1034 | |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1035 | void WideString::Trim() { |
Lei Zhang | 7981d15 | 2018-01-11 14:26:01 +0000 | [diff] [blame] | 1036 | TrimRight(kWideTrimChars); |
| 1037 | TrimLeft(kWideTrimChars); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1038 | } |
| 1039 | |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1040 | void WideString::Trim(wchar_t target) { |
| 1041 | wchar_t str[2] = {target, 0}; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1042 | TrimRight(str); |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1043 | TrimLeft(str); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1044 | } |
| 1045 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 1046 | void WideString::Trim(WideStringView targets) { |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1047 | TrimRight(targets); |
| 1048 | TrimLeft(targets); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1049 | } |
| 1050 | |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1051 | void WideString::TrimLeft() { |
Lei Zhang | 7981d15 | 2018-01-11 14:26:01 +0000 | [diff] [blame] | 1052 | TrimLeft(kWideTrimChars); |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1053 | } |
| 1054 | |
| 1055 | void WideString::TrimLeft(wchar_t target) { |
| 1056 | wchar_t str[2] = {target, 0}; |
| 1057 | TrimLeft(str); |
| 1058 | } |
| 1059 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 1060 | void WideString::TrimLeft(WideStringView targets) { |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1061 | if (!m_pData || targets.IsEmpty()) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1062 | return; |
| 1063 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 1064 | size_t len = GetLength(); |
Ryan Harrison | 81f9eee | 2017-09-05 15:33:18 -0400 | [diff] [blame] | 1065 | if (len == 0) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1066 | return; |
| 1067 | |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 1068 | size_t pos = 0; |
tsepez | 184b825 | 2016-04-11 10:56:00 -0700 | [diff] [blame] | 1069 | while (pos < len) { |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 1070 | size_t i = 0; |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1071 | while (i < targets.GetLength() && |
| 1072 | targets.CharAt(i) != m_pData->m_String[pos]) { |
tsepez | 184b825 | 2016-04-11 10:56:00 -0700 | [diff] [blame] | 1073 | i++; |
| 1074 | } |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1075 | if (i == targets.GetLength()) |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1076 | break; |
tsepez | 184b825 | 2016-04-11 10:56:00 -0700 | [diff] [blame] | 1077 | pos++; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1078 | } |
Ryan Harrison | 81f9eee | 2017-09-05 15:33:18 -0400 | [diff] [blame] | 1079 | if (!pos) |
| 1080 | return; |
| 1081 | |
| 1082 | ReallocBeforeWrite(len); |
Ryan Harrison | 875e98c | 2017-09-27 10:53:11 -0400 | [diff] [blame] | 1083 | size_t nDataLength = len - pos; |
Ryan Harrison | 81f9eee | 2017-09-05 15:33:18 -0400 | [diff] [blame] | 1084 | memmove(m_pData->m_String, m_pData->m_String + pos, |
| 1085 | (nDataLength + 1) * sizeof(wchar_t)); |
| 1086 | m_pData->m_nDataLength = nDataLength; |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1087 | } |
| 1088 | |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1089 | void WideString::TrimRight() { |
Lei Zhang | 7981d15 | 2018-01-11 14:26:01 +0000 | [diff] [blame] | 1090 | TrimRight(kWideTrimChars); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1091 | } |
| 1092 | |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1093 | void WideString::TrimRight(wchar_t target) { |
| 1094 | wchar_t str[2] = {target, 0}; |
| 1095 | TrimRight(str); |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1096 | } |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1097 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 1098 | void WideString::TrimRight(WideStringView targets) { |
Lei Zhang | 135c660 | 2017-11-21 18:07:00 +0000 | [diff] [blame] | 1099 | if (IsEmpty() || targets.IsEmpty()) |
| 1100 | return; |
| 1101 | |
| 1102 | size_t pos = GetLength(); |
| 1103 | while (pos && targets.Contains(m_pData->m_String[pos - 1])) |
| 1104 | pos--; |
| 1105 | |
| 1106 | if (pos < m_pData->m_nDataLength) { |
| 1107 | ReallocBeforeWrite(m_pData->m_nDataLength); |
| 1108 | m_pData->m_String[pos] = 0; |
| 1109 | m_pData->m_nDataLength = pos; |
| 1110 | } |
| 1111 | } |
| 1112 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1113 | int WideString::GetInteger() const { |
Lei Zhang | 412e908 | 2015-12-14 18:34:00 -0800 | [diff] [blame] | 1114 | return m_pData ? FXSYS_wtoi(m_pData->m_String) : 0; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 1115 | } |
tsepez | 46bf033 | 2016-04-06 16:48:26 -0700 | [diff] [blame] | 1116 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1117 | std::wostream& operator<<(std::wostream& os, const WideString& str) { |
Ryan Harrison | 475f433 | 2017-06-28 11:25:37 -0400 | [diff] [blame] | 1118 | return os.write(str.c_str(), str.GetLength()); |
| 1119 | } |
| 1120 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1121 | std::ostream& operator<<(std::ostream& os, const WideString& str) { |
Tom Sepez | b4c95fe | 2018-11-27 01:09:44 +0000 | [diff] [blame] | 1122 | os << str.ToUTF8(); |
Ryan Harrison | 475f433 | 2017-06-28 11:25:37 -0400 | [diff] [blame] | 1123 | return os; |
| 1124 | } |
Ryan Harrison | 297f161 | 2017-06-28 15:57:51 -0400 | [diff] [blame] | 1125 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 1126 | std::wostream& operator<<(std::wostream& os, WideStringView str) { |
Tom Sepez | 33b42e4 | 2017-07-19 13:19:12 -0700 | [diff] [blame] | 1127 | return os.write(str.unterminated_c_str(), str.GetLength()); |
Ryan Harrison | 297f161 | 2017-06-28 15:57:51 -0400 | [diff] [blame] | 1128 | } |
| 1129 | |
Tom Sepez | 1ab2757 | 2018-12-14 20:31:31 +0000 | [diff] [blame] | 1130 | std::ostream& operator<<(std::ostream& os, WideStringView str) { |
Ryan Harrison | 297f161 | 2017-06-28 15:57:51 -0400 | [diff] [blame] | 1131 | os << FX_UTF8Encode(str); |
| 1132 | return os; |
| 1133 | } |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 1134 | |
| 1135 | } // namespace fxcrt |
Tom Sepez | a44f5aa | 2018-11-29 21:30:55 +0000 | [diff] [blame] | 1136 | |
Tom Sepez | 96e8a31 | 2021-05-27 16:42:47 +0000 | [diff] [blame] | 1137 | uint32_t FX_HashCode_GetW(WideStringView str) { |
Tom Sepez | a44f5aa | 2018-11-29 21:30:55 +0000 | [diff] [blame] | 1138 | uint32_t dwHashCode = 0; |
Tom Sepez | 96e8a31 | 2021-05-27 16:42:47 +0000 | [diff] [blame] | 1139 | for (WideStringView::UnsignedType c : str) |
| 1140 | dwHashCode = 1313 * dwHashCode + c; |
| 1141 | return dwHashCode; |
| 1142 | } |
| 1143 | |
| 1144 | uint32_t FX_HashCode_GetLoweredW(WideStringView str) { |
| 1145 | uint32_t dwHashCode = 0; |
| 1146 | for (wchar_t c : str) // match FXSYS_towlower() arg type. |
| 1147 | dwHashCode = 1313 * dwHashCode + FXSYS_towlower(c); |
Tom Sepez | a44f5aa | 2018-11-29 21:30:55 +0000 | [diff] [blame] | 1148 | return dwHashCode; |
| 1149 | } |