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
15U_NAMESPACE_BEGIN
16
17LSR::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
34LSR::LSR(LSR &&other) 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
45void LSR::deleteOwned() {
46 uprv_free(owned);
47}
48
49LSR &LSR::operator=(LSR &&other) 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
66UBool 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
75bool 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
85int32_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
104LSR &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
114U_NAMESPACE_END
115