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