intl/unicharutil/src/nsEntityConverter.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:6476968ae5bd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "nsEntityConverter.h"
7 #include "nsLiteralString.h"
8 #include "nsString.h"
9 #include "mozilla/Services.h"
10 #include "nsServiceManagerUtils.h"
11 #include "nsCRT.h"
12
13 //
14 // implementation methods
15 //
16 nsEntityConverter::nsEntityConverter() :
17 mVersionList(nullptr),
18 mVersionListLength(0)
19 {
20 }
21
22 nsEntityConverter::~nsEntityConverter()
23 {
24 if (mVersionList)
25 delete [] mVersionList;
26 }
27
28 NS_IMETHODIMP
29 nsEntityConverter::LoadVersionPropertyFile()
30 {
31 NS_NAMED_LITERAL_CSTRING(url, "resource://gre/res/entityTables/htmlEntityVersions.properties");
32
33 nsCOMPtr<nsIStringBundleService> bundleService =
34 mozilla::services::GetStringBundleService();
35 if (!bundleService)
36 return NS_ERROR_FAILURE;
37
38 nsCOMPtr<nsIStringBundle> entities;
39 nsresult rv = bundleService->CreateBundle(url.get(), getter_AddRefs(entities));
40 if (NS_FAILED(rv)) return rv;
41
42 nsresult result;
43
44 nsAutoString key;
45 nsXPIDLString value;
46 rv = entities->GetStringFromName(MOZ_UTF16("length"),
47 getter_Copies(value));
48 NS_ASSERTION(NS_SUCCEEDED(rv),"nsEntityConverter: malformed entity table\n");
49 if (NS_FAILED(rv)) return rv;
50
51 mVersionListLength = nsAutoString(value).ToInteger(&result);
52 NS_ASSERTION(32 >= mVersionListLength,"nsEntityConverter: malformed entity table\n");
53 if (32 < mVersionListLength) return NS_ERROR_FAILURE;
54
55 mVersionList = new nsEntityVersionList[mVersionListLength];
56 if (!mVersionList) return NS_ERROR_OUT_OF_MEMORY;
57
58 for (uint32_t i = 0; i < mVersionListLength && NS_SUCCEEDED(rv); i++) {
59 key.SetLength(0);
60 key.AppendInt(i+1, 10);
61 rv = entities->GetStringFromName(key.get(), getter_Copies(value));
62 uint32_t len = value.Length();
63 if (kVERSION_STRING_LEN < len) return NS_ERROR_UNEXPECTED;
64
65 memcpy(mVersionList[i].mEntityListName, value.get(), len*sizeof(char16_t));
66 mVersionList[i].mEntityListName[len] = 0;
67 mVersionList[i].mVersion = (1 << i);
68 }
69
70 return NS_OK;
71 }
72
73 already_AddRefed<nsIStringBundle>
74 nsEntityConverter::LoadEntityBundle(uint32_t version)
75 {
76 nsAutoCString url(NS_LITERAL_CSTRING("resource://gre/res/entityTables/"));
77 nsresult rv;
78
79 nsCOMPtr<nsIStringBundleService> bundleService =
80 do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
81 NS_ENSURE_SUCCESS(rv, nullptr);
82
83 const char16_t *versionName = GetVersionName(version);
84 NS_ENSURE_TRUE(versionName, nullptr);
85
86 // all property file names are ASCII, like "html40Latin1" so this is safe
87 LossyAppendUTF16toASCII(versionName, url);
88 url.Append(".properties");
89
90 nsCOMPtr<nsIStringBundle> bundle;
91 rv = bundleService->CreateBundle(url.get(), getter_AddRefs(bundle));
92 NS_ENSURE_SUCCESS(rv, nullptr);
93
94 return bundle.forget();
95 }
96
97 const char16_t*
98 nsEntityConverter:: GetVersionName(uint32_t versionNumber)
99 {
100 for (uint32_t i = 0; i < mVersionListLength; i++) {
101 if (versionNumber == mVersionList[i].mVersion)
102 return mVersionList[i].mEntityListName;
103 }
104
105 return nullptr;
106 }
107
108 nsIStringBundle*
109 nsEntityConverter:: GetVersionBundleInstance(uint32_t versionNumber)
110 {
111 if (!mVersionList) {
112 // load the property file which contains available version names
113 // and generate a list of version/name pair
114 if (NS_FAILED(LoadVersionPropertyFile()))
115 return nullptr;
116 }
117
118 uint32_t i;
119 for (i = 0; i < mVersionListLength; i++) {
120 if (versionNumber == mVersionList[i].mVersion) {
121 if (!mVersionList[i].mEntities)
122 { // not loaded
123 // load the property file
124 mVersionList[i].mEntities = LoadEntityBundle(versionNumber);
125 NS_ASSERTION(mVersionList[i].mEntities, "LoadEntityBundle failed");
126 }
127 return mVersionList[i].mEntities.get();
128 }
129 }
130
131 return nullptr;
132 }
133
134
135 //
136 // nsISupports methods
137 //
138 NS_IMPL_ISUPPORTS(nsEntityConverter,nsIEntityConverter)
139
140
141 //
142 // nsIEntityConverter
143 //
144 NS_IMETHODIMP
145 nsEntityConverter::ConvertToEntity(char16_t character, uint32_t entityVersion, char **_retval)
146 {
147 return ConvertUTF32ToEntity((uint32_t)character, entityVersion, _retval);
148 }
149
150 NS_IMETHODIMP
151 nsEntityConverter::ConvertUTF32ToEntity(uint32_t character, uint32_t entityVersion, char **_retval)
152 {
153 NS_ASSERTION(_retval, "null ptr- _retval");
154 if(nullptr == _retval)
155 return NS_ERROR_NULL_POINTER;
156 *_retval = nullptr;
157
158 for (uint32_t mask = 1, mask2 = 0xFFFFFFFFL; (0!=(entityVersion & mask2)); mask<<=1, mask2<<=1) {
159 if (0 == (entityVersion & mask))
160 continue;
161 nsIStringBundle* entities = GetVersionBundleInstance(entityVersion & mask);
162 NS_ASSERTION(entities, "Cannot get the property file");
163
164 if (!entities)
165 continue;
166
167 nsAutoString key(NS_LITERAL_STRING("entity."));
168 key.AppendInt(character,10);
169
170 nsXPIDLString value;
171 nsresult rv = entities->GetStringFromName(key.get(), getter_Copies(value));
172 if (NS_SUCCEEDED(rv)) {
173 *_retval = ToNewCString(value);
174 if(nullptr == *_retval)
175 return NS_ERROR_OUT_OF_MEMORY;
176 else
177 return NS_OK;
178 }
179 }
180 return NS_ERROR_ILLEGAL_VALUE;
181 }
182
183 NS_IMETHODIMP
184 nsEntityConverter::ConvertToEntities(const char16_t *inString, uint32_t entityVersion, char16_t **_retval)
185 {
186 NS_ENSURE_ARG_POINTER(inString);
187 NS_ENSURE_ARG_POINTER(_retval);
188
189 *_retval = nullptr;
190
191 nsString outString;
192
193 // per character look for the entity
194 uint32_t len = NS_strlen(inString);
195 for (uint32_t i = 0; i < len; i++) {
196 nsAutoString key(NS_LITERAL_STRING("entity."));
197 if (NS_IS_HIGH_SURROGATE(inString[i]) &&
198 i + 2 < len &&
199 NS_IS_LOW_SURROGATE(inString[i + 1])) {
200 key.AppendInt(SURROGATE_TO_UCS4(inString[i], inString[i+1]), 10);
201 ++i;
202 }
203 else {
204 key.AppendInt(inString[i],10);
205 }
206
207 nsXPIDLString value;
208 const char16_t *entity = nullptr;
209
210 for (uint32_t mask = 1, mask2 = 0xFFFFFFFFL; (0!=(entityVersion & mask2)); mask<<=1, mask2<<=1) {
211 if (0 == (entityVersion & mask))
212 continue;
213 nsIStringBundle* entities = GetVersionBundleInstance(entityVersion & mask);
214 NS_ASSERTION(entities, "Cannot get the property file");
215
216 if (!entities)
217 continue;
218
219 nsresult rv = entities->GetStringFromName(key.get(),
220 getter_Copies(value));
221 if (NS_SUCCEEDED(rv)) {
222 entity = value.get();
223 break;
224 }
225 }
226 if (entity) {
227 outString.Append(entity);
228 }
229 else {
230 outString.Append(&inString[i], 1);
231 }
232 }
233
234 *_retval = ToNewUnicode(outString);
235 if (!*_retval)
236 return NS_ERROR_OUT_OF_MEMORY;
237
238 return NS_OK;
239 }

mercurial