| OLD | NEW |
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include <limits> | 30 #include <limits> |
| 31 | 31 |
| 32 #include "base.h" | 32 #include "base.h" |
| 33 #include "debug.h" | 33 #include "debug.h" |
| 34 #include "library.h" | 34 #include "library.h" |
| 35 | 35 |
| 36 ABP_NS_BEGIN | 36 ABP_NS_BEGIN |
| 37 | 37 |
| 38 inline void String_assert_writable(bool isWritable); | 38 inline void String_assert_writable(bool isWritable); |
| 39 | 39 |
| 40 // hacky because without templates |
| 41 #ifdef ABP_UTF8_STRING |
| 42 #define ABP_TEXT(val) val |
| 43 struct StringTraits |
| 44 { |
| 45 typedef char char_type; |
| 46 }; |
| 47 #else |
| 48 #define ABP_TEXT(val) u##val |
| 49 struct StringTraits |
| 50 { |
| 51 typedef char16_t char_type; |
| 52 }; |
| 53 #endif |
| 54 |
| 40 class String | 55 class String |
| 41 { | 56 { |
| 42 friend class DependentString; | 57 friend class DependentString; |
| 43 friend class OwnedString; | 58 friend class OwnedString; |
| 44 | 59 |
| 45 public: | 60 public: |
| 46 typedef char16_t value_type; | 61 typedef StringTraits::char_type value_type; |
| 47 typedef size_t size_type; | 62 typedef size_t size_type; |
| 48 | 63 |
| 49 // Type flags, stored in the top 2 bits of the mLen member | 64 // Type flags, stored in the top 2 bits of the mLen member |
| 50 static constexpr size_type INVALID = 0xC0000000; | 65 static constexpr size_type INVALID = 0xC0000000; |
| 51 static constexpr size_type DELETED = 0x80000000; | 66 static constexpr size_type DELETED = 0x80000000; |
| 52 static constexpr size_type READ_ONLY = 0x40000000; | 67 static constexpr size_type READ_ONLY = 0x40000000; |
| 53 static constexpr size_type READ_WRITE = 0x00000000; | 68 static constexpr size_type READ_WRITE = 0x00000000; |
| 54 | 69 |
| 55 static constexpr size_type FLAGS_MASK = 0xC0000000; | 70 static constexpr size_type FLAGS_MASK = 0xC0000000; |
| 56 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF; | 71 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 | 206 |
| 192 void toLower() | 207 void toLower() |
| 193 { | 208 { |
| 194 size_type len = length(); | 209 size_type len = length(); |
| 195 for (size_type i = 0; i < len; ++i) | 210 for (size_type i = 0; i < len; ++i) |
| 196 { | 211 { |
| 197 value_type currChar = mBuf[i]; | 212 value_type currChar = mBuf[i]; |
| 198 | 213 |
| 199 // This should be more efficient with a lookup table but I couldn't measur
e | 214 // This should be more efficient with a lookup table but I couldn't measur
e |
| 200 // any performance difference. | 215 // any performance difference. |
| 201 if (currChar >= u'A' && currChar <= u'Z') | 216 if (currChar >= ABP_TEXT('A') && currChar <= ABP_TEXT('Z')) |
| 202 mBuf[i] = currChar + u'a' - u'A'; | 217 mBuf[i] = currChar + ABP_TEXT('a') - ABP_TEXT('A'); |
| 203 else if (currChar >= 128) | 218 else if (currChar >= 128) |
| 204 { | 219 { |
| 205 mBuf[i] = CharToLower(currChar); | 220 mBuf[i] = CharToLower(currChar); |
| 206 } | 221 } |
| 207 } | 222 } |
| 208 } | 223 } |
| 209 }; | 224 }; |
| 210 | 225 |
| 211 #ifdef INSIDE_TESTS | 226 #ifdef INSIDE_TESTS |
| 212 inline std::ostream& operator<<(std::ostream& os, const String& str) | 227 inline std::ostream& operator<<(std::ostream& os, const String& str) |
| 213 { | 228 { |
| 229 #ifdef ABP_UTF8_STRING |
| 230 os.write(str.data(), str.length()); |
| 231 #else |
| 214 #if _MSC_VER >= 1900 | 232 #if _MSC_VER >= 1900 |
| 215 std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> converter; | 233 std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> converter; |
| 216 auto p = reinterpret_cast<const int16_t *>(str.data()); | 234 auto p = reinterpret_cast<const int16_t *>(str.data()); |
| 217 os << converter.to_bytes(p, p + str.length()); | 235 os << converter.to_bytes(p, p + str.length()); |
| 218 #else | 236 #else |
| 219 std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter; | 237 std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter; |
| 220 os << converter.to_bytes(str.data(), str.data() + str.length()); | 238 os << converter.to_bytes(str.data(), str.data() + str.length()); |
| 221 #endif | 239 #endif // _MSC_VER >= 1900 |
| 240 #endif // ABP_UTF8_STRING |
| 222 return os; | 241 return os; |
| 223 } | 242 } |
| 224 #endif | 243 #endif // INSIDE_TESTS |
| 225 | 244 |
| 226 class DependentString : public String | 245 class DependentString : public String |
| 227 { | 246 { |
| 228 public: | 247 public: |
| 229 explicit DependentString() | 248 explicit DependentString() |
| 230 : String(nullptr, 0, INVALID) | 249 : String(nullptr, 0, INVALID) |
| 231 { | 250 { |
| 232 } | 251 } |
| 233 | 252 |
| 234 explicit DependentString(value_type* buf, size_type len) | 253 explicit DependentString(value_type* buf, size_type len) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 #endif | 314 #endif |
| 296 | 315 |
| 297 inline DependentString operator "" _str(const String::value_type* str, | 316 inline DependentString operator "" _str(const String::value_type* str, |
| 298 String::size_type len) | 317 String::size_type len) |
| 299 { | 318 { |
| 300 return DependentString(str, len); | 319 return DependentString(str, len); |
| 301 } | 320 } |
| 302 | 321 |
| 303 inline void String_assert_writable(bool isWritable) | 322 inline void String_assert_writable(bool isWritable) |
| 304 { | 323 { |
| 305 assert2(isWritable, u"Writing access to a read-only string"_str); | 324 assert2(isWritable, ABP_TEXT("Writing access to a read-only string"_str)); |
| 306 } | 325 } |
| 307 | 326 |
| 308 class OwnedString : public String | 327 class OwnedString : public String |
| 309 { | 328 { |
| 310 private: | 329 private: |
| 311 void grow(size_type additionalSize) | 330 void grow(size_type additionalSize) |
| 312 { | 331 { |
| 313 OwnedString newValue(length() + additionalSize); | 332 OwnedString newValue(length() + additionalSize); |
| 314 if (length() > 0) | 333 if (length() > 0) |
| 315 std::memcpy(newValue.mBuf, mBuf, sizeof(value_type) * length()); | 334 std::memcpy(newValue.mBuf, mBuf, sizeof(value_type) * length()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 std::swap(mBuf, str.mBuf); | 412 std::swap(mBuf, str.mBuf); |
| 394 std::swap(mLen, str.mLen); | 413 std::swap(mLen, str.mLen); |
| 395 return *this; | 414 return *this; |
| 396 } | 415 } |
| 397 | 416 |
| 398 void append(const value_type* source, size_type sourceLen) | 417 void append(const value_type* source, size_type sourceLen) |
| 399 { | 418 { |
| 400 if (!sourceLen) | 419 if (!sourceLen) |
| 401 return; | 420 return; |
| 402 | 421 |
| 403 assert2(source, u"Null buffer passed to OwnedString.append()"_str); | 422 assert2(source, ABP_TEXT("Null buffer passed to OwnedString.append()"_str)); |
| 404 size_t oldLength = length(); | 423 size_t oldLength = length(); |
| 405 grow(sourceLen); | 424 grow(sourceLen); |
| 406 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); | 425 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); |
| 407 } | 426 } |
| 408 | 427 |
| 428 #ifndef ABP_UTF8_STRING |
| 409 void append(const char* source, size_type sourceLen) | 429 void append(const char* source, size_type sourceLen) |
| 410 { | 430 { |
| 411 if (!sourceLen) | 431 if (!sourceLen) |
| 412 return; | 432 return; |
| 413 | 433 |
| 414 assert2(source, u"Null buffer passed to OwnedString.append()"_str); | 434 assert2(source, ABP_TEXT("Null buffer passed to OwnedString.append()"_str)); |
| 415 size_t oldLength = length(); | 435 size_t oldLength = length(); |
| 416 grow(sourceLen); | 436 grow(sourceLen); |
| 417 for (size_t i = 0; i < sourceLen; i++) | 437 for (size_t i = 0; i < sourceLen; i++) |
| 418 mBuf[oldLength + i] = source[i]; | 438 mBuf[oldLength + i] = source[i]; |
| 419 } | 439 } |
| 440 #endif // !ABP_UTF8_STRING |
| 420 | 441 |
| 421 void append(const String& str) | 442 void append(const String& str) |
| 422 { | 443 { |
| 423 append(str.mBuf, str.length()); | 444 append(str.mBuf, str.length()); |
| 424 } | 445 } |
| 425 | 446 |
| 426 void append(value_type c) | 447 void append(value_type c) |
| 427 { | 448 { |
| 428 append(&c, 1); | 449 append(&c, 1); |
| 429 } | 450 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 441 | 462 |
| 442 size_type size = 0; | 463 size_type size = 0; |
| 443 for (T i = num; i; i /= 10) | 464 for (T i = num; i; i /= 10) |
| 444 size++; | 465 size++; |
| 445 size = (size ? size : 1); | 466 size = (size ? size : 1); |
| 446 | 467 |
| 447 size_type pos = length(); | 468 size_type pos = length(); |
| 448 grow((negative ? 1 : 0) + size); | 469 grow((negative ? 1 : 0) + size); |
| 449 | 470 |
| 450 if (negative) | 471 if (negative) |
| 451 mBuf[pos++] = '-'; | 472 mBuf[pos++] = ABP_TEXT('-'); |
| 452 | 473 |
| 453 for (int i = size - 1; i >= 0; i--) | 474 for (int i = size - 1; i >= 0; i--) |
| 454 { | 475 { |
| 455 mBuf[pos + i] = '0' + (num % 10); | 476 mBuf[pos + i] = ABP_TEXT('0') + (num % 10); |
| 456 num /= 10; | 477 num /= 10; |
| 457 } | 478 } |
| 458 } | 479 } |
| 459 }; | 480 }; |
| 460 | 481 |
| 461 #ifdef INSIDE_TESTS | 482 #ifdef INSIDE_TESTS |
| 462 inline std::ostream& operator<<(std::ostream& os, const OwnedString& str) | 483 inline std::ostream& operator<<(std::ostream& os, const OwnedString& str) |
| 463 { | 484 { |
| 464 return os << static_cast<const String&>(str); | 485 return os << static_cast<const String&>(str); |
| 465 } | 486 } |
| 466 #endif | 487 #endif |
| 467 | 488 |
| 468 template<typename T> | 489 template<typename T> |
| 469 struct LexicalCastImpl; | 490 struct LexicalCastImpl; |
| 470 | 491 |
| 471 /// Performs common conversions of a text represented value. | 492 /// Performs common conversions of a text represented value. |
| 472 template<typename T> | 493 template<typename T> |
| 473 inline T lexical_cast(const String& value) | 494 inline T lexical_cast(const String& value) |
| 474 { | 495 { |
| 475 return LexicalCastImpl<T>::Convert(value); | 496 return LexicalCastImpl<T>::Convert(value); |
| 476 } | 497 } |
| 477 | 498 |
| 478 template<> | 499 template<> |
| 479 struct LexicalCastImpl<bool> | 500 struct LexicalCastImpl<bool> |
| 480 { | 501 { |
| 481 static bool Convert(const String& value) | 502 static bool Convert(const String& value) |
| 482 { | 503 { |
| 483 return value == u"true"_str; | 504 return value == ABP_TEXT("true"_str); |
| 484 } | 505 } |
| 485 }; | 506 }; |
| 486 | 507 |
| 487 template<typename T> | 508 template<typename T> |
| 488 struct LexicalCastImpl | 509 struct LexicalCastImpl |
| 489 { | 510 { |
| 490 static_assert(std::is_integral<T>::value, "T should be a number"); | 511 static_assert(std::is_integral<T>::value, "T should be a number"); |
| 491 static T Convert(const String& value) | 512 static T Convert(const String& value) |
| 492 { | 513 { |
| 493 String::size_type len = value.length(); | 514 String::size_type len = value.length(); |
| 494 if (len == 0) | 515 if (len == 0) |
| 495 return 0; | 516 return 0; |
| 496 String::size_type pos = 0; | 517 String::size_type pos = 0; |
| 497 bool negative = std::numeric_limits<T>::is_signed && value[0] == u'-'; | 518 bool negative = std::numeric_limits<T>::is_signed && value[0] == ABP_TEXT('-
'); |
| 498 if (negative) | 519 if (negative) |
| 499 { | 520 { |
| 500 ++pos; | 521 ++pos; |
| 501 } | 522 } |
| 502 T result = 0; | 523 T result = 0; |
| 503 for (; pos < len; ++pos) | 524 for (; pos < len; ++pos) |
| 504 { | 525 { |
| 505 auto c = value[pos]; | 526 auto c = value[pos]; |
| 506 if (c < u'0' || c > u'9') | 527 if (c < ABP_TEXT('0') || c > ABP_TEXT('9')) |
| 507 return 0; | 528 return 0; |
| 508 // isDangerous is the optimization because there is no need for some check
s | 529 // isDangerous is the optimization because there is no need for some check
s |
| 509 // when the values are far from edge cases. | 530 // when the values are far from edge cases. |
| 510 // It targets the normal values, when a value is prefixed with several | 531 // It targets the normal values, when a value is prefixed with several |
| 511 // zeros additional checks start to work earlier than the actual value of | 532 // zeros additional checks start to work earlier than the actual value of |
| 512 // result reaches an edge case, but it does not affect the result. | 533 // result reaches an edge case, but it does not affect the result. |
| 513 bool isDangerous = pos >= std::numeric_limits<T>::digits10; | 534 bool isDangerous = pos >= std::numeric_limits<T>::digits10; |
| 514 // It also invalidates the parsing of too big numbers in comparison with | 535 // It also invalidates the parsing of too big numbers in comparison with |
| 515 // stopping when it encounters a non numerical character. | 536 // stopping when it encounters a non numerical character. |
| 516 // cast<uint8_t>(u"1230"_str) -> 0 | 537 // cast<uint8_t>(u"1230"_str) -> 0 |
| 517 // cast<uint8_t>(u"123E"_str) -> 123 | 538 // cast<uint8_t>(u"123E"_str) -> 123 |
| 518 if (isDangerous && std::numeric_limits<T>::max() / 10 < result) | 539 if (isDangerous && std::numeric_limits<T>::max() / 10 < result) |
| 519 { | 540 { |
| 520 return 0; | 541 return 0; |
| 521 } | 542 } |
| 522 result *= 10; | 543 result *= 10; |
| 523 uint8_t digit = c - u'0'; | 544 uint8_t digit = c - ABP_TEXT('0'); |
| 524 if (isDangerous && (std::numeric_limits<T>::max() - digit < result - (nega
tive ? 1 : 0))) | 545 if (isDangerous && (std::numeric_limits<T>::max() - digit < result - (nega
tive ? 1 : 0))) |
| 525 { | 546 { |
| 526 return 0; | 547 return 0; |
| 527 } | 548 } |
| 528 result += digit; | 549 result += digit; |
| 529 } | 550 } |
| 530 return negative ? -result : result; | 551 return negative ? -result : result; |
| 531 } | 552 } |
| 532 }; | 553 }; |
| 533 | 554 |
| 534 template<> | 555 template<> |
| 535 inline OwnedString lexical_cast<OwnedString>(const String& value) | 556 inline OwnedString lexical_cast<OwnedString>(const String& value) |
| 536 { | 557 { |
| 537 return OwnedString{value}; | 558 return OwnedString{value}; |
| 538 } | 559 } |
| 539 | 560 |
| 540 DependentString TrimSpaces(const String& value); | 561 DependentString TrimSpaces(const String& value); |
| 541 | 562 |
| 542 // Splits the `value` string into two `DependentString`s excluding the character
staying at `separatorPos`. | 563 // Splits the `value` string into two `DependentString`s excluding the character
staying at `separatorPos`. |
| 543 // Useful for parsing. | 564 // Useful for parsing. |
| 544 std::pair<DependentString, DependentString> SplitString(const String& value, Str
ing::size_type separatorPos); | 565 std::pair<DependentString, DependentString> SplitString(const String& value, Str
ing::size_type separatorPos); |
| 545 | 566 |
| 546 ABP_NS_END | 567 ABP_NS_END |
| OLD | NEW |