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
LSR(char prefix,const char * lang,const char * scr,const char * r,int32_t f,UErrorCode & errorCode)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
LSR(StringPiece lang,StringPiece scr,StringPiece r,int32_t f,UErrorCode & errorCode)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
LSR(LSR && other)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
deleteOwned()65 void LSR::deleteOwned() {
66 uprv_free(owned);
67 }
68
operator =(LSR && other)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
isEquivalentTo(const LSR & other) const86 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
operator ==(const LSR & other) const95 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
indexForRegion(const char * region)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
setHashCode()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
135