intl/locale/src/unix/nsPosixLocale.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nscore.h"
michael@0 7 #include "nsString.h"
michael@0 8 #include "nsPosixLocale.h"
michael@0 9 #include "prprf.h"
michael@0 10 #include "plstr.h"
michael@0 11 #include "nsReadableUtils.h"
michael@0 12
michael@0 13 static bool
michael@0 14 ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator);
michael@0 15
michael@0 16 nsresult
michael@0 17 nsPosixLocale::GetPlatformLocale(const nsAString& locale, nsACString& posixLocale)
michael@0 18 {
michael@0 19 char country_code[MAX_COUNTRY_CODE_LEN+1];
michael@0 20 char lang_code[MAX_LANGUAGE_CODE_LEN+1];
michael@0 21 char extra[MAX_EXTRA_LEN+1];
michael@0 22 char posix_locale[MAX_LOCALE_LEN+1];
michael@0 23 NS_LossyConvertUTF16toASCII xp_locale(locale);
michael@0 24
michael@0 25 if (!xp_locale.IsEmpty()) {
michael@0 26 if (!ParseLocaleString(xp_locale.get(),lang_code,country_code,extra,'-')) {
michael@0 27 // strncpy(posixLocale,"C",length);
michael@0 28 posixLocale = xp_locale; // use xp locale if parse failed
michael@0 29 return NS_OK;
michael@0 30 }
michael@0 31
michael@0 32 if (*country_code) {
michael@0 33 if (*extra) {
michael@0 34 PR_snprintf(posix_locale,sizeof(posix_locale),"%s_%s.%s",lang_code,country_code,extra);
michael@0 35 }
michael@0 36 else {
michael@0 37 PR_snprintf(posix_locale,sizeof(posix_locale),"%s_%s",lang_code,country_code);
michael@0 38 }
michael@0 39 }
michael@0 40 else {
michael@0 41 if (*extra) {
michael@0 42 PR_snprintf(posix_locale,sizeof(posix_locale),"%s.%s",lang_code,extra);
michael@0 43 }
michael@0 44 else {
michael@0 45 PR_snprintf(posix_locale,sizeof(posix_locale),"%s",lang_code);
michael@0 46 }
michael@0 47 }
michael@0 48
michael@0 49 posixLocale = posix_locale;
michael@0 50 return NS_OK;
michael@0 51 }
michael@0 52
michael@0 53 return NS_ERROR_FAILURE;
michael@0 54 }
michael@0 55
michael@0 56 nsresult
michael@0 57 nsPosixLocale::GetXPLocale(const char* posixLocale, nsAString& locale)
michael@0 58 {
michael@0 59 char country_code[MAX_COUNTRY_CODE_LEN+1];
michael@0 60 char lang_code[MAX_LANGUAGE_CODE_LEN+1];
michael@0 61 char extra[MAX_EXTRA_LEN+1];
michael@0 62 char posix_locale[MAX_LOCALE_LEN+1];
michael@0 63
michael@0 64 if (posixLocale!=nullptr) {
michael@0 65 if (strcmp(posixLocale,"C")==0 || strcmp(posixLocale,"POSIX")==0) {
michael@0 66 locale.AssignLiteral("en-US");
michael@0 67 return NS_OK;
michael@0 68 }
michael@0 69 if (!ParseLocaleString(posixLocale,lang_code,country_code,extra,'_')) {
michael@0 70 // * locale = "x-user-defined";
michael@0 71 // use posix if parse failed
michael@0 72 CopyASCIItoUTF16(nsDependentCString(posixLocale), locale);
michael@0 73 return NS_OK;
michael@0 74 }
michael@0 75
michael@0 76 // Special case: substitute "nb" (Norwegian Bokmal) for macrolanguage
michael@0 77 // code "no" (Norwegian)
michael@0 78 if (nsDependentCString(lang_code).LowerCaseEqualsLiteral("no")) {
michael@0 79 lang_code[1] = 'b';
michael@0 80 }
michael@0 81
michael@0 82 if (*country_code) {
michael@0 83 PR_snprintf(posix_locale,sizeof(posix_locale),"%s-%s",lang_code,country_code);
michael@0 84 }
michael@0 85 else {
michael@0 86 PR_snprintf(posix_locale,sizeof(posix_locale),"%s",lang_code);
michael@0 87 }
michael@0 88
michael@0 89 CopyASCIItoUTF16(nsDependentCString(posix_locale), locale);
michael@0 90 return NS_OK;
michael@0 91
michael@0 92 }
michael@0 93
michael@0 94 return NS_ERROR_FAILURE;
michael@0 95
michael@0 96 }
michael@0 97
michael@0 98 //
michael@0 99 // returns false/true depending on if it was of the form LL-CC.Extra
michael@0 100 static bool
michael@0 101 ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator)
michael@0 102 {
michael@0 103 const char *src = locale_string;
michael@0 104 char modifier[MAX_EXTRA_LEN+1];
michael@0 105 char *dest;
michael@0 106 int dest_space, len;
michael@0 107
michael@0 108 *language = '\0';
michael@0 109 *country = '\0';
michael@0 110 *extra = '\0';
michael@0 111 if (strlen(locale_string) < 2) {
michael@0 112 return(false);
michael@0 113 }
michael@0 114
michael@0 115 //
michael@0 116 // parse the language part
michael@0 117 //
michael@0 118 dest = language;
michael@0 119 dest_space = MAX_LANGUAGE_CODE_LEN;
michael@0 120 while ((*src) && (isalpha(*src)) && (dest_space--)) {
michael@0 121 *dest++ = tolower(*src++);
michael@0 122 }
michael@0 123 *dest = '\0';
michael@0 124 len = dest - language;
michael@0 125 if ((len != 2) && (len != 3)) {
michael@0 126 NS_ASSERTION((len == 2) || (len == 3), "language code too short");
michael@0 127 NS_ASSERTION(len < 3, "reminder: verify we can handle 3+ character language code in all parts of the system; eg: language packs");
michael@0 128 *language = '\0';
michael@0 129 return(false);
michael@0 130 }
michael@0 131
michael@0 132 // check if all done
michael@0 133 if (*src == '\0') {
michael@0 134 return(true);
michael@0 135 }
michael@0 136
michael@0 137 if ((*src != '_') && (*src != '-') && (*src != '.') && (*src != '@')) {
michael@0 138 NS_ASSERTION(isalpha(*src), "language code too long");
michael@0 139 NS_ASSERTION(!isalpha(*src), "unexpected language/country separator");
michael@0 140 *language = '\0';
michael@0 141 return(false);
michael@0 142 }
michael@0 143
michael@0 144 //
michael@0 145 // parse the country part
michael@0 146 //
michael@0 147 if ((*src == '_') || (*src == '-')) {
michael@0 148 src++;
michael@0 149 dest = country;
michael@0 150 dest_space = MAX_COUNTRY_CODE_LEN;
michael@0 151 while ((*src) && (isalpha(*src)) && (dest_space--)) {
michael@0 152 *dest++ = toupper(*src++);
michael@0 153 }
michael@0 154 *dest = '\0';
michael@0 155 len = dest - country;
michael@0 156 if (len != 2) {
michael@0 157 NS_ASSERTION(len == 2, "unexpected country code length");
michael@0 158 *language = '\0';
michael@0 159 *country = '\0';
michael@0 160 return(false);
michael@0 161 }
michael@0 162 }
michael@0 163
michael@0 164 // check if all done
michael@0 165 if (*src == '\0') {
michael@0 166 return(true);
michael@0 167 }
michael@0 168
michael@0 169 if ((*src != '.') && (*src != '@')) {
michael@0 170 NS_ASSERTION(isalpha(*src), "country code too long");
michael@0 171 NS_ASSERTION(!isalpha(*src), "unexpected country/extra separator");
michael@0 172 *language = '\0';
michael@0 173 *country = '\0';
michael@0 174 return(false);
michael@0 175 }
michael@0 176
michael@0 177 //
michael@0 178 // handle the extra part
michael@0 179 //
michael@0 180 if (*src == '.') {
michael@0 181 src++; // move past the extra part separator
michael@0 182 dest = extra;
michael@0 183 dest_space = MAX_EXTRA_LEN;
michael@0 184 while ((*src) && (*src != '@') && (dest_space--)) {
michael@0 185 *dest++ = *src++;
michael@0 186 }
michael@0 187 *dest = '\0';
michael@0 188 len = dest - extra;
michael@0 189 if (len < 1) {
michael@0 190 NS_ASSERTION(len > 0, "found country/extra separator but no extra code");
michael@0 191 *language = '\0';
michael@0 192 *country = '\0';
michael@0 193 *extra = '\0';
michael@0 194 return(false);
michael@0 195 }
michael@0 196 }
michael@0 197
michael@0 198 // check if all done
michael@0 199 if (*src == '\0') {
michael@0 200 return(true);
michael@0 201 }
michael@0 202
michael@0 203 //
michael@0 204 // handle the modifier part
michael@0 205 //
michael@0 206
michael@0 207 if (*src == '@') {
michael@0 208 src++; // move past the modifier separator
michael@0 209 NS_ASSERTION(strcmp("euro",src) == 0, "found non euro modifier");
michael@0 210 dest = modifier;
michael@0 211 dest_space = MAX_EXTRA_LEN;
michael@0 212 while ((*src) && (dest_space--)) {
michael@0 213 *dest++ = *src++;
michael@0 214 }
michael@0 215 *dest = '\0';
michael@0 216 len = dest - modifier;
michael@0 217 if (len < 1) {
michael@0 218 NS_ASSERTION(len > 0, "found modifier separator but no modifier code");
michael@0 219 *language = '\0';
michael@0 220 *country = '\0';
michael@0 221 *extra = '\0';
michael@0 222 *modifier = '\0';
michael@0 223 return(false);
michael@0 224 }
michael@0 225 }
michael@0 226
michael@0 227 // check if all done
michael@0 228 if (*src == '\0') {
michael@0 229 return(true);
michael@0 230 }
michael@0 231
michael@0 232 NS_ASSERTION(*src == '\0', "extra/modifier code too long");
michael@0 233 *language = '\0';
michael@0 234 *country = '\0';
michael@0 235 *extra = '\0';
michael@0 236
michael@0 237 return(false);
michael@0 238 }
michael@0 239

mercurial