intl/locale/src/unix/nsPosixLocale.cpp

changeset 0
6474c204b198
     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 +

mercurial