2 *******************************************************************************
3 * Copyright (C) 2007-2008, 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
79 * TextTrieMap is a trie implementation for supporting
80 * fast prefix match for the string key.
82 class TextTrieMap
: public UMemory
{
84 TextTrieMap(UBool ignoreCase
);
85 virtual ~TextTrieMap();
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;
94 CharacterNode
*fNodes
;
95 int32_t fNodesCapacity
;
99 CharacterNode
* addChildNode(CharacterNode
*parent
, UChar c
, UErrorCode
&status
);
100 CharacterNode
* getChildNode(CharacterNode
*parent
, UChar c
) const;
102 void search(CharacterNode
*node
, const UnicodeString
&text
, int32_t start
,
103 int32_t index
, TextTrieMapSearchResultHandler
*handler
, UErrorCode
&status
) const;
106 inline UChar32
TextTrieMap::isEmpty(void) const {
107 return fNodes
== NULL
;
110 // Name types, these bit flag are used for zone string lookup
111 enum TimeZoneTranslationType
{
113 GENERIC_LONG
= 0x0002,
114 GENERIC_SHORT
= 0x0004,
115 STANDARD_LONG
= 0x0008,
116 STANDARD_SHORT
= 0x0010,
117 DAYLIGHT_LONG
= 0x0020,
118 DAYLIGHT_SHORT
= 0x0040
121 // Name type index, these constants are used for index in the zone strings array.
122 enum TimeZoneTranslationTypeIndex
{
125 ZSIDX_SHORT_STANDARD
,
127 ZSIDX_SHORT_DAYLIGHT
,
137 * ZoneStringInfo is a class holding a localized zone string
140 class ZoneStringInfo
: public UMemory
{
142 virtual ~ZoneStringInfo();
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;
151 friend class ZoneStringFormat
;
152 friend class ZoneStringSearchResultHandler
;
154 ZoneStringInfo(const UnicodeString
&id
, const UnicodeString
&str
, TimeZoneTranslationType type
);
158 TimeZoneTranslationType fType
;
161 inline UnicodeString
& ZoneStringInfo::getID(UnicodeString
&result
) const {
162 return result
.setTo(fId
);
165 inline UnicodeString
& ZoneStringInfo::getString(UnicodeString
&result
) const {
166 return result
.setTo(fStr
);
169 inline UBool
ZoneStringInfo::isStandard(void) const {
170 return (fType
== STANDARD_LONG
|| fType
== STANDARD_SHORT
);
173 inline UBool
ZoneStringInfo::isDaylight(void) const {
174 return (fType
== DAYLIGHT_LONG
|| fType
== DAYLIGHT_SHORT
);
177 inline UBool
ZoneStringInfo::isGeneric(void) const {
178 return (fType
== LOCATION
|| fType
== GENERIC_LONG
|| fType
== GENERIC_SHORT
);
181 class SafeZoneStringFormatPtr
;
183 class ZoneStringFormat
: public UMemory
{
185 ZoneStringFormat(const UnicodeString
* const* strings
, int32_t rowCount
, int32_t columnCount
, UErrorCode
&status
);
186 ZoneStringFormat(const Locale
& locale
, UErrorCode
&status
);
187 virtual ~ZoneStringFormat();
189 static SafeZoneStringFormatPtr
* getZoneStringFormat(const Locale
& locale
, UErrorCode
&status
);
192 * Create a snapshot of old zone strings array for the given date
194 UnicodeString
** createZoneStringsArray(UDate date
, int32_t &rowCount
, int32_t &colCount
, UErrorCode
&status
) const;
196 const UnicodeString
** getZoneStrings(int32_t &rowCount
, int32_t &columnCount
) const;
198 UnicodeString
& getSpecificLongString(const Calendar
&cal
,
199 UnicodeString
&result
, UErrorCode
&status
) const;
201 UnicodeString
& getSpecificShortString(const Calendar
&cal
,
202 UBool commonlyUsedOnly
, UnicodeString
&result
, UErrorCode
&status
) const;
204 UnicodeString
& getGenericLongString(const Calendar
&cal
,
205 UnicodeString
&result
, UErrorCode
&status
) const;
207 UnicodeString
& getGenericShortString(const Calendar
&cal
,
208 UBool commonlyUsedOnly
, UnicodeString
&result
, UErrorCode
&status
) const;
210 UnicodeString
& getGenericLocationString(const Calendar
&cal
,
211 UnicodeString
&result
, UErrorCode
&status
) const;
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;
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;
245 Hashtable fTzidToStrings
;
246 Hashtable fMzidToStrings
;
247 TextTrieMap fZoneStringsTrie
;
250 * Private method to get a zone string except generic partial location types.
252 UnicodeString
& getString(const UnicodeString
&tzid
, TimeZoneTranslationTypeIndex typeIdx
, UDate date
,
253 UBool commonlyUsedOnly
, UnicodeString
& result
) const;
256 * Private method to get a generic string, with fallback logic involved,
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).
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.
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
273 UnicodeString
& getGenericString(const Calendar
&cal
, UBool isShort
, UBool commonlyUsedOnly
,
274 UnicodeString
&result
, UErrorCode
&status
) const;
277 * Private method to get a generic partial location string
279 UnicodeString
& getGenericPartialLocationString(const UnicodeString
&tzid
, UBool isShort
,
280 UDate date
, UBool commonlyUsedOnly
, UnicodeString
&result
) const;
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
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.
294 const ZoneStringInfo
* find(const UnicodeString
&text
, int32_t start
, int32_t types
,
295 int32_t &matchLength
, UErrorCode
&status
) const;
297 UnicodeString
& getRegion(UnicodeString
®ion
) const;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
362 * ZooneStrings is a container of localized zone strings used by ZoneStringFormat
364 class ZoneStrings
: public UMemory
{
366 ZoneStrings(UnicodeString
*strings
, int32_t stringsCount
, UBool commonlyUsed
,
367 UnicodeString
**genericPartialLocationStrings
, int32_t genericRowCount
, int32_t genericColCount
);
368 virtual ~ZoneStrings();
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;
376 UnicodeString
*fStrings
;
377 int32_t fStringsCount
;
378 UBool fIsCommonlyUsed
;
379 UnicodeString
**fGenericPartialLocationStrings
;
380 int32_t fGenericPartialLocationRowCount
;
381 int32_t fGenericPartialLocationColCount
;
385 ZoneStrings::isShortFormatCommonlyUsed(void) const {
386 return fIsCommonlyUsed
;
390 * ZoneStringSearchResultHandler is an implementation of
391 * TextTrieMapSearchHandler. This class is used by ZoneStringFormat
392 * for collecting search results for localized zone strings.
394 class ZoneStringSearchResultHandler
: public TextTrieMapSearchResultHandler
{
396 ZoneStringSearchResultHandler(UErrorCode
&status
);
397 virtual ~ZoneStringSearchResultHandler();
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
);
406 int32_t fMatchLen
[ZSIDX_COUNT
];
411 * ZoneStringFormat cache implementation
413 class ZSFCacheEntry
: public UMemory
{
418 const ZoneStringFormat
* getZoneStringFormat(void);
421 friend class ZSFCache
;
423 ZSFCacheEntry(const Locale
&locale
, ZoneStringFormat
*zsf
, ZSFCacheEntry
*next
);
426 ZoneStringFormat
*fZoneStringFormat
;
427 ZSFCacheEntry
*fNext
;
431 class SafeZoneStringFormatPtr
: public UMemory
{
433 ~SafeZoneStringFormatPtr();
434 const ZoneStringFormat
* get() const;
437 friend class ZSFCache
;
439 SafeZoneStringFormatPtr(ZSFCacheEntry
*cacheEntry
);
441 ZSFCacheEntry
*fCacheEntry
;
444 class ZSFCache
: public UMemory
{
446 ZSFCache(int32_t capacity
);
449 SafeZoneStringFormatPtr
* get(const Locale
&locale
, UErrorCode
&status
);
453 ZSFCacheEntry
*fFirst
;
458 #endif /* #if !UCONFIG_NO_FORMATTING */