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