From 50e67ce34524ba78a99af6982285211ae0d18108 Mon Sep 17 00:00:00 2001 From: Peter Edberg Date: Wed, 4 Mar 2015 00:11:53 +0000 Subject: [PATCH] ICU-11553 Add C wrapper for FieldPositionIterator & 2 udat_formatX calls to use it X-SVN-Rev: 37118 --- .gitattributes | 2 + icu4c/source/i18n/Makefile.in | 4 +- icu4c/source/i18n/i18n.vcxproj | 15 +++ icu4c/source/i18n/i18n.vcxproj.filters | 6 + icu4c/source/i18n/udat.cpp | 45 +++++++ icu4c/source/i18n/ufieldpositer.cpp | 59 +++++++++ icu4c/source/i18n/unicode/udat.h | 149 ++++++++++++++++------ icu4c/source/i18n/unicode/ufieldpositer.h | 121 ++++++++++++++++++ icu4c/source/test/cintltst/cdattst.c | 102 +++++++++++++++ 9 files changed, 464 insertions(+), 39 deletions(-) create mode 100644 icu4c/source/i18n/ufieldpositer.cpp create mode 100644 icu4c/source/i18n/unicode/ufieldpositer.h diff --git a/.gitattributes b/.gitattributes index 87b2557fb8f..2b93351a80d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -88,6 +88,8 @@ icu4c/source/extra/uconv/uconv.vcxproj -text icu4c/source/extra/uconv/uconv.vcxproj.filters -text icu4c/source/i18n/i18n.vcxproj -text icu4c/source/i18n/i18n.vcxproj.filters -text +icu4c/source/i18n/ufieldpositer.cpp -text +icu4c/source/i18n/unicode/ufieldpositer.h -text icu4c/source/io/io.vcxproj -text icu4c/source/io/io.vcxproj.filters -text icu4c/source/layout/layout.vcxproj -text diff --git a/icu4c/source/i18n/Makefile.in b/icu4c/source/i18n/Makefile.in index 8517dd50c92..bb730d6a44d 100644 --- a/icu4c/source/i18n/Makefile.in +++ b/icu4c/source/i18n/Makefile.in @@ -1,6 +1,6 @@ #****************************************************************************** # -# Copyright (C) 1998-2014, International Business Machines +# Copyright (C) 1998-2015, International Business Machines # Corporation and others. All Rights Reserved. # #****************************************************************************** @@ -91,7 +91,7 @@ wintzimpl.o windtfmt.o winnmfmt.o basictz.o dtrule.o rbtz.o tzrule.o tztrans.o v upluralrules.o plurrule.o plurfmt.o selfmt.o dtitvfmt.o dtitvinf.o udateintervalformat.o \ tmunit.o tmutamt.o tmutfmt.o currpinf.o \ uspoof.o uspoof_impl.o uspoof_build.o uspoof_conf.o uspoof_wsconf.o decfmtst.o smpdtfst.o \ -ztrans.o zrule.o vzone.o fphdlimp.o fpositer.o locdspnm.o \ +ztrans.o zrule.o vzone.o fphdlimp.o fpositer.o ufieldpositer.o locdspnm.o \ decNumber.o decContext.o alphaindex.o tznames.o tznames_impl.o tzgnames.o \ tzfmt.o compactdecimalformat.o gender.o region.o scriptset.o identifier_info.o \ uregion.o reldatefmt.o quantityformatter.o measunit.o filteredbrk.o \ diff --git a/icu4c/source/i18n/i18n.vcxproj b/icu4c/source/i18n/i18n.vcxproj index d34987efc0b..caa286e6aa8 100644 --- a/icu4c/source/i18n/i18n.vcxproj +++ b/icu4c/source/i18n/i18n.vcxproj @@ -365,6 +365,7 @@ + @@ -1421,6 +1422,20 @@ ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) copy "%(FullPath)" ..\..\include\unicode + + ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) + + + copy "%(FullPath)" ..\..\include\unicode + + ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) + copy "%(FullPath)" ..\..\include\unicode + + ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) + copy "%(FullPath)" ..\..\include\unicode + + ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) + copy "%(FullPath)" ..\..\include\unicode ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) diff --git a/icu4c/source/i18n/i18n.vcxproj.filters b/icu4c/source/i18n/i18n.vcxproj.filters index 9c518b81510..6658a482c8b 100644 --- a/icu4c/source/i18n/i18n.vcxproj.filters +++ b/icu4c/source/i18n/i18n.vcxproj.filters @@ -282,6 +282,9 @@ formatting + + formatting + formatting @@ -1134,6 +1137,9 @@ formatting + + formatting + formatting diff --git a/icu4c/source/i18n/udat.cpp b/icu4c/source/i18n/udat.cpp index 2ad49c88e21..96890cfabb1 100644 --- a/icu4c/source/i18n/udat.cpp +++ b/icu4c/source/i18n/udat.cpp @@ -22,6 +22,7 @@ #include "unicode/dtfmtsym.h" #include "unicode/ustring.h" #include "unicode/udisplaycontext.h" +#include "unicode/ufieldpositer.h" #include "cpputils.h" #include "reldtfmt.h" #include "umutex.h" @@ -269,6 +270,50 @@ udat_formatCalendar(const UDateFormat* format, return res.extract(result, resultLength, *status); } +U_CAPI int32_t U_EXPORT2 +udat_formatForFields( const UDateFormat* format, + UDate dateToFormat, + UChar* result, + int32_t resultLength, + UFieldPositionIterator* fpositer, + UErrorCode* status) +{ + if(U_FAILURE(*status)) return -1; + + UnicodeString res; + if(!(result==NULL && resultLength==0)) { + // NULL destination for pure preflighting: empty dummy string + // otherwise, alias the destination buffer + res.setTo(result, 0, resultLength); + } + + ((DateFormat*)format)->format(dateToFormat, res, (FieldPositionIterator*)fpositer, *status); + + return res.extract(result, resultLength, *status); +} + +U_CAPI int32_t U_EXPORT2 +udat_formatCalendarForFields(const UDateFormat* format, + UCalendar* calendar, + UChar* result, + int32_t resultLength, + UFieldPositionIterator* fpositer, + UErrorCode* status) +{ + if(U_FAILURE(*status)) return -1; + + UnicodeString res; + if(!(result==NULL && resultLength==0)) { + // NULL destination for pure preflighting: empty dummy string + // otherwise, alias the destination buffer + res.setTo(result, 0, resultLength); + } + + ((DateFormat*)format)->format(*(Calendar*)calendar, res, (FieldPositionIterator*)fpositer, *status); + + return res.extract(result, resultLength, *status); +} + U_CAPI UDate U_EXPORT2 udat_parse( const UDateFormat* format, const UChar* text, diff --git a/icu4c/source/i18n/ufieldpositer.cpp b/icu4c/source/i18n/ufieldpositer.cpp new file mode 100644 index 00000000000..7f8688425d6 --- /dev/null +++ b/icu4c/source/i18n/ufieldpositer.cpp @@ -0,0 +1,59 @@ +/* +***************************************************************************************** +* Copyright (C) 2015, International Business Machines +* Corporation and others. All Rights Reserved. +***************************************************************************************** +*/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/ufieldpositer.h" +#include "unicode/fpositer.h" +#include "unicode/localpointer.h" + +U_NAMESPACE_USE + + +U_CAPI UFieldPositionIterator* U_EXPORT2 +ufieldpositer_open(UErrorCode* status) +{ + if (U_FAILURE(*status)) { + return NULL; + } + FieldPositionIterator* fpositer = new FieldPositionIterator(); + if (fpositer == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + } + return (UFieldPositionIterator*)fpositer; +} + + +U_CAPI void U_EXPORT2 +ufieldpositer_close(UFieldPositionIterator *fpositer) +{ + delete (FieldPositionIterator*)fpositer; +} + + +U_CAPI int32_t U_EXPORT2 +ufieldpositer_next(UFieldPositionIterator *fpositer, + int32_t *beginIndex, int32_t *endIndex) +{ + FieldPosition fp; + int32_t field = -1; + if (((FieldPositionIterator*)fpositer)->next(fp)) { + field = fp.getField(); + if (beginIndex) { + *beginIndex = fp.getBeginIndex(); + } + if (endIndex) { + *endIndex = fp.getEndIndex(); + } + } + return field; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/unicode/udat.h b/icu4c/source/i18n/unicode/udat.h index 5add1516841..4cea93c649a 100644 --- a/icu4c/source/i18n/unicode/udat.h +++ b/icu4c/source/i18n/unicode/udat.h @@ -16,6 +16,7 @@ #include "unicode/ucal.h" #include "unicode/unum.h" #include "unicode/udisplaycontext.h" +#include "unicode/ufieldpositer.h" /** * \file * \brief C API: DateFormat @@ -945,7 +946,7 @@ udat_clone(const UDateFormat *fmt, UErrorCode *status); /** -* Format a date using an UDateFormat. +* Format a date using a UDateFormat. * The date will be formatted using the conventions specified in {@link #udat_open } * @param format The formatter to use * @param dateToFormat The date to format @@ -976,8 +977,8 @@ udat_format( const UDateFormat* format, * The date will be formatted using the conventions specified in {@link #udat_open } * @param format The formatter to use * @param calendar The calendar to format. The calendar instance might be -* mutated when fields are not fully calculated yet, although -* this function won't change the logical date and time held +* mutated if fields are not yet fully calculated, though +* the function won't change the logical date and time held * by the instance. * @param result A pointer to a buffer to receive the formatted number. * @param capacity The maximum size of result. @@ -1000,6 +1001,80 @@ udat_formatCalendar( const UDateFormat* format, int32_t capacity, UFieldPosition* position, UErrorCode* status); + +/** +* Format a date using a UDateFormat. +* The date will be formatted using the conventions specified in {@link #udat_open} +* @param format +* The formatter to use +* @param dateToFormat +* The date to format +* @param result +* A pointer to a buffer to receive the formatted number. +* @param resultLength +* The maximum size of result. +* @param fpositer +* A pointer to a UFieldPositionIterator created by {@link #ufieldpositer_open} +* (may be NULL if field position information is not needed). Any +* iteration information already present in the UFieldPositionIterator +* will be deleted, and the iterator will be reset to apply to the +* fields in the formatted string created by this function call; the +* field values provided by {@link #ufieldpositer_next} will be from the +* UDateFormatField enum. +* @param status +* A pointer to a UErrorCode to receive any errors +* @return +* The total buffer size needed; if greater than resultLength, the output was truncated. +* @see udat_parse +* @see UFieldPositionIterator +* @draft ICU 55 +*/ +U_DRAFT int32_t U_EXPORT2 +udat_formatForFields( const UDateFormat* format, + UDate dateToFormat, + UChar* result, + int32_t resultLength, + UFieldPositionIterator* fpositer, + UErrorCode* status); + +/** +* Format a date using a UDateFormat. +* The date will be formatted using the conventions specified in {@link #udat_open } +* @param format +* The formatter to use +* @param calendar +* The calendar to format. The calendar instance might be mutated if fields +* are not yet fully calculated, though the function won't change the logical +* date and time held by the instance. +* @param result +* A pointer to a buffer to receive the formatted number. +* @param capacity +* The maximum size of result. +* @param fpositer +* A pointer to a UFieldPositionIterator created by {@link #ufieldpositer_open} +* (may be NULL if field position information is not needed). Any +* iteration information already present in the UFieldPositionIterator +* will be deleted, and the iterator will be reset to apply to the +* fields in the formatted string created by this function call; the +* field values provided by {@link #ufieldpositer_next} will be from the +* UDateFormatField enum. +* @param status +* A pointer to a UErrorCode to receive any errors +* @return +* The total buffer size needed; if greater than resultLength, the output was truncated. +* @see udat_format +* @see udat_parseCalendar +* @see UFieldPositionIterator +* @draft ICU 55 +*/ +U_DRAFT int32_t U_EXPORT2 +udat_formatCalendarForFields( const UDateFormat* format, + UCalendar* calendar, + UChar* result, + int32_t capacity, + UFieldPositionIterator* fpositer, + UErrorCode* status); + #endif /* U_HIDE_DRAFT_API */ /** @@ -1341,40 +1416,40 @@ typedef enum UDateFormatSymbolType { UDAT_STANDALONE_SHORTER_WEEKDAYS #ifndef U_HIDE_DRAFT_API , - /** - * Cyclic year names (only supported for some calendars, and only for FORMAT usage; - * udat_setSymbols not supported for UDAT_CYCLIC_YEARS_WIDE) - * @draft ICU 54 - */ - UDAT_CYCLIC_YEARS_WIDE, - /** - * Cyclic year names (only supported for some calendars, and only for FORMAT usage) - * @draft ICU 54 - */ - UDAT_CYCLIC_YEARS_ABBREVIATED, - /** - * Cyclic year names (only supported for some calendars, and only for FORMAT usage; - * udat_setSymbols not supported for UDAT_CYCLIC_YEARS_NARROW) - * @draft ICU 54 - */ - UDAT_CYCLIC_YEARS_NARROW, - /** - * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage; - * udat_setSymbols not supported for UDAT_ZODIAC_NAMES_WIDE) - * @draft ICU 54 - */ - UDAT_ZODIAC_NAMES_WIDE, - /** - * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage) - * @draft ICU 54 - */ - UDAT_ZODIAC_NAMES_ABBREVIATED, - /** - * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage; - * udat_setSymbols not supported for UDAT_ZODIAC_NAMES_NARROW) - * @draft ICU 54 - */ - UDAT_ZODIAC_NAMES_NARROW + /** + * Cyclic year names (only supported for some calendars, and only for FORMAT usage; + * udat_setSymbols not supported for UDAT_CYCLIC_YEARS_WIDE) + * @draft ICU 54 + */ + UDAT_CYCLIC_YEARS_WIDE, + /** + * Cyclic year names (only supported for some calendars, and only for FORMAT usage) + * @draft ICU 54 + */ + UDAT_CYCLIC_YEARS_ABBREVIATED, + /** + * Cyclic year names (only supported for some calendars, and only for FORMAT usage; + * udat_setSymbols not supported for UDAT_CYCLIC_YEARS_NARROW) + * @draft ICU 54 + */ + UDAT_CYCLIC_YEARS_NARROW, + /** + * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage; + * udat_setSymbols not supported for UDAT_ZODIAC_NAMES_WIDE) + * @draft ICU 54 + */ + UDAT_ZODIAC_NAMES_WIDE, + /** + * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage) + * @draft ICU 54 + */ + UDAT_ZODIAC_NAMES_ABBREVIATED, + /** + * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage; + * udat_setSymbols not supported for UDAT_ZODIAC_NAMES_NARROW) + * @draft ICU 54 + */ + UDAT_ZODIAC_NAMES_NARROW #endif /* U_HIDE_DRAFT_API */ } UDateFormatSymbolType; diff --git a/icu4c/source/i18n/unicode/ufieldpositer.h b/icu4c/source/i18n/unicode/ufieldpositer.h new file mode 100644 index 00000000000..6cc9ffada49 --- /dev/null +++ b/icu4c/source/i18n/unicode/ufieldpositer.h @@ -0,0 +1,121 @@ +/* +***************************************************************************************** +* Copyright (C) 2015, International Business Machines +* Corporation and others. All Rights Reserved. +***************************************************************************************** +*/ + +#ifndef UFIELDPOSITER_H +#define UFIELDPOSITER_H + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING +#ifndef U_HIDE_DRAFT_API + +#include "unicode/localpointer.h" + +/** + * \file + * \brief C API: UFieldPositionIterator for use with format APIs. + * + * Usage: + * ufieldpositer_open creates an empty (unset) UFieldPositionIterator. + * This can be passed to format functions such as {@link #udat_formatForFields}, + * which will set it to apply to the fields in a particular formatted string. + * ufieldpositer_next can then be used to iterate over those fields, + * providing for each field its type (using values that are specific to the + * particular format type, such as date or number formats), as well as the + * start and end positions of the field in the formatted string. + * A given UFieldPositionIterator can be re-used for different format calls; + * each such call resets it to apply to that format string. + * ufieldpositer_close should be called to dispose of the UFieldPositionIterator + * when it is no longer needed. + * + * @see FieldPositionIterator + */ + +/** + * Opaque UFieldPositionIterator object for use in C. + * @draft ICU 55 + */ +struct UFieldPositionIterator; +typedef struct UFieldPositionIterator UFieldPositionIterator; /**< C typedef for struct UFieldPositionIterator. @draft ICU 55 */ + +/** + * Open a new, unset UFieldPositionIterator object. + * @param status + * A pointer to a UErrorCode to receive any errors. + * @return + * A pointer to an empty (unset) UFieldPositionIterator object, + * or NULL if an error occurred. + * @draft ICU 55 + */ +U_DRAFT UFieldPositionIterator* U_EXPORT2 +ufieldpositer_open(UErrorCode* status); + +/** + * Close a UFieldPositionIterator object. Once closed it may no longer be used. + * @param fpositer + * A pointer to the UFieldPositionIterator object to close. + * @draft ICU 55 + */ +U_DRAFT void U_EXPORT2 +ufieldpositer_close(UFieldPositionIterator *fpositer); + + +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUFieldPositionIteratorPointer + * "Smart pointer" class, closes a UFieldPositionIterator via ufieldpositer_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @draft ICU 55 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUFieldPositionIteratorPointer, UFieldPositionIterator, ufieldpositer_close); + +U_NAMESPACE_END + +#endif + +/** + * Get information for the next field in the formatted string to which this + * UFieldPositionIterator currently applies, or return FALSE if there are + * no more fields. + * @param fpositer + * A pointer to the UFieldPositionIterator object containing iteration + * state for the format fields. + * @param beginIndex + * A pointer to an int32_t to receive information about the start offset + * of the field in the formatted string (undefined if the function + * returns a negative value). May be NULL if this information is not needed. + * @param endIndex + * A pointer to an int32_t to receive information about the end offset + * of the field in the formatted string (undefined if the function + * returns a negative value). May be NULL if this information is not needed. + * @return + * The field type (non-negative value), or a negative value if there are + * no more fields for which to provide information. If negative, then any + * values pointed to by beginIndex and endIndex are undefined. + * + * The values for field type depend on what type of formatter the + * UFieldPositionIterator has been set by; for a date formatter, the + * values from the UDateFormatField enum. For more information, see the + * descriptions of format functions that take a UFieldPositionIterator* + * parameter, such as {@link #udat_formatForFields}. + * + * @draft ICU 55 + */ +U_DRAFT int32_t U_EXPORT2 +ufieldpositer_next(UFieldPositionIterator *fpositer, + int32_t *beginIndex, int32_t *endIndex); + +#endif /* U_HIDE_DRAFT_API */ +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/icu4c/source/test/cintltst/cdattst.c b/icu4c/source/test/cintltst/cdattst.c index fec9f2640ee..aef58d07660 100644 --- a/icu4c/source/test/cintltst/cdattst.c +++ b/icu4c/source/test/cintltst/cdattst.c @@ -25,6 +25,7 @@ #include "unicode/ucal.h" #include "unicode/unum.h" #include "unicode/ustring.h" +#include "unicode/ufieldpositer.h" #include "cintltst.h" #include "cdattst.h" #include "cformtst.h" @@ -38,6 +39,7 @@ static void TestRelativeCrash(void); static void TestContext(void); static void TestCalendarDateParse(void); static void TestParseErrorReturnValue(void); +static void TestFormatForFields(void); #define LEN(a) (sizeof(a)/sizeof(a[0])) @@ -58,6 +60,7 @@ void addDateForTest(TestNode** root) TESTCASE(TestCalendarDateParse); TESTCASE(TestOverrideNumberFormat); TESTCASE(TestParseErrorReturnValue); + TESTCASE(TestFormatForFields); } /* Testing the DateFormat API */ static void TestDateFormat() @@ -1734,4 +1737,103 @@ static void TestParseErrorReturnValue(void) { udat_close(df); } +/* + * Ticket #11553 + * Test new udat_formatForFields, udat_formatCalendarForFields (and UFieldPositionIterator) + */ +static const char localeForFields[] = "en_US"; +/* zoneGMT[]defined above */ +static const UDate date2015Feb25 = 1424841000000.0; /* Wednesday, February 25, 2015 at 5:10:00 AM GMT */ + +typedef struct { + int32_t field; + int32_t beginPos; + int32_t endPos; +} FieldsData; +static const FieldsData expectedFields[] = { + { UDAT_DAY_OF_WEEK_FIELD /* 9*/, 0, 9 }, + { UDAT_MONTH_FIELD /* 2*/, 11, 19 }, + { UDAT_DATE_FIELD /* 3*/, 20, 22 }, + { UDAT_YEAR_FIELD /* 1*/, 24, 28 }, + { UDAT_HOUR1_FIELD /*15*/, 32, 33 }, + { UDAT_TIME_SEPARATOR_FIELD /*35*/, 33, 34 }, + { UDAT_MINUTE_FIELD /* 6*/, 34, 36 }, + { UDAT_TIME_SEPARATOR_FIELD /*35*/, 36, 37 }, + { UDAT_SECOND_FIELD /* 7*/, 37, 39 }, + { UDAT_AM_PM_FIELD /*14*/, 40, 42 }, + { UDAT_TIMEZONE_FIELD /*17*/, 43, 46 }, + { -1, -1, -1 }, +}; + +enum {kUBufFieldsLen = 128, kBBufFieldsLen = 256 }; + +static void TestFormatForFields(void) { + UErrorCode status = U_ZERO_ERROR; + UFieldPositionIterator* fpositer = ufieldpositer_open(&status); + if ( U_FAILURE(status) ) { + log_err("ufieldpositer_open fails, status %s\n", u_errorName(status)); + } else { + UDateFormat* udfmt = udat_open(UDAT_LONG, UDAT_FULL, localeForFields, zoneGMT, -1, NULL, 0, &status); + UCalendar* ucal = ucal_open(zoneGMT, -1, localeForFields, UCAL_DEFAULT, &status); + if ( U_FAILURE(status) ) { + log_data_err("udat_open or ucal_open fails for locale %s, status %s (Are you missing data?)\n", localeForFields, u_errorName(status)); + } else { + int32_t ulen, field, beginPos, endPos; + UChar ubuf[kUBufFieldsLen]; + const FieldsData * fptr; + + status = U_ZERO_ERROR; + ulen = udat_formatForFields(udfmt, date2015Feb25, ubuf, kUBufFieldsLen, fpositer, &status); + if ( U_FAILURE(status) ) { + log_err("udat_formatForFields fails, status %s\n", u_errorName(status)); + } else { + for (fptr = expectedFields; ; fptr++) { + field = ufieldpositer_next(fpositer, &beginPos, &endPos); + if (field != fptr->field || (field >= 0 && (beginPos != fptr->beginPos || endPos != fptr->endPos))) { + if (fptr->field >= 0) { + log_err("udat_formatForFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n", + aescstrdup(ubuf, ulen), fptr->field, fptr->beginPos, fptr->endPos, field, beginPos, endPos); + } else { + log_err("udat_formatForFields as \"%s\"; expect field < 0, get field %d range %d-%d\n", + aescstrdup(ubuf, ulen), field, beginPos, endPos); + } + break; + } + if (field < 0) { + break; + } + } + } + + ucal_setMillis(ucal, date2015Feb25, &status); + status = U_ZERO_ERROR; + ulen = udat_formatCalendarForFields(udfmt, ucal, ubuf, kUBufFieldsLen, fpositer, &status); + if ( U_FAILURE(status) ) { + log_err("udat_formatCalendarForFields fails, status %s\n", u_errorName(status)); + } else { + for (fptr = expectedFields; ; fptr++) { + field = ufieldpositer_next(fpositer, &beginPos, &endPos); + if (field != fptr->field || (field >= 0 && (beginPos != fptr->beginPos || endPos != fptr->endPos))) { + if (fptr->field >= 0) { + log_err("udat_formatFudat_formatCalendarForFieldsorFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n", + aescstrdup(ubuf, ulen), fptr->field, fptr->beginPos, fptr->endPos, field, beginPos, endPos); + } else { + log_err("udat_formatCalendarForFields as \"%s\"; expect field < 0, get field %d range %d-%d\n", + aescstrdup(ubuf, ulen), field, beginPos, endPos); + } + break; + } + if (field < 0) { + break; + } + } + } + + ucal_close(ucal); + udat_close(udfmt); + } + ufieldpositer_close(fpositer); + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */