Index: source/common/uloc_tag.c |
diff --git a/source/common/uloc_tag.c b/source/common/uloc_tag.c |
index 0583ea5e1485b485388f70b61f32484a395de159..224470ad89c66e92b74f667b4dc83ef5eb017ee8 100644 |
--- a/source/common/uloc_tag.c |
+++ b/source/common/uloc_tag.c |
@@ -1,3 +1,5 @@ |
+// Copyright (C) 2016 and later: Unicode, Inc. and others. |
+// License & terms of use: http://www.unicode.org/copyright.html |
/* |
********************************************************************** |
* Copyright (C) 2009-2015, International Business Machines |
@@ -17,6 +19,7 @@ |
#include "ulocimp.h" |
#include "uassert.h" |
+ |
/* struct holding a single variant */ |
typedef struct VariantListEntry { |
const char *variant; |
@@ -577,6 +580,14 @@ _addExtensionToList(ExtensionListEntry **first, ExtensionListEntry *ext, UBool l |
cmp = LDMLEXT - *(cur->key); |
} else { |
cmp = uprv_compareInvCharsAsAscii(ext->key, cur->key); |
+ /* Both are u extension keys - we need special handling for 'attribute' */ |
+ if (cmp != 0) { |
+ if (uprv_strcmp(cur->key, LOCALE_ATTRIBUTE_KEY) == 0) { |
+ cmp = 1; |
+ } else if (uprv_strcmp(ext->key, LOCALE_ATTRIBUTE_KEY) == 0) { |
+ cmp = -1; |
+ } |
+ } |
} |
} else { |
cmp = uprv_compareInvCharsAsAscii(ext->key, cur->key); |
@@ -892,7 +903,6 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac |
char buf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; |
char attrBuf[ULOC_KEYWORD_AND_VALUES_CAPACITY] = { 0 }; |
int32_t attrBufLength = 0; |
- UBool isAttribute = FALSE; |
UEnumeration *keywordEnum = NULL; |
int32_t reslen = 0; |
@@ -919,7 +929,6 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac |
UBool isBcpUExt; |
while (TRUE) { |
- isAttribute = FALSE; |
key = uenum_next(keywordEnum, NULL, status); |
if (key == NULL) { |
break; |
@@ -941,7 +950,6 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac |
/* special keyword used for representing Unicode locale attributes */ |
if (uprv_strcmp(key, LOCALE_ATTRIBUTE_KEY) == 0) { |
- isAttribute = TRUE; |
if (len > 0) { |
int32_t i = 0; |
while (TRUE) { |
@@ -984,6 +992,9 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac |
} |
} |
} |
+ /* for a place holder ExtensionListEntry */ |
+ bcpKey = LOCALE_ATTRIBUTE_KEY; |
+ bcpValue = NULL; |
} |
} else if (isBcpUExt) { |
bcpKey = uloc_toUnicodeLocaleKey(key); |
@@ -1063,22 +1074,20 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac |
} |
} |
- if (!isAttribute) { |
- /* create ExtensionListEntry */ |
- ext = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); |
- if (ext == NULL) { |
- *status = U_MEMORY_ALLOCATION_ERROR; |
- break; |
- } |
- ext->key = bcpKey; |
- ext->value = bcpValue; |
+ /* create ExtensionListEntry */ |
+ ext = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); |
+ if (ext == NULL) { |
+ *status = U_MEMORY_ALLOCATION_ERROR; |
+ break; |
+ } |
+ ext->key = bcpKey; |
+ ext->value = bcpValue; |
- if (!_addExtensionToList(&firstExt, ext, TRUE)) { |
- uprv_free(ext); |
- if (strict) { |
- *status = U_ILLEGAL_ARGUMENT_ERROR; |
- break; |
- } |
+ if (!_addExtensionToList(&firstExt, ext, TRUE)) { |
+ uprv_free(ext); |
+ if (strict) { |
+ *status = U_ILLEGAL_ARGUMENT_ERROR; |
+ break; |
} |
} |
} |
@@ -1101,12 +1110,9 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac |
if (U_SUCCESS(*status) && (firstExt != NULL || firstAttr != NULL)) { |
UBool startLDMLExtension = FALSE; |
- |
- attr = firstAttr; |
- ext = firstExt; |
- do { |
- if (!startLDMLExtension && (ext && uprv_strlen(ext->key) > 1)) { |
- /* write LDML singleton extension */ |
+ for (ext = firstExt; ext; ext = ext->next) { |
+ if (!startLDMLExtension && uprv_strlen(ext->key) > 1) { |
+ /* first LDML u singlton extension */ |
if (reslen < capacity) { |
*(appendAt + reslen) = SEP; |
} |
@@ -1120,7 +1126,20 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac |
} |
/* write out the sorted BCP47 attributes, extensions and private use */ |
- if (ext && (uprv_strlen(ext->key) == 1 || attr == NULL)) { |
+ if (uprv_strcmp(ext->key, LOCALE_ATTRIBUTE_KEY) == 0) { |
+ /* write the value for the attributes */ |
+ for (attr = firstAttr; attr; attr = attr->next) { |
+ if (reslen < capacity) { |
+ *(appendAt + reslen) = SEP; |
+ } |
+ reslen++; |
+ len = (int32_t)uprv_strlen(attr->attribute); |
+ if (reslen < capacity) { |
+ uprv_memcpy(appendAt + reslen, attr->attribute, uprv_min(len, capacity - reslen)); |
+ } |
+ reslen += len; |
+ } |
+ } else { |
if (reslen < capacity) { |
*(appendAt + reslen) = SEP; |
} |
@@ -1139,23 +1158,8 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac |
uprv_memcpy(appendAt + reslen, ext->value, uprv_min(len, capacity - reslen)); |
} |
reslen += len; |
- |
- ext = ext->next; |
- } else if (attr) { |
- /* write the value for the attributes */ |
- if (reslen < capacity) { |
- *(appendAt + reslen) = SEP; |
- } |
- reslen++; |
- len = (int32_t)uprv_strlen(attr->attribute); |
- if (reslen < capacity) { |
- uprv_memcpy(appendAt + reslen, attr->attribute, uprv_min(len, capacity - reslen)); |
- } |
- reslen += len; |
- |
- attr = attr->next; |
} |
- } while (attr != NULL || ext != NULL); |
+ } |
} |
cleanup: |
/* clean up */ |
@@ -1771,6 +1775,15 @@ _appendPrivateuseToLanguageTag(const char* localeID, char* appendAt, int32_t cap |
#define EXTV 0x0040 |
#define PRIV 0x0080 |
+/** |
+ * Ticket #12705 - Visual Studio 2015 Update 3 contains a new code optimizer which has problems optimizing |
+ * this function. (See https://blogs.msdn.microsoft.com/vcblog/2016/05/04/new-code-optimizer/ ) |
+ * As a workaround, we will turn off optimization just for this function on VS2015 Update 3 and above. |
+ */ |
+#if (defined(_MSC_VER) && (_MSC_VER >= 1900) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190024210)) |
+#pragma optimize( "", off ) |
+#endif |
+ |
static ULanguageTag* |
ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* status) { |
ULanguageTag *t; |
@@ -2134,6 +2147,13 @@ error: |
return NULL; |
} |
+/** |
+* Ticket #12705 - Turn optimization back on. |
+*/ |
+#if (defined(_MSC_VER) && (_MSC_VER >= 1900) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190024210)) |
+#pragma optimize( "", on ) |
+#endif |
+ |
static void |
ultag_close(ULanguageTag* langtag) { |