]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/listformatter.cpp
ICU-57132.0.1.tar.gz
[apple/icu.git] / icuSources / common / listformatter.cpp
index 17bc0666d8bd6a030742b35e6ab731a8e3947d5d..a02549eba9f3cdc6177160b296c68ab2f64ef185 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 2013-2014, International Business Machines
+*   Copyright (C) 2013-2016, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
@@ -15,7 +15,7 @@
 */
 
 #include "unicode/listformatter.h"
-#include "simplepatternformatter.h"
+#include "unicode/simpleformatter.h"
 #include "mutex.h"
 #include "hash.h"
 #include "cstring.h"
 #include "ucln_cmn.h"
 #include "uresimp.h"
 
-#define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0]))
-
 U_NAMESPACE_BEGIN
 
 struct ListFormatInternal : public UMemory {
-    SimplePatternFormatter twoPattern;
-    SimplePatternFormatter startPattern;
-    SimplePatternFormatter middlePattern;
-    SimplePatternFormatter endPattern;
+    SimpleFormatter twoPattern;
+    SimpleFormatter startPattern;
+    SimpleFormatter middlePattern;
+    SimpleFormatter endPattern;
 
 ListFormatInternal(
         const UnicodeString& two,
         const UnicodeString& start,
         const UnicodeString& middle,
-        const UnicodeString& end) :
-        twoPattern(two),
-        startPattern(start),
-        middlePattern(middle),
-        endPattern(end) {}
-
-ListFormatInternal(const ListFormatData &data) :
-        twoPattern(data.twoPattern),
-        startPattern(data.startPattern),
-        middlePattern(data.middlePattern),
-        endPattern(data.endPattern) { }
+        const UnicodeString& end,
+        UErrorCode &errorCode) :
+        twoPattern(two, 2, 2, errorCode),
+        startPattern(start, 2, 2, errorCode),
+        middlePattern(middle, 2, 2, errorCode),
+        endPattern(end, 2, 2, errorCode) {}
+
+ListFormatInternal(const ListFormatData &data, UErrorCode &errorCode) :
+        twoPattern(data.twoPattern, errorCode),
+        startPattern(data.startPattern, errorCode),
+        middlePattern(data.middlePattern, errorCode),
+        endPattern(data.endPattern, errorCode) { }
 
 ListFormatInternal(const ListFormatInternal &other) :
     twoPattern(other.twoPattern),
@@ -180,12 +179,6 @@ static ListFormatInternal* loadListFormatInternal(
     rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode);
     rb = ures_getByKeyWithFallback(rb, style, rb, &errorCode);
 
-    // TODO(Travis Keep): This is a hack until fallbacks can be added for
-    // listPattern/duration and listPattern/duration-narrow in CLDR.
-    if (errorCode == U_MISSING_RESOURCE_ERROR) {
-        errorCode = U_ZERO_ERROR;
-        rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode);
-    }
     if (U_FAILURE(errorCode)) {
         ures_close(rb);
         return NULL;
@@ -199,11 +192,15 @@ static ListFormatInternal* loadListFormatInternal(
     if (U_FAILURE(errorCode)) {
         return NULL;
     }
-    ListFormatInternal* result = new ListFormatInternal(two, start, middle, end);
+    ListFormatInternal* result = new ListFormatInternal(two, start, middle, end, errorCode);
     if (result == NULL) {
         errorCode = U_MEMORY_ALLOCATION_ERROR;
         return NULL;
     }
+    if (U_FAILURE(errorCode)) {
+        delete result;
+        return NULL;
+    }
     return result;
 }
 
@@ -239,8 +236,8 @@ ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *s
     return p;
 }
 
-ListFormatter::ListFormatter(const ListFormatData& listFormatData) {
-    owned = new ListFormatInternal(listFormatData);
+ListFormatter::ListFormatter(const ListFormatData& listFormatData, UErrorCode &errorCode) {
+    owned = new ListFormatInternal(listFormatData, errorCode);
     data = owned;
 }
 
@@ -256,10 +253,11 @@ ListFormatter::~ListFormatter() {
  * On entry offset is an offset into first or -1 if offset unspecified.
  * On exit offset is offset of second in result if recordOffset was set
  * Otherwise if it was >=0 it is set to point into result where it used
- * to point into first.
+ * to point into first. On exit, result is the join of first and second
+ * according to pat. Any previous value of result gets replaced.
  */
-static void joinStrings(
-        const SimplePatternFormatter& pat,
+static void joinStringsAndReplace(
+        const SimpleFormatter& pat,
         const UnicodeString& first,
         const UnicodeString& second,
         UnicodeString &result,
@@ -271,12 +269,12 @@ static void joinStrings(
     }
     const UnicodeString *params[2] = {&first, &second};
     int32_t offsets[2];
-    pat.format(
+    pat.formatAndReplace(
             params,
-            LENGTHOF(params),
+            UPRV_LENGTHOF(params),
             result,
             offsets,
-            LENGTHOF(offsets),
+            UPRV_LENGTHOF(offsets),
             errorCode);
     if (U_FAILURE(errorCode)) {
         return;
@@ -327,62 +325,43 @@ UnicodeString& ListFormatter::format(
         appendTo.append(items[0]);
         return appendTo;
     }
-    if (nItems == 2) {
-        if (index == 0) {
-            offset = 0;
-        }
-        joinStrings(
-                data->twoPattern,
-                items[0],
-                items[1],
-                appendTo,
-                index == 1,
-                offset,
-                errorCode);
-        return appendTo;
-    }
-    UnicodeString temp[2];
+    UnicodeString result(items[0]);
     if (index == 0) {
         offset = 0;
     }
-    joinStrings(
-            data->startPattern,
-            items[0],
+    joinStringsAndReplace(
+            nItems == 2 ? data->twoPattern : data->startPattern,
+            result,
             items[1],
-            temp[0],
+            result,
             index == 1,
             offset,
             errorCode);
-    int32_t i;
-    int32_t pos = 0;
-    int32_t npos = 1;
-    for (i = 2; i < nItems - 1; ++i) {
-         temp[npos].remove();
-         joinStrings(
-                 data->middlePattern,
-                 temp[pos],
-                 items[i],
-                 temp[npos],
-                 index == i,
-                 offset,
-                 errorCode);
-         pos = npos;
-         npos = (pos + 1) & 1;
+    if (nItems > 2) {
+        for (int32_t i = 2; i < nItems - 1; ++i) {
+             joinStringsAndReplace(
+                     data->middlePattern,
+                     result,
+                     items[i],
+                     result,
+                     index == i,
+                     offset,
+                     errorCode);
+        }
+        joinStringsAndReplace(
+                data->endPattern,
+                result,
+                items[nItems - 1],
+                result,
+                index == nItems - 1,
+                offset,
+                errorCode);
     }
-    temp[npos].remove();
-    joinStrings(
-            data->endPattern,
-            temp[pos],
-            items[nItems - 1],
-            temp[npos],
-            index == nItems - 1,
-            offset,
-            errorCode);
     if (U_SUCCESS(errorCode)) {
         if (offset >= 0) {
             offset += appendTo.length();
         }
-        appendTo += temp[npos];
+        appendTo += result;
     }
     return appendTo;
 }