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