1 /**
2  *******************************************************************************
3  * Copyright (C) 2001-2014, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  *
7  *******************************************************************************
8  */
9 #include "unicode/utypes.h"
10 
11 #if !UCONFIG_NO_SERVICE
12 
13 #include "unicode/resbund.h"
14 #include "uresimp.h"
15 #include "cmemory.h"
16 #include "servloc.h"
17 #include "ustrfmt.h"
18 #include "uhash.h"
19 #include "charstr.h"
20 #include "uassert.h"
21 
22 #define UNDERSCORE_CHAR ((UChar)0x005f)
23 #define AT_SIGN_CHAR    ((UChar)64)
24 #define PERIOD_CHAR     ((UChar)46)
25 
26 U_NAMESPACE_BEGIN
27 
28 LocaleKey*
createWithCanonicalFallback(const UnicodeString * primaryID,const UnicodeString * canonicalFallbackID,UErrorCode & status)29 LocaleKey::createWithCanonicalFallback(const UnicodeString* primaryID,
30                                        const UnicodeString* canonicalFallbackID,
31                                        UErrorCode& status)
32 {
33     return LocaleKey::createWithCanonicalFallback(primaryID, canonicalFallbackID, KIND_ANY, status);
34 }
35 
36 LocaleKey*
createWithCanonicalFallback(const UnicodeString * primaryID,const UnicodeString * canonicalFallbackID,int32_t kind,UErrorCode & status)37 LocaleKey::createWithCanonicalFallback(const UnicodeString* primaryID,
38                                        const UnicodeString* canonicalFallbackID,
39                                        int32_t kind,
40                                        UErrorCode& status)
41 {
42     if (primaryID == NULL || U_FAILURE(status)) {
43         return NULL;
44     }
45     UnicodeString canonicalPrimaryID;
46     LocaleUtility::canonicalLocaleString(primaryID, canonicalPrimaryID);
47     return new LocaleKey(*primaryID, canonicalPrimaryID, canonicalFallbackID, kind);
48 }
49 
LocaleKey(const UnicodeString & primaryID,const UnicodeString & canonicalPrimaryID,const UnicodeString * canonicalFallbackID,int32_t kind)50 LocaleKey::LocaleKey(const UnicodeString& primaryID,
51                      const UnicodeString& canonicalPrimaryID,
52                      const UnicodeString* canonicalFallbackID,
53                      int32_t kind)
54   : ICUServiceKey(primaryID)
55   , _kind(kind)
56   , _primaryID(canonicalPrimaryID)
57   , _fallbackID()
58   , _currentID()
59 {
60     _fallbackID.setToBogus();
61     if (_primaryID.length() != 0) {
62         if (canonicalFallbackID != NULL && _primaryID != *canonicalFallbackID) {
63             _fallbackID = *canonicalFallbackID;
64         }
65     }
66 
67     _currentID = _primaryID;
68 }
69 
~LocaleKey()70 LocaleKey::~LocaleKey() {}
71 
72 UnicodeString&
prefix(UnicodeString & result) const73 LocaleKey::prefix(UnicodeString& result) const {
74     if (_kind != KIND_ANY) {
75         UChar buffer[64];
76         uprv_itou(buffer, 64, _kind, 10, 0);
77         UnicodeString temp(buffer);
78         result.append(temp);
79     }
80     return result;
81 }
82 
83 int32_t
kind() const84 LocaleKey::kind() const {
85     return _kind;
86 }
87 
88 UnicodeString&
canonicalID(UnicodeString & result) const89 LocaleKey::canonicalID(UnicodeString& result) const {
90     return result.append(_primaryID);
91 }
92 
93 UnicodeString&
currentID(UnicodeString & result) const94 LocaleKey::currentID(UnicodeString& result) const {
95     if (!_currentID.isBogus()) {
96         result.append(_currentID);
97     }
98     return result;
99 }
100 
101 UnicodeString&
currentDescriptor(UnicodeString & result) const102 LocaleKey::currentDescriptor(UnicodeString& result) const {
103     if (!_currentID.isBogus()) {
104         prefix(result).append(PREFIX_DELIMITER).append(_currentID);
105     } else {
106         result.setToBogus();
107     }
108     return result;
109 }
110 
111 Locale&
canonicalLocale(Locale & result) const112 LocaleKey::canonicalLocale(Locale& result) const {
113     return LocaleUtility::initLocaleFromName(_primaryID, result);
114 }
115 
116 Locale&
currentLocale(Locale & result) const117 LocaleKey::currentLocale(Locale& result) const {
118     return LocaleUtility::initLocaleFromName(_currentID, result);
119 }
120 
121 UBool
fallback()122 LocaleKey::fallback() {
123     if (!_currentID.isBogus()) {
124         int x = _currentID.lastIndexOf(UNDERSCORE_CHAR);
125         if (x != -1) {
126             _currentID.remove(x); // truncate current or fallback, whichever we're pointing to
127             return TRUE;
128         }
129 
130         if (!_fallbackID.isBogus()) {
131             _currentID = _fallbackID;
132             _fallbackID.setToBogus();
133             return TRUE;
134         }
135 
136         if (_currentID.length() > 0) {
137             _currentID.remove(0); // completely truncate
138             return TRUE;
139         }
140 
141         _currentID.setToBogus();
142     }
143 
144     return FALSE;
145 }
146 
147 UBool
isFallbackOf(const UnicodeString & id) const148 LocaleKey::isFallbackOf(const UnicodeString& id) const {
149     UnicodeString temp(id);
150     parseSuffix(temp);
151     return temp.indexOf(_primaryID) == 0 &&
152         (temp.length() == _primaryID.length() ||
153         temp.charAt(_primaryID.length()) == UNDERSCORE_CHAR);
154 }
155 
156 #ifdef SERVICE_DEBUG
157 UnicodeString&
debug(UnicodeString & result) const158 LocaleKey::debug(UnicodeString& result) const
159 {
160     ICUServiceKey::debug(result);
161     result.append((UnicodeString)" kind: ");
162     result.append(_kind);
163     result.append((UnicodeString)" primaryID: ");
164     result.append(_primaryID);
165     result.append((UnicodeString)" fallbackID: ");
166     result.append(_fallbackID);
167     result.append((UnicodeString)" currentID: ");
168     result.append(_currentID);
169     return result;
170 }
171 
172 UnicodeString&
debugClass(UnicodeString & result) const173 LocaleKey::debugClass(UnicodeString& result) const
174 {
175     return result.append((UnicodeString)"LocaleKey ");
176 }
177 #endif
178 
179 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocaleKey)
180 
181 U_NAMESPACE_END
182 
183 /* !UCONFIG_NO_SERVICE */
184 #endif
185 
186 
187