2 *******************************************************************************
3 * Copyright (C) 2007-2010, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
10 #include "unicode/utypes.h"
12 #if !UCONFIG_NO_FORMATTING
14 #include "unicode/unistr.h"
15 #include "unicode/calendar.h"
22 * Character node used by TextTrieMap
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.
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;
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
;
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
49 inline UBool
CharacterNode::hasValues() const {
50 return (UBool
)(fValues
!= NULL
);
53 inline int32_t CharacterNode::countValues() const {
56 !fHasValuesVector
? 1 :
57 ((const UVector
*)fValues
)->size();
60 inline const void *CharacterNode::getValue(int32_t index
) const {
61 if (!fHasValuesVector
) {
62 return fValues
; // Assume index == 0.
64 return ((const UVector
*)fValues
)->elementAt(index
);
69 * Search result handler callback interface used by TextTrieMap search.
71 class TextTrieMapSearchResultHandler
: public UMemory
{
73 virtual UBool
handleMatch(int32_t matchLength
,
74 const CharacterNode
*node
, UErrorCode
& status
) = 0;
75 virtual ~TextTrieMapSearchResultHandler(); //added to avoid warning
80 * ZSFStringPool Pool of (UChar *) strings. Provides for sharing of repeated
81 * strings within ZoneStringFormats.
83 class ZSFStringPoolChunk
;
84 class ZSFStringPool
: public UMemory
{
86 ZSFStringPool(UErrorCode
&status
);
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.
92 * Life time of the returned string is that of the pool.
94 const UChar
*get(const UChar
*s
, UErrorCode
&status
);
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.
99 const UChar
*get(const UnicodeString
&s
, UErrorCode
&status
);
101 /* Adopt a string into the pool, without copying it.
102 * Used for strings from resource bundles, which will persist without copying.
104 const UChar
*adopt(const UChar
*s
, UErrorCode
&status
);
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.
112 ZSFStringPoolChunk
*fChunks
;
118 * TextTrieMap is a trie implementation for supporting
119 * fast prefix match for the string key.
121 class TextTrieMap
: public UMemory
{
123 TextTrieMap(UBool ignoreCase
);
124 virtual ~TextTrieMap();
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;
133 CharacterNode
*fNodes
;
134 int32_t fNodesCapacity
;
137 UVector
*fLazyContents
;
141 CharacterNode
* addChildNode(CharacterNode
*parent
, UChar c
, UErrorCode
&status
);
142 CharacterNode
* getChildNode(CharacterNode
*parent
, UChar c
) const;
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;
151 // Name types, these bit flag are used for zone string lookup
152 enum TimeZoneTranslationType
{
154 GENERIC_LONG
= 0x0002,
155 GENERIC_SHORT
= 0x0004,
156 STANDARD_LONG
= 0x0008,
157 STANDARD_SHORT
= 0x0010,
158 DAYLIGHT_LONG
= 0x0020,
159 DAYLIGHT_SHORT
= 0x0040
162 // Name type index, these constants are used for index in the zone strings array.
163 enum TimeZoneTranslationTypeIndex
{
166 ZSIDX_SHORT_STANDARD
,
168 ZSIDX_SHORT_DAYLIGHT
,
179 * ZoneStringInfo is a class holding a localized zone string
182 class ZoneStringInfo
: public UMemory
{
184 virtual ~ZoneStringInfo();
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;
193 friend class ZoneStringFormat
;
194 friend class ZoneStringSearchResultHandler
;
196 ZoneStringInfo(const UnicodeString
&id
, const UnicodeString
&str
,
197 TimeZoneTranslationType type
, ZSFStringPool
&sp
, UErrorCode
&status
);
201 TimeZoneTranslationType fType
;
204 inline UnicodeString
& ZoneStringInfo::getID(UnicodeString
&result
) const {
205 return result
.setTo(fId
, -1);
208 inline UnicodeString
& ZoneStringInfo::getString(UnicodeString
&result
) const {
209 return result
.setTo(fStr
, -1);
212 inline UBool
ZoneStringInfo::isStandard(void) const {
213 return (fType
== STANDARD_LONG
|| fType
== STANDARD_SHORT
);
216 inline UBool
ZoneStringInfo::isDaylight(void) const {
217 return (fType
== DAYLIGHT_LONG
|| fType
== DAYLIGHT_SHORT
);
220 inline UBool
ZoneStringInfo::isGeneric(void) const {
221 return (fType
== LOCATION
|| fType
== GENERIC_LONG
|| fType
== GENERIC_SHORT
);
224 class SafeZoneStringFormatPtr
;
226 class ZoneStringFormat
: public UMemory
{
228 ZoneStringFormat(const UnicodeString
* const* strings
, int32_t rowCount
, int32_t columnCount
, UErrorCode
&status
);
229 ZoneStringFormat(const Locale
& locale
, UErrorCode
&status
);
230 virtual ~ZoneStringFormat();
232 /* Gets zone string format from cache if available, create it if not cached. */
233 static SafeZoneStringFormatPtr
* getZoneStringFormat(const Locale
& locale
, UErrorCode
&status
);
236 * Create a snapshot of old zone strings array for the given date
238 UnicodeString
** createZoneStringsArray(UDate date
, int32_t &rowCount
, int32_t &colCount
, UErrorCode
&status
) const;
240 /* TODO: There is no implementation for this function. Delete declaration? */
241 const UnicodeString
** getZoneStrings(int32_t &rowCount
, int32_t &columnCount
) const;
243 UnicodeString
& getSpecificLongString(const Calendar
&cal
,
244 UnicodeString
&result
, UErrorCode
&status
) const;
246 UnicodeString
& getSpecificShortString(const Calendar
&cal
,
247 UBool commonlyUsedOnly
, UnicodeString
&result
, UErrorCode
&status
) const;
249 UnicodeString
& getGenericLongString(const Calendar
&cal
,
250 UnicodeString
&result
, UErrorCode
&status
) const;
252 UnicodeString
& getGenericShortString(const Calendar
&cal
,
253 UBool commonlyUsedOnly
, UnicodeString
&result
, UErrorCode
&status
) const;
255 UnicodeString
& getGenericLocationString(const Calendar
&cal
,
256 UnicodeString
&result
, UErrorCode
&status
) const;
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;
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;
290 UHashtable
*fTzidToStrings
;
291 UHashtable
*fMzidToStrings
;
293 TextTrieMap fZoneStringsTrie
;
294 ZSFStringPool fStringPool
;
296 UResourceBundle
*fZoneStringsArray
;
297 UResourceBundle
*fMetazoneItem
;
298 UResourceBundle
*fZoneItem
;
300 UBool fIsFullyLoaded
;
302 void loadZone(const UnicodeString
&utzid
, UErrorCode
&status
);
303 void addSingleZone(UnicodeString
&utzid
, UErrorCode
&status
);
304 void loadFull(UErrorCode
&status
);
308 * Private method to get a zone string except generic partial location types.
310 UnicodeString
& getString(const UnicodeString
&tzid
, TimeZoneTranslationTypeIndex typeIdx
, UDate date
,
311 UBool commonlyUsedOnly
, UnicodeString
& result
) const;
314 * Private method to get a generic string, with fallback logic involved,
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).
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.
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
331 UnicodeString
& getGenericString(const Calendar
&cal
, UBool isShort
, UBool commonlyUsedOnly
,
332 UnicodeString
&result
, UErrorCode
&status
) const;
335 * Private method to get a generic partial location string
337 UnicodeString
& getGenericPartialLocationString(const UnicodeString
&tzid
, UBool isShort
,
338 UDate date
, UBool commonlyUsedOnly
, UnicodeString
&result
) const;
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
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.
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;
357 UnicodeString
& getRegion(UnicodeString
®ion
) const;
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
);
367 inline UnicodeString
&
368 ZoneStringFormat::getLongStandard(const UnicodeString
&tzid
, UDate date
,
369 UnicodeString
&result
) const {
370 return getString(tzid
, ZSIDX_LONG_STANDARD
, date
, FALSE
/* not used */, result
);
373 inline UnicodeString
&
374 ZoneStringFormat::getLongDaylight(const UnicodeString
&tzid
, UDate date
,
375 UnicodeString
&result
) const {
376 return getString(tzid
, ZSIDX_LONG_DAYLIGHT
, date
, FALSE
/* not used */, result
);
379 inline UnicodeString
&
380 ZoneStringFormat::getLongGenericNonLocation(const UnicodeString
&tzid
, UDate date
,
381 UnicodeString
&result
) const {
382 return getString(tzid
, ZSIDX_LONG_GENERIC
, date
, FALSE
/* not used */, result
);
385 inline UnicodeString
&
386 ZoneStringFormat::getLongGenericPartialLocation(const UnicodeString
&tzid
, UDate date
,
387 UnicodeString
&result
) const {
388 return getGenericPartialLocationString(tzid
, FALSE
, date
, FALSE
/* not used */, result
);
391 inline UnicodeString
&
392 ZoneStringFormat::getShortStandard(const UnicodeString
&tzid
, UDate date
, UBool commonlyUsedOnly
,
393 UnicodeString
&result
) const {
394 return getString(tzid
, ZSIDX_SHORT_STANDARD
, date
, commonlyUsedOnly
, result
);
397 inline UnicodeString
&
398 ZoneStringFormat::getShortDaylight(const UnicodeString
&tzid
, UDate date
, UBool commonlyUsedOnly
,
399 UnicodeString
&result
) const {
400 return getString(tzid
, ZSIDX_SHORT_DAYLIGHT
, date
, commonlyUsedOnly
, result
);
403 inline UnicodeString
&
404 ZoneStringFormat::getShortGenericNonLocation(const UnicodeString
&tzid
, UDate date
, UBool commonlyUsedOnly
,
405 UnicodeString
&result
) const {
406 return getString(tzid
, ZSIDX_SHORT_GENERIC
, date
, commonlyUsedOnly
, result
);
409 inline UnicodeString
&
410 ZoneStringFormat::getShortGenericPartialLocation(const UnicodeString
&tzid
, UDate date
, UBool commonlyUsedOnly
,
411 UnicodeString
&result
) const {
412 return getGenericPartialLocationString(tzid
, TRUE
, date
, commonlyUsedOnly
, result
);
415 inline UnicodeString
&
416 ZoneStringFormat::getGenericLocation(const UnicodeString
&tzid
, UnicodeString
&result
) const {
417 return getString(tzid
, ZSIDX_LOCATION
, 0 /*not used*/, FALSE
/*not used*/, result
);
422 * ZoneStrings is a container of localized zone strings used by ZoneStringFormat
424 class ZoneStrings
: public UMemory
{
426 ZoneStrings(UnicodeString
*strings
,
427 int32_t stringsCount
,
429 UnicodeString
**genericPartialLocationStrings
,
430 int32_t genericRowCount
,
431 int32_t genericColCount
,
434 virtual ~ZoneStrings();
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;
442 const UChar
**fStrings
;
443 int32_t fStringsCount
;
444 UBool fIsCommonlyUsed
;
445 const UChar
* **fGenericPartialLocationStrings
;
446 int32_t fGenericPartialLocationRowCount
;
447 int32_t fGenericPartialLocationColCount
;
451 ZoneStrings::isShortFormatCommonlyUsed(void) const {
452 return fIsCommonlyUsed
;
456 * ZoneStringSearchResultHandler is an implementation of
457 * TextTrieMapSearchHandler. This class is used by ZoneStringFormat
458 * for collecting search results for localized zone strings.
460 class ZoneStringSearchResultHandler
: public TextTrieMapSearchResultHandler
{
462 ZoneStringSearchResultHandler(UErrorCode
&status
);
463 virtual ~ZoneStringSearchResultHandler();
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
);
472 int32_t fMatchLen
[ZSIDX_COUNT
];
477 * ZoneStringFormat cache implementation
479 class ZSFCacheEntry
: public UMemory
{
484 const ZoneStringFormat
* getZoneStringFormat(void);
487 friend class ZSFCache
;
489 ZSFCacheEntry(const Locale
&locale
, ZoneStringFormat
*zsf
, ZSFCacheEntry
*next
);
492 ZoneStringFormat
*fZoneStringFormat
;
493 ZSFCacheEntry
*fNext
;
497 class SafeZoneStringFormatPtr
: public UMemory
{
499 ~SafeZoneStringFormatPtr();
500 const ZoneStringFormat
* get() const;
503 friend class ZSFCache
;
505 SafeZoneStringFormatPtr(ZSFCacheEntry
*cacheEntry
);
507 ZSFCacheEntry
*fCacheEntry
;
510 class ZSFCache
: public UMemory
{
512 ZSFCache(int32_t capacity
);
515 SafeZoneStringFormatPtr
* get(const Locale
&locale
, UErrorCode
&status
);
519 ZSFCacheEntry
*fFirst
;
524 #endif /* #if !UCONFIG_NO_FORMATTING */