|
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/. */ |
|
5 |
|
6 #include "nsCollation.h" |
|
7 #include "nsCollationCID.h" |
|
8 #include "nsUnicharUtils.h" |
|
9 #include "prmem.h" |
|
10 #include "nsIUnicodeEncoder.h" |
|
11 #include "nsICharsetConverterManager.h" |
|
12 #include "nsServiceManagerUtils.h" |
|
13 |
|
14 //////////////////////////////////////////////////////////////////////////////// |
|
15 |
|
16 NS_DEFINE_CID(kCollationCID, NS_COLLATION_CID); |
|
17 |
|
18 NS_IMPL_ISUPPORTS(nsCollationFactory, nsICollationFactory) |
|
19 |
|
20 nsresult nsCollationFactory::CreateCollation(nsILocale* locale, nsICollation** instancePtr) |
|
21 { |
|
22 // Create a collation interface instance. |
|
23 // |
|
24 nsICollation *inst; |
|
25 nsresult res; |
|
26 |
|
27 res = CallCreateInstance(kCollationCID, &inst); |
|
28 if (NS_FAILED(res)) { |
|
29 return res; |
|
30 } |
|
31 |
|
32 inst->Initialize(locale); |
|
33 *instancePtr = inst; |
|
34 |
|
35 return res; |
|
36 } |
|
37 |
|
38 //////////////////////////////////////////////////////////////////////////////// |
|
39 |
|
40 nsCollation::nsCollation() |
|
41 { |
|
42 MOZ_COUNT_CTOR(nsCollation); |
|
43 } |
|
44 |
|
45 nsCollation::~nsCollation() |
|
46 { |
|
47 MOZ_COUNT_DTOR(nsCollation); |
|
48 } |
|
49 |
|
50 nsresult nsCollation::NormalizeString(const nsAString& stringIn, nsAString& stringOut) |
|
51 { |
|
52 int32_t aLength = stringIn.Length(); |
|
53 |
|
54 if (aLength <= 64) { |
|
55 char16_t conversionBuffer[64]; |
|
56 ToLowerCase(PromiseFlatString(stringIn).get(), conversionBuffer, aLength); |
|
57 stringOut.Assign(conversionBuffer, aLength); |
|
58 } |
|
59 else { |
|
60 char16_t* conversionBuffer; |
|
61 conversionBuffer = new char16_t[aLength]; |
|
62 if (!conversionBuffer) { |
|
63 return NS_ERROR_OUT_OF_MEMORY; |
|
64 } |
|
65 ToLowerCase(PromiseFlatString(stringIn).get(), conversionBuffer, aLength); |
|
66 stringOut.Assign(conversionBuffer, aLength); |
|
67 delete [] conversionBuffer; |
|
68 } |
|
69 return NS_OK; |
|
70 } |
|
71 |
|
72 nsresult nsCollation::SetCharset(const char* aCharset) |
|
73 { |
|
74 NS_ENSURE_ARG_POINTER(aCharset); |
|
75 |
|
76 nsresult rv; |
|
77 nsCOMPtr <nsICharsetConverterManager> charsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); |
|
78 if (NS_SUCCEEDED(rv)) { |
|
79 rv = charsetConverterManager->GetUnicodeEncoder(aCharset, |
|
80 getter_AddRefs(mEncoder)); |
|
81 } |
|
82 return rv; |
|
83 } |
|
84 |
|
85 nsresult nsCollation::UnicodeToChar(const nsAString& aSrc, char** dst) |
|
86 { |
|
87 NS_ENSURE_ARG_POINTER(dst); |
|
88 |
|
89 nsresult res = NS_OK; |
|
90 if (!mEncoder) |
|
91 res = SetCharset("ISO-8859-1"); |
|
92 |
|
93 if (NS_SUCCEEDED(res)) { |
|
94 const nsPromiseFlatString& src = PromiseFlatString(aSrc); |
|
95 const char16_t *unichars = src.get(); |
|
96 int32_t unicharLength = src.Length(); |
|
97 int32_t dstLength; |
|
98 res = mEncoder->GetMaxLength(unichars, unicharLength, &dstLength); |
|
99 if (NS_SUCCEEDED(res)) { |
|
100 int32_t bufLength = dstLength + 1 + 32; // extra 32 bytes for Finish() call |
|
101 *dst = (char *) PR_Malloc(bufLength); |
|
102 if (*dst) { |
|
103 **dst = '\0'; |
|
104 res = mEncoder->Convert(unichars, &unicharLength, *dst, &dstLength); |
|
105 |
|
106 if (NS_SUCCEEDED(res) || (NS_ERROR_UENC_NOMAPPING == res)) { |
|
107 // Finishes the conversion. The converter has the possibility to write some |
|
108 // extra data and flush its final state. |
|
109 int32_t finishLength = bufLength - dstLength; // remaining unused buffer length |
|
110 if (finishLength > 0) { |
|
111 res = mEncoder->Finish((*dst + dstLength), &finishLength); |
|
112 if (NS_SUCCEEDED(res)) { |
|
113 (*dst)[dstLength + finishLength] = '\0'; |
|
114 } |
|
115 } |
|
116 } |
|
117 if (NS_FAILED(res)) { |
|
118 PR_Free(*dst); |
|
119 *dst = nullptr; |
|
120 } |
|
121 } |
|
122 else { |
|
123 res = NS_ERROR_OUT_OF_MEMORY; |
|
124 } |
|
125 } |
|
126 } |
|
127 |
|
128 return res; |
|
129 } |
|
130 |
|
131 |
|
132 |