| Left: | ||
| Right: |
| 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 | |
|
hub
2018/03/13 21:29:16
Can't we make this macro shorter? Things are getti
sergei
2018/03/14 10:17:10
I'm afraid it can clash with some another macro, s
| |
| 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 std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter; | 232 std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter; |
| 215 os << converter.to_bytes(str.data(), str.data() + str.length()); | 233 os << converter.to_bytes(str.data(), str.data() + str.length()); |
| 234 #endif | |
| 216 return os; | 235 return os; |
| 217 } | 236 } |
| 218 #endif | 237 #endif |
| 219 | 238 |
| 220 class DependentString : public String | 239 class DependentString : public String |
| 221 { | 240 { |
| 222 public: | 241 public: |
| 223 explicit DependentString() | 242 explicit DependentString() |
| 224 : String(nullptr, 0, INVALID) | 243 : String(nullptr, 0, INVALID) |
| 225 { | 244 { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 #endif | 308 #endif |
| 290 | 309 |
| 291 inline DependentString operator "" _str(const String::value_type* str, | 310 inline DependentString operator "" _str(const String::value_type* str, |
| 292 String::size_type len) | 311 String::size_type len) |
| 293 { | 312 { |
| 294 return DependentString(str, len); | 313 return DependentString(str, len); |
| 295 } | 314 } |
| 296 | 315 |
| 297 inline void String_assert_writable(bool isWritable) | 316 inline void String_assert_writable(bool isWritable) |
| 298 { | 317 { |
| 299 assert2(isWritable, u"Writing access to a read-only string"_str); | 318 assert2(isWritable, ABP_TEXT("Writing access to a read-only string"_str)); |
| 300 } | 319 } |
| 301 | 320 |
| 302 class OwnedString : public String | 321 class OwnedString : public String |
| 303 { | 322 { |
| 304 private: | 323 private: |
| 305 void grow(size_type additionalSize) | 324 void grow(size_type additionalSize) |
| 306 { | 325 { |
| 307 OwnedString newValue(length() + additionalSize); | 326 OwnedString newValue(length() + additionalSize); |
| 308 if (length() > 0) | 327 if (length() > 0) |
| 309 std::memcpy(newValue.mBuf, mBuf, sizeof(value_type) * length()); | 328 std::memcpy(newValue.mBuf, mBuf, sizeof(value_type) * length()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 std::swap(mBuf, str.mBuf); | 406 std::swap(mBuf, str.mBuf); |
| 388 std::swap(mLen, str.mLen); | 407 std::swap(mLen, str.mLen); |
| 389 return *this; | 408 return *this; |
| 390 } | 409 } |
| 391 | 410 |
| 392 void append(const value_type* source, size_type sourceLen) | 411 void append(const value_type* source, size_type sourceLen) |
| 393 { | 412 { |
| 394 if (!sourceLen) | 413 if (!sourceLen) |
| 395 return; | 414 return; |
| 396 | 415 |
| 397 assert2(source, u"Null buffer passed to OwnedString.append()"_str); | 416 assert2(source, ABP_TEXT("Null buffer passed to OwnedString.append()"_str)); |
| 398 size_t oldLength = length(); | 417 size_t oldLength = length(); |
| 399 grow(sourceLen); | 418 grow(sourceLen); |
| 400 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); | 419 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); |
| 401 } | 420 } |
| 402 | 421 |
| 422 #ifndef ABP_UTF8_STRING | |
| 403 void append(const char* source, size_type sourceLen) | 423 void append(const char* source, size_type sourceLen) |
| 404 { | 424 { |
| 405 if (!sourceLen) | 425 if (!sourceLen) |
| 406 return; | 426 return; |
| 407 | 427 |
| 408 assert2(source, u"Null buffer passed to OwnedString.append()"_str); | 428 assert2(source, ABP_TEXT("Null buffer passed to OwnedString.append()"_str)); |
| 409 size_t oldLength = length(); | 429 size_t oldLength = length(); |
| 410 grow(sourceLen); | 430 grow(sourceLen); |
| 411 for (size_t i = 0; i < sourceLen; i++) | 431 for (size_t i = 0; i < sourceLen; i++) |
| 412 mBuf[oldLength + i] = source[i]; | 432 mBuf[oldLength + i] = source[i]; |
| 413 } | 433 } |
| 434 #endif // !ABP_UTF8_STRING | |
| 414 | 435 |
| 415 void append(const String& str) | 436 void append(const String& str) |
| 416 { | 437 { |
| 417 append(str.mBuf, str.length()); | 438 append(str.mBuf, str.length()); |
| 418 } | 439 } |
| 419 | 440 |
| 420 void append(value_type c) | 441 void append(value_type c) |
| 421 { | 442 { |
| 422 append(&c, 1); | 443 append(&c, 1); |
| 423 } | 444 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 435 | 456 |
| 436 size_type size = 0; | 457 size_type size = 0; |
| 437 for (T i = num; i; i /= 10) | 458 for (T i = num; i; i /= 10) |
| 438 size++; | 459 size++; |
| 439 size = (size ? size : 1); | 460 size = (size ? size : 1); |
| 440 | 461 |
| 441 size_type pos = length(); | 462 size_type pos = length(); |
| 442 grow((negative ? 1 : 0) + size); | 463 grow((negative ? 1 : 0) + size); |
| 443 | 464 |
| 444 if (negative) | 465 if (negative) |
| 445 mBuf[pos++] = '-'; | 466 mBuf[pos++] = ABP_TEXT('-'); |
| 446 | 467 |
| 447 for (int i = size - 1; i >= 0; i--) | 468 for (int i = size - 1; i >= 0; i--) |
| 448 { | 469 { |
| 449 mBuf[pos + i] = '0' + (num % 10); | 470 mBuf[pos + i] = ABP_TEXT('0') + (num % 10); |
| 450 num /= 10; | 471 num /= 10; |
| 451 } | 472 } |
| 452 } | 473 } |
| 453 }; | 474 }; |
| 454 | 475 |
| 455 #ifdef INSIDE_TESTS | 476 #ifdef INSIDE_TESTS |
| 456 inline std::ostream& operator<<(std::ostream& os, const OwnedString& str) | 477 inline std::ostream& operator<<(std::ostream& os, const OwnedString& str) |
| 457 { | 478 { |
| 458 return os << static_cast<const String&>(str); | 479 return os << static_cast<const String&>(str); |
| 459 } | 480 } |
| 460 #endif | 481 #endif |
| 461 | 482 |
| 462 template<typename T> | 483 template<typename T> |
| 463 struct LexicalCastImpl; | 484 struct LexicalCastImpl; |
| 464 | 485 |
| 465 /// Performs common conversions of a text represented value. | 486 /// Performs common conversions of a text represented value. |
| 466 template<typename T> | 487 template<typename T> |
| 467 inline T lexical_cast(const String& value) | 488 inline T lexical_cast(const String& value) |
| 468 { | 489 { |
| 469 return LexicalCastImpl<T>::Convert(value); | 490 return LexicalCastImpl<T>::Convert(value); |
| 470 } | 491 } |
| 471 | 492 |
| 472 template<> | 493 template<> |
| 473 struct LexicalCastImpl<bool> | 494 struct LexicalCastImpl<bool> |
| 474 { | 495 { |
| 475 static bool Convert(const String& value) | 496 static bool Convert(const String& value) |
| 476 { | 497 { |
| 477 return value == u"true"_str; | 498 return value == ABP_TEXT("true"_str); |
| 478 } | 499 } |
| 479 }; | 500 }; |
| 480 | 501 |
| 481 template<typename T> | 502 template<typename T> |
| 482 struct LexicalCastImpl | 503 struct LexicalCastImpl |
| 483 { | 504 { |
| 484 static_assert(std::is_integral<T>::value, "T should be a number"); | 505 static_assert(std::is_integral<T>::value, "T should be a number"); |
| 485 static T Convert(const String& value) | 506 static T Convert(const String& value) |
| 486 { | 507 { |
| 487 String::size_type len = value.length(); | 508 String::size_type len = value.length(); |
| 488 if (len == 0) | 509 if (len == 0) |
| 489 return 0; | 510 return 0; |
| 490 String::size_type pos = 0; | 511 String::size_type pos = 0; |
| 491 bool negative = std::numeric_limits<T>::is_signed && value[0] == u'-'; | 512 bool negative = std::numeric_limits<T>::is_signed && value[0] == ABP_TEXT('- '); |
| 492 if (negative) | 513 if (negative) |
| 493 { | 514 { |
| 494 ++pos; | 515 ++pos; |
| 495 } | 516 } |
| 496 T result = 0; | 517 T result = 0; |
| 497 for (; pos < len; ++pos) | 518 for (; pos < len; ++pos) |
| 498 { | 519 { |
| 499 auto c = value[pos]; | 520 auto c = value[pos]; |
| 500 if (c < u'0' || c > u'9') | 521 if (c < ABP_TEXT('0') || c > ABP_TEXT('9')) |
| 501 return 0; | 522 return 0; |
| 502 // isDangerous is the optimization because there is no need for some check s | 523 // isDangerous is the optimization because there is no need for some check s |
| 503 // when the values are far from edge cases. | 524 // when the values are far from edge cases. |
| 504 // It targets the normal values, when a value is prefixed with several | 525 // It targets the normal values, when a value is prefixed with several |
| 505 // zeros additional checks start to work earlier than the actual value of | 526 // zeros additional checks start to work earlier than the actual value of |
| 506 // result reaches an edge case, but it does not affect the result. | 527 // result reaches an edge case, but it does not affect the result. |
| 507 bool isDangerous = pos >= std::numeric_limits<T>::digits10; | 528 bool isDangerous = pos >= std::numeric_limits<T>::digits10; |
| 508 // It also invalidates the parsing of too big numbers in comparison with | 529 // It also invalidates the parsing of too big numbers in comparison with |
| 509 // stopping when it encounters a non numerical character. | 530 // stopping when it encounters a non numerical character. |
| 510 // cast<uint8_t>(u"1230"_str) -> 0 | 531 // cast<uint8_t>(u"1230"_str) -> 0 |
| 511 // cast<uint8_t>(u"123E"_str) -> 123 | 532 // cast<uint8_t>(u"123E"_str) -> 123 |
| 512 if (isDangerous && std::numeric_limits<T>::max() / 10 < result) | 533 if (isDangerous && std::numeric_limits<T>::max() / 10 < result) |
| 513 { | 534 { |
| 514 return 0; | 535 return 0; |
| 515 } | 536 } |
| 516 result *= 10; | 537 result *= 10; |
| 517 uint8_t digit = c - u'0'; | 538 uint8_t digit = c - ABP_TEXT('0'); |
| 518 if (isDangerous && (std::numeric_limits<T>::max() - digit < result - (nega tive ? 1 : 0))) | 539 if (isDangerous && (std::numeric_limits<T>::max() - digit < result - (nega tive ? 1 : 0))) |
| 519 { | 540 { |
| 520 return 0; | 541 return 0; |
| 521 } | 542 } |
| 522 result += digit; | 543 result += digit; |
| 523 } | 544 } |
| 524 return negative ? -result : result; | 545 return negative ? -result : result; |
| 525 } | 546 } |
| 526 }; | 547 }; |
| 527 | 548 |
| 528 template<> | 549 template<> |
| 529 inline OwnedString lexical_cast<OwnedString>(const String& value) | 550 inline OwnedString lexical_cast<OwnedString>(const String& value) |
| 530 { | 551 { |
| 531 return OwnedString{value}; | 552 return OwnedString{value}; |
| 532 } | 553 } |
| 533 | 554 |
| 534 DependentString TrimSpaces(const String& value); | 555 DependentString TrimSpaces(const String& value); |
| 535 | 556 |
| 536 // Splits the `value` string into two `DependentString`s excluding the character staying at `separatorPos`. | 557 // Splits the `value` string into two `DependentString`s excluding the character staying at `separatorPos`. |
| 537 // Useful for parsing. | 558 // Useful for parsing. |
| 538 std::pair<DependentString, DependentString> SplitString(const String& value, Str ing::size_type separatorPos); | 559 std::pair<DependentString, DependentString> SplitString(const String& value, Str ing::size_type separatorPos); |
| 539 | 560 |
| 540 ABP_NS_END | 561 ABP_NS_END |
| OLD | NEW |