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(LSR && other)34 LSR::LSR(LSR &&other) U_NOEXCEPT :
35         language(other.language), script(other.script), region(other.region), owned(other.owned),
36         regionIndex(other.regionIndex), flags(other.flags),
37         hashCode(other.hashCode) {
38     if (owned != nullptr) {
39         other.language = other.script = "";
40         other.owned = nullptr;
41         other.hashCode = 0;
42     }
43 }
44 
deleteOwned()45 void LSR::deleteOwned() {
46     uprv_free(owned);
47 }
48 
operator =(LSR && other)49 LSR &LSR::operator=(LSR &&other) U_NOEXCEPT {
50     this->~LSR();
51     language = other.language;
52     script = other.script;
53     region = other.region;
54     regionIndex = other.regionIndex;
55     flags = other.flags;
56     owned = other.owned;
57     hashCode = other.hashCode;
58     if (owned != nullptr) {
59         other.language = other.script = "";
60         other.owned = nullptr;
61         other.hashCode = 0;
62     }
63     return *this;
64 }
65 
isEquivalentTo(const LSR & other) const66 UBool LSR::isEquivalentTo(const LSR &other) const {
67     return
68         uprv_strcmp(language, other.language) == 0 &&
69         uprv_strcmp(script, other.script) == 0 &&
70         regionIndex == other.regionIndex &&
71         // Compare regions if both are ill-formed (and their indexes are 0).
72         (regionIndex > 0 || uprv_strcmp(region, other.region) == 0);
73 }
74 
operator ==(const LSR & other) const75 UBool LSR::operator==(const LSR &other) const {
76     return
77         uprv_strcmp(language, other.language) == 0 &&
78         uprv_strcmp(script, other.script) == 0 &&
79         regionIndex == other.regionIndex &&
80         // Compare regions if both are ill-formed (and their indexes are 0).
81         (regionIndex > 0 || uprv_strcmp(region, other.region) == 0) &&
82         flags == other.flags;
83 }
84 
indexForRegion(const char * region)85 int32_t LSR::indexForRegion(const char *region) {
86     int32_t c = region[0];
87     int32_t a = c - '0';
88     if (0 <= a && a <= 9) {  // digits: "419"
89         int32_t b = region[1] - '0';
90         if (b < 0 || 9 < b) { return 0; }
91         c = region[2] - '0';
92         if (c < 0 || 9 < c || region[3] != 0) { return 0; }
93         return (10 * a + b) * 10 + c + 1;
94     } else {  // letters: "DE"
95         a = uprv_upperOrdinal(c);
96         if (a < 0 || 25 < a) { return 0; }
97         int32_t b = uprv_upperOrdinal(region[1]);
98         if (b < 0 || 25 < b || region[2] != 0) { return 0; }
99         return 26 * a + b + 1001;
100     }
101     return 0;
102 }
103 
setHashCode()104 LSR &LSR::setHashCode() {
105     if (hashCode == 0) {
106         uint32_t h = ustr_hashCharsN(language, static_cast<int32_t>(uprv_strlen(language)));
107         h = h * 37 + ustr_hashCharsN(script, static_cast<int32_t>(uprv_strlen(script)));
108         h = h * 37 + regionIndex;
109         hashCode = h * 37 + flags;
110     }
111     return *this;
112 }
113 
114 U_NAMESPACE_END
115