]> granicus.if.org Git - icu/commitdiff
ICU-10244 (C) Handle localeDisplayPattern/separator as pattern
authorPeter Edberg <pedberg@unicode.org>
Mon, 8 Jul 2013 06:34:53 +0000 (06:34 +0000)
committerPeter Edberg <pedberg@unicode.org>
Mon, 8 Jul 2013 06:34:53 +0000 (06:34 +0000)
X-SVN-Rev: 33889

icu4c/source/common/locdispnames.cpp
icu4c/source/i18n/locdspnm.cpp

index dd4445246fb4e41754fdb9fb784801f5886493f3..cca0730be9b28b65da41c7e17f1269a2d9b14a6f 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 1997-2012, International Business Machines
+*   Copyright (C) 1997-2013, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
@@ -465,8 +465,7 @@ uloc_getDisplayName(const char *locale,
                     UChar *dest, int32_t destCapacity,
                     UErrorCode *pErrorCode)
 {
-    static const UChar defaultSeparator[3] = { 0x002c, 0x0020, 0x0000 }; /* comma + space */
-    static const int32_t defaultSepLen = 2;
+    static const UChar defaultSeparator[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */
     static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */
     static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */
     static const int32_t subLen = 3;
@@ -518,7 +517,25 @@ uloc_getDisplayName(const char *locale,
     /* If we couldn't find any data, then use the defaults */
     if(sepLen == 0) {
        separator = defaultSeparator;
-       sepLen = defaultSepLen;
+    }
+    /* #10244: Even though separator is now a pattern, it is awkward to handle it as such
+     * here since we are trying to build the display string in place in the dest buffer,
+     * and to handle it as a pattern would entail having separate storage for the
+     * substrings that need to be combined (the first of which may be the result of
+     * previous such combinations). So for now we continue to treat the portion between
+     * {0} and {1} as a string to be appended when joining substrings, ignoring anything
+     * that is before {0} or after {1} (no existing separator pattern has any such thing).
+     * This is similar to how pattern is handled below.
+     */
+    {
+        UChar *p0=u_strstr(separator, sub0);
+        UChar *p1=u_strstr(separator, sub1);
+        if (p0==NULL || p1==NULL || p1<p0) {
+            *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
+            return 0;
+        }
+        separator = (const UChar *)p0 + subLen;
+        sepLen = p1 - separator;
     }
 
     if(patLen==0 || (patLen==defaultPatLen && !u_strncmp(pattern, defaultPattern, patLen))) {
index 9b63a3ed33ab71a023ece8327445ff5093906297..42524102b7cb6a71bfd34aeaf7fe808c8bac3a88 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2010-2012, International Business Machines Corporation and
+* Copyright (C) 2010-2013, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */
@@ -271,7 +271,7 @@ class LocaleDisplayNamesImpl : public LocaleDisplayNames {
     UDialectHandling dialectHandling;
     ICUDataTable langData;
     ICUDataTable regionData;
-    UnicodeString sep;
+    MessageFormat *separatorFormat;
     MessageFormat *format;
     MessageFormat *keyTypeFormat;
     UDisplayContext capitalizationContext;
@@ -333,6 +333,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
     : dialectHandling(dialectHandling)
     , langData(U_ICUDATA_LANG, locale)
     , regionData(U_ICUDATA_REGION, locale)
+    , separatorFormat(NULL)
     , format(NULL)
     , keyTypeFormat(NULL)
     , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
@@ -345,6 +346,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
     : dialectHandling(ULDN_STANDARD_NAMES)
     , langData(U_ICUDATA_LANG, locale)
     , regionData(U_ICUDATA_REGION, locale)
+    , separatorFormat(NULL)
     , format(NULL)
     , keyTypeFormat(NULL)
     , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
@@ -373,17 +375,19 @@ LocaleDisplayNamesImpl::initialize(void) {
         ? regionData.getLocale()
         : langData.getLocale();
 
+    UnicodeString sep;
     langData.getNoFallback("localeDisplayPattern", "separator", sep);
     if (sep.isBogus()) {
-        sep = UnicodeString("", -1, US_INV);
+        sep = UnicodeString("{0}, {1}", -1, US_INV);
     }
+    UErrorCode status = U_ZERO_ERROR;
+    separatorFormat = new MessageFormat(sep, status);
 
     UnicodeString pattern;
     langData.getNoFallback("localeDisplayPattern", "pattern", pattern);
     if (pattern.isBogus()) {
         pattern = UnicodeString("{0} ({1})", -1, US_INV);
     }
-    UErrorCode status = U_ZERO_ERROR;
     format = new MessageFormat(pattern, status);
 
     UnicodeString ktPattern;
@@ -444,6 +448,7 @@ LocaleDisplayNamesImpl::initialize(void) {
 }
 
 LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() {
+    delete separatorFormat;
     delete format;
     delete keyTypeFormat;
  }
@@ -639,10 +644,21 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale,
 
 UnicodeString&
 LocaleDisplayNamesImpl::appendWithSep(UnicodeString& buffer, const UnicodeString& src) const {
-    if (!buffer.isEmpty()) {
-        buffer.append(sep);
+    if (buffer.isEmpty()) {
+        buffer.setTo(src);
+    } else {
+        UnicodeString combined;
+        Formattable data[] = {
+          buffer,
+          src
+        };
+        FieldPosition fpos;
+        UErrorCode status = U_ZERO_ERROR;
+        separatorFormat->format(data, 2, combined, fpos, status);
+        if (U_SUCCESS(status)) {
+            buffer.setTo(combined);
+        }
     }
-    buffer.append(src);
     return buffer;
 }