uloc_tag.c revision 27f654740f2a26ad62a5c155af9199af9e69b889
1b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 2b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru********************************************************************** 350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* Copyright (C) 2009-2010, 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" 17b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 18b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* struct holding a single variant */ 19b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct VariantListEntry { 20b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *variant; 21b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru struct VariantListEntry *next; 22b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} VariantListEntry; 23b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 24b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* struct holding a single extension */ 25b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct ExtensionListEntry { 26b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key; 27b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *value; 28b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru struct ExtensionListEntry *next; 29b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} ExtensionListEntry; 30b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 31b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAXEXTLANG 3 32b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct ULanguageTag { 33b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *buf; /* holding parsed subtags */ 34b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *language; 35b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *extlang[MAXEXTLANG]; 36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *script; 37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *region; 38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *variants; 39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *extensions; 40b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *privateuse; 41b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *grandfathered; 42b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} ULanguageTag; 43b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 44b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MINLEN 2 45b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define SEP '-' 46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define PRIVATEUSE 'x' 47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LDMLEXT 'u' 48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LOCALE_SEP '_' 50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LOCALE_EXT_SEP '@' 51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LOCALE_KEYWORD_SEP ';' 52b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LOCALE_KEY_TYPE_SEP '=' 53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 54b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define ISALPHA(c) (((c)>='A' && (c)<='Z') || ((c)>='a' && (c)<='z')) 55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define ISNUMERIC(c) ((c)>='0' && (c)<='9') 56b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 57b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* EMPTY = ""; 58b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* LANG_UND = "und"; 59b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* PRIVATEUSE_KEY = "x"; 6027f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char* _POSIX = "_POSIX"; 6127f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char* POSIX_KEY = "va"; 6227f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char* POSIX_VALUE = "posix"; 63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LANG_UND_LEN 3 65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* GRANDFATHERED[] = { 67b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* grandfathered preferred */ 68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "art-lojban", "jbo", 69b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "cel-gaulish", "", 70b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "en-GB-oed", "", 71b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-ami", "ami", 72b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-bnn", "bnn", 73b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-default", "", 74b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-enochian", "", 75b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-hak", "hak", 76b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-klingon", "tlh", 77b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-lux", "lb", 78b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-mingo", "", 79b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-navajo", "nv", 80b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-pwn", "pwn", 81b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-tao", "tao", 82b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-tay", "tay", 83b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "i-tsu", "tsu", 84b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "no-bok", "nb", 85b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "no-nyn", "nn", 86b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "sgn-be-fr", "sfb", 87b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "sgn-be-nl", "vgt", 88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "sgn-ch-de", "sgg", 89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-guoyu", "cmn", 90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-hakka", "hak", 91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-min", "", 92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-min-nan", "nan", 93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "zh-xiang", "hsn", 94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru NULL, NULL 95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}; 96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* DEPRECATEDLANGS[] = { 98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* deprecated new */ 99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "iw", "he", 100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "ji", "yi", 101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "in", "id", 102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru NULL, NULL 103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}; 104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* These ultag_ functions may be exposed as APIs later 109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic ULanguageTag* 114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* status); 115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_close(ULanguageTag* langtag); 118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getLanguage(const ULanguageTag* langtag); 121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if 0 123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getJDKLanguage(const ULanguageTag* langtag); 125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtlang(const ULanguageTag* langtag, int32_t idx); 129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtlangSize(const ULanguageTag* langtag); 132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getScript(const ULanguageTag* langtag); 135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getRegion(const ULanguageTag* langtag); 138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getVariant(const ULanguageTag* langtag, int32_t idx); 141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getVariantsSize(const ULanguageTag* langtag); 144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionKey(const ULanguageTag* langtag, int32_t idx); 147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionValue(const ULanguageTag* langtag, int32_t idx); 150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionsSize(const ULanguageTag* langtag); 153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getPrivateUse(const ULanguageTag* langtag); 156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if 0 158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getGrandfathered(const ULanguageTag* langtag); 160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Language subtag syntax validation functions 166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isAlphaString(const char* s, int32_t len) { 172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < len; i++) { 174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ISALPHA(*(s + i))) { 175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isNumericString(const char* s, int32_t len) { 183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < len; i++) { 185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ISNUMERIC(*(s + i))) { 186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isAlphaNumericString(const char* s, int32_t len) { 194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < len; i++) { 196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ISALPHA(*(s + i)) && !ISNUMERIC(*(s + i))) { 197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isLanguageSubtag(const char* s, int32_t len) { 205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * language = 2*3ALPHA ; shortest ISO 639 code 207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ["-" extlang] ; sometimes followed by 208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ; extended language subtags 209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * / 4ALPHA ; or reserved for future use 210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * / 5*8ALPHA ; or registered language subtag 211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 21350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 2 && len <= 8 && _isAlphaString(s, len)) { 216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isExtlangSubtag(const char* s, int32_t len) { 223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * extlang = 3ALPHA ; selected ISO 639 codes 225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * *2("-" 3ALPHA) ; permanently reserved 226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 3 && _isAlphaString(s, len)) { 231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isScriptSubtag(const char* s, int32_t len) { 238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * script = 4ALPHA ; ISO 15924 code 240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 4 && _isAlphaString(s, len)) { 245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isRegionSubtag(const char* s, int32_t len) { 252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * region = 2ALPHA ; ISO 3166-1 code 254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * / 3DIGIT ; UN M.49 code 255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 25750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 2 && _isAlphaString(s, len)) { 260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 3 && _isNumericString(s, len)) { 263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isVariantSubtag(const char* s, int32_t len) { 270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * variant = 5*8alphanum ; registered variants 272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * / (DIGIT 3alphanum) 273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 27550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 5 && len <= 8 && _isAlphaString(s, len)) { 278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 4 && ISNUMERIC(*s) && _isAlphaNumericString(s + 1, 3)) { 281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isExtensionSingleton(const char* s, int32_t len) { 288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * extension = singleton 1*("-" (2*8alphanum)) 290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 1 && ISALPHA(*s) && (uprv_tolower(*s) != PRIVATEUSE)) { 295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isExtensionSubtag(const char* s, int32_t len) { 302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * extension = singleton 1*("-" (2*8alphanum)) 304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 30650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 2 && len <= 8 && _isAlphaNumericString(s, len)) { 309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isExtensionSubtags(const char* s, int32_t len) { 316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *p = s; 317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *pSubtag = NULL; 318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ((p - s) < len) { 324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*p == SEP) { 325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pSubtag == NULL) { 326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 32850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!_isExtensionSubtag(pSubtag, (int32_t)(p - pSubtag))) { 329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = NULL; 332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (pSubtag == NULL) { 333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = p; 334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pSubtag == NULL) { 338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return _isExtensionSubtag(pSubtag, (int32_t)(p - pSubtag)); 341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isPrivateuseValueSubtag(const char* s, int32_t len) { 345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * privateuse = "x" 1*("-" (1*8alphanum)) 347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 34950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 1 && len <= 8 && _isAlphaNumericString(s, len)) { 352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isPrivateuseValueSubtags(const char* s, int32_t len) { 359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *p = s; 360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *pSubtag = NULL; 361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ((p - s) < len) { 367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*p == SEP) { 368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pSubtag == NULL) { 369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 37150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!_isPrivateuseValueSubtag(pSubtag, (int32_t)(p - pSubtag))) { 372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = NULL; 375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (pSubtag == NULL) { 376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = p; 377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pSubtag == NULL) { 381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 38350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return _isPrivateuseValueSubtag(pSubtag, (int32_t)(p - pSubtag)); 384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isLDMLKey(const char* s, int32_t len) { 388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 2 && _isAlphaNumericString(s, len)) { 392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_isLDMLType(const char* s, int32_t len) { 399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < 0) { 40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(s); 401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len >= 3 && len <= 8 && _isAlphaNumericString(s, len)) { 403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Helper functions 412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_addVariantToList(VariantListEntry **first, VariantListEntry *var) { 418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool bAdded = TRUE; 419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*first == NULL) { 421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var->next = NULL; 422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *first = var; 423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *prev, *cur; 425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t cmp; 426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* reorder variants in alphabetical order */ 428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev = NULL; 429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = *first; 430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cur == NULL) { 432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev->next = var; 433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var->next = NULL; 434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 43650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cmp = uprv_compareInvCharsAsAscii(var->variant, cur->variant); 437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cmp < 0) { 438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (prev == NULL) { 439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *first = var; 440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev->next = var; 442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var->next = cur; 444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cmp == 0) { 447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* duplicated variant */ 448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bAdded = FALSE; 449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev = cur; 452b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 454b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return bAdded; 457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool 461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_addExtensionToList(ExtensionListEntry **first, ExtensionListEntry *ext, UBool localeToBCP) { 462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool bAdded = TRUE; 463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*first == NULL) { 465b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext->next = NULL; 466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *first = ext; 467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *prev, *cur; 469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t cmp; 470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* reorder variants in alphabetical order */ 472b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev = NULL; 473b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = *first; 474b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cur == NULL) { 476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev->next = ext; 477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext->next = NULL; 478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (localeToBCP) { 481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* special handling for locale to bcp conversion */ 482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len, curlen; 483b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 48450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(ext->key); 48550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho curlen = (int32_t)uprv_strlen(cur->key); 486b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 487b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 1 && curlen == 1) { 488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*(ext->key) == *(cur->key)) { 489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = 0; 490b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (*(ext->key) == PRIVATEUSE) { 491b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = 1; 492b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (*(cur->key) == PRIVATEUSE) { 493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = -1; 494b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 495b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = *(ext->key) - *(cur->key); 496b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 497b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (len == 1) { 498b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = *(ext->key) - LDMLEXT; 499b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (curlen == 1) { 500b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cmp = LDMLEXT - *(cur->key); 501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 50250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cmp = uprv_compareInvCharsAsAscii(ext->key, cur->key); 503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 50550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cmp = uprv_compareInvCharsAsAscii(ext->key, cur->key); 506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cmp < 0) { 508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (prev == NULL) { 509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *first = ext; 510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev->next = ext; 512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext->next = cur; 514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cmp == 0) { 517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* duplicated extension key */ 518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bAdded = FALSE; 519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru prev = cur; 522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 525b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 526b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return bAdded; 527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_initializeULanguageTag(ULanguageTag* langtag) { 531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->buf = NULL; 534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->language = EMPTY; 536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < MAXEXTLANG; i++) { 537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->extlang[i] = NULL; 538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->script = EMPTY; 541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->region = EMPTY; 542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->variants = NULL; 544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->extensions = NULL; 545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->grandfathered = EMPTY; 547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru langtag->privateuse = EMPTY; 548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 55050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define KEYTYPEDATA "keyTypeData" 55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define KEYMAP "keyMap" 55250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define TYPEMAP "typeMap" 55350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define TYPEALIAS "typeAlias" 554b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX_BCP47_SUBTAG_LEN 9 /* including null terminator */ 555b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX_LDML_KEY_LEN 22 556b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX_LDML_TYPE_LEN 32 557b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 558b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 559b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_ldmlKeyToBCP47(const char* key, int32_t keyLen, 560b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* bcpKey, int32_t bcpKeyCapacity, 561b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 562b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *rb; 563b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char keyBuf[MAX_LDML_KEY_LEN]; 564b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char bcpKeyBuf[MAX_BCP47_SUBTAG_LEN]; 565b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t resultLen = 0; 566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar *uBcpKey; 569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t bcpKeyLen; 570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen < 0) { 57250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyLen = (int32_t)uprv_strlen(key); 573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen >= sizeof(keyBuf)) { 576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* no known valid LDML key exceeding 21 */ 577b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 578b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 579b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(keyBuf, key, keyLen); 582b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[keyLen] = 0; 583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 584b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 585b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < keyLen; i++) { 586b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[i] = uprv_tolower(keyBuf[i]); 587b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 588b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rb = ures_openDirect(NULL, KEYTYPEDATA, status); 59050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, KEYMAP, rb, status); 591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 592b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 593b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 594b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 596b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 597b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uBcpKey = ures_getStringByKey(rb, keyBuf, &bcpKeyLen, &tmpStatus); 598b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(tmpStatus)) { 599b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uBcpKey, bcpKeyBuf, bcpKeyLen); 600b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKeyBuf[bcpKeyLen] = 0; 601b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = bcpKeyLen; 602b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 603b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isLDMLKey(key, keyLen)) { 604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpKeyBuf, key, keyLen); 605b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKeyBuf[keyLen] = 0; 606b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = keyLen; 607b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* mapping not availabe */ 609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 614b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 615b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 616b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 617b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpKey, bcpKeyBuf, uprv_min(resultLen, bcpKeyCapacity)); 619b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(bcpKey, bcpKeyCapacity, resultLen, status); 620b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 621b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 622b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 623b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_bcp47ToLDMLKey(const char* bcpKey, int32_t bcpKeyLen, 624b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* key, int32_t keyCapacity, 625b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 626b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *rb; 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 const char *resKey = NULL; 63150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *mapData; 632b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 633b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (bcpKeyLen < 0) { 63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bcpKeyLen = (int32_t)uprv_strlen(bcpKey); 635b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 636b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 637b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (bcpKeyLen >= sizeof(bcpKeyBuf)) { 638b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 639b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 640b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 641b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 642b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpKeyBuf, bcpKey, bcpKeyLen); 643b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKeyBuf[bcpKeyLen] = 0; 644b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 645b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 646b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < bcpKeyLen; i++) { 647b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKeyBuf[i] = uprv_tolower(bcpKeyBuf[i]); 648b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 649b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 65050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rb = ures_openDirect(NULL, KEYTYPEDATA, status); 65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, KEYMAP, rb, status); 652b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 653b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 654b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 655b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 656b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 65750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapData = ures_getNextResource(rb, NULL, status); 658b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (U_SUCCESS(*status)) { 659b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar *uBcpKey; 660b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char tmpBcpKeyBuf[MAX_BCP47_SUBTAG_LEN]; 661b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t tmpBcpKeyLen; 662b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uBcpKey = ures_getString(mapData, &tmpBcpKeyLen, status); 664b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 665b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 666b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 667b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uBcpKey, tmpBcpKeyBuf, tmpBcpKeyLen); 668b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpBcpKeyBuf[tmpBcpKeyLen] = 0; 66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(bcpKeyBuf, tmpBcpKeyBuf) == 0) { 670b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* found a matching BCP47 key */ 67150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resKey = ures_getKey(mapData); 67250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resultLen = (int32_t)uprv_strlen(resKey); 673b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 674b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 675b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ures_hasNext(rb)) { 676b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 677b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getNextResource(rb, mapData, status); 679b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 68050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(mapData); 681b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 682b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 683b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 684b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 685b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 686b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 687b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (resKey == NULL) { 688b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resKey = bcpKeyBuf; 689b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = bcpKeyLen; 690b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 691b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 692b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(key, resKey, uprv_min(resultLen, keyCapacity)); 693b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(key, keyCapacity, resultLen, status); 694b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 695b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 696b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 697b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_ldmlTypeToBCP47(const char* key, int32_t keyLen, 698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char* type, int32_t typeLen, 699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* bcpType, int32_t bcpTypeCapacity, 700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 70150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *rb, *keyTypeData, *typeMapForKey; 702b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char keyBuf[MAX_LDML_KEY_LEN]; 703b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char typeBuf[MAX_LDML_TYPE_LEN]; 704b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char bcpTypeBuf[MAX_BCP47_SUBTAG_LEN]; 705b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t resultLen = 0; 706b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 707b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 70850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *uBcpType, *uCanonicalType; 70950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t bcpTypeLen, canonicalTypeLen; 710b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool isTimezone = FALSE; 711b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen < 0) { 71350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyLen = (int32_t)uprv_strlen(key); 714b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 715b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen >= sizeof(keyBuf)) { 716b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* no known valid LDML key exceeding 21 */ 717b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 718b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 719b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 720b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(keyBuf, key, keyLen); 721b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[keyLen] = 0; 722b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 724b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < keyLen; i++) { 725b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[i] = uprv_tolower(keyBuf[i]); 726b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 72750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(keyBuf, "timezone") == 0) { 728b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru isTimezone = TRUE; 729b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 730b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 731b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (typeLen < 0) { 73250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeLen = (int32_t)uprv_strlen(type); 733b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 734b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (typeLen >= sizeof(typeBuf)) { 735b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 736b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 737b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 738b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 73950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (isTimezone) { 74050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* replace '/' with ':' */ 74150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < typeLen; i++) { 74250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*(type + i) == '/') { 74350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[i] = ':'; 74450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 74550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[i] = *(type + i); 74650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 747b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 74850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[typeLen] = 0; 74950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho type = &typeBuf[0]; 750b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 751b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 75250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyTypeData = ures_openDirect(NULL, KEYTYPEDATA, status); 75350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rb = ures_getByKey(keyTypeData, TYPEMAP, NULL, status); 754b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 755b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 75650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(keyTypeData); 757b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 758b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 759b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 76050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeMapForKey = ures_getByKey(rb, keyBuf, NULL, &tmpStatus); 76150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uBcpType = ures_getStringByKey(typeMapForKey, type, &bcpTypeLen, &tmpStatus); 762b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(tmpStatus)) { 763b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uBcpType, bcpTypeBuf, bcpTypeLen); 764b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = bcpTypeLen; 765b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (tmpStatus == U_MISSING_RESOURCE_ERROR) { 76650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is this type alias? */ 76750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tmpStatus = U_ZERO_ERROR; 76850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(keyTypeData, TYPEALIAS, rb, &tmpStatus); 76950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, keyBuf, rb, &tmpStatus); 77050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uCanonicalType = ures_getStringByKey(rb, type, &canonicalTypeLen, &tmpStatus); 77150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(tmpStatus)) { 77250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_UCharsToChars(uCanonicalType, typeBuf, canonicalTypeLen); 77350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (isTimezone) { 77450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* replace '/' with ':' */ 77550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < canonicalTypeLen; i++) { 77650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (typeBuf[i] == '/') { 77750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[i] = ':'; 77850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 77950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 78050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 78150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho typeBuf[canonicalTypeLen] = 0; 78250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 78350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* look up the canonical type */ 78450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uBcpType = ures_getStringByKey(typeMapForKey, typeBuf, &bcpTypeLen, &tmpStatus); 78550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(tmpStatus)) { 78650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_UCharsToChars(uBcpType, bcpTypeBuf, bcpTypeLen); 78750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resultLen = bcpTypeLen; 78850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 78950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 79050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tmpStatus == U_MISSING_RESOURCE_ERROR) { 79150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (_isLDMLType(type, typeLen)) { 79250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memcpy(bcpTypeBuf, type, typeLen); 79350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resultLen = typeLen; 79450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 79550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* mapping not availabe */ 79650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 79750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 798b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = tmpStatus; 801b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 802b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 80350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(typeMapForKey); 80450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(keyTypeData); 805b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 806b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 807b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 808b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 809b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 810b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpType, bcpTypeBuf, uprv_min(resultLen, bcpTypeCapacity)); 811b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(bcpType, bcpTypeCapacity, resultLen, status); 812b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 815b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_bcp47ToLDMLType(const char* key, int32_t keyLen, 816b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char* bcpType, int32_t bcpTypeLen, 817b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* type, int32_t typeCapacity, 818b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 819b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *rb; 820b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char keyBuf[MAX_LDML_KEY_LEN]; 821b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char bcpTypeBuf[MAX_BCP47_SUBTAG_LEN]; 822b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t resultLen = 0; 823b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 824b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *resType = NULL; 82550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *mapData; 826b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 827b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t copyLen; 828b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 829b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen < 0) { 83050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyLen = (int32_t)uprv_strlen(key); 831b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 832b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 833b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyLen >= sizeof(keyBuf)) { 834b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* no known valid LDML key exceeding 21 */ 835b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 837b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 838b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(keyBuf, key, keyLen); 839b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[keyLen] = 0; 840b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < keyLen; i++) { 843b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyBuf[i] = uprv_tolower(keyBuf[i]); 844b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 845b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (bcpTypeLen < 0) { 84850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bcpTypeLen = (int32_t)uprv_strlen(bcpType); 849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (bcpTypeLen >= sizeof(bcpTypeBuf)) { 852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(bcpTypeBuf, bcpType, bcpTypeLen); 857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpTypeBuf[bcpTypeLen] = 0; 858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* to lower case */ 860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < bcpTypeLen; i++) { 861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpTypeBuf[i] = uprv_tolower(bcpTypeBuf[i]); 862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 86450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rb = ures_openDirect(NULL, KEYTYPEDATA, status); 86550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, TYPEMAP, rb, status); 866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_getByKey(rb, keyBuf, rb, &tmpStatus); 87250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapData = ures_getNextResource(rb, NULL, &tmpStatus); 873b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (U_SUCCESS(tmpStatus)) { 874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar *uBcpType; 875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char tmpBcpTypeBuf[MAX_BCP47_SUBTAG_LEN]; 876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t tmpBcpTypeLen; 877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 87850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uBcpType = ures_getString(mapData, &tmpBcpTypeLen, &tmpStatus); 879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus)) { 880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uBcpType, tmpBcpTypeBuf, tmpBcpTypeLen); 883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpBcpTypeBuf[tmpBcpTypeLen] = 0; 88450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(bcpTypeBuf, tmpBcpTypeBuf) == 0) { 885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* found a matching BCP47 type */ 88650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resType = ures_getKey(mapData); 88750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resultLen = (int32_t)uprv_strlen(resType); 888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!ures_hasNext(rb)) { 891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 89350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getNextResource(rb, mapData, &tmpStatus); 894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 89550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(mapData); 896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) && tmpStatus != U_MISSING_RESOURCE_ERROR) { 899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = tmpStatus; 900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 901b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 903b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (resType == NULL) { 904b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resType = bcpTypeBuf; 905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru resultLen = bcpTypeLen; 906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 907b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru copyLen = uprv_min(resultLen, typeCapacity); 909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(type, resType, copyLen); 910b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 91150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(keyBuf, "timezone") == 0) { 912b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < copyLen; i++) { 913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*(type + i) == ':') { 914b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(type + i) = '/'; 915b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 916b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 917b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 918b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 919b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(type, typeCapacity, resultLen, status); 920b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 921b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 923b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_appendLanguageToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UErrorCode* status) { 924b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_LANG_CAPACITY]; 925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len, i; 927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 933b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getLanguage(localeID, buf, sizeof(buf), &tmpStatus); 934b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 935b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 938b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 939b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = 0; 940b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 941b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 942b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Note: returned language code is in lower case letters */ 943b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 944b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len == 0) { 945b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 946b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, LANG_UND, uprv_min(LANG_UND_LEN, capacity - reslen)); 947b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 948b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += LANG_UND_LEN; 949b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (!_isLanguageSubtag(buf, len)) { 950b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* invalid language code */ 951b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 952b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 953b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 954b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 955b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 956b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, LANG_UND, uprv_min(LANG_UND_LEN, capacity - reslen)); 957b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 958b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += LANG_UND_LEN; 959b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 960b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* resolve deprecated */ 961b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; DEPRECATEDLANGS[i] != NULL; i += 2) { 96250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(buf, DEPRECATEDLANGS[i]) == 0) { 963b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_strcpy(buf, DEPRECATEDLANGS[i + 1]); 96450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(buf); 965b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 966b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 967b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 968b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 969b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, buf, uprv_min(len, capacity - reslen)); 970b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 971b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 972b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 973b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_terminateChars(appendAt, capacity, reslen, status); 974b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 975b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 976b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 977b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 978b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_appendScriptToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UErrorCode* status) { 979b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_SCRIPT_CAPACITY]; 980b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 98150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t len; 982b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 983b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 984b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 985b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 986b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 987b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 988b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getScript(localeID, buf, sizeof(buf), &tmpStatus); 989b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 990b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 991b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 992b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 993b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 994b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 995b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 996b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 997b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isScriptSubtag(buf, len)) { 998b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* invalid script code */ 999b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1000b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1001b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1002b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1003b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1004b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1005b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1006b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1007b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1008b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1009b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1010b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, buf, uprv_min(len, capacity - reslen)); 1011b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1012b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1013b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1014b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1015b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_terminateChars(appendAt, capacity, reslen, status); 1016b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 1017b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1018b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1019b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 1020b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_appendRegionToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UErrorCode* status) { 1021b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_COUNTRY_CAPACITY]; 1022b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 102350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t len; 1024b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1025b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1026b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1027b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1028b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1029b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1030b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getCountry(localeID, buf, sizeof(buf), &tmpStatus); 1031b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1032b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1033b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1034b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1035b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1036b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1037b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1038b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 1039b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isRegionSubtag(buf, len)) { 1040b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* invalid region code */ 1041b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1042b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1043b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1044b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1045b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1046b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1047b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1048b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1049b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1050b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1051b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1052b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, buf, uprv_min(len, capacity - reslen)); 1053b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1054b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1055b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1056b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1057b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_terminateChars(appendAt, capacity, reslen, status); 1058b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 1059b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1060b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1061b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 106227f654740f2a26ad62a5c155af9199af9e69b889claireho_appendVariantsToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UBool *hadPosix, UErrorCode* status) { 1063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_FULLNAME_CAPACITY]; 1064b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 1065b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len, i; 1066b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1067b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1068b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1069b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1070b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1071b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1072b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getVariant(localeID, buf, sizeof(buf), &tmpStatus); 1073b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1074b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1075b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1076b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1077b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1078b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1079b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 1081b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *p, *pVar; 1082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool bNext = TRUE; 1083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *var; 1084b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *varFirst = NULL; 1085b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1086b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pVar = NULL; 1087b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = buf; 1088b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (bNext) { 1089b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*p == SEP || *p == LOCALE_SEP || *p == 0) { 1090b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*p == 0) { 1091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bNext = FALSE; 1092b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1093b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *p = 0; /* terminate */ 1094b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1095b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pVar == NULL) { 1096b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1097b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1098b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1099b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* ignore empty variant */ 1101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 110250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* ICU uses upper case letters for variants, but 110350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho the canonical format is lowercase in BCP47 */ 1104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; *(pVar + i) != 0; i++) { 1105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(pVar + i) = uprv_tolower(*(pVar + i)); 1106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* validate */ 1109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isVariantSubtag(pVar, -1)) { 111027f654740f2a26ad62a5c155af9199af9e69b889claireho if (uprv_strcmp(pVar,POSIX_VALUE)) { 111127f654740f2a26ad62a5c155af9199af9e69b889claireho /* emit the variant to the list */ 111227f654740f2a26ad62a5c155af9199af9e69b889claireho var = uprv_malloc(sizeof(VariantListEntry)); 111327f654740f2a26ad62a5c155af9199af9e69b889claireho if (var == NULL) { 111427f654740f2a26ad62a5c155af9199af9e69b889claireho *status = U_MEMORY_ALLOCATION_ERROR; 1115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 111727f654740f2a26ad62a5c155af9199af9e69b889claireho var->variant = pVar; 111827f654740f2a26ad62a5c155af9199af9e69b889claireho if (!_addVariantToList(&varFirst, var)) { 111927f654740f2a26ad62a5c155af9199af9e69b889claireho /* duplicated variant */ 112027f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_free(var); 112127f654740f2a26ad62a5c155af9199af9e69b889claireho if (strict) { 112227f654740f2a26ad62a5c155af9199af9e69b889claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 112327f654740f2a26ad62a5c155af9199af9e69b889claireho break; 112427f654740f2a26ad62a5c155af9199af9e69b889claireho } 112527f654740f2a26ad62a5c155af9199af9e69b889claireho } 112627f654740f2a26ad62a5c155af9199af9e69b889claireho } else { 112727f654740f2a26ad62a5c155af9199af9e69b889claireho /* Special handling for POSIX variant, need to remember that we had it and then */ 112827f654740f2a26ad62a5c155af9199af9e69b889claireho /* treat it like an extension later. */ 112927f654740f2a26ad62a5c155af9199af9e69b889claireho *hadPosix = TRUE; 1130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (strict) { 1132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* reset variant starting position */ 1137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pVar = NULL; 1138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (pVar == NULL) { 1139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pVar = p; 1140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 1142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(*status)) { 1145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (varFirst != NULL) { 1146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t varLen; 1147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out sorted/validated/normalized variants to the target */ 1149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = varFirst; 1150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (var != NULL) { 1151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 115550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho varLen = (int32_t)uprv_strlen(var->variant); 1156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, var->variant, uprv_min(varLen, capacity - reslen)); 1158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += varLen; 1160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = var->next; 1161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* clean up */ 1166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = varFirst; 1167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (var != NULL) { 1168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *tmpVar = var->next; 1169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(var); 1170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = tmpVar; 1171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_terminateChars(appendAt, capacity, reslen, status); 1179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 1180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 118327f654740f2a26ad62a5c155af9199af9e69b889claireho_appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UBool hadPosix, UErrorCode* status) { 1184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char buf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; 1185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UEnumeration *keywordEnum = NULL; 1186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keywordEnum = uloc_openKeywords(localeID, status); 118927f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_FAILURE(*status) && !hadPosix) { 1190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uenum_close(keywordEnum); 1191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 119327f654740f2a26ad62a5c155af9199af9e69b889claireho if (keywordEnum != NULL || hadPosix) { 1194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* reorder extensions */ 1195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len; 1196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key; 1197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *firstExt = NULL; 1198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *ext; 1199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char extBuf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; 1200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *pExtBuf = extBuf; 1201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t extBufCapacity = sizeof(extBuf); 1202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *bcpKey, *bcpValue; 1203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 1204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t keylen; 1205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool isLDMLKeyword; 1206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 1208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru key = uenum_next(keywordEnum, NULL, status); 1209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (key == NULL) { 1210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = uloc_getKeywordValue(localeID, key, buf, sizeof(buf), &tmpStatus); 1213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus)) { 1214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* ignore this keyword */ 1219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpStatus = U_ZERO_ERROR; 1220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 122350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keylen = (int32_t)uprv_strlen(key); 1224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru isLDMLKeyword = (keylen > 1); 1225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (isLDMLKeyword) { 1227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t modKeyLen; 1228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* transform key and value to bcp47 style */ 1230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru modKeyLen = _ldmlKeyToBCP47(key, keylen, pExtBuf, extBufCapacity, &tmpStatus); 1231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpStatus = U_ZERO_ERROR; 1237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKey = pExtBuf; 1241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtBuf += (modKeyLen + 1); 1242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru extBufCapacity -= (modKeyLen + 1); 1243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = _ldmlTypeToBCP47(key, keylen, buf, len, pExtBuf, extBufCapacity, &tmpStatus); 1245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { 1246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpStatus = U_ZERO_ERROR; 1251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpValue = pExtBuf; 1254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtBuf += (len + 1); 1255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru extBufCapacity -= (len + 1); 1256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*key == PRIVATEUSE) { 1258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isPrivateuseValueSubtags(buf, len)) { 1259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isExtensionSingleton(key, keylen) || !_isExtensionSubtags(buf, len)) { 1267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpKey = key; 1275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ((len + 1) < extBufCapacity) { 1276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(pExtBuf, buf, len); 1277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bcpValue = pExtBuf; 1278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtBuf += len; 1280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pExtBuf = 0; 1282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtBuf++; 1283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru extBufCapacity -= (len + 1); 1285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* create ExtensionListEntry */ 1292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext = uprv_malloc(sizeof(ExtensionListEntry)); 1293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (ext == NULL) { 1294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext->key = bcpKey; 1298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext->value = bcpValue; 1299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_addExtensionToList(&firstExt, ext, TRUE)) { 1301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(ext); 1302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (strict) { 1303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 130827f654740f2a26ad62a5c155af9199af9e69b889claireho 130927f654740f2a26ad62a5c155af9199af9e69b889claireho /* Special handling for POSIX variant - add the keywords for POSIX */ 131027f654740f2a26ad62a5c155af9199af9e69b889claireho if (hadPosix) { 131127f654740f2a26ad62a5c155af9199af9e69b889claireho /* create ExtensionListEntry for POSIX */ 131227f654740f2a26ad62a5c155af9199af9e69b889claireho ext = uprv_malloc(sizeof(ExtensionListEntry)); 131327f654740f2a26ad62a5c155af9199af9e69b889claireho if (ext == NULL) { 131427f654740f2a26ad62a5c155af9199af9e69b889claireho *status = U_MEMORY_ALLOCATION_ERROR; 131527f654740f2a26ad62a5c155af9199af9e69b889claireho } 131627f654740f2a26ad62a5c155af9199af9e69b889claireho ext->key = POSIX_KEY; 131727f654740f2a26ad62a5c155af9199af9e69b889claireho ext->value = POSIX_VALUE; 131827f654740f2a26ad62a5c155af9199af9e69b889claireho 131927f654740f2a26ad62a5c155af9199af9e69b889claireho if (!_addExtensionToList(&firstExt, ext, TRUE)) { 132027f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_free(ext); 132127f654740f2a26ad62a5c155af9199af9e69b889claireho } 132227f654740f2a26ad62a5c155af9199af9e69b889claireho } 132327f654740f2a26ad62a5c155af9199af9e69b889claireho 1324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(*status) && (firstExt != NULL)) { 1325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool startLDMLExtension = FALSE; 1326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the sorted BCP47 extensions and private use */ 1328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext = firstExt; 1329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (ext != NULL) { 133050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((int32_t)uprv_strlen(ext->key) > 1 && !startLDMLExtension) { 1331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write LDML singleton extension */ 1332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = LDMLEXT; 1338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru startLDMLExtension = TRUE; 1341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 134750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(ext->key); 1348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, ext->key, uprv_min(len, capacity - reslen)); 1350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = SEP; 1354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 135650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(ext->value); 1357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, ext->value, uprv_min(len, capacity - reslen)); 1359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext = ext->next; 1363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* clean up */ 1366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext = firstExt; 1367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (ext != NULL) { 1368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *tmpExt = ext->next; 1369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(ext); 1370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ext = tmpExt; 1371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uenum_close(keywordEnum); 1374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(appendAt, capacity, reslen, status); 1381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/** 1384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Append keywords parsed from LDML extension value 1385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * e.g. "u-ca-gregory-co-trad" -> {calendar = gregorian} {collation = traditional} 1386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Note: char* buf is used for storing keywords 1387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 1388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 138927f654740f2a26ad62a5c155af9199af9e69b889claireho_appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendTo, char* buf, int32_t bufSize, UBool *posixVariant, UErrorCode *status) { 1390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *p, *pNext, *pSep; 1391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *pBcpKey, *pBcpType; 1392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *pKey, *pType; 1393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t bcpKeyLen = 0, bcpTypeLen; 1394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *kwd, *nextKwd; 1395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *kwdFirst = NULL; 1396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t bufIdx = 0; 1397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len; 1398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = ldmlext; 1400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pBcpKey = pBcpType = NULL; 1401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (pNext) { 1402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = pSep = pNext; 1403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* locate next separator char */ 1405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*pSep) { 1406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == SEP) { 1407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep++; 1410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == 0) { 1412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* last subtag */ 1413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = NULL; 1414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = pSep + 1; 1416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pBcpKey == NULL) { 1419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pBcpKey = p; 142050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bcpKeyLen = (int32_t)(pSep - p); 1421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pBcpType = p; 142350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bcpTypeLen = (int32_t)(pSep - p); 1424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* BCP key to locale key */ 1426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = _bcp47ToLDMLKey(pBcpKey, bcpKeyLen, buf + bufIdx, bufSize - bufIdx - 1, status); 1427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto cleanup; 1429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pKey = buf + bufIdx; 1431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bufIdx += len; 1432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(buf + bufIdx) = 0; 1433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bufIdx++; 1434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* BCP type to locale type */ 1436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = _bcp47ToLDMLType(pKey, -1, pBcpType, bcpTypeLen, buf + bufIdx, bufSize - bufIdx - 1, status); 1437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto cleanup; 1439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pType = buf + bufIdx; 1441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bufIdx += len; 1442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(buf + bufIdx) = 0; 1443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bufIdx++; 1444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 144527f654740f2a26ad62a5c155af9199af9e69b889claireho /* Special handling for u-va-posix, since we want to treat this as a variant, not */ 144627f654740f2a26ad62a5c155af9199af9e69b889claireho /* as a keyword. */ 1447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 144827f654740f2a26ad62a5c155af9199af9e69b889claireho if ( !uprv_strcmp(pKey,POSIX_KEY) && !uprv_strcmp(pType,POSIX_VALUE) ) { 144927f654740f2a26ad62a5c155af9199af9e69b889claireho *posixVariant = TRUE; 145027f654740f2a26ad62a5c155af9199af9e69b889claireho } else { 145127f654740f2a26ad62a5c155af9199af9e69b889claireho /* create an ExtensionListEntry for this keyword */ 145227f654740f2a26ad62a5c155af9199af9e69b889claireho kwd = uprv_malloc(sizeof(ExtensionListEntry)); 145327f654740f2a26ad62a5c155af9199af9e69b889claireho if (kwd == NULL) { 145427f654740f2a26ad62a5c155af9199af9e69b889claireho *status = U_MEMORY_ALLOCATION_ERROR; 145527f654740f2a26ad62a5c155af9199af9e69b889claireho goto cleanup; 145627f654740f2a26ad62a5c155af9199af9e69b889claireho } 1457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 145827f654740f2a26ad62a5c155af9199af9e69b889claireho kwd->key = pKey; 145927f654740f2a26ad62a5c155af9199af9e69b889claireho kwd->value = pType; 146027f654740f2a26ad62a5c155af9199af9e69b889claireho 146127f654740f2a26ad62a5c155af9199af9e69b889claireho if (!_addExtensionToList(&kwdFirst, kwd, FALSE)) { 146227f654740f2a26ad62a5c155af9199af9e69b889claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 146327f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_free(kwd); 146427f654740f2a26ad62a5c155af9199af9e69b889claireho goto cleanup; 146527f654740f2a26ad62a5c155af9199af9e69b889claireho } 1466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* for next pair */ 1469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pBcpKey = NULL; 1470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pBcpType = NULL; 1471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1472b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1473b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1474b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pBcpKey != NULL) { 1475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto cleanup; 1477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwdFirst; 1480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (kwd != NULL) { 1481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru nextKwd = kwd->next; 1482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru _addExtensionToList(appendTo, kwd, FALSE); 1483b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = nextKwd; 1484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1486b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 1487b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querucleanup: 1489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwdFirst; 1490b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (kwd != NULL) { 1491b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru nextKwd = kwd->next; 1492b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(kwd); 1493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = nextKwd; 1494b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1495b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1496b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1497b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1498b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 1499b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_appendKeywords(ULanguageTag* langtag, char* appendAt, int32_t capacity, UErrorCode* status) { 1500b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 1501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i, n; 1502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len; 1503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *kwdFirst = NULL; 1504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *kwd; 1505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key, *type; 1506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char kwdBuf[ULOC_KEYWORDS_CAPACITY]; 150727f654740f2a26ad62a5c155af9199af9e69b889claireho UBool posixVariant = FALSE; 1508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ultag_getExtensionsSize(langtag); 1514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* resolve locale keywords and reordering keys */ 1516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < n; i++) { 1517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru key = ultag_getExtensionKey(langtag, i); 1518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru type = ultag_getExtensionValue(langtag, i); 1519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*key == LDMLEXT) { 152027f654740f2a26ad62a5c155af9199af9e69b889claireho _appendLDMLExtensionAsKeywords(type, &kwdFirst, kwdBuf, sizeof(kwdBuf), &posixVariant, status); 1521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1525b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = uprv_malloc(sizeof(ExtensionListEntry)); 1526b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (kwd == NULL) { 1527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd->key = key; 1531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd->value = type; 1532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_addExtensionToList(&kwdFirst, kwd, FALSE)) { 1533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(kwd); 1534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(*status)) { 1541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru type = ultag_getPrivateUse(langtag); 154250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((int32_t)uprv_strlen(type) > 0) { 1543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* add private use as a keyword */ 1544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = uprv_malloc(sizeof(ExtensionListEntry)); 1545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (kwd == NULL) { 1546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd->key = PRIVATEUSE_KEY; 1549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd->value = type; 1550b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_addExtensionToList(&kwdFirst, kwd, FALSE)) { 1551b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(kwd); 1552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 1553b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1554b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1555b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1556b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1557b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 155827f654740f2a26ad62a5c155af9199af9e69b889claireho /* If a POSIX variant was in the extensions, write it out before writing the keywords. */ 155927f654740f2a26ad62a5c155af9199af9e69b889claireho 156027f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_SUCCESS(*status) && posixVariant) { 156127f654740f2a26ad62a5c155af9199af9e69b889claireho len = (int32_t) uprv_strlen(_POSIX); 156227f654740f2a26ad62a5c155af9199af9e69b889claireho if (reslen < capacity) { 156327f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_memcpy(appendAt + reslen, _POSIX, uprv_min(len, capacity - reslen)); 156427f654740f2a26ad62a5c155af9199af9e69b889claireho } 156527f654740f2a26ad62a5c155af9199af9e69b889claireho reslen += len; 156627f654740f2a26ad62a5c155af9199af9e69b889claireho } 156727f654740f2a26ad62a5c155af9199af9e69b889claireho 1568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(*status) && kwdFirst != NULL) { 1569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the sorted keywords */ 1570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwdFirst; 1571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (kwd != NULL) { 1572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (kwd == kwdFirst) { 1574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* '@' */ 1575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = LOCALE_EXT_SEP; 1576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1577b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* ';' */ 1578b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = LOCALE_KEYWORD_SEP; 1579b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1582b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* key */ 158450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(kwd->key); 1585b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1586b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, kwd->key, uprv_min(len, capacity - reslen)); 1587b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1588b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1589b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1590b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* '=' */ 1591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1592b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(appendAt + reslen) = LOCALE_KEY_TYPE_SEP; 1593b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1594b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 1595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1596b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* type */ 159750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(kwd->value); 1598b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < capacity) { 1599b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(appendAt + reslen, kwd->value, uprv_min(len, capacity - reslen)); 1600b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1601b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 1602b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1603b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwd->next; 1604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1605b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1606b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1607b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* clean up */ 1608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = kwdFirst; 1609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (kwd != NULL) { 1610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *tmpKwd = kwd->next; 1611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(kwd); 1612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru kwd = tmpKwd; 1613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1614b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1615b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1616b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 1617b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1619b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(appendAt, capacity, reslen, status); 1620b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1621b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1622b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 1623b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 1624b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 1625b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ultag_ functions 1626b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 1627b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 1628b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 1629b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1630b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* Bit flags used by the parser */ 1631b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LANG 0x0001 1632b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define EXTL 0x0002 1633b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define SCRT 0x0004 1634b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define REGN 0x0008 1635b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define VART 0x0010 1636b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define EXTS 0x0020 1637b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define EXTV 0x0040 1638b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define PRIV 0x0080 1639b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1640b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic ULanguageTag* 1641b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* status) { 1642b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ULanguageTag *t; 1643b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *tagBuf; 1644b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int16_t next; 1645b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *pSubtag, *pNext, *pLastGoodPosition; 1646b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t subtagLen; 1647b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t extlangIdx; 1648b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *pExtension; 164950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *pExtValueSubtag, *pExtValueSubtagEnd; 1650b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 1651b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool isLDMLExtension, reqLDMLType; 1652b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1653b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (parsedLen != NULL) { 1654b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *parsedLen = 0; 1655b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1656b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1657b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 1658b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 1659b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1660b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1661b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tagLen < 0) { 166250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tagLen = (int32_t)uprv_strlen(tag); 1663b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1664b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1665b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* copy the entire string */ 1666b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tagBuf = (char*)uprv_malloc(tagLen + 1); 1667b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tagBuf == NULL) { 1668b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1669b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 1670b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1671b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(tagBuf, tag, tagLen); 1672b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(tagBuf + tagLen) = 0; 1673b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1674b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* create a ULanguageTag */ 1675b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru t = (ULanguageTag*)uprv_malloc(sizeof(ULanguageTag)); 1676b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru _initializeULanguageTag(t); 1677b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru t->buf = tagBuf; 1678b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (t == NULL) { 1679b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(tagBuf); 1680b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1681b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 1682b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1683b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1684b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tagLen < MINLEN) { 1685b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* the input tag is too short - return empty ULanguageTag */ 1686b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return t; 1687b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1688b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1689b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* check if the tag is grandfathered */ 1690b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; GRANDFATHERED[i] != NULL; i += 2) { 169150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (T_CString_stricmp(GRANDFATHERED[i], tagBuf) == 0) { 1692b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* a grandfathered tag is always longer than its preferred mapping */ 1693b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_strcpy(t->buf, GRANDFATHERED[i + 1]); 1694b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru t->language = t->buf; 1695b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (parsedLen != NULL) { 1696b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *parsedLen = tagLen; 1697b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return t; 1699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1701b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1702b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 1703b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * langtag = language 1704b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ["-" script] 1705b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ["-" region] 1706b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * *("-" variant) 1707b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * *("-" extension) 1708b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ["-" privateuse] 1709b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 1710b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1711b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = LANG | PRIV; 1712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = pLastGoodPosition = tagBuf; 1713b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru extlangIdx = 0; 1714b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 171550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtValueSubtag = NULL; 1716b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtValueSubtagEnd = NULL; 1717b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru isLDMLExtension = FALSE; 1718b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reqLDMLType = FALSE; 1719b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1720b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (pNext) { 1721b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *pSep; 1722b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = pNext; 1724b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1725b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* locate next separator char */ 1726b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep = pSubtag; 1727b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*pSep) { 1728b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == SEP) { 1729b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1730b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1731b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep++; 1732b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1733b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == 0) { 1734b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* last subtag */ 1735b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = NULL; 1736b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1737b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = pSep + 1; 1738b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 173950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho subtagLen = (int32_t)(pSep - pSubtag); 1740b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1741b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & LANG) { 1742b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isLanguageSubtag(pSubtag, subtagLen)) { 1743b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; /* terminate */ 174450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->language = T_CString_toLowerCase(pSubtag); 1745b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1746b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 1747b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTL | SCRT | REGN | VART | EXTS | PRIV; 1748b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1749b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1750b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1751b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & EXTL) { 1752b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isExtlangSubtag(pSubtag, subtagLen)) { 1753b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 175450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->extlang[extlangIdx++] = T_CString_toLowerCase(pSubtag); 1755b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1756b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 1757b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (extlangIdx < 3) { 1758b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTL | SCRT | REGN | VART | EXTS | PRIV; 1759b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1760b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = SCRT | REGN | VART | EXTS | PRIV; 1761b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1762b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1763b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1764b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1765b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & SCRT) { 1766b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isScriptSubtag(pSubtag, subtagLen)) { 176750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *p = pSubtag; 176850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1769b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 177050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 177150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to title case */ 177250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p = uprv_toupper(*p); 177350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p++; 177450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; *p; p++) { 177550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p = uprv_tolower(*p); 177650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 177750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1778b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru t->script = pSubtag; 1779b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1780b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 1781b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = REGN | VART | EXTS | PRIV; 1782b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1783b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1784b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1785b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & REGN) { 1786b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isRegionSubtag(pSubtag, subtagLen)) { 1787b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 178850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->region = T_CString_toUpperCase(pSubtag); 1789b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1790b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 1791b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = VART | EXTS | PRIV; 1792b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1793b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1794b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1795b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & VART) { 1796b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isVariantSubtag(pSubtag, subtagLen)) { 1797b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *var; 1798b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool isAdded; 1799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = (VariantListEntry*)uprv_malloc(sizeof(VariantListEntry)); 1801b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (var == NULL) { 1802b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1803b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto error; 1804b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1805b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 180650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var->variant = T_CString_toUpperCase(pSubtag); 1807b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru isAdded = _addVariantToList(&(t->variants), var); 1808b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!isAdded) { 1809b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* duplicated variant entry */ 1810b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(var); 1811b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1812b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 1814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = VART | EXTS | PRIV; 1815b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1816b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1817b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1818b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & EXTS) { 1819b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isExtensionSingleton(pSubtag, subtagLen)) { 1820b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pExtension != NULL) { 182150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pExtValueSubtag == NULL || pExtValueSubtagEnd == NULL) { 1822b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* the previous extension is incomplete */ 1823b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 182450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension = NULL; 1825b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1826b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1827b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1828b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* terminate the previous extension value */ 1829b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pExtValueSubtagEnd = 0; 183050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension->value = T_CString_toLowerCase(pExtValueSubtag); 1831b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1832b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* insert the extension to the list */ 1833b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_addExtensionToList(&(t->extensions), pExtension, FALSE)) { 1834b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pExtValueSubtagEnd; 1835b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* stop parsing here */ 1837b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 1838b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 1839b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1840b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (isLDMLExtension && reqLDMLType) { 1843b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* incomplete LDML extension key and type pair */ 1844b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 1845b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 184950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isLDMLExtension = (uprv_tolower(*pSubtag) == LDMLEXT); 1850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* create a new extension */ 1852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = uprv_malloc(sizeof(ExtensionListEntry)); 1853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pExtension == NULL) { 1854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto error; 1856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pSep = 0; 185850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension->key = T_CString_toLowerCase(pSubtag); 1859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension->value = NULL; /* will be set later */ 1860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* 186250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * reset the start and the end location of extension value 1863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * subtags for this extension 1864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 186550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtValueSubtag = NULL; 1866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtValueSubtagEnd = NULL; 1867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTV; 1869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1872b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & EXTV) { 1873b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isExtensionSubtag(pSubtag, subtagLen)) { 1874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (isLDMLExtension) { 1875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reqLDMLType) { 1876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* already saw an LDML key */ 1877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isLDMLType(pSubtag, subtagLen)) { 1878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* stop parsing here and let the valid LDML extension key/type 1879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pairs processed by the code out of this while loop */ 1880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtValueSubtagEnd = pSep; 1883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reqLDMLType = FALSE; 1884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTS | EXTV | PRIV; 1885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* LDML key */ 1887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!_isLDMLKey(pSubtag, subtagLen)) { 1888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* stop parsing here and let the valid LDML extension key/type 1889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pairs processed by the code out of this while loop */ 1890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reqLDMLType = TRUE; 1893b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTV; 1894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Mark the end of this subtag */ 1897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtValueSubtagEnd = pSep; 1898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru next = EXTS | EXTV | PRIV; 1899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 190150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pExtValueSubtag == NULL) { 1902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* if the start postion of this extension's value is not yet, 1903b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru this one is the first value subtag */ 190450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtValueSubtag = pSubtag; 1905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 1907b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (next & PRIV) { 191050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_tolower(*pSubtag) == PRIVATEUSE) { 1911b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *pPrivuseVal; 1912b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pExtension != NULL) { 1914b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Process the last extension */ 191550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pExtValueSubtag == NULL || pExtValueSubtagEnd == NULL) { 1916b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* the previous extension is incomplete */ 1917b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 191850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension = NULL; 1919b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1920b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1921b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* terminate the previous extension value */ 1922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pExtValueSubtagEnd = 0; 192350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension->value = T_CString_toLowerCase(pExtValueSubtag); 1924b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* insert the extension to the list */ 1926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_addExtensionToList(&(t->extensions), pExtension, FALSE)) { 1927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pExtValueSubtagEnd; 1928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 1929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* stop parsing here */ 1931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 1932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pExtension = NULL; 1933b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1934b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1935b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1938b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* The rest of part will be private use value subtags */ 1939b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pNext == NULL) { 1940b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* empty private use subtag */ 1941b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1942b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1943b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* back up the private use value start position */ 1944b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pPrivuseVal = pNext; 1945b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1946b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* validate private use value subtags */ 1947b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (pNext) { 1948b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSubtag = pNext; 1949b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep = pSubtag; 1950b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*pSep) { 1951b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == SEP) { 1952b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1953b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1954b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pSep++; 1955b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1956b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*pSep == 0) { 1957b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* last subtag */ 1958b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = NULL; 1959b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1960b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pNext = pSep + 1; 1961b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 196250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho subtagLen = (int32_t)(pSep - pSubtag); 1963b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1964b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_isPrivateuseValueSubtag(pSubtag, subtagLen)) { 1965b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pSep; 1966b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1967b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1968b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1969b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1970b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pLastGoodPosition - pPrivuseVal > 0) { 1971b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pLastGoodPosition = 0; 197250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->privateuse = T_CString_toLowerCase(pPrivuseVal); 1973b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1974b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* No more subtags, exiting the parse loop */ 1975b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1976b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1977b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1978b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1979b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* If we fell through here, it means this subtag is illegal - quit parsing */ 1980b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 1981b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1982b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1983b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (pExtension != NULL) { 1984b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Process the last extension */ 198550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pExtValueSubtag == NULL || pExtValueSubtagEnd == NULL) { 1986b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* the previous extension is incomplete */ 1987b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 1988b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1989b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* terminate the previous extension value */ 1990b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *pExtValueSubtagEnd = 0; 199150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pExtension->value = T_CString_toLowerCase(pExtValueSubtag); 1992b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* insert the extension to the list */ 1993b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (_addExtensionToList(&(t->extensions), pExtension, FALSE)) { 1994b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pLastGoodPosition = pExtValueSubtagEnd; 1995b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 1996b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(pExtension); 1997b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1998b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1999b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2000b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2001b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (parsedLen != NULL) { 200250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *parsedLen = (int32_t)(pLastGoodPosition - t->buf); 2003b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2004b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2005b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return t; 2006b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2007b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruerror: 2008b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(t); 2009b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 2010b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2011b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2012b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 2013b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_close(ULanguageTag* langtag) { 2014b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2015b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (langtag == NULL) { 2016b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 2017b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2018b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2019b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(langtag->buf); 2020b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2021b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (langtag->variants) { 2022b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *curVar = langtag->variants; 2023b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (curVar) { 2024b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *nextVar = curVar->next; 2025b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(curVar); 2026b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru curVar = nextVar; 2027b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2028b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2029b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2030b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (langtag->extensions) { 2031b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *curExt = langtag->extensions; 2032b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (curExt) { 2033b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *nextExt = curExt->next; 2034b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(curExt); 2035b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru curExt = nextExt; 2036b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2037b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2038b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2039b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(langtag); 2040b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2041b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2042b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2043b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getLanguage(const ULanguageTag* langtag) { 2044b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->language; 2045b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2046b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2047b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if 0 2048b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2049b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getJDKLanguage(const ULanguageTag* langtag) { 2050b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 2051b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; DEPRECATEDLANGS[i] != NULL; i += 2) { 205250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(DEPRECATEDLANGS[i], langtag->language) == 0) { 2053b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return DEPRECATEDLANGS[i + 1]; 2054b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2055b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2056b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->language; 2057b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2058b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 2059b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2060b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2061b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtlang(const ULanguageTag* langtag, int32_t idx) { 2062b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (idx >= 0 && idx < MAXEXTLANG) { 2063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->extlang[idx]; 2064b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2065b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 2066b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2067b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2068b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 2069b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtlangSize(const ULanguageTag* langtag) { 2070b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t size = 0; 2071b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 2072b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < MAXEXTLANG; i++) { 2073b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (langtag->extlang[i]) { 2074b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru size++; 2075b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2076b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2077b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return size; 2078b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2079b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2081b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getScript(const ULanguageTag* langtag) { 2082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->script; 2083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2084b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2085b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2086b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getRegion(const ULanguageTag* langtag) { 2087b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->region; 2088b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2089b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2090b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getVariant(const ULanguageTag* langtag, int32_t idx) { 2092b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *var = NULL; 2093b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *cur = langtag->variants; 2094b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i = 0; 2095b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (cur) { 2096b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (i == idx) { 2097b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru var = cur->variant; 2098b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2099b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru i++; 2102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return var; 2104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 2107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getVariantsSize(const ULanguageTag* langtag) { 2108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t size = 0; 2109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru VariantListEntry *cur = langtag->variants; 2110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 2111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cur == NULL) { 2112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru size++; 2115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return size; 2118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionKey(const ULanguageTag* langtag, int32_t idx) { 2122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key = NULL; 2123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *cur = langtag->extensions; 2124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i = 0; 2125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (cur) { 2126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (i == idx) { 2127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru key = cur->key; 2128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru i++; 2132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return key; 2134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionValue(const ULanguageTag* langtag, int32_t idx) { 2138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *val = NULL; 2139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *cur = langtag->extensions; 2140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i = 0; 2141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (cur) { 2142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (i == idx) { 2143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru val = cur->value; 2144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru i++; 2148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return val; 2150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t 2153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getExtensionsSize(const ULanguageTag* langtag) { 2154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t size = 0; 2155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ExtensionListEntry *cur = langtag->extensions; 2156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (TRUE) { 2157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (cur == NULL) { 2158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 2159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru size++; 2161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cur = cur->next; 2162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return size; 2164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getPrivateUse(const ULanguageTag* langtag) { 2168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->privateuse; 2169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if 0 2172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char* 2173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruultag_getGrandfathered(const ULanguageTag* langtag) { 2174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return langtag->grandfathered; 2175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 2177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 2180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 2181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 2182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Locale/BCP47 conversion APIs, exposed as uloc_* 2183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* 2184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* ------------------------------------------------- 2185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 2186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_DRAFT int32_t U_EXPORT2 2187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruuloc_toLanguageTag(const char* localeID, 2188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* langtag, 2189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t langtagCapacity, 2190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool strict, 2191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode* status) { 2192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* char canonical[ULOC_FULLNAME_CAPACITY]; */ /* See #6822 */ 2193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char canonical[256]; 2194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 2195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode tmpStatus = U_ZERO_ERROR; 219627f654740f2a26ad62a5c155af9199af9e69b889claireho UBool hadPosix = FALSE; 2197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Note: uloc_canonicalize returns "en_US_POSIX" for input locale ID "". See #6835 */ 2199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru canonical[0] = 0; 2200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (uprv_strlen(localeID) > 0) { 2201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uloc_canonicalize(localeID, canonical, sizeof(canonical), &tmpStatus); 2202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tmpStatus != U_ZERO_ERROR) { 2203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 2204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 2205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += _appendLanguageToLanguageTag(canonical, langtag, langtagCapacity, strict, status); 2209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += _appendScriptToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, status); 2210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += _appendRegionToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, status); 221127f654740f2a26ad62a5c155af9199af9e69b889claireho reslen += _appendVariantsToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, &hadPosix, status); 221227f654740f2a26ad62a5c155af9199af9e69b889claireho reslen += _appendKeywordsToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, hadPosix, status); 2213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return reslen; 2215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_DRAFT int32_t U_EXPORT2 2219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruuloc_forLanguageTag(const char* langtag, 2220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char* localeID, 2221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t localeIDCapacity, 2222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t* parsedLength, 2223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode* status) { 2224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ULanguageTag *lt; 2225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t reslen = 0; 2226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *subtag, *p; 2227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len; 2228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i, n; 2229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool noRegion = TRUE; 2230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru lt = ultag_parse(langtag, -1, parsedLength, status); 2232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 2233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 2234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* language */ 2237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getExtlangSize(lt) > 0 ? ultag_getExtlang(lt, 0) : ultag_getLanguage(lt); 223850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_compareInvCharsAsAscii(subtag, LANG_UND) != 0) { 223950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(subtag); 2240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 2241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(localeID, subtag, uprv_min(len, localeIDCapacity - reslen)); 2243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 2245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* script */ 2249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getScript(lt); 225050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(subtag); 2251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 2252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = LOCALE_SEP; 2254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the script in title case */ 2258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = subtag; 2259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*p) { 2260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (p == subtag) { 2262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = uprv_toupper(*p); 2263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 2264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = *p; 2265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 2269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* region */ 2273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getRegion(lt); 227450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho len = (int32_t)uprv_strlen(subtag); 2275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len > 0) { 2276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = LOCALE_SEP; 2278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the retion in upper case */ 2281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = subtag; 2282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*p) { 2283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = uprv_toupper(*p); 2285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 2288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru noRegion = FALSE; 2290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* variants */ 2293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ultag_getVariantsSize(lt); 2294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (n > 0) { 2295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (noRegion) { 2296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = LOCALE_SEP; 2298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i = 0; i < n; i++) { 2303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getVariant(lt, i); 2304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = LOCALE_SEP; 2306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* write out the variant in upper case */ 2309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p = subtag; 2310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*p) { 2311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(localeID + reslen) = uprv_toupper(*p); 2313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen++; 2315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru p++; 2316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* keywords */ 2321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ultag_getExtensionsSize(lt); 2322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru subtag = ultag_getPrivateUse(lt); 2323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (n > 0 || uprv_strlen(subtag) > 0) { 2324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen == 0) { 2325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* need a language */ 2326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (reslen < localeIDCapacity) { 2327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memcpy(localeID + reslen, LANG_UND, uprv_min(LANG_UND_LEN, localeIDCapacity - reslen)); 2328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += LANG_UND_LEN; 2330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru len = _appendKeywords(lt, localeID + reslen, localeIDCapacity - reslen, status); 2332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reslen += len; 2333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ultag_close(lt); 2336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return u_terminateChars(localeID, localeIDCapacity, reslen, status); 2337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 2338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 2340