1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 * Copyright (C) 2011-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
8 */
9
10 #ifndef __TZNAMES_IMPL_H__
11 #define __TZNAMES_IMPL_H__
12
13
14 /**
15 * \file
16 * \brief C++ API: TimeZoneNames object
17 */
18
19 #include "unicode/utypes.h"
20
21 #if !UCONFIG_NO_FORMATTING
22
23 #include "unicode/tznames.h"
24 #include "unicode/ures.h"
25 #include "unicode/locid.h"
26 #include "uhash.h"
27 #include "uvector.h"
28 #include "umutex.h"
29
30 // Some zone display names involving supplementary characters can be over 50 chars, 100 UTF-16 code units, 200 UTF-8 bytes
31 #define ZONE_NAME_U16_MAX 128
32
33 U_NAMESPACE_BEGIN
34
35 /*
36 * ZNStringPool Pool of (char16_t *) strings. Provides for sharing of repeated
37 * zone strings.
38 */
39 struct ZNStringPoolChunk;
40 class U_I18N_API ZNStringPool: public UMemory {
41 public:
42 ZNStringPool(UErrorCode &status);
43 ~ZNStringPool();
44
45 /* Get the pooled string that is equal to the supplied string s.
46 * Copy the string into the pool if it is not already present.
47 *
48 * Life time of the returned string is that of the pool.
49 */
50 const char16_t *get(const char16_t *s, UErrorCode &status);
51
52 /* Get the pooled string that is equal to the supplied string s.
53 * Copy the string into the pool if it is not already present.
54 */
55 const char16_t *get(const UnicodeString &s, UErrorCode &status);
56
57 /* Adopt a string into the pool, without copying it.
58 * Used for strings from resource bundles, which will persist without copying.
59 */
60 const char16_t *adopt(const char16_t *s, UErrorCode &status);
61
62 /* Freeze the string pool. Discards the hash table that is used
63 * for looking up a string. All pointers to pooled strings remain valid.
64 */
65 void freeze();
66
67 private:
68 ZNStringPoolChunk *fChunks;
69 UHashtable *fHash;
70 };
71
72 /*
73 * Character node used by TextTrieMap
74 */
75 struct CharacterNode {
76 // No constructor or destructor.
77 // We malloc and free an uninitialized array of CharacterNode objects
78 // and clear and delete them ourselves.
79
80 void clear();
81 void deleteValues(UObjectDeleter *valueDeleter);
82
83 void addValue(void *value, UObjectDeleter *valueDeleter, UErrorCode &status);
84 inline UBool hasValues() const;
85 inline int32_t countValues() const;
86 inline const void *getValue(int32_t index) const;
87
88 void *fValues; // Union of one single value vs. UVector of values.
89 char16_t fCharacter; // UTF-16 code unit.
90 uint16_t fFirstChild; // 0 if no children.
91 uint16_t fNextSibling; // 0 terminates the list.
92 UBool fHasValuesVector;
93 UBool fPadding;
94
95 // No value: fValues == nullptr and fHasValuesVector == false
96 // One value: fValues == value and fHasValuesVector == false
97 // >=2 values: fValues == UVector of values and fHasValuesVector == true
98 };
99
hasValues()100 inline UBool CharacterNode::hasValues() const {
101 return (UBool)(fValues != nullptr);
102 }
103
countValues()104 inline int32_t CharacterNode::countValues() const {
105 return
106 fValues == nullptr ? 0 :
107 !fHasValuesVector ? 1 :
108 ((const UVector *)fValues)->size();
109 }
110
getValue(int32_t index)111 inline const void *CharacterNode::getValue(int32_t index) const {
112 if (!fHasValuesVector) {
113 return fValues; // Assume index == 0.
114 } else {
115 return ((const UVector *)fValues)->elementAt(index);
116 }
117 }
118
119 /*
120 * Search result handler callback interface used by TextTrieMap search.
121 */
122 class TextTrieMapSearchResultHandler : public UMemory {
123 public:
124 virtual UBool handleMatch(int32_t matchLength,
125 const CharacterNode *node, UErrorCode& status) = 0;
126 virtual ~TextTrieMapSearchResultHandler(); //added to avoid warning
127 };
128
129 /**
130 * TextTrieMap is a trie implementation for supporting
131 * fast prefix match for the string key.
132 */
133 class U_I18N_API TextTrieMap : public UMemory {
134 public:
135 TextTrieMap(UBool ignoreCase, UObjectDeleter *valeDeleter);
136 virtual ~TextTrieMap();
137
138 void put(const UnicodeString &key, void *value, ZNStringPool &sp, UErrorCode &status);
139 void put(const char16_t*, void *value, UErrorCode &status);
140 void search(const UnicodeString &text, int32_t start,
141 TextTrieMapSearchResultHandler *handler, UErrorCode& status) const;
142 int32_t isEmpty() const;
143
144 private:
145 UBool fIgnoreCase;
146 CharacterNode *fNodes;
147 int32_t fNodesCapacity;
148 int32_t fNodesCount;
149
150 UVector *fLazyContents;
151 UBool fIsEmpty;
152 UObjectDeleter *fValueDeleter;
153
154 UBool growNodes();
155 CharacterNode* addChildNode(CharacterNode *parent, char16_t c, UErrorCode &status);
156 CharacterNode* getChildNode(CharacterNode *parent, char16_t c) const;
157
158 void putImpl(const UnicodeString &key, void *value, UErrorCode &status);
159 void buildTrie(UErrorCode &status);
160 void search(CharacterNode *node, const UnicodeString &text, int32_t start,
161 int32_t index, TextTrieMapSearchResultHandler *handler, UErrorCode &status) const;
162 };
163
164
165
166 class ZNames;
167 class TextTrieMap;
168 class ZNameSearchHandler;
169
170 class TimeZoneNamesImpl : public TimeZoneNames {
171 public:
172 TimeZoneNamesImpl(const Locale& locale, UErrorCode& status);
173
174 virtual ~TimeZoneNamesImpl();
175
176 virtual bool operator==(const TimeZoneNames& other) const override;
177 virtual TimeZoneNamesImpl* clone() const override;
178
179 StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const override;
180 StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const override;
181
182 UnicodeString& getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const override;
183 UnicodeString& getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const override;
184
185 UnicodeString& getMetaZoneDisplayName(const UnicodeString& mzID, UTimeZoneNameType type, UnicodeString& name) const override;
186 UnicodeString& getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const override;
187
188 UnicodeString& getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const override;
189
190 TimeZoneNames::MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const override;
191
192 void loadAllDisplayNames(UErrorCode& status) override;
193 void getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[], UErrorCode& status) const override;
194
195 static UnicodeString& getDefaultExemplarLocationName(const UnicodeString& tzID, UnicodeString& name);
196
197 static StringEnumeration* _getAvailableMetaZoneIDs(UErrorCode& status);
198 static StringEnumeration* _getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status);
199 static UnicodeString& _getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID);
200 static UnicodeString& _getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID);
201
202 private:
203
204 Locale fLocale;
205
206 UResourceBundle* fZoneStrings;
207
208 UHashtable* fTZNamesMap;
209 UHashtable* fMZNamesMap;
210
211 UBool fNamesTrieFullyLoaded;
212 UBool fNamesFullyLoaded;
213 TextTrieMap fNamesTrie;
214
215 void initialize(const Locale& locale, UErrorCode& status);
216 void cleanup();
217
218 void loadStrings(const UnicodeString& tzCanonicalID, UErrorCode& status);
219
220 ZNames* loadMetaZoneNames(const UnicodeString& mzId, UErrorCode& status);
221 ZNames* loadTimeZoneNames(const UnicodeString& mzId, UErrorCode& status);
222 TimeZoneNames::MatchInfoCollection* doFind(ZNameSearchHandler& handler,
223 const UnicodeString& text, int32_t start, UErrorCode& status) const;
224 void addAllNamesIntoTrie(UErrorCode& errorCode);
225
226 void internalLoadAllDisplayNames(UErrorCode& status);
227
228 struct ZoneStringsLoader;
229 };
230
231 class TZDBNames;
232
233 class TZDBTimeZoneNames : public TimeZoneNames {
234 public:
235 TZDBTimeZoneNames(const Locale& locale);
236 virtual ~TZDBTimeZoneNames();
237
238 virtual bool operator==(const TimeZoneNames& other) const override;
239 virtual TZDBTimeZoneNames* clone() const override;
240
241 StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const override;
242 StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const override;
243
244 UnicodeString& getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const override;
245 UnicodeString& getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const override;
246
247 UnicodeString& getMetaZoneDisplayName(const UnicodeString& mzID, UTimeZoneNameType type, UnicodeString& name) const override;
248 UnicodeString& getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const override;
249
250 TimeZoneNames::MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const override;
251
252 // When TZDBNames for the metazone is not available, this method returns nullptr,
253 // but does NOT set U_MISSING_RESOURCE_ERROR to status.
254 static const TZDBNames* getMetaZoneNames(const UnicodeString& mzId, UErrorCode& status);
255
256 private:
257 Locale fLocale;
258 char fRegion[ULOC_COUNTRY_CAPACITY];
259 };
260
261 U_NAMESPACE_END
262
263 #endif /* #if !UCONFIG_NO_FORMATTING */
264
265 #endif // __TZNAMES_IMPL_H__
266 //eof
267 //
268