1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/locale/src/unix/nsPosixLocale.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,239 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nscore.h" 1.10 +#include "nsString.h" 1.11 +#include "nsPosixLocale.h" 1.12 +#include "prprf.h" 1.13 +#include "plstr.h" 1.14 +#include "nsReadableUtils.h" 1.15 + 1.16 +static bool 1.17 +ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator); 1.18 + 1.19 +nsresult 1.20 +nsPosixLocale::GetPlatformLocale(const nsAString& locale, nsACString& posixLocale) 1.21 +{ 1.22 + char country_code[MAX_COUNTRY_CODE_LEN+1]; 1.23 + char lang_code[MAX_LANGUAGE_CODE_LEN+1]; 1.24 + char extra[MAX_EXTRA_LEN+1]; 1.25 + char posix_locale[MAX_LOCALE_LEN+1]; 1.26 + NS_LossyConvertUTF16toASCII xp_locale(locale); 1.27 + 1.28 + if (!xp_locale.IsEmpty()) { 1.29 + if (!ParseLocaleString(xp_locale.get(),lang_code,country_code,extra,'-')) { 1.30 +// strncpy(posixLocale,"C",length); 1.31 + posixLocale = xp_locale; // use xp locale if parse failed 1.32 + return NS_OK; 1.33 + } 1.34 + 1.35 + if (*country_code) { 1.36 + if (*extra) { 1.37 + PR_snprintf(posix_locale,sizeof(posix_locale),"%s_%s.%s",lang_code,country_code,extra); 1.38 + } 1.39 + else { 1.40 + PR_snprintf(posix_locale,sizeof(posix_locale),"%s_%s",lang_code,country_code); 1.41 + } 1.42 + } 1.43 + else { 1.44 + if (*extra) { 1.45 + PR_snprintf(posix_locale,sizeof(posix_locale),"%s.%s",lang_code,extra); 1.46 + } 1.47 + else { 1.48 + PR_snprintf(posix_locale,sizeof(posix_locale),"%s",lang_code); 1.49 + } 1.50 + } 1.51 + 1.52 + posixLocale = posix_locale; 1.53 + return NS_OK; 1.54 + } 1.55 + 1.56 + return NS_ERROR_FAILURE; 1.57 +} 1.58 + 1.59 +nsresult 1.60 +nsPosixLocale::GetXPLocale(const char* posixLocale, nsAString& locale) 1.61 +{ 1.62 + char country_code[MAX_COUNTRY_CODE_LEN+1]; 1.63 + char lang_code[MAX_LANGUAGE_CODE_LEN+1]; 1.64 + char extra[MAX_EXTRA_LEN+1]; 1.65 + char posix_locale[MAX_LOCALE_LEN+1]; 1.66 + 1.67 + if (posixLocale!=nullptr) { 1.68 + if (strcmp(posixLocale,"C")==0 || strcmp(posixLocale,"POSIX")==0) { 1.69 + locale.AssignLiteral("en-US"); 1.70 + return NS_OK; 1.71 + } 1.72 + if (!ParseLocaleString(posixLocale,lang_code,country_code,extra,'_')) { 1.73 +// * locale = "x-user-defined"; 1.74 + // use posix if parse failed 1.75 + CopyASCIItoUTF16(nsDependentCString(posixLocale), locale); 1.76 + return NS_OK; 1.77 + } 1.78 + 1.79 + // Special case: substitute "nb" (Norwegian Bokmal) for macrolanguage 1.80 + // code "no" (Norwegian) 1.81 + if (nsDependentCString(lang_code).LowerCaseEqualsLiteral("no")) { 1.82 + lang_code[1] = 'b'; 1.83 + } 1.84 + 1.85 + if (*country_code) { 1.86 + PR_snprintf(posix_locale,sizeof(posix_locale),"%s-%s",lang_code,country_code); 1.87 + } 1.88 + else { 1.89 + PR_snprintf(posix_locale,sizeof(posix_locale),"%s",lang_code); 1.90 + } 1.91 + 1.92 + CopyASCIItoUTF16(nsDependentCString(posix_locale), locale); 1.93 + return NS_OK; 1.94 + 1.95 + } 1.96 + 1.97 + return NS_ERROR_FAILURE; 1.98 + 1.99 +} 1.100 + 1.101 +// 1.102 +// returns false/true depending on if it was of the form LL-CC.Extra 1.103 +static bool 1.104 +ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator) 1.105 +{ 1.106 + const char *src = locale_string; 1.107 + char modifier[MAX_EXTRA_LEN+1]; 1.108 + char *dest; 1.109 + int dest_space, len; 1.110 + 1.111 + *language = '\0'; 1.112 + *country = '\0'; 1.113 + *extra = '\0'; 1.114 + if (strlen(locale_string) < 2) { 1.115 + return(false); 1.116 + } 1.117 + 1.118 + // 1.119 + // parse the language part 1.120 + // 1.121 + dest = language; 1.122 + dest_space = MAX_LANGUAGE_CODE_LEN; 1.123 + while ((*src) && (isalpha(*src)) && (dest_space--)) { 1.124 + *dest++ = tolower(*src++); 1.125 + } 1.126 + *dest = '\0'; 1.127 + len = dest - language; 1.128 + if ((len != 2) && (len != 3)) { 1.129 + NS_ASSERTION((len == 2) || (len == 3), "language code too short"); 1.130 + NS_ASSERTION(len < 3, "reminder: verify we can handle 3+ character language code in all parts of the system; eg: language packs"); 1.131 + *language = '\0'; 1.132 + return(false); 1.133 + } 1.134 + 1.135 + // check if all done 1.136 + if (*src == '\0') { 1.137 + return(true); 1.138 + } 1.139 + 1.140 + if ((*src != '_') && (*src != '-') && (*src != '.') && (*src != '@')) { 1.141 + NS_ASSERTION(isalpha(*src), "language code too long"); 1.142 + NS_ASSERTION(!isalpha(*src), "unexpected language/country separator"); 1.143 + *language = '\0'; 1.144 + return(false); 1.145 + } 1.146 + 1.147 + // 1.148 + // parse the country part 1.149 + // 1.150 + if ((*src == '_') || (*src == '-')) { 1.151 + src++; 1.152 + dest = country; 1.153 + dest_space = MAX_COUNTRY_CODE_LEN; 1.154 + while ((*src) && (isalpha(*src)) && (dest_space--)) { 1.155 + *dest++ = toupper(*src++); 1.156 + } 1.157 + *dest = '\0'; 1.158 + len = dest - country; 1.159 + if (len != 2) { 1.160 + NS_ASSERTION(len == 2, "unexpected country code length"); 1.161 + *language = '\0'; 1.162 + *country = '\0'; 1.163 + return(false); 1.164 + } 1.165 + } 1.166 + 1.167 + // check if all done 1.168 + if (*src == '\0') { 1.169 + return(true); 1.170 + } 1.171 + 1.172 + if ((*src != '.') && (*src != '@')) { 1.173 + NS_ASSERTION(isalpha(*src), "country code too long"); 1.174 + NS_ASSERTION(!isalpha(*src), "unexpected country/extra separator"); 1.175 + *language = '\0'; 1.176 + *country = '\0'; 1.177 + return(false); 1.178 + } 1.179 + 1.180 + // 1.181 + // handle the extra part 1.182 + // 1.183 + if (*src == '.') { 1.184 + src++; // move past the extra part separator 1.185 + dest = extra; 1.186 + dest_space = MAX_EXTRA_LEN; 1.187 + while ((*src) && (*src != '@') && (dest_space--)) { 1.188 + *dest++ = *src++; 1.189 + } 1.190 + *dest = '\0'; 1.191 + len = dest - extra; 1.192 + if (len < 1) { 1.193 + NS_ASSERTION(len > 0, "found country/extra separator but no extra code"); 1.194 + *language = '\0'; 1.195 + *country = '\0'; 1.196 + *extra = '\0'; 1.197 + return(false); 1.198 + } 1.199 + } 1.200 + 1.201 + // check if all done 1.202 + if (*src == '\0') { 1.203 + return(true); 1.204 + } 1.205 + 1.206 + // 1.207 + // handle the modifier part 1.208 + // 1.209 + 1.210 + if (*src == '@') { 1.211 + src++; // move past the modifier separator 1.212 + NS_ASSERTION(strcmp("euro",src) == 0, "found non euro modifier"); 1.213 + dest = modifier; 1.214 + dest_space = MAX_EXTRA_LEN; 1.215 + while ((*src) && (dest_space--)) { 1.216 + *dest++ = *src++; 1.217 + } 1.218 + *dest = '\0'; 1.219 + len = dest - modifier; 1.220 + if (len < 1) { 1.221 + NS_ASSERTION(len > 0, "found modifier separator but no modifier code"); 1.222 + *language = '\0'; 1.223 + *country = '\0'; 1.224 + *extra = '\0'; 1.225 + *modifier = '\0'; 1.226 + return(false); 1.227 + } 1.228 + } 1.229 + 1.230 + // check if all done 1.231 + if (*src == '\0') { 1.232 + return(true); 1.233 + } 1.234 + 1.235 + NS_ASSERTION(*src == '\0', "extra/modifier code too long"); 1.236 + *language = '\0'; 1.237 + *country = '\0'; 1.238 + *extra = '\0'; 1.239 + 1.240 + return(false); 1.241 +} 1.242 +