]>
Commit | Line | Data |
---|---|---|
46f4442e A |
1 | /* |
2 | ******************************************************************************* | |
3 | * Copyright (C) 2007-2008, International Business Machines Corporation and * | |
4 | * others. All Rights Reserved. * | |
5 | ******************************************************************************* | |
6 | */ | |
7 | #ifndef ZSTRFMT_H | |
8 | #define ZSTRFMT_H | |
9 | ||
10 | #include "unicode/utypes.h" | |
11 | ||
12 | #if !UCONFIG_NO_FORMATTING | |
13 | ||
14 | #include "unicode/unistr.h" | |
15 | #include "unicode/calendar.h" | |
16 | #include "hash.h" | |
17 | #include "uvector.h" | |
18 | ||
19 | U_NAMESPACE_BEGIN | |
20 | ||
21 | /* | |
22 | * Character node used by TextTrieMap | |
23 | */ | |
24 | struct CharacterNode { | |
25 | // No constructor or destructor. | |
26 | // We malloc and free an uninitalized array of CharacterNode objects | |
27 | // and clear and delete them ourselves. | |
28 | ||
29 | void clear(); | |
30 | void deleteValues(); | |
31 | ||
32 | void addValue(void *value, UErrorCode &status); | |
33 | inline UBool hasValues() const; | |
34 | inline int32_t countValues() const; | |
35 | inline const void *getValue(int32_t index) const; | |
36 | ||
37 | void *fValues; // Union of one single value vs. UVector of values. | |
38 | UChar fCharacter; // UTF-16 code unit. | |
39 | uint16_t fFirstChild; // 0 if no children. | |
40 | uint16_t fNextSibling; // 0 terminates the list. | |
41 | UBool fHasValuesVector; | |
42 | UBool fPadding; | |
43 | ||
44 | // No value: fValues == NULL and fHasValuesVector == FALSE | |
45 | // One value: fValues == value and fHasValuesVector == FALSE | |
46 | // >=2 values: fValues == UVector of values and fHasValuesVector == TRUE | |
47 | }; | |
48 | ||
49 | inline UBool CharacterNode::hasValues() const { | |
50 | return (UBool)(fValues != NULL); | |
51 | } | |
52 | ||
53 | inline int32_t CharacterNode::countValues() const { | |
54 | return | |
55 | fValues == NULL ? 0 : | |
56 | !fHasValuesVector ? 1 : | |
57 | ((const UVector *)fValues)->size(); | |
58 | } | |
59 | ||
60 | inline const void *CharacterNode::getValue(int32_t index) const { | |
61 | if (!fHasValuesVector) { | |
62 | return fValues; // Assume index == 0. | |
63 | } else { | |
64 | return ((const UVector *)fValues)->elementAt(index); | |
65 | } | |
66 | } | |
67 | ||
68 | /* | |
69 | * Search result handler callback interface used by TextTrieMap search. | |
70 | */ | |
71 | class TextTrieMapSearchResultHandler : public UMemory { | |
72 | public: | |
73 | virtual UBool handleMatch(int32_t matchLength, | |
74 | const CharacterNode *node, UErrorCode& status) = 0; | |
75 | virtual ~TextTrieMapSearchResultHandler(); //added to avoid warning | |
76 | }; | |
77 | ||
78 | /** | |
79 | * TextTrieMap is a trie implementation for supporting | |
80 | * fast prefix match for the string key. | |
81 | */ | |
82 | class TextTrieMap : public UMemory { | |
83 | public: | |
84 | TextTrieMap(UBool ignoreCase); | |
85 | virtual ~TextTrieMap(); | |
86 | ||
87 | void put(const UnicodeString &key, void *value, UErrorCode &status); | |
88 | void search(const UnicodeString &text, int32_t start, | |
89 | TextTrieMapSearchResultHandler *handler, UErrorCode& status) const; | |
90 | inline int32_t isEmpty() const; | |
91 | ||
92 | private: | |
93 | UBool fIgnoreCase; | |
94 | CharacterNode *fNodes; | |
95 | int32_t fNodesCapacity; | |
96 | int32_t fNodesCount; | |
97 | ||
98 | UBool growNodes(); | |
99 | CharacterNode* addChildNode(CharacterNode *parent, UChar c, UErrorCode &status); | |
100 | CharacterNode* getChildNode(CharacterNode *parent, UChar c) const; | |
101 | ||
102 | void search(CharacterNode *node, const UnicodeString &text, int32_t start, | |
103 | int32_t index, TextTrieMapSearchResultHandler *handler, UErrorCode &status) const; | |
104 | }; | |
105 | ||
106 | inline UChar32 TextTrieMap::isEmpty(void) const { | |
107 | return fNodes == NULL; | |
108 | } | |
109 | ||
110 | // Name types, these bit flag are used for zone string lookup | |
111 | enum TimeZoneTranslationType { | |
112 | LOCATION = 0x0001, | |
113 | GENERIC_LONG = 0x0002, | |
114 | GENERIC_SHORT = 0x0004, | |
115 | STANDARD_LONG = 0x0008, | |
116 | STANDARD_SHORT = 0x0010, | |
117 | DAYLIGHT_LONG = 0x0020, | |
118 | DAYLIGHT_SHORT = 0x0040 | |
119 | }; | |
120 | ||
121 | // Name type index, these constants are used for index in the zone strings array. | |
122 | enum TimeZoneTranslationTypeIndex { | |
123 | ZSIDX_LOCATION = 0, | |
124 | ZSIDX_LONG_STANDARD, | |
125 | ZSIDX_SHORT_STANDARD, | |
126 | ZSIDX_LONG_DAYLIGHT, | |
127 | ZSIDX_SHORT_DAYLIGHT, | |
128 | ZSIDX_LONG_GENERIC, | |
129 | ZSIDX_SHORT_GENERIC, | |
130 | ||
131 | ZSIDX_COUNT | |
132 | }; | |
133 | ||
134 | class MessageFormat; | |
135 | ||
136 | /* | |
137 | * ZoneStringInfo is a class holding a localized zone string | |
138 | * information. | |
139 | */ | |
140 | class ZoneStringInfo : public UMemory { | |
141 | public: | |
142 | virtual ~ZoneStringInfo(); | |
143 | ||
144 | inline UnicodeString& getID(UnicodeString &result) const; | |
145 | inline UnicodeString& getString(UnicodeString &result) const; | |
146 | inline UBool isStandard(void) const; | |
147 | inline UBool isDaylight(void) const; | |
148 | inline UBool isGeneric(void) const; | |
149 | ||
150 | private: | |
151 | friend class ZoneStringFormat; | |
152 | friend class ZoneStringSearchResultHandler; | |
153 | ||
154 | ZoneStringInfo(const UnicodeString &id, const UnicodeString &str, TimeZoneTranslationType type); | |
155 | ||
156 | UnicodeString fId; | |
157 | UnicodeString fStr; | |
158 | TimeZoneTranslationType fType; | |
159 | }; | |
160 | ||
161 | inline UnicodeString& ZoneStringInfo::getID(UnicodeString &result) const { | |
162 | return result.setTo(fId); | |
163 | } | |
164 | ||
165 | inline UnicodeString& ZoneStringInfo::getString(UnicodeString &result) const { | |
166 | return result.setTo(fStr); | |
167 | } | |
168 | ||
169 | inline UBool ZoneStringInfo::isStandard(void) const { | |
170 | return (fType == STANDARD_LONG || fType == STANDARD_SHORT); | |
171 | } | |
172 | ||
173 | inline UBool ZoneStringInfo::isDaylight(void) const { | |
174 | return (fType == DAYLIGHT_LONG || fType == DAYLIGHT_SHORT); | |
175 | } | |
176 | ||
177 | inline UBool ZoneStringInfo::isGeneric(void) const { | |
178 | return (fType == LOCATION || fType == GENERIC_LONG || fType == GENERIC_SHORT); | |
179 | } | |
180 | ||
181 | class SafeZoneStringFormatPtr; | |
182 | ||
183 | class ZoneStringFormat : public UMemory { | |
184 | public: | |
185 | ZoneStringFormat(const UnicodeString* const* strings, int32_t rowCount, int32_t columnCount, UErrorCode &status); | |
186 | ZoneStringFormat(const Locale& locale, UErrorCode &status); | |
187 | virtual ~ZoneStringFormat(); | |
188 | ||
189 | static SafeZoneStringFormatPtr* getZoneStringFormat(const Locale& locale, UErrorCode &status); | |
190 | ||
191 | /* | |
192 | * Create a snapshot of old zone strings array for the given date | |
193 | */ | |
194 | UnicodeString** createZoneStringsArray(UDate date, int32_t &rowCount, int32_t &colCount, UErrorCode &status) const; | |
195 | ||
196 | const UnicodeString** getZoneStrings(int32_t &rowCount, int32_t &columnCount) const; | |
197 | ||
198 | UnicodeString& getSpecificLongString(const Calendar &cal, | |
199 | UnicodeString &result, UErrorCode &status) const; | |
200 | ||
201 | UnicodeString& getSpecificShortString(const Calendar &cal, | |
202 | UBool commonlyUsedOnly, UnicodeString &result, UErrorCode &status) const; | |
203 | ||
204 | UnicodeString& getGenericLongString(const Calendar &cal, | |
205 | UnicodeString &result, UErrorCode &status) const; | |
206 | ||
207 | UnicodeString& getGenericShortString(const Calendar &cal, | |
208 | UBool commonlyUsedOnly, UnicodeString &result, UErrorCode &status) const; | |
209 | ||
210 | UnicodeString& getGenericLocationString(const Calendar &cal, | |
211 | UnicodeString &result, UErrorCode &status) const; | |
212 | ||
213 | const ZoneStringInfo* findSpecificLong(const UnicodeString &text, int32_t start, | |
214 | int32_t &matchLength, UErrorCode &status) const; | |
215 | const ZoneStringInfo* findSpecificShort(const UnicodeString &text, int32_t start, | |
216 | int32_t &matchLength, UErrorCode &status) const; | |
217 | const ZoneStringInfo* findGenericLong(const UnicodeString &text, int32_t start, | |
218 | int32_t &matchLength, UErrorCode &status) const; | |
219 | const ZoneStringInfo* findGenericShort(const UnicodeString &text, int32_t start, | |
220 | int32_t &matchLength, UErrorCode &status) const; | |
221 | const ZoneStringInfo* findGenericLocation(const UnicodeString &text, int32_t start, | |
222 | int32_t &matchLength, UErrorCode &status) const; | |
223 | ||
224 | // Following APIs are not used by SimpleDateFormat, but public for testing purpose | |
225 | inline UnicodeString& getLongStandard(const UnicodeString &tzid, UDate date, | |
226 | UnicodeString &result) const; | |
227 | inline UnicodeString& getLongDaylight(const UnicodeString &tzid, UDate date, | |
228 | UnicodeString &result) const; | |
229 | inline UnicodeString& getLongGenericNonLocation(const UnicodeString &tzid, UDate date, | |
230 | UnicodeString &result) const; | |
231 | inline UnicodeString& getLongGenericPartialLocation(const UnicodeString &tzid, UDate date, | |
232 | UnicodeString &result) const; | |
233 | inline UnicodeString& getShortStandard(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly, | |
234 | UnicodeString &result) const; | |
235 | inline UnicodeString& getShortDaylight(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly, | |
236 | UnicodeString &result) const; | |
237 | inline UnicodeString& getShortGenericNonLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly, | |
238 | UnicodeString &result) const; | |
239 | inline UnicodeString& getShortGenericPartialLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly, | |
240 | UnicodeString &result) const; | |
241 | inline UnicodeString& getGenericLocation(const UnicodeString &tzid, UnicodeString &result) const; | |
242 | ||
243 | private: | |
244 | Locale fLocale; | |
245 | Hashtable fTzidToStrings; | |
246 | Hashtable fMzidToStrings; | |
247 | TextTrieMap fZoneStringsTrie; | |
248 | ||
249 | /* | |
250 | * Private method to get a zone string except generic partial location types. | |
251 | */ | |
252 | UnicodeString& getString(const UnicodeString &tzid, TimeZoneTranslationTypeIndex typeIdx, UDate date, | |
253 | UBool commonlyUsedOnly, UnicodeString& result) const; | |
254 | ||
255 | /* | |
256 | * Private method to get a generic string, with fallback logic involved, | |
257 | * that is, | |
258 | * | |
259 | * 1. If a generic non-location string is avaiable for the zone, return it. | |
260 | * 2. If a generic non-location string is associated with a metazone and | |
261 | * the zone never use daylight time around the given date, use the standard | |
262 | * string (if available). | |
263 | * | |
264 | * Note: In CLDR1.5.1, the same localization is used for generic and standard. | |
265 | * In this case, we do not use the standard string and do the rest. | |
266 | * | |
267 | * 3. If a generic non-location string is associated with a metazone and | |
268 | * the offset at the given time is different from the preferred zone for the | |
269 | * current locale, then return the generic partial location string (if avaiable) | |
270 | * 4. If a generic non-location string is not available, use generic location | |
271 | * string. | |
272 | */ | |
273 | UnicodeString& getGenericString(const Calendar &cal, UBool isShort, UBool commonlyUsedOnly, | |
274 | UnicodeString &result, UErrorCode &status) const; | |
275 | ||
276 | /* | |
277 | * Private method to get a generic partial location string | |
278 | */ | |
279 | UnicodeString& getGenericPartialLocationString(const UnicodeString &tzid, UBool isShort, | |
280 | UDate date, UBool commonlyUsedOnly, UnicodeString &result) const; | |
281 | ||
282 | /* | |
283 | * Find a prefix matching time zone for the given zone string types. | |
284 | * @param text The text contains a time zone string | |
285 | * @param start The start index within the text | |
286 | * @param types The bit mask representing a set of requested types | |
287 | * @param matchLength Receives the match length | |
288 | * @param status | |
289 | * @return If any zone string matched for the requested types, returns a | |
290 | * ZoneStringInfo for the longest match. If no matches are found for | |
291 | * the requested types, returns a ZoneStringInfo for the longest match | |
292 | * for any other types. If nothing matches at all, returns null. | |
293 | */ | |
294 | const ZoneStringInfo* find(const UnicodeString &text, int32_t start, int32_t types, | |
295 | int32_t &matchLength, UErrorCode &status) const; | |
296 | ||
297 | UnicodeString& getRegion(UnicodeString ®ion) const; | |
298 | ||
299 | static MessageFormat* getFallbackFormat(const Locale &locale, UErrorCode &status); | |
300 | static MessageFormat* getRegionFormat(const Locale &locale, UErrorCode &status); | |
301 | static const UChar* getZoneStringFromBundle(const UResourceBundle *zoneitem, const char *key); | |
302 | static UBool isCommonlyUsed(const UResourceBundle *zoneitem); | |
303 | static UnicodeString& getLocalizedCountry(const UnicodeString &countryCode, const Locale &locale, | |
304 | UnicodeString &displayCountry); | |
305 | }; | |
306 | ||
307 | inline UnicodeString& | |
308 | ZoneStringFormat::getLongStandard(const UnicodeString &tzid, UDate date, | |
309 | UnicodeString &result) const { | |
310 | return getString(tzid, ZSIDX_LONG_STANDARD, date, FALSE /* not used */, result); | |
311 | } | |
312 | ||
313 | inline UnicodeString& | |
314 | ZoneStringFormat::getLongDaylight(const UnicodeString &tzid, UDate date, | |
315 | UnicodeString &result) const { | |
316 | return getString(tzid, ZSIDX_LONG_DAYLIGHT, date, FALSE /* not used */, result); | |
317 | } | |
318 | ||
319 | inline UnicodeString& | |
320 | ZoneStringFormat::getLongGenericNonLocation(const UnicodeString &tzid, UDate date, | |
321 | UnicodeString &result) const { | |
322 | return getString(tzid, ZSIDX_LONG_GENERIC, date, FALSE /* not used */, result); | |
323 | } | |
324 | ||
325 | inline UnicodeString& | |
326 | ZoneStringFormat::getLongGenericPartialLocation(const UnicodeString &tzid, UDate date, | |
327 | UnicodeString &result) const { | |
328 | return getGenericPartialLocationString(tzid, FALSE, date, FALSE /* not used */, result); | |
329 | } | |
330 | ||
331 | inline UnicodeString& | |
332 | ZoneStringFormat::getShortStandard(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly, | |
333 | UnicodeString &result) const { | |
334 | return getString(tzid, ZSIDX_SHORT_STANDARD, date, commonlyUsedOnly, result); | |
335 | } | |
336 | ||
337 | inline UnicodeString& | |
338 | ZoneStringFormat::getShortDaylight(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly, | |
339 | UnicodeString &result) const { | |
340 | return getString(tzid, ZSIDX_SHORT_DAYLIGHT, date, commonlyUsedOnly, result); | |
341 | } | |
342 | ||
343 | inline UnicodeString& | |
344 | ZoneStringFormat::getShortGenericNonLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly, | |
345 | UnicodeString &result) const { | |
346 | return getString(tzid, ZSIDX_SHORT_GENERIC, date, commonlyUsedOnly, result); | |
347 | } | |
348 | ||
349 | inline UnicodeString& | |
350 | ZoneStringFormat::getShortGenericPartialLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly, | |
351 | UnicodeString &result) const { | |
352 | return getGenericPartialLocationString(tzid, TRUE, date, commonlyUsedOnly, result); | |
353 | } | |
354 | ||
355 | inline UnicodeString& | |
356 | ZoneStringFormat::getGenericLocation(const UnicodeString &tzid, UnicodeString &result) const { | |
357 | return getString(tzid, ZSIDX_LOCATION, 0 /*not used*/, FALSE /*not used*/, result); | |
358 | } | |
359 | ||
360 | ||
361 | /* | |
362 | * ZooneStrings is a container of localized zone strings used by ZoneStringFormat | |
363 | */ | |
364 | class ZoneStrings : public UMemory { | |
365 | public: | |
366 | ZoneStrings(UnicodeString *strings, int32_t stringsCount, UBool commonlyUsed, | |
367 | UnicodeString **genericPartialLocationStrings, int32_t genericRowCount, int32_t genericColCount); | |
368 | virtual ~ZoneStrings(); | |
369 | ||
370 | UnicodeString& getString(int32_t typeIdx, UnicodeString &result) const; | |
371 | inline UBool isShortFormatCommonlyUsed(void) const; | |
372 | UnicodeString& getGenericPartialLocationString(const UnicodeString &mzid, UBool isShort, | |
373 | UBool commonlyUsedOnly, UnicodeString &result) const; | |
374 | ||
375 | private: | |
376 | UnicodeString *fStrings; | |
377 | int32_t fStringsCount; | |
378 | UBool fIsCommonlyUsed; | |
379 | UnicodeString **fGenericPartialLocationStrings; | |
380 | int32_t fGenericPartialLocationRowCount; | |
381 | int32_t fGenericPartialLocationColCount; | |
382 | }; | |
383 | ||
384 | inline UBool | |
385 | ZoneStrings::isShortFormatCommonlyUsed(void) const { | |
386 | return fIsCommonlyUsed; | |
387 | } | |
388 | ||
389 | /* | |
390 | * ZoneStringSearchResultHandler is an implementation of | |
391 | * TextTrieMapSearchHandler. This class is used by ZoneStringFormat | |
392 | * for collecting search results for localized zone strings. | |
393 | */ | |
394 | class ZoneStringSearchResultHandler : public TextTrieMapSearchResultHandler { | |
395 | public: | |
396 | ZoneStringSearchResultHandler(UErrorCode &status); | |
397 | virtual ~ZoneStringSearchResultHandler(); | |
398 | ||
399 | virtual UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status); | |
400 | int32_t countMatches(void); | |
401 | const ZoneStringInfo* getMatch(int32_t index, int32_t &matchLength); | |
402 | void clear(void); | |
403 | ||
404 | private: | |
405 | UVector fResults; | |
406 | int32_t fMatchLen[ZSIDX_COUNT]; | |
407 | }; | |
408 | ||
409 | ||
410 | /* | |
411 | * ZoneStringFormat cache implementation | |
412 | */ | |
413 | class ZSFCacheEntry : public UMemory { | |
414 | public: | |
415 | ~ZSFCacheEntry(); | |
416 | ||
417 | void delRef(void); | |
418 | const ZoneStringFormat* getZoneStringFormat(void); | |
419 | ||
420 | private: | |
421 | friend class ZSFCache; | |
422 | ||
423 | ZSFCacheEntry(const Locale &locale, ZoneStringFormat *zsf, ZSFCacheEntry *next); | |
424 | ||
425 | Locale fLocale; | |
426 | ZoneStringFormat *fZoneStringFormat; | |
427 | ZSFCacheEntry *fNext; | |
428 | int32_t fRefCount; | |
429 | }; | |
430 | ||
431 | class SafeZoneStringFormatPtr : public UMemory { | |
432 | public: | |
433 | ~SafeZoneStringFormatPtr(); | |
434 | const ZoneStringFormat* get() const; | |
435 | ||
436 | private: | |
437 | friend class ZSFCache; | |
438 | ||
439 | SafeZoneStringFormatPtr(ZSFCacheEntry *cacheEntry); | |
440 | ||
441 | ZSFCacheEntry *fCacheEntry; | |
442 | }; | |
443 | ||
444 | class ZSFCache : public UMemory { | |
445 | public: | |
446 | ZSFCache(int32_t capacity); | |
447 | ~ZSFCache(); | |
448 | ||
449 | SafeZoneStringFormatPtr* get(const Locale &locale, UErrorCode &status); | |
450 | ||
451 | private: | |
452 | int32_t fCapacity; | |
453 | ZSFCacheEntry *fFirst; | |
454 | }; | |
455 | ||
456 | U_NAMESPACE_END | |
457 | ||
458 | #endif /* #if !UCONFIG_NO_FORMATTING */ | |
459 | ||
460 | #endif // ZSTRFMT_H |