/* Function: EnumEraNames Enumerates all the era names of the specified locale and calendar, invoking the callback function for each era name. */ bool EnumEraNames(Locale& locale, CalendarId calendarId, CalendarDataType dataType, EnumCalendarInfoCallback callback, const void* context) { UErrorCode err = U_ZERO_ERROR; const char* calendarName = GetCalendarName(calendarId); DateFormatSymbols dateFormatSymbols(locale, calendarName, err); if (U_FAILURE(err)) return false; int32_t eraNameCount; const UnicodeString* eraNames; if (dataType == EraNames) { eraNames = dateFormatSymbols.getEras(eraNameCount); } else if (dataType == AbbrevEraNames) { eraNames = dateFormatSymbols.getNarrowEras(eraNameCount); } else { assert(false); return false; } return EnumCalendarArray(eraNames, eraNameCount, callback, context); }
/* Function: GetNativeCalendarName Gets the native calendar name. */ CalendarDataResult GetNativeCalendarName(Locale& locale, CalendarId calendarId, UChar* nativeName, int32_t stringCapacity) { LocalPointer<LocaleDisplayNames> displayNames(LocaleDisplayNames::createInstance(locale)); UnicodeString calendarName; displayNames->keyValueDisplayName("calendar", GetCalendarName(calendarId), calendarName); UErrorCode err = U_ZERO_ERROR; calendarName.extract(nativeName, stringCapacity, err); return GetCalendarDataResult(err); }
/* Function: GetNativeCalendarName Gets the native calendar name. */ static ResultCode GetNativeCalendarName(const char* locale, CalendarId calendarId, UChar* nativeName, int32_t stringCapacity) { UErrorCode err = U_ZERO_ERROR; ULocaleDisplayNames* pDisplayNames = uldn_open(locale, ULDN_STANDARD_NAMES, &err); uldn_keyValueDisplayName(pDisplayNames, "calendar", GetCalendarName(calendarId), nativeName, stringCapacity, &err); uldn_close(pDisplayNames); return GetResultCode(err); }
/* Function: EnumMonths Enumerates all the month names of the specified context and width, invoking the callback function for each month name. */ bool EnumMonths( Locale& locale, CalendarId calendarId, DateFormatSymbols::DtContextType dtContext, DateFormatSymbols::DtWidthType dtWidth, EnumCalendarInfoCallback callback, const void* context) { UErrorCode err = U_ZERO_ERROR; DateFormatSymbols dateFormatSymbols(locale, GetCalendarName(calendarId), err); if (U_FAILURE(err)) return false; int32_t monthsCount; const UnicodeString* monthNames = dateFormatSymbols.getMonths(monthsCount, dtContext, dtWidth); return EnumCalendarArray(monthNames, monthsCount, callback, context); }
/* Function: EnumWeekdays Enumerates all the weekday names of the specified context and width, invoking the callback function for each weekday name. */ bool EnumWeekdays( Locale& locale, CalendarId calendarId, DateFormatSymbols::DtContextType dtContext, DateFormatSymbols::DtWidthType dtWidth, EnumCalendarInfoCallback callback, const void* context) { UErrorCode err = U_ZERO_ERROR; DateFormatSymbols dateFormatSymbols(locale, GetCalendarName(calendarId), err); if (U_FAILURE(err)) return false; int32_t daysCount; const UnicodeString* dayNames = dateFormatSymbols.getWeekdays(daysCount, dtContext, dtWidth); // ICU returns an empty string for the first/zeroth element in the weekdays array. // So skip the first element. dayNames++; daysCount--; return EnumCalendarArray(dayNames, daysCount, callback, context); }
/* Function: EnumAbbrevEraNames Enumerates all the abbreviated era names of the specified locale and calendar, invoking the callback function for each era name. */ static int32_t EnumAbbrevEraNames(const char* locale, CalendarId calendarId, EnumCalendarInfoCallback callback, const void* context) { // The C-API for ICU provides no way to get at the abbreviated era names for a calendar (so we can't use EnumSymbols // here). Instead we will try to walk the ICU resource tables directly and fall back to regular era names if can't // find good data. char localeNameBuf[ULOC_FULLNAME_CAPACITY]; char parentNameBuf[ULOC_FULLNAME_CAPACITY]; char* localeNamePtr = localeNameBuf; char* parentNamePtr = parentNameBuf; strncpy(localeNamePtr, locale, ULOC_FULLNAME_CAPACITY); while (TRUE) { UErrorCode status = U_ZERO_ERROR; const char* name = GetCalendarName(calendarId); UResourceBundle* rootResBundle = ures_open(NULL, localeNamePtr, &status); UResourceBundle* calResBundle = ures_getByKey(rootResBundle, "calendar", NULL, &status); UResourceBundle* targetCalResBundle = ures_getByKey(calResBundle, name, NULL, &status); UResourceBundle* erasColResBundle = ures_getByKey(targetCalResBundle, "eras", NULL, &status); UResourceBundle* erasResBundle = ures_getByKey(erasColResBundle, "narrow", NULL, &status); if (U_SUCCESS(status)) { EnumUResourceBundle(erasResBundle, callback, context); CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); return TRUE; } // Couldn't find the data we need for this locale, we should fallback. if (localeNameBuf[0] == 0x0) { CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); // We are already at the root locale so there is nothing to fall back to, just use the regular eras. break; } uloc_getParent(localeNamePtr, parentNamePtr, ULOC_FULLNAME_CAPACITY, &status); if (U_FAILURE(status)) { CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); // Something bad happened getting the parent name, bail out. break; } // Swap localeNamePtr and parentNamePtr, parentNamePtr is what we want to use on the next iteration // and we can use the current localeName as scratch space if we have to fall back on that // iteration. char* temp = localeNamePtr; localeNamePtr = parentNamePtr; parentNamePtr = temp; CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); } // Walking the resource bundles didn't work, just use the regular eras. return EnumSymbols(locale, calendarId, UDAT_ERAS, 0, callback, context); }
/* Function: EnumSymbols Enumerates all of the symbols of a type for a locale and calendar and invokes a callback for each value. */ static int32_t EnumSymbols(const char* locale, CalendarId calendarId, UDateFormatSymbolType type, int32_t startIndex, EnumCalendarInfoCallback callback, const void* context) { UErrorCode err = U_ZERO_ERROR; UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) return FALSE; char localeWithCalendarName[ULOC_FULLNAME_CAPACITY]; strncpy(localeWithCalendarName, locale, ULOC_FULLNAME_CAPACITY); uloc_setKeywordValue("calendar", GetCalendarName(calendarId), localeWithCalendarName, ULOC_FULLNAME_CAPACITY, &err); UCalendar* pCalendar = ucal_open(NULL, 0, localeWithCalendarName, UCAL_DEFAULT, &err); if (U_FAILURE(err)) { udat_close(pFormat); return FALSE; } udat_setCalendar(pFormat, pCalendar); int32_t symbolCount = udat_countSymbols(pFormat, type); UChar stackSymbolBuf[100]; UChar* symbolBuf; for (int32_t i = startIndex; U_SUCCESS(err) && i < symbolCount; i++) { UErrorCode ignore = U_ZERO_ERROR; int symbolLen = udat_getSymbols(pFormat, type, i, NULL, 0, &ignore) + 1; if (symbolLen <= sizeof(stackSymbolBuf) / sizeof(stackSymbolBuf[0])) { symbolBuf = stackSymbolBuf; } else { symbolBuf = calloc(symbolLen, sizeof(UChar)); if (symbolBuf == NULL) { err = U_MEMORY_ALLOCATION_ERROR; break; } } udat_getSymbols(pFormat, type, i, symbolBuf, symbolLen, &err); if (U_SUCCESS(err)) { callback(symbolBuf, context); } if (symbolBuf != stackSymbolBuf) { free(symbolBuf); } } udat_close(pFormat); ucal_close(pCalendar); return UErrorCodeToBool(err); }