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"
9 #include "mozilla/Services.h"
10 #include "nsServiceManagerUtils.h"
14 // implementation methods
16 nsEntityConverter::nsEntityConverter() :
17 mVersionList(nullptr),
22 nsEntityConverter::~nsEntityConverter()
25 delete [] mVersionList
;
29 nsEntityConverter::LoadVersionPropertyFile()
31 NS_NAMED_LITERAL_CSTRING(url
, "resource://gre/res/entityTables/htmlEntityVersions.properties");
33 nsCOMPtr
<nsIStringBundleService
> bundleService
=
34 mozilla::services::GetStringBundleService();
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
;
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
++) {
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
);
73 already_AddRefed
<nsIStringBundle
>
74 nsEntityConverter::LoadEntityBundle(uint32_t version
)
76 nsAutoCString
url(NS_LITERAL_CSTRING("resource://gre/res/entityTables/"));
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();
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
;
109 nsEntityConverter:: GetVersionBundleInstance(uint32_t versionNumber
)
112 // load the property file which contains available version names
113 // and generate a list of version/name pair
114 if (NS_FAILED(LoadVersionPropertyFile()))
119 for (i
= 0; i
< mVersionListLength
; i
++) {
120 if (versionNumber
== mVersionList
[i
].mVersion
) {
121 if (!mVersionList
[i
].mEntities
)
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();
136 // nsISupports methods
138 NS_IMPL_ISUPPORTS(nsEntityConverter
,nsIEntityConverter
)
142 // nsIEntityConverter
145 nsEntityConverter::ConvertToEntity(char16_t character
, uint32_t entityVersion
, char **_retval
)
147 return ConvertUTF32ToEntity((uint32_t)character
, entityVersion
, _retval
);
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
;
158 for (uint32_t mask
= 1, mask2
= 0xFFFFFFFFL
; (0!=(entityVersion
& mask2
)); mask
<<=1, mask2
<<=1) {
159 if (0 == (entityVersion
& mask
))
161 nsIStringBundle
* entities
= GetVersionBundleInstance(entityVersion
& mask
);
162 NS_ASSERTION(entities
, "Cannot get the property file");
167 nsAutoString
key(NS_LITERAL_STRING("entity."));
168 key
.AppendInt(character
,10);
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
;
180 return NS_ERROR_ILLEGAL_VALUE
;
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
);
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
]) &&
199 NS_IS_LOW_SURROGATE(inString
[i
+ 1])) {
200 key
.AppendInt(SURROGATE_TO_UCS4(inString
[i
], inString
[i
+1]), 10);
204 key
.AppendInt(inString
[i
],10);
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
))
213 nsIStringBundle
* entities
= GetVersionBundleInstance(entityVersion
& mask
);
214 NS_ASSERTION(entities
, "Cannot get the property file");
219 nsresult rv
= entities
->GetStringFromName(key
.get(),
220 getter_Copies(value
));
221 if (NS_SUCCEEDED(rv
)) {
222 entity
= value
.get();
227 outString
.Append(entity
);
230 outString
.Append(&inString
[i
], 1);
234 *_retval
= ToNewUnicode(outString
);
236 return NS_ERROR_OUT_OF_MEMORY
;