]> granicus.if.org Git - icu/commitdiff
Clone parsePreferencesTests from u_parseDelimitedFile (w/ minor mods)
authorHugo van der Merwe <17109322+hugovdm@users.noreply.github.com>
Thu, 12 Mar 2020 17:36:27 +0000 (18:36 +0100)
committerHugo van der Merwe <17109322+hugovdm@users.noreply.github.com>
Fri, 13 Mar 2020 13:13:22 +0000 (14:13 +0100)
icu4c/source/test/intltest/unitstest.cpp

index c8cdfdc6ed4b8ee6a9b1565b71d0c82af5aef3c2..962f8251b7beda77448ac7438e58663bcbac71d5 100644 (file)
@@ -6,6 +6,7 @@
 #if !UCONFIG_NO_FORMATTING
 
 #include "charstr.h"
+#include "filestrm.h"
 #include "intltest.h"
 #include "number_decimalquantity.h"
 #include "unicode/ctest.h"
@@ -217,8 +218,7 @@ void unitsTestDataLineFn(void *context, char *fields[][2], int32_t fieldCount, U
     // Possible after merging in younies/tryingdouble:
     // UnitConverter converter(sourceUnit, targetUnit, *pErrorCode);
     // double got = converter.convert(1000, *pErrorCode);
-    // ((UnitsTest*)context)->assertEqualsNear(quantity.data(), expected, got,
-    // 0.0001);
+    // ((UnitsTest*)context)->assertEqualsNear(quantity.data(), expected, got, 0.0001);
     //
     // In the meantime, printing to stderr.
     fprintf(stderr,
@@ -299,8 +299,7 @@ void unitPreferencesTestDataLineFn(void *context, char *fields[][2], int32_t fie
     // Possible after merging in younies/tryingdouble:
     // UnitConverter converter(sourceUnit, targetUnit, *pErrorCode);
     // double got = converter.convert(1000, *pErrorCode);
-    // ((UnitsTest*)context)->assertEqualsNear(quantity.data(), expected, got,
-    // 0.0001);
+    // ((UnitsTest*)context)->assertEqualsNear(quantity.data(), expected, got, 0.0001);
     //
     // In the meantime, printing to stderr.
     fprintf(stderr,
@@ -312,6 +311,106 @@ void unitPreferencesTestDataLineFn(void *context, char *fields[][2], int32_t fie
             outputUnit.data(), outputR.length(), outputR.data(), expectedOutput);
 }
 
+// WIP(hugovdm): we need to replace u_parseDelimitedFile with something
+// custom, because not all lines in unitPreferencesTest.txt have the same
+// number of fields.
+void parsePreferencesTests(const char *filename, char delimiter, char *fields[][2], int32_t fieldCount,
+                           UParseLineFn *lineFn, void *context, UErrorCode *pErrorCode) {
+    FileStream *file;
+    char line[10000];
+    char *start, *limit;
+    int32_t i, length;
+
+    if (U_FAILURE(*pErrorCode)) { return; }
+
+    if (fields == NULL || lineFn == NULL || fieldCount <= 0) {
+        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
+        return;
+    }
+
+    if (filename == NULL || *filename == 0 || (*filename == '-' && filename[1] == 0)) {
+        filename = NULL;
+        file = T_FileStream_stdin();
+    } else {
+        file = T_FileStream_open(filename, "r");
+    }
+    if (file == NULL) {
+        *pErrorCode = U_FILE_ACCESS_ERROR;
+        return;
+    }
+
+    while (T_FileStream_readLine(file, line, sizeof(line)) != NULL) {
+        /* remove trailing newline characters */
+        length = (int32_t)(u_rtrim(line) - line);
+
+        // FYI: uparse.cpp had this code, which we're skipping here:
+        // /*
+        //  * detect a line with # @missing:
+        //  * start parsing after that, or else from the beginning of the line
+        //  * set the default warning for @missing lines
+        //  */
+        // start = (char *)getMissingLimit(line);
+        // if (start == line) {
+        //   *pErrorCode = U_ZERO_ERROR;
+        // } else {
+        //   *pErrorCode = U_USING_DEFAULT_WARNING;
+        // }
+        start = line;
+        *pErrorCode = U_ZERO_ERROR;
+
+        /* skip this line if it is empty or a comment */
+        if (*start == 0 || *start == '#') { continue; }
+
+        /* remove in-line comments */
+        limit = uprv_strchr(start, '#');
+        if (limit != NULL) {
+            /* get white space before the pound sign */
+            while (limit > start && U_IS_INV_WHITESPACE(*(limit - 1))) {
+                --limit;
+            }
+
+            /* truncate the line */
+            *limit = 0;
+        }
+
+        /* skip lines with only whitespace */
+        if (u_skipWhitespace(start)[0] == 0) { continue; }
+
+        /* for each field, call the corresponding field function */
+        for (i = 0; i < fieldCount; ++i) {
+            /* set the limit pointer of this field */
+            limit = start;
+            while (*limit != delimiter && *limit != 0) {
+                ++limit;
+            }
+
+            /* set the field start and limit in the fields array */
+            fields[i][0] = start;
+            fields[i][1] = limit;
+
+            /* set start to the beginning of the next field, if any */
+            start = limit;
+            if (*start != 0) {
+                ++start;
+            } else if (i + 1 < fieldCount) {
+                *pErrorCode = U_PARSE_ERROR;
+                limit = line + length;
+                i = fieldCount;
+                break;
+            }
+        }
+
+        /* too few fields? */
+        if (U_FAILURE(*pErrorCode)) { break; }
+
+        /* call the field function */
+        lineFn(context, fields, fieldCount, pErrorCode);
+        if (U_FAILURE(*pErrorCode)) { break; }
+    }
+
+    if (filename != NULL) { T_FileStream_close(file); }
+}
+
 /**
  * Runs data-driven unit tests for unit preferences.
  */
@@ -331,11 +430,8 @@ void UnitsTest::testPreferences() {
     path.appendPathPart("units", errorCode);
     path.appendPathPart(filename, errorCode);
 
-    // WIP(hugovdm): we need to replace u_parseDelimitedFile with something
-    // custom, because not all lines in unitPreferencesTest.txt have the same
-    // number of fields.
-    u_parseDelimitedFile(path.data(), ';', fields, kNumFields, unitPreferencesTestDataLineFn, this,
-                         errorCode);
+    parsePreferencesTests(path.data(), ';', fields, kNumFields, unitPreferencesTestDataLineFn, this,
+                          errorCode);
     if (errorCode.errIfFailureAndReset("error parsing %s: %s\n", path.data(), u_errorName(errorCode))) {
         return;
     }