1// © 2019 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html#License
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, UErrorCode &errorCode) :
18 language(nullptr), script(nullptr), region(r),
19 regionIndex(indexForRegion(region)) {
20 if (U_SUCCESS(errorCode)) {
21 CharString langScript;
22 langScript.append(prefix, errorCode).append(lang, errorCode).append('\0', errorCode);
23 int32_t scriptOffset = langScript.length();
24 langScript.append(prefix, errorCode).append(scr, errorCode);
25 owned = langScript.cloneData(errorCode);
26 if (U_SUCCESS(errorCode)) {
27 language = owned;
28 script = owned + scriptOffset;
29 }
30 }
31}
32
33LSR::LSR(LSR &&other) U_NOEXCEPT :
34 language(other.language), script(other.script), region(other.region), owned(other.owned),
35 regionIndex(other.regionIndex), hashCode(other.hashCode) {
36 if (owned != nullptr) {
37 other.language = other.script = "";
38 other.owned = nullptr;
39 other.hashCode = 0;
40 }
41}
42
43void LSR::deleteOwned() {
44 uprv_free(owned);
45}
46
47LSR &LSR::operator=(LSR &&other) U_NOEXCEPT {
48 this->~LSR();
49 language = other.language;
50 script = other.script;
51 region = other.region;
52 regionIndex = other.regionIndex;
53 owned = other.owned;
54 hashCode = other.hashCode;
55 if (owned != nullptr) {
56 other.language = other.script = "";
57 other.owned = nullptr;
58 other.hashCode = 0;
59 }
60 return *this;
61}
62
63UBool LSR::operator==(const LSR &other) const {
64 return
65 uprv_strcmp(language, other.language) == 0 &&
66 uprv_strcmp(script, other.script) == 0 &&
67 regionIndex == other.regionIndex &&
68 // Compare regions if both are ill-formed (and their indexes are 0).
69 (regionIndex > 0 || uprv_strcmp(region, other.region) == 0);
70}
71
72int32_t LSR::indexForRegion(const char *region) {
73 int32_t c = region[0];
74 int32_t a = c - '0';
75 if (0 <= a && a <= 9) { // digits: "419"
76 int32_t b = region[1] - '0';
77 if (b < 0 || 9 < b) { return 0; }
78 c = region[2] - '0';
79 if (c < 0 || 9 < c || region[3] != 0) { return 0; }
80 return (10 * a + b) * 10 + c + 1;
81 } else { // letters: "DE"
82 a = uprv_upperOrdinal(c);
83 if (a < 0 || 25 < a) { return 0; }
84 int32_t b = uprv_upperOrdinal(region[1]);
85 if (b < 0 || 25 < b || region[2] != 0) { return 0; }
86 return 26 * a + b + 1001;
87 }
88 return 0;
89}
90
91LSR &LSR::setHashCode() {
92 if (hashCode == 0) {
93 hashCode =
94 (ustr_hashCharsN(language, static_cast<int32_t>(uprv_strlen(language))) * 37 +
95 ustr_hashCharsN(script, static_cast<int32_t>(uprv_strlen(script)))) * 37 +
96 regionIndex;
97 }
98 return *this;
99}
100
101U_NAMESPACE_END
102