+ dataerrln("FAIL: %s", line);
+ }
+ return pass;
+}
+
+static const char *const kModeStrings[UNORM_MODE_COUNT] = {
+ "?", "none", "D", "KD", "C", "KC", "FCD"
+};
+
+static const char *const kMessages[UNORM_MODE_COUNT] = {
+ "?!=?", "?!=?", "c3!=D(c%d)", "c5!=KC(c%d)", "c2!=C(c%d)", "c4!=KC(c%d)", "FCD"
+};
+
+UBool NormalizerConformanceTest::checkNorm(UNormalizationMode mode, int32_t options,
+ const Normalizer2 *norm2,
+ const UnicodeString &s, const UnicodeString &exp,
+ int32_t field) {
+ const char *modeString = kModeStrings[mode];
+ char msg[20];
+ snprintf(msg, sizeof(msg), kMessages[mode], field);
+ UnicodeString out;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ Normalizer::normalize(s, mode, options, out, errorCode);
+ if (U_FAILURE(errorCode)) {
+ dataerrln("Error running normalize UNORM_NF%s: %s", modeString, u_errorName(errorCode));
+ return FALSE;
+ }
+ if (!assertEqual(modeString, "", s, out, exp, msg)) {
+ return FALSE;
+ }
+
+ iterativeNorm(s, mode, options, out, +1);
+ if (!assertEqual(modeString, "(+1)", s, out, exp, msg)) {
+ return FALSE;
+ }
+
+ iterativeNorm(s, mode, options, out, -1);
+ if (!assertEqual(modeString, "(-1)", s, out, exp, msg)) {
+ return FALSE;
+ }
+
+ if (norm2 == nullptr || options != 0) {
+ return TRUE;
+ }
+
+ std::string s8;
+ s.toUTF8String(s8);
+ std::string exp8;
+ exp.toUTF8String(exp8);
+ std::string out8;
+ Edits edits;
+ Edits *editsPtr = (mode == UNORM_NFC || mode == UNORM_NFKC) ? &edits : nullptr;
+ StringByteSink<std::string> sink(&out8, static_cast<int32_t>(exp8.length()));
+ norm2->normalizeUTF8(0, s8, sink, editsPtr, errorCode);
+ if (U_FAILURE(errorCode)) {
+ errln("Normalizer2.%s.normalizeUTF8(%s) failed: %s",
+ modeString, s8.c_str(), u_errorName(errorCode));
+ return FALSE;
+ }
+ if (out8 != exp8) {
+ errln("Normalizer2.%s.normalizeUTF8(%s)=%s != %s",
+ modeString, s8.c_str(), out8.c_str(), exp8.c_str());
+ return FALSE;
+ }
+ if (editsPtr == nullptr) {
+ return TRUE;