* created by: Umesh P. Nair
*/
+#include "cmemory.h"
+#include "unicode/fpositer.h" // FieldPositionIterator
#include "unicode/listformatter.h"
#include "unicode/simpleformatter.h"
+#include "unicode/ulistformatter.h"
+#include "fphdlimp.h"
#include "mutex.h"
#include "hash.h"
#include "cstring.h"
+#include "uarrsort.h"
#include "ulocimp.h"
#include "charstr.h"
#include "ucln_in.h"
-static Hashtable* listPatternHash = NULL;
+static Hashtable* listPatternHash = nullptr;
static UMutex listFormatterMutex = U_MUTEX_INITIALIZER;
static const char STANDARD_STYLE[] = "standard";
U_CDECL_BEGIN
static UBool U_CALLCONV uprv_listformatter_cleanup() {
delete listPatternHash;
- listPatternHash = NULL;
+ listPatternHash = nullptr;
return TRUE;
}
ListFormatter::ListFormatter(const ListFormatter& other) :
owned(other.owned), data(other.data) {
- if (other.owned != NULL) {
+ if (other.owned != nullptr) {
owned = new ListFormatInternal(*other.owned);
data = owned;
}
owned = new ListFormatInternal(*other.owned);
data = owned;
} else {
- owned = NULL;
+ owned = nullptr;
data = other.data;
}
return *this;
}
listPatternHash = new Hashtable();
- if (listPatternHash == NULL) {
+ if (listPatternHash == nullptr) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
return;
}
const ListFormatInternal* ListFormatter::getListFormatInternal(
const Locale& locale, const char *style, UErrorCode& errorCode) {
if (U_FAILURE(errorCode)) {
- return NULL;
+ return nullptr;
}
CharString keyBuffer(locale.getName(), errorCode);
keyBuffer.append(':', errorCode).append(style, errorCode);
UnicodeString key(keyBuffer.data(), -1, US_INV);
- ListFormatInternal* result = NULL;
+ ListFormatInternal* result = nullptr;
{
Mutex m(&listFormatterMutex);
- if (listPatternHash == NULL) {
+ if (listPatternHash == nullptr) {
initializeHash(errorCode);
if (U_FAILURE(errorCode)) {
- return NULL;
+ return nullptr;
}
}
result = static_cast<ListFormatInternal*>(listPatternHash->get(key));
}
- if (result != NULL) {
+ if (result != nullptr) {
return result;
}
result = loadListFormatInternal(locale, style, errorCode);
if (U_FAILURE(errorCode)) {
- return NULL;
+ return nullptr;
}
{
Mutex m(&listFormatterMutex);
ListFormatInternal* temp = static_cast<ListFormatInternal*>(listPatternHash->get(key));
- if (temp != NULL) {
+ if (temp != nullptr) {
delete result;
result = temp;
} else {
listPatternHash->put(key, result, errorCode);
if (U_FAILURE(errorCode)) {
- return NULL;
+ return nullptr;
}
}
}
ListFormatInternal* ListFormatter::loadListFormatInternal(
const Locale& locale, const char * style, UErrorCode& errorCode) {
- UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode);
+ UResourceBundle* rb = ures_open(nullptr, locale.getName(), &errorCode);
rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode);
if (U_FAILURE(errorCode)) {
ures_close(rb);
- return NULL;
+ return nullptr;
}
ListFormatter::ListPatternsSink sink;
char currentStyle[kStyleLenMax+1];
}
ures_close(rb);
if (U_FAILURE(errorCode)) {
- return NULL;
+ return nullptr;
}
if (sink.two.isEmpty() || sink.start.isEmpty() || sink.middle.isEmpty() || sink.end.isEmpty()) {
errorCode = U_MISSING_RESOURCE_ERROR;
- return NULL;
+ return nullptr;
}
ListFormatInternal* result = new ListFormatInternal(sink.two, sink.start, sink.middle, sink.end, errorCode);
- if (result == NULL) {
+ if (result == nullptr) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
+ return nullptr;
}
if (U_FAILURE(errorCode)) {
delete result;
- return NULL;
+ return nullptr;
}
return result;
}
Locale tempLocale = locale;
const ListFormatInternal* listFormatInternal = getListFormatInternal(tempLocale, style, errorCode);
if (U_FAILURE(errorCode)) {
- return NULL;
+ return nullptr;
}
ListFormatter* p = new ListFormatter(listFormatInternal);
- if (p == NULL) {
+ if (p == nullptr) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
+ return nullptr;
}
return p;
}
data = owned;
}
-ListFormatter::ListFormatter(const ListFormatInternal* listFormatterInternal) : owned(NULL), data(listFormatterInternal) {
+ListFormatter::ListFormatter(const ListFormatInternal* listFormatterInternal) : owned(nullptr), data(listFormatterInternal) {
}
ListFormatter::~ListFormatter() {
UnicodeString &result,
UBool recordOffset,
int32_t &offset,
+ int32_t *offsetFirst,
+ int32_t *offsetSecond,
UErrorCode& errorCode) {
if (U_FAILURE(errorCode)) {
return;
} else if (offset >= 0) {
offset += offsets[0];
}
+ if (offsetFirst != nullptr) *offsetFirst = offsets[0];
+ if (offsetSecond != nullptr) *offsetSecond = offsets[1];
}
UnicodeString& ListFormatter::format(
return format(items, nItems, appendTo, -1, offset, errorCode);
}
+UnicodeString& ListFormatter::format(
+ const UnicodeString items[],
+ int32_t nItems,
+ UnicodeString & appendTo,
+ FieldPositionIterator* posIter,
+ UErrorCode& errorCode) const {
+ int32_t offset;
+ FieldPositionIteratorHandler handler(posIter, errorCode);
+ return format_(items, nItems, appendTo, -1, offset, &handler, errorCode);
+};
+
UnicodeString& ListFormatter::format(
const UnicodeString items[],
int32_t nItems,
int32_t index,
int32_t &offset,
UErrorCode& errorCode) const {
+ return format_(items, nItems, appendTo, index, offset, nullptr, errorCode);
+}
+
+UnicodeString& ListFormatter::format_(
+ const UnicodeString items[],
+ int32_t nItems,
+ UnicodeString& appendTo,
+ int32_t index,
+ int32_t &offset,
+ FieldPositionHandler* handler,
+ UErrorCode& errorCode) const {
offset = -1;
if (U_FAILURE(errorCode)) {
return appendTo;
}
- if (data == NULL) {
+ if (data == nullptr) {
errorCode = U_INVALID_STATE_ERROR;
return appendTo;
}
if (index == 0) {
offset = appendTo.length();
}
+ if (handler != nullptr) {
+ handler->addAttribute(ULISTFMT_ELEMENT_FIELD,
+ appendTo.length(),
+ appendTo.length() + items[0].length());
+ }
appendTo.append(items[0]);
return appendTo;
}
if (index == 0) {
offset = 0;
}
+ int32_t offsetFirst;
+ int32_t offsetSecond;
+ int32_t prefixLength = 0;
+ // for n items, there are 2 * (n + 1) boundary including 0 and the upper
+ // edge.
+ MaybeStackArray<int32_t, 10> offsets((handler != nullptr) ? 2 * (nItems + 1): 0);
joinStringsAndReplace(
nItems == 2 ? data->twoPattern : data->startPattern,
result,
result,
index == 1,
offset,
+ &offsetFirst,
+ &offsetSecond,
errorCode);
+ if (handler != nullptr) {
+ offsets[0] = 0;
+ prefixLength += offsetFirst;
+ offsets[1] = offsetSecond - prefixLength;
+ }
if (nItems > 2) {
for (int32_t i = 2; i < nItems - 1; ++i) {
joinStringsAndReplace(
result,
index == i,
offset,
+ &offsetFirst,
+ &offsetSecond,
errorCode);
+ if (handler != nullptr) {
+ prefixLength += offsetFirst;
+ offsets[i] = offsetSecond - prefixLength;
+ }
}
joinStringsAndReplace(
data->endPattern,
result,
index == nItems - 1,
offset,
+ &offsetFirst,
+ &offsetSecond,
errorCode);
+ if (handler != nullptr) {
+ prefixLength += offsetFirst;
+ offsets[nItems - 1] = offsetSecond - prefixLength;
+ }
+ }
+ if (handler != nullptr) {
+ // If there are already some data in appendTo, we need to adjust the index
+ // by shifting that lenght while insert into handler.
+ int32_t shift = appendTo.length() + prefixLength;
+ // Output the ULISTFMT_ELEMENT_FIELD in the order of the input elements
+ for (int32_t i = 0; i < nItems; ++i) {
+ offsets[i + nItems] = offsets[i] + items[i].length() + shift;
+ offsets[i] += shift;
+ handler->addAttribute(
+ ULISTFMT_ELEMENT_FIELD, // id
+ offsets[i], // index
+ offsets[i + nItems]); // limit
+ }
+ // The locale pattern may reorder the items (such as in ur-IN locale),
+ // so we cannot assume the array is in accendning order.
+ // To handle the edging case, just insert the two ends into the array
+ // and sort. Then we output ULISTFMT_LITERAL_FIELD if the indecies
+ // between the even and odd position are not the same in the sorted array.
+ offsets[2 * nItems] = shift - prefixLength;
+ offsets[2 * nItems + 1] = result.length() + shift - prefixLength;
+ uprv_sortArray(offsets.getAlias(), 2 * (nItems + 1), sizeof(int32_t),
+ uprv_int32Comparator, nullptr,
+ false, &errorCode);
+ for (int32_t i = 0; i <= nItems; ++i) {
+ if (offsets[i * 2] != offsets[i * 2 + 1]) {
+ handler->addAttribute(
+ ULISTFMT_LITERAL_FIELD, // id
+ offsets[i * 2], // index
+ offsets[i * 2 + 1]); // limit
+ }
+ }
}
if (U_SUCCESS(errorCode)) {
if (offset >= 0) {
*/
#include "listformattertest.h"
+#include "unicode/ulistformatter.h"
#include <string.h>
+namespace {
+const char* attrString(int32_t attrId) {
+ switch (attrId) {
+ case ULISTFMT_LITERAL_FIELD: return "literal";
+ case ULISTFMT_ELEMENT_FIELD: return "element";
+ default: return "xxx";
+ }
+}
+} // namespace
+
+void ListFormatterTest::ExpectPositions(FieldPositionIterator& iter,
+ int32_t *values, int32_t tupleCount) {
+ UBool found[10];
+ FieldPosition fp;
+ if (tupleCount > 10) {
+ assertTrue("internal error, tupleCount too large", FALSE);
+ } else {
+ for (int i = 0; i < tupleCount; ++i) {
+ found[i] = FALSE;
+ }
+ }
+ while (iter.next(fp)) {
+ UBool ok = FALSE;
+ int32_t id = fp.getField();
+ int32_t start = fp.getBeginIndex();
+ int32_t limit = fp.getEndIndex();
+ char buf[128];
+ sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
+ logln(buf);
+ for (int i = 0; i < tupleCount; ++i) {
+ if (found[i]) {
+ continue;
+ }
+ if (values[i*3] == id && values[i*3+1] == start && values[i*3+2] == limit) {
+ found[i] = ok = TRUE;
+ break;
+ }
+ }
+ assertTrue((UnicodeString)"found [" + attrString(id) + "," + start + "," + limit + "]", ok);
+ }
+ // check that all were found
+ UBool ok = TRUE;
+ for (int i = 0; i < tupleCount; ++i) {
+ if (!found[i]) {
+ ok = FALSE;
+ assertTrue((UnicodeString) "missing [" + attrString(values[i*3]) + "," + values[i*3+1] +
+ "," + values[i*3+2] + "]", found[i]);
+ }
+ }
+ assertTrue("no expected values were missing", ok);
+}
+
ListFormatterTest::ListFormatterTest() :
prefix("Prefix: ", -1, US_INV),
one("Alice", -1, US_INV), two("Bob", -1, US_INV),
}
void ListFormatterTest::CheckFormatting(const ListFormatter* formatter, UnicodeString data[], int32_t dataSize,
- const UnicodeString& expected_result) {
+ const UnicodeString& expected_result, const char* testName) {
UnicodeString actualResult(prefix);
- UErrorCode errorCode = U_ZERO_ERROR;
+ IcuTestErrorCode errorCode(*this, testName);
formatter->format(data, dataSize, actualResult, errorCode);
UnicodeString expectedStringWithPrefix = prefix + expected_result;
if (expectedStringWithPrefix != actualResult) {
}
void ListFormatterTest::CheckFourCases(const char* locale_string, UnicodeString one, UnicodeString two,
- UnicodeString three, UnicodeString four, UnicodeString results[4]) {
- UErrorCode errorCode = U_ZERO_ERROR;
+ UnicodeString three, UnicodeString four, UnicodeString results[4], const char* testName) {
+ IcuTestErrorCode errorCode(*this, testName);
LocalPointer<ListFormatter> formatter(ListFormatter::createInstance(Locale(locale_string), errorCode));
if (U_FAILURE(errorCode)) {
dataerrln("ListFormatter::createInstance(Locale(\"%s\"), errorCode) failed in CheckFourCases: %s", locale_string, u_errorName(errorCode));
return;
}
UnicodeString input1[] = {one};
- CheckFormatting(formatter.getAlias(), input1, 1, results[0]);
+ CheckFormatting(formatter.getAlias(), input1, 1, results[0], testName);
UnicodeString input2[] = {one, two};
- CheckFormatting(formatter.getAlias(), input2, 2, results[1]);
+ CheckFormatting(formatter.getAlias(), input2, 2, results[1], testName);
UnicodeString input3[] = {one, two, three};
- CheckFormatting(formatter.getAlias(), input3, 3, results[2]);
+ CheckFormatting(formatter.getAlias(), input3, 3, results[2], testName);
UnicodeString input4[] = {one, two, three, four};
- CheckFormatting(formatter.getAlias(), input4, 4, results[3]);
+ CheckFormatting(formatter.getAlias(), input4, 4, results[3], testName);
}
UBool ListFormatterTest::RecordFourCases(const Locale& locale, UnicodeString one, UnicodeString two,
- UnicodeString three, UnicodeString four, UnicodeString results[4]) {
- UErrorCode errorCode = U_ZERO_ERROR;
+ UnicodeString three, UnicodeString four, UnicodeString results[4], const char* testName) {
+ IcuTestErrorCode errorCode(*this, testName);
LocalPointer<ListFormatter> formatter(ListFormatter::createInstance(locale, errorCode));
if (U_FAILURE(errorCode)) {
dataerrln("ListFormatter::createInstance(\"%s\", errorCode) failed in RecordFourCases: %s", locale.getName(), u_errorName(errorCode));
one + ", " + two + ", " + three + ", " + four
};
- CheckFourCases("", one, two, three, four, results);
+ CheckFourCases("", one, two, three, four, results, "TestRoot()");
}
// Bogus locale should fallback to root.
void ListFormatterTest::TestBogus() {
UnicodeString results[4];
- if (RecordFourCases(Locale::getDefault(), one, two, three, four, results)) {
- CheckFourCases("ex_PY", one, two, three, four, results);
+ if (RecordFourCases(Locale::getDefault(), one, two, three, four, results, "TestBogus()")) {
+ CheckFourCases("ex_PY", one, two, three, four, results, "TestBogus()");
}
}
one + ", " + two + ", " + three + ", and " + four
};
- CheckFourCases("en", one, two, three, four, results);
+ CheckFourCases("en", one, two, three, four, results, "TestEnglish()");
}
void ListFormatterTest::Test9946() {
- UErrorCode errorCode = U_ZERO_ERROR;
+ IcuTestErrorCode errorCode(*this, "Test9946()");
LocalPointer<ListFormatter> formatter(ListFormatter::createInstance(Locale("en"), errorCode));
if (U_FAILURE(errorCode)) {
dataerrln(
one + ", " + two + ", " + three + ", and " + four
};
- CheckFourCases("en_US", one, two, three, four, results);
+ CheckFourCases("en_US", one, two, three, four, results, "TestEnglishUS()");
}
// Tests resource loading and inheritance when region sublocale
one + ", " + two + ", " + three + " and " + four
};
- CheckFourCases("en_GB", one, two, three, four, results);
+ CheckFourCases("en_GB", one, two, three, four, results, "TestEnglishGB()");
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWontCrash() {
+ IcuTestErrorCode errorCode(*this, "TestFieldPositionIteratorWontCrash()");
+ LocalPointer<ListFormatter> formatter(
+ ListFormatter::createInstance(Locale("en"), errorCode));
+ if (U_FAILURE(errorCode)) {
+ dataerrln(
+ "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in "
+ "TestFieldPositionIteratorWontCrash: %s",
+ u_errorName(errorCode));
+ return;
+ }
+ UnicodeString data[3] = {"a", "bbb", "cc"};
+ UnicodeString actualResult;
+ // make sure NULL as FieldPositionIterator won't caused crash.
+ formatter->format(data, 3, actualResult, nullptr, errorCode);
+ if (U_FAILURE(errorCode)) {
+ dataerrln(
+ "ListFormatter::format(data, 3, nullptr, errorCode) "
+ "failed in TestFieldPositionIteratorWontCrash: %s",
+ u_errorName(errorCode));
+ return;
+ }
+}
+
+void ListFormatterTest::RunTestFieldPositionIteratorWithFormatter(
+ ListFormatter* formatter,
+ UnicodeString data[], int32_t n, int32_t expected[], int32_t tupleCount,
+ UnicodeString& appendTo, const char16_t *expectedFormatted,
+ const char* testName) {
+ IcuTestErrorCode errorCode(*this, testName);
+ FieldPositionIterator iter;
+ formatter->format(data, n, appendTo, &iter, errorCode);
+ if (U_FAILURE(errorCode)) {
+ dataerrln(
+ "ListFormatter::format(data, %d, &iter, errorCode) "
+ "failed in %s: %s", n, testName, u_errorName(errorCode));
+ return;
+ }
+ if (appendTo != expectedFormatted) {
+ errln(UnicodeString("Expected: |") + expectedFormatted + "|, Actual: |" + appendTo + "|");
+ }
+ ExpectPositions(iter, expected, tupleCount);
+}
+
+void ListFormatterTest::RunTestFieldPositionIteratorWithNItemsPatternShift(
+ UnicodeString data[], int32_t n, int32_t expected[], int32_t tupleCount,
+ UnicodeString& appendTo, const char16_t *expectedFormatted,
+ const char* testName) {
+ IcuTestErrorCode errorCode(*this, testName);
+ LocalPointer<ListFormatter> formatter(
+ ListFormatter::createInstance(Locale("ur", "IN"), "unit-narrow", errorCode));
+ if (U_FAILURE(errorCode)) {
+ dataerrln(
+ "ListFormatter::createInstance(Locale(\"ur\", \"IN\"), \"unit-narrow\", errorCode) failed in "
+ "%s: %s", testName, u_errorName(errorCode));
+ return;
+ }
+ RunTestFieldPositionIteratorWithFormatter(
+ formatter.getAlias(),
+ data, n, expected, tupleCount, appendTo, expectedFormatted, testName);
+}
+
+void ListFormatterTest::RunTestFieldPositionIteratorWithNItems(
+ UnicodeString data[], int32_t n, int32_t expected[], int32_t tupleCount,
+ UnicodeString& appendTo, const char16_t *expectedFormatted,
+ const char* testName) {
+ IcuTestErrorCode errorCode(*this, testName);
+ LocalPointer<ListFormatter> formatter(
+ ListFormatter::createInstance(Locale("en"), errorCode));
+ if (U_FAILURE(errorCode)) {
+ dataerrln(
+ "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in "
+ "%s: %s", testName, u_errorName(errorCode));
+ return;
+ }
+ RunTestFieldPositionIteratorWithFormatter(
+ formatter.getAlias(),
+ data, n, expected, tupleCount, appendTo, expectedFormatted, testName);
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWith3ItemsAndDataBefore() {
+ // 0 1 2
+ // 0123456789012345678901234567
+ // "Hello World: a, bbb, and cc"
+ UnicodeString data[3] = {"a", "bbb", "cc"};
+ int32_t expected[] = {
+ ULISTFMT_ELEMENT_FIELD, 13, 14,
+ ULISTFMT_LITERAL_FIELD, 14, 16,
+ ULISTFMT_ELEMENT_FIELD, 16, 19,
+ ULISTFMT_LITERAL_FIELD, 19, 25,
+ ULISTFMT_ELEMENT_FIELD, 25, 27
+ };
+ int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ UnicodeString appendTo(u"Hello World: ");
+ RunTestFieldPositionIteratorWithNItems(
+ data, 3, expected, tupleCount, appendTo,
+ u"Hello World: a, bbb, and cc",
+ "TestFieldPositionIteratorWith3ItemsAndDataBefore");
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWith3Items() {
+ // 0 1
+ // 012345678901234
+ // "a, bbb, and cc"
+ UnicodeString data[3] = {"a", "bbb", "cc"};
+ int32_t expected[] = {
+ ULISTFMT_ELEMENT_FIELD, 0, 1,
+ ULISTFMT_LITERAL_FIELD, 1, 3,
+ ULISTFMT_ELEMENT_FIELD, 3, 6,
+ ULISTFMT_LITERAL_FIELD, 6, 12,
+ ULISTFMT_ELEMENT_FIELD, 12, 14
+ };
+ int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ UnicodeString appendTo;
+ RunTestFieldPositionIteratorWithNItems(
+ data, 3, expected, tupleCount, appendTo,
+ u"a, bbb, and cc",
+ "TestFieldPositionIteratorWith3Items");
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWith3ItemsPatternShift() {
+ // 0 1
+ // 012345678901234
+ // "cc bbb a"
+ UnicodeString data[3] = {"a", "bbb", "cc"};
+ int32_t expected[] = {
+ ULISTFMT_ELEMENT_FIELD, 7, 8,
+ ULISTFMT_LITERAL_FIELD, 6, 7,
+ ULISTFMT_ELEMENT_FIELD, 3, 6,
+ ULISTFMT_LITERAL_FIELD, 2, 3,
+ ULISTFMT_ELEMENT_FIELD, 0, 2
+ };
+ int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ UnicodeString appendTo;
+ RunTestFieldPositionIteratorWithNItemsPatternShift(
+ data, 3, expected, tupleCount, appendTo,
+ u"cc bbb a",
+ "TestFieldPositionIteratorWith3ItemsPatternShift");
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWith2ItemsAndDataBefore() {
+ // 0 1
+ // 0123456789012345
+ // "Foo: bbb and cc"
+ UnicodeString data[2] = {"bbb", "cc"};
+ int32_t expected[] = {
+ ULISTFMT_ELEMENT_FIELD, 5, 8,
+ ULISTFMT_LITERAL_FIELD, 8, 13,
+ ULISTFMT_ELEMENT_FIELD, 13, 15
+ };
+ int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ UnicodeString appendTo("Foo: ");
+ RunTestFieldPositionIteratorWithNItems(
+ data, 2, expected, tupleCount, appendTo,
+ u"Foo: bbb and cc",
+ "TestFieldPositionIteratorWith2ItemsAndDataBefore");
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWith2Items() {
+ // 0 1
+ // 01234567890
+ // "bbb and cc"
+ UnicodeString data[2] = {"bbb", "cc"};
+ int32_t expected[] = {
+ ULISTFMT_ELEMENT_FIELD, 0, 3,
+ ULISTFMT_LITERAL_FIELD, 3, 8,
+ ULISTFMT_ELEMENT_FIELD, 8, 10
+ };
+ int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ UnicodeString appendTo;
+ RunTestFieldPositionIteratorWithNItems(
+ data, 2, expected, tupleCount, appendTo,
+ u"bbb and cc",
+ "TestFieldPositionIteratorWith2Items");
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWith2ItemsPatternShift() {
+ // 0 1
+ // 01234567890
+ // "cc bbb"
+ UnicodeString data[2] = {"bbb", "cc"};
+ int32_t expected[] = {
+ ULISTFMT_ELEMENT_FIELD, 3, 6,
+ ULISTFMT_LITERAL_FIELD, 2, 3,
+ ULISTFMT_ELEMENT_FIELD, 0, 2
+ };
+ int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ UnicodeString appendTo;
+ RunTestFieldPositionIteratorWithNItemsPatternShift(
+ data, 2, expected, tupleCount, appendTo,
+ u"cc bbb",
+ "TestFieldPositionIteratorWith2ItemsPatternShift");
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWith1ItemAndDataBefore() {
+ // 012345678
+ // "Hello cc"
+ UnicodeString data[1] = {"cc"};
+ int32_t expected[] = {
+ ULISTFMT_ELEMENT_FIELD, 6, 8
+ };
+ int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ UnicodeString appendTo("Hello ");
+ RunTestFieldPositionIteratorWithNItems(
+ data, 1, expected, tupleCount, appendTo,
+ u"Hello cc",
+ "TestFieldPositionIteratorWith1ItemAndDataBefore");
+}
+
+void ListFormatterTest::TestFieldPositionIteratorWith1Item() {
+ // 012
+ // "cc"
+ UnicodeString data[1] = {"cc"};
+ int32_t expected[] = {
+ ULISTFMT_ELEMENT_FIELD, 0, 2
+ };
+ int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ UnicodeString appendTo;
+ RunTestFieldPositionIteratorWithNItems(
+ data, 1, expected, tupleCount, appendTo,
+ u"cc",
+ "TestFieldPositionIteratorWith1Item");
}
// Tests resource loading and inheritance when region sublocale
one + ", " + two + ", " + three + " og " + four
};
- CheckFourCases("nn", one, two, three, four, results);
+ CheckFourCases("nn", one, two, three, four, results, "TestNynorsk()");
}
// Tests resource loading and inheritance when region sublocale
one + comma_string + two + comma_string + three + and_string + four
};
- CheckFourCases("zh_Hant_HK", one, two, three, four, results);
+ CheckFourCases("zh_Hant_HK", one, two, three, four, results, "TestChineseTradHK()");
}
// Formatting in Russian.
one + ", " + two + ", " + three + and_string + four
};
- CheckFourCases("ru", one, two, three, four, results);
+ CheckFourCases("ru", one, two, three, four, results, "TestRussian()");
}
// Formatting in Malayalam.
one + ", " + two + ", " + three + ", " + four + total_string
};
- CheckFourCases("ml", one, two, three, four, results);
+ CheckFourCases("ml", one, two, three, four, results, "TestMalayalam()");
}
// Formatting in Zulu.
one + ", " + two + ", " + three + ", ne-" + four
};
- CheckFourCases("zu", one, two, three, four, results);
+ CheckFourCases("zu", one, two, three, four, results, "TestZulu()");
}
void ListFormatterTest::TestOutOfOrderPatterns() {
four + " in the last after " + three + " after " + two + " after the first " + one
};
- UErrorCode errorCode = U_ZERO_ERROR;
+ IcuTestErrorCode errorCode(*this, "TestOutOfOrderPatterns()");
ListFormatData data("{1} after {0}", "{1} after the first {0}",
"{1} after {0}", "{1} in the last after {0}");
ListFormatter formatter(data, errorCode);
UnicodeString input1[] = {one};
- CheckFormatting(&formatter, input1, 1, results[0]);
+ CheckFormatting(&formatter, input1, 1, results[0], "TestOutOfOrderPatterns()");
UnicodeString input2[] = {one, two};
- CheckFormatting(&formatter, input2, 2, results[1]);
+ CheckFormatting(&formatter, input2, 2, results[1], "TestOutOfOrderPatterns()");
UnicodeString input3[] = {one, two, three};
- CheckFormatting(&formatter, input3, 3, results[2]);
+ CheckFormatting(&formatter, input3, 3, results[2], "TestOutOfOrderPatterns()");
UnicodeString input4[] = {one, two, three, four};
- CheckFormatting(&formatter, input4, 4, results[3]);
+ CheckFormatting(&formatter, input4, 4, results[3], "TestOutOfOrderPatterns()");
}
void ListFormatterTest::runIndexedTest(int32_t index, UBool exec,
case 9: name = "TestEnglishGB"; if (exec) TestEnglishGB(); break;
case 10: name = "TestNynorsk"; if (exec) TestNynorsk(); break;
case 11: name = "TestChineseTradHK"; if (exec) TestChineseTradHK(); break;
-
+ case 12: name = "TestFieldPositionIteratorWontCrash";
+ if (exec) TestFieldPositionIteratorWontCrash();
+ break;
+ case 13: name = "TestFieldPositionIteratorWith1Item";
+ if (exec) TestFieldPositionIteratorWith1Item();
+ break;
+ case 14: name = "TestFieldPositionIteratorWith1ItemAndDataBefore";
+ if (exec) TestFieldPositionIteratorWith1ItemAndDataBefore();
+ break;
+ case 15: name = "TestFieldPositionIteratorWith2Items";
+ if (exec) TestFieldPositionIteratorWith2Items();
+ break;
+ case 16: name = "TestFieldPositionIteratorWith2ItemsAndDataBefore";
+ if (exec) TestFieldPositionIteratorWith2ItemsAndDataBefore();
+ break;
+ case 17: name = "TestFieldPositionIteratorWith2ItemsPatternShift";
+ if (exec) TestFieldPositionIteratorWith2ItemsPatternShift();
+ break;
+ case 18: name = "TestFieldPositionIteratorWith3Items";
+ if (exec) TestFieldPositionIteratorWith3Items();
+ break;
+ case 19: name = "TestFieldPositionIteratorWith3ItemsAndDataBefore";
+ if (exec) TestFieldPositionIteratorWith3ItemsAndDataBefore();
+ break;
+ case 20: name = "TestFieldPositionIteratorWith3ItemsPatternShift";
+ if (exec) TestFieldPositionIteratorWith3ItemsPatternShift();
+ break;
default: name = ""; break;
}
}