Bumping manifests a=b2g-bump
[gecko.git] / intl / unicharutil / nsEntityConverter.cpp
blobad3aaa0f2236d85a639ee3605f5c467149050476
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/. */
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"
14 // implementation methods
16 nsEntityConverter::nsEntityConverter() :
17 mVersionList(nullptr),
18 mVersionListLength(0)
22 nsEntityConverter::~nsEntityConverter()
24 if (mVersionList)
25 delete [] mVersionList;
28 NS_IMETHODIMP
29 nsEntityConverter::LoadVersionPropertyFile()
31 NS_NAMED_LITERAL_CSTRING(url, "resource://gre/res/entityTables/htmlEntityVersions.properties");
33 nsCOMPtr<nsIStringBundleService> bundleService =
34 mozilla::services::GetStringBundleService();
35 if (!bundleService)
36 return NS_ERROR_FAILURE;
38 nsCOMPtr<nsIStringBundle> entities;
39 nsresult rv = bundleService->CreateBundle(url.get(), getter_AddRefs(entities));
40 if (NS_FAILED(rv)) return rv;
42 nsresult result;
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;
51 mVersionListLength = nsAutoString(value).ToInteger(&result);
52 NS_ASSERTION(32 >= mVersionListLength,"nsEntityConverter: malformed entity table\n");
53 if (32 < mVersionListLength) return NS_ERROR_FAILURE;
55 mVersionList = new nsEntityVersionList[mVersionListLength];
56 if (!mVersionList) return NS_ERROR_OUT_OF_MEMORY;
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;
65 memcpy(mVersionList[i].mEntityListName, value.get(), len*sizeof(char16_t));
66 mVersionList[i].mEntityListName[len] = 0;
67 mVersionList[i].mVersion = (1 << i);
70 return NS_OK;
73 already_AddRefed<nsIStringBundle>
74 nsEntityConverter::LoadEntityBundle(uint32_t version)
76 nsAutoCString url(NS_LITERAL_CSTRING("resource://gre/res/entityTables/"));
77 nsresult rv;
79 nsCOMPtr<nsIStringBundleService> bundleService =
80 do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
81 NS_ENSURE_SUCCESS(rv, nullptr);
83 const char16_t *versionName = GetVersionName(version);
84 NS_ENSURE_TRUE(versionName, nullptr);
86 // all property file names are ASCII, like "html40Latin1" so this is safe
87 LossyAppendUTF16toASCII(versionName, url);
88 url.AppendLiteral(".properties");
90 nsCOMPtr<nsIStringBundle> bundle;
91 rv = bundleService->CreateBundle(url.get(), getter_AddRefs(bundle));
92 NS_ENSURE_SUCCESS(rv, nullptr);
94 return bundle.forget();
97 const char16_t*
98 nsEntityConverter:: GetVersionName(uint32_t versionNumber)
100 for (uint32_t i = 0; i < mVersionListLength; i++) {
101 if (versionNumber == mVersionList[i].mVersion)
102 return mVersionList[i].mEntityListName;
105 return nullptr;
108 nsIStringBundle*
109 nsEntityConverter:: GetVersionBundleInstance(uint32_t versionNumber)
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;
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");
127 return mVersionList[i].mEntities.get();
131 return nullptr;
136 // nsISupports methods
138 NS_IMPL_ISUPPORTS(nsEntityConverter,nsIEntityConverter)
142 // nsIEntityConverter
144 NS_IMETHODIMP
145 nsEntityConverter::ConvertToEntity(char16_t character, uint32_t entityVersion, char **_retval)
147 return ConvertUTF32ToEntity((uint32_t)character, entityVersion, _retval);
150 NS_IMETHODIMP
151 nsEntityConverter::ConvertUTF32ToEntity(uint32_t character, uint32_t entityVersion, char **_retval)
153 NS_ASSERTION(_retval, "null ptr- _retval");
154 if(nullptr == _retval)
155 return NS_ERROR_NULL_POINTER;
156 *_retval = nullptr;
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");
164 if (!entities)
165 continue;
167 nsAutoString key(NS_LITERAL_STRING("entity."));
168 key.AppendInt(character,10);
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;
180 return NS_ERROR_ILLEGAL_VALUE;
183 NS_IMETHODIMP
184 nsEntityConverter::ConvertToEntities(const char16_t *inString, uint32_t entityVersion, char16_t **_retval)
186 NS_ENSURE_ARG_POINTER(inString);
187 NS_ENSURE_ARG_POINTER(_retval);
189 *_retval = nullptr;
191 nsString outString;
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;
203 else {
204 key.AppendInt(inString[i],10);
207 nsXPIDLString value;
208 const char16_t *entity = nullptr;
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");
216 if (!entities)
217 continue;
219 nsresult rv = entities->GetStringFromName(key.get(),
220 getter_Copies(value));
221 if (NS_SUCCEEDED(rv)) {
222 entity = value.get();
223 break;
226 if (entity) {
227 outString.Append(entity);
229 else {
230 outString.Append(&inString[i], 1);
234 *_retval = ToNewUnicode(outString);
235 if (!*_retval)
236 return NS_ERROR_OUT_OF_MEMORY;
238 return NS_OK;