• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "native_module_xml.h"
17 #include "js_xml.h"
18 
19 extern const char _binary_js_xml_js_start[];
20 extern const char _binary_js_xml_js_end[];
21 extern const char _binary_xml_abc_start[];
22 extern const char _binary_xml_abc_end[];
23 
24 namespace OHOS::xml {
XmlSerializerConstructor(napi_env env,napi_callback_info info)25     static napi_value XmlSerializerConstructor(napi_env env, napi_callback_info info)
26     {
27         napi_value thisVar = nullptr;
28         void *data = nullptr;
29         size_t argc = 2;
30         napi_value args[2] = { nullptr }; // 2:The number of parameters is 2
31         XmlSerializer *object = nullptr;
32         size_t iLength = 0;
33         size_t offPos = 0;
34         napi_value arraybuffer = nullptr;
35         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, &data));
36         NAPI_ASSERT(env, argc == 1 || argc == 2, "Wrong number of arguments"); // 2: number of args
37 
38         bool bFlag = false;
39         napi_is_arraybuffer(env, args[0], &bFlag);
40         if (bFlag) {
41             napi_get_arraybuffer_info(env, args[0], &data, &iLength);
42         } else {
43             napi_is_dataview(env, args[0], &bFlag);
44             if (bFlag) {
45                 napi_get_dataview_info(env, args[0], &iLength, &data, &arraybuffer, &offPos);
46             } else {
47                 napi_throw_error(env, "401", "Parameter error. The type of Parameter must be ArrayBuffer or DataView.");
48                 return nullptr;
49             }
50         }
51 
52         if (argc == 1) {
53             object = new XmlSerializer(reinterpret_cast<char*>(data), iLength);
54         } else if (argc == 2) { // 2:When the input parameter is set to 2
55             std::string encoding = "";
56             napi_valuetype valuetype;
57             NAPI_CALL(env, napi_typeof(env, args[1], &valuetype));
58             NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
59             napi_status status = napi_ok;
60             status = XmlSerializer::DealNapiStrValue(env, args[1], encoding);
61             if (status == napi_ok) {
62                 object = new XmlSerializer(reinterpret_cast<char*>(data), iLength, encoding);
63             }
64         }
65         napi_status status = napi_wrap(env, thisVar, object,
66             [](napi_env environment, void *data, void *hint) {
67                 auto obj = reinterpret_cast<XmlSerializer*>(data);
68                 if (obj != nullptr) {
69                     delete obj;
70                     obj = nullptr;
71                 }
72             }, nullptr, nullptr);
73         if (status != napi_ok && object != nullptr) {
74             HILOG_ERROR("XmlPullParserConstructor:: napi_wrap failed");
75             delete object;
76             object = nullptr;
77         }
78         return thisVar;
79     }
80 
DealCdata(void * data,size_t len)81     std::string DealCdata(void *data, size_t len)
82     {
83         std::string strEnd(reinterpret_cast<char*>(data), len);
84         strEnd = strEnd.substr(0, std::strlen(strEnd.c_str()));
85         std::string cDataBegin = "<![CDATA[";
86         std::string cDataEnd = "]]>";
87         size_t foundPosBegin = strEnd.find(cDataBegin);
88         size_t foundPosEnd = strEnd.find(cDataEnd);
89         size_t count = 0;
90         while (foundPosBegin != std::string::npos) {
91             std::string temp = strEnd.substr(foundPosBegin, foundPosEnd - foundPosBegin + cDataEnd.length());
92             std::string resStr = "";
93             for (char c : temp) {
94                 if (c != '\r' && c != '\n') {
95                     resStr += c;
96                 }
97                 if (c == '\r') {
98                     resStr += "\\r";
99                     count++;
100                 }
101                 if (c == '\n') {
102                     resStr += "\\n";
103                     count++;
104                 }
105             }
106             strEnd.replace(foundPosBegin, temp.length(), resStr);
107             foundPosBegin = strEnd.find(cDataBegin, foundPosBegin + 1);
108             foundPosEnd = strEnd.find(cDataEnd, foundPosEnd + count + 1);
109         }
110         return strEnd;
111     }
112 
XmlPullParserConstructor(napi_env env,napi_callback_info info)113     static napi_value XmlPullParserConstructor(napi_env env, napi_callback_info info)
114     {
115         napi_value thisVar = nullptr;
116         void *data = nullptr;
117         size_t argc = 2;
118         napi_value args[2] = { nullptr }; // 2:two args
119         XmlPullParser *object = nullptr;
120         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, &data));
121         NAPI_ASSERT(env, argc == 1 || argc == 2, "Wrong number of arguments"); // 2:two args
122         napi_valuetype valuetype = napi_null;
123         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
124         NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type: DataView or ArrayBuffer expected.");
125         bool bFlag = false;
126         size_t len = 0;
127         size_t offPos = 0;
128         napi_value arraybuffer = nullptr;
129         napi_is_arraybuffer(env, args[0], &bFlag);
130         if (bFlag) {
131             napi_get_arraybuffer_info(env, args[0], &data, &len);
132         } else {
133             napi_is_dataview(env, args[0], &bFlag);
134             if (bFlag) {
135                 napi_get_dataview_info(env, args[0], &len, &data, &arraybuffer, &offPos);
136             } else {
137                 napi_throw_error(env, "401", "Parameter error. The type of Parameter must be ArrayBuffer or DataView.");
138                 return nullptr;
139             }
140         }
141         if (data) {
142             std::string strEnd = DealCdata(data, len);
143             if (argc == 1) {
144                 object = new XmlPullParser(env, strEnd, "utf-8");
145             } else if (argc == 2) { // 2:When the input parameter is set to 2
146                 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype));
147                 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
148                 std::string strEncoding = "";
149                 XmlSerializer::DealNapiStrValue(env, args[1], strEncoding);
150                 object = new XmlPullParser(env, strEnd, strEncoding);
151             }
152         }
153         napi_status status = napi_wrap(env, thisVar, object,
154             [](napi_env env, void *data, void *hint) {
155                 auto obj = reinterpret_cast<XmlPullParser*>(data);
156                 if (obj != nullptr) {
157                     delete obj;
158                     obj = nullptr;
159                 }
160             }, nullptr, nullptr);
161         if (status != napi_ok && object != nullptr) {
162             HILOG_ERROR("XmlPullParserConstructor:: napi_wrap failed");
163             delete object;
164             object = nullptr;
165         }
166         return thisVar;
167     }
168 
SetAttributes(napi_env env,napi_callback_info info)169     static napi_value SetAttributes(napi_env env, napi_callback_info info)
170     {
171         napi_value thisVar = nullptr;
172         size_t argc = 2;
173         napi_value args[2] = { nullptr }; // 2:two args
174         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
175         NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); // 2: number of args
176         napi_valuetype valuetype = napi_null;
177         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
178         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. string expected.");
179         NAPI_CALL(env, napi_typeof(env, args[1], &valuetype));
180         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. string expected.");
181         XmlSerializer *object = nullptr;
182         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
183         std::string name;
184         std::string value;
185         XmlSerializer::DealNapiStrValue(env, args[0], name);
186         XmlSerializer::DealNapiStrValue(env, args[1], value);
187         object->SetAttributes(name, value);
188         napi_value result = nullptr;
189         NAPI_CALL(env, napi_get_undefined(env, &result));
190         return result;
191     }
192 
AddEmptyElement(napi_env env,napi_callback_info info)193     static napi_value AddEmptyElement(napi_env env, napi_callback_info info)
194     {
195         napi_value thisVar = nullptr;
196         size_t argc = 1;
197         napi_value args[1] = { 0 };
198         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
199         NAPI_ASSERT(env, argc == 1, "Wrong number of arguments.");
200 
201         napi_valuetype valuetype;
202         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
203         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
204         XmlSerializer *object = nullptr;
205         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
206         std::string name;
207         object->DealNapiStrValue(env, args[0], name);
208         object->AddEmptyElement(name);
209 
210         napi_value result = nullptr;
211         NAPI_CALL(env, napi_get_undefined(env, &result));
212         return result;
213     }
214 
SetDeclaration(napi_env env,napi_callback_info info)215     static napi_value SetDeclaration(napi_env env, napi_callback_info info)
216     {
217         napi_value thisVar = nullptr;
218         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
219         XmlSerializer *object = nullptr;
220         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
221         object->SetDeclaration();
222         napi_value result = nullptr;
223         NAPI_CALL(env, napi_get_undefined(env, &result));
224         return result;
225     }
226 
StartElement(napi_env env,napi_callback_info info)227     static napi_value StartElement(napi_env env, napi_callback_info info)
228     {
229         size_t argc = 1;
230         napi_value args[1] = { nullptr };
231         napi_value thisVar = nullptr;
232         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
233         NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
234         XmlSerializer *object = nullptr;
235         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
236         std::string name;
237         object->DealNapiStrValue(env, args[0], name);
238         object->StartElement(name);
239         napi_value result = nullptr;
240         NAPI_CALL(env, napi_get_undefined(env, &result));
241         return result;
242     }
243 
EndElement(napi_env env,napi_callback_info info)244     static napi_value EndElement(napi_env env, napi_callback_info info)
245     {
246         napi_value thisVar = nullptr;
247         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
248         XmlSerializer *object = nullptr;
249         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
250         object->EndElement();
251         napi_value result = nullptr;
252         NAPI_CALL(env, napi_get_undefined(env, &result));
253         return result;
254     }
255 
SetNamespace(napi_env env,napi_callback_info info)256     static napi_value SetNamespace(napi_env env, napi_callback_info info)
257     {
258         napi_value thisVar = nullptr;
259         size_t argc = 2;
260         napi_value args[2] = { nullptr }; // 2:two args
261         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
262         NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); // 2:two args
263         napi_valuetype valuetype = napi_null;
264         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
265         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
266         NAPI_CALL(env, napi_typeof(env, args[1], &valuetype));
267         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
268         XmlSerializer *object = nullptr;
269         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
270         std::string prefix;
271         std::string nsTemp;
272         XmlSerializer::DealNapiStrValue(env, args[0], prefix);
273         XmlSerializer::DealNapiStrValue(env, args[1], nsTemp);
274         object->SetNamespace(prefix, nsTemp);
275         napi_value result = nullptr;
276         NAPI_CALL(env, napi_get_undefined(env, &result));
277         return result;
278     }
279 
SetComment(napi_env env,napi_callback_info info)280     static napi_value SetComment(napi_env env, napi_callback_info info)
281     {
282         napi_value thisVar = nullptr;
283         size_t argc = 1;
284         napi_value args[1] = { nullptr };
285         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
286         NAPI_ASSERT(env, argc == 1, "Wrong number of arguments.");
287         napi_valuetype valuetype = napi_null;
288         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
289         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
290         XmlSerializer *object = nullptr;
291         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
292         std::string comment;
293         object->DealNapiStrValue(env, args[0], comment);
294         object->SetComment(comment);
295         napi_value result = nullptr;
296         NAPI_CALL(env, napi_get_undefined(env, &result));
297         return result;
298     }
299 
SetCData(napi_env env,napi_callback_info info)300     static napi_value SetCData(napi_env env, napi_callback_info info)
301     {
302         napi_value thisVar = nullptr;
303         size_t argc = 1;
304         napi_value args[1] = { nullptr };
305         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
306         NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
307         napi_valuetype valuetype = napi_null;
308         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
309         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
310         XmlSerializer *object = nullptr;
311         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
312         std::string data;
313         XmlSerializer::DealNapiStrValue(env, args[0], data);
314         object->SetCData(data);
315         napi_value result = nullptr;
316         NAPI_CALL(env, napi_get_undefined(env, &result));
317         return result;
318     }
319 
SetText(napi_env env,napi_callback_info info)320     static napi_value SetText(napi_env env, napi_callback_info info)
321     {
322         napi_value thisVar = nullptr;
323         size_t argc = 1;
324         napi_value args[1] = { nullptr };
325         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
326         NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
327         napi_valuetype valuetype = napi_null;
328         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
329         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
330         XmlSerializer *object = nullptr;
331         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
332         std::string text;
333         XmlSerializer::DealNapiStrValue(env, args[0], text);
334         object->SetText(text);
335         napi_value result = nullptr;
336         NAPI_CALL(env, napi_get_undefined(env, &result));
337         return result;
338     }
339 
SetDocType(napi_env env,napi_callback_info info)340     static napi_value SetDocType(napi_env env, napi_callback_info info)
341     {
342         napi_value thisVar = nullptr;
343         size_t argc = 1;
344         napi_value args[1] = { nullptr };
345         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
346         NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
347         napi_valuetype valuetype = napi_null;
348         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
349         NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type: string expected.");
350         XmlSerializer *object = nullptr;
351         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
352         std::string text;
353         XmlSerializer::DealNapiStrValue(env, args[0], text);
354         object->SetDocType(text);
355         napi_value result = nullptr;
356         NAPI_CALL(env, napi_get_undefined(env, &result));
357         return result;
358     }
XmlSerializerError(napi_env env,napi_callback_info info)359     static napi_value XmlSerializerError(napi_env env, napi_callback_info info)
360     {
361         napi_value thisVar = nullptr;
362         napi_value result = nullptr;
363         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
364         XmlSerializer *object = nullptr;
365         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
366         std::string temp = object->XmlSerializerError();
367         size_t templen = temp.size();
368         NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
369         return result;
370     }
371 
XmlSerializerInit(napi_env env,napi_value exports)372     napi_value XmlSerializerInit(napi_env env, napi_value exports)
373     {
374         const char *xmlSerializerClass = "XmlSerializer";
375         napi_value xmlClass = nullptr;
376         napi_property_descriptor xmlDesc[] = {
377             DECLARE_NAPI_FUNCTION("setAttributes", SetAttributes),
378             DECLARE_NAPI_FUNCTION("addEmptyElement", AddEmptyElement),
379             DECLARE_NAPI_FUNCTION("setDeclaration", SetDeclaration),
380             DECLARE_NAPI_FUNCTION("startElement", StartElement),
381             DECLARE_NAPI_FUNCTION("endElement", EndElement),
382             DECLARE_NAPI_FUNCTION("setNamespace", SetNamespace),
383             DECLARE_NAPI_FUNCTION("setComment", SetComment),
384             DECLARE_NAPI_FUNCTION("setCDATA", SetCData),
385             DECLARE_NAPI_FUNCTION("setText", SetText),
386             DECLARE_NAPI_FUNCTION("setDocType", SetDocType),
387             DECLARE_NAPI_FUNCTION("XmlSerializerError", XmlSerializerError)
388         };
389         NAPI_CALL(env, napi_define_class(env, xmlSerializerClass, strlen(xmlSerializerClass), XmlSerializerConstructor,
390                                          nullptr, sizeof(xmlDesc) / sizeof(xmlDesc[0]), xmlDesc, &xmlClass));
391         napi_property_descriptor desc[] = {
392             DECLARE_NAPI_PROPERTY("XmlSerializer", xmlClass)
393         };
394         napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
395         return exports;
396     }
397 
Parse(napi_env env,napi_callback_info info)398     static napi_value Parse(napi_env env, napi_callback_info info)
399     {
400         napi_value thisVar = nullptr;
401         size_t argc = 1;
402         napi_value args[1] = { nullptr };
403         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr));
404         NAPI_ASSERT(env, argc == 1, "Wrong number of arguments, one expected.");
405         napi_valuetype valuetype;
406         NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
407         NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type: object expected.");
408         XmlPullParser *object = nullptr;
409         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
410         object->DealOptionInfo(env, args[0]);
411         object->Parse(env, thisVar);
412         napi_value result = nullptr;
413         NAPI_CALL(env, napi_get_undefined(env, &result));
414         return result;
415     }
416 
XmlPullParserError(napi_env env,napi_callback_info info)417     static napi_value XmlPullParserError(napi_env env, napi_callback_info info)
418     {
419         napi_value thisVar = nullptr;
420         napi_value result = nullptr;
421         NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
422         XmlPullParser *object = nullptr;
423         NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object)));
424         std::string temp = object->XmlPullParserError();
425         size_t templen = temp.size();
426         NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
427         return result;
428     }
429 
XmlPullParserInit(napi_env env,napi_value exports)430     napi_value XmlPullParserInit(napi_env env, napi_value exports)
431     {
432         const char *xmlPullParserClass = "XmlPullParser";
433         napi_value xmlClass = nullptr;
434         napi_property_descriptor xmlDesc[] = {
435             DECLARE_NAPI_FUNCTION("parse", Parse),
436             DECLARE_NAPI_FUNCTION("XmlPullParserError", XmlPullParserError)
437         };
438         NAPI_CALL(env, napi_define_class(env, xmlPullParserClass, strlen(xmlPullParserClass),
439             XmlPullParserConstructor, nullptr, sizeof(xmlDesc) / sizeof(xmlDesc[0]),
440             xmlDesc, &xmlClass));
441         napi_property_descriptor desc[] = {
442             DECLARE_NAPI_PROPERTY("XmlPullParser", xmlClass)
443         };
444         napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
445         return exports;
446     };
447 
Init(napi_env env,napi_value exports)448     static napi_value Init(napi_env env, napi_value exports)
449     {
450         XmlSerializerInit(env, exports);
451         XmlPullParserInit(env, exports);
452         return exports;
453     }
454 
455     extern "C"
NAPI_xml_GetJSCode(const char ** buf,int * bufLen)456     __attribute__((visibility("default"))) void NAPI_xml_GetJSCode(const char **buf, int *bufLen)
457     {
458         if (buf != nullptr) {
459             *buf = _binary_js_xml_js_start;
460         }
461 
462         if (bufLen != nullptr) {
463             *bufLen = _binary_js_xml_js_end - _binary_js_xml_js_start;
464         }
465     }
466     extern "C"
NAPI_xml_GetABCCode(const char ** buf,int * buflen)467     __attribute__((visibility("default"))) void NAPI_xml_GetABCCode(const char** buf, int* buflen)
468     {
469         if (buf != nullptr) {
470             *buf = _binary_xml_abc_start;
471         }
472         if (buflen != nullptr) {
473             *buflen = _binary_xml_abc_end - _binary_xml_abc_start;
474         }
475     }
476 
477 
478     static napi_module_with_js xmlModule = {
479         .nm_version = 1,
480         .nm_flags = 0,
481         .nm_filename = nullptr,
482         .nm_register_func = Init,
483         .nm_modname = "xml",
484         .nm_priv = reinterpret_cast<void*>(0),
485         .nm_get_abc_code = NAPI_xml_GetABCCode,
486         .nm_get_js_code = NAPI_xml_GetJSCode,
487     };
XmlRegisterModule()488     extern "C" __attribute__((constructor)) void XmlRegisterModule()
489     {
490         napi_module_with_js_register(&xmlModule);
491     }
492 } // namespace OHOS::Xml
493