1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**********************************************************************
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius*   Copyright (C) 1997-2013, International Business Machines
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**********************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File ULOC.CPP
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/01/97    aliu        Creation.
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   08/21/98    stephen     JDK 1.2 sync
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   12/08/98    rtg         New Locale implementation and C API
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   03/15/99    damiba      overhaul.
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/06/99    stephen     changed setDefault() to realloc and copy
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/14/99    stephen     Changed calls to ures_open for new params
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/21/99    stephen     Modified setDefault() to propagate to C++
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   05/14/04    alan        7 years later: refactored, cleaned up, fixed bugs,
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           brought canonicalization code into line with spec
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*****************************************************************************/
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   POSIX's locale format, from putil.c: [no spaces]
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     ll [ _CC ] [ . MM ] [ @ VV]
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     l = lang, C = ctry, M = charmap, V = variant
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uloc.h"
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "putilimp.h"
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr_imp.h"
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ulocimp.h"
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_cmn.h"
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "locmap.h"
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uarrsort.h"
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uenumimp.h"
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uassert.h"
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h> /* for sprintf */
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* ### Declarations **************************************************/
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Locale stuff from locid.cpp */
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC void locale_set_default(const char *id);
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC const char *locale_get_default(void);
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC int32_t
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querulocale_getKeywords(const char *localeID,
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char prev,
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char *keywords, int32_t keywordCapacity,
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char *values, int32_t valuesCapacity, int32_t *valLen,
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool valuesToo,
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode *status);
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* ### Data tables **************************************************/
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Table of language codes, both 2- and 3-letter, with preference
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * given to 2-letter codes where possible.  Includes 3-letter codes
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * that lack a 2-letter equivalent.
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This list must be in sorted order.  This list is returned directly
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to the user by some API.
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This list must be kept in sync with LANGUAGES_3, with corresponding
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * entries matched.
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This table should be terminated with a NULL entry, followed by a
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * second list, and another NULL entry.  The first list is visible to
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * user code when this array is returned by API.  The second list
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * contains codes we support, but do not expose through user API.
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Notes
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Tables updated per http://lcweb.loc.gov/standards/iso639-2/ to
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * include the revisions up to 2001/7/27 *CWB*
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The 3 character codes are the terminology codes like RFC 3066.  This
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * is compatible with prior ICU codes
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * "in" "iw" "ji" "jw" & "sh" have been withdrawn but are still in the
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * table but now at the end of the table because 3 character codes are
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * duplicates.  This avoids bad searches going from 3 to 2 character
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * codes.
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The range qaa-qtz is reserved for local use
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/* Generated using org.unicode.cldr.icu.GenerateISO639LanguageTables */
9659d709d503bab6e2b61931737e662dd293b40578ccornelius/* ISO639 table version is 20130531 */
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char * const LANGUAGES[] = {
988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "aa",  "ab",  "ace", "ach", "ada", "ady", "ae",  "af",
998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "afa", "afh", "agq", "ain", "ak",  "akk", "ale", "alg",
1008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "alt", "am",  "an",  "ang", "anp", "apa", "ar",  "arc",
1018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "arn", "arp", "art", "arw", "as",  "asa", "ast", "ath",
1028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "aus", "av",  "awa", "ay",  "az",
1038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ba",  "bad", "bai", "bal", "ban", "bas", "bat", "bax",
1048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "bbj", "be",  "bej", "bem", "ber", "bez", "bfd", "bg",
1058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "bh",  "bho", "bi",  "bik", "bin", "bkm", "bla", "bm",
1068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "bn",  "bnt", "bo",  "br",  "bra", "brx", "bs",  "bss",
1078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "btk", "bua", "bug", "bum", "byn", "byv",
1088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ca",  "cad", "cai", "car", "cau", "cay", "cch", "ce",
1098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ceb", "cel", "cgg", "ch",  "chb", "chg", "chk", "chm",
1108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "chn", "cho", "chp", "chr", "chy", "ckb", "cmc", "co",
1118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "cop", "cpe", "cpf", "cpp", "cr",  "crh", "crp", "cs",
1128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "csb", "cu",  "cus", "cv",  "cy",
1138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "da",  "dak", "dar", "dav", "day", "de",  "del", "den",
1148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "dgr", "din", "dje", "doi", "dra", "dsb", "dua", "dum",
1158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "dv",  "dyo", "dyu", "dz",  "dzg",
1168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ebu", "ee",  "efi", "egy", "eka", "el",  "elx", "en",
1178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "enm", "eo",  "es",  "et",  "eu",  "ewo",
1188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "fa",  "fan", "fat", "ff",  "fi",  "fil", "fiu", "fj",
1198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "fo",  "fon", "fr",  "frm", "fro", "frr", "frs", "fur",
1208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "fy",
1218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ga",  "gaa", "gay", "gba", "gd",  "gem", "gez", "gil",
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "gl",  "gmh", "gn",  "goh", "gon", "gor", "got", "grb",
1238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "grc", "gsw", "gu",  "guz", "gv",  "gwi",
1248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ha",  "hai", "haw", "he",  "hi",  "hil", "him", "hit",
1258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "hmn", "ho",  "hr",  "hsb", "ht",  "hu",  "hup", "hy",
1268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "hz",
1278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ia",  "iba", "ibb", "id",  "ie",  "ig",  "ii",  "ijo",
1288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ik",  "ilo", "inc", "ine", "inh", "io",  "ira", "iro",
1298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "is",  "it",  "iu",
1308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ja",  "jbo", "jgo", "jmc", "jpr", "jrb", "jv",
1318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ka",  "kaa", "kab", "kac", "kaj", "kam", "kar", "kaw",
1328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "kbd", "kbl", "kcg", "kde", "kea", "kfo", "kg",  "kha",
1338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "khi", "kho", "khq", "ki",  "kj",  "kk",  "kkj", "kl",
1348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "kln", "km",  "kmb", "kn",  "ko",  "kok", "kos", "kpe",
1358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "kr",  "krc", "krl", "kro", "kru", "ks",  "ksb", "ksf",
1368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ksh", "ku",  "kum", "kut", "kv",  "kw",  "ky",
1378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "la",  "lad", "lag", "lah", "lam", "lb",  "lez", "lg",
1388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "li",  "lkt", "ln",  "lo",  "lol", "loz", "lt",  "lu",
1398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "lua", "lui", "lun", "luo", "lus", "luy", "lv",
1408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mad", "maf", "mag", "mai", "mak", "man", "map", "mas",
1418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mde", "mdf", "mdr", "men", "mer", "mfe", "mg",  "mga",
1428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mgh", "mgo", "mh",  "mi",  "mic", "min", "mis", "mk",
1438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mkh", "ml",  "mn",  "mnc", "mni", "mno", "mo",  "moh",
1448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mos", "mr",  "ms",  "mt",  "mua", "mul", "mun", "mus",
1458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mwl", "mwr", "my",  "mye", "myn", "myv",
1468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "na",  "nah", "nai", "nap", "naq", "nb",  "nd",  "nds",
1478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ne",  "new", "ng",  "nia", "nic", "niu", "nl",  "nmg",
1488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "nn",  "nnh", "no",  "nog", "non", "nqo", "nr",  "nso",
1498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "nub", "nus", "nv",  "nwc", "ny",  "nym", "nyn", "nyo",
1508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "nzi",
1518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "oc",  "oj",  "om",  "or",  "os",  "osa", "ota", "oto",
1528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "pa",  "paa", "pag", "pal", "pam", "pap", "pau", "peo",
1538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "phi", "phn", "pi",  "pl",  "pon", "pra", "pro", "ps",
1548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "pt",
1558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "qu",
1568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "raj", "rap", "rar", "rm",  "rn",  "ro",  "roa", "rof",
1578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "rom", "ru",  "rup", "rw",  "rwk",
1588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "sa",  "sad", "sah", "sai", "sal", "sam", "saq", "sas",
1598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "sat", "sba", "sbp", "sc",  "scn", "sco", "sd",  "se",
1608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "see", "seh", "sel", "sem", "ses", "sg",  "sga", "sgn",
1618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "shi", "shn", "shu", "si",  "sid", "sio", "sit",
1628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "sk",  "sl",  "sla", "sm",  "sma", "smi", "smj", "smn",
1638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "sms", "sn",  "snk", "so",  "sog", "son", "sq",  "sr",
1648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "srn", "srr", "ss",  "ssa", "ssy", "st",  "su",  "suk",
1658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "sus", "sux", "sv",  "sw",  "swb", "swc", "syc", "syr",
1668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ta",  "tai", "te",  "tem", "teo", "ter", "tet", "tg",
1678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "th",  "ti",  "tig", "tiv", "tk",  "tkl", "tl",  "tlh",
1688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "tli", "tmh", "tn",  "to",  "tog", "tpi", "tr",  "trv",
1698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ts",  "tsi", "tt",  "tum", "tup", "tut", "tvl", "tw",
1708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "twq", "ty",  "tyv", "tzm",
1718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "udm", "ug",  "uga", "uk",  "umb", "und", "ur",  "uz",
1728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "vai", "ve",  "vi",  "vo",  "vot", "vun",
1738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "wa",  "wae", "wak", "wal", "war", "was", "wen", "wo",
1748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "xal", "xh",  "xog",
1758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "yao", "yap", "yav", "ybb", "yi",  "yo",  "ypk", "yue",
17659d709d503bab6e2b61931737e662dd293b40578ccornelius    "za",  "zap", "zbl", "zen", "zgh", "zh",  "znd", "zu",
17759d709d503bab6e2b61931737e662dd293b40578ccornelius    "zun", "zxx", "zza",
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNULL,
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "in",  "iw",  "ji",  "jw",  "sh",    /* obsolete language codes */
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNULL
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char* const DEPRECATED_LANGUAGES[]={
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "in", "iw", "ji", "jw", NULL, NULL
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char* const REPLACEMENT_LANGUAGES[]={
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "id", "he", "yi", "jv", NULL, NULL
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Table of 3-letter language codes.
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is a lookup table used to convert 3-letter language codes to
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * their 2-letter equivalent, where possible.  It must be kept in sync
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * with LANGUAGES.  For all valid i, LANGUAGES[i] must refer to the
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * same language as LANGUAGES_3[i].  The commented-out lines are
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * copied from LANGUAGES to make eyeballing this baby easier.
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Where a 3-letter language code has no 2-letter equivalent, the
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * 3-letter code occupies both LANGUAGES[i] and LANGUAGES_3[i].
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This table should be terminated with a NULL entry, followed by a
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * second list, and another NULL entry.  The two lists correspond to
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the two lists in LANGUAGES.
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
2068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/* Generated using org.unicode.cldr.icu.GenerateISO639LanguageTables */
20759d709d503bab6e2b61931737e662dd293b40578ccornelius/* ISO639 table version is 20130531 */
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char * const LANGUAGES_3[] = {
2098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "aar", "abk", "ace", "ach", "ada", "ady", "ave", "afr",
2108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "afa", "afh", "agq", "ain", "aka", "akk", "ale", "alg",
2118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "alt", "amh", "arg", "ang", "anp", "apa", "ara", "arc",
2128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "arn", "arp", "art", "arw", "asm", "asa", "ast", "ath",
2138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "aus", "ava", "awa", "aym", "aze",
2148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "bak", "bad", "bai", "bal", "ban", "bas", "bat", "bax",
2158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "bbj", "bel", "bej", "bem", "ber", "bez", "bfd", "bul",
2168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "bih", "bho", "bis", "bik", "bin", "bkm", "bla", "bam",
2178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ben", "bnt", "bod", "bre", "bra", "brx", "bos", "bss",
2188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "btk", "bua", "bug", "bum", "byn", "byv",
2198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "cat", "cad", "cai", "car", "cau", "cay", "cch", "che",
2208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ceb", "cel", "cgg", "cha", "chb", "chg", "chk", "chm",
2218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "chn", "cho", "chp", "chr", "chy", "ckb", "cmc", "cos",
2228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "cop", "cpe", "cpf", "cpp", "cre", "crh", "crp", "ces",
2238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "csb", "chu", "cus", "chv", "cym",
2248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "dan", "dak", "dar", "dav", "day", "deu", "del", "den",
2258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "dgr", "din", "dje", "doi", "dra", "dsb", "dua", "dum",
2268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "div", "dyo", "dyu", "dzo", "dzg",
2278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ebu", "ewe", "efi", "egy", "eka", "ell", "elx", "eng",
2288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "enm", "epo", "spa", "est", "eus", "ewo",
2298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "fas", "fan", "fat", "ful", "fin", "fil", "fiu", "fij",
2308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "fao", "fon", "fra", "frm", "fro", "frr", "frs", "fur",
2318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "fry",
2328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "gle", "gaa", "gay", "gba", "gla", "gem", "gez", "gil",
2338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "glg", "gmh", "grn", "goh", "gon", "gor", "got", "grb",
2348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "grc", "gsw", "guj", "guz", "glv", "gwi",
2358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "hau", "hai", "haw", "heb", "hin", "hil", "him", "hit",
2368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "hmn", "hmo", "hrv", "hsb", "hat", "hun", "hup", "hye",
2378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "her",
2388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ina", "iba", "ibb", "ind", "ile", "ibo", "iii", "ijo",
2398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ipk", "ilo", "inc", "ine", "inh", "ido", "ira", "iro",
2408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "isl", "ita", "iku",
2418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "jpn", "jbo", "jgo", "jmc", "jpr", "jrb", "jav",
2428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "kat", "kaa", "kab", "kac", "kaj", "kam", "kar", "kaw",
2438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "kbd", "kbl", "kcg", "kde", "kea", "kfo", "kon", "kha",
2448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "khi", "kho", "khq", "kik", "kua", "kaz", "kkj", "kal",
2458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "kln", "khm", "kmb", "kan", "kor", "kok", "kos", "kpe",
2468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "kau", "krc", "krl", "kro", "kru", "kas", "ksb", "ksf",
2478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ksh", "kur", "kum", "kut", "kom", "cor", "kir",
2488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "lat", "lad", "lag", "lah", "lam", "ltz", "lez", "lug",
2498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "lim", "lkt", "lin", "lao", "lol", "loz", "lit", "lub",
2508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "lua", "lui", "lun", "luo", "lus", "luy", "lav",
2518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mad", "maf", "mag", "mai", "mak", "man", "map", "mas",
2528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mde", "mdf", "mdr", "men", "mer", "mfe", "mlg", "mga",
2538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mgh", "mgo", "mah", "mri", "mic", "min", "mis", "mkd",
2548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mkh", "mal", "mon", "mnc", "mni", "mno", "mol", "moh",
2558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mos", "mar", "msa", "mlt", "mua", "mul", "mun", "mus",
2568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "mwl", "mwr", "mya", "mye", "myn", "myv",
2578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "nau", "nah", "nai", "nap", "naq", "nob", "nde", "nds",
2588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "nep", "new", "ndo", "nia", "nic", "niu", "nld", "nmg",
2598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "nno", "nnh", "nor", "nog", "non", "nqo", "nbl", "nso",
2608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "nub", "nus", "nav", "nwc", "nya", "nym", "nyn", "nyo",
2618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "nzi",
2628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "oci", "oji", "orm", "ori", "oss", "osa", "ota", "oto",
2638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "pan", "paa", "pag", "pal", "pam", "pap", "pau", "peo",
2648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "phi", "phn", "pli", "pol", "pon", "pra", "pro", "pus",
2658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "por",
2668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "que",
2678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "raj", "rap", "rar", "roh", "run", "ron", "roa", "rof",
2688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "rom", "rus", "rup", "kin", "rwk",
2698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "san", "sad", "sah", "sai", "sal", "sam", "saq", "sas",
2708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "sat", "sba", "sbp", "srd", "scn", "sco", "snd", "sme",
2718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "see", "seh", "sel", "sem", "ses", "sag", "sga", "sgn",
2728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "shi", "shn", "shu", "sin", "sid", "sio", "sit",
2738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "slk", "slv", "sla", "smo", "sma", "smi", "smj", "smn",
2748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "sms", "sna", "snk", "som", "sog", "son", "sqi", "srp",
2758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "srn", "srr", "ssw", "ssa", "ssy", "sot", "sun", "suk",
2768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "sus", "sux", "swe", "swa", "swb", "swc", "syc", "syr",
2778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "tam", "tai", "tel", "tem", "teo", "ter", "tet", "tgk",
2788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "tha", "tir", "tig", "tiv", "tuk", "tkl", "tgl", "tlh",
2798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "tli", "tmh", "tsn", "ton", "tog", "tpi", "tur", "trv",
2808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "tso", "tsi", "tat", "tum", "tup", "tut", "tvl", "twi",
2818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "twq", "tah", "tyv", "tzm",
2828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "udm", "uig", "uga", "ukr", "umb", "und", "urd", "uzb",
2838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "vai", "ven", "vie", "vol", "vot", "vun",
2848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "wln", "wae", "wak", "wal", "war", "was", "wen", "wol",
2858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "xal", "xho", "xog",
2868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "yao", "yap", "yav", "ybb", "yid", "yor", "ypk", "yue",
28759d709d503bab6e2b61931737e662dd293b40578ccornelius    "zha", "zap", "zbl", "zen", "zgh", "zho", "znd", "zul",
28859d709d503bab6e2b61931737e662dd293b40578ccornelius    "zun", "zxx", "zza",
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNULL,
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "in",  "iw",  "ji",  "jw",  "sh",                          */
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "ind", "heb", "yid", "jaw", "srp",
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNULL
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Table of 2-letter country codes.
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This list must be in sorted order.  This list is returned directly
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to the user by some API.
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This list must be kept in sync with COUNTRIES_3, with corresponding
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * entries matched.
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This table should be terminated with a NULL entry, followed by a
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * second list, and another NULL entry.  The first list is visible to
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * user code when this array is returned by API.  The second list
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * contains codes we support, but do not expose through user API.
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Notes:
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * ZR(ZAR) is now CD(COD) and FX(FXX) is PS(PSE) as per
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * http://www.evertype.com/standards/iso3166/iso3166-1-en.html added
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * new codes keeping the old ones for compatibility updated to include
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * 1999/12/03 revisions *CWB*
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * RO(ROM) is now RO(ROU) according to
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * http://www.iso.org/iso/en/prods-services/iso3166ma/03updates-on-iso-3166/nlv3e-rou.html
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char * const COUNTRIES[] = {
3208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "AD",  "AE",  "AF",  "AG",  "AI",  "AL",  "AM",
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "AO",  "AQ",  "AR",  "AS",  "AT",  "AU",  "AW",  "AX",  "AZ",
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "BA",  "BB",  "BD",  "BE",  "BF",  "BG",  "BH",  "BI",
3238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "BJ",  "BL",  "BM",  "BN",  "BO",  "BQ",  "BR",  "BS",  "BT",  "BV",
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "BW",  "BY",  "BZ",  "CA",  "CC",  "CD",  "CF",  "CG",
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "CH",  "CI",  "CK",  "CL",  "CM",  "CN",  "CO",  "CR",
3268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "CU",  "CV",  "CW",  "CX",  "CY",  "CZ",  "DE",  "DJ",  "DK",
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "DM",  "DO",  "DZ",  "EC",  "EE",  "EG",  "EH",  "ER",
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "ES",  "ET",  "FI",  "FJ",  "FK",  "FM",  "FO",  "FR",
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "GA",  "GB",  "GD",  "GE",  "GF",  "GG",  "GH",  "GI",  "GL",
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "GM",  "GN",  "GP",  "GQ",  "GR",  "GS",  "GT",  "GU",
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "GW",  "GY",  "HK",  "HM",  "HN",  "HR",  "HT",  "HU",
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "ID",  "IE",  "IL",  "IM",  "IN",  "IO",  "IQ",  "IR",  "IS",
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "IT",  "JE",  "JM",  "JO",  "JP",  "KE",  "KG",  "KH",  "KI",
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "KM",  "KN",  "KP",  "KR",  "KW",  "KY",  "KZ",  "LA",
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "LB",  "LC",  "LI",  "LK",  "LR",  "LS",  "LT",  "LU",
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "LV",  "LY",  "MA",  "MC",  "MD",  "ME",  "MF",  "MG",  "MH",  "MK",
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "ML",  "MM",  "MN",  "MO",  "MP",  "MQ",  "MR",  "MS",
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "MT",  "MU",  "MV",  "MW",  "MX",  "MY",  "MZ",  "NA",
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "NC",  "NE",  "NF",  "NG",  "NI",  "NL",  "NO",  "NP",
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "NR",  "NU",  "NZ",  "OM",  "PA",  "PE",  "PF",  "PG",
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "PH",  "PK",  "PL",  "PM",  "PN",  "PR",  "PS",  "PT",
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "PW",  "PY",  "QA",  "RE",  "RO",  "RS",  "RU",  "RW",  "SA",
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "SB",  "SC",  "SD",  "SE",  "SG",  "SH",  "SI",  "SJ",
3448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "SK",  "SL",  "SM",  "SN",  "SO",  "SR",  "SS",  "ST",  "SV",
3458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "SX",  "SY",  "SZ",  "TC",  "TD",  "TF",  "TG",  "TH",  "TJ",
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "TK",  "TL",  "TM",  "TN",  "TO",  "TR",  "TT",  "TV",
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "TW",  "TZ",  "UA",  "UG",  "UM",  "US",  "UY",  "UZ",
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "VA",  "VC",  "VE",  "VG",  "VI",  "VN",  "VU",  "WF",
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "WS",  "YE",  "YT",  "ZA",  "ZM",  "ZW",
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNULL,
3518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "AN",  "BU", "CS", "FX", "RO", "SU", "TP", "YD", "YU", "ZR",   /* obsolete country codes */
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNULL
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const char* const DEPRECATED_COUNTRIES[] = {
3568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "AN", "BU", "CS", "DD", "DY", "FX", "HV", "NH", "RH", "SU", "TP", "UK", "VD", "YD", "YU", "ZR", NULL, NULL /* deprecated country list */
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char* const REPLACEMENT_COUNTRIES[] = {
3598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*  "AN", "BU", "CS", "DD", "DY", "FX", "HV", "NH", "RH", "SU", "TP", "UK", "VD", "YD", "YU", "ZR" */
3608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "CW", "MM", "RS", "DE", "BJ", "FR", "BF", "VU", "ZW", "RU", "TL", "GB", "VN", "YE", "RS", "CD", NULL, NULL  /* replacement country codes */
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Table of 3-letter country codes.
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is a lookup table used to convert 3-letter country codes to
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * their 2-letter equivalent.  It must be kept in sync with COUNTRIES.
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * For all valid i, COUNTRIES[i] must refer to the same country as
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * COUNTRIES_3[i].  The commented-out lines are copied from COUNTRIES
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to make eyeballing this baby easier.
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This table should be terminated with a NULL entry, followed by a
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * second list, and another NULL entry.  The two lists correspond to
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the two lists in COUNTRIES.
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char * const COUNTRIES_3[] = {
3778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*  "AD",  "AE",  "AF",  "AG",  "AI",  "AL",  "AM",      */
3788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "AND", "ARE", "AFG", "ATG", "AIA", "ALB", "ARM",
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "AO",  "AQ",  "AR",  "AS",  "AT",  "AU",  "AW",  "AX",  "AZ",     */
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "AGO", "ATA", "ARG", "ASM", "AUT", "AUS", "ABW", "ALA", "AZE",
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "BA",  "BB",  "BD",  "BE",  "BF",  "BG",  "BH",  "BI",     */
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "BIH", "BRB", "BGD", "BEL", "BFA", "BGR", "BHR", "BDI",
3838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*  "BJ",  "BL",  "BM",  "BN",  "BO",  "BQ",  "BR",  "BS",  "BT",  "BV",     */
3848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "BEN", "BLM", "BMU", "BRN", "BOL", "BES", "BRA", "BHS", "BTN", "BVT",
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "BW",  "BY",  "BZ",  "CA",  "CC",  "CD",  "CF",  "CG",     */
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "BWA", "BLR", "BLZ", "CAN", "CCK", "COD", "CAF", "COG",
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "CH",  "CI",  "CK",  "CL",  "CM",  "CN",  "CO",  "CR",     */
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "CHE", "CIV", "COK", "CHL", "CMR", "CHN", "COL", "CRI",
3898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*  "CU",  "CV",  "CW",  "CX",  "CY",  "CZ",  "DE",  "DJ",  "DK",     */
3908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "CUB", "CPV", "CUW", "CXR", "CYP", "CZE", "DEU", "DJI", "DNK",
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "DM",  "DO",  "DZ",  "EC",  "EE",  "EG",  "EH",  "ER",     */
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "DMA", "DOM", "DZA", "ECU", "EST", "EGY", "ESH", "ERI",
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "ES",  "ET",  "FI",  "FJ",  "FK",  "FM",  "FO",  "FR",     */
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "ESP", "ETH", "FIN", "FJI", "FLK", "FSM", "FRO", "FRA",
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "GA",  "GB",  "GD",  "GE",  "GF",  "GG",  "GH",  "GI",  "GL",     */
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "GAB", "GBR", "GRD", "GEO", "GUF", "GGY", "GHA", "GIB", "GRL",
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "GM",  "GN",  "GP",  "GQ",  "GR",  "GS",  "GT",  "GU",     */
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "GMB", "GIN", "GLP", "GNQ", "GRC", "SGS", "GTM", "GUM",
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "GW",  "GY",  "HK",  "HM",  "HN",  "HR",  "HT",  "HU",     */
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "GNB", "GUY", "HKG", "HMD", "HND", "HRV", "HTI", "HUN",
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "ID",  "IE",  "IL",  "IM",  "IN",  "IO",  "IQ",  "IR",  "IS" */
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "IDN", "IRL", "ISR", "IMN", "IND", "IOT", "IRQ", "IRN", "ISL",
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "IT",  "JE",  "JM",  "JO",  "JP",  "KE",  "KG",  "KH",  "KI",     */
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "ITA", "JEY", "JAM", "JOR", "JPN", "KEN", "KGZ", "KHM", "KIR",
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "KM",  "KN",  "KP",  "KR",  "KW",  "KY",  "KZ",  "LA",     */
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "COM", "KNA", "PRK", "KOR", "KWT", "CYM", "KAZ", "LAO",
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "LB",  "LC",  "LI",  "LK",  "LR",  "LS",  "LT",  "LU",     */
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "LBN", "LCA", "LIE", "LKA", "LBR", "LSO", "LTU", "LUX",
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "LV",  "LY",  "MA",  "MC",  "MD",  "ME",  "MF",  "MG",  "MH",  "MK",     */
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "LVA", "LBY", "MAR", "MCO", "MDA", "MNE", "MAF", "MDG", "MHL", "MKD",
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "ML",  "MM",  "MN",  "MO",  "MP",  "MQ",  "MR",  "MS",     */
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "MLI", "MMR", "MNG", "MAC", "MNP", "MTQ", "MRT", "MSR",
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "MT",  "MU",  "MV",  "MW",  "MX",  "MY",  "MZ",  "NA",     */
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "MLT", "MUS", "MDV", "MWI", "MEX", "MYS", "MOZ", "NAM",
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "NC",  "NE",  "NF",  "NG",  "NI",  "NL",  "NO",  "NP",     */
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "NCL", "NER", "NFK", "NGA", "NIC", "NLD", "NOR", "NPL",
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "NR",  "NU",  "NZ",  "OM",  "PA",  "PE",  "PF",  "PG",     */
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "NRU", "NIU", "NZL", "OMN", "PAN", "PER", "PYF", "PNG",
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "PH",  "PK",  "PL",  "PM",  "PN",  "PR",  "PS",  "PT",     */
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "PHL", "PAK", "POL", "SPM", "PCN", "PRI", "PSE", "PRT",
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "PW",  "PY",  "QA",  "RE",  "RO",  "RS",  "RU",  "RW",  "SA",     */
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "PLW", "PRY", "QAT", "REU", "ROU", "SRB", "RUS", "RWA", "SAU",
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "SB",  "SC",  "SD",  "SE",  "SG",  "SH",  "SI",  "SJ",     */
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "SLB", "SYC", "SDN", "SWE", "SGP", "SHN", "SVN", "SJM",
4258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*  "SK",  "SL",  "SM",  "SN",  "SO",  "SR",  "SS",  "ST",  "SV",     */
4268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "SVK", "SLE", "SMR", "SEN", "SOM", "SUR", "SSD", "STP", "SLV",
4278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*  "SX",  "SY",  "SZ",  "TC",  "TD",  "TF",  "TG",  "TH",  "TJ",     */
4288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "SXM", "SYR", "SWZ", "TCA", "TCD", "ATF", "TGO", "THA", "TJK",
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "TK",  "TL",  "TM",  "TN",  "TO",  "TR",  "TT",  "TV",     */
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "TKL", "TLS", "TKM", "TUN", "TON", "TUR", "TTO", "TUV",
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "TW",  "TZ",  "UA",  "UG",  "UM",  "US",  "UY",  "UZ",     */
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "TWN", "TZA", "UKR", "UGA", "UMI", "USA", "URY", "UZB",
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "VA",  "VC",  "VE",  "VG",  "VI",  "VN",  "VU",  "WF",     */
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "VAT", "VCT", "VEN", "VGB", "VIR", "VNM", "VUT", "WLF",
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*  "WS",  "YE",  "YT",  "ZA",  "ZM",  "ZW",          */
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "WSM", "YEM", "MYT", "ZAF", "ZMB", "ZWE",
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNULL,
4388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*  "AN",  "BU",  "CS",  "FX",  "RO", "SU",  "TP",  "YD",  "YU",  "ZR" */
4398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ANT", "BUR", "SCG", "FXX", "ROM", "SUN", "TMP", "YMD", "YUG", "ZAR",
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNULL
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct CanonicalizationMap {
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *id;          /* input ID */
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *canonicalID; /* canonicalized output ID */
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *keyword;     /* keyword, or NULL if none */
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *value;       /* keyword value, or NULL if kw==NULL */
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} CanonicalizationMap;
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * A map to canonicalize locale IDs.  This handles a variety of
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * different semantic kinds of transformations.
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const CanonicalizationMap CANONICALIZE_MAP[] = {
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "",               "en_US_POSIX", NULL, NULL }, /* .NET name */
45627f654740f2a26ad62a5c155af9199af9e69b889claireho    { "c",              "en_US_POSIX", NULL, NULL }, /* POSIX name */
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "posix",          "en_US_POSIX", NULL, NULL }, /* POSIX name (alias of C) */
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "art_LOJBAN",     "jbo", NULL, NULL }, /* registered name */
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "az_AZ_CYRL",     "az_Cyrl_AZ", NULL, NULL }, /* .NET name */
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "az_AZ_LATN",     "az_Latn_AZ", NULL, NULL }, /* .NET name */
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "ca_ES_PREEURO",  "ca_ES", "currency", "ESP" },
462c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "de__PHONEBOOK",  "de", "collation", "phonebook" }, /* Old ICU name */
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "de_AT_PREEURO",  "de_AT", "currency", "ATS" },
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "de_DE_PREEURO",  "de_DE", "currency", "DEM" },
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "de_LU_PREEURO",  "de_LU", "currency", "LUF" },
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "el_GR_PREEURO",  "el_GR", "currency", "GRD" },
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "en_BE_PREEURO",  "en_BE", "currency", "BEF" },
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "en_IE_PREEURO",  "en_IE", "currency", "IEP" },
469c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "es__TRADITIONAL", "es", "collation", "traditional" }, /* Old ICU name */
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "es_ES_PREEURO",  "es_ES", "currency", "ESP" },
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "eu_ES_PREEURO",  "eu_ES", "currency", "ESP" },
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "fi_FI_PREEURO",  "fi_FI", "currency", "FIM" },
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "fr_BE_PREEURO",  "fr_BE", "currency", "BEF" },
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "fr_FR_PREEURO",  "fr_FR", "currency", "FRF" },
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "fr_LU_PREEURO",  "fr_LU", "currency", "LUF" },
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "ga_IE_PREEURO",  "ga_IE", "currency", "IEP" },
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "gl_ES_PREEURO",  "gl_ES", "currency", "ESP" },
478c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "hi__DIRECT",     "hi", "collation", "direct" }, /* Old ICU name */
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "it_IT_PREEURO",  "it_IT", "currency", "ITL" },
480c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "ja_JP_TRADITIONAL", "ja_JP", "calendar", "japanese" }, /* Old ICU name */
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "nb_NO_NY",       "nn_NO", NULL, NULL },  /* "markus said this was ok" :-) */
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "nl_BE_PREEURO",  "nl_BE", "currency", "BEF" },
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "nl_NL_PREEURO",  "nl_NL", "currency", "NLG" },
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "pt_PT_PREEURO",  "pt_PT", "currency", "PTE" },
485c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "sr_SP_CYRL",     "sr_Cyrl_RS", NULL, NULL }, /* .NET name */
486c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "sr_SP_LATN",     "sr_Latn_RS", NULL, NULL }, /* .NET name */
487c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "sr_YU_CYRILLIC", "sr_Cyrl_RS", NULL, NULL }, /* Linux name */
488c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "th_TH_TRADITIONAL", "th_TH", "calendar", "buddhist" }, /* Old ICU name */
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "uz_UZ_CYRILLIC", "uz_Cyrl_UZ", NULL, NULL }, /* Linux name */
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "uz_UZ_CYRL",     "uz_Cyrl_UZ", NULL, NULL }, /* .NET name */
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "uz_UZ_LATN",     "uz_Latn_UZ", NULL, NULL }, /* .NET name */
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "zh_CHS",         "zh_Hans", NULL, NULL }, /* .NET name */
493c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "zh_CHT",         "zh_Hant", NULL, NULL }, /* .NET name */
494103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    { "zh_GAN",         "gan", NULL, NULL }, /* registered name */
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { "zh_GUOYU",       "zh", NULL, NULL }, /* registered name */
496103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    { "zh_HAKKA",       "hak", NULL, NULL }, /* registered name */
497103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    { "zh_MIN_NAN",     "nan", NULL, NULL }, /* registered name */
498103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    { "zh_WUU",         "wuu", NULL, NULL }, /* registered name */
499103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    { "zh_XIANG",       "hsn", NULL, NULL }, /* registered name */
500103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    { "zh_YUE",         "yue", NULL, NULL }, /* registered name */
501c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru};
502c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
503c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querutypedef struct VariantMap {
504c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const char *variant;          /* input ID */
505c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const char *keyword;     /* keyword, or NULL if none */
506c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const char *value;       /* keyword value, or NULL if kw==NULL */
507c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru} VariantMap;
508c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
509c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const VariantMap VARIANT_MAP[] = {
510c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "EURO",   "currency", "EUR" },
511c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "PINYIN", "collation", "pinyin" }, /* Solaris variant */
512c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    { "STROKE", "collation", "stroke" }  /* Solaris variant */
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
51527f654740f2a26ad62a5c155af9199af9e69b889claireho/* ### BCP47 Conversion *******************************************/
51627f654740f2a26ad62a5c155af9199af9e69b889claireho/* Test if the locale id has BCP47 u extension and does not have '@' */
51727f654740f2a26ad62a5c155af9199af9e69b889claireho#define _hasBCP47Extension(id) (id && uprv_strstr(id, "@") == NULL && getShortestSubtagLength(localeID) == 1)
51827f654740f2a26ad62a5c155af9199af9e69b889claireho/* Converts the BCP47 id to Unicode id. Does nothing to id if conversion fails */
51927f654740f2a26ad62a5c155af9199af9e69b889claireho#define _ConvertBCP47(finalID, id, buffer, length,err) \
52027f654740f2a26ad62a5c155af9199af9e69b889claireho        if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || U_FAILURE(*err)) { \
52127f654740f2a26ad62a5c155af9199af9e69b889claireho            finalID=id; \
52227f654740f2a26ad62a5c155af9199af9e69b889claireho        } else { \
52327f654740f2a26ad62a5c155af9199af9e69b889claireho            finalID=buffer; \
52427f654740f2a26ad62a5c155af9199af9e69b889claireho        }
52527f654740f2a26ad62a5c155af9199af9e69b889claireho/* Gets the size of the shortest subtag in the given localeID. */
52627f654740f2a26ad62a5c155af9199af9e69b889clairehostatic int32_t getShortestSubtagLength(const char *localeID) {
52727f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t localeIDLength = uprv_strlen(localeID);
52827f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t length = localeIDLength;
52927f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t tmpLength = 0;
53027f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t i;
53127f654740f2a26ad62a5c155af9199af9e69b889claireho    UBool reset = TRUE;
53227f654740f2a26ad62a5c155af9199af9e69b889claireho
53327f654740f2a26ad62a5c155af9199af9e69b889claireho    for (i = 0; i < localeIDLength; i++) {
53427f654740f2a26ad62a5c155af9199af9e69b889claireho        if (localeID[i] != '_' && localeID[i] != '-') {
53527f654740f2a26ad62a5c155af9199af9e69b889claireho            if (reset) {
53627f654740f2a26ad62a5c155af9199af9e69b889claireho                tmpLength = 0;
53727f654740f2a26ad62a5c155af9199af9e69b889claireho                reset = FALSE;
53827f654740f2a26ad62a5c155af9199af9e69b889claireho            }
53927f654740f2a26ad62a5c155af9199af9e69b889claireho            tmpLength++;
54027f654740f2a26ad62a5c155af9199af9e69b889claireho        } else {
54127f654740f2a26ad62a5c155af9199af9e69b889claireho            if (tmpLength != 0 && tmpLength < length) {
54227f654740f2a26ad62a5c155af9199af9e69b889claireho                length = tmpLength;
54327f654740f2a26ad62a5c155af9199af9e69b889claireho            }
54427f654740f2a26ad62a5c155af9199af9e69b889claireho            reset = TRUE;
54527f654740f2a26ad62a5c155af9199af9e69b889claireho        }
54627f654740f2a26ad62a5c155af9199af9e69b889claireho    }
54727f654740f2a26ad62a5c155af9199af9e69b889claireho
54827f654740f2a26ad62a5c155af9199af9e69b889claireho    return length;
54927f654740f2a26ad62a5c155af9199af9e69b889claireho}
55027f654740f2a26ad62a5c155af9199af9e69b889claireho
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* ### Keywords **************************************************/
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ULOC_KEYWORD_BUFFER_LEN 25
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ULOC_MAX_NO_KEYWORDS 25
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55627f654740f2a26ad62a5c155af9199af9e69b889clairehoU_CAPI const char * U_EXPORT2
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querulocale_getKeywordsStart(const char *localeID) {
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *result = NULL;
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((result = uprv_strchr(localeID, '@')) != NULL) {
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return result;
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (U_CHARSET_FAMILY == U_EBCDIC_FAMILY)
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* We do this because the @ sign is variant, and the @ sign used on one
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        EBCDIC machine won't be compiled the same way on other EBCDIC based
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        machines. */
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        static const uint8_t ebcdicSigns[] = { 0x7C, 0x44, 0x66, 0x80, 0xAC, 0xAE, 0xAF, 0xB5, 0xEC, 0xEF, 0x00 };
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const uint8_t *charToFind = ebcdicSigns;
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(*charToFind) {
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if((result = uprv_strchr(localeID, *charToFind)) != NULL) {
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return result;
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            charToFind++;
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param buf buffer of size [ULOC_KEYWORD_BUFFER_LEN]
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param keywordName incoming name to be canonicalized
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param status return status (keyword too long)
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return length of the keyword name
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t locale_canonKeywordName(char *buf, const char *keywordName, UErrorCode *status)
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t i;
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t keywordNameLen = (int32_t)uprv_strlen(keywordName);
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(keywordNameLen >= ULOC_KEYWORD_BUFFER_LEN) {
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* keyword name too long for internal buffer */
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *status = U_INTERNAL_PROGRAM_ERROR;
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          return 0;
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* normalize the keyword name */
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  for(i = 0; i < keywordNameLen; i++) {
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    buf[i] = uprv_tolower(keywordName[i]);
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  buf[i] = 0;
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return keywordNameLen;
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct {
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char keyword[ULOC_KEYWORD_BUFFER_LEN];
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t keywordLen;
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *valueStart;
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t valueLen;
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} KeywordStruct;
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV
614103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliuscompareKeywordStructs(const void * /*context*/, const void *left, const void *right) {
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* leftString = ((const KeywordStruct *)left)->keyword;
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* rightString = ((const KeywordStruct *)right)->keyword;
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return uprv_strcmp(leftString, rightString);
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Both addKeyword and addValue must already be in canonical form.
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Either both addKeyword and addValue are NULL, or neither is NULL.
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * If they are not NULL they must be zero terminated.
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * If addKeyword is not NULL is must have length small enough to fit in KeywordStruct.keyword.
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_getKeywords(const char *localeID,
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             char prev,
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             char *keywords, int32_t keywordCapacity,
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             char *values, int32_t valuesCapacity, int32_t *valLen,
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UBool valuesToo,
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const char* addKeyword,
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const char* addValue,
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UErrorCode *status)
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    KeywordStruct keywordList[ULOC_MAX_NO_KEYWORDS];
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t maxKeywords = ULOC_MAX_NO_KEYWORDS;
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t numKeywords = 0;
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* pos = localeID;
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* equalSign = NULL;
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* semicolon = NULL;
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i = 0, j, n;
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t keywordsLen = 0;
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t valuesLen = 0;
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(prev == '@') { /* start of keyword definition */
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* we will grab pairs, trim spaces, lowercase keywords, sort and return */
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        do {
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool duplicate = FALSE;
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* skip leading spaces */
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(*pos == ' ') {
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos++;
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!*pos) { /* handle trailing "; " */
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(numKeywords == maxKeywords) {
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_INTERNAL_PROGRAM_ERROR;
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0;
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            equalSign = uprv_strchr(pos, '=');
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            semicolon = uprv_strchr(pos, ';');
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* lack of '=' [foo@currency] is illegal */
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* ';' before '=' [foo@currency;collation=pinyin] is illegal */
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(!equalSign || (semicolon && semicolon<equalSign)) {
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_INVALID_FORMAT_ERROR;
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0;
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* need to normalize both keyword and keyword name */
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(equalSign - pos >= ULOC_KEYWORD_BUFFER_LEN) {
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* keyword name too long for internal buffer */
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_INTERNAL_PROGRAM_ERROR;
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0;
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i = 0, n = 0; i < equalSign - pos; ++i) {
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (pos[i] != ' ') {
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    keywordList[numKeywords].keyword[n++] = uprv_tolower(pos[i]);
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
68159d709d503bab6e2b61931737e662dd293b40578ccornelius
68259d709d503bab6e2b61931737e662dd293b40578ccornelius            /* zero-length keyword is an error. */
68359d709d503bab6e2b61931737e662dd293b40578ccornelius            if (n == 0) {
68459d709d503bab6e2b61931737e662dd293b40578ccornelius                *status = U_INVALID_FORMAT_ERROR;
68559d709d503bab6e2b61931737e662dd293b40578ccornelius                return 0;
68659d709d503bab6e2b61931737e662dd293b40578ccornelius            }
68759d709d503bab6e2b61931737e662dd293b40578ccornelius
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            keywordList[numKeywords].keyword[n] = 0;
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            keywordList[numKeywords].keywordLen = n;
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* now grab the value part. First we skip the '=' */
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            equalSign++;
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* then we leading spaces */
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(*equalSign == ' ') {
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                equalSign++;
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
69659d709d503bab6e2b61931737e662dd293b40578ccornelius
69759d709d503bab6e2b61931737e662dd293b40578ccornelius            /* Premature end or zero-length value */
69859d709d503bab6e2b61931737e662dd293b40578ccornelius            if (!equalSign || equalSign == semicolon) {
69959d709d503bab6e2b61931737e662dd293b40578ccornelius                *status = U_INVALID_FORMAT_ERROR;
70059d709d503bab6e2b61931737e662dd293b40578ccornelius                return 0;
70159d709d503bab6e2b61931737e662dd293b40578ccornelius            }
70259d709d503bab6e2b61931737e662dd293b40578ccornelius
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            keywordList[numKeywords].valueStart = equalSign;
70459d709d503bab6e2b61931737e662dd293b40578ccornelius
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pos = semicolon;
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i = 0;
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(pos) {
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while(*(pos - i - 1) == ' ') {
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    i++;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordList[numKeywords].valueLen = (int32_t)(pos - equalSign - i);
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos++;
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                i = (int32_t)uprv_strlen(equalSign);
715816c50fb47edc483a0516072584640b520045214claireho                while(i && equalSign[i-1] == ' ') {
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    i--;
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordList[numKeywords].valueLen = i;
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* If this is a duplicate keyword, then ignore it */
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for (j=0; j<numKeywords; ++j) {
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (uprv_strcmp(keywordList[j].keyword, keywordList[numKeywords].keyword) == 0) {
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    duplicate = TRUE;
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!duplicate) {
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++numKeywords;
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } while(pos);
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Handle addKeyword/addValue. */
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (addKeyword != NULL) {
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool duplicate = FALSE;
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            U_ASSERT(addValue != NULL);
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Search for duplicate; if found, do nothing. Explicit keyword
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               overrides addKeyword. */
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for (j=0; j<numKeywords; ++j) {
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (uprv_strcmp(keywordList[j].keyword, addKeyword) == 0) {
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    duplicate = TRUE;
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!duplicate) {
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (numKeywords == maxKeywords) {
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *status = U_INTERNAL_PROGRAM_ERROR;
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return 0;
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_strcpy(keywordList[numKeywords].keyword, addKeyword);
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordList[numKeywords].keywordLen = (int32_t)uprv_strlen(addKeyword);
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordList[numKeywords].valueStart = addValue;
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordList[numKeywords].valueLen = (int32_t)uprv_strlen(addValue);
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++numKeywords;
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            U_ASSERT(addValue == NULL);
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* now we have a list of keywords */
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* we need to sort it */
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_sortArray(keywordList, numKeywords, sizeof(KeywordStruct), compareKeywordStructs, NULL, FALSE, status);
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Now construct the keyword part */
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i = 0; i < numKeywords; i++) {
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(keywordsLen + keywordList[i].keywordLen + 1< keywordCapacity) {
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_strcpy(keywords+keywordsLen, keywordList[i].keyword);
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(valuesToo) {
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    keywords[keywordsLen + keywordList[i].keywordLen] = '=';
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    keywords[keywordsLen + keywordList[i].keywordLen] = 0;
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            keywordsLen += keywordList[i].keywordLen + 1;
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(valuesToo) {
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(keywordsLen + keywordList[i].valueLen < keywordCapacity) {
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_strncpy(keywords+keywordsLen, keywordList[i].valueStart, keywordList[i].valueLen);
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordsLen += keywordList[i].valueLen;
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(i < numKeywords - 1) {
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(keywordsLen < keywordCapacity) {
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        keywords[keywordsLen] = ';';
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    keywordsLen++;
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(values) {
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(valuesLen + keywordList[i].valueLen + 1< valuesCapacity) {
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_strcpy(values+valuesLen, keywordList[i].valueStart);
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    values[valuesLen + keywordList[i].valueLen] = 0;
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                valuesLen += keywordList[i].valueLen + 1;
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(values) {
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            values[valuesLen] = 0;
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(valLen) {
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *valLen = valuesLen;
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return u_terminateChars(keywords, keywordCapacity, keywordsLen, status);
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC int32_t
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querulocale_getKeywords(const char *localeID,
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   char prev,
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   char *keywords, int32_t keywordCapacity,
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   char *values, int32_t valuesCapacity, int32_t *valLen,
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   UBool valuesToo,
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   UErrorCode *status) {
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return _getKeywords(localeID, prev, keywords, keywordCapacity,
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        values, valuesCapacity, valLen, valuesToo,
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        NULL, NULL, status);
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getKeywordValue(const char* localeID,
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     const char* keywordName,
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     char* buffer, int32_t bufferCapacity,
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     UErrorCode* status)
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
82527f654740f2a26ad62a5c155af9199af9e69b889claireho    const char* startSearchHere = NULL;
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* nextSeparator = NULL;
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char keywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN];
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char localeKeywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN];
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i = 0;
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result = 0;
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(status && U_SUCCESS(*status) && localeID) {
83327f654740f2a26ad62a5c155af9199af9e69b889claireho      char tempBuffer[ULOC_FULLNAME_CAPACITY];
83427f654740f2a26ad62a5c155af9199af9e69b889claireho      const char* tmpLocaleID;
83527f654740f2a26ad62a5c155af9199af9e69b889claireho
83627f654740f2a26ad62a5c155af9199af9e69b889claireho      if (_hasBCP47Extension(localeID)) {
83727f654740f2a26ad62a5c155af9199af9e69b889claireho          _ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), status);
83827f654740f2a26ad62a5c155af9199af9e69b889claireho      } else {
83927f654740f2a26ad62a5c155af9199af9e69b889claireho          tmpLocaleID=localeID;
84027f654740f2a26ad62a5c155af9199af9e69b889claireho      }
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
84227f654740f2a26ad62a5c155af9199af9e69b889claireho      startSearchHere = uprv_strchr(tmpLocaleID, '@'); /* TODO: REVISIT: shouldn't this be locale_getKeywordsStart ? */
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(startSearchHere == NULL) {
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          /* no keywords, return at once */
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          return 0;
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locale_canonKeywordName(keywordNameBuffer, keywordName, status);
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(U_FAILURE(*status)) {
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      /* find the first keyword */
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      while(startSearchHere) {
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          startSearchHere++;
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          /* skip leading spaces (allowed?) */
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          while(*startSearchHere == ' ') {
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              startSearchHere++;
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          nextSeparator = uprv_strchr(startSearchHere, '=');
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          /* need to normalize both keyword and keyword name */
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          if(!nextSeparator) {
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              break;
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          if(nextSeparator - startSearchHere >= ULOC_KEYWORD_BUFFER_LEN) {
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              /* keyword name too long for internal buffer */
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              *status = U_INTERNAL_PROGRAM_ERROR;
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              return 0;
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          for(i = 0; i < nextSeparator - startSearchHere; i++) {
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              localeKeywordNameBuffer[i] = uprv_tolower(startSearchHere[i]);
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          /* trim trailing spaces */
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          while(startSearchHere[i-1] == ' ') {
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              i--;
876103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius              U_ASSERT(i>=0);
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          localeKeywordNameBuffer[i] = 0;
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          startSearchHere = uprv_strchr(nextSeparator, ';');
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          if(uprv_strcmp(keywordNameBuffer, localeKeywordNameBuffer) == 0) {
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              nextSeparator++;
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              while(*nextSeparator == ' ') {
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  nextSeparator++;
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              }
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              /* we actually found the keyword. Copy the value */
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              if(startSearchHere && startSearchHere - nextSeparator < bufferCapacity) {
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  while(*(startSearchHere-1) == ' ') {
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                      startSearchHere--;
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  }
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  uprv_strncpy(buffer, nextSeparator, startSearchHere - nextSeparator);
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  result = u_terminateChars(buffer, bufferCapacity, (int32_t)(startSearchHere - nextSeparator), status);
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              } else if(!startSearchHere && (int32_t)uprv_strlen(nextSeparator) < bufferCapacity) { /* last item in string */
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  i = (int32_t)uprv_strlen(nextSeparator);
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  while(nextSeparator[i - 1] == ' ') {
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                      i--;
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  }
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  uprv_strncpy(buffer, nextSeparator, i);
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  result = u_terminateChars(buffer, bufferCapacity, i, status);
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              } else {
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  /* give a bigger buffer, please */
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  *status = U_BUFFER_OVERFLOW_ERROR;
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  if(startSearchHere) {
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                      result = (int32_t)(startSearchHere - nextSeparator);
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  } else {
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                      result = (int32_t)uprv_strlen(nextSeparator);
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  }
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              }
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              return result;
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_setKeywordValue(const char* keywordName,
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     const char* keywordValue,
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     char* buffer, int32_t bufferCapacity,
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     UErrorCode* status)
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* TODO: sorting. removal. */
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t keywordNameLen;
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t keywordValueLen;
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t bufLen;
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t needLen = 0;
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t foundValueLen;
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t keywordAtEnd = 0; /* is the keyword at the end of the string? */
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char keywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN];
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char localeKeywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN];
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i = 0;
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t rc;
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char* nextSeparator = NULL;
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char* nextEqualsign = NULL;
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char* startSearchHere = NULL;
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char* keywordStart = NULL;
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *insertHere = NULL;
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*status)) {
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(bufferCapacity>1) {
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        bufLen = (int32_t)uprv_strlen(buffer);
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_ILLEGAL_ARGUMENT_ERROR;
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(bufferCapacity<bufLen) {
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* The capacity is less than the length?! Is this NULL terminated? */
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_ILLEGAL_ARGUMENT_ERROR;
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(keywordValue && !*keywordValue) {
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        keywordValue = NULL;
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(keywordValue) {
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        keywordValueLen = (int32_t)uprv_strlen(keywordValue);
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        keywordValueLen = 0;
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    keywordNameLen = locale_canonKeywordName(keywordNameBuffer, keywordName, status);
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*status)) {
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startSearchHere = (char*)locale_getKeywordsStart(buffer);
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(startSearchHere == NULL || (startSearchHere[1]==0)) {
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(!keywordValue) { /* no keywords = nothing to remove */
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return bufLen;
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        needLen = bufLen+1+keywordNameLen+1+keywordValueLen;
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(startSearchHere) { /* had a single @ */
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            needLen--; /* already had the @ */
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* startSearchHere points at the @ */
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            startSearchHere=buffer+bufLen;
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(needLen >= bufferCapacity) {
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_BUFFER_OVERFLOW_ERROR;
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return needLen; /* no change */
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *startSearchHere = '@';
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startSearchHere++;
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcpy(startSearchHere, keywordNameBuffer);
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startSearchHere += keywordNameLen;
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *startSearchHere = '=';
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startSearchHere++;
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcpy(startSearchHere, keywordValue);
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startSearchHere+=keywordValueLen;
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return needLen;
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } /* end shortcut - no @ */
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    keywordStart = startSearchHere;
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* search for keyword */
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(keywordStart) {
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        keywordStart++;
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* skip leading spaces (allowed?) */
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(*keywordStart == ' ') {
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            keywordStart++;
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        nextEqualsign = uprv_strchr(keywordStart, '=');
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* need to normalize both keyword and keyword name */
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(!nextEqualsign) {
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(nextEqualsign - keywordStart >= ULOC_KEYWORD_BUFFER_LEN) {
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* keyword name too long for internal buffer */
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INTERNAL_PROGRAM_ERROR;
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i = 0; i < nextEqualsign - keywordStart; i++) {
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            localeKeywordNameBuffer[i] = uprv_tolower(keywordStart[i]);
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* trim trailing spaces */
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(keywordStart[i-1] == ' ') {
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i--;
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
101854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        U_ASSERT(i>=0 && i<ULOC_KEYWORD_BUFFER_LEN);
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeKeywordNameBuffer[i] = 0;
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        nextSeparator = uprv_strchr(nextEqualsign, ';');
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rc = uprv_strcmp(keywordNameBuffer, localeKeywordNameBuffer);
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(rc == 0) {
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            nextEqualsign++;
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(*nextEqualsign == ' ') {
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                nextEqualsign++;
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* we actually found the keyword. Change the value */
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (nextSeparator) {
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordAtEnd = 0;
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                foundValueLen = (int32_t)(nextSeparator - nextEqualsign);
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordAtEnd = 1;
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                foundValueLen = (int32_t)uprv_strlen(nextEqualsign);
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(keywordValue) { /* adding a value - not removing */
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              if(foundValueLen == keywordValueLen) {
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_strncpy(nextEqualsign, keywordValue, keywordValueLen);
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return bufLen; /* no change in size */
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              } else if(foundValueLen > keywordValueLen) {
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t delta = foundValueLen - keywordValueLen;
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(nextSeparator) { /* RH side */
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  uprv_memmove(nextSeparator - delta, nextSeparator, bufLen-(nextSeparator-buffer));
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_strncpy(nextEqualsign, keywordValue, keywordValueLen);
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                bufLen -= delta;
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                buffer[bufLen]=0;
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return bufLen;
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              } else { /* FVL < KVL */
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t delta = keywordValueLen - foundValueLen;
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if((bufLen+delta) >= bufferCapacity) {
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  *status = U_BUFFER_OVERFLOW_ERROR;
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  return bufLen+delta;
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(nextSeparator) { /* RH side */
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  uprv_memmove(nextSeparator+delta,nextSeparator, bufLen-(nextSeparator-buffer));
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_strncpy(nextEqualsign, keywordValue, keywordValueLen);
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                bufLen += delta;
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                buffer[bufLen]=0;
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return bufLen;
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              }
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else { /* removing a keyword */
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              if(keywordAtEnd) {
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* zero out the ';' or '@' just before startSearchhere */
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordStart[-1] = 0;
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return (int32_t)((keywordStart-buffer)-1); /* (string length without keyword) minus separator */
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              } else {
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_memmove(keywordStart, nextSeparator+1, bufLen-((nextSeparator+1)-buffer));
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                keywordStart[bufLen-((nextSeparator+1)-buffer)]=0;
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return (int32_t)(bufLen-((nextSeparator+1)-keywordStart));
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              }
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if(rc<0){ /* end match keyword */
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          /* could insert at this location. */
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          insertHere = keywordStart;
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        keywordStart = nextSeparator;
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } /* end loop searching */
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!keywordValue) {
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return bufLen; /* removal of non-extant keyword - no change */
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* we know there is at least one keyword. */
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    needLen = bufLen+1+keywordNameLen+1+keywordValueLen;
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(needLen >= bufferCapacity) {
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_BUFFER_OVERFLOW_ERROR;
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return needLen; /* no change */
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(insertHere) {
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      uprv_memmove(insertHere+(1+keywordNameLen+1+keywordValueLen), insertHere, bufLen-(insertHere-buffer));
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      keywordStart = insertHere;
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      keywordStart = buffer+bufLen;
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *keywordStart = ';';
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      keywordStart++;
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strncpy(keywordStart, keywordNameBuffer, keywordNameLen);
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    keywordStart += keywordNameLen;
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *keywordStart = '=';
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    keywordStart++;
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strncpy(keywordStart, keywordValue, keywordValueLen); /* terminates. */
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    keywordStart+=keywordValueLen;
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(insertHere) {
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *keywordStart = ';';
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      keywordStart++;
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    buffer[needLen]=0;
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return needLen;
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* ### ID parsing implementation **************************************************/
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define _isPrefixLetter(a) ((a=='x')||(a=='X')||(a=='i')||(a=='I'))
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*returns TRUE if one of the special prefixes is here (s=string)
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  'x-' or 'i-' */
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define _isIDPrefix(s) (_isPrefixLetter(s[0])&&_isIDSeparator(s[1]))
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Dot terminates it because of POSIX form  where dot precedes the codepage
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * except for variant
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define _isTerminator(a)  ((a==0)||(a=='.')||(a=='@'))
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char* _strnchr(const char* str, int32_t len, char c) {
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_ASSERT(str != 0 && len >= 0);
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (len-- != 0) {
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char d = *str;
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (d == c) {
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return (char*) str;
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (d == 0) {
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++str;
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Lookup 'key' in the array 'list'.  The array 'list' should contain
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * a NULL entry, followed by more entries, and a second NULL entry.
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The 'list' param should be LANGUAGES, LANGUAGES_3, COUNTRIES, or
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * COUNTRIES_3.
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int16_t _findIndex(const char* const* list, const char* key)
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* const* anchor = list;
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t pass = 0;
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Make two passes through two NULL-terminated arrays at 'list' */
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (pass++ < 2) {
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (*list) {
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (uprv_strcmp(key, *list) == 0) {
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return (int16_t)(list - anchor);
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            list++;
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++list;     /* skip final NULL *CWB*/
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* count the length of src while copying it to dest; return strlen(src) */
1167103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic inline int32_t
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_copyCount(char *dest, int32_t destCapacity, const char *src) {
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *anchor;
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char c;
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    anchor=src;
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(;;) {
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((c=*src)==0) {
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return (int32_t)(src-anchor);
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(destCapacity<=0) {
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return (int32_t)((src-anchor)+uprv_strlen(src));
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++src;
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *dest++=c;
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --destCapacity;
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
118650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CFUNC const char*
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getCurrentCountryID(const char* oldID){
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset = _findIndex(DEPRECATED_COUNTRIES, oldID);
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offset >= 0) {
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return REPLACEMENT_COUNTRIES[offset];
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return oldID;
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
119450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CFUNC const char*
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getCurrentLanguageID(const char* oldID){
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset = _findIndex(DEPRECATED_LANGUAGES, oldID);
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offset >= 0) {
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return REPLACEMENT_LANGUAGES[offset];
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return oldID;
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the internal functions _getLanguage(), _getCountry(), _getVariant()
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * avoid duplicating code to handle the earlier locale ID pieces
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * in the functions for the later ones by
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * setting the *pEnd pointer to where they stopped parsing
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * TODO try to use this in Locale
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
121050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CFUNC int32_t
121150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoulocimp_getLanguage(const char *localeID,
121250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    char *language, int32_t languageCapacity,
121350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    const char **pEnd) {
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=0;
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset;
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char lang[4]={ 0, 0, 0, 0 }; /* temporary buffer to hold language code for searching */
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* if it starts with i- or x- then copy that prefix */
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(_isIDPrefix(localeID)) {
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(i<languageCapacity) {
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            language[i]=(char)uprv_tolower(*localeID);
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(i<languageCapacity) {
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            language[i+1]='-';
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i+=2;
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID+=2;
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* copy the language as far as possible and count its length */
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(!_isTerminator(*localeID) && !_isIDSeparator(*localeID)) {
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(i<languageCapacity) {
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            language[i]=(char)uprv_tolower(*localeID);
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(i<3) {
1236103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(i>=0);
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            lang[i]=(char)uprv_tolower(*localeID);
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i++;
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID++;
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(i==3) {
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* convert 3 character code to 2 character code if possible *CWB*/
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset=_findIndex(LANGUAGES_3, lang);
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(offset>=0) {
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i=_copyCount(language, languageCapacity, LANGUAGES[offset]);
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pEnd!=NULL) {
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pEnd=localeID;
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return i;
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
125750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CFUNC int32_t
125850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoulocimp_getScript(const char *localeID,
125950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                  char *script, int32_t scriptCapacity,
126050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                  const char **pEnd)
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t idLen = 0;
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (pEnd != NULL) {
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pEnd = localeID;
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* copy the second item as far as possible and count its length */
1269103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    while(!_isTerminator(localeID[idLen]) && !_isIDSeparator(localeID[idLen])
1270103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            && uprv_isASCIILetter(localeID[idLen])) {
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        idLen++;
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* If it's exactly 4 characters long, then it's a script and not a country. */
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (idLen == 4) {
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i;
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pEnd != NULL) {
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pEnd = localeID+idLen;
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(idLen > scriptCapacity) {
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            idLen = scriptCapacity;
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (idLen >= 1) {
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            script[0]=(char)uprv_toupper(*(localeID++));
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (i = 1; i < idLen; i++) {
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            script[i]=(char)uprv_tolower(*(localeID++));
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        idLen = 0;
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return idLen;
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CFUNC int32_t
129750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoulocimp_getCountry(const char *localeID,
129850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   char *country, int32_t countryCapacity,
129950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   const char **pEnd)
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
130150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t idLen=0;
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char cnty[ULOC_COUNTRY_CAPACITY]={ 0, 0, 0, 0 };
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset;
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* copy the country as far as possible and count its length */
130650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    while(!_isTerminator(localeID[idLen]) && !_isIDSeparator(localeID[idLen])) {
130750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(idLen<(ULOC_COUNTRY_CAPACITY-1)) {   /*CWB*/
130850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            cnty[idLen]=(char)uprv_toupper(localeID[idLen]);
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
131050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        idLen++;
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
131350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* the country should be either length 2 or 3 */
131450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (idLen == 2 || idLen == 3) {
131550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UBool gotCountry = FALSE;
131650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* convert 3 character code to 2 character code if possible *CWB*/
131750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(idLen==3) {
131850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            offset=_findIndex(COUNTRIES_3, cnty);
131950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(offset>=0) {
132050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                idLen=_copyCount(country, countryCapacity, COUNTRIES[offset]);
132150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                gotCountry = TRUE;
132250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
132350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
132450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (!gotCountry) {
132550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            int32_t i = 0;
132650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            for (i = 0; i < idLen; i++) {
132750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if (i < countryCapacity) {
132850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    country[i]=(char)uprv_toupper(localeID[i]);
132950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
133050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
133250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        localeID+=idLen;
133350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
133450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        idLen = 0;
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pEnd!=NULL) {
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pEnd=localeID;
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
134050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
134150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return idLen;
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param needSeparator if true, then add leading '_' if any variants
1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * are added to 'variant'
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_getVariantEx(const char *localeID,
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              char prev,
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              char *variant, int32_t variantCapacity,
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UBool needSeparator) {
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=0;
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* get one or more variant tags and separate them with '_' */
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(_isIDSeparator(prev)) {
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* get a variant string after a '-' or '_' */
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(!_isTerminator(*localeID)) {
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (needSeparator) {
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (i<variantCapacity) {
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    variant[i] = '_';
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++i;
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                needSeparator = FALSE;
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(i<variantCapacity) {
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                variant[i]=(char)uprv_toupper(*localeID);
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(variant[i]=='-') {
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    variant[i]='_';
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i++;
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            localeID++;
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* if there is no variant tag after a '-' or '_' then look for '@' */
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(i==0) {
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(prev=='@') {
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* keep localeID */
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if((localeID=locale_getKeywordsStart(localeID))!=NULL) {
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++localeID; /* point after the '@' */
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(!_isTerminator(*localeID)) {
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (needSeparator) {
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (i<variantCapacity) {
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    variant[i] = '_';
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++i;
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                needSeparator = FALSE;
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(i<variantCapacity) {
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                variant[i]=(char)uprv_toupper(*localeID);
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(variant[i]=='-' || variant[i]==',') {
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    variant[i]='_';
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i++;
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            localeID++;
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return i;
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_getVariant(const char *localeID,
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char prev,
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char *variant, int32_t variantCapacity) {
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return _getVariantEx(localeID, prev, variant, variantCapacity, FALSE);
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Delete ALL instances of a variant from the given list of one or
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * more variants.  Example: "FOO_EURO_BAR_EURO" => "FOO_BAR".
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param variants the source string of one or more variants,
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * separated by '_'.  This will be MODIFIED IN PLACE.  Not zero
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * terminated; if it is, trailing zero will NOT be maintained.
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param variantsLen length of variants
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param toDelete variant to delete, without separators, e.g.  "EURO"
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * or "PREEURO"; not zero terminated
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param toDeleteLen length of toDelete
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return number of characters deleted from variants
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_deleteVariant(char* variants, int32_t variantsLen,
1429c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru               const char* toDelete, int32_t toDeleteLen)
1430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t delta = 0; /* number of chars deleted */
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;) {
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool flag = FALSE;
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (variantsLen < toDeleteLen) {
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return delta;
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (uprv_strncmp(variants, toDelete, toDeleteLen) == 0 &&
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (variantsLen == toDeleteLen ||
1439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             (flag=(variants[toDeleteLen] == '_'))))
1440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        {
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t d = toDeleteLen + (flag?1:0);
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            variantsLen -= d;
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta += d;
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (variantsLen > 0) {
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_memmove(variants, variants+d, variantsLen);
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char* p = _strnchr(variants, variantsLen, '_');
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (p == NULL) {
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return delta;
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++p;
1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            variantsLen -= (int32_t)(p - variants);
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            variants = p;
1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Keyword enumeration */
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct UKeywordsContext {
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char* keywords;
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char* current;
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} UKeywordsContext;
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_kw_closeKeywords(UEnumeration *enumerator) {
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(((UKeywordsContext *)enumerator->context)->keywords);
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(enumerator->context);
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(enumerator);
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV
1474103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusuloc_kw_countKeywords(UEnumeration *en, UErrorCode * /*status*/) {
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *kw = ((UKeywordsContext *)en->context)->keywords;
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result = 0;
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(*kw) {
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result++;
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        kw += uprv_strlen(kw)+1;
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char* U_CALLCONV
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_kw_nextKeyword(UEnumeration* en,
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t* resultLength,
1487103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    UErrorCode* /*status*/) {
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* result = ((UKeywordsContext *)en->context)->current;
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len = 0;
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(*result) {
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        len = (int32_t)uprv_strlen(((UKeywordsContext *)en->context)->current);
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((UKeywordsContext *)en->context)->current += len+1;
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = NULL;
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (resultLength) {
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *resultLength = len;
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_kw_resetKeywords(UEnumeration* en,
1504103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                      UErrorCode* /*status*/) {
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((UKeywordsContext *)en->context)->current = ((UKeywordsContext *)en->context)->keywords;
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UEnumeration gKeywordsEnum = {
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NULL,
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NULL,
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_kw_closeKeywords,
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_kw_countKeywords,
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uenum_unextDefault,
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_kw_nextKeyword,
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_kw_resetKeywords
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UEnumeration* U_EXPORT2
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_openKeywordList(const char *keywordList, int32_t keywordListSize, UErrorCode* status)
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1521c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UKeywordsContext *myContext = NULL;
1522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UEnumeration *result = NULL;
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(U_FAILURE(*status)) {
1525c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return NULL;
1526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1527c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    result = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
1528c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* Null pointer test */
1529c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (result == NULL) {
1530c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
1531c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return NULL;
1532c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1533c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uprv_memcpy(result, &gKeywordsEnum, sizeof(UEnumeration));
153454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    myContext = static_cast<UKeywordsContext *>(uprv_malloc(sizeof(UKeywordsContext)));
1535c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (myContext == NULL) {
1536c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
1537c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uprv_free(result);
1538c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return NULL;
1539c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1540c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    myContext->keywords = (char *)uprv_malloc(keywordListSize+1);
1541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uprv_memcpy(myContext->keywords, keywordList, keywordListSize);
1542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    myContext->keywords[keywordListSize] = 0;
1543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    myContext->current = myContext->keywords;
1544c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    result->context = myContext;
1545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return result;
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UEnumeration* U_EXPORT2
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_openKeywords(const char* localeID,
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UErrorCode* status)
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=0;
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char keywords[256];
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t keywordsCapacity = 256;
155527f654740f2a26ad62a5c155af9199af9e69b889claireho    char tempBuffer[ULOC_FULLNAME_CAPACITY];
155627f654740f2a26ad62a5c155af9199af9e69b889claireho    const char* tmpLocaleID;
155727f654740f2a26ad62a5c155af9199af9e69b889claireho
1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(status==NULL || U_FAILURE(*status)) {
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
156227f654740f2a26ad62a5c155af9199af9e69b889claireho    if (_hasBCP47Extension(localeID)) {
156327f654740f2a26ad62a5c155af9199af9e69b889claireho        _ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), status);
156427f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
156527f654740f2a26ad62a5c155af9199af9e69b889claireho        if (localeID==NULL) {
156627f654740f2a26ad62a5c155af9199af9e69b889claireho           localeID=uloc_getDefault();
156727f654740f2a26ad62a5c155af9199af9e69b889claireho        }
156827f654740f2a26ad62a5c155af9199af9e69b889claireho        tmpLocaleID=localeID;
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Skip the language */
157227f654740f2a26ad62a5c155af9199af9e69b889claireho    ulocimp_getLanguage(tmpLocaleID, NULL, 0, &tmpLocaleID);
157327f654740f2a26ad62a5c155af9199af9e69b889claireho    if(_isIDSeparator(*tmpLocaleID)) {
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *scriptID;
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Skip the script if available */
157627f654740f2a26ad62a5c155af9199af9e69b889claireho        ulocimp_getScript(tmpLocaleID+1, NULL, 0, &scriptID);
157727f654740f2a26ad62a5c155af9199af9e69b889claireho        if(scriptID != tmpLocaleID+1) {
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Found optional script */
157927f654740f2a26ad62a5c155af9199af9e69b889claireho            tmpLocaleID = scriptID;
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Skip the Country */
158227f654740f2a26ad62a5c155af9199af9e69b889claireho        if (_isIDSeparator(*tmpLocaleID)) {
158327f654740f2a26ad62a5c155af9199af9e69b889claireho            ulocimp_getCountry(tmpLocaleID+1, NULL, 0, &tmpLocaleID);
158427f654740f2a26ad62a5c155af9199af9e69b889claireho            if(_isIDSeparator(*tmpLocaleID)) {
158527f654740f2a26ad62a5c155af9199af9e69b889claireho                _getVariant(tmpLocaleID+1, *tmpLocaleID, NULL, 0);
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* keywords are located after '@' */
159127f654740f2a26ad62a5c155af9199af9e69b889claireho    if((tmpLocaleID = locale_getKeywordsStart(tmpLocaleID)) != NULL) {
159227f654740f2a26ad62a5c155af9199af9e69b889claireho        i=locale_getKeywords(tmpLocaleID+1, '@', keywords, keywordsCapacity, NULL, 0, NULL, FALSE, status);
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(i) {
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return uloc_openKeywordList(keywords, i, status);
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* bit-flags for 'options' parameter of _canonicalize */
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define _ULOC_STRIP_KEYWORDS 0x2
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define _ULOC_CANONICALIZE   0x1
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define OPTION_SET(options, mask) ((options & mask) != 0)
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char i_default[] = {'i', '-', 'd', 'e', 'f', 'a', 'u', 'l', 't'};
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define I_DEFAULT_LENGTH (sizeof i_default / sizeof i_default[0])
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Canonicalize the given localeID, to level 1 or to level 2,
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * depending on the options.  To specify level 1, pass in options=0.
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * To specify level 2, pass in options=_ULOC_CANONICALIZE.
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is the code underlying uloc_getName and uloc_canonicalize.
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_canonicalize(const char* localeID,
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              char* result,
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t resultCapacity,
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              uint32_t options,
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UErrorCode* err) {
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t j, len, fieldCount=0, scriptSize=0, variantSize=0, nameCapacity;
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char localeBuffer[ULOC_FULLNAME_CAPACITY];
162727f654740f2a26ad62a5c155af9199af9e69b889claireho    char tempBuffer[ULOC_FULLNAME_CAPACITY];
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* origLocaleID;
162927f654740f2a26ad62a5c155af9199af9e69b889claireho    const char* tmpLocaleID;
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* keywordAssign = NULL;
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* separatorIndicator = NULL;
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* addKeyword = NULL;
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* addValue = NULL;
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char* name;
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char* variant = NULL; /* pointer into name, or NULL */
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*err)) {
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
164127f654740f2a26ad62a5c155af9199af9e69b889claireho    if (_hasBCP47Extension(localeID)) {
164227f654740f2a26ad62a5c155af9199af9e69b889claireho        _ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), err);
164327f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
164427f654740f2a26ad62a5c155af9199af9e69b889claireho        if (localeID==NULL) {
164527f654740f2a26ad62a5c155af9199af9e69b889claireho           localeID=uloc_getDefault();
164627f654740f2a26ad62a5c155af9199af9e69b889claireho        }
164727f654740f2a26ad62a5c155af9199af9e69b889claireho        tmpLocaleID=localeID;
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
164927f654740f2a26ad62a5c155af9199af9e69b889claireho
165027f654740f2a26ad62a5c155af9199af9e69b889claireho    origLocaleID=tmpLocaleID;
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* if we are doing a full canonicalization, then put results in
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       localeBuffer, if necessary; otherwise send them to result. */
165450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (/*OPTION_SET(options, _ULOC_CANONICALIZE) &&*/
1655103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        (result == NULL || resultCapacity < (int32_t)sizeof(localeBuffer))) {
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = localeBuffer;
1657103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        nameCapacity = (int32_t)sizeof(localeBuffer);
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = result;
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        nameCapacity = resultCapacity;
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* get all pieces, one after another, and separate with '_' */
166427f654740f2a26ad62a5c155af9199af9e69b889claireho    len=ulocimp_getLanguage(tmpLocaleID, name, nameCapacity, &tmpLocaleID);
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(len == I_DEFAULT_LENGTH && uprv_strncmp(origLocaleID, i_default, len) == 0) {
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *d = uloc_getDefault();
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        len = (int32_t)uprv_strlen(d);
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (name != NULL) {
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strncpy(name, d, len);
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
167427f654740f2a26ad62a5c155af9199af9e69b889claireho    } else if(_isIDSeparator(*tmpLocaleID)) {
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *scriptID;
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++fieldCount;
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(len<nameCapacity) {
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            name[len]='_';
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++len;
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1683103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        scriptSize=ulocimp_getScript(tmpLocaleID+1,
1684103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            (len<nameCapacity ? name+len : NULL), nameCapacity-len, &scriptID);
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(scriptSize > 0) {
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Found optional script */
168727f654740f2a26ad62a5c155af9199af9e69b889claireho            tmpLocaleID = scriptID;
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++fieldCount;
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len+=scriptSize;
169027f654740f2a26ad62a5c155af9199af9e69b889claireho            if (_isIDSeparator(*tmpLocaleID)) {
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* If there is something else, then we add the _ */
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(len<nameCapacity) {
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    name[len]='_';
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++len;
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
169927f654740f2a26ad62a5c155af9199af9e69b889claireho        if (_isIDSeparator(*tmpLocaleID)) {
170050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const char *cntryID;
1701103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            int32_t cntrySize = ulocimp_getCountry(tmpLocaleID+1,
1702103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                (len<nameCapacity ? name+len : NULL), nameCapacity-len, &cntryID);
170350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if (cntrySize > 0) {
170450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                /* Found optional country */
170527f654740f2a26ad62a5c155af9199af9e69b889claireho                tmpLocaleID = cntryID;
170650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                len+=cntrySize;
170750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
170827f654740f2a26ad62a5c155af9199af9e69b889claireho            if(_isIDSeparator(*tmpLocaleID)) {
170954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                /* If there is something else, then we add the _  if we found country before. */
171054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                if (cntrySize >= 0 && ! _isIDSeparator(*(tmpLocaleID+1)) ) {
171150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    ++fieldCount;
171250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    if(len<nameCapacity) {
171350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        name[len]='_';
171450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
171550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    ++len;
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
171750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1718103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                variantSize = _getVariant(tmpLocaleID+1, *tmpLocaleID,
1719103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    (len<nameCapacity ? name+len : NULL), nameCapacity-len);
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (variantSize > 0) {
1721103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    variant = len<nameCapacity ? name+len : NULL;
1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    len += variantSize;
172327f654740f2a26ad62a5c155af9199af9e69b889claireho                    tmpLocaleID += variantSize + 1; /* skip '_' and variant */
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Copy POSIX-style charset specifier, if any [mr.utf8] */
173027f654740f2a26ad62a5c155af9199af9e69b889claireho    if (!OPTION_SET(options, _ULOC_CANONICALIZE) && *tmpLocaleID == '.') {
1731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool done = FALSE;
1732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        do {
173327f654740f2a26ad62a5c155af9199af9e69b889claireho            char c = *tmpLocaleID;
1734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch (c) {
1735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            case 0:
1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            case '@':
1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                done = TRUE;
1738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            default:
1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (len<nameCapacity) {
1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    name[len] = c;
1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++len;
174427f654740f2a26ad62a5c155af9199af9e69b889claireho                ++tmpLocaleID;
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } while (!done);
1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Scan ahead to next '@' and determine if it is followed by '=' and/or ';'
175127f654740f2a26ad62a5c155af9199af9e69b889claireho       After this, tmpLocaleID either points to '@' or is NULL */
175227f654740f2a26ad62a5c155af9199af9e69b889claireho    if ((tmpLocaleID=locale_getKeywordsStart(tmpLocaleID))!=NULL) {
175327f654740f2a26ad62a5c155af9199af9e69b889claireho        keywordAssign = uprv_strchr(tmpLocaleID, '=');
175427f654740f2a26ad62a5c155af9199af9e69b889claireho        separatorIndicator = uprv_strchr(tmpLocaleID, ';');
1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Copy POSIX-style variant, if any [mr@FOO] */
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!OPTION_SET(options, _ULOC_CANONICALIZE) &&
175927f654740f2a26ad62a5c155af9199af9e69b889claireho        tmpLocaleID != NULL && keywordAssign == NULL) {
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (;;) {
176127f654740f2a26ad62a5c155af9199af9e69b889claireho            char c = *tmpLocaleID;
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (c == 0) {
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (len<nameCapacity) {
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                name[len] = c;
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++len;
176927f654740f2a26ad62a5c155af9199af9e69b889claireho            ++tmpLocaleID;
1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (OPTION_SET(options, _ULOC_CANONICALIZE)) {
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Handle @FOO variant if @ is present and not followed by = */
177527f654740f2a26ad62a5c155af9199af9e69b889claireho        if (tmpLocaleID!=NULL && keywordAssign==NULL) {
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t posixVariantSize;
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Add missing '_' if needed */
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fieldCount < 2 || (fieldCount < 3 && scriptSize > 0)) {
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                do {
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(len<nameCapacity) {
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        name[len]='_';
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ++len;
1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ++fieldCount;
1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } while(fieldCount<2);
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
178727f654740f2a26ad62a5c155af9199af9e69b889claireho            posixVariantSize = _getVariantEx(tmpLocaleID+1, '@', name+len, nameCapacity-len,
1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                             (UBool)(variantSize > 0));
1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (posixVariantSize > 0) {
1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (variant == NULL) {
1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    variant = name+len;
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                len += posixVariantSize;
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                variantSize += posixVariantSize;
1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1798c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /* Handle generic variants first */
1799c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (variant) {
1800c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            for (j=0; j<(int32_t)(sizeof(VARIANT_MAP)/sizeof(VARIANT_MAP[0])); j++) {
1801c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                const char* variantToCompare = VARIANT_MAP[j].variant;
1802c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                int32_t n = (int32_t)uprv_strlen(variantToCompare);
1803c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                int32_t variantLen = _deleteVariant(variant, uprv_min(variantSize, (nameCapacity-len)), variantToCompare, n);
1804c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                len -= variantLen;
1805c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                if (variantLen > 0) {
1806ab19ce4e2e94e2c9e847a6ae07773a48e4d40713claireho                    if (len > 0 && name[len-1] == '_') { /* delete trailing '_' */
1807c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        --len;
1808c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    }
1809c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    addKeyword = VARIANT_MAP[j].keyword;
1810c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    addValue = VARIANT_MAP[j].value;
1811c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    break;
1812c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                }
1813c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1814ab19ce4e2e94e2c9e847a6ae07773a48e4d40713claireho            if (len > 0 && len <= nameCapacity && name[len-1] == '_') { /* delete trailing '_' */
1815c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                --len;
1816c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Look up the ID in the canonicalization map */
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (j=0; j<(int32_t)(sizeof(CANONICALIZE_MAP)/sizeof(CANONICALIZE_MAP[0])); j++) {
1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const char* id = CANONICALIZE_MAP[j].id;
1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t n = (int32_t)uprv_strlen(id);
1823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (len == n && uprv_strncmp(name, id, n) == 0) {
182427f654740f2a26ad62a5c155af9199af9e69b889claireho                if (n == 0 && tmpLocaleID != NULL) {
1825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break; /* Don't remap "" if keywords present */
1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                len = _copyCount(name, nameCapacity, CANONICALIZE_MAP[j].canonicalID);
1828c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                if (CANONICALIZE_MAP[j].keyword) {
1829c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    addKeyword = CANONICALIZE_MAP[j].keyword;
1830c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    addValue = CANONICALIZE_MAP[j].value;
1831c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                }
1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!OPTION_SET(options, _ULOC_STRIP_KEYWORDS)) {
183827f654740f2a26ad62a5c155af9199af9e69b889claireho        if (tmpLocaleID!=NULL && keywordAssign!=NULL &&
1839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (!separatorIndicator || separatorIndicator > keywordAssign)) {
1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(len<nameCapacity) {
1841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                name[len]='@';
1842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++len;
1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++fieldCount;
1845103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            len += _getKeywords(tmpLocaleID+1, '@', (len<nameCapacity ? name+len : NULL), nameCapacity-len,
1846103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                NULL, 0, NULL, TRUE, addKeyword, addValue, err);
1847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (addKeyword != NULL) {
184854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            U_ASSERT(addValue != NULL && len < nameCapacity);
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* inelegant but works -- later make _getKeywords do this? */
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len += _copyCount(name+len, nameCapacity-len, "@");
1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len += _copyCount(name+len, nameCapacity-len, addKeyword);
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len += _copyCount(name+len, nameCapacity-len, "=");
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len += _copyCount(name+len, nameCapacity-len, addValue);
1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(*err) && result != NULL && name == localeBuffer) {
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strncpy(result, localeBuffer, (len > resultCapacity) ? resultCapacity : len);
1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateChars(result, resultCapacity, len, err);
1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* ### ID parsing API **************************************************/
1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t  U_EXPORT2
1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getParent(const char*    localeID,
1868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               char* parent,
1869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t parentCapacity,
1870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               UErrorCode* err)
1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *lastUnderscore;
1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i;
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*err))
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeID == NULL)
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID = uloc_getDefault();
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lastUnderscore=uprv_strrchr(localeID, '_');
1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(lastUnderscore!=NULL) {
1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i=(int32_t)(lastUnderscore-localeID);
1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i=0;
1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(i>0 && parent != localeID) {
1889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memcpy(parent, localeID, uprv_min(i, parentCapacity));
1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateChars(parent, parentCapacity, i, err);
1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getLanguage(const char*    localeID,
1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         char* language,
1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         int32_t languageCapacity,
1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         UErrorCode* err)
1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* uloc_getLanguage will return a 2 character iso-639 code if one exists. *CWB*/
1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=0;
1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (err==NULL || U_FAILURE(*err)) {
1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(localeID==NULL) {
1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID=uloc_getDefault();
1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
191150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    i=ulocimp_getLanguage(localeID, language, languageCapacity, NULL);
1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateChars(language, languageCapacity, i, err);
1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getScript(const char*    localeID,
1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         char* script,
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         int32_t scriptCapacity,
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         UErrorCode* err)
1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=0;
1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(err==NULL || U_FAILURE(*err)) {
1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(localeID==NULL) {
1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID=uloc_getDefault();
1929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* skip the language */
193250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ulocimp_getLanguage(localeID, NULL, 0, &localeID);
1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(_isIDSeparator(*localeID)) {
193450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        i=ulocimp_getScript(localeID+1, script, scriptCapacity, NULL);
1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateChars(script, scriptCapacity, i, err);
1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t  U_EXPORT2
1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getCountry(const char* localeID,
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char* country,
1942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t countryCapacity,
1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode* err)
1944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=0;
1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(err==NULL || U_FAILURE(*err)) {
1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(localeID==NULL) {
1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID=uloc_getDefault();
1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Skip the language */
195650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ulocimp_getLanguage(localeID, NULL, 0, &localeID);
1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(_isIDSeparator(*localeID)) {
1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *scriptID;
1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Skip the script if available */
196050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ulocimp_getScript(localeID+1, NULL, 0, &scriptID);
1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(scriptID != localeID+1) {
1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Found optional script */
1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            localeID = scriptID;
1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(_isIDSeparator(*localeID)) {
196650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            i=ulocimp_getCountry(localeID+1, country, countryCapacity, NULL);
1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateChars(country, countryCapacity, i, err);
1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t  U_EXPORT2
1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getVariant(const char* localeID,
1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                char* variant,
1975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t variantCapacity,
1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode* err)
1977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
197827f654740f2a26ad62a5c155af9199af9e69b889claireho    char tempBuffer[ULOC_FULLNAME_CAPACITY];
197927f654740f2a26ad62a5c155af9199af9e69b889claireho    const char* tmpLocaleID;
1980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=0;
1981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(err==NULL || U_FAILURE(*err)) {
1983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198627f654740f2a26ad62a5c155af9199af9e69b889claireho    if (_hasBCP47Extension(localeID)) {
198727f654740f2a26ad62a5c155af9199af9e69b889claireho        _ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), err);
198827f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
198927f654740f2a26ad62a5c155af9199af9e69b889claireho        if (localeID==NULL) {
199027f654740f2a26ad62a5c155af9199af9e69b889claireho           localeID=uloc_getDefault();
199127f654740f2a26ad62a5c155af9199af9e69b889claireho        }
199227f654740f2a26ad62a5c155af9199af9e69b889claireho        tmpLocaleID=localeID;
1993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Skip the language */
199627f654740f2a26ad62a5c155af9199af9e69b889claireho    ulocimp_getLanguage(tmpLocaleID, NULL, 0, &tmpLocaleID);
199727f654740f2a26ad62a5c155af9199af9e69b889claireho    if(_isIDSeparator(*tmpLocaleID)) {
1998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *scriptID;
1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Skip the script if available */
200027f654740f2a26ad62a5c155af9199af9e69b889claireho        ulocimp_getScript(tmpLocaleID+1, NULL, 0, &scriptID);
200127f654740f2a26ad62a5c155af9199af9e69b889claireho        if(scriptID != tmpLocaleID+1) {
2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Found optional script */
200327f654740f2a26ad62a5c155af9199af9e69b889claireho            tmpLocaleID = scriptID;
2004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Skip the Country */
200627f654740f2a26ad62a5c155af9199af9e69b889claireho        if (_isIDSeparator(*tmpLocaleID)) {
200750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const char *cntryID;
200827f654740f2a26ad62a5c155af9199af9e69b889claireho            ulocimp_getCountry(tmpLocaleID+1, NULL, 0, &cntryID);
200927f654740f2a26ad62a5c155af9199af9e69b889claireho            if (cntryID != tmpLocaleID+1) {
201050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                /* Found optional country */
201127f654740f2a26ad62a5c155af9199af9e69b889claireho                tmpLocaleID = cntryID;
201250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
201327f654740f2a26ad62a5c155af9199af9e69b889claireho            if(_isIDSeparator(*tmpLocaleID)) {
201427f654740f2a26ad62a5c155af9199af9e69b889claireho                /* If there was no country ID, skip a possible extra IDSeparator */
201527f654740f2a26ad62a5c155af9199af9e69b889claireho                if (tmpLocaleID != cntryID && _isIDSeparator(tmpLocaleID[1])) {
201627f654740f2a26ad62a5c155af9199af9e69b889claireho                    tmpLocaleID++;
201727f654740f2a26ad62a5c155af9199af9e69b889claireho                }
201827f654740f2a26ad62a5c155af9199af9e69b889claireho                i=_getVariant(tmpLocaleID+1, *tmpLocaleID, variant, variantCapacity);
2019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* removed by weiv. We don't want to handle POSIX variants anymore. Use canonicalization function */
2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* if we do not have a variant tag yet then try a POSIX variant after '@' */
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!haveVariant && (localeID=uprv_strrchr(localeID, '@'))!=NULL) {
2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i=_getVariant(localeID+1, '@', variant, variantCapacity);
2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateChars(variant, variantCapacity, i, err);
2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t  U_EXPORT2
2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getName(const char* localeID,
2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             char* name,
2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t nameCapacity,
2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UErrorCode* err)
2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return _canonicalize(localeID, name, nameCapacity, 0, err);
2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t  U_EXPORT2
2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getBaseName(const char* localeID,
2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 char* name,
2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t nameCapacity,
2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 UErrorCode* err)
2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return _canonicalize(localeID, name, nameCapacity, _ULOC_STRIP_KEYWORDS, err);
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t  U_EXPORT2
2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_canonicalize(const char* localeID,
2053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  char* name,
2054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t nameCapacity,
2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UErrorCode* err)
2056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return _canonicalize(localeID, name, nameCapacity, _ULOC_CANONICALIZE, err);
2058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char*  U_EXPORT2
2061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getISO3Language(const char* localeID)
2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int16_t offset;
2064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char lang[ULOC_LANG_CAPACITY];
2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode err = U_ZERO_ERROR;
2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeID == NULL)
2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID = uloc_getDefault();
2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getLanguage(localeID, lang, ULOC_LANG_CAPACITY, &err);
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(err))
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return "";
2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset = _findIndex(LANGUAGES, lang);
2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offset < 0)
2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return "";
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return LANGUAGES_3[offset];
2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char*  U_EXPORT2
2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getISO3Country(const char* localeID)
2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int16_t offset;
2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char cntry[ULOC_LANG_CAPACITY];
2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode err = U_ZERO_ERROR;
2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeID == NULL)
2088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localeID = uloc_getDefault();
2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getCountry(localeID, cntry, ULOC_LANG_CAPACITY, &err);
2092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(err))
2093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return "";
2094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset = _findIndex(COUNTRIES, cntry);
2095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offset < 0)
2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return "";
2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return COUNTRIES_3[offset];
2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI uint32_t  U_EXPORT2
2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getLCID(const char* localeID)
2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char       langID[ULOC_FULLNAME_CAPACITY];
2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getLanguage(localeID, langID, sizeof(langID), &status);
2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
2110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
211259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (uprv_strchr(localeID, '@')) {
211359d709d503bab6e2b61931737e662dd293b40578ccornelius        // uprv_convertToLCID does not support keywords other than collation.
211459d709d503bab6e2b61931737e662dd293b40578ccornelius        // Remove all keywords except collation.
211559d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t len;
211659d709d503bab6e2b61931737e662dd293b40578ccornelius        char collVal[ULOC_KEYWORDS_CAPACITY];
211759d709d503bab6e2b61931737e662dd293b40578ccornelius        char tmpLocaleID[ULOC_FULLNAME_CAPACITY];
211859d709d503bab6e2b61931737e662dd293b40578ccornelius
211959d709d503bab6e2b61931737e662dd293b40578ccornelius        len = uloc_getKeywordValue(localeID, "collation", collVal,
212059d709d503bab6e2b61931737e662dd293b40578ccornelius            sizeof(collVal)/sizeof(collVal[0]) - 1, &status);
212159d709d503bab6e2b61931737e662dd293b40578ccornelius
212259d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_SUCCESS(status) && len > 0) {
212359d709d503bab6e2b61931737e662dd293b40578ccornelius            collVal[len] = 0;
212459d709d503bab6e2b61931737e662dd293b40578ccornelius
212559d709d503bab6e2b61931737e662dd293b40578ccornelius            len = uloc_getBaseName(localeID, tmpLocaleID,
212659d709d503bab6e2b61931737e662dd293b40578ccornelius                sizeof(tmpLocaleID)/sizeof(tmpLocaleID[0]) - 1, &status);
212759d709d503bab6e2b61931737e662dd293b40578ccornelius
212859d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_SUCCESS(status)) {
212959d709d503bab6e2b61931737e662dd293b40578ccornelius                tmpLocaleID[len] = 0;
213059d709d503bab6e2b61931737e662dd293b40578ccornelius
213159d709d503bab6e2b61931737e662dd293b40578ccornelius                len = uloc_setKeywordValue("collation", collVal, tmpLocaleID,
213259d709d503bab6e2b61931737e662dd293b40578ccornelius                    sizeof(tmpLocaleID)/sizeof(tmpLocaleID[0]) - len - 1, &status);
213359d709d503bab6e2b61931737e662dd293b40578ccornelius
213459d709d503bab6e2b61931737e662dd293b40578ccornelius                if (U_SUCCESS(status)) {
213559d709d503bab6e2b61931737e662dd293b40578ccornelius                    tmpLocaleID[len] = 0;
213659d709d503bab6e2b61931737e662dd293b40578ccornelius                    return uprv_convertToLCID(langID, tmpLocaleID, &status);
213759d709d503bab6e2b61931737e662dd293b40578ccornelius                }
213859d709d503bab6e2b61931737e662dd293b40578ccornelius            }
213959d709d503bab6e2b61931737e662dd293b40578ccornelius        }
214059d709d503bab6e2b61931737e662dd293b40578ccornelius
214159d709d503bab6e2b61931737e662dd293b40578ccornelius        // fall through - all keywords are simply ignored
214259d709d503bab6e2b61931737e662dd293b40578ccornelius        status = U_ZERO_ERROR;
214359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
214459d709d503bab6e2b61931737e662dd293b40578ccornelius
2145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return uprv_convertToLCID(langID, localeID, &status);
2146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
2149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getLocaleForLCID(uint32_t hostid, char *locale, int32_t localeCapacity,
2150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode *status)
2151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
215259d709d503bab6e2b61931737e662dd293b40578ccornelius    return uprv_convertToPosix(hostid, locale, localeCapacity, status);
2153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* ### Default locale **************************************************/
2156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char*  U_EXPORT2
2158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getDefault()
2159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return locale_get_default();
2161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void  U_EXPORT2
2164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_setDefault(const char*   newDefaultLocale,
2165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UErrorCode* err)
2166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*err))
2168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
2169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* the error code isn't currently used for anything by this function*/
2170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* propagate change to C++ */
2172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    locale_set_default(newDefaultLocale);
2173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
21768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius * Returns a list of all 2-letter language codes defined in ISO 639.  This is a pointer
2177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to an array of pointers to arrays of char.  All of these pointers are owned
2178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * by ICU-- do not delete them, and do not write through them.  The array is
2179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * terminated with a null pointer.
2180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
2181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char* const*  U_EXPORT2
2182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getISOLanguages()
2183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return LANGUAGES;
2185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
2188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Returns a list of all 2-letter country codes defined in ISO 639.  This is a
2189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * pointer to an array of pointers to arrays of char.  All of these pointers are
2190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * owned by ICU-- do not delete them, and do not write through them.  The array is
2191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * terminated with a null pointer.
2192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
2193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char* const*  U_EXPORT2
2194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_getISOCountries()
2195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return COUNTRIES;
2197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* this function to be moved into cstring.c later */
2201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char gDecimal = 0;
2202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic /* U_CAPI */
2204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querudouble
2205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* U_EXPORT2 */
2206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_uloc_strtod(const char *start, char **end) {
2207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *decimal;
2208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *myEnd;
2209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char buf[30];
2210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    double rv;
2211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!gDecimal) {
2212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char rep[5];
2213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* For machines that decide to change the decimal on you,
2214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        and try to be too smart with localization.
2215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        This normally should be just a '.'. */
2216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sprintf(rep, "%+1.1f", 1.0);
2217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        gDecimal = rep[2];
2218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(gDecimal == '.') {
2221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return uprv_strtod(start, end); /* fall through to OS */
2222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
2223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strncpy(buf, start, 29);
2224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        buf[29]=0;
2225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        decimal = uprv_strchr(buf, '.');
2226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(decimal) {
2227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *decimal = gDecimal;
2228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
2229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return uprv_strtod(start, end); /* no decimal point */
2230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rv = uprv_strtod(buf, &myEnd);
2232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(end) {
2233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *end = (char*)(start+(myEnd-buf)); /* cast away const (to follow uprv_strtod API.) */
2234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return rv;
2236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct {
2240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    float q;
2241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t dummy;  /* to avoid uninitialized memory copy from qsort */
2242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *locale;
2243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} _acceptLangItem;
2244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV
2246103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusuloc_acceptLanguageCompare(const void * /*context*/, const void *a, const void *b)
2247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const _acceptLangItem *aa = (const _acceptLangItem*)a;
2249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const _acceptLangItem *bb = (const _acceptLangItem*)b;
2250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t rc = 0;
2252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(bb->q < aa->q) {
2253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rc = -1;  /* A > B */
2254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(bb->q > aa->q) {
2255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rc = 1;   /* A < B */
2256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
2257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rc = 0;   /* A = B */
2258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(rc==0) {
2261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rc = uprv_stricmp(aa->locale, bb->locale);
2262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*  fprintf(stderr, "a:[%s:%g], b:[%s:%g] -> %d\n",
2266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    aa->locale, aa->q,
2267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    bb->locale, bb->q,
2268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rc);*/
2269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return rc;
2272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, nl-nl;q=0.55, nl;q=0.53
2276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
2277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
2279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, UAcceptResult *outResult,
2280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            const char *httpAcceptLanguage,
2281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            UEnumeration* availableLocales,
2282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            UErrorCode *status)
2283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    _acceptLangItem *j;
2285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    _acceptLangItem smallBuffer[30];
2286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char **strs;
2287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char tmp[ULOC_FULLNAME_CAPACITY +1];
2288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t n = 0;
2289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *itemEnd;
2290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *paramEnd;
2291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *s;
2292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *t;
2293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t res;
2294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i;
2295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t l = (int32_t)uprv_strlen(httpAcceptLanguage);
2296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t jSize;
2297c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char *tempstr; /* Use for null pointer check */
2298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    j = smallBuffer;
2300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    jSize = sizeof(smallBuffer)/sizeof(smallBuffer[0]);
2301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*status)) {
2302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
2303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(s=httpAcceptLanguage;s&&*s;) {
2306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(isspace(*s)) /* eat space at the beginning */
2307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s++;
2308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        itemEnd=uprv_strchr(s,',');
2309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        paramEnd=uprv_strchr(s,';');
2310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(!itemEnd) {
2311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            itemEnd = httpAcceptLanguage+l; /* end of string */
2312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(paramEnd && paramEnd<itemEnd) {
2314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* semicolon (;) is closer than end (,) */
2315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            t = paramEnd+1;
2316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(*t=='q') {
2317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                t++;
2318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(isspace(*t)) {
2320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                t++;
2321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(*t=='=') {
2323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                t++;
2324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(isspace(*t)) {
2326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                t++;
2327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            j[n].q = (float)_uloc_strtod(t,NULL);
2329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
2330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* no semicolon - it's 1.0 */
2331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            j[n].q = 1.0f;
2332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            paramEnd = itemEnd;
2333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        j[n].dummy=0;
2335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* eat spaces prior to semi */
2336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(t=(paramEnd-1);(paramEnd>s)&&isspace(*t);t--)
2337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ;
2338c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /* Check for null pointer from uprv_strndup */
2339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        tempstr = uprv_strndup(s,(int32_t)((t+1)-s));
2340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (tempstr == NULL) {
2341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            *status = U_MEMORY_ALLOCATION_ERROR;
2342c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return -1;
2343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
2344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        j[n].locale = tempstr;
2345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uloc_canonicalize(j[n].locale,tmp,sizeof(tmp)/sizeof(tmp[0]),status);
2346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(strcmp(j[n].locale,tmp)) {
2347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(j[n].locale);
2348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            j[n].locale=uprv_strdup(tmp);
2349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*fprintf(stderr,"%d: s <%s> q <%g>\n", n, j[n].locale, j[n].q);*/
2352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        n++;
2354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        s = itemEnd;
2355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(*s==',') { /* eat duplicate commas */
2356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s++;
2357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(n>=jSize) {
2359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(j==smallBuffer) {  /* overflowed the small buffer. */
236054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                j = static_cast<_acceptLangItem *>(uprv_malloc(sizeof(j[0])*(jSize*2)));
2361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(j!=NULL) {
2362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_memcpy(j,smallBuffer,sizeof(j[0])*jSize);
2363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fprintf(stderr,"malloced at size %d\n", jSize);
2366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
236854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                j = static_cast<_acceptLangItem *>(uprv_realloc(j, sizeof(j[0])*jSize*2));
2369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fprintf(stderr,"re-alloced at size %d\n", jSize);
2371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            jSize *= 2;
2374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(j==NULL) {
2375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_MEMORY_ALLOCATION_ERROR;
2376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return -1;
2377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_sortArray(j, n, sizeof(j[0]), uloc_acceptLanguageCompare, NULL, TRUE, status);
2381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*status)) {
2382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(j != smallBuffer) {
2383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fprintf(stderr,"freeing j %p\n", j);
2385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(j);
2387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
2389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
239054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    strs = static_cast<char **>(uprv_malloc((size_t)(sizeof(strs[0])*n)));
2391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* Check for null pointer */
2392c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (strs == NULL) {
2393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uprv_free(j); /* Free to avoid memory leak */
2394c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
2395c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return -1;
2396c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0;i<n;i++) {
2398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*fprintf(stderr,"%d: s <%s> q <%g>\n", i, j[i].locale, j[i].q);*/
2400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        strs[i]=j[i].locale;
2402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    res =  uloc_acceptLanguage(result, resultAvailable, outResult,
2404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        (const char**)strs, n, availableLocales, status);
2405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0;i<n;i++) {
2406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(strs[i]);
2407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(strs);
2409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(j != smallBuffer) {
2410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(stderr,"freeing j %p\n", j);
2412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(j);
2414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return res;
2416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
2420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuloc_acceptLanguage(char *result, int32_t resultAvailable,
2421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UAcceptResult *outResult, const char **acceptList,
2422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t acceptListCount,
2423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UEnumeration* availableLocales,
2424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UErrorCode *status)
2425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i,j;
2427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
2428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t maxLen=0;
2429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char tmp[ULOC_FULLNAME_CAPACITY+1];
2430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *l;
2431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char **fallbackList;
2432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*status)) {
2433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
2434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
243554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    fallbackList = static_cast<char **>(uprv_malloc((size_t)(sizeof(fallbackList[0])*acceptListCount)));
2436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fallbackList==NULL) {
2437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
2438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
2439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0;i<acceptListCount;i++) {
2441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(stderr,"%02d: %s\n", i, acceptList[i]);
2443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while((l=uenum_next(availableLocales, NULL, status))) {
2445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fprintf(stderr,"  %s\n", l);
2447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len = (int32_t)uprv_strlen(l);
2449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(!uprv_strcmp(acceptList[i], l)) {
2450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(outResult) {
2451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *outResult = ULOC_ACCEPT_VALID;
2452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fprintf(stderr, "MATCH! %s\n", l);
2455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(len>0) {
2457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_strncpy(result, l, uprv_min(len, resultAvailable));
2458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(j=0;j<i;j++) {
2460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_free(fallbackList[j]);
2461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_free(fallbackList);
2463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return u_terminateChars(result, resultAvailable, len, status);
2464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(len>maxLen) {
2466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                maxLen = len;
2467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uenum_reset(availableLocales, status);
2470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* save off parent info */
2471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(uloc_getParent(acceptList[i], tmp, sizeof(tmp)/sizeof(tmp[0]), status)!=0) {
2472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fallbackList[i] = uprv_strdup(tmp);
2473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
2474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fallbackList[i]=0;
2475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(maxLen--;maxLen>0;maxLen--) {
2479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0;i<acceptListCount;i++) {
2480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(fallbackList[i] && ((int32_t)uprv_strlen(fallbackList[i])==maxLen)) {
2481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fprintf(stderr,"Try: [%s]", fallbackList[i]);
2483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while((l=uenum_next(availableLocales, NULL, status))) {
2485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    fprintf(stderr,"  %s\n", l);
2487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    len = (int32_t)uprv_strlen(l);
2489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(!uprv_strcmp(fallbackList[i], l)) {
2490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if(outResult) {
2491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            *outResult = ULOC_ACCEPT_FALLBACK;
2492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(ULOC_DEBUG)
2494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        fprintf(stderr, "fallback MATCH! %s\n", l);
2495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if(len>0) {
2497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            uprv_strncpy(result, l, uprv_min(len, resultAvailable));
2498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        for(j=0;j<acceptListCount;j++) {
2500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            uprv_free(fallbackList[j]);
2501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        uprv_free(fallbackList);
2503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        return u_terminateChars(result, resultAvailable, len, status);
2504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uenum_reset(availableLocales, status);
2507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(uloc_getParent(fallbackList[i], tmp, sizeof(tmp)/sizeof(tmp[0]), status)!=0) {
2509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_free(fallbackList[i]);
2510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    fallbackList[i] = uprv_strdup(tmp);
2511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
2512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_free(fallbackList[i]);
2513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    fallbackList[i]=0;
2514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(outResult) {
2518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *outResult = ULOC_ACCEPT_FAILED;
2519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0;i<acceptListCount;i++) {
2522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(fallbackList[i]);
2523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(fallbackList);
2525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
2526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*eof*/
2529