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