1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Pierre Phaneuf <pp@ludusdesign.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsIPlatformCharset.h"
40 : #include "nsIServiceManager.h"
41 : #include "nsIComponentManager.h"
42 : #include "nsCollation.h"
43 : #include "nsCollationCID.h"
44 : #include "nsUnicharUtils.h"
45 : #include "prmem.h"
46 : #include "nsReadableUtils.h"
47 :
48 : ////////////////////////////////////////////////////////////////////////////////
49 :
50 : NS_DEFINE_CID(kCollationCID, NS_COLLATION_CID);
51 :
52 180 : NS_IMPL_ISUPPORTS1(nsCollationFactory, nsICollationFactory)
53 :
54 19 : nsresult nsCollationFactory::CreateCollation(nsILocale* locale, nsICollation** instancePtr)
55 : {
56 : // Create a collation interface instance.
57 : //
58 : nsICollation *inst;
59 : nsresult res;
60 :
61 19 : res = CallCreateInstance(kCollationCID, &inst);
62 19 : if (NS_FAILED(res)) {
63 0 : return res;
64 : }
65 :
66 19 : inst->Initialize(locale);
67 19 : *instancePtr = inst;
68 :
69 19 : return res;
70 : }
71 :
72 : ////////////////////////////////////////////////////////////////////////////////
73 :
74 19 : nsCollation::nsCollation()
75 : {
76 19 : MOZ_COUNT_CTOR(nsCollation);
77 19 : }
78 :
79 38 : nsCollation::~nsCollation()
80 : {
81 19 : MOZ_COUNT_DTOR(nsCollation);
82 19 : }
83 :
84 22072 : nsresult nsCollation::NormalizeString(const nsAString& stringIn, nsAString& stringOut)
85 : {
86 22072 : PRInt32 aLength = stringIn.Length();
87 :
88 22072 : if (aLength <= 64) {
89 : PRUnichar conversionBuffer[64];
90 20470 : ToLowerCase(PromiseFlatString(stringIn).get(), conversionBuffer, aLength);
91 20470 : stringOut.Assign(conversionBuffer, aLength);
92 : }
93 : else {
94 : PRUnichar* conversionBuffer;
95 3204 : conversionBuffer = new PRUnichar[aLength];
96 1602 : if (!conversionBuffer) {
97 0 : return NS_ERROR_OUT_OF_MEMORY;
98 : }
99 1602 : ToLowerCase(PromiseFlatString(stringIn).get(), conversionBuffer, aLength);
100 1602 : stringOut.Assign(conversionBuffer, aLength);
101 1602 : delete [] conversionBuffer;
102 : }
103 22072 : return NS_OK;
104 : }
105 :
106 19 : nsresult nsCollation::SetCharset(const char* aCharset)
107 : {
108 19 : NS_ENSURE_ARG_POINTER(aCharset);
109 :
110 : nsresult rv;
111 38 : nsCOMPtr <nsICharsetConverterManager> charsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
112 19 : if (NS_SUCCEEDED(rv)) {
113 19 : rv = charsetConverterManager->GetUnicodeEncoder(aCharset,
114 19 : getter_AddRefs(mEncoder));
115 : }
116 19 : return rv;
117 : }
118 :
119 29318 : nsresult nsCollation::UnicodeToChar(const nsAString& aSrc, char** dst)
120 : {
121 29318 : NS_ENSURE_ARG_POINTER(dst);
122 :
123 29318 : nsresult res = NS_OK;
124 29318 : if (!mEncoder)
125 0 : res = SetCharset("ISO-8859-1");
126 :
127 29318 : if (NS_SUCCEEDED(res)) {
128 58636 : const nsPromiseFlatString& src = PromiseFlatString(aSrc);
129 29318 : const PRUnichar *unichars = src.get();
130 29318 : PRInt32 unicharLength = src.Length();
131 : PRInt32 dstLength;
132 29318 : res = mEncoder->GetMaxLength(unichars, unicharLength, &dstLength);
133 29318 : if (NS_SUCCEEDED(res)) {
134 29318 : PRInt32 bufLength = dstLength + 1 + 32; // extra 32 bytes for Finish() call
135 29318 : *dst = (char *) PR_Malloc(bufLength);
136 29318 : if (*dst) {
137 29318 : **dst = '\0';
138 29318 : res = mEncoder->Convert(unichars, &unicharLength, *dst, &dstLength);
139 :
140 29318 : if (NS_SUCCEEDED(res) || (NS_ERROR_UENC_NOMAPPING == res)) {
141 : // Finishes the conversion. The converter has the possibility to write some
142 : // extra data and flush its final state.
143 29318 : PRInt32 finishLength = bufLength - dstLength; // remaining unused buffer length
144 29318 : if (finishLength > 0) {
145 29318 : res = mEncoder->Finish((*dst + dstLength), &finishLength);
146 29318 : if (NS_SUCCEEDED(res)) {
147 29318 : (*dst)[dstLength + finishLength] = '\0';
148 : }
149 : }
150 : }
151 29318 : if (NS_FAILED(res)) {
152 0 : PR_Free(*dst);
153 0 : *dst = nsnull;
154 : }
155 : }
156 : else {
157 0 : res = NS_ERROR_OUT_OF_MEMORY;
158 : }
159 : }
160 : }
161 :
162 29318 : return res;
163 : }
164 :
165 :
166 :
|