intl/locale/src/mac/nsCollationMacUC.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/locale/src/mac/nsCollationMacUC.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,202 @@
     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 "nsCollationMacUC.h"
    1.10 +#include "nsILocaleService.h"
    1.11 +#include "nsIServiceManager.h"
    1.12 +#include "prmem.h"
    1.13 +#include "nsString.h"
    1.14 +
    1.15 +NS_IMPL_ISUPPORTS(nsCollationMacUC, nsICollation)
    1.16 +
    1.17 +nsCollationMacUC::nsCollationMacUC() 
    1.18 +  : mInit(false)
    1.19 +  , mHasCollator(false)
    1.20 +  , mLocale(nullptr)
    1.21 +  , mLastStrength(-1)
    1.22 +  , mCollator(nullptr)
    1.23 +  , mBuffer(nullptr)
    1.24 +  , mBufferLen(1)
    1.25 +{
    1.26 +}
    1.27 +
    1.28 +nsCollationMacUC::~nsCollationMacUC() 
    1.29 +{
    1.30 +  if (mHasCollator) {
    1.31 +#ifdef DEBUG
    1.32 +    OSStatus err =
    1.33 +#endif
    1.34 +      ::UCDisposeCollator(&mCollator);
    1.35 +    mHasCollator = false;
    1.36 +    NS_ASSERTION((err == noErr), "UCDisposeCollator failed");
    1.37 +  }
    1.38 +  PR_FREEIF(mBuffer);
    1.39 +}
    1.40 +
    1.41 +nsresult nsCollationMacUC::StrengthToOptions(const int32_t aStrength,
    1.42 +                                             UCCollateOptions* aOptions)
    1.43 +{
    1.44 +  NS_ENSURE_ARG_POINTER(aOptions);
    1.45 +  NS_ENSURE_TRUE((aStrength < 4), NS_ERROR_FAILURE);
    1.46 +  // set our default collation options
    1.47 +  UCCollateOptions options = kUCCollateStandardOptions | kUCCollatePunctuationSignificantMask;
    1.48 +  if (aStrength & kCollationCaseInsensitiveAscii)
    1.49 +    options |= kUCCollateCaseInsensitiveMask;
    1.50 +  if (aStrength & kCollationAccentInsenstive)
    1.51 +    options |= kUCCollateDiacritInsensitiveMask;
    1.52 +  *aOptions = options;
    1.53 +  return NS_OK;
    1.54 +}
    1.55 +
    1.56 +nsresult nsCollationMacUC::ConvertLocale(nsILocale* aNSLocale, LocaleRef* aMacLocale) 
    1.57 +{
    1.58 +  NS_ENSURE_ARG_POINTER(aNSLocale);
    1.59 +  NS_ENSURE_ARG_POINTER(aMacLocale);
    1.60 +
    1.61 +  nsAutoString localeString;
    1.62 +  nsresult res = aNSLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"), localeString);
    1.63 +  NS_ENSURE_TRUE(NS_SUCCEEDED(res) && !localeString.IsEmpty(),
    1.64 +                 NS_ERROR_FAILURE);
    1.65 +  NS_LossyConvertUTF16toASCII tmp(localeString);
    1.66 +  tmp.ReplaceChar('-', '_');
    1.67 +  OSStatus err;
    1.68 +  err = ::LocaleRefFromLocaleString(tmp.get(), aMacLocale);
    1.69 +  NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
    1.70 +
    1.71 +  return NS_OK;
    1.72 +}
    1.73 +
    1.74 +nsresult nsCollationMacUC::EnsureCollator(const int32_t newStrength) 
    1.75 +{
    1.76 +  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
    1.77 +  if (mHasCollator && (mLastStrength == newStrength))
    1.78 +    return NS_OK;
    1.79 +
    1.80 +  OSStatus err;
    1.81 +  if (mHasCollator) {
    1.82 +    err = ::UCDisposeCollator(&mCollator);
    1.83 +    mHasCollator = false;
    1.84 +    NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
    1.85 +  }
    1.86 +
    1.87 +  UCCollateOptions newOptions;
    1.88 +  nsresult res = StrengthToOptions(newStrength, &newOptions);
    1.89 +  NS_ENSURE_SUCCESS(res, res);
    1.90 +  
    1.91 +  LocaleOperationVariant opVariant = 0; // default variant for now
    1.92 +  err = ::UCCreateCollator(mLocale, opVariant, newOptions, &mCollator);
    1.93 +  NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
    1.94 +  mHasCollator = true;
    1.95 +
    1.96 +  mLastStrength = newStrength;
    1.97 +  return NS_OK;
    1.98 +}
    1.99 +
   1.100 +NS_IMETHODIMP nsCollationMacUC::Initialize(nsILocale* locale) 
   1.101 +{
   1.102 +  NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED);
   1.103 +  nsCOMPtr<nsILocale> appLocale;
   1.104 +
   1.105 +  nsresult rv;
   1.106 +  if (!locale) {
   1.107 +    nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
   1.108 +    NS_ENSURE_SUCCESS(rv, rv);
   1.109 +    rv = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
   1.110 +    NS_ENSURE_SUCCESS(rv, rv);
   1.111 +    locale = appLocale;
   1.112 +  }
   1.113 +
   1.114 +  rv = ConvertLocale(locale, &mLocale);
   1.115 +  NS_ENSURE_SUCCESS(rv, rv);
   1.116 +
   1.117 +  mInit = true;
   1.118 +  return NS_OK;
   1.119 +}
   1.120 +
   1.121 +NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsAString& stringIn,
   1.122 +                                                   uint8_t** key, uint32_t* outLen)
   1.123 +{
   1.124 +  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
   1.125 +  NS_ENSURE_ARG_POINTER(key);
   1.126 +  NS_ENSURE_ARG_POINTER(outLen);
   1.127 +
   1.128 +  nsresult res = EnsureCollator(strength);
   1.129 +  NS_ENSURE_SUCCESS(res, res);
   1.130 +
   1.131 +  uint32_t stringInLen = stringIn.Length();
   1.132 +  uint32_t maxKeyLen = (1 + stringInLen) * kCollationValueSizeFactor * sizeof(UCCollationValue);
   1.133 +  if (maxKeyLen > mBufferLen) {
   1.134 +    uint32_t newBufferLen = mBufferLen;
   1.135 +    do {
   1.136 +      newBufferLen *= 2;
   1.137 +    } while (newBufferLen < maxKeyLen);
   1.138 +    void *newBuffer = PR_Malloc(newBufferLen);
   1.139 +    if (!newBuffer)
   1.140 +      return NS_ERROR_OUT_OF_MEMORY;
   1.141 +
   1.142 +    PR_FREEIF(mBuffer);
   1.143 +    mBuffer = newBuffer;
   1.144 +    mBufferLen = newBufferLen;
   1.145 +  }
   1.146 +
   1.147 +  ItemCount actual;
   1.148 +  OSStatus err = ::UCGetCollationKey(mCollator, (const UniChar*) PromiseFlatString(stringIn).get(),
   1.149 +                                     (UniCharCount) stringInLen,
   1.150 +                                     (ItemCount) (mBufferLen / sizeof(UCCollationValue)),
   1.151 +                                     &actual, (UCCollationValue *)mBuffer);
   1.152 +  NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
   1.153 +
   1.154 +  uint32_t keyLength = actual * sizeof(UCCollationValue);
   1.155 +  void *newKey = PR_Malloc(keyLength);
   1.156 +  if (!newKey)
   1.157 +    return NS_ERROR_OUT_OF_MEMORY;
   1.158 +
   1.159 +  memcpy(newKey, mBuffer, keyLength);
   1.160 +  *key = (uint8_t *)newKey;
   1.161 +  *outLen = keyLength;
   1.162 +
   1.163 +  return NS_OK;
   1.164 +}
   1.165 +
   1.166 +NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& string1,
   1.167 +                                              const nsAString& string2, int32_t* result) 
   1.168 +{
   1.169 +  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
   1.170 +  NS_ENSURE_ARG_POINTER(result);
   1.171 +  *result = 0;
   1.172 +
   1.173 +  nsresult res = EnsureCollator(strength);
   1.174 +  NS_ENSURE_SUCCESS(res, res);
   1.175 +  *result = 0;
   1.176 +
   1.177 +  OSStatus err;
   1.178 +  err = ::UCCompareText(mCollator, 
   1.179 +                        (const UniChar *) PromiseFlatString(string1).get(), (UniCharCount) string1.Length(),
   1.180 +                        (const UniChar *) PromiseFlatString(string2).get(), (UniCharCount) string2.Length(),
   1.181 +                        nullptr, (SInt32*) result);
   1.182 +
   1.183 +  NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
   1.184 +  return NS_OK;
   1.185 +}
   1.186 +
   1.187 +NS_IMETHODIMP nsCollationMacUC::CompareRawSortKey(const uint8_t* key1, uint32_t len1,
   1.188 +                                                  const uint8_t* key2, uint32_t len2,
   1.189 +                                                  int32_t* result)
   1.190 +{
   1.191 +  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
   1.192 +  NS_ENSURE_ARG_POINTER(key1);
   1.193 +  NS_ENSURE_ARG_POINTER(key2);
   1.194 +  NS_ENSURE_ARG_POINTER(result);
   1.195 +  *result = 0;
   1.196 +
   1.197 +  OSStatus err;
   1.198 +  err = ::UCCompareCollationKeys((const UCCollationValue*) key1, (ItemCount) len1,
   1.199 +                                 (const UCCollationValue*) key2, (ItemCount) len2,
   1.200 +                                 nullptr, (SInt32*) result);
   1.201 +
   1.202 +  NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
   1.203 +
   1.204 +  return NS_OK;
   1.205 +}

mercurial