lsr.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // © 2019 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. // lsr.cpp
  4. // created: 2019may08 Markus W. Scherer
  5. #include "unicode/utypes.h"
  6. #include "charstr.h"
  7. #include "cmemory.h"
  8. #include "cstring.h"
  9. #include "lsr.h"
  10. #include "uinvchar.h"
  11. #include "ustr_imp.h"
  12. U_NAMESPACE_BEGIN
  13. LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t f,
  14. UErrorCode &errorCode) :
  15. language(nullptr), script(nullptr), region(r),
  16. regionIndex(indexForRegion(region)), flags(f) {
  17. if (U_SUCCESS(errorCode)) {
  18. CharString langScript;
  19. langScript.append(prefix, errorCode).append(lang, errorCode).append('\0', errorCode);
  20. int32_t scriptOffset = langScript.length();
  21. langScript.append(prefix, errorCode).append(scr, errorCode);
  22. owned = langScript.cloneData(errorCode);
  23. if (U_SUCCESS(errorCode)) {
  24. language = owned;
  25. script = owned + scriptOffset;
  26. }
  27. }
  28. }
  29. LSR::LSR(StringPiece lang, StringPiece scr, StringPiece r, int32_t f,
  30. UErrorCode &errorCode) :
  31. language(nullptr), script(nullptr), region(nullptr),
  32. regionIndex(indexForRegion(r.data())), flags(f) {
  33. if (U_SUCCESS(errorCode)) {
  34. CharString data;
  35. data.append(lang, errorCode).append('\0', errorCode);
  36. int32_t scriptOffset = data.length();
  37. data.append(scr, errorCode).append('\0', errorCode);
  38. int32_t regionOffset = data.length();
  39. data.append(r, errorCode);
  40. owned = data.cloneData(errorCode);
  41. if (U_SUCCESS(errorCode)) {
  42. language = owned;
  43. script = owned + scriptOffset;
  44. region = owned + regionOffset;
  45. }
  46. }
  47. }
  48. LSR::LSR(LSR &&other) noexcept :
  49. language(other.language), script(other.script), region(other.region), owned(other.owned),
  50. regionIndex(other.regionIndex), flags(other.flags),
  51. hashCode(other.hashCode) {
  52. if (owned != nullptr) {
  53. other.language = other.script = "";
  54. other.owned = nullptr;
  55. other.hashCode = 0;
  56. }
  57. }
  58. void LSR::deleteOwned() {
  59. uprv_free(owned);
  60. }
  61. LSR &LSR::operator=(LSR &&other) noexcept {
  62. this->~LSR();
  63. language = other.language;
  64. script = other.script;
  65. region = other.region;
  66. regionIndex = other.regionIndex;
  67. flags = other.flags;
  68. owned = other.owned;
  69. hashCode = other.hashCode;
  70. if (owned != nullptr) {
  71. other.language = other.script = "";
  72. other.owned = nullptr;
  73. other.hashCode = 0;
  74. }
  75. return *this;
  76. }
  77. UBool LSR::isEquivalentTo(const LSR &other) const {
  78. return
  79. uprv_strcmp(language, other.language) == 0 &&
  80. uprv_strcmp(script, other.script) == 0 &&
  81. regionIndex == other.regionIndex &&
  82. // Compare regions if both are ill-formed (and their indexes are 0).
  83. (regionIndex > 0 || uprv_strcmp(region, other.region) == 0);
  84. }
  85. bool LSR::operator==(const LSR &other) const {
  86. return
  87. uprv_strcmp(language, other.language) == 0 &&
  88. uprv_strcmp(script, other.script) == 0 &&
  89. regionIndex == other.regionIndex &&
  90. // Compare regions if both are ill-formed (and their indexes are 0).
  91. (regionIndex > 0 || uprv_strcmp(region, other.region) == 0) &&
  92. flags == other.flags;
  93. }
  94. int32_t LSR::indexForRegion(const char *region) {
  95. int32_t c = region[0];
  96. int32_t a = c - '0';
  97. if (0 <= a && a <= 9) { // digits: "419"
  98. int32_t b = region[1] - '0';
  99. if (b < 0 || 9 < b) { return 0; }
  100. c = region[2] - '0';
  101. if (c < 0 || 9 < c || region[3] != 0) { return 0; }
  102. return (10 * a + b) * 10 + c + 1;
  103. } else { // letters: "DE"
  104. a = uprv_upperOrdinal(c);
  105. if (a < 0 || 25 < a) { return 0; }
  106. int32_t b = uprv_upperOrdinal(region[1]);
  107. if (b < 0 || 25 < b || region[2] != 0) { return 0; }
  108. return 26 * a + b + 1001;
  109. }
  110. return 0;
  111. }
  112. LSR &LSR::setHashCode() {
  113. if (hashCode == 0) {
  114. uint32_t h = ustr_hashCharsN(language, static_cast<int32_t>(uprv_strlen(language)));
  115. h = h * 37 + ustr_hashCharsN(script, static_cast<int32_t>(uprv_strlen(script)));
  116. h = h * 37 + regionIndex;
  117. hashCode = h * 37 + flags;
  118. }
  119. return *this;
  120. }
  121. U_NAMESPACE_END