intl/locale/src/unix/nsCollationUnix.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.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include  <locale.h>
     7 #include "prmem.h"
     8 #include "nsCollationUnix.h"
     9 #include "nsIServiceManager.h"
    10 #include "nsIComponentManager.h"
    11 #include "nsILocaleService.h"
    12 #include "nsIPlatformCharset.h"
    13 #include "nsPosixLocale.h"
    14 #include "nsCOMPtr.h"
    15 #include "nsUnicharUtils.h"
    16 #include "nsCRT.h"
    17 //#define DEBUG_UNIX_COLLATION
    19 inline void nsCollationUnix::DoSetLocale()
    20 {
    21   char *locale = setlocale(LC_COLLATE, nullptr);
    22   mSavedLocale.Assign(locale ? locale : "");
    23   if (!mSavedLocale.EqualsIgnoreCase(mLocale.get())) {
    24     (void) setlocale(LC_COLLATE, PromiseFlatCString(Substring(mLocale,0,MAX_LOCALE_LEN)).get());
    25   }
    26 }
    28 inline void nsCollationUnix::DoRestoreLocale()
    29 {
    30   if (!mSavedLocale.EqualsIgnoreCase(mLocale.get())) { 
    31     (void) setlocale(LC_COLLATE, PromiseFlatCString(Substring(mSavedLocale,0,MAX_LOCALE_LEN)).get());
    32   }
    33 }
    35 nsCollationUnix::nsCollationUnix() : mCollation(nullptr)
    36 {
    37 }
    39 nsCollationUnix::~nsCollationUnix() 
    40 {
    41   if (mCollation)
    42     delete mCollation;
    43 }
    45 NS_IMPL_ISUPPORTS(nsCollationUnix, nsICollation)
    47 nsresult nsCollationUnix::Initialize(nsILocale* locale) 
    48 {
    49 #define kPlatformLocaleLength 64
    50   NS_ASSERTION(!mCollation, "Should only be initialized once");
    52   nsresult res;
    54   mCollation = new nsCollation;
    56   // default platform locale
    57   mLocale.Assign('C');
    59   nsAutoString localeStr;
    60   NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_COLLATE##PLATFORM");
    62   // get locale string, use app default if no locale specified
    63   if (locale == nullptr) {
    64     nsCOMPtr<nsILocaleService> localeService = 
    65              do_GetService(NS_LOCALESERVICE_CONTRACTID, &res);
    66     if (NS_SUCCEEDED(res)) {
    67       nsCOMPtr<nsILocale> appLocale;
    68       res = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
    69       if (NS_SUCCEEDED(res)) {
    70         res = appLocale->GetCategory(aCategory, localeStr);
    71         NS_ASSERTION(NS_SUCCEEDED(res), "failed to get app locale info");
    72       }
    73     }
    74   }
    75   else {
    76     res = locale->GetCategory(aCategory, localeStr);
    77     NS_ASSERTION(NS_SUCCEEDED(res), "failed to get locale info");
    78   }
    80   // Get platform locale and charset name from locale, if available
    81   if (NS_SUCCEEDED(res)) {
    82     // keep the same behavior as 4.x as well as avoiding Linux collation key problem
    83     if (localeStr.LowerCaseEqualsLiteral("en_us")) { // note: locale is in platform format
    84       localeStr.AssignLiteral("C");
    85     }
    87     nsPosixLocale::GetPlatformLocale(localeStr, mLocale);
    89     nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &res);
    90     if (NS_SUCCEEDED(res)) {
    91       nsAutoCString mappedCharset;
    92       res = platformCharset->GetDefaultCharsetForLocale(localeStr, mappedCharset);
    93       if (NS_SUCCEEDED(res)) {
    94         mCollation->SetCharset(mappedCharset.get());
    95       }
    96     }
    97   }
    99   return NS_OK;
   100 }
   103 nsresult nsCollationUnix::CompareString(int32_t strength,
   104                                         const nsAString& string1,
   105                                         const nsAString& string2,
   106                                         int32_t* result) 
   107 {
   108   nsresult res = NS_OK;
   110   nsAutoString stringNormalized1, stringNormalized2;
   111   if (strength != kCollationCaseSensitive) {
   112     res = mCollation->NormalizeString(string1, stringNormalized1);
   113     if (NS_FAILED(res)) {
   114       return res;
   115     }
   116     res = mCollation->NormalizeString(string2, stringNormalized2);
   117     if (NS_FAILED(res)) {
   118       return res;
   119     }
   120   } else {
   121     stringNormalized1 = string1;
   122     stringNormalized2 = string2;
   123   }
   125   // convert unicode to charset
   126   char *str1, *str2;
   128   res = mCollation->UnicodeToChar(stringNormalized1, &str1);
   129   if (NS_SUCCEEDED(res) && str1) {
   130     res = mCollation->UnicodeToChar(stringNormalized2, &str2);
   131     if (NS_SUCCEEDED(res) && str2) {
   132       DoSetLocale();
   133       *result = strcoll(str1, str2);
   134       DoRestoreLocale();
   135       PR_Free(str2);
   136     }
   137     PR_Free(str1);
   138   }
   140   return res;
   141 }
   144 nsresult nsCollationUnix::AllocateRawSortKey(int32_t strength, 
   145                                              const nsAString& stringIn,
   146                                              uint8_t** key, uint32_t* outLen)
   147 {
   148   nsresult res = NS_OK;
   150   nsAutoString stringNormalized;
   151   if (strength != kCollationCaseSensitive) {
   152     res = mCollation->NormalizeString(stringIn, stringNormalized);
   153     if (NS_FAILED(res))
   154       return res;
   155   } else {
   156     stringNormalized = stringIn;
   157   }
   158   // convert unicode to charset
   159   char *str;
   161   res = mCollation->UnicodeToChar(stringNormalized, &str);
   162   if (NS_SUCCEEDED(res) && str) {
   163     DoSetLocale();
   164     // call strxfrm to generate a key 
   165     size_t len = strxfrm(nullptr, str, 0) + 1;
   166     void *buffer = PR_Malloc(len);
   167     if (!buffer) {
   168       res = NS_ERROR_OUT_OF_MEMORY;
   169     } else if (strxfrm((char *)buffer, str, len) >= len) {
   170       PR_Free(buffer);
   171       res = NS_ERROR_FAILURE;
   172     } else {
   173       *key = (uint8_t *)buffer;
   174       *outLen = len;
   175     }
   176     DoRestoreLocale();
   177     PR_Free(str);
   178   }
   180   return res;
   181 }
   183 nsresult nsCollationUnix::CompareRawSortKey(const uint8_t* key1, uint32_t len1, 
   184                                             const uint8_t* key2, uint32_t len2, 
   185                                             int32_t* result)
   186 {
   187   *result = PL_strcmp((const char *)key1, (const char *)key2);
   188   return NS_OK;
   189 }

mercurial