intl/locale/src/unix/nsCollationUnix.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial