intl/locale/src/mac/nsCollationMacUC.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     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 "nsCollationMacUC.h"
     7 #include "nsILocaleService.h"
     8 #include "nsIServiceManager.h"
     9 #include "prmem.h"
    10 #include "nsString.h"
    12 NS_IMPL_ISUPPORTS(nsCollationMacUC, nsICollation)
    14 nsCollationMacUC::nsCollationMacUC() 
    15   : mInit(false)
    16   , mHasCollator(false)
    17   , mLocale(nullptr)
    18   , mLastStrength(-1)
    19   , mCollator(nullptr)
    20   , mBuffer(nullptr)
    21   , mBufferLen(1)
    22 {
    23 }
    25 nsCollationMacUC::~nsCollationMacUC() 
    26 {
    27   if (mHasCollator) {
    28 #ifdef DEBUG
    29     OSStatus err =
    30 #endif
    31       ::UCDisposeCollator(&mCollator);
    32     mHasCollator = false;
    33     NS_ASSERTION((err == noErr), "UCDisposeCollator failed");
    34   }
    35   PR_FREEIF(mBuffer);
    36 }
    38 nsresult nsCollationMacUC::StrengthToOptions(const int32_t aStrength,
    39                                              UCCollateOptions* aOptions)
    40 {
    41   NS_ENSURE_ARG_POINTER(aOptions);
    42   NS_ENSURE_TRUE((aStrength < 4), NS_ERROR_FAILURE);
    43   // set our default collation options
    44   UCCollateOptions options = kUCCollateStandardOptions | kUCCollatePunctuationSignificantMask;
    45   if (aStrength & kCollationCaseInsensitiveAscii)
    46     options |= kUCCollateCaseInsensitiveMask;
    47   if (aStrength & kCollationAccentInsenstive)
    48     options |= kUCCollateDiacritInsensitiveMask;
    49   *aOptions = options;
    50   return NS_OK;
    51 }
    53 nsresult nsCollationMacUC::ConvertLocale(nsILocale* aNSLocale, LocaleRef* aMacLocale) 
    54 {
    55   NS_ENSURE_ARG_POINTER(aNSLocale);
    56   NS_ENSURE_ARG_POINTER(aMacLocale);
    58   nsAutoString localeString;
    59   nsresult res = aNSLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"), localeString);
    60   NS_ENSURE_TRUE(NS_SUCCEEDED(res) && !localeString.IsEmpty(),
    61                  NS_ERROR_FAILURE);
    62   NS_LossyConvertUTF16toASCII tmp(localeString);
    63   tmp.ReplaceChar('-', '_');
    64   OSStatus err;
    65   err = ::LocaleRefFromLocaleString(tmp.get(), aMacLocale);
    66   NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
    68   return NS_OK;
    69 }
    71 nsresult nsCollationMacUC::EnsureCollator(const int32_t newStrength) 
    72 {
    73   NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
    74   if (mHasCollator && (mLastStrength == newStrength))
    75     return NS_OK;
    77   OSStatus err;
    78   if (mHasCollator) {
    79     err = ::UCDisposeCollator(&mCollator);
    80     mHasCollator = false;
    81     NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
    82   }
    84   UCCollateOptions newOptions;
    85   nsresult res = StrengthToOptions(newStrength, &newOptions);
    86   NS_ENSURE_SUCCESS(res, res);
    88   LocaleOperationVariant opVariant = 0; // default variant for now
    89   err = ::UCCreateCollator(mLocale, opVariant, newOptions, &mCollator);
    90   NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
    91   mHasCollator = true;
    93   mLastStrength = newStrength;
    94   return NS_OK;
    95 }
    97 NS_IMETHODIMP nsCollationMacUC::Initialize(nsILocale* locale) 
    98 {
    99   NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED);
   100   nsCOMPtr<nsILocale> appLocale;
   102   nsresult rv;
   103   if (!locale) {
   104     nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
   105     NS_ENSURE_SUCCESS(rv, rv);
   106     rv = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
   107     NS_ENSURE_SUCCESS(rv, rv);
   108     locale = appLocale;
   109   }
   111   rv = ConvertLocale(locale, &mLocale);
   112   NS_ENSURE_SUCCESS(rv, rv);
   114   mInit = true;
   115   return NS_OK;
   116 }
   118 NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsAString& stringIn,
   119                                                    uint8_t** key, uint32_t* outLen)
   120 {
   121   NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
   122   NS_ENSURE_ARG_POINTER(key);
   123   NS_ENSURE_ARG_POINTER(outLen);
   125   nsresult res = EnsureCollator(strength);
   126   NS_ENSURE_SUCCESS(res, res);
   128   uint32_t stringInLen = stringIn.Length();
   129   uint32_t maxKeyLen = (1 + stringInLen) * kCollationValueSizeFactor * sizeof(UCCollationValue);
   130   if (maxKeyLen > mBufferLen) {
   131     uint32_t newBufferLen = mBufferLen;
   132     do {
   133       newBufferLen *= 2;
   134     } while (newBufferLen < maxKeyLen);
   135     void *newBuffer = PR_Malloc(newBufferLen);
   136     if (!newBuffer)
   137       return NS_ERROR_OUT_OF_MEMORY;
   139     PR_FREEIF(mBuffer);
   140     mBuffer = newBuffer;
   141     mBufferLen = newBufferLen;
   142   }
   144   ItemCount actual;
   145   OSStatus err = ::UCGetCollationKey(mCollator, (const UniChar*) PromiseFlatString(stringIn).get(),
   146                                      (UniCharCount) stringInLen,
   147                                      (ItemCount) (mBufferLen / sizeof(UCCollationValue)),
   148                                      &actual, (UCCollationValue *)mBuffer);
   149   NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
   151   uint32_t keyLength = actual * sizeof(UCCollationValue);
   152   void *newKey = PR_Malloc(keyLength);
   153   if (!newKey)
   154     return NS_ERROR_OUT_OF_MEMORY;
   156   memcpy(newKey, mBuffer, keyLength);
   157   *key = (uint8_t *)newKey;
   158   *outLen = keyLength;
   160   return NS_OK;
   161 }
   163 NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& string1,
   164                                               const nsAString& string2, int32_t* result) 
   165 {
   166   NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
   167   NS_ENSURE_ARG_POINTER(result);
   168   *result = 0;
   170   nsresult res = EnsureCollator(strength);
   171   NS_ENSURE_SUCCESS(res, res);
   172   *result = 0;
   174   OSStatus err;
   175   err = ::UCCompareText(mCollator, 
   176                         (const UniChar *) PromiseFlatString(string1).get(), (UniCharCount) string1.Length(),
   177                         (const UniChar *) PromiseFlatString(string2).get(), (UniCharCount) string2.Length(),
   178                         nullptr, (SInt32*) result);
   180   NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
   181   return NS_OK;
   182 }
   184 NS_IMETHODIMP nsCollationMacUC::CompareRawSortKey(const uint8_t* key1, uint32_t len1,
   185                                                   const uint8_t* key2, uint32_t len2,
   186                                                   int32_t* result)
   187 {
   188   NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
   189   NS_ENSURE_ARG_POINTER(key1);
   190   NS_ENSURE_ARG_POINTER(key2);
   191   NS_ENSURE_ARG_POINTER(result);
   192   *result = 0;
   194   OSStatus err;
   195   err = ::UCCompareCollationKeys((const UCCollationValue*) key1, (ItemCount) len1,
   196                                  (const UCCollationValue*) key2, (ItemCount) len2,
   197                                  nullptr, (SInt32*) result);
   199   NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
   201   return NS_OK;
   202 }

mercurial