• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 * Copyright (C) 2007-2010, 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 "uhash.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 
hasValues()49 inline UBool CharacterNode::hasValues() const {
50     return (UBool)(fValues != NULL);
51 }
52 
countValues()53 inline int32_t CharacterNode::countValues() const {
54     return
55         fValues == NULL ? 0 :
56         !fHasValuesVector ? 1 :
57         ((const UVector *)fValues)->size();
58 }
59 
getValue(int32_t index)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 /*
80  * ZSFStringPool   Pool of (UChar *) strings.  Provides for sharing of repeated
81  *                 strings within ZoneStringFormats.
82  */
83 struct ZSFStringPoolChunk;
84 class ZSFStringPool: public UMemory {
85   public:
86     ZSFStringPool(UErrorCode &status);
87     ~ZSFStringPool();
88 
89     /* Get the pooled string that is equal to the supplied string s.
90      * Copy the string into the pool if it is not already present.
91      *
92      * Life time of the returned string is that of the pool.
93      */
94     const UChar *get(const UChar *s, UErrorCode &status);
95 
96     /* Get the pooled string that is equal to the supplied string s.
97      * Copy the string into the pool if it is not already present.
98      */
99     const UChar *get(const UnicodeString &s, UErrorCode &status);
100 
101     /* Adopt a string into the pool, without copying it.
102      * Used for strings from resource bundles, which will persist without copying.
103      */
104     const UChar *adopt(const UChar *s, UErrorCode &status);
105 
106     /* Freeze the string pool.  Discards the hash table that is used
107      * for looking up a string.  All pointers to pooled strings remain valid.
108      */
109     void freeze();
110 
111   private:
112     ZSFStringPoolChunk   *fChunks;
113     UHashtable           *fHash;
114 };
115 
116 
117 /**
118  * TextTrieMap is a trie implementation for supporting
119  * fast prefix match for the string key.
120  */
121 class TextTrieMap : public UMemory {
122 public:
123     TextTrieMap(UBool ignoreCase);
124     virtual ~TextTrieMap();
125 
126     void put(const UnicodeString &key, void *value, ZSFStringPool &sp, UErrorCode &status);
127     void search(const UnicodeString &text, int32_t start,
128         TextTrieMapSearchResultHandler *handler, UErrorCode& status) const;
129     int32_t isEmpty() const;
130 
131 private:
132     UBool           fIgnoreCase;
133     CharacterNode   *fNodes;
134     int32_t         fNodesCapacity;
135     int32_t         fNodesCount;
136 
137     UVector         *fLazyContents;
138     UBool           fIsEmpty;
139 
140     UBool growNodes();
141     CharacterNode* addChildNode(CharacterNode *parent, UChar c, UErrorCode &status);
142     CharacterNode* getChildNode(CharacterNode *parent, UChar c) const;
143 
144     void putImpl(const UnicodeString &key, void *value, UErrorCode &status);
145     void buildTrie(UErrorCode &status);
146     void search(CharacterNode *node, const UnicodeString &text, int32_t start,
147         int32_t index, TextTrieMapSearchResultHandler *handler, UErrorCode &status) const;
148 };
149 
150 
151 // Name types, these bit flag are used for zone string lookup
152 enum TimeZoneTranslationType {
153     LOCATION        = 0x0001,
154     GENERIC_LONG    = 0x0002,
155     GENERIC_SHORT   = 0x0004,
156     STANDARD_LONG   = 0x0008,
157     STANDARD_SHORT  = 0x0010,
158     DAYLIGHT_LONG   = 0x0020,
159     DAYLIGHT_SHORT  = 0x0040
160 };
161 
162 // Name type index, these constants are used for index in the zone strings array.
163 enum TimeZoneTranslationTypeIndex {
164     ZSIDX_LOCATION = 0,
165     ZSIDX_LONG_STANDARD,
166     ZSIDX_SHORT_STANDARD,
167     ZSIDX_LONG_DAYLIGHT,
168     ZSIDX_SHORT_DAYLIGHT,
169     ZSIDX_LONG_GENERIC,
170     ZSIDX_SHORT_GENERIC,
171 
172     ZSIDX_COUNT
173 };
174 
175 class MessageFormat;
176 
177 
178 /*
179  * ZoneStringInfo is a class holding a localized zone string
180  * information.
181  */
182 class ZoneStringInfo : public UMemory {
183 public:
184     virtual ~ZoneStringInfo();
185 
186     inline UnicodeString& getID(UnicodeString &result) const;
187     inline UnicodeString& getString(UnicodeString &result) const;
188     inline UBool isStandard(void) const;
189     inline UBool isDaylight(void) const;
190     inline UBool isGeneric(void) const;
191 
192 private:
193     friend class ZoneStringFormat;
194     friend class ZoneStringSearchResultHandler;
195 
196     ZoneStringInfo(const UnicodeString &id, const UnicodeString &str,
197                    TimeZoneTranslationType type, ZSFStringPool &sp, UErrorCode &status);
198 
199     const UChar   *fId;
200     const UChar   *fStr;
201     TimeZoneTranslationType fType;
202 };
203 
getID(UnicodeString & result)204 inline UnicodeString& ZoneStringInfo::getID(UnicodeString &result) const {
205     return result.setTo(fId, -1);
206 }
207 
getString(UnicodeString & result)208 inline UnicodeString& ZoneStringInfo::getString(UnicodeString &result) const {
209     return result.setTo(fStr, -1);
210 }
211 
isStandard(void)212 inline UBool ZoneStringInfo::isStandard(void) const {
213     return (fType == STANDARD_LONG || fType == STANDARD_SHORT);
214 }
215 
isDaylight(void)216 inline UBool ZoneStringInfo::isDaylight(void) const {
217     return (fType == DAYLIGHT_LONG || fType == DAYLIGHT_SHORT);
218 }
219 
isGeneric(void)220 inline UBool ZoneStringInfo::isGeneric(void) const {
221     return (fType == LOCATION || fType == GENERIC_LONG || fType == GENERIC_SHORT);
222 }
223 
224 class SafeZoneStringFormatPtr;
225 
226 class ZoneStringFormat : public UMemory {
227 public:
228     ZoneStringFormat(const UnicodeString* const* strings, int32_t rowCount, int32_t columnCount, UErrorCode &status);
229     ZoneStringFormat(const Locale& locale, UErrorCode &status);
230     virtual ~ZoneStringFormat();
231 
232     /* Gets zone string format from cache if available, create it if not cached. */
233     static SafeZoneStringFormatPtr* getZoneStringFormat(const Locale& locale, UErrorCode &status);
234 
235     /*
236      * Create a snapshot of old zone strings array for the given date
237      */
238     UnicodeString** createZoneStringsArray(UDate date, int32_t &rowCount, int32_t &colCount, UErrorCode &status) const;
239 
240     /* TODO:  There is no implementation for this function.  Delete declaration? */
241     const UnicodeString** getZoneStrings(int32_t &rowCount, int32_t &columnCount) const;
242 
243     UnicodeString& getSpecificLongString(const Calendar &cal,
244         UnicodeString &result, UErrorCode &status) const;
245 
246     UnicodeString& getSpecificShortString(const Calendar &cal,
247         UBool commonlyUsedOnly, UnicodeString &result, UErrorCode &status) const;
248 
249     UnicodeString& getGenericLongString(const Calendar &cal,
250         UnicodeString &result, UErrorCode &status) const;
251 
252     UnicodeString& getGenericShortString(const Calendar &cal,
253         UBool commonlyUsedOnly, UnicodeString &result, UErrorCode &status) const;
254 
255     UnicodeString& getGenericLocationString(const Calendar &cal,
256         UnicodeString &result, UErrorCode &status) const;
257 
258     const ZoneStringInfo* findSpecificLong(const UnicodeString &text, int32_t start,
259         int32_t &matchLength, UErrorCode &status) const;
260     const ZoneStringInfo* findSpecificShort(const UnicodeString &text, int32_t start,
261         int32_t &matchLength, UErrorCode &status) const;
262     const ZoneStringInfo* findGenericLong(const UnicodeString &text, int32_t start,
263         int32_t &matchLength, UErrorCode &status) const;
264     const ZoneStringInfo* findGenericShort(const UnicodeString &text, int32_t start,
265         int32_t &matchLength, UErrorCode &status) const;
266     const ZoneStringInfo* findGenericLocation(const UnicodeString &text, int32_t start,
267         int32_t &matchLength, UErrorCode &status) const;
268 
269     // Following APIs are not used by SimpleDateFormat, but public for testing purpose
270     inline UnicodeString& getLongStandard(const UnicodeString &tzid, UDate date,
271         UnicodeString &result) const;
272     inline UnicodeString& getLongDaylight(const UnicodeString &tzid, UDate date,
273         UnicodeString &result) const;
274     inline UnicodeString& getLongGenericNonLocation(const UnicodeString &tzid, UDate date,
275         UnicodeString &result) const;
276     inline UnicodeString& getLongGenericPartialLocation(const UnicodeString &tzid, UDate date,
277         UnicodeString &result) const;
278     inline UnicodeString& getShortStandard(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
279         UnicodeString &result) const;
280     inline UnicodeString& getShortDaylight(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
281         UnicodeString &result) const;
282     inline UnicodeString& getShortGenericNonLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
283         UnicodeString &result) const;
284     inline UnicodeString& getShortGenericPartialLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
285         UnicodeString &result) const;
286     inline UnicodeString& getGenericLocation(const UnicodeString &tzid, UnicodeString &result) const;
287 
288 private:
289     Locale           fLocale;
290     UHashtable      *fTzidToStrings;
291     UHashtable      *fMzidToStrings;
292 
293     TextTrieMap      fZoneStringsTrie;
294     ZSFStringPool    fStringPool;
295 
296     UResourceBundle *fZoneStringsArray;
297     UResourceBundle *fMetazoneItem;
298     UResourceBundle *fZoneItem;
299 
300 	UBool			 fIsFullyLoaded;
301 
302 	void loadZone(const UnicodeString &utzid, UErrorCode &status);
303 	void addSingleZone(UnicodeString &utzid, UErrorCode &status);
304 	void loadFull(UErrorCode &status);
305 
306 
307     /*
308      * Private method to get a zone string except generic partial location types.
309      */
310     UnicodeString& getString(const UnicodeString &tzid, TimeZoneTranslationTypeIndex typeIdx, UDate date,
311         UBool commonlyUsedOnly, UnicodeString& result) const;
312 
313     /*
314      * Private method to get a generic string, with fallback logic involved,
315      * that is,
316      *
317      * 1. If a generic non-location string is avaiable for the zone, return it.
318      * 2. If a generic non-location string is associated with a metazone and
319      *    the zone never use daylight time around the given date, use the standard
320      *    string (if available).
321      *
322      *    Note: In CLDR1.5.1, the same localization is used for generic and standard.
323      *    In this case, we do not use the standard string and do the rest.
324      *
325      * 3. If a generic non-location string is associated with a metazone and
326      *    the offset at the given time is different from the preferred zone for the
327      *    current locale, then return the generic partial location string (if avaiable)
328      * 4. If a generic non-location string is not available, use generic location
329      *    string.
330      */
331     UnicodeString& getGenericString(const Calendar &cal, UBool isShort, UBool commonlyUsedOnly,
332         UnicodeString &result, UErrorCode &status) const;
333 
334     /*
335      * Private method to get a generic partial location string
336      */
337     UnicodeString& getGenericPartialLocationString(const UnicodeString &tzid, UBool isShort,
338         UDate date, UBool commonlyUsedOnly, UnicodeString &result) const;
339 
340     /*
341      * Find a prefix matching time zone for the given zone string types.
342      * @param text The text contains a time zone string
343      * @param start The start index within the text
344      * @param types The bit mask representing a set of requested types
345      * @param matchLength Receives the match length
346      * @param status
347      * @return If any zone string matched for the requested types, returns a
348      * ZoneStringInfo for the longest match.  If no matches are found for
349      * the requested types, returns a ZoneStringInfo for the longest match
350      * for any other types.  If nothing matches at all, returns null.
351      */
352     const ZoneStringInfo* find(const UnicodeString &text, int32_t start, int32_t types,
353         int32_t &matchLength, UErrorCode &status) const;
354 	const ZoneStringInfo* subFind(const UnicodeString &text, int32_t start, int32_t types,
355                        int32_t &matchLength, UErrorCode &status) const;
356 
357     UnicodeString& getRegion(UnicodeString &region) const;
358 
359     static MessageFormat* getFallbackFormat(const Locale &locale, UErrorCode &status);
360     static MessageFormat* getRegionFormat(const Locale &locale, UErrorCode &status);
361     const UChar* getZoneStringFromBundle(const UResourceBundle *zoneitem, const char *key);
362     static UBool isCommonlyUsed(const UResourceBundle *zoneitem);
363     static UnicodeString& getLocalizedCountry(const UnicodeString &countryCode, const Locale &locale,
364         UnicodeString &displayCountry);
365 };
366 
367 inline UnicodeString&
getLongStandard(const UnicodeString & tzid,UDate date,UnicodeString & result)368 ZoneStringFormat::getLongStandard(const UnicodeString &tzid, UDate date,
369                                   UnicodeString &result) const {
370     return getString(tzid, ZSIDX_LONG_STANDARD, date, FALSE /* not used */, result);
371 }
372 
373 inline UnicodeString&
getLongDaylight(const UnicodeString & tzid,UDate date,UnicodeString & result)374 ZoneStringFormat::getLongDaylight(const UnicodeString &tzid, UDate date,
375                                   UnicodeString &result) const {
376     return getString(tzid, ZSIDX_LONG_DAYLIGHT, date, FALSE /* not used */, result);
377 }
378 
379 inline UnicodeString&
getLongGenericNonLocation(const UnicodeString & tzid,UDate date,UnicodeString & result)380 ZoneStringFormat::getLongGenericNonLocation(const UnicodeString &tzid, UDate date,
381                                             UnicodeString &result) const {
382     return getString(tzid, ZSIDX_LONG_GENERIC, date, FALSE /* not used */, result);
383 }
384 
385 inline UnicodeString&
getLongGenericPartialLocation(const UnicodeString & tzid,UDate date,UnicodeString & result)386 ZoneStringFormat::getLongGenericPartialLocation(const UnicodeString &tzid, UDate date,
387                                                 UnicodeString &result) const {
388     return getGenericPartialLocationString(tzid, FALSE, date, FALSE /* not used */, result);
389 }
390 
391 inline UnicodeString&
getShortStandard(const UnicodeString & tzid,UDate date,UBool commonlyUsedOnly,UnicodeString & result)392 ZoneStringFormat::getShortStandard(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
393                                    UnicodeString &result) const {
394     return getString(tzid, ZSIDX_SHORT_STANDARD, date, commonlyUsedOnly, result);
395 }
396 
397 inline UnicodeString&
getShortDaylight(const UnicodeString & tzid,UDate date,UBool commonlyUsedOnly,UnicodeString & result)398 ZoneStringFormat::getShortDaylight(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
399                                    UnicodeString &result) const {
400     return getString(tzid, ZSIDX_SHORT_DAYLIGHT, date, commonlyUsedOnly, result);
401 }
402 
403 inline UnicodeString&
getShortGenericNonLocation(const UnicodeString & tzid,UDate date,UBool commonlyUsedOnly,UnicodeString & result)404 ZoneStringFormat::getShortGenericNonLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
405                                              UnicodeString &result) const {
406     return getString(tzid, ZSIDX_SHORT_GENERIC, date, commonlyUsedOnly, result);
407 }
408 
409 inline UnicodeString&
getShortGenericPartialLocation(const UnicodeString & tzid,UDate date,UBool commonlyUsedOnly,UnicodeString & result)410 ZoneStringFormat::getShortGenericPartialLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
411                                                  UnicodeString &result) const {
412     return getGenericPartialLocationString(tzid, TRUE, date, commonlyUsedOnly, result);
413 }
414 
415 inline UnicodeString&
getGenericLocation(const UnicodeString & tzid,UnicodeString & result)416 ZoneStringFormat::getGenericLocation(const UnicodeString &tzid, UnicodeString &result) const {
417     return getString(tzid, ZSIDX_LOCATION, 0 /*not used*/, FALSE /*not used*/, result);
418 }
419 
420 
421 /*
422  * ZoneStrings is a container of localized zone strings used by ZoneStringFormat
423  */
424 class ZoneStrings : public UMemory {
425 public:
426     ZoneStrings(UnicodeString *strings,
427                 int32_t        stringsCount,
428                 UBool          commonlyUsed,
429                 UnicodeString **genericPartialLocationStrings,
430                 int32_t        genericRowCount,
431                 int32_t        genericColCount,
432                 ZSFStringPool &sp,
433                 UErrorCode    &status);
434     virtual         ~ZoneStrings();
435 
436     UnicodeString&   getString(int32_t typeIdx, UnicodeString &result) const;
437     inline UBool     isShortFormatCommonlyUsed(void) const;
438     UnicodeString&   getGenericPartialLocationString(const UnicodeString &mzid, UBool isShort,
439                                         UBool commonlyUsedOnly, UnicodeString &result) const;
440 
441 private:
442     const UChar   **fStrings;
443     int32_t         fStringsCount;
444     UBool           fIsCommonlyUsed;
445     const UChar * **fGenericPartialLocationStrings;
446     int32_t         fGenericPartialLocationRowCount;
447     int32_t         fGenericPartialLocationColCount;
448 };
449 
450 inline UBool
isShortFormatCommonlyUsed(void)451 ZoneStrings::isShortFormatCommonlyUsed(void) const {
452     return fIsCommonlyUsed;
453 }
454 
455 /*
456  * ZoneStringSearchResultHandler is an implementation of
457  * TextTrieMapSearchHandler.  This class is used by ZoneStringFormat
458  * for collecting search results for localized zone strings.
459  */
460 class ZoneStringSearchResultHandler : public TextTrieMapSearchResultHandler {
461 public:
462     ZoneStringSearchResultHandler(UErrorCode &status);
463     virtual ~ZoneStringSearchResultHandler();
464 
465     virtual UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
466     int32_t countMatches(void);
467     const ZoneStringInfo* getMatch(int32_t index, int32_t &matchLength);
468     void clear(void);
469 
470 private:
471     UVector fResults;
472     int32_t fMatchLen[ZSIDX_COUNT];
473 };
474 
475 
476 /*
477  * ZoneStringFormat cache implementation
478  */
479 class ZSFCacheEntry : public UMemory {
480 public:
481     ~ZSFCacheEntry();
482 
483     void delRef(void);
484     const ZoneStringFormat* getZoneStringFormat(void);
485 
486 private:
487     friend class ZSFCache;
488 
489     ZSFCacheEntry(const Locale &locale, ZoneStringFormat *zsf, ZSFCacheEntry *next);
490 
491     Locale              fLocale;
492     ZoneStringFormat    *fZoneStringFormat;
493     ZSFCacheEntry       *fNext;
494     int32_t             fRefCount;
495 };
496 
497 class SafeZoneStringFormatPtr : public UMemory {
498 public:
499     ~SafeZoneStringFormatPtr();
500     const ZoneStringFormat* get() const;
501 
502 private:
503     friend class ZSFCache;
504 
505     SafeZoneStringFormatPtr(ZSFCacheEntry *cacheEntry);
506 
507     ZSFCacheEntry   *fCacheEntry;
508 };
509 
510 class ZSFCache : public UMemory {
511 public:
512     ZSFCache(int32_t capacity);
513     ~ZSFCache();
514 
515     SafeZoneStringFormatPtr* get(const Locale &locale, UErrorCode &status);
516 
517 private:
518     int32_t         fCapacity;
519     ZSFCacheEntry   *fFirst;
520 };
521 
522 U_NAMESPACE_END
523 
524 #endif /* #if !UCONFIG_NO_FORMATTING */
525 
526 #endif // ZSTRFMT_H
527