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 (UChar *) 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 UChar *get(const UChar *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 UChar *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 UChar *adopt(const UChar *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 uninitalized 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     UChar    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 == NULL               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 != NULL);
102 }
103 
countValues()104 inline int32_t CharacterNode::countValues() const {
105     return
106         fValues == NULL ? 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 UChar*, 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, UChar c, UErrorCode &status);
156     CharacterNode* getChildNode(CharacterNode *parent, UChar 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 UBool operator==(const TimeZoneNames& other) const;
177     virtual TimeZoneNamesImpl* clone() const;
178 
179     StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const;
180     StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const;
181 
182     UnicodeString& getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const;
183     UnicodeString& getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const;
184 
185     UnicodeString& getMetaZoneDisplayName(const UnicodeString& mzID, UTimeZoneNameType type, UnicodeString& name) const;
186     UnicodeString& getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const;
187 
188     UnicodeString& getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const;
189 
190     TimeZoneNames::MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
191 
192     void loadAllDisplayNames(UErrorCode& status);
193     void getDisplayNames(const UnicodeString& tzID, const UTimeZoneNameType types[], int32_t numTypes, UDate date, UnicodeString dest[], UErrorCode& status) const;
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 UBool operator==(const TimeZoneNames& other) const;
239     virtual TZDBTimeZoneNames* clone() const;
240 
241     StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const;
242     StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const;
243 
244     UnicodeString& getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const;
245     UnicodeString& getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const;
246 
247     UnicodeString& getMetaZoneDisplayName(const UnicodeString& mzID, UTimeZoneNameType type, UnicodeString& name) const;
248     UnicodeString& getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const;
249 
250     TimeZoneNames::MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
251 
252     // When TZDBNames for the metazone is not available, this method returns NULL,
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