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