|
39 | 39 | #include "cmemory.h"
|
40 | 40 | #include "cstring.h"
|
41 | 41 | #include "charstr.h"
|
| 42 | +#include "erarules.h" |
42 | 43 | #include "dt_impl.h"
|
43 | 44 | #include "locbased.h"
|
44 | 45 | #include "gregoimp.h"
|
@@ -1776,50 +1777,8 @@ struct CalendarDataSink : public ResourceSink {
|
1776 | 1777 | arraySizes.puti(path, dataArraySize, errorCode);
|
1777 | 1778 | if (U_FAILURE(errorCode)) { return; }
|
1778 | 1779 | } else if (value.getType() == URES_TABLE) {
|
1779 |
| - // We might have an eras table that is replacing an eras leaf array |
1780 |
| - if (path.startsWith(u"eras", 4)) { |
1781 |
| - // path is one of eras/wide, eras/abbreviated, eras/narrow |
1782 |
| - ResourceTable rDataTable = value.getTable(errorCode); |
1783 |
| - int32_t dataTableSize = rDataTable.getSize(); |
1784 |
| - UVector dataList(uprv_deleteUObject, uhash_compareUnicodeString, dataTableSize, errorCode); |
1785 |
| - if (U_FAILURE(errorCode)) { return; } |
1786 |
| - // Expand the UVector as necessary to have index from 0 up to the max |
1787 |
| - // eraCode, and fill in the slots for the eras defined in the resource data |
1788 |
| - // (filling in empty strings for other eras as we expand, since they would |
1789 |
| - // otherwise not get set to anything in particular such as null). |
1790 |
| - for (int32_t dataTableIndex = 0; dataTableIndex < dataTableSize; dataTableIndex++) { |
1791 |
| - rDataTable.getKeyAndValue(dataTableIndex, key, value); |
1792 |
| - int32_t listIndex = uprv_strtol(key, nullptr, 10); |
1793 |
| - if (listIndex + 1 > dataList.size()) { |
1794 |
| - dataList.ensureCapacity(listIndex + 1, errorCode); // needed only to minimize expansions |
1795 |
| - if (U_FAILURE(errorCode)) { return; } |
1796 |
| - // Fill in empty strings for all added slots (else they are undefined) |
1797 |
| - while (dataList.size() < listIndex + 1) { |
1798 |
| - LocalPointer<UnicodeString> emptyString(new UnicodeString(), errorCode); |
1799 |
| - dataList.adoptElement(emptyString.orphan(), errorCode); |
1800 |
| - } |
1801 |
| - } |
1802 |
| - // Now set the eraName that we just read |
1803 |
| - LocalPointer<UnicodeString> eraName((value.getType() == URES_STRING) ? |
1804 |
| - new UnicodeString(value.getUnicodeString(errorCode)) : new UnicodeString(), errorCode); |
1805 |
| - if (U_FAILURE(errorCode)) { return; } |
1806 |
| - dataList.setElementAt(eraName.orphan(), listIndex); |
1807 |
| - } |
1808 |
| - // Now convert to array running from era code 0 to the max era we have data for, fill |
1809 |
| - // in from the UVector |
1810 |
| - int32_t dataArraySize = dataList.size(); |
1811 |
| - LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode); |
1812 |
| - // Fill out dataArray from dataList (dataList.toArray did not seem to work as expected) |
1813 |
| - for (int32_t dataArrayIndex = 0; dataArrayIndex < dataArraySize; dataArrayIndex++) { |
1814 |
| - dataArray[dataArrayIndex] = std::move(*(reinterpret_cast<UnicodeString *>(dataList.elementAt(dataArrayIndex)))); |
1815 |
| - } |
1816 |
| - // Save array... |
1817 |
| - arrays.put(path, dataArray.orphan(), errorCode); |
1818 |
| - arraySizes.puti(path, dataArraySize, errorCode); |
1819 |
| - } else { |
1820 |
| - // We are not on a leaf, recursively process the subtable. |
1821 |
| - processResource(path, key, value, errorCode); |
1822 |
| - } |
| 1780 | + // We are not on a leaf, recursively process the subtable. |
| 1781 | + processResource(path, key, value, errorCode); |
1823 | 1782 | if (U_FAILURE(errorCode)) { return; }
|
1824 | 1783 | }
|
1825 | 1784 |
|
@@ -1944,6 +1903,51 @@ initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharSt
|
1944 | 1903 | }
|
1945 | 1904 | }
|
1946 | 1905 |
|
| 1906 | +static void |
| 1907 | +initEras(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, const UResourceBundle *ctebPtr, const char* eraWidth, int32_t maxEra, UErrorCode &status) { |
| 1908 | + if (U_SUCCESS(status)) { |
| 1909 | + length = 0; |
| 1910 | + UnicodeString keyUString(key.data(), -1, US_INV); |
| 1911 | + Hashtable *eraNamesTable = static_cast<Hashtable*>(sink.maps.get(keyUString)); |
| 1912 | + |
| 1913 | + if (eraNamesTable != nullptr) { |
| 1914 | + UErrorCode resStatus = U_ZERO_ERROR; |
| 1915 | + LocalUResourceBundlePointer ctewb(ures_getByKeyWithFallback(ctebPtr, eraWidth, nullptr, &resStatus)); |
| 1916 | + const UResourceBundle *ctewbPtr = (U_SUCCESS(resStatus))? ctewb.getAlias() : nullptr; |
| 1917 | + *field = new UnicodeString[maxEra + 1]; |
| 1918 | + if (*field == nullptr) { |
| 1919 | + status = U_MEMORY_ALLOCATION_ERROR; |
| 1920 | + return; |
| 1921 | + } |
| 1922 | + length = maxEra + 1; |
| 1923 | + for (int32_t eraCode = 0; eraCode <= maxEra; eraCode++) { |
| 1924 | + char eraCodeStr[12]; // T_CString_integerToString is documented to generate at most 12 bytes including nul terminator |
| 1925 | + int32_t eraCodeStrLen = T_CString_integerToString(eraCodeStr, eraCode, 10); |
| 1926 | + UnicodeString eraCodeKey = UnicodeString(eraCodeStr, eraCodeStrLen, US_INV); |
| 1927 | + UnicodeString *eraName = static_cast<UnicodeString*>(eraNamesTable->get(eraCodeKey)); |
| 1928 | + (*field)[eraCode].remove(); |
| 1929 | + if (eraName != nullptr) { |
| 1930 | + // Get eraName from map (created by CalendarSink) |
| 1931 | + (*field)[eraCode].fastCopyFrom(*eraName); |
| 1932 | + } else if (ctewbPtr != nullptr) { |
| 1933 | + // Try filling in missing items from parent locale(s) |
| 1934 | + resStatus = U_ZERO_ERROR; |
| 1935 | + LocalUResourceBundlePointer ctewkb(ures_getByKeyWithFallback(ctewbPtr, eraCodeStr, nullptr, &resStatus)); |
| 1936 | + if (U_SUCCESS(resStatus)) { |
| 1937 | + int32_t eraNameLen; |
| 1938 | + const UChar* eraNamePtr = ures_getString(ctewkb.getAlias(), &eraNameLen, &resStatus); |
| 1939 | + if (U_SUCCESS(resStatus)) { |
| 1940 | + (*field)[eraCode].setTo(false, eraNamePtr, eraNameLen); |
| 1941 | + } |
| 1942 | + } |
| 1943 | + } |
| 1944 | + } |
| 1945 | + return; |
| 1946 | + } |
| 1947 | + status = U_MISSING_RESOURCE_ERROR; |
| 1948 | + } |
| 1949 | +} |
| 1950 | + |
1947 | 1951 | static void
|
1948 | 1952 | initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
|
1949 | 1953 | field[index].remove();
|
@@ -2344,17 +2348,30 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
|
2344 | 2348 | validLocale = Locale(ures_getLocaleByType(cb.getAlias(), ULOC_VALID_LOCALE, &status));
|
2345 | 2349 | actualLocale = Locale(ures_getLocaleByType(cb.getAlias(), ULOC_ACTUAL_LOCALE, &status));
|
2346 | 2350 |
|
| 2351 | + // Era setup |
| 2352 | + if (type == nullptr) { |
| 2353 | + type = "gregorian"; |
| 2354 | + } |
| 2355 | + LocalPointer<EraRules> eraRules(EraRules::createInstance(type, false, status)); |
| 2356 | + int32_t maxEra = (U_SUCCESS(status))? eraRules->getMaxEraCode(): 0; |
| 2357 | + UErrorCode resStatus = U_ZERO_ERROR; |
| 2358 | + LocalUResourceBundlePointer ctpb(ures_getByKeyWithFallback(cb.getAlias(), type, nullptr, &resStatus)); |
| 2359 | + LocalUResourceBundlePointer cteb(ures_getByKeyWithFallback(ctpb.getAlias(), gErasTag, nullptr, &resStatus)); |
| 2360 | + const UResourceBundle *ctebPtr = (U_SUCCESS(resStatus))? cteb.getAlias() : nullptr; |
2347 | 2361 | // Load eras
|
2348 |
| - initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status); |
| 2362 | + initEras(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), |
| 2363 | + ctebPtr, gNamesAbbrTag, maxEra, status); |
2349 | 2364 | UErrorCode oldStatus = status;
|
2350 |
| - initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status); |
| 2365 | + initEras(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), |
| 2366 | + ctebPtr, gNamesWideTag, maxEra, status); |
2351 | 2367 | if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
|
2352 | 2368 | status = oldStatus;
|
2353 | 2369 | assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
|
2354 | 2370 | }
|
2355 | 2371 | // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
|
2356 | 2372 | oldStatus = status;
|
2357 |
| - initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status); |
| 2373 | + initEras(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), |
| 2374 | + ctebPtr, gNamesNarrowTag, maxEra, status); |
2358 | 2375 | if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
|
2359 | 2376 | status = oldStatus;
|
2360 | 2377 | assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
|
|
0 commit comments