summaryrefslogtreecommitdiff
path: root/deps/icu-small/source/i18n/dtptngen.cpp
diff options
context:
space:
mode:
authorSteven R. Loomis <srloomis@us.ibm.com>2016-10-19 17:24:31 -0700
committerSteven R. Loomis <srloomis@us.ibm.com>2016-10-31 13:42:52 -0700
commit40366df885ec75c7eeee5e7e7626212ae1a6e770 (patch)
tree488aa7a7778b2a42083883540724def7d5eb4f50 /deps/icu-small/source/i18n/dtptngen.cpp
parent03023fa7ae060c082a014f792d5d1f481a599460 (diff)
downloadandroid-node-v8-40366df885ec75c7eeee5e7e7626212ae1a6e770.tar.gz
android-node-v8-40366df885ec75c7eeee5e7e7626212ae1a6e770.tar.bz2
android-node-v8-40366df885ec75c7eeee5e7e7626212ae1a6e770.zip
deps: Intl: ICU 58 bump - small icu (BIG COMMIT)
This commit contains the ICU 58.1 delta. It is especially large because of the ICU license change, and, because the line endings were off previously. * bump to ICU 58.1 - check in small ICU source * from 58.1 final http://site.icu-project.org/download/58 Fixes: https://github.com/nodejs/node/issues/7844 PR-URL: https://github.com/nodejs/node/pull/9234 Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'deps/icu-small/source/i18n/dtptngen.cpp')
-rw-r--r--deps/icu-small/source/i18n/dtptngen.cpp816
1 files changed, 413 insertions, 403 deletions
diff --git a/deps/icu-small/source/i18n/dtptngen.cpp b/deps/icu-small/source/i18n/dtptngen.cpp
index 2a6b35b511..17e7ec7cde 100644
--- a/deps/icu-small/source/i18n/dtptngen.cpp
+++ b/deps/icu-small/source/i18n/dtptngen.cpp
@@ -1,3 +1,5 @@
+// Copyright (C) 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 2007-2016, International Business Machines Corporation and
@@ -31,13 +33,13 @@
#include "cmemory.h"
#include "cstring.h"
#include "locbased.h"
-#include "gregoimp.h"
#include "hash.h"
#include "uhash.h"
#include "uresimp.h"
#include "dtptngen_impl.h"
#include "ucln_in.h"
#include "charstr.h"
+#include "uassert.h"
#if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
/**
@@ -221,10 +223,6 @@ static const char* const CLDR_FIELD_NAME[] = {
"hour", "minute", "second", "*", "zone"
};
-static const char* const Resource_Fields[] = {
- "day", "dayperiod", "era", "hour", "minute", "month", "second", "week",
- "weekday", "year", "zone", "quarter" };
-
// For appendItems
static const UChar UDATPG_ItemFormat[]= {0x7B, 0x30, 0x7D, 0x20, 0x251C, 0x7B, 0x32, 0x7D, 0x3A,
0x20, 0x7B, 0x31, 0x7D, 0x2524, 0}; // {0} \u251C{2}: {1}\u2524
@@ -392,12 +390,12 @@ UInitOnce initOnce = U_INITONCE_INITIALIZER;
UHashtable *localeToAllowedHourFormatsMap = NULL;
// Value deleter for hashmap.
-void deleteAllowedHourFormats(void *ptr) {
+U_CFUNC void U_CALLCONV deleteAllowedHourFormats(void *ptr) {
uprv_free(ptr);
}
// Close hashmap at cleanup.
-UBool allowedHourFormatsCleanup() {
+U_CFUNC UBool U_CALLCONV allowedHourFormatsCleanup() {
uhash_close(localeToAllowedHourFormatsMap);
return TRUE;
}
@@ -420,11 +418,8 @@ DateTimePatternGenerator::initData(const Locale& locale, UErrorCode &status) {
skipMatcher = NULL;
fAvailableFormatKeyHash=NULL;
- addCanonicalItems();
+ addCanonicalItems(status);
addICUPatterns(locale, status);
- if (U_FAILURE(status)) {
- return;
- }
addCLDRData(locale, status);
setDateTimeFromCalendar(locale, status);
setDecimalSymbols(locale, status);
@@ -434,80 +429,51 @@ DateTimePatternGenerator::initData(const Locale& locale, UErrorCode &status) {
namespace {
-struct AllowedHourFormatsSink : public ResourceTableSink {
+struct AllowedHourFormatsSink : public ResourceSink {
// Initialize sub-sinks.
- AllowedHourFormatsSink() : localeSink(*this), allowedListSink(*this) {}
+ AllowedHourFormatsSink() {}
virtual ~AllowedHourFormatsSink();
- // Entry point.
- virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &status) {
- if (U_FAILURE(status)) { return NULL; }
-
- locale = key;
- return &localeSink;
- }
-
- struct LocaleSink : public ResourceTableSink {
- AllowedHourFormatsSink &outer;
- LocaleSink(AllowedHourFormatsSink &outer) : outer(outer) {}
- virtual ~LocaleSink();
-
- virtual void put(const char *key, const ResourceValue &value, UErrorCode &status) {
- if (U_FAILURE(status)) { return; }
-
- if (uprv_strcmp(key, "allowed") == 0) {
- outer.allowedFormats = static_cast<int32_t *>(uprv_malloc(2 * sizeof(int32_t)));
- outer.allowedFormatsLength = 1;
- if (outer.allowedFormats == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return;
- }
- outer.allowedFormats[0] = outer.getHourFormatFromUnicodeString(
- value.getUnicodeString(status));
- }
- }
-
- virtual ResourceArraySink *getOrCreateArraySink(const char *key, int32_t size, UErrorCode &status) {
- if (U_FAILURE(status)) { return NULL; }
-
- if (uprv_strcmp(key, "allowed") == 0) {
- outer.allowedFormats = static_cast<int32_t *>(uprv_malloc((size + 1) * sizeof(int32_t)));
- outer.allowedFormatsLength = size;
- if (outer.allowedFormats == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- } else {
- return &outer.allowedListSink;
+ virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
+ UErrorCode &errorCode) {
+ ResourceTable timeData = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ for (int32_t i = 0; timeData.getKeyAndValue(i, key, value); ++i) {
+ const char *regionOrLocale = key;
+ ResourceTable formatList = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ for (int32_t j = 0; formatList.getKeyAndValue(j, key, value); ++j) {
+ if (uprv_strcmp(key, "allowed") == 0) { // Ignore "preferred" list.
+ LocalMemory<int32_t> list;
+ int32_t length;
+ if (value.getType() == URES_STRING) {
+ if (list.allocateInsteadAndReset(2) == NULL) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ list[0] = getHourFormatFromUnicodeString(value.getUnicodeString(errorCode));
+ length = 1;
+ }
+ else {
+ ResourceArray allowedFormats = value.getArray(errorCode);
+ length = allowedFormats.getSize();
+ if (list.allocateInsteadAndReset(length + 1) == NULL) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ for (int32_t k = 0; k < length; ++k) {
+ allowedFormats.getValue(k, value);
+ list[k] = getHourFormatFromUnicodeString(value.getUnicodeString(errorCode));
+ }
+ }
+ list[length] = ALLOWED_HOUR_FORMAT_UNKNOWN;
+ uhash_put(localeToAllowedHourFormatsMap,
+ const_cast<char *>(regionOrLocale), list.orphan(), &errorCode);
+ if (U_FAILURE(errorCode)) { return; }
}
}
- return NULL;
- }
-
- virtual void leave(UErrorCode &status) {
- if (U_FAILURE(status) || outer.allowedFormats == NULL) { return; }
-
- outer.allowedFormats[outer.allowedFormatsLength] = ALLOWED_HOUR_FORMAT_UNKNOWN;
- uhash_put(localeToAllowedHourFormatsMap, const_cast<char *>(outer.locale), outer.allowedFormats, &status);
- outer.allowedFormats = NULL;
}
- } localeSink;
-
- struct AllowedListSink : public ResourceArraySink {
- AllowedHourFormatsSink &outer;
- AllowedListSink(AllowedHourFormatsSink &outer) : outer(outer) {}
- virtual ~AllowedListSink();
-
- virtual void put(int32_t index, const ResourceValue &value, UErrorCode &status) {
- if (U_FAILURE(status)) { return; }
-
- outer.allowedFormats[index] = outer.getHourFormatFromUnicodeString(
- value.getUnicodeString(status));
- }
- } allowedListSink;
-
- const char *locale;
- int32_t *allowedFormats;
- int32_t allowedFormatsLength;
+ }
AllowedHourFormat getHourFormatFromUnicodeString(UnicodeString s) {
if (s.length() == 1) {
@@ -527,10 +493,8 @@ struct AllowedHourFormatsSink : public ResourceTableSink {
} // namespace
AllowedHourFormatsSink::~AllowedHourFormatsSink() {}
-AllowedHourFormatsSink::LocaleSink::~LocaleSink() {}
-AllowedHourFormatsSink::AllowedListSink::~AllowedListSink() {}
-void DateTimePatternGenerator::loadAllowedHourFormatsData(UErrorCode &status) {
+U_CFUNC void U_CALLCONV DateTimePatternGenerator::loadAllowedHourFormatsData(UErrorCode &status) {
if (U_FAILURE(status)) { return; }
localeToAllowedHourFormatsMap = uhash_open(
uhash_hashChars, uhash_compareChars, NULL, &status);
@@ -544,14 +508,13 @@ void DateTimePatternGenerator::loadAllowedHourFormatsData(UErrorCode &status) {
// into the hashmap, store 6 single-value sub-arrays right at the beginning of the
// vector (at index enum*2) for easy data sharing, copy sub-arrays into runtime
// object. Remember to clean up the vector, too.
- ures_getAllTableItemsWithFallback(rb.getAlias(), "timeData", sink, status);
+ ures_getAllItemsWithFallback(rb.getAlias(), "timeData", sink, status);
ucln_i18n_registerCleanup(UCLN_I18N_ALLOWED_HOUR_FORMATS, allowedHourFormatsCleanup);
}
void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErrorCode &status) {
if (U_FAILURE(status)) { return; }
-
const char *localeID = locale.getName();
char maxLocaleID[ULOC_FULLNAME_CAPACITY];
int32_t length = uloc_addLikelySubtags(localeID, maxLocaleID, ULOC_FULLNAME_CAPACITY, &status);
@@ -632,41 +595,38 @@ DateTimePatternGenerator::staticGetBaseSkeleton(
void
DateTimePatternGenerator::addICUPatterns(const Locale& locale, UErrorCode& status) {
+ if (U_FAILURE(status)) { return; }
UnicodeString dfPattern;
UnicodeString conflictingString;
DateFormat* df;
- if (U_FAILURE(status)) {
- return;
- }
-
// Load with ICU patterns
for (int32_t i=DateFormat::kFull; i<=DateFormat::kShort; i++) {
DateFormat::EStyle style = (DateFormat::EStyle)i;
df = DateFormat::createDateInstance(style, locale);
SimpleDateFormat* sdf;
if (df != NULL && (sdf = dynamic_cast<SimpleDateFormat*>(df)) != NULL) {
- addPattern(sdf->toPattern(dfPattern), FALSE, conflictingString, status);
+ sdf->toPattern(dfPattern);
+ addPattern(dfPattern, FALSE, conflictingString, status);
}
// TODO Maybe we should return an error when the date format isn't simple.
delete df;
- if (U_FAILURE(status)) {
- return;
- }
+ if (U_FAILURE(status)) { return; }
df = DateFormat::createTimeInstance(style, locale);
if (df != NULL && (sdf = dynamic_cast<SimpleDateFormat*>(df)) != NULL) {
- addPattern(sdf->toPattern(dfPattern), FALSE, conflictingString, status);
- // HACK for hh:ss
- if ( i==DateFormat::kMedium ) {
- hackPattern = dfPattern;
+ sdf->toPattern(dfPattern);
+ addPattern(dfPattern, FALSE, conflictingString, status);
+
+ // TODO: C++ and Java are inconsistent (see #12568).
+ // C++ uses MEDIUM, but Java uses SHORT.
+ if ( i==DateFormat::kShort && !dfPattern.isEmpty() ) {
+ consumeShortTimePattern(dfPattern, status);
}
}
// TODO Maybe we should return an error when the date format isn't simple.
delete df;
- if (U_FAILURE(status)) {
- return;
- }
+ if (U_FAILURE(status)) { return; }
}
}
@@ -721,221 +681,223 @@ DateTimePatternGenerator::hackTimes(const UnicodeString& hackPattern, UErrorCode
static const UChar hourFormatChars[] = { CAP_H, LOW_H, CAP_K, LOW_K, 0 }; // HhKk, the hour format characters
void
-DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& err) {
- UResourceBundle *rb, *calTypeBundle, *calBundle;
- UResourceBundle *patBundle, *fieldBundle, *fBundle;
- UnicodeString rbPattern, value, field;
- UnicodeString conflictingPattern;
- const char *key=NULL;
- int32_t i;
-
- UnicodeString defaultItemFormat(TRUE, UDATPG_ItemFormat, UPRV_LENGTHOF(UDATPG_ItemFormat)-1); // Read-only alias.
-
- err = U_ZERO_ERROR;
-
- fDefaultHourFormatChar = 0;
- for (i=0; i<UDATPG_FIELD_COUNT; ++i ) {
- appendItemNames[i]=CAP_F;
- if (i<10) {
- appendItemNames[i]+=(UChar)(i+0x30);
- }
- else {
- appendItemNames[i]+=(UChar)0x31;
- appendItemNames[i]+=(UChar)(i-10 + 0x30);
- }
- // NUL-terminate for the C API.
- appendItemNames[i].getTerminatedBuffer();
- }
-
- rb = ures_open(NULL, locale.getName(), &err);
- if (rb == NULL || U_FAILURE(err)) {
- return;
- }
- const char *curLocaleName=ures_getLocaleByType(rb, ULOC_ACTUAL_LOCALE, &err);
- const char * calendarTypeToUse = DT_DateTimeGregorianTag; // initial default
- char calendarType[ULOC_KEYWORDS_CAPACITY]; // to be filled in with the type to use, if all goes well
+DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString& destination, UErrorCode& err) {
+ destination.clear().append(DT_DateTimeGregorianTag, -1, err); // initial default
if ( U_SUCCESS(err) ) {
- char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY];
+ char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY];
// obtain a locale that always has the calendar key value that should be used
- (void)ures_getFunctionalEquivalent(localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, NULL,
- "calendar", "calendar", locale.getName(), NULL, FALSE, &err);
+ ures_getFunctionalEquivalent(
+ localeWithCalendarKey,
+ ULOC_LOCALE_IDENTIFIER_CAPACITY,
+ NULL,
+ "calendar",
+ "calendar",
+ locale.getName(),
+ NULL,
+ FALSE,
+ &err);
localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
// now get the calendar key value from that locale
- int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType, ULOC_KEYWORDS_CAPACITY, &err);
+ char calendarType[ULOC_KEYWORDS_CAPACITY];
+ int32_t calendarTypeLen = uloc_getKeywordValue(
+ localeWithCalendarKey,
+ "calendar",
+ calendarType,
+ ULOC_KEYWORDS_CAPACITY,
+ &err);
if (U_SUCCESS(err) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
- calendarTypeToUse = calendarType;
+ destination.clear().append(calendarType, -1, err);
+ if (U_FAILURE(err)) { return; }
}
err = U_ZERO_ERROR;
}
- calBundle = ures_getByKeyWithFallback(rb, DT_DateTimeCalendarTag, NULL, &err);
- calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &err);
+}
- key=NULL;
- int32_t dtCount=0;
- patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimePatternsTag, NULL, &err);
- while (U_SUCCESS(err)) {
- rbPattern = ures_getNextUnicodeString(patBundle, &key, &err);
- dtCount++;
- if (rbPattern.length()==0 ) {
- break; // no more pattern
- }
- else {
- if (dtCount==9) {
- setDateTimeFormat(rbPattern);
- } else if (dtCount==4) { // short time format
- // set fDefaultHourFormatChar to the hour format character from this pattern
- int32_t tfIdx, tfLen = rbPattern.length();
- UBool ignoreChars = FALSE;
- for (tfIdx = 0; tfIdx < tfLen; tfIdx++) {
- UChar tfChar = rbPattern.charAt(tfIdx);
- if ( tfChar == SINGLE_QUOTE ) {
- ignoreChars = !ignoreChars; // toggle (handle quoted literals & '' for single quote)
- } else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != NULL ) {
- fDefaultHourFormatChar = tfChar;
- break;
- }
- }
- }
+void
+DateTimePatternGenerator::consumeShortTimePattern(const UnicodeString& shortTimePattern,
+ UErrorCode& status) {
+
+ // set fDefaultHourFormatChar to the hour format character from this pattern
+ int32_t tfIdx, tfLen = shortTimePattern.length();
+ UBool ignoreChars = FALSE;
+ for (tfIdx = 0; tfIdx < tfLen; tfIdx++) {
+ UChar tfChar = shortTimePattern.charAt(tfIdx);
+ if ( tfChar == SINGLE_QUOTE ) {
+ ignoreChars = !ignoreChars; // toggle (handle quoted literals & '' for single quote)
+ } else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != NULL ) {
+ fDefaultHourFormatChar = tfChar;
+ break;
}
}
- ures_close(patBundle);
- err = U_ZERO_ERROR;
- patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimeAppendItemsTag, NULL, &err);
- key=NULL;
- UnicodeString itemKey;
- while (U_SUCCESS(err)) {
- rbPattern = ures_getNextUnicodeString(patBundle, &key, &err);
- if (rbPattern.length()==0 ) {
- break; // no more pattern
- }
- else {
- setAppendItemFormat(getAppendFormatNumber(key), rbPattern);
+ // HACK for hh:ss
+ hackTimes(shortTimePattern, status);
+}
+
+struct DateTimePatternGenerator::AppendItemFormatsSink : public ResourceSink {
+
+ // Destination for data, modified via setters.
+ DateTimePatternGenerator& dtpg;
+
+ AppendItemFormatsSink(DateTimePatternGenerator& _dtpg) : dtpg(_dtpg) {}
+ virtual ~AppendItemFormatsSink();
+
+ virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
+ UErrorCode &errorCode) {
+ ResourceTable itemsTable = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ for (int32_t i = 0; itemsTable.getKeyAndValue(i, key, value); ++i) {
+ UDateTimePatternField field = dtpg.getAppendFormatNumber(key);
+ if (field == UDATPG_FIELD_COUNT) { continue; }
+ const UnicodeString& valueStr = value.getUnicodeString(errorCode);
+ if (dtpg.getAppendItemFormat(field).isEmpty() && !valueStr.isEmpty()) {
+ dtpg.setAppendItemFormat(field, valueStr);
+ }
}
}
- ures_close(patBundle);
- key=NULL;
- err = U_ZERO_ERROR;
- fBundle = ures_getByKeyWithFallback(rb, DT_DateTimeFieldsTag, NULL, &err);
- for (i=0; i<MAX_RESOURCE_FIELD; ++i) {
- err = U_ZERO_ERROR;
- patBundle = ures_getByKeyWithFallback(fBundle, Resource_Fields[i], NULL, &err);
- fieldBundle = ures_getByKeyWithFallback(patBundle, "dn", NULL, &err);
- rbPattern = ures_getNextUnicodeString(fieldBundle, &key, &err);
- ures_close(fieldBundle);
- ures_close(patBundle);
- if (rbPattern.length()==0 ) {
- continue;
- }
- else {
- setAppendItemName(getAppendNameNumber(Resource_Fields[i]), rbPattern);
+ void fillInMissing() {
+ UnicodeString defaultItemFormat(TRUE, UDATPG_ItemFormat, UPRV_LENGTHOF(UDATPG_ItemFormat)-1); // Read-only alias.
+ for (int32_t i = 0; i < UDATPG_FIELD_COUNT; i++) {
+ UDateTimePatternField field = (UDateTimePatternField)i;
+ if (dtpg.getAppendItemFormat(field).isEmpty()) {
+ dtpg.setAppendItemFormat(field, defaultItemFormat);
+ }
}
}
- ures_close(fBundle);
+};
- // add available formats
- UBool firstTimeThrough = TRUE;
- err = U_ZERO_ERROR;
- initHashtable(err);
- UBool override = TRUE;
- while (TRUE) {
- // At the start of the loop:
- // - rb is the open resource bundle for the current locale being processed,
- // whose actual name is in curLocaleName.
- // - if U_SUCCESS(err), then calBundle and calTypeBundle are open;
- // process contents of calTypeBundle, then close calBundle and calTypeBundle.
- if (U_SUCCESS(err)) {
- // process contents of calTypeBundle
- patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimeAvailableFormatsTag, NULL, &err);
- if (U_SUCCESS(err)) {
- int32_t numberKeys = ures_getSize(patBundle);
- int32_t len;
- const UChar *retPattern;
- key=NULL;
-#if defined(U_USE_ASCII_BUNDLE_ITERATOR)
- UResourceBundleAIterator aiter;
- ures_a_open(&aiter, patBundle, &err);
-#endif
- for(i=0; i<numberKeys; ++i) {
-#if defined(U_USE_ASCII_BUNDLE_ITERATOR)
- retPattern=ures_a_getNextString(&aiter, &len, &key, &err);
-#else
- retPattern=ures_getNextString(patBundle, &len, &key, &err);
-#endif
- UnicodeString format=UnicodeString(retPattern);
- UnicodeString retKey=UnicodeString(key, -1, US_INV);
- if ( firstTimeThrough || !isAvailableFormatSet(retKey) ) {
- setAvailableFormat(retKey, err);
- // Add pattern with its associated skeleton. Override any duplicate derived from std patterns,
- // but not a previous availableFormats entry:
- addPatternWithSkeleton(format, &retKey, override, conflictingPattern, err);
- }
+struct DateTimePatternGenerator::AppendItemNamesSink : public ResourceSink {
+
+ // Destination for data, modified via setters.
+ DateTimePatternGenerator& dtpg;
+
+ AppendItemNamesSink(DateTimePatternGenerator& _dtpg) : dtpg(_dtpg) {}
+ virtual ~AppendItemNamesSink();
+
+ virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
+ UErrorCode &errorCode) {
+ ResourceTable itemsTable = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ for (int32_t i = 0; itemsTable.getKeyAndValue(i, key, value); ++i) {
+ UDateTimePatternField field = dtpg.getAppendNameNumber(key);
+ if (field == UDATPG_FIELD_COUNT) { continue; }
+ ResourceTable detailsTable = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ for (int32_t j = 0; detailsTable.getKeyAndValue(j, key, value); ++j) {
+ if (uprv_strcmp(key, "dn") != 0) { continue; }
+ const UnicodeString& valueStr = value.getUnicodeString(errorCode);
+ if (dtpg.getAppendItemName(field).isEmpty() && !valueStr.isEmpty()) {
+ dtpg.setAppendItemName(field, valueStr);
}
-#if defined(U_USE_ASCII_BUNDLE_ITERATOR)
- ures_a_close(&aiter);
-#endif
- ures_close(patBundle);
+ break;
}
- firstTimeThrough = FALSE;
- // close calBundle and calTypeBundle
- ures_close(calTypeBundle);
- ures_close(calBundle);
- }
- if (uprv_strcmp(curLocaleName,"root")==0 || uprv_strlen(curLocaleName)==0) {
- // we just finished handling root, nothing more to check
- ures_close(rb);
- break;
}
- // Find the name of the appropriate parent locale (from %%Parent if present, else
- // uloc_getParent on the actual locale name)
- // (It would be nice to have a ures function that did this...)
- err = U_ZERO_ERROR;
- char parentLocale[ULOC_FULLNAME_CAPACITY];
- int32_t locNameLen;
- const UChar * parentUName = ures_getStringByKey(rb, "%%Parent", &locNameLen, &err);
- if (U_SUCCESS(err) && err != U_USING_FALLBACK_WARNING && locNameLen < ULOC_FULLNAME_CAPACITY) {
- u_UCharsToChars(parentUName, parentLocale, locNameLen + 1);
- } else {
- err = U_ZERO_ERROR;
- uloc_getParent(curLocaleName, parentLocale, ULOC_FULLNAME_CAPACITY, &err);
- if (U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
- // just fallback to root, since we are not already there
- parentLocale[0] = 0;
- err = U_ZERO_ERROR;
+ }
+
+ void fillInMissing() {
+ for (int32_t i = 0; i < UDATPG_FIELD_COUNT; i++) {
+ UDateTimePatternField field = (UDateTimePatternField)i;
+ UnicodeString& valueStr = dtpg.getMutableAppendItemName(field);
+ if (valueStr.isEmpty()) {
+ valueStr = CAP_F;
+ U_ASSERT(i < 20);
+ if (i < 10) {
+ // F0, F1, ..., F9
+ valueStr += (UChar)(i+0x30);
+ } else {
+ // F10, F11, ...
+ valueStr += (UChar)0x31;
+ valueStr += (UChar)(i-10 + 0x30);
+ }
+ // NUL-terminate for the C API.
+ valueStr.getTerminatedBuffer();
}
}
- // Close current locale bundle
- ures_close(rb);
- // And open its parent, which becomes the new current locale being processed
- rb = ures_open(NULL, parentLocale, &err);
- if ( U_FAILURE(err) ) {
- err = U_ZERO_ERROR;
- break;
- }
- // Get the name of the parent / new current locale
- curLocaleName=ures_getLocaleByType(rb, ULOC_ACTUAL_LOCALE, &err);
- if ( U_FAILURE(err) ) {
- curLocaleName = parentLocale;
- err = U_ZERO_ERROR;
- }
- if (uprv_strcmp(curLocaleName,"root")==0 || uprv_strlen(curLocaleName)==0) {
- override = FALSE;
- }
- // Open calBundle and calTypeBundle
- calBundle = ures_getByKeyWithFallback(rb, DT_DateTimeCalendarTag, NULL, &err);
- if (U_SUCCESS(err)) {
- calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &err);
- if ( U_FAILURE(err) ) {
- ures_close(calBundle);
+ }
+};
+
+struct DateTimePatternGenerator::AvailableFormatsSink : public ResourceSink {
+
+ // Destination for data, modified via setters.
+ DateTimePatternGenerator& dtpg;
+
+ // Temporary variable, required for calling addPatternWithSkeleton.
+ UnicodeString conflictingPattern;
+
+ AvailableFormatsSink(DateTimePatternGenerator& _dtpg) : dtpg(_dtpg) {}
+ virtual ~AvailableFormatsSink();
+
+ virtual void put(const char *key, ResourceValue &value, UBool isRoot,
+ UErrorCode &errorCode) {
+ ResourceTable itemsTable = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ for (int32_t i = 0; itemsTable.getKeyAndValue(i, key, value); ++i) {
+ const UnicodeString formatKey(key, -1, US_INV);
+ if (!dtpg.isAvailableFormatSet(formatKey) ) {
+ dtpg.setAvailableFormat(formatKey, errorCode);
+ // Add pattern with its associated skeleton. Override any duplicate
+ // derived from std patterns, but not a previous availableFormats entry:
+ const UnicodeString& formatValue = value.getUnicodeString(errorCode);
+ conflictingPattern.remove();
+ dtpg.addPatternWithSkeleton(formatValue, &formatKey, !isRoot, conflictingPattern, errorCode);
}
}
- // Go to the top of the loop to process contents of calTypeBundle
}
+};
- if (hackPattern.length()>0) {
- hackTimes(hackPattern, err);
- }
+// Virtual destructors must be defined out of line.
+DateTimePatternGenerator::AppendItemFormatsSink::~AppendItemFormatsSink() {}
+DateTimePatternGenerator::AppendItemNamesSink::~AppendItemNamesSink() {}
+DateTimePatternGenerator::AvailableFormatsSink::~AvailableFormatsSink() {}
+
+void
+DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& errorCode) {
+ if (U_FAILURE(errorCode)) { return; }
+ UnicodeString rbPattern, value, field;
+ CharString path;
+
+ LocalUResourceBundlePointer rb(ures_open(NULL, locale.getName(), &errorCode));
+ if (U_FAILURE(errorCode)) { return; }
+
+ CharString calendarTypeToUse; // to be filled in with the type to use, if all goes well
+ getCalendarTypeToUse(locale, calendarTypeToUse, errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+
+ // Local err to ignore resource not found exceptions
+ UErrorCode err = U_ZERO_ERROR;
+
+ // Load append item formats.
+ AppendItemFormatsSink appendItemFormatsSink(*this);
+ path.clear()
+ .append(DT_DateTimeCalendarTag, errorCode)
+ .append('/', errorCode)
+ .append(calendarTypeToUse, errorCode)
+ .append('/', errorCode)
+ .append(DT_DateTimeAppendItemsTag, errorCode); // i.e., calendar/xxx/appendItems
+ if (U_FAILURE(errorCode)) { return; }
+ ures_getAllItemsWithFallback(rb.getAlias(), path.data(), appendItemFormatsSink, err);
+ appendItemFormatsSink.fillInMissing();
+
+ // Load CLDR item names.
+ err = U_ZERO_ERROR;
+ AppendItemNamesSink appendItemNamesSink(*this);
+ ures_getAllItemsWithFallback(rb.getAlias(), DT_DateTimeFieldsTag, appendItemNamesSink, err);
+ appendItemNamesSink.fillInMissing();
+
+ // Load the available formats from CLDR.
+ err = U_ZERO_ERROR;
+ initHashtable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ AvailableFormatsSink availableFormatsSink(*this);
+ path.clear()
+ .append(DT_DateTimeCalendarTag, errorCode)
+ .append('/', errorCode)
+ .append(calendarTypeToUse, errorCode)
+ .append('/', errorCode)
+ .append(DT_DateTimeAvailableFormatsTag, errorCode); // i.e., calendar/xxx/availableFormats
+ if (U_FAILURE(errorCode)) { return; }
+ ures_getAllItemsWithFallback(rb.getAlias(), path.data(), availableFormatsSink, err);
}
void
@@ -949,7 +911,6 @@ DateTimePatternGenerator::initHashtable(UErrorCode& err) {
}
}
-
void
DateTimePatternGenerator::setAppendItemFormat(UDateTimePatternField field, const UnicodeString& value) {
appendItemFormats[field] = value;
@@ -970,7 +931,12 @@ DateTimePatternGenerator::setAppendItemName(UDateTimePatternField field, const U
}
const UnicodeString&
-DateTimePatternGenerator:: getAppendItemName(UDateTimePatternField field) const {
+DateTimePatternGenerator::getAppendItemName(UDateTimePatternField field) const {
+ return appendItemNames[field];
+}
+
+UnicodeString&
+DateTimePatternGenerator::getMutableAppendItemName(UDateTimePatternField field) {
return appendItemNames[field];
}
@@ -1096,12 +1062,15 @@ DateTimePatternGenerator::getDecimal() const {
}
void
-DateTimePatternGenerator::addCanonicalItems() {
+DateTimePatternGenerator::addCanonicalItems(UErrorCode& status) {
+ if (U_FAILURE(status)) { return; }
UnicodeString conflictingPattern;
- UErrorCode status = U_ZERO_ERROR;
for (int32_t i=0; i<UDATPG_FIELD_COUNT; i++) {
- addPattern(UnicodeString(Canonical_Items[i]), FALSE, conflictingPattern, status);
+ if (Canonical_Items[i] > 0) {
+ addPattern(UnicodeString(Canonical_Items[i]), FALSE, conflictingPattern, status);
+ }
+ if (U_FAILURE(status)) { return; }
}
}
@@ -1123,16 +1092,35 @@ DateTimePatternGenerator::setDateTimeFromCalendar(const Locale& locale, UErrorCo
int32_t resStrLen = 0;
Calendar* fCalendar = Calendar::createInstance(locale, status);
- CalendarData calData(locale, fCalendar?fCalendar->getType():NULL, status);
- UResourceBundle *dateTimePatterns = calData.getByKey(DT_DateTimePatternsTag, status);
- if (U_FAILURE(status)) return;
+ if (U_FAILURE(status)) { return; }
+
+ LocalUResourceBundlePointer calData(ures_open(NULL, locale.getBaseName(), &status));
+ ures_getByKey(calData.getAlias(), DT_DateTimeCalendarTag, calData.getAlias(), &status);
- if (ures_getSize(dateTimePatterns) <= DateFormat::kDateTime)
+ LocalUResourceBundlePointer dateTimePatterns;
+ if (fCalendar != NULL && fCalendar->getType() != NULL && *fCalendar->getType() != '\0'
+ && uprv_strcmp(fCalendar->getType(), DT_DateTimeGregorianTag) != 0) {
+ dateTimePatterns.adoptInstead(ures_getByKeyWithFallback(calData.getAlias(), fCalendar->getType(),
+ NULL, &status));
+ ures_getByKeyWithFallback(dateTimePatterns.getAlias(), DT_DateTimePatternsTag,
+ dateTimePatterns.getAlias(), &status);
+ }
+
+ if (dateTimePatterns.isNull() || status == U_MISSING_RESOURCE_ERROR) {
+ status = U_ZERO_ERROR;
+ dateTimePatterns.adoptInstead(ures_getByKeyWithFallback(calData.getAlias(), DT_DateTimeGregorianTag,
+ dateTimePatterns.orphan(), &status));
+ ures_getByKeyWithFallback(dateTimePatterns.getAlias(), DT_DateTimePatternsTag,
+ dateTimePatterns.getAlias(), &status);
+ }
+ if (U_FAILURE(status)) { return; }
+
+ if (ures_getSize(dateTimePatterns.getAlias()) <= DateFormat::kDateTime)
{
status = U_INVALID_FORMAT_ERROR;
return;
}
- resStr = ures_getStringByIndex(dateTimePatterns, (int32_t)DateFormat::kDateTime, &resStrLen, &status);
+ resStr = ures_getStringByIndex(dateTimePatterns.getAlias(), (int32_t)DateFormat::kDateTime, &resStrLen, &status);
setDateTimeFormat(UnicodeString(TRUE, resStr, resStrLen));
delete fCalendar;
@@ -1324,8 +1312,8 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern,
}
if ((flags & kDTPGFixFractionalSeconds) != 0 && typeValue == UDATPG_SECOND_FIELD) {
- UnicodeString newField=dtMatcher->skeleton.original[UDATPG_FRACTIONAL_SECOND_FIELD];
- field = field + decimal + newField;
+ field += decimal;
+ dtMatcher->skeleton.original.appendFieldTo(UDATPG_FRACTIONAL_SECOND_FIELD, field);
} else if (dtMatcher->skeleton.type[typeValue]!=0) {
// Here:
// - "reqField" is the field from the originally requested skeleton, with length
@@ -1349,9 +1337,9 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern,
// a) The length of the field in the skeleton (skelFieldLen) is equal to reqFieldLen.
// b) The pattern field is numeric and the skeleton field is not, or vice versa.
- UnicodeString reqField = dtMatcher->skeleton.original[typeValue];
- int32_t reqFieldLen = reqField.length();
- if (reqField.charAt(0) == CAP_E && reqFieldLen < 3)
+ UChar reqFieldChar = dtMatcher->skeleton.original.getFieldChar(typeValue);
+ int32_t reqFieldLen = dtMatcher->skeleton.original.getFieldLength(typeValue);
+ if (reqFieldChar == CAP_E && reqFieldLen < 3)
reqFieldLen = 3; // 1-3 for E are equivalent to 3 for c,e
int32_t adjFieldLen = reqFieldLen;
if ( (typeValue==UDATPG_HOUR_FIELD && (options & UDATPG_MATCH_HOUR_FIELD_LENGTH)==0) ||
@@ -1359,8 +1347,7 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern,
(typeValue==UDATPG_SECOND_FIELD && (options & UDATPG_MATCH_SECOND_FIELD_LENGTH)==0) ) {
adjFieldLen = field.length();
} else if (specifiedSkeleton) {
- UnicodeString skelField = specifiedSkeleton->original[typeValue];
- int32_t skelFieldLen = skelField.length();
+ int32_t skelFieldLen = specifiedSkeleton->original.getFieldLength(typeValue);
UBool patFieldIsNumeric = (row->type > 0);
UBool skelFieldIsNumeric = (specifiedSkeleton->type[typeValue] > 0);
if (skelFieldLen == reqFieldLen || (patFieldIsNumeric && !skelFieldIsNumeric) || (skelFieldIsNumeric && !patFieldIsNumeric)) {
@@ -1368,9 +1355,12 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern,
adjFieldLen = field.length();
}
}
- UChar c = (typeValue!= UDATPG_HOUR_FIELD && typeValue!= UDATPG_MONTH_FIELD &&
- typeValue!= UDATPG_WEEKDAY_FIELD && (typeValue!= UDATPG_YEAR_FIELD || reqField.charAt(0)==CAP_Y))?
- reqField.charAt(0): field.charAt(0);
+ UChar c = (typeValue!= UDATPG_HOUR_FIELD
+ && typeValue!= UDATPG_MONTH_FIELD
+ && typeValue!= UDATPG_WEEKDAY_FIELD
+ && (typeValue!= UDATPG_YEAR_FIELD || reqFieldChar==CAP_Y))
+ ? reqFieldChar
+ : field.charAt(0);
if (typeValue == UDATPG_HOUR_FIELD && (flags & kDTPGSkeletonUsesCapJ) != 0) {
c = fDefaultHourFormatChar;
}
@@ -1733,36 +1723,19 @@ PatternMap::getPatternFromSkeleton(PtnSkeleton& skeleton, const PtnSkeleton** sp
}
// find boot entry
- UChar baseChar='\0';
- for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
- if (skeleton.baseOriginal[i].length() !=0 ) {
- baseChar = skeleton.baseOriginal[i].charAt(0);
- break;
- }
- }
-
+ UChar baseChar = skeleton.getFirstChar();
if ((curElem=getHeader(baseChar))==NULL) {
return NULL; // no match
}
do {
- int32_t i=0;
+ UBool equal;
if (specifiedSkeletonPtr != NULL) { // called from DateTimePatternGenerator::getBestRaw or addPattern, use original
- for (i=0; i<UDATPG_FIELD_COUNT; ++i) {
- if (curElem->skeleton->original[i].compare(skeleton.original[i]) != 0 )
- {
- break;
- }
- }
+ equal = curElem->skeleton->original == skeleton.original;
} else { // called from DateTimePatternGenerator::getRedundants, use baseOriginal
- for (i=0; i<UDATPG_FIELD_COUNT; ++i) {
- if (curElem->skeleton->baseOriginal[i].compare(skeleton.baseOriginal[i]) != 0 )
- {
- break;
- }
- }
+ equal = curElem->skeleton->baseOriginal == skeleton.baseOriginal;
}
- if (i == UDATPG_FIELD_COUNT) {
+ if (equal) {
if (specifiedSkeletonPtr && curElem->skeletonWasSpecified) {
*specifiedSkeletonPtr = curElem->skeleton;
}
@@ -1866,37 +1839,35 @@ void
DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton& skeletonResult) {
int32_t i;
for (i=0; i<UDATPG_FIELD_COUNT; ++i) {
- skeletonResult.type[i]=NONE;
+ skeletonResult.type[i] = NONE;
}
fp->set(pattern);
for (i=0; i < fp->itemNumber; i++) {
- UnicodeString field = fp->items[i];
- if ( field.charAt(0) == LOW_A ) {
+ const UnicodeString& value = fp->items[i];
+ if ( value.charAt(0) == LOW_A ) {
continue; // skip 'a'
}
- if ( fp->isQuoteLiteral(field) ) {
+ if ( fp->isQuoteLiteral(value) ) {
UnicodeString quoteLiteral;
fp->getQuoteLiteral(quoteLiteral, &i);
continue;
}
- int32_t canonicalIndex = fp->getCanonicalIndex(field);
+ int32_t canonicalIndex = fp->getCanonicalIndex(value);
if (canonicalIndex < 0 ) {
continue;
}
const dtTypeElem *row = &dtTypes[canonicalIndex];
- int32_t typeValue = row->field;
- skeletonResult.original[typeValue]=field;
+ int32_t field = row->field;
+ skeletonResult.original.populate(field, value);
UChar repeatChar = row->patternChar;
int32_t repeatCount = row->minLen; // #7930 removes cap at 3
- while (repeatCount-- > 0) {
- skeletonResult.baseOriginal[typeValue] += repeatChar;
- }
- int16_t subTypeValue = row->type;
+ skeletonResult.baseOriginal.populate(field, repeatChar, repeatCount);
+ int16_t subField = row->type;
if ( row->type > 0) {
- subTypeValue += field.length();
+ subField += value.length();
}
- skeletonResult.type[typeValue] = subTypeValue;
+ skeletonResult.type[field] = subField;
}
copyFrom(skeletonResult);
}
@@ -1904,23 +1875,13 @@ DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton
void
DateTimeMatcher::getBasePattern(UnicodeString &result ) {
result.remove(); // Reset the result first.
- for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i ) {
- if (skeleton.baseOriginal[i].length()!=0) {
- result += skeleton.baseOriginal[i];
- }
- }
+ skeleton.baseOriginal.appendTo(result);
}
UnicodeString
DateTimeMatcher::getPattern() {
UnicodeString result;
-
- for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i ) {
- if (skeleton.original[i].length()!=0) {
- result += skeleton.original[i];
- }
- }
- return result;
+ return skeleton.original.appendTo(result);
}
int32_t
@@ -1953,34 +1914,19 @@ DateTimeMatcher::getDistance(const DateTimeMatcher& other, int32_t includeMask,
void
DateTimeMatcher::copyFrom(const PtnSkeleton& newSkeleton) {
- for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
- this->skeleton.type[i]=newSkeleton.type[i];
- this->skeleton.original[i]=newSkeleton.original[i];
- this->skeleton.baseOriginal[i]=newSkeleton.baseOriginal[i];
- }
+ skeleton.copyFrom(newSkeleton);
}
void
DateTimeMatcher::copyFrom() {
// same as clear
- for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
- this->skeleton.type[i]=0;
- this->skeleton.original[i].remove();
- this->skeleton.baseOriginal[i].remove();
- }
+ skeleton.clear();
}
UBool
DateTimeMatcher::equals(const DateTimeMatcher* other) const {
- if (other==NULL) {
- return FALSE;
- }
- for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
- if (this->skeleton.original[i]!=other->skeleton.original[i] ) {
- return FALSE;
- }
- }
- return TRUE;
+ if (other==NULL) { return FALSE; }
+ return skeleton.original == other->skeleton.original;
}
int32_t
@@ -2074,7 +2020,7 @@ FormatParser::getCanonicalIndex(const UnicodeString& s, UBool strict) {
}
int32_t i = 0;
int32_t bestRow = -1;
- while (dtTypes[i].patternChar != '\0') {
+ while (dtTypes[i].patternChar != 0x0000) {
if ( dtTypes[i].patternChar != ch ) {
++i;
continue;
@@ -2246,52 +2192,116 @@ PatternMapIterator::next() {
return *matcher;
}
-PtnSkeleton::PtnSkeleton() {
+
+SkeletonFields::SkeletonFields() {
+ // Set initial values to zero
+ clear();
}
+void SkeletonFields::clear() {
+ uprv_memset(chars, 0, sizeof(chars));
+ uprv_memset(lengths, 0, sizeof(lengths));
+}
-PtnSkeleton::PtnSkeleton(const PtnSkeleton& other) {
- for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
- this->type[i]=other.type[i];
- this->original[i]=other.original[i];
- this->baseOriginal[i]=other.baseOriginal[i];
+void SkeletonFields::copyFrom(const SkeletonFields& other) {
+ uprv_memcpy(chars, other.chars, sizeof(chars));
+ uprv_memcpy(lengths, other.lengths, sizeof(lengths));
+}
+
+void SkeletonFields::clearField(int32_t field) {
+ chars[field] = 0;
+ lengths[field] = 0;
+}
+
+UChar SkeletonFields::getFieldChar(int32_t field) const {
+ return chars[field];
+}
+
+int32_t SkeletonFields::getFieldLength(int32_t field) const {
+ return lengths[field];
+}
+
+void SkeletonFields::populate(int32_t field, const UnicodeString& value) {
+ populate(field, value.charAt(0), value.length());
+}
+
+void SkeletonFields::populate(int32_t field, UChar ch, int32_t length) {
+ chars[field] = (int8_t) ch;
+ lengths[field] = (int8_t) length;
+}
+
+UBool SkeletonFields::isFieldEmpty(int32_t field) const {
+ return lengths[field] == 0;
+}
+
+UnicodeString& SkeletonFields::appendTo(UnicodeString& string) const {
+ for (int32_t i = 0; i < UDATPG_FIELD_COUNT; ++i) {
+ appendFieldTo(i, string);
}
+ return string;
}
-UBool
-PtnSkeleton::equals(const PtnSkeleton& other) {
- for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
- if ( (type[i]!= other.type[i]) ||
- (original[i]!=other.original[i]) ||
- (baseOriginal[i]!=other.baseOriginal[i]) ) {
- return FALSE;
+UnicodeString& SkeletonFields::appendFieldTo(int32_t field, UnicodeString& string) const {
+ UChar ch(chars[field]);
+ int32_t length = (int32_t) lengths[field];
+
+ for (int32_t i=0; i<length; i++) {
+ string += ch;
+ }
+ return string;
+}
+
+UChar SkeletonFields::getFirstChar() const {
+ for (int32_t i = 0; i < UDATPG_FIELD_COUNT; ++i) {
+ if (lengths[i] != 0) {
+ return chars[i];
}
}
- return TRUE;
+ return '\0';
+}
+
+
+PtnSkeleton::PtnSkeleton() {
+}
+
+PtnSkeleton::PtnSkeleton(const PtnSkeleton& other) {
+ copyFrom(other);
+}
+
+void PtnSkeleton::copyFrom(const PtnSkeleton& other) {
+ uprv_memcpy(type, other.type, sizeof(type));
+ original.copyFrom(other.original);
+ baseOriginal.copyFrom(other.baseOriginal);
+}
+
+void PtnSkeleton::clear() {
+ uprv_memset(type, 0, sizeof(type));
+ original.clear();
+ baseOriginal.clear();
+}
+
+UBool
+PtnSkeleton::equals(const PtnSkeleton& other) const {
+ return (original == other.original)
+ && (baseOriginal == other.baseOriginal)
+ && (uprv_memcmp(type, other.type, sizeof(type)) == 0);
}
UnicodeString
-PtnSkeleton::getSkeleton() {
+PtnSkeleton::getSkeleton() const {
UnicodeString result;
-
- for(int32_t i=0; i< UDATPG_FIELD_COUNT; ++i) {
- if (original[i].length()!=0) {
- result += original[i];
- }
- }
- return result;
+ return original.appendTo(result);
}
UnicodeString
-PtnSkeleton::getBaseSkeleton() {
+PtnSkeleton::getBaseSkeleton() const {
UnicodeString result;
+ return baseOriginal.appendTo(result);
+}
- for(int32_t i=0; i< UDATPG_FIELD_COUNT; ++i) {
- if (baseOriginal[i].length()!=0) {
- result += baseOriginal[i];
- }
- }
- return result;
+UChar
+PtnSkeleton::getFirstChar() const {
+ return baseOriginal.getFirstChar();
}
PtnSkeleton::~PtnSkeleton() {