From a0f02b12d0d76e710c7ad674c43b145635a32578 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 8 Feb 2019 02:07:00 -0800 Subject: [PATCH] ICU-20121 Adding span field for FormattedList. --- icu4c/source/i18n/listformatter.cpp | 15 ++++++++++ icu4c/source/i18n/unicode/listformatter.h | 7 +++++ icu4c/source/i18n/unicode/uformattedvalue.h | 7 +++++ icu4c/source/i18n/unicode/ulistformatter.h | 7 +++++ icu4c/source/test/cintltst/ulistfmttest.c | 30 ++++++++++++------- .../test/intltest/listformattertest.cpp | 9 ++++-- 6 files changed, 62 insertions(+), 13 deletions(-) diff --git a/icu4c/source/i18n/listformatter.cpp b/icu4c/source/i18n/listformatter.cpp index 5968284a792..68814211cdf 100644 --- a/icu4c/source/i18n/listformatter.cpp +++ b/icu4c/source/i18n/listformatter.cpp @@ -420,6 +420,21 @@ FormattedList ListFormatter::formatStringsToValue( if (U_FAILURE(errorCode)) { return FormattedList(errorCode); } + + // Add span fields and sort + ConstrainedFieldPosition cfpos; + cfpos.constrainField(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD); + int32_t i = 0; + handler.setCategory(UFIELD_CATEGORY_LIST_SPAN); + while (result->nextPosition(cfpos, errorCode)) { + handler.addAttribute(i++, cfpos.getStart(), cfpos.getLimit()); + } + handler.getError(errorCode); + if (U_FAILURE(errorCode)) { + return FormattedList(errorCode); + } + result->sort(); + return FormattedList(result.orphan()); } #endif diff --git a/icu4c/source/i18n/unicode/listformatter.h b/icu4c/source/i18n/unicode/listformatter.h index b11676d5f80..bf956ba52c5 100644 --- a/icu4c/source/i18n/unicode/listformatter.h +++ b/icu4c/source/i18n/unicode/listformatter.h @@ -66,6 +66,13 @@ struct ListFormatData : public UMemory { /** * An immutable class containing the result of a list formatting operation. * + * When calling nextPosition(): + * The fields are returned from start to end. The special field category + * UFIELD_CATEGORY_LIST_SPAN is used to indicate which argument + * was inserted at the given position. The span category will + * always occur before the corresponding instance of UFIELD_CATEGORY_LIST + * in the nextPosition() iterator. + * * Not intended for public subclassing. * * @draft ICU 64 diff --git a/icu4c/source/i18n/unicode/uformattedvalue.h b/icu4c/source/i18n/unicode/uformattedvalue.h index 362408bfeb7..1fe977f30e9 100644 --- a/icu4c/source/i18n/unicode/uformattedvalue.h +++ b/icu4c/source/i18n/unicode/uformattedvalue.h @@ -79,6 +79,13 @@ typedef enum UFieldCategory { UFIELD_CATEGORY_COUNT, #endif + /** + * Category for spans in a list. + * + * @draft ICU 64 + */ + UFIELD_CATEGORY_LIST_SPAN = 0x1000 + UFIELD_CATEGORY_LIST, + /** * Category for spans in a date interval. * diff --git a/icu4c/source/i18n/unicode/ulistformatter.h b/icu4c/source/i18n/unicode/ulistformatter.h index cf730bfd7e3..2afc50d847b 100644 --- a/icu4c/source/i18n/unicode/ulistformatter.h +++ b/icu4c/source/i18n/unicode/ulistformatter.h @@ -114,6 +114,13 @@ ulistfmt_openResult(UErrorCode* ec); * * You can think of this method as a cast between types. * + * When calling ufmtval_nextPosition(): + * The fields are returned from start to end. The special field category + * UFIELD_CATEGORY_LIST_SPAN is used to indicate which argument + * was inserted at the given position. The span category will + * always occur before the corresponding instance of UFIELD_CATEGORY_LIST + * in the ufmtval_nextPosition() iterator. + * * @param uresult The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. diff --git a/icu4c/source/test/cintltst/ulistfmttest.c b/icu4c/source/test/cintltst/ulistfmttest.c index b89f1b37c77..5eb5a1eaa4b 100644 --- a/icu4c/source/test/cintltst/ulistfmttest.c +++ b/icu4c/source/test/cintltst/ulistfmttest.c @@ -147,11 +147,14 @@ static void TestUListFmtToValue() { assertSuccess("Formatting", &ec); static const UFieldPositionWithCategory expectedFieldPositions[] = { // field, begin index, end index + {UFIELD_CATEGORY_LIST_SPAN, 0, 0, 5}, {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 5}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 7, 16}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 27}, {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 5, 7}, - {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}}; + {UFIELD_CATEGORY_LIST_SPAN, 1, 7, 16}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 7, 16}, + {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}, + {UFIELD_CATEGORY_LIST_SPAN, 2, 22, 27}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 27}}; checkMixedFormattedValue( message, ulistfmt_resultAsValue(fl, &ec), @@ -175,19 +178,26 @@ static void TestUListFmtToValue() { assertSuccess("Formatting", &ec); static const UFieldPositionWithCategory expectedFieldPositions[] = { // field, begin index, end index + {UFIELD_CATEGORY_LIST_SPAN, 0, 0, 1}, {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 1}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 3, 4}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 6, 7}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 9, 10}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 12, 13}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 15, 16}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 23}, {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 1, 3}, + {UFIELD_CATEGORY_LIST_SPAN, 1, 3, 4}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 3, 4}, {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 4, 6}, + {UFIELD_CATEGORY_LIST_SPAN, 2, 6, 7}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 6, 7}, {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 7, 9}, + {UFIELD_CATEGORY_LIST_SPAN, 3, 9, 10}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 9, 10}, {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 10, 12}, + {UFIELD_CATEGORY_LIST_SPAN, 4, 12, 13}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 12, 13}, {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 13, 15}, - {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}}; + {UFIELD_CATEGORY_LIST_SPAN, 5, 15, 16}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 15, 16}, + {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}, + {UFIELD_CATEGORY_LIST_SPAN, 6, 22, 23}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 23}}; checkMixedFormattedValue( message, ulistfmt_resultAsValue(fl, &ec), diff --git a/icu4c/source/test/intltest/listformattertest.cpp b/icu4c/source/test/intltest/listformattertest.cpp index 239eb78ac09..955c3d981d4 100644 --- a/icu4c/source/test/intltest/listformattertest.cpp +++ b/icu4c/source/test/intltest/listformattertest.cpp @@ -556,11 +556,14 @@ void ListFormatterTest::TestFormattedValue() { FormattedList result = fmt->formatStringsToValue(inputs, UPRV_LENGTHOF(inputs), status); static const UFieldPositionWithCategory expectedFieldPositions[] = { // field, begin index, end index + {UFIELD_CATEGORY_LIST_SPAN, 0, 0, 5}, {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 5}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 7, 16}, - {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 27}, {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 5, 7}, - {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}}; + {UFIELD_CATEGORY_LIST_SPAN, 1, 7, 16}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 7, 16}, + {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}, + {UFIELD_CATEGORY_LIST_SPAN, 2, 22, 27}, + {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 27}}; checkMixedFormattedValue( message, result, -- 2.40.0