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.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsCollationMacUC.h"
michael@0 7 #include "nsILocaleService.h"
michael@0 8 #include "nsIServiceManager.h"
michael@0 9 #include "prmem.h"
michael@0 10 #include "nsString.h"
michael@0 11
michael@0 12 NS_IMPL_ISUPPORTS(nsCollationMacUC, nsICollation)
michael@0 13
michael@0 14 nsCollationMacUC::nsCollationMacUC()
michael@0 15 : mInit(false)
michael@0 16 , mHasCollator(false)
michael@0 17 , mLocale(nullptr)
michael@0 18 , mLastStrength(-1)
michael@0 19 , mCollator(nullptr)
michael@0 20 , mBuffer(nullptr)
michael@0 21 , mBufferLen(1)
michael@0 22 {
michael@0 23 }
michael@0 24
michael@0 25 nsCollationMacUC::~nsCollationMacUC()
michael@0 26 {
michael@0 27 if (mHasCollator) {
michael@0 28 #ifdef DEBUG
michael@0 29 OSStatus err =
michael@0 30 #endif
michael@0 31 ::UCDisposeCollator(&mCollator);
michael@0 32 mHasCollator = false;
michael@0 33 NS_ASSERTION((err == noErr), "UCDisposeCollator failed");
michael@0 34 }
michael@0 35 PR_FREEIF(mBuffer);
michael@0 36 }
michael@0 37
michael@0 38 nsresult nsCollationMacUC::StrengthToOptions(const int32_t aStrength,
michael@0 39 UCCollateOptions* aOptions)
michael@0 40 {
michael@0 41 NS_ENSURE_ARG_POINTER(aOptions);
michael@0 42 NS_ENSURE_TRUE((aStrength < 4), NS_ERROR_FAILURE);
michael@0 43 // set our default collation options
michael@0 44 UCCollateOptions options = kUCCollateStandardOptions | kUCCollatePunctuationSignificantMask;
michael@0 45 if (aStrength & kCollationCaseInsensitiveAscii)
michael@0 46 options |= kUCCollateCaseInsensitiveMask;
michael@0 47 if (aStrength & kCollationAccentInsenstive)
michael@0 48 options |= kUCCollateDiacritInsensitiveMask;
michael@0 49 *aOptions = options;
michael@0 50 return NS_OK;
michael@0 51 }
michael@0 52
michael@0 53 nsresult nsCollationMacUC::ConvertLocale(nsILocale* aNSLocale, LocaleRef* aMacLocale)
michael@0 54 {
michael@0 55 NS_ENSURE_ARG_POINTER(aNSLocale);
michael@0 56 NS_ENSURE_ARG_POINTER(aMacLocale);
michael@0 57
michael@0 58 nsAutoString localeString;
michael@0 59 nsresult res = aNSLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"), localeString);
michael@0 60 NS_ENSURE_TRUE(NS_SUCCEEDED(res) && !localeString.IsEmpty(),
michael@0 61 NS_ERROR_FAILURE);
michael@0 62 NS_LossyConvertUTF16toASCII tmp(localeString);
michael@0 63 tmp.ReplaceChar('-', '_');
michael@0 64 OSStatus err;
michael@0 65 err = ::LocaleRefFromLocaleString(tmp.get(), aMacLocale);
michael@0 66 NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
michael@0 67
michael@0 68 return NS_OK;
michael@0 69 }
michael@0 70
michael@0 71 nsresult nsCollationMacUC::EnsureCollator(const int32_t newStrength)
michael@0 72 {
michael@0 73 NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
michael@0 74 if (mHasCollator && (mLastStrength == newStrength))
michael@0 75 return NS_OK;
michael@0 76
michael@0 77 OSStatus err;
michael@0 78 if (mHasCollator) {
michael@0 79 err = ::UCDisposeCollator(&mCollator);
michael@0 80 mHasCollator = false;
michael@0 81 NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
michael@0 82 }
michael@0 83
michael@0 84 UCCollateOptions newOptions;
michael@0 85 nsresult res = StrengthToOptions(newStrength, &newOptions);
michael@0 86 NS_ENSURE_SUCCESS(res, res);
michael@0 87
michael@0 88 LocaleOperationVariant opVariant = 0; // default variant for now
michael@0 89 err = ::UCCreateCollator(mLocale, opVariant, newOptions, &mCollator);
michael@0 90 NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
michael@0 91 mHasCollator = true;
michael@0 92
michael@0 93 mLastStrength = newStrength;
michael@0 94 return NS_OK;
michael@0 95 }
michael@0 96
michael@0 97 NS_IMETHODIMP nsCollationMacUC::Initialize(nsILocale* locale)
michael@0 98 {
michael@0 99 NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED);
michael@0 100 nsCOMPtr<nsILocale> appLocale;
michael@0 101
michael@0 102 nsresult rv;
michael@0 103 if (!locale) {
michael@0 104 nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
michael@0 105 NS_ENSURE_SUCCESS(rv, rv);
michael@0 106 rv = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
michael@0 107 NS_ENSURE_SUCCESS(rv, rv);
michael@0 108 locale = appLocale;
michael@0 109 }
michael@0 110
michael@0 111 rv = ConvertLocale(locale, &mLocale);
michael@0 112 NS_ENSURE_SUCCESS(rv, rv);
michael@0 113
michael@0 114 mInit = true;
michael@0 115 return NS_OK;
michael@0 116 }
michael@0 117
michael@0 118 NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsAString& stringIn,
michael@0 119 uint8_t** key, uint32_t* outLen)
michael@0 120 {
michael@0 121 NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
michael@0 122 NS_ENSURE_ARG_POINTER(key);
michael@0 123 NS_ENSURE_ARG_POINTER(outLen);
michael@0 124
michael@0 125 nsresult res = EnsureCollator(strength);
michael@0 126 NS_ENSURE_SUCCESS(res, res);
michael@0 127
michael@0 128 uint32_t stringInLen = stringIn.Length();
michael@0 129 uint32_t maxKeyLen = (1 + stringInLen) * kCollationValueSizeFactor * sizeof(UCCollationValue);
michael@0 130 if (maxKeyLen > mBufferLen) {
michael@0 131 uint32_t newBufferLen = mBufferLen;
michael@0 132 do {
michael@0 133 newBufferLen *= 2;
michael@0 134 } while (newBufferLen < maxKeyLen);
michael@0 135 void *newBuffer = PR_Malloc(newBufferLen);
michael@0 136 if (!newBuffer)
michael@0 137 return NS_ERROR_OUT_OF_MEMORY;
michael@0 138
michael@0 139 PR_FREEIF(mBuffer);
michael@0 140 mBuffer = newBuffer;
michael@0 141 mBufferLen = newBufferLen;
michael@0 142 }
michael@0 143
michael@0 144 ItemCount actual;
michael@0 145 OSStatus err = ::UCGetCollationKey(mCollator, (const UniChar*) PromiseFlatString(stringIn).get(),
michael@0 146 (UniCharCount) stringInLen,
michael@0 147 (ItemCount) (mBufferLen / sizeof(UCCollationValue)),
michael@0 148 &actual, (UCCollationValue *)mBuffer);
michael@0 149 NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
michael@0 150
michael@0 151 uint32_t keyLength = actual * sizeof(UCCollationValue);
michael@0 152 void *newKey = PR_Malloc(keyLength);
michael@0 153 if (!newKey)
michael@0 154 return NS_ERROR_OUT_OF_MEMORY;
michael@0 155
michael@0 156 memcpy(newKey, mBuffer, keyLength);
michael@0 157 *key = (uint8_t *)newKey;
michael@0 158 *outLen = keyLength;
michael@0 159
michael@0 160 return NS_OK;
michael@0 161 }
michael@0 162
michael@0 163 NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& string1,
michael@0 164 const nsAString& string2, int32_t* result)
michael@0 165 {
michael@0 166 NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
michael@0 167 NS_ENSURE_ARG_POINTER(result);
michael@0 168 *result = 0;
michael@0 169
michael@0 170 nsresult res = EnsureCollator(strength);
michael@0 171 NS_ENSURE_SUCCESS(res, res);
michael@0 172 *result = 0;
michael@0 173
michael@0 174 OSStatus err;
michael@0 175 err = ::UCCompareText(mCollator,
michael@0 176 (const UniChar *) PromiseFlatString(string1).get(), (UniCharCount) string1.Length(),
michael@0 177 (const UniChar *) PromiseFlatString(string2).get(), (UniCharCount) string2.Length(),
michael@0 178 nullptr, (SInt32*) result);
michael@0 179
michael@0 180 NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
michael@0 181 return NS_OK;
michael@0 182 }
michael@0 183
michael@0 184 NS_IMETHODIMP nsCollationMacUC::CompareRawSortKey(const uint8_t* key1, uint32_t len1,
michael@0 185 const uint8_t* key2, uint32_t len2,
michael@0 186 int32_t* result)
michael@0 187 {
michael@0 188 NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
michael@0 189 NS_ENSURE_ARG_POINTER(key1);
michael@0 190 NS_ENSURE_ARG_POINTER(key2);
michael@0 191 NS_ENSURE_ARG_POINTER(result);
michael@0 192 *result = 0;
michael@0 193
michael@0 194 OSStatus err;
michael@0 195 err = ::UCCompareCollationKeys((const UCCollationValue*) key1, (ItemCount) len1,
michael@0 196 (const UCCollationValue*) key2, (ItemCount) len2,
michael@0 197 nullptr, (SInt32*) result);
michael@0 198
michael@0 199 NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
michael@0 200
michael@0 201 return NS_OK;
michael@0 202 }

mercurial