uloc_tag.c revision 54dcd9b6a06071f647dac967e9e267abb9410720
1b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 2b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru********************************************************************** 3103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius* Copyright (C) 2009-2012, International Business Machines 4b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Corporation and others. All Rights Reserved. 5b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru********************************************************************** 6b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 7b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 8b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/utypes.h" 9b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/ures.h" 10b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/putil.h" 11b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/uloc.h" 12b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "ustr_imp.h" 13b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "cmemory.h" 14b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "cstring.h" 15b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "putilimp.h" 1650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uinvchar.h" 17b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "ulocimp.h" 1854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "uassert.h" 1954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 2054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 21b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 22b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* struct holding a single variant */ 23b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct VariantListEntry { 24b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *variant; 25b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru struct VariantListEntry *next; 26b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} VariantListEntry; 27b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/* struct holding a single attribute value */ 29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct AttributeListEntry { 30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const char *attribute; 31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho struct AttributeListEntry *next; 32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} AttributeListEntry; 33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 34b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* struct holding a single extension */ 35b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct ExtensionListEntry { 36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key; 37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *value; 38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru struct ExtensionListEntry *next; 39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} ExtensionListEntry; 40b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 41b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAXEXTLANG 3 42b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct ULanguageTag { 43b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *buf; /* holding parsed subtags */ 44b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *language; 45b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *extlang[MAXEXTLANG]; 46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *script; 47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *region; 48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *variants; 49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *extensions; 50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *privateuse; 51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *grandfathered; 52b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} ULanguageTag; 53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 54b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MINLEN 2 55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define SEP '-' 56b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define PRIVATEUSE 'x' 57b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LDMLEXT 'u' 58b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 59b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LOCALE_SEP '_' 60b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LOCALE_EXT_SEP '@' 61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LOCALE_KEYWORD_SEP ';' 62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LOCALE_KEY_TYPE_SEP '=' 63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 64103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#define ISALPHA(c) uprv_isASCIILetter(c) 65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define ISNUMERIC(c) ((c)>='0' && (c)<='9') 66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 6754dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char EMPTY[] = ""; 6854dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char LANG_UND[] = "und"; 6954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char PRIVATEUSE_KEY[] = "x"; 7054dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char _POSIX[] = "_POSIX"; 7154dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char POSIX_KEY[] = "va"; 7254dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char POSIX_VALUE[] = "posix"; 7354dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char LOCALE_ATTRIBUTE_KEY[] = "attribute"; 7454dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char PRIVUSE_VARIANT_PREFIX[] = "lvariant"; 7554dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char LOCALE_TYPE_YES[] = "yes"; 76b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 77b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LANG_UND_LEN 3 78b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 7954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char* const GRANDFATHERED[] = { 80b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* grandfathered preferred */ 81b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "art-lojban", "jbo", 82b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho "cel-gaulish", "xtg-x-cel-gaulish", 83b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho "en-GB-oed", "en-GB-x-oed", 84b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-ami", "ami", 85b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-bnn", "bnn", 86b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho "i-default", "en-x-i-default", 87b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho "i-enochian", "und-x-i-enochian", 88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-hak", "hak", 89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-klingon", "tlh", 90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-lux", "lb", 91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho "i-mingo", "see-x-i-mingo", 92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-navajo", "nv", 93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-pwn", "pwn", 94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-tao", "tao", 95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-tay", "tay", 96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-tsu", "tsu", 97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "no-bok", "nb", 98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "no-nyn", "nn", 99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "sgn-be-fr", "sfb", 100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "sgn-be-nl", "vgt", 101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "sgn-ch-de", "sgg", 102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-guoyu", "cmn", 103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-hakka", "hak", 104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho "zh-min", "nan-x-zh-min", 105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-min-nan", "nan", 106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-xiang", "hsn", 107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru NULL, NULL 108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}; 109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 11054dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char DEPRECATEDLANGS[][4] = { 111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* deprecated new */ 112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "iw", "he", 113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "ji", "yi", 11454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius "in", "id" 115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}; 116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* These ultag_ functions may be exposed as APIs later 121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic ULanguageTag* 126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* status); 127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_close(ULanguageTag* langtag); 130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getLanguage(const ULanguageTag* langtag); 133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if 0 135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getJDKLanguage(const ULanguageTag* langtag); 137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtlang(const ULanguageTag* langtag, int32_t idx); 141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtlangSize(const ULanguageTag* langtag); 144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getScript(const ULanguageTag* langtag); 147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getRegion(const ULanguageTag* langtag); 150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getVariant(const ULanguageTag* langtag, int32_t idx); 153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getVariantsSize(const ULanguageTag* langtag); 156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionKey(const ULanguageTag* langtag, int32_t idx); 159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionValue(const ULanguageTag* langtag, int32_t idx); 162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionsSize(const ULanguageTag* langtag); 165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getPrivateUse(const ULanguageTag* langtag); 168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if 0 170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getGrandfathered(const ULanguageTag* langtag); 172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Language subtag syntax validation functions 178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isAlphaString(const char* s, int32_t len) { 184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < len; i++) { 186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ISALPHA(*(s + i))) { 187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isNumericString(const char* s, int32_t len) { 195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < len; i++) { 197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ISNUMERIC(*(s + i))) { 198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isAlphaNumericString(const char* s, int32_t len) { 206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < len; i++) { 208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ISALPHA(*(s + i)) && !ISNUMERIC(*(s + i))) { 209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isLanguageSubtag(const char* s, int32_t len) { 217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * language = 2*3ALPHA ; shortest ISO 639 code 219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ["-" extlang] ; sometimes followed by 220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ; extended language subtags 221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * / 4ALPHA ; or reserved for future use 222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * / 5*8ALPHA ; or registered language subtag 223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 22550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 2 && len <= 8 && _isAlphaString(s, len)) { 228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isExtlangSubtag(const char* s, int32_t len) { 235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * extlang = 3ALPHA ; selected ISO 639 codes 237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * *2("-" 3ALPHA) ; permanently reserved 238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 24050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 3 && _isAlphaString(s, len)) { 243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isScriptSubtag(const char* s, int32_t len) { 250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * script = 4ALPHA ; ISO 15924 code 252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 25450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 4 && _isAlphaString(s, len)) { 257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isRegionSubtag(const char* s, int32_t len) { 264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * region = 2ALPHA ; ISO 3166-1 code 266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * / 3DIGIT ; UN M.49 code 267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 26950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 2 && _isAlphaString(s, len)) { 272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 3 && _isNumericString(s, len)) { 275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isVariantSubtag(const char* s, int32_t len) { 282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * variant = 5*8alphanum ; registered variants 284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * / (DIGIT 3alphanum) 285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 28750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len >= 5 && len <= 8 && _isAlphaNumericString(s, len)) { 290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 4 && ISNUMERIC(*s) && _isAlphaNumericString(s + 1, 3)) { 293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho_isPrivateuseVariantSubtag(const char* s, int32_t len) { 300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* 301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * variant = 1*8alphanum ; registered variants 302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * / (DIGIT 3alphanum) 303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len < 0) { 305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = (int32_t)uprv_strlen(s); 306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len >= 1 && len <= 8 && _isAlphaNumericString(s, len)) { 308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return TRUE; 309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return FALSE; 311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool 314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isExtensionSingleton(const char* s, int32_t len) { 315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * extension = singleton 1*("-" (2*8alphanum)) 317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 31950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 1 && ISALPHA(*s) && (uprv_tolower(*s) != PRIVATEUSE)) { 322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isExtensionSubtag(const char* s, int32_t len) { 329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * extension = singleton 1*("-" (2*8alphanum)) 331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 2 && len <= 8 && _isAlphaNumericString(s, len)) { 336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isExtensionSubtags(const char* s, int32_t len) { 343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *p = s; 344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *pSubtag = NULL; 345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ((p - s) < len) { 351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*p == SEP) { 352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pSubtag == NULL) { 353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!_isExtensionSubtag(pSubtag, (int32_t)(p - pSubtag))) { 356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = NULL; 359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (pSubtag == NULL) { 360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = p; 361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pSubtag == NULL) { 365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 36750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return _isExtensionSubtag(pSubtag, (int32_t)(p - pSubtag)); 368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isPrivateuseValueSubtag(const char* s, int32_t len) { 372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * privateuse = "x" 1*("-" (1*8alphanum)) 374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 37650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 1 && len <= 8 && _isAlphaNumericString(s, len)) { 379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isPrivateuseValueSubtags(const char* s, int32_t len) { 386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *p = s; 387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *pSubtag = NULL; 388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ((p - s) < len) { 394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*p == SEP) { 395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pSubtag == NULL) { 396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!_isPrivateuseValueSubtag(pSubtag, (int32_t)(p - pSubtag))) { 399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = NULL; 402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (pSubtag == NULL) { 403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = p; 404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pSubtag == NULL) { 408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return _isPrivateuseValueSubtag(pSubtag, (int32_t)(p - pSubtag)); 411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isLDMLKey(const char* s, int32_t len) { 415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 2 && _isAlphaNumericString(s, len)) { 419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isLDMLType(const char* s, int32_t len) { 426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 3 && len <= 8 && _isAlphaNumericString(s, len)) { 430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Helper functions 439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_addVariantToList(VariantListEntry **first, VariantListEntry *var) { 445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool bAdded = TRUE; 446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*first == NULL) { 448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var->next = NULL; 449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *first = var; 450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *prev, *cur; 452b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t cmp; 453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* variants order should be preserved */ 455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev = NULL; 456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = *first; 457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cur == NULL) { 459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev->next = var; 460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var->next = NULL; 461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* Checking for duplicate variant */ 46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cmp = uprv_compareInvCharsAsAscii(var->variant, cur->variant); 466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (cmp == 0) { 467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* duplicated variant */ 468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho bAdded = FALSE; 469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho prev = cur; 472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cur = cur->next; 473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return bAdded; 477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool 480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho_addAttributeToList(AttributeListEntry **first, AttributeListEntry *attr) { 481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool bAdded = TRUE; 482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (*first == NULL) { 484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attr->next = NULL; 485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *first = attr; 486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho AttributeListEntry *prev, *cur; 488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t cmp; 489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* reorder variants in alphabetical order */ 491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho prev = NULL; 492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cur = *first; 493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while (TRUE) { 494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (cur == NULL) { 495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho prev->next = attr; 496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attr->next = NULL; 497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cmp = uprv_compareInvCharsAsAscii(attr->attribute, cur->attribute); 500b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cmp < 0) { 501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (prev == NULL) { 502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *first = attr; 503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho prev->next = attr; 505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attr->next = cur; 507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cmp == 0) { 510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* duplicated variant */ 511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bAdded = FALSE; 512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev = cur; 515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return bAdded; 520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_addExtensionToList(ExtensionListEntry **first, ExtensionListEntry *ext, UBool localeToBCP) { 525b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool bAdded = TRUE; 526b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*first == NULL) { 528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext->next = NULL; 529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *first = ext; 530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *prev, *cur; 532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t cmp; 533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* reorder variants in alphabetical order */ 535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev = NULL; 536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = *first; 537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cur == NULL) { 539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev->next = ext; 540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext->next = NULL; 541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (localeToBCP) { 544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* special handling for locale to bcp conversion */ 545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len, curlen; 546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 54750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(ext->key); 54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho curlen = (int32_t)uprv_strlen(cur->key); 549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 550b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 1 && curlen == 1) { 551b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*(ext->key) == *(cur->key)) { 552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = 0; 553b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (*(ext->key) == PRIVATEUSE) { 554b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = 1; 555b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (*(cur->key) == PRIVATEUSE) { 556b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = -1; 557b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 558b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = *(ext->key) - *(cur->key); 559b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 560b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (len == 1) { 561b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = *(ext->key) - LDMLEXT; 562b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (curlen == 1) { 563b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = LDMLEXT - *(cur->key); 564b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cmp = uprv_compareInvCharsAsAscii(ext->key, cur->key); 566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 56850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cmp = uprv_compareInvCharsAsAscii(ext->key, cur->key); 569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cmp < 0) { 571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (prev == NULL) { 572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *first = ext; 573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev->next = ext; 575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext->next = cur; 577b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 578b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 579b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cmp == 0) { 580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* duplicated extension key */ 581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bAdded = FALSE; 582b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 584b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev = cur; 585b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 586b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 587b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 588b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 589b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return bAdded; 590b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 592b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 593b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_initializeULanguageTag(ULanguageTag* langtag) { 594b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 596b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->buf = NULL; 597b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 598b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->language = EMPTY; 599b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < MAXEXTLANG; i++) { 600b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->extlang[i] = NULL; 601b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 602b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 603b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->script = EMPTY; 604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->region = EMPTY; 605b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 606b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->variants = NULL; 607b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->extensions = NULL; 608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->grandfathered = EMPTY; 610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->privateuse = EMPTY; 611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 61350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define KEYTYPEDATA "keyTypeData" 61450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define KEYMAP "keyMap" 61550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define TYPEMAP "typeMap" 61650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define TYPEALIAS "typeAlias" 617b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX_BCP47_SUBTAG_LEN 9 /* including null terminator */ 618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX_LDML_KEY_LEN 22 619b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX_LDML_TYPE_LEN 32 620b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 621b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 622b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_ldmlKeyToBCP47(const char* key, int32_t keyLen, 623b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* bcpKey, int32_t bcpKeyCapacity, 624b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 625b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *rb; 626b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char keyBuf[MAX_LDML_KEY_LEN]; 627b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char bcpKeyBuf[MAX_BCP47_SUBTAG_LEN]; 628b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t resultLen = 0; 629b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 630b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 631b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar *uBcpKey; 632b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t bcpKeyLen; 633b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 634b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen < 0) { 63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyLen = (int32_t)uprv_strlen(key); 636b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 637b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 638b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen >= sizeof(keyBuf)) { 639b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* no known valid LDML key exceeding 21 */ 640b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 641b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 642b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 643b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 644b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(keyBuf, key, keyLen); 645b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[keyLen] = 0; 646b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 647b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 648b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < keyLen; i++) { 649b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[i] = uprv_tolower(keyBuf[i]); 650b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 651b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rb = ures_openDirect(NULL, KEYTYPEDATA, status); 65350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, KEYMAP, rb, status); 654b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 655b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 656b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 657b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 658b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 659b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 660b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uBcpKey = ures_getStringByKey(rb, keyBuf, &bcpKeyLen, &tmpStatus); 661b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(tmpStatus)) { 662b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uBcpKey, bcpKeyBuf, bcpKeyLen); 663b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKeyBuf[bcpKeyLen] = 0; 664b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = bcpKeyLen; 665b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 666b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isLDMLKey(key, keyLen)) { 667b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpKeyBuf, key, keyLen); 668b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKeyBuf[keyLen] = 0; 669b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = keyLen; 670b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 671b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* mapping not availabe */ 672b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 673b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 674b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 675b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 676b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 677b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 678b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 679b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 680b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 681b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpKey, bcpKeyBuf, uprv_min(resultLen, bcpKeyCapacity)); 682b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(bcpKey, bcpKeyCapacity, resultLen, status); 683b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 684b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 685b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 686b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_bcp47ToLDMLKey(const char* bcpKey, int32_t bcpKeyLen, 687b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* key, int32_t keyCapacity, 688b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 689b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *rb; 690b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char bcpKeyBuf[MAX_BCP47_SUBTAG_LEN]; 691b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t resultLen = 0; 692b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 693b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *resKey = NULL; 69450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *mapData; 695b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 696b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (bcpKeyLen < 0) { 69750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bcpKeyLen = (int32_t)uprv_strlen(bcpKey); 698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (bcpKeyLen >= sizeof(bcpKeyBuf)) { 701b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 702b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 703b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 704b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 705b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpKeyBuf, bcpKey, bcpKeyLen); 706b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKeyBuf[bcpKeyLen] = 0; 707b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 708b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 709b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < bcpKeyLen; i++) { 710b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKeyBuf[i] = uprv_tolower(bcpKeyBuf[i]); 711b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 71350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rb = ures_openDirect(NULL, KEYTYPEDATA, status); 71450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, KEYMAP, rb, status); 715b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 716b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 717b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 718b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 719b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 72050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapData = ures_getNextResource(rb, NULL, status); 721b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (U_SUCCESS(*status)) { 722b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar *uBcpKey; 723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char tmpBcpKeyBuf[MAX_BCP47_SUBTAG_LEN]; 724b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t tmpBcpKeyLen; 725b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 72650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uBcpKey = ures_getString(mapData, &tmpBcpKeyLen, status); 727b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 728b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 729b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 730b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uBcpKey, tmpBcpKeyBuf, tmpBcpKeyLen); 731b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpBcpKeyBuf[tmpBcpKeyLen] = 0; 73250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(bcpKeyBuf, tmpBcpKeyBuf) == 0) { 733b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* found a matching BCP47 key */ 73450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resKey = ures_getKey(mapData); 73550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resultLen = (int32_t)uprv_strlen(resKey); 736b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 737b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 738b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ures_hasNext(rb)) { 739b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 740b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 74150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getNextResource(rb, mapData, status); 742b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 74350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(mapData); 744b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 745b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 746b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 747b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 748b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 749b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 750b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (resKey == NULL) { 751b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resKey = bcpKeyBuf; 752b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = bcpKeyLen; 753b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 754b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 755b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(key, resKey, uprv_min(resultLen, keyCapacity)); 756b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(key, keyCapacity, resultLen, status); 757b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 758b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 759b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 760b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_ldmlTypeToBCP47(const char* key, int32_t keyLen, 761b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char* type, int32_t typeLen, 762b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* bcpType, int32_t bcpTypeCapacity, 763b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 76450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *rb, *keyTypeData, *typeMapForKey; 765b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char keyBuf[MAX_LDML_KEY_LEN]; 766b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char typeBuf[MAX_LDML_TYPE_LEN]; 767b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char bcpTypeBuf[MAX_BCP47_SUBTAG_LEN]; 768b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t resultLen = 0; 769b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 770b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 77150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *uBcpType, *uCanonicalType; 77250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t bcpTypeLen, canonicalTypeLen; 773b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool isTimezone = FALSE; 774b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 775b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen < 0) { 77650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyLen = (int32_t)uprv_strlen(key); 777b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 778b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen >= sizeof(keyBuf)) { 779b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* no known valid LDML key exceeding 21 */ 780b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 781b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 782b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 783b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(keyBuf, key, keyLen); 784b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[keyLen] = 0; 785b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 786b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 787b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < keyLen; i++) { 788b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[i] = uprv_tolower(keyBuf[i]); 789b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 79050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(keyBuf, "timezone") == 0) { 791b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru isTimezone = TRUE; 792b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 793b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 794b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (typeLen < 0) { 79550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeLen = (int32_t)uprv_strlen(type); 796b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 797b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (typeLen >= sizeof(typeBuf)) { 798b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 801b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 80250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (isTimezone) { 80350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* replace '/' with ':' */ 80450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < typeLen; i++) { 80550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*(type + i) == '/') { 80650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[i] = ':'; 80750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 80850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[i] = *(type + i); 80950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 810b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 81150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[typeLen] = 0; 81250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho type = &typeBuf[0]; 813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 81550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyTypeData = ures_openDirect(NULL, KEYTYPEDATA, status); 81650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rb = ures_getByKey(keyTypeData, TYPEMAP, NULL, status); 817b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 818b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 81950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(keyTypeData); 820b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 821b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 822b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 82350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeMapForKey = ures_getByKey(rb, keyBuf, NULL, &tmpStatus); 82450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uBcpType = ures_getStringByKey(typeMapForKey, type, &bcpTypeLen, &tmpStatus); 825b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(tmpStatus)) { 826b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uBcpType, bcpTypeBuf, bcpTypeLen); 827b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = bcpTypeLen; 828b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (tmpStatus == U_MISSING_RESOURCE_ERROR) { 82950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is this type alias? */ 83050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tmpStatus = U_ZERO_ERROR; 83150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(keyTypeData, TYPEALIAS, rb, &tmpStatus); 83250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, keyBuf, rb, &tmpStatus); 83350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uCanonicalType = ures_getStringByKey(rb, type, &canonicalTypeLen, &tmpStatus); 83450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(tmpStatus)) { 83550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_UCharsToChars(uCanonicalType, typeBuf, canonicalTypeLen); 83650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (isTimezone) { 83750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* replace '/' with ':' */ 83850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < canonicalTypeLen; i++) { 83950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (typeBuf[i] == '/') { 84050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[i] = ':'; 84150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 84250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 84350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 84450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[canonicalTypeLen] = 0; 84550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 84650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* look up the canonical type */ 84750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uBcpType = ures_getStringByKey(typeMapForKey, typeBuf, &bcpTypeLen, &tmpStatus); 84850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(tmpStatus)) { 84950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_UCharsToChars(uBcpType, bcpTypeBuf, bcpTypeLen); 85050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resultLen = bcpTypeLen; 85150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 85250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 85350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tmpStatus == U_MISSING_RESOURCE_ERROR) { 85450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (_isLDMLType(type, typeLen)) { 85550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memcpy(bcpTypeBuf, type, typeLen); 85650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resultLen = typeLen; 85750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 85850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* mapping not availabe */ 85950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 86050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = tmpStatus; 864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 865b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 86650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(typeMapForKey); 86750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(keyTypeData); 868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 872b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 873b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpType, bcpTypeBuf, uprv_min(resultLen, bcpTypeCapacity)); 874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(bcpType, bcpTypeCapacity, resultLen, status); 875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_bcp47ToLDMLType(const char* key, int32_t keyLen, 879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char* bcpType, int32_t bcpTypeLen, 880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* type, int32_t typeCapacity, 881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *rb; 883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char keyBuf[MAX_LDML_KEY_LEN]; 884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char bcpTypeBuf[ULOC_KEYWORDS_CAPACITY]; /* ensure buffter is large enough for multiple values (e.g. buddhist-greg) */ 885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t resultLen = 0; 886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t i, typeSize; 887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *resType = NULL; 88850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *mapData; 889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t copyLen; 891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen < 0) { 89350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyLen = (int32_t)uprv_strlen(key); 894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen >= sizeof(keyBuf)) { 897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* no known valid LDML key exceeding 21 */ 898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 901b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(keyBuf, key, keyLen); 902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[keyLen] = 0; 903b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 904b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < keyLen; i++) { 906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[i] = uprv_tolower(keyBuf[i]); 907b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 910b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (bcpTypeLen < 0) { 91150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bcpTypeLen = (int32_t)uprv_strlen(bcpType); 912b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 914b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho typeSize = 0; 915b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (i = 0; i < bcpTypeLen; i++) { 916b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (bcpType[i] == SEP) { 917b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (typeSize >= MAX_BCP47_SUBTAG_LEN) { 918b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 919b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 920b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 921b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho typeSize = 0; 922b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 923b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho typeSize++; 924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpTypeBuf, bcpType, bcpTypeLen); 928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpTypeBuf[bcpTypeLen] = 0; 929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < bcpTypeLen; i++) { 932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpTypeBuf[i] = uprv_tolower(bcpTypeBuf[i]); 933b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 934b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 93550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rb = ures_openDirect(NULL, KEYTYPEDATA, status); 93650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, TYPEMAP, rb, status); 937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 938b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 939b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 940b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 941b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 942b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_getByKey(rb, keyBuf, rb, &tmpStatus); 94350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapData = ures_getNextResource(rb, NULL, &tmpStatus); 944b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (U_SUCCESS(tmpStatus)) { 945b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar *uBcpType; 946b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char tmpBcpTypeBuf[MAX_BCP47_SUBTAG_LEN]; 947b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t tmpBcpTypeLen; 948b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 94950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uBcpType = ures_getString(mapData, &tmpBcpTypeLen, &tmpStatus); 950b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus)) { 951b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 952b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 953b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uBcpType, tmpBcpTypeBuf, tmpBcpTypeLen); 954b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpBcpTypeBuf[tmpBcpTypeLen] = 0; 95550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(bcpTypeBuf, tmpBcpTypeBuf) == 0) { 956b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* found a matching BCP47 type */ 95750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resType = ures_getKey(mapData); 95850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resultLen = (int32_t)uprv_strlen(resType); 959b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 960b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 961b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ures_hasNext(rb)) { 962b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 963b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 96450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getNextResource(rb, mapData, &tmpStatus); 965b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 96650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(mapData); 967b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 968b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 969b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) && tmpStatus != U_MISSING_RESOURCE_ERROR) { 970b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = tmpStatus; 971b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 972b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 973b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 974b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (resType == NULL) { 975b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resType = bcpTypeBuf; 976b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = bcpTypeLen; 977b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 978b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 979b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru copyLen = uprv_min(resultLen, typeCapacity); 980b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(type, resType, copyLen); 981b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 98250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(keyBuf, "timezone") == 0) { 983b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < copyLen; i++) { 984b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*(type + i) == ':') { 985b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(type + i) = '/'; 986b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 987b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 988b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 989b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 990b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(type, typeCapacity, resultLen, status); 991b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 992b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 993b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 994b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_appendLanguageToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UErrorCode* status) { 995b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_LANG_CAPACITY]; 996b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 997b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len, i; 998b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 999b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1000b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1001b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1002b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1003b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1004b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getLanguage(localeID, buf, sizeof(buf), &tmpStatus); 1005b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1006b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1007b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1008b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1009b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1010b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = 0; 1011b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1012b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1013b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Note: returned language code is in lower case letters */ 1014b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1015b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 0) { 1016b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1017b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, LANG_UND, uprv_min(LANG_UND_LEN, capacity - reslen)); 1018b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1019b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += LANG_UND_LEN; 1020b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (!_isLanguageSubtag(buf, len)) { 1021b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* invalid language code */ 1022b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1023b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1024b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1025b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1026b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1027b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, LANG_UND, uprv_min(LANG_UND_LEN, capacity - reslen)); 1028b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1029b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += LANG_UND_LEN; 1030b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1031b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* resolve deprecated */ 103254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius for (i = 0; i < LENGTHOF(DEPRECATEDLANGS); i += 2) { 103350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(buf, DEPRECATEDLANGS[i]) == 0) { 1034b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_strcpy(buf, DEPRECATEDLANGS[i + 1]); 103550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(buf); 1036b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1037b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1038b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1039b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1040b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, buf, uprv_min(len, capacity - reslen)); 1041b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1042b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1043b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1044b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_terminateChars(appendAt, capacity, reslen, status); 1045b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 1046b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1047b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1048b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 1049b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_appendScriptToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UErrorCode* status) { 1050b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_SCRIPT_CAPACITY]; 1051b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 105250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t len; 1053b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1054b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1055b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1056b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1057b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1058b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1059b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getScript(localeID, buf, sizeof(buf), &tmpStatus); 1060b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1061b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1062b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1064b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1065b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1066b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1067b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 1068b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isScriptSubtag(buf, len)) { 1069b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* invalid script code */ 1070b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1071b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1072b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1073b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1074b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1075b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1076b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1077b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1078b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1079b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1081b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, buf, uprv_min(len, capacity - reslen)); 1082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1084b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1085b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1086b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_terminateChars(appendAt, capacity, reslen, status); 1087b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 1088b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1089b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1090b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 1091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_appendRegionToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UErrorCode* status) { 1092b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_COUNTRY_CAPACITY]; 1093b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 109450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t len; 1095b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1096b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1097b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1098b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1099b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getCountry(localeID, buf, sizeof(buf), &tmpStatus); 1102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 1110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isRegionSubtag(buf, len)) { 1111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* invalid region code */ 1112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, buf, uprv_min(len, capacity - reslen)); 1124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_terminateChars(appendAt, capacity, reslen, status); 1129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 1130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 113327f654740f2a26ad62a5c155af9199af9e69b889claireho_appendVariantsToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UBool *hadPosix, UErrorCode* status) { 1134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_FULLNAME_CAPACITY]; 1135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 1136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len, i; 1137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getVariant(localeID, buf, sizeof(buf), &tmpStatus); 1144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 1152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *p, *pVar; 1153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool bNext = TRUE; 1154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *var; 1155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *varFirst = NULL; 1156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pVar = NULL; 1158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = buf; 1159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (bNext) { 1160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*p == SEP || *p == LOCALE_SEP || *p == 0) { 1161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*p == 0) { 1162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bNext = FALSE; 1163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *p = 0; /* terminate */ 1165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pVar == NULL) { 1167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* ignore empty variant */ 1172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 117350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* ICU uses upper case letters for variants, but 117450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho the canonical format is lowercase in BCP47 */ 1175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; *(pVar + i) != 0; i++) { 1176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(pVar + i) = uprv_tolower(*(pVar + i)); 1177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* validate */ 1180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isVariantSubtag(pVar, -1)) { 1181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (uprv_strcmp(pVar,POSIX_VALUE) || len != uprv_strlen(POSIX_VALUE)) { 118227f654740f2a26ad62a5c155af9199af9e69b889claireho /* emit the variant to the list */ 118354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius var = (VariantListEntry*)uprv_malloc(sizeof(VariantListEntry)); 118427f654740f2a26ad62a5c155af9199af9e69b889claireho if (var == NULL) { 118527f654740f2a26ad62a5c155af9199af9e69b889claireho *status = U_MEMORY_ALLOCATION_ERROR; 1186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 118827f654740f2a26ad62a5c155af9199af9e69b889claireho var->variant = pVar; 118927f654740f2a26ad62a5c155af9199af9e69b889claireho if (!_addVariantToList(&varFirst, var)) { 119027f654740f2a26ad62a5c155af9199af9e69b889claireho /* duplicated variant */ 119127f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_free(var); 119227f654740f2a26ad62a5c155af9199af9e69b889claireho if (strict) { 119327f654740f2a26ad62a5c155af9199af9e69b889claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 119427f654740f2a26ad62a5c155af9199af9e69b889claireho break; 119527f654740f2a26ad62a5c155af9199af9e69b889claireho } 119627f654740f2a26ad62a5c155af9199af9e69b889claireho } 119727f654740f2a26ad62a5c155af9199af9e69b889claireho } else { 119827f654740f2a26ad62a5c155af9199af9e69b889claireho /* Special handling for POSIX variant, need to remember that we had it and then */ 119927f654740f2a26ad62a5c155af9199af9e69b889claireho /* treat it like an extension later. */ 120027f654740f2a26ad62a5c155af9199af9e69b889claireho *hadPosix = TRUE; 1201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (strict) { 1203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (_isPrivateuseValueSubtag(pVar, -1)) { 1206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* Handle private use subtags separately */ 1207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* reset variant starting position */ 1211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pVar = NULL; 1212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (pVar == NULL) { 1213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pVar = p; 1214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 1216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(*status)) { 1219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (varFirst != NULL) { 1220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t varLen; 1221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* write out validated/normalized variants to the target */ 1223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = varFirst; 1224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (var != NULL) { 1225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 122950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho varLen = (int32_t)uprv_strlen(var->variant); 1230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, var->variant, uprv_min(varLen, capacity - reslen)); 1232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += varLen; 1234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = var->next; 1235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* clean up */ 1240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = varFirst; 1241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (var != NULL) { 1242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *tmpVar = var->next; 1243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(var); 1244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = tmpVar; 1245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_terminateChars(appendAt, capacity, reslen, status); 1253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 1254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 125727f654740f2a26ad62a5c155af9199af9e69b889claireho_appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UBool hadPosix, UErrorCode* status) { 1258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; 1259103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius char attrBuf[ULOC_KEYWORD_AND_VALUES_CAPACITY] = { 0 }; 1260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t attrBufLength = 0; 1261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool isAttribute = FALSE; 1262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UEnumeration *keywordEnum = NULL; 1263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keywordEnum = uloc_openKeywords(localeID, status); 126627f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_FAILURE(*status) && !hadPosix) { 1267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uenum_close(keywordEnum); 1268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 127027f654740f2a26ad62a5c155af9199af9e69b889claireho if (keywordEnum != NULL || hadPosix) { 1271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* reorder extensions */ 1272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len; 1273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key; 1274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *firstExt = NULL; 1275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *ext; 1276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho AttributeListEntry *firstAttr = NULL; 1277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho AttributeListEntry *attr; 1278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char *attrValue; 1279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char extBuf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; 1280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *pExtBuf = extBuf; 1281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t extBufCapacity = sizeof(extBuf); 1282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *bcpKey, *bcpValue; 1283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 1284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t keylen; 1285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool isLDMLKeyword; 1286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 1288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho isAttribute = FALSE; 1289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru key = uenum_next(keywordEnum, NULL, status); 1290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (key == NULL) { 1291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getKeywordValue(localeID, key, buf, sizeof(buf), &tmpStatus); 1294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus)) { 1295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* ignore this keyword */ 1300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpStatus = U_ZERO_ERROR; 1301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 130450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keylen = (int32_t)uprv_strlen(key); 1305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru isLDMLKeyword = (keylen > 1); 1306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* special keyword used for representing Unicode locale attributes */ 1308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (uprv_strcmp(key, LOCALE_ATTRIBUTE_KEY) == 0) { 1309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho isAttribute = TRUE; 1310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len > 0) { 1311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t i = 0; 1312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while (TRUE) { 1313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attrBufLength = 0; 1314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (; i < len; i++) { 1315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (buf[i] != '-') { 1316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attrBuf[attrBufLength++] = buf[i]; 1317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 1318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho i++; 1319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (attrBufLength > 0) { 1323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attrBuf[attrBufLength] = 0; 1324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (i >= len){ 1326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* create AttributeListEntry */ 133054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr = (AttributeListEntry*)uprv_malloc(sizeof(AttributeListEntry)); 1331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (attr == NULL) { 1332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_MEMORY_ALLOCATION_ERROR; 1333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 133554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attrValue = (char*)uprv_malloc(attrBufLength + 1); 1336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (attrValue == NULL) { 1337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_MEMORY_ALLOCATION_ERROR; 1338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_strcpy(attrValue, attrBuf); 1341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attr->attribute = attrValue; 1342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!_addAttributeToList(&firstAttr, attr)) { 1344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(attr); 1345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(attrValue); 1346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (strict) { 1347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 1348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (isLDMLKeyword) { 1354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t modKeyLen; 1355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* transform key and value to bcp47 style */ 1357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru modKeyLen = _ldmlKeyToBCP47(key, keylen, pExtBuf, extBufCapacity, &tmpStatus); 1358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpStatus = U_ZERO_ERROR; 1364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKey = pExtBuf; 1368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtBuf += (modKeyLen + 1); 1369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru extBufCapacity -= (modKeyLen + 1); 1370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = _ldmlTypeToBCP47(key, keylen, buf, len, pExtBuf, extBufCapacity, &tmpStatus); 1372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpStatus = U_ZERO_ERROR; 1378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpValue = pExtBuf; 1381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtBuf += (len + 1); 1382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru extBufCapacity -= (len + 1); 1383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*key == PRIVATEUSE) { 1385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isPrivateuseValueSubtags(buf, len)) { 1386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isExtensionSingleton(key, keylen) || !_isExtensionSubtags(buf, len)) { 1394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKey = key; 1402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ((len + 1) < extBufCapacity) { 1403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(pExtBuf, buf, len); 1404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpValue = pExtBuf; 1405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtBuf += len; 1407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pExtBuf = 0; 1409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtBuf++; 1410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru extBufCapacity -= (len + 1); 1412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!isAttribute) { 1419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* create ExtensionListEntry */ 142054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius ext = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); 1421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (ext == NULL) { 1422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_MEMORY_ALLOCATION_ERROR; 1423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ext->key = bcpKey; 1426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ext->value = bcpValue; 1427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!_addExtensionToList(&firstExt, ext, TRUE)) { 1429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(ext); 1430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (strict) { 1431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 1432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 143727f654740f2a26ad62a5c155af9199af9e69b889claireho 143827f654740f2a26ad62a5c155af9199af9e69b889claireho /* Special handling for POSIX variant - add the keywords for POSIX */ 143927f654740f2a26ad62a5c155af9199af9e69b889claireho if (hadPosix) { 144027f654740f2a26ad62a5c155af9199af9e69b889claireho /* create ExtensionListEntry for POSIX */ 144154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius ext = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); 144227f654740f2a26ad62a5c155af9199af9e69b889claireho if (ext == NULL) { 144327f654740f2a26ad62a5c155af9199af9e69b889claireho *status = U_MEMORY_ALLOCATION_ERROR; 1444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho goto cleanup; 144527f654740f2a26ad62a5c155af9199af9e69b889claireho } 144627f654740f2a26ad62a5c155af9199af9e69b889claireho ext->key = POSIX_KEY; 144727f654740f2a26ad62a5c155af9199af9e69b889claireho ext->value = POSIX_VALUE; 144827f654740f2a26ad62a5c155af9199af9e69b889claireho 144927f654740f2a26ad62a5c155af9199af9e69b889claireho if (!_addExtensionToList(&firstExt, ext, TRUE)) { 145027f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_free(ext); 145127f654740f2a26ad62a5c155af9199af9e69b889claireho } 145227f654740f2a26ad62a5c155af9199af9e69b889claireho } 145327f654740f2a26ad62a5c155af9199af9e69b889claireho 1454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(*status) && (firstExt != NULL || firstAttr != NULL)) { 1455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool startLDMLExtension = FALSE; 1456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attr = firstAttr; 1458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext = firstExt; 1459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho do { 1460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!startLDMLExtension && (ext && uprv_strlen(ext->key) > 1)) { 1461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* write LDML singleton extension */ 1462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 1463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *(appendAt + reslen) = SEP; 1464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen++; 1466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 1467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *(appendAt + reslen) = LDMLEXT; 1468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen++; 1470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho startLDMLExtension = TRUE; 1472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* write out the sorted BCP47 attributes, extensions and private use */ 1475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (ext && (uprv_strlen(ext->key) == 1 || attr == NULL)) { 1476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = (int32_t)uprv_strlen(ext->key); 1481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_memcpy(appendAt + reslen, ext->key, uprv_min(len, capacity - reslen)); 1483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen += len; 1485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 1486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *(appendAt + reslen) = SEP; 1487b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = (int32_t)uprv_strlen(ext->value); 1490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 1491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_memcpy(appendAt + reslen, ext->value, uprv_min(len, capacity - reslen)); 1492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen += len; 1494b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ext = ext->next; 1496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (attr) { 1497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* write the value for the attributes */ 1498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 1499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *(appendAt + reslen) = SEP; 1500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen++; 1502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = (int32_t)uprv_strlen(attr->attribute); 1503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 1504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_memcpy(appendAt + reslen, attr->attribute, uprv_min(len, capacity - reslen)); 1505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen += len; 1507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attr = attr->next; 1509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } while (attr != NULL || ext != NULL); 1511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehocleanup: 1513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* clean up */ 1514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext = firstExt; 1515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (ext != NULL) { 1516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *tmpExt = ext->next; 1517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(ext); 1518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext = tmpExt; 1519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attr = firstAttr; 1522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while (attr != NULL) { 1523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho AttributeListEntry *tmpAttr = attr->next; 1524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char *pValue = (char *)attr->attribute; 1525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(pValue); 1526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(attr); 1527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho attr = tmpAttr; 1528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uenum_close(keywordEnum); 1531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(appendAt, capacity, reslen, status); 1538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/** 1541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Append keywords parsed from LDML extension value 1542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * e.g. "u-ca-gregory-co-trad" -> {calendar = gregorian} {collation = traditional} 1543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Note: char* buf is used for storing keywords 1544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 1545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 154627f654740f2a26ad62a5c155af9199af9e69b889claireho_appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendTo, char* buf, int32_t bufSize, UBool *posixVariant, UErrorCode *status) { 154754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char *pTag; /* beginning of current subtag */ 154854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char *pKwds; /* beginning of key-type pairs */ 154954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius UBool variantExists = *posixVariant; 155054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 155154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius ExtensionListEntry *kwdFirst = NULL; /* first LDML keyword */ 1552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *kwd, *nextKwd; 155354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 155454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius AttributeListEntry *attrFirst = NULL; /* first attribute */ 155554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius AttributeListEntry *attr, *nextAttr; 155654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 155754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t len; 1558b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t bufIdx = 0; 155954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 156054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius char attrBuf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; 156154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t attrBufIdx = 0; 1562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* Reset the posixVariant value */ 1564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *posixVariant = FALSE; 1565b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 156654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pTag = ldmlext; 156754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pKwds = NULL; 1568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 156954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* Iterate through u extension attributes */ 157054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius while (*pTag) { 1571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* locate next separator char */ 157254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius for (len = 0; *(pTag + len) && *(pTag + len) != SEP; len++); 157354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 157454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (_isLDMLKey(pTag, len)) { 157554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pKwds = pTag; 157654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius break; 1577b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 157854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 157954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* add this attribute to the list */ 158054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr = (AttributeListEntry*)uprv_malloc(sizeof(AttributeListEntry)); 158154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (attr == NULL) { 158254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *status = U_MEMORY_ALLOCATION_ERROR; 158354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 1584b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1585b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 158654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (len < (int32_t)sizeof(attrBuf) - attrBufIdx) { 158754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_memcpy(&attrBuf[attrBufIdx], pTag, len); 158854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attrBuf[attrBufIdx + len] = 0; 158954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr->attribute = &attrBuf[attrBufIdx]; 159054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attrBufIdx += (len + 1); 1591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 159254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *status = U_ILLEGAL_ARGUMENT_ERROR; 159354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 159454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 1595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 159654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (!_addAttributeToList(&attrFirst, attr)) { 159754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *status = U_ILLEGAL_ARGUMENT_ERROR; 159854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_free(attr); 159954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 160054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 1601b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 160254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* next tag */ 160354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pTag += len; 160454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (*pTag) { 160554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* next to the separator */ 160654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pTag++; 160754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 160854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 160954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 161054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (attrFirst) { 161154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* emit attributes as an LDML keyword, e.g. attribute=attr1-attr2 */ 161254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 161354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (attrBufIdx > bufSize) { 161454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* attrBufIdx == <total length of attribute subtag> + 1 */ 161554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *status = U_ILLEGAL_ARGUMENT_ERROR; 161654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 161754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 161854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 161954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); 162054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (kwd == NULL) { 162154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *status = U_MEMORY_ALLOCATION_ERROR; 162254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 162354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 162454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 162554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd->key = LOCALE_ATTRIBUTE_KEY; 162654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd->value = buf; 162754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 162854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* attribute subtags sorted in alphabetical order as type */ 162954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr = attrFirst; 163054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius while (attr != NULL) { 163154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius nextAttr = attr->next; 163254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 163354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* buffer size check is done above */ 163454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (attr != attrFirst) { 163554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *(buf + bufIdx) = SEP; 163654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bufIdx++; 1637b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 163854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 163954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius len = uprv_strlen(attr->attribute); 164054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_memcpy(buf + bufIdx, attr->attribute, len); 1641b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bufIdx += len; 1642b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 164354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr = nextAttr; 164454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 164554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *(buf + bufIdx) = 0; 164654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bufIdx++; 164754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 164854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (!_addExtensionToList(&kwdFirst, kwd, FALSE)) { 164954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *status = U_ILLEGAL_ARGUMENT_ERROR; 165054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_free(kwd); 165154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 165254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 1653b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 165454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* once keyword entry is created, delete the attribute list */ 165554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr = attrFirst; 165654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius while (attr != NULL) { 165754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius nextAttr = attr->next; 165854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_free(attr); 165954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr = nextAttr; 166054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 166154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attrFirst = NULL; 166254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 166354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 166454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (pKwds) { 166554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char *pBcpKey = NULL; /* u extenstion key subtag */ 166654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char *pBcpType = NULL; /* beginning of u extension type subtag(s) */ 166754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t bcpKeyLen = 0; 166854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t bcpTypeLen = 0; 166954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius UBool isDone = FALSE; 167054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 167154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pTag = pKwds; 167254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* BCP47 representation of LDML key/type pairs */ 167354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius while (!isDone) { 167454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char *pNextBcpKey = NULL; 167554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t nextBcpKeyLen; 167654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius UBool emitKeyword = FALSE; 167754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 167854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (*pTag) { 167954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* locate next separator char */ 168054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius for (len = 0; *(pTag + len) && *(pTag + len) != SEP; len++); 168154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 168254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (_isLDMLKey(pTag, len)) { 168354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (pBcpKey) { 168454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius emitKeyword = TRUE; 168554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pNextBcpKey = pTag; 168654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius nextBcpKeyLen = len; 168754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 168854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pBcpKey = pTag; 168954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bcpKeyLen = len; 169054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 169154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 169254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius U_ASSERT(pBcpKey != NULL); 169354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* within LDML type subtags */ 169454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (pBcpType) { 169554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bcpTypeLen += (len + 1); 169654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 169754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pBcpType = pTag; 169854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bcpTypeLen = len; 169954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 170054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 170154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 170254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* next tag */ 170354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pTag += len; 170454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (*pTag) { 170554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* next to the separator */ 170654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pTag++; 170754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 170827f654740f2a26ad62a5c155af9199af9e69b889claireho } else { 170954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* processing last one */ 171054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius emitKeyword = TRUE; 171154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius isDone = TRUE; 171254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 171354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 171454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (emitKeyword) { 171554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char *pKey = NULL; /* LDML key */ 171654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char *pType = NULL; /* LDML type */ 171754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 171854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius U_ASSERT(pBcpKey != NULL); 171954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 172054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* u extension key to LDML key */ 172154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius len = _bcp47ToLDMLKey(pBcpKey, bcpKeyLen, buf + bufIdx, bufSize - bufIdx - 1, status); 172254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (U_FAILURE(*status)) { 172327f654740f2a26ad62a5c155af9199af9e69b889claireho goto cleanup; 172427f654740f2a26ad62a5c155af9199af9e69b889claireho } 172554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pKey = buf + bufIdx; 172654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bufIdx += len; 172754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *(buf + bufIdx) = 0; 172854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bufIdx++; 172954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 173054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (pBcpType) { 173154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* BCP type to locale type */ 173254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius len = _bcp47ToLDMLType(pKey, -1, pBcpType, bcpTypeLen, buf + bufIdx, bufSize - bufIdx - 1, status); 173354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (U_FAILURE(*status)) { 173454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 173554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 173654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pType = buf + bufIdx; 173754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bufIdx += len; 173854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *(buf + bufIdx) = 0; 173954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bufIdx++; 174054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 174154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* typeless - default type value is "yes" */ 174254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pType = LOCALE_TYPE_YES; 174354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 174454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 174554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* Special handling for u-va-posix, since we want to treat this as a variant, 174654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius not as a keyword */ 174754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (!variantExists && !uprv_strcmp(pKey, POSIX_KEY) && !uprv_strcmp(pType, POSIX_VALUE) ) { 174854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *posixVariant = TRUE; 174954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 175054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* create an ExtensionListEntry for this keyword */ 175154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); 175254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (kwd == NULL) { 175354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *status = U_MEMORY_ALLOCATION_ERROR; 175454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 175554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 1756b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 175754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd->key = pKey; 175854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd->value = pType; 175927f654740f2a26ad62a5c155af9199af9e69b889claireho 176054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (!_addExtensionToList(&kwdFirst, kwd, FALSE)) { 176154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *status = U_ILLEGAL_ARGUMENT_ERROR; 176254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_free(kwd); 176354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius goto cleanup; 176454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 176527f654740f2a26ad62a5c155af9199af9e69b889claireho } 1766b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 176754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pBcpKey = pNextBcpKey; 176854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bcpKeyLen = pNextBcpKey != NULL ? nextBcpKeyLen : 0; 176954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pBcpType = NULL; 177054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius bcpTypeLen = 0; 177154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 1772b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1773b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1774b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1775b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwdFirst; 1776b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (kwd != NULL) { 1777b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru nextKwd = kwd->next; 1778b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru _addExtensionToList(appendTo, kwd, FALSE); 1779b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = nextKwd; 1780b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1781b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1782b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 1783b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1784b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querucleanup: 178554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr = attrFirst; 178654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius while (attr != NULL) { 178754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius nextAttr = attr->next; 178854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_free(attr); 178954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius attr = nextAttr; 179054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 179154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 1792b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwdFirst; 1793b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (kwd != NULL) { 1794b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru nextKwd = kwd->next; 1795b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(kwd); 1796b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = nextKwd; 1797b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1798b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1801b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 1802b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_appendKeywords(ULanguageTag* langtag, char* appendAt, int32_t capacity, UErrorCode* status) { 1803b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1804b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i, n; 1805b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len; 1806b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *kwdFirst = NULL; 1807b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *kwd; 1808b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key, *type; 1809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char *kwdBuf = NULL; 1810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t kwdBufLength = capacity; 181127f654740f2a26ad62a5c155af9199af9e69b889claireho UBool posixVariant = FALSE; 1812b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1815b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1816b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 181754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwdBuf = (char*)uprv_malloc(kwdBufLength); 1818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (kwdBuf == NULL) { 1819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_MEMORY_ALLOCATION_ERROR; 1820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 1821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* Determine if variants already exists */ 1824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (ultag_getVariantsSize(langtag)) { 1825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho posixVariant = TRUE; 1826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1828b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ultag_getExtensionsSize(langtag); 1829b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1830b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* resolve locale keywords and reordering keys */ 1831b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < n; i++) { 1832b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru key = ultag_getExtensionKey(langtag, i); 1833b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru type = ultag_getExtensionValue(langtag, i); 1834b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*key == LDMLEXT) { 1835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho _appendLDMLExtensionAsKeywords(type, &kwdFirst, kwdBuf, kwdBufLength, &posixVariant, status); 1836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1837b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1838b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1839b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 184054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); 1841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (kwd == NULL) { 1842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1843b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1844b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1845b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd->key = key; 1846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd->value = type; 1847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_addExtensionToList(&kwdFirst, kwd, FALSE)) { 1848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(kwd); 1849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(*status)) { 1856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru type = ultag_getPrivateUse(langtag); 185750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((int32_t)uprv_strlen(type) > 0) { 1858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* add private use as a keyword */ 185954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); 1860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (kwd == NULL) { 1861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd->key = PRIVATEUSE_KEY; 1864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd->value = type; 1865b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_addExtensionToList(&kwdFirst, kwd, FALSE)) { 1866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(kwd); 1867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1872b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 187327f654740f2a26ad62a5c155af9199af9e69b889claireho /* If a POSIX variant was in the extensions, write it out before writing the keywords. */ 187427f654740f2a26ad62a5c155af9199af9e69b889claireho 187527f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_SUCCESS(*status) && posixVariant) { 187627f654740f2a26ad62a5c155af9199af9e69b889claireho len = (int32_t) uprv_strlen(_POSIX); 187727f654740f2a26ad62a5c155af9199af9e69b889claireho if (reslen < capacity) { 187827f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_memcpy(appendAt + reslen, _POSIX, uprv_min(len, capacity - reslen)); 187927f654740f2a26ad62a5c155af9199af9e69b889claireho } 188027f654740f2a26ad62a5c155af9199af9e69b889claireho reslen += len; 188127f654740f2a26ad62a5c155af9199af9e69b889claireho } 188227f654740f2a26ad62a5c155af9199af9e69b889claireho 188354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (U_SUCCESS(*status) && kwdFirst != NULL) { 1884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the sorted keywords */ 1885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool firstValue = TRUE; 1886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwdFirst; 1887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho do { 1888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (firstValue) { 1890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* '@' */ 1891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = LOCALE_EXT_SEP; 1892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho firstValue = FALSE; 189354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 1894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* ';' */ 1895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = LOCALE_KEYWORD_SEP; 1896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 190054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* key */ 190154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius len = (int32_t)uprv_strlen(kwd->key); 190254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (reslen < capacity) { 190354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_memcpy(appendAt + reslen, kwd->key, uprv_min(len, capacity - reslen)); 190454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 190554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius reslen += len; 1906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 190754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* '=' */ 190854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (reslen < capacity) { 190954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *(appendAt + reslen) = LOCALE_KEY_TYPE_SEP; 191054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 191154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius reslen++; 1912b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 191354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* type */ 191454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius len = (int32_t)uprv_strlen(kwd->value); 191554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (reslen < capacity) { 191654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_memcpy(appendAt + reslen, kwd->value, uprv_min(len, capacity - reslen)); 1917b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 191854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius reslen += len; 191954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 192054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius kwd = kwd->next; 192154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } while (kwd); 1922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1923b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1924b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* clean up */ 1925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwdFirst; 1926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (kwd != NULL) { 1927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *tmpKwd = kwd->next; 1928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(kwd); 1929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = tmpKwd; 1930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1932b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(kwdBuf); 1933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1934b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1935b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1938b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(appendAt, capacity, reslen, status); 1939b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1940b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t 1942b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho_appendPrivateuseToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UBool hadPosix, UErrorCode* status) { 1943b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char buf[ULOC_FULLNAME_CAPACITY]; 1944b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char tmpAppend[ULOC_FULLNAME_CAPACITY]; 1945b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode tmpStatus = U_ZERO_ERROR; 1946b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t len, i; 1947b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t reslen = 0; 1948b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(*status)) { 1950b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 1951b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1952b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1953b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = uloc_getVariant(localeID, buf, sizeof(buf), &tmpStatus); 1954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (strict) { 1956b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 1957b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 1959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len > 0) { 1962b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char *p, *pPriv; 1963b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool bNext = TRUE; 1964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool firstValue = TRUE; 1965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool writeValue; 1966b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1967b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho pPriv = NULL; 1968b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho p = buf; 1969b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while (bNext) { 1970b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho writeValue = FALSE; 1971b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (*p == SEP || *p == LOCALE_SEP || *p == 0) { 1972b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (*p == 0) { 1973b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho bNext = FALSE; 1974b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 1975b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *p = 0; /* terminate */ 1976b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1977b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (pPriv != NULL) { 1978b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* Private use in the canonical format is lowercase in BCP47 */ 1979b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (i = 0; *(pPriv + i) != 0; i++) { 1980b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *(pPriv + i) = uprv_tolower(*(pPriv + i)); 1981b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1982b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1983b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* validate */ 1984b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (_isPrivateuseValueSubtag(pPriv, -1)) { 1985b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (firstValue) { 1986b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!_isVariantSubtag(pPriv, -1)) { 1987b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho writeValue = TRUE; 1988b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1989b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 1990b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho writeValue = TRUE; 1991b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1992b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (strict) { 1993b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 1994b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1995b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 1996b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1997b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1998b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1999b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (writeValue) { 2000b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 2001b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpAppend[reslen++] = SEP; 2002b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2003b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2004b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (firstValue) { 2005b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 2006b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpAppend[reslen++] = *PRIVATEUSE_KEY; 2007b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2008b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2009b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 2010b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpAppend[reslen++] = SEP; 2011b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2012b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = (int32_t)uprv_strlen(PRIVUSE_VARIANT_PREFIX); 2014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 2015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_memcpy(tmpAppend + reslen, PRIVUSE_VARIANT_PREFIX, uprv_min(len, capacity - reslen)); 2016b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2017b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen += len; 2018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2019b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 2020b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpAppend[reslen++] = SEP; 2021b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2022b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2023b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho firstValue = FALSE; 2024b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2025b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = (int32_t)uprv_strlen(pPriv); 2027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 2028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_memcpy(tmpAppend + reslen, pPriv, uprv_min(len, capacity - reslen)); 2029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen += len; 2031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* reset private use starting position */ 2034b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho pPriv = NULL; 2035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (pPriv == NULL) { 2036b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho pPriv = p; 2037b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2038b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho p++; 2039b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2040b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2041b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(*status)) { 2042b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 2043b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2046b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(*status)) { 2047b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = reslen; 2048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (reslen < capacity) { 2049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_memcpy(appendAt, tmpAppend, uprv_min(len, capacity - reslen)); 2050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho u_terminateChars(appendAt, capacity, reslen, status); 2054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return reslen; 2056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 2057b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2058b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 2059b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 2060b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 2061b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ultag_ functions 2062b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 2063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 2064b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 2065b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2066b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* Bit flags used by the parser */ 2067b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LANG 0x0001 2068b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define EXTL 0x0002 2069b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define SCRT 0x0004 2070b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define REGN 0x0008 2071b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define VART 0x0010 2072b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define EXTS 0x0020 2073b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define EXTV 0x0040 2074b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define PRIV 0x0080 2075b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2076b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic ULanguageTag* 2077b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* status) { 2078b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ULanguageTag *t; 2079b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *tagBuf; 2080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int16_t next; 2081b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *pSubtag, *pNext, *pLastGoodPosition; 2082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t subtagLen; 2083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t extlangIdx; 2084b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *pExtension; 2085b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho AttributeListEntry *pAttribute; 208650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *pExtValueSubtag, *pExtValueSubtagEnd; 2087b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 208854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius UBool isLDMLExtension, privateuseVar = FALSE; 208954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t grandfatheredLen = 0; 2090b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (parsedLen != NULL) { 2092b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *parsedLen = 0; 2093b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2094b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2095b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 2096b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 2097b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2098b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2099b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tagLen < 0) { 210050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tagLen = (int32_t)uprv_strlen(tag); 2101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* copy the entire string */ 2104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tagBuf = (char*)uprv_malloc(tagLen + 1); 2105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tagBuf == NULL) { 2106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 2107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 2108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(tagBuf, tag, tagLen); 2110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(tagBuf + tagLen) = 0; 2111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* create a ULanguageTag */ 2113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru t = (ULanguageTag*)uprv_malloc(sizeof(ULanguageTag)); 2114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (t == NULL) { 2115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(tagBuf); 2116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 2117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 2118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho _initializeULanguageTag(t); 2120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho t->buf = tagBuf; 2121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tagLen < MINLEN) { 2123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* the input tag is too short - return empty ULanguageTag */ 2124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return t; 2125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* check if the tag is grandfathered */ 2128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; GRANDFATHERED[i] != NULL; i += 2) { 2129103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (uprv_stricmp(GRANDFATHERED[i], tagBuf) == 0) { 213054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t newTagLength; 213154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 213254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius grandfatheredLen = tagLen; /* back up for output parsedLen */ 213354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius newTagLength = uprv_strlen(GRANDFATHERED[i+1]); 2134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tagLen < newTagLength) { 2135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(tagBuf); 2136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tagBuf = (char*)uprv_malloc(newTagLength + 1); 2137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tagBuf == NULL) { 2138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_MEMORY_ALLOCATION_ERROR; 2139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 2140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho t->buf = tagBuf; 2142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tagLen = newTagLength; 2143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_strcpy(t->buf, GRANDFATHERED[i + 1]); 2145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 2146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 2150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * langtag = language 2151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ["-" script] 2152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ["-" region] 2153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * *("-" variant) 2154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * *("-" extension) 2155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ["-" privateuse] 2156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 2157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = LANG | PRIV; 2159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = pLastGoodPosition = tagBuf; 2160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru extlangIdx = 0; 2161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 216250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtValueSubtag = NULL; 2163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtValueSubtagEnd = NULL; 2164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho pAttribute = NULL; 2165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru isLDMLExtension = FALSE; 2166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (pNext) { 2168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *pSep; 2169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = pNext; 2171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* locate next separator char */ 2173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep = pSubtag; 2174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*pSep) { 2175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == SEP) { 2176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep++; 2179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == 0) { 2181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* last subtag */ 2182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = NULL; 2183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = pSep + 1; 2185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 218650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho subtagLen = (int32_t)(pSep - pSubtag); 2187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & LANG) { 2189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isLanguageSubtag(pSubtag, subtagLen)) { 2190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; /* terminate */ 219150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->language = T_CString_toLowerCase(pSubtag); 2192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 2194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTL | SCRT | REGN | VART | EXTS | PRIV; 2195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 2196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & EXTL) { 2199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isExtlangSubtag(pSubtag, subtagLen)) { 2200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 220150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->extlang[extlangIdx++] = T_CString_toLowerCase(pSubtag); 2202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 2204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (extlangIdx < 3) { 2205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTL | SCRT | REGN | VART | EXTS | PRIV; 2206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = SCRT | REGN | VART | EXTS | PRIV; 2208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 2210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & SCRT) { 2213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isScriptSubtag(pSubtag, subtagLen)) { 221450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *p = pSubtag; 221550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 2216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 221750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 221850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to title case */ 221950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p = uprv_toupper(*p); 222050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p++; 222150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; *p; p++) { 222250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p = uprv_tolower(*p); 222350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 222450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 2225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru t->script = pSubtag; 2226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 2228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = REGN | VART | EXTS | PRIV; 2229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 2230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & REGN) { 2233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isRegionSubtag(pSubtag, subtagLen)) { 2234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 223550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->region = T_CString_toUpperCase(pSubtag); 2236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 2238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = VART | EXTS | PRIV; 2239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 2240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & VART) { 2243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (_isVariantSubtag(pSubtag, subtagLen) || 2244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho (privateuseVar && _isPrivateuseVariantSubtag(pSubtag, subtagLen))) { 2245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *var; 2246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool isAdded; 2247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = (VariantListEntry*)uprv_malloc(sizeof(VariantListEntry)); 2249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (var == NULL) { 2250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 2251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto error; 2252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 225450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var->variant = T_CString_toUpperCase(pSubtag); 2255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru isAdded = _addVariantToList(&(t->variants), var); 2256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!isAdded) { 2257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* duplicated variant entry */ 2258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(var); 2259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 2262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = VART | EXTS | PRIV; 2263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 2264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & EXTS) { 2267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isExtensionSingleton(pSubtag, subtagLen)) { 2268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pExtension != NULL) { 226950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pExtValueSubtag == NULL || pExtValueSubtagEnd == NULL) { 2270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* the previous extension is incomplete */ 2271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 227250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension = NULL; 2273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* terminate the previous extension value */ 2277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pExtValueSubtagEnd = 0; 227850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension->value = T_CString_toLowerCase(pExtValueSubtag); 2279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* insert the extension to the list */ 2281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_addExtensionToList(&(t->extensions), pExtension, FALSE)) { 2282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pExtValueSubtagEnd; 2283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* stop parsing here */ 2285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 2286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 2287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 229150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isLDMLExtension = (uprv_tolower(*pSubtag) == LDMLEXT); 2292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* create a new extension */ 229454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pExtension = (ExtensionListEntry*)uprv_malloc(sizeof(ExtensionListEntry)); 2295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pExtension == NULL) { 2296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 2297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto error; 2298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 230050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension->key = T_CString_toLowerCase(pSubtag); 2301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension->value = NULL; /* will be set later */ 2302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 230450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * reset the start and the end location of extension value 2305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * subtags for this extension 2306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 230750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtValueSubtag = NULL; 2308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtValueSubtagEnd = NULL; 2309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTV; 2311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 2312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & EXTV) { 2315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isExtensionSubtag(pSubtag, subtagLen)) { 231654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (pExtValueSubtag == NULL) { 231754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* if the start postion of this extension's value is not yet, 231854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius this one is the first value subtag */ 231954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pExtValueSubtag = pSubtag; 2320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 232254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius /* Mark the end of this subtag */ 232354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pExtValueSubtagEnd = pSep; 232454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius next = EXTS | EXTV | PRIV; 2325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 232654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius continue; 2327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & PRIV) { 233050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_tolower(*pSubtag) == PRIVATEUSE) { 2331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *pPrivuseVal; 2332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pExtension != NULL) { 2334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Process the last extension */ 233550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pExtValueSubtag == NULL || pExtValueSubtagEnd == NULL) { 2336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* the previous extension is incomplete */ 2337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 233850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension = NULL; 2339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* terminate the previous extension value */ 2342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pExtValueSubtagEnd = 0; 234350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension->value = T_CString_toLowerCase(pExtValueSubtag); 2344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* insert the extension to the list */ 2346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_addExtensionToList(&(t->extensions), pExtension, FALSE)) { 2347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pExtValueSubtagEnd; 2348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 2349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* stop parsing here */ 2351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 2352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 2353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* The rest of part will be private use value subtags */ 2359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pNext == NULL) { 2360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* empty private use subtag */ 2361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* back up the private use value start position */ 2364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pPrivuseVal = pNext; 2365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* validate private use value subtags */ 2367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (pNext) { 2368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = pNext; 2369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep = pSubtag; 2370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*pSep) { 2371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == SEP) { 2372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep++; 2375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == 0) { 2377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* last subtag */ 2378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = NULL; 2379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = pSep + 1; 2381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 238250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho subtagLen = (int32_t)(pSep - pSubtag); 2383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (uprv_strncmp(pSubtag, PRIVUSE_VARIANT_PREFIX, uprv_strlen(PRIVUSE_VARIANT_PREFIX)) == 0) { 2385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *pSep = 0; 2386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho next = VART; 2387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho privateuseVar = TRUE; 2388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 2389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (_isPrivateuseValueSubtag(pSubtag, subtagLen)) { 2390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 2391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (next == VART) { 2397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho continue; 2398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pLastGoodPosition - pPrivuseVal > 0) { 2401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pLastGoodPosition = 0; 240250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->privateuse = T_CString_toLowerCase(pPrivuseVal); 2403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* No more subtags, exiting the parse loop */ 2405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* If we fell through here, it means this subtag is illegal - quit parsing */ 2411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pExtension != NULL) { 2415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Process the last extension */ 241650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pExtValueSubtag == NULL || pExtValueSubtagEnd == NULL) { 2417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* the previous extension is incomplete */ 2418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 2419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* terminate the previous extension value */ 2421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pExtValueSubtagEnd = 0; 242250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension->value = T_CString_toLowerCase(pExtValueSubtag); 2423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* insert the extension to the list */ 2424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_addExtensionToList(&(t->extensions), pExtension, FALSE)) { 2425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pExtValueSubtagEnd; 2426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 2428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (parsedLen != NULL) { 243354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius *parsedLen = (grandfatheredLen > 0) ? grandfatheredLen : (int32_t)(pLastGoodPosition - t->buf); 2434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return t; 2437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruerror: 2439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(t); 2440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 2441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 2444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_close(ULanguageTag* langtag) { 2445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (langtag == NULL) { 2447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 2448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(langtag->buf); 2451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2452b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (langtag->variants) { 2453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *curVar = langtag->variants; 2454b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (curVar) { 2455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *nextVar = curVar->next; 2456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(curVar); 2457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru curVar = nextVar; 2458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (langtag->extensions) { 2462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *curExt = langtag->extensions; 2463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (curExt) { 2464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *nextExt = curExt->next; 2465b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(curExt); 2466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru curExt = nextExt; 2467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(langtag); 2471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2472b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2473b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2474b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getLanguage(const ULanguageTag* langtag) { 2475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->language; 2476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if 0 2479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getJDKLanguage(const ULanguageTag* langtag) { 2481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 2482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; DEPRECATEDLANGS[i] != NULL; i += 2) { 248350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(DEPRECATEDLANGS[i], langtag->language) == 0) { 2484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return DEPRECATEDLANGS[i + 1]; 2485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2486b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2487b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->language; 2488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 2490b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2491b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2492b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtlang(const ULanguageTag* langtag, int32_t idx) { 2493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (idx >= 0 && idx < MAXEXTLANG) { 2494b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->extlang[idx]; 2495b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2496b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 2497b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2498b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2499b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 2500b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtlangSize(const ULanguageTag* langtag) { 2501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t size = 0; 2502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 2503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < MAXEXTLANG; i++) { 2504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (langtag->extlang[i]) { 2505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru size++; 2506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return size; 2509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getScript(const ULanguageTag* langtag) { 2513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->script; 2514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getRegion(const ULanguageTag* langtag) { 2518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->region; 2519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getVariant(const ULanguageTag* langtag, int32_t idx) { 2523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *var = NULL; 2524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *cur = langtag->variants; 2525b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i = 0; 2526b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (cur) { 2527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (i == idx) { 2528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = cur->variant; 2529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru i++; 2533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return var; 2535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 2538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getVariantsSize(const ULanguageTag* langtag) { 2539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t size = 0; 2540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *cur = langtag->variants; 2541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 2542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cur == NULL) { 2543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru size++; 2546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return size; 2549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2550b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2551b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionKey(const ULanguageTag* langtag, int32_t idx) { 2553b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key = NULL; 2554b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *cur = langtag->extensions; 2555b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i = 0; 2556b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (cur) { 2557b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (i == idx) { 2558b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru key = cur->key; 2559b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2560b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2561b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2562b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru i++; 2563b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2564b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return key; 2565b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionValue(const ULanguageTag* langtag, int32_t idx) { 2569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *val = NULL; 2570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *cur = langtag->extensions; 2571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i = 0; 2572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (cur) { 2573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (i == idx) { 2574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru val = cur->value; 2575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2577b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2578b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru i++; 2579b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return val; 2581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2582b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 2584b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionsSize(const ULanguageTag* langtag) { 2585b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t size = 0; 2586b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *cur = langtag->extensions; 2587b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 2588b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cur == NULL) { 2589b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2590b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru size++; 2592b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2593b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2594b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return size; 2595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2596b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2597b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2598b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getPrivateUse(const ULanguageTag* langtag) { 2599b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->privateuse; 2600b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2601b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2602b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if 0 2603b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getGrandfathered(const ULanguageTag* langtag) { 2605b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->grandfathered; 2606b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2607b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 2608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 2611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 2612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 2613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Locale/BCP47 conversion APIs, exposed as uloc_* 2614b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 2615b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 2616b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 261754dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI int32_t U_EXPORT2 2618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruuloc_toLanguageTag(const char* localeID, 2619b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* langtag, 2620b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t langtagCapacity, 2621b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool strict, 2622b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode* status) { 2623b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* char canonical[ULOC_FULLNAME_CAPACITY]; */ /* See #6822 */ 2624b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char canonical[256]; 2625b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 2626b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 262727f654740f2a26ad62a5c155af9199af9e69b889claireho UBool hadPosix = FALSE; 2628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const char* pKeywordStart; 2629b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2630b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Note: uloc_canonicalize returns "en_US_POSIX" for input locale ID "". See #6835 */ 2631b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru canonical[0] = 0; 2632b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (uprv_strlen(localeID) > 0) { 2633b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uloc_canonicalize(localeID, canonical, sizeof(canonical), &tmpStatus); 2634b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tmpStatus != U_ZERO_ERROR) { 2635b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 2636b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 2637b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2638b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2639b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2640b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* For handling special case - private use only tag */ 2641b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho pKeywordStart = locale_getKeywordsStart(canonical); 2642b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (pKeywordStart == canonical) { 2643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UEnumeration *kwdEnum; 2644b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int kwdCnt = 0; 2645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool done = FALSE; 2646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho kwdEnum = uloc_openKeywords((const char*)canonical, &tmpStatus); 2648b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (kwdEnum != NULL) { 2649b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho kwdCnt = uenum_count(kwdEnum, &tmpStatus); 2650b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (kwdCnt == 1) { 2651b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const char *key; 2652b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t len = 0; 2653b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2654b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho key = uenum_next(kwdEnum, &len, &tmpStatus); 2655b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len == 1 && *key == PRIVATEUSE) { 2656b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char buf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; 2657b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho buf[0] = PRIVATEUSE; 2658b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho buf[1] = SEP; 2659b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = uloc_getKeywordValue(localeID, key, &buf[2], sizeof(buf) - 2, &tmpStatus); 2660b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpStatus)) { 2661b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (_isPrivateuseValueSubtags(&buf[2], len)) { 2662b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* return private use only tag */ 2663b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen = len + 2; 2664b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_memcpy(langtag, buf, uprv_min(reslen, langtagCapacity)); 2665b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho u_terminateChars(langtag, langtagCapacity, reslen, status); 2666b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho done = TRUE; 2667b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (strict) { 2668b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 2669b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho done = TRUE; 2670b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2671b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* if not strict mode, then "und" will be returned */ 2672b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 2673b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 2674b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho done = TRUE; 2675b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2676b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2677b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2678b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uenum_close(kwdEnum); 2679b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (done) { 2680b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return reslen; 2681b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2682b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2683b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2684b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 2685b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += _appendLanguageToLanguageTag(canonical, langtag, langtagCapacity, strict, status); 2686b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += _appendScriptToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, status); 2687b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += _appendRegionToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, status); 268827f654740f2a26ad62a5c155af9199af9e69b889claireho reslen += _appendVariantsToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, &hadPosix, status); 268927f654740f2a26ad62a5c155af9199af9e69b889claireho reslen += _appendKeywordsToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, hadPosix, status); 2690b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho reslen += _appendPrivateuseToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, hadPosix, status); 2691b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2692b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 2693b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2694b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2695b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 269654dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI int32_t U_EXPORT2 2697b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruuloc_forLanguageTag(const char* langtag, 2698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* localeID, 2699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t localeIDCapacity, 2700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t* parsedLength, 2701b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode* status) { 2702b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ULanguageTag *lt; 2703b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 2704b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *subtag, *p; 2705b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len; 270654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t i, n; 2707b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool noRegion = TRUE; 2708b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2709b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru lt = ultag_parse(langtag, -1, parsedLength, status); 2710b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 2711b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 2712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2713b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2714b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* language */ 2715b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getExtlangSize(lt) > 0 ? ultag_getExtlang(lt, 0) : ultag_getLanguage(lt); 271650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(subtag, LANG_UND) != 0) { 271750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(subtag); 2718b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 2719b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2720b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(localeID, subtag, uprv_min(len, localeIDCapacity - reslen)); 2721b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2722b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 2723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2724b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2725b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2726b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* script */ 2727b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getScript(lt); 272850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(subtag); 2729b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 2730b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2731b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = LOCALE_SEP; 2732b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2733b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2734b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2735b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the script in title case */ 2736b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = subtag; 2737b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*p) { 2738b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2739b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (p == subtag) { 2740b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = uprv_toupper(*p); 2741b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2742b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = *p; 2743b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2744b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2745b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2746b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 2747b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2748b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2749b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2750b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* region */ 2751b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getRegion(lt); 275250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(subtag); 2753b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 2754b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2755b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = LOCALE_SEP; 2756b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2757b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2758b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the retion in upper case */ 2759b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = subtag; 2760b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*p) { 2761b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2762b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = uprv_toupper(*p); 2763b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2764b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2765b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 2766b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2767b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru noRegion = FALSE; 2768b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2769b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2770b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* variants */ 2771b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ultag_getVariantsSize(lt); 2772b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (n > 0) { 2773b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (noRegion) { 2774b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2775b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = LOCALE_SEP; 2776b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2777b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2778b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2779b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2780b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < n; i++) { 2781b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getVariant(lt, i); 2782b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2783b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = LOCALE_SEP; 2784b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2785b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2786b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the variant in upper case */ 2787b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = subtag; 2788b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*p) { 2789b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2790b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = uprv_toupper(*p); 2791b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2792b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2793b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 2794b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2795b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2796b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2797b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2798b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* keywords */ 2799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ultag_getExtensionsSize(lt); 2800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getPrivateUse(lt); 280154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (n > 0 || uprv_strlen(subtag) > 0) { 280254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (reslen == 0 && n > 0) { 2803b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* need a language */ 2804b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2805b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(localeID + reslen, LANG_UND, uprv_min(LANG_UND_LEN, localeIDCapacity - reslen)); 2806b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2807b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += LANG_UND_LEN; 2808b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2809b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = _appendKeywords(lt, localeID + reslen, localeIDCapacity - reslen, status); 2810b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 2811b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2812b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ultag_close(lt); 2814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(localeID, localeIDCapacity, reslen, status); 2815b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2816b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2817b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2818