summaryrefslogtreecommitdiffstats
path: root/intl/locale/nsCollation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/locale/nsCollation.cpp')
-rw-r--r--intl/locale/nsCollation.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/intl/locale/nsCollation.cpp b/intl/locale/nsCollation.cpp
new file mode 100644
index 000000000..f6fa54471
--- /dev/null
+++ b/intl/locale/nsCollation.cpp
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsCollation.h"
+#include "nsCollationCID.h"
+#include "nsUnicharUtils.h"
+#include "prmem.h"
+#include "nsIUnicodeEncoder.h"
+#include "nsServiceManagerUtils.h"
+#include "mozilla/dom/EncodingUtils.h"
+
+using mozilla::dom::EncodingUtils;
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_DEFINE_CID(kCollationCID, NS_COLLATION_CID);
+
+NS_IMPL_ISUPPORTS(nsCollationFactory, nsICollationFactory)
+
+nsresult nsCollationFactory::CreateCollation(nsILocale* locale, nsICollation** instancePtr)
+{
+ // Create a collation interface instance.
+ //
+ nsICollation *inst;
+ nsresult res;
+
+ res = CallCreateInstance(kCollationCID, &inst);
+ if (NS_FAILED(res)) {
+ return res;
+ }
+
+ inst->Initialize(locale);
+ *instancePtr = inst;
+
+ return res;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsCollation::nsCollation()
+{
+ MOZ_COUNT_CTOR(nsCollation);
+}
+
+nsCollation::~nsCollation()
+{
+ MOZ_COUNT_DTOR(nsCollation);
+}
+
+nsresult nsCollation::NormalizeString(const nsAString& stringIn, nsAString& stringOut)
+{
+ int32_t aLength = stringIn.Length();
+
+ if (aLength <= 64) {
+ char16_t conversionBuffer[64];
+ ToLowerCase(PromiseFlatString(stringIn).get(), conversionBuffer, aLength);
+ stringOut.Assign(conversionBuffer, aLength);
+ }
+ else {
+ char16_t* conversionBuffer;
+ conversionBuffer = new char16_t[aLength];
+ if (!conversionBuffer) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ ToLowerCase(PromiseFlatString(stringIn).get(), conversionBuffer, aLength);
+ stringOut.Assign(conversionBuffer, aLength);
+ delete [] conversionBuffer;
+ }
+ return NS_OK;
+}
+
+nsresult nsCollation::SetCharset(const char* aCharset)
+{
+ NS_ENSURE_ARG_POINTER(aCharset);
+
+ nsDependentCString label(aCharset);
+ nsAutoCString encoding;
+ if (!EncodingUtils::FindEncodingForLabelNoReplacement(label, encoding)) {
+ return NS_ERROR_UCONV_NOCONV;
+ }
+ mEncoder = EncodingUtils::EncoderForEncoding(encoding);
+ return NS_OK;
+}
+
+nsresult nsCollation::UnicodeToChar(const nsAString& aSrc, char** dst)
+{
+ NS_ENSURE_ARG_POINTER(dst);
+
+ nsresult res = NS_OK;
+ if (!mEncoder)
+ res = SetCharset("ISO-8859-1");
+
+ if (NS_SUCCEEDED(res)) {
+ const nsPromiseFlatString& src = PromiseFlatString(aSrc);
+ const char16_t *unichars = src.get();
+ int32_t unicharLength = src.Length();
+ int32_t dstLength;
+ res = mEncoder->GetMaxLength(unichars, unicharLength, &dstLength);
+ if (NS_SUCCEEDED(res)) {
+ int32_t bufLength = dstLength + 1 + 32; // extra 32 bytes for Finish() call
+ *dst = (char *) PR_Malloc(bufLength);
+ if (*dst) {
+ **dst = '\0';
+ res = mEncoder->Convert(unichars, &unicharLength, *dst, &dstLength);
+
+ if (NS_SUCCEEDED(res) || (NS_ERROR_UENC_NOMAPPING == res)) {
+ // Finishes the conversion. The converter has the possibility to write some
+ // extra data and flush its final state.
+ int32_t finishLength = bufLength - dstLength; // remaining unused buffer length
+ if (finishLength > 0) {
+ res = mEncoder->Finish((*dst + dstLength), &finishLength);
+ if (NS_SUCCEEDED(res)) {
+ (*dst)[dstLength + finishLength] = '\0';
+ }
+ }
+ }
+ if (NS_FAILED(res)) {
+ PR_Free(*dst);
+ *dst = nullptr;
+ }
+ }
+ else {
+ res = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ }
+
+ return res;
+}
+
+
+