node-expat.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. #include <nan.h>
  2. extern "C" {
  3. #include <expat.h>
  4. }
  5. using namespace v8;
  6. using namespace node;
  7. class Parser : public Nan::ObjectWrap {
  8. public:
  9. static void Initialize(Handle<Object> target)
  10. {
  11. Nan::HandleScope scope;
  12. Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
  13. t->InstanceTemplate()->SetInternalFieldCount(1);
  14. Nan::SetPrototypeMethod(t, "parse", Parse);
  15. Nan::SetPrototypeMethod(t, "setEncoding", SetEncoding);
  16. Nan::SetPrototypeMethod(t, "setUnknownEncoding", SetUnknownEncoding);
  17. Nan::SetPrototypeMethod(t, "getError", GetError);
  18. Nan::SetPrototypeMethod(t, "stop", Stop);
  19. Nan::SetPrototypeMethod(t, "resume", Resume);
  20. Nan::SetPrototypeMethod(t, "reset", Reset);
  21. Nan::SetPrototypeMethod(t, "getCurrentLineNumber", GetCurrentLineNumber);
  22. Nan::SetPrototypeMethod(t, "getCurrentColumnNumber", GetCurrentColumnNumber);
  23. Nan::SetPrototypeMethod(t, "getCurrentByteIndex", GetCurrentByteIndex);
  24. target->Set(Nan::New("Parser").ToLocalChecked(), t->GetFunction());
  25. }
  26. protected:
  27. /*** Constructor ***/
  28. static NAN_METHOD(New)
  29. {
  30. Nan::HandleScope scope;
  31. XML_Char *encoding = NULL;
  32. if (info.Length() == 1 && info[0]->IsString())
  33. {
  34. Nan::Utf8String encodingArg(info[0]);
  35. encoding = new XML_Char[encodingArg.length() + 1];
  36. strcpy(encoding, *encodingArg);
  37. }
  38. Parser *parser = new Parser(encoding);
  39. if (encoding)
  40. delete[] encoding;
  41. parser->Wrap(info.This());
  42. info.GetReturnValue().Set(info.This());
  43. }
  44. Parser(const XML_Char *encoding)
  45. : Nan::ObjectWrap()
  46. {
  47. parser = XML_ParserCreate(encoding);
  48. assert(parser != NULL);
  49. attachHandlers();
  50. }
  51. ~Parser()
  52. {
  53. XML_ParserFree(parser);
  54. }
  55. void attachHandlers()
  56. {
  57. XML_SetUserData(parser, this);
  58. XML_SetElementHandler(parser, StartElement, EndElement);
  59. XML_SetCharacterDataHandler(parser, Text);
  60. XML_SetCdataSectionHandler(parser, StartCdata, EndCdata);
  61. XML_SetProcessingInstructionHandler(parser, ProcessingInstruction);
  62. XML_SetCommentHandler(parser, Comment);
  63. XML_SetXmlDeclHandler(parser, XmlDecl);
  64. XML_SetEntityDeclHandler(parser, EntityDecl);
  65. XML_SetUnknownEncodingHandler(parser, UnknownEncoding, this);
  66. }
  67. /*** parse() ***/
  68. static NAN_METHOD(Parse)
  69. {
  70. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  71. Nan::HandleScope scope;
  72. Local<String> str;
  73. int isFinal = 0;
  74. /* Argument 2: isFinal :: Bool */
  75. if (info.Length() >= 2)
  76. {
  77. isFinal = info[1]->IsTrue();
  78. }
  79. /* Argument 1: buf :: String or Buffer */
  80. if (info.Length() >= 1 && info[0]->IsString())
  81. {
  82. str = info[0]->ToString();
  83. info.GetReturnValue().Set(parser->parseString(**str, isFinal) ? Nan::True() : Nan::False());
  84. }
  85. else if (info.Length() >= 1 && info[0]->IsObject())
  86. {
  87. Local<Object> obj = info[0]->ToObject();
  88. if (Buffer::HasInstance(obj))
  89. {
  90. info.GetReturnValue().Set(parser->parseBuffer(obj, isFinal) ? Nan::True() : Nan::False());
  91. }
  92. else
  93. {
  94. Nan::ThrowTypeError("Parse buffer must be String or Buffer");
  95. return;
  96. }
  97. }
  98. else {
  99. Nan::ThrowTypeError("Parse buffer must be String or Buffer");
  100. return;
  101. }
  102. }
  103. /** Parse a v8 String by first writing it to the expat parser's
  104. buffer */
  105. bool parseString(String &str, int isFinal)
  106. {
  107. int len = str.Utf8Length();
  108. if (len == 0)
  109. return true;
  110. void *buf = XML_GetBuffer(parser, len);
  111. assert(buf != NULL);
  112. assert(str.WriteUtf8(static_cast<char *>(buf), len) == len);
  113. return XML_ParseBuffer(parser, len, isFinal) != XML_STATUS_ERROR;
  114. }
  115. /** Parse a node.js Buffer directly */
  116. bool parseBuffer(Local<Object> buffer, int isFinal)
  117. {
  118. return XML_Parse(parser, Buffer::Data(buffer), Buffer::Length(buffer), isFinal) != XML_STATUS_ERROR;
  119. }
  120. /*** setEncoding() ***/
  121. static NAN_METHOD(SetEncoding)
  122. {
  123. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  124. Nan::HandleScope scope;
  125. if (info.Length() == 1 && info[0]->IsString())
  126. {
  127. Nan::Utf8String encoding(info[0]);
  128. int status = parser->setEncoding(*encoding);
  129. info.GetReturnValue().Set(status ? Nan::True() : Nan::False());
  130. }
  131. else
  132. info.GetReturnValue().Set(Nan::False());
  133. }
  134. int setEncoding(XML_Char *encoding)
  135. {
  136. return XML_SetEncoding(parser, encoding) != 0;
  137. }
  138. /*** getError() ***/
  139. static NAN_METHOD(GetError)
  140. {
  141. Nan::HandleScope scope;
  142. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  143. const XML_LChar *error = parser->getError();
  144. if (error)
  145. info.GetReturnValue().Set(Nan::New(error).ToLocalChecked());
  146. else
  147. info.GetReturnValue().Set(Nan::Null());
  148. }
  149. /*** stop() ***/
  150. static NAN_METHOD(Stop)
  151. {
  152. Nan::HandleScope scope;
  153. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  154. int status = parser->stop();
  155. info.GetReturnValue().Set(status ? Nan::True() : Nan::False());
  156. }
  157. int stop()
  158. {
  159. return XML_StopParser(parser, XML_TRUE) != 0;
  160. }
  161. /*** resume() ***/
  162. static NAN_METHOD(Resume)
  163. {
  164. Nan::HandleScope scope;
  165. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  166. int status = parser->resume();
  167. info.GetReturnValue().Set(status ? Nan::True() : Nan::False());
  168. }
  169. int resume()
  170. {
  171. return XML_ResumeParser(parser) != 0;
  172. }
  173. static NAN_METHOD(Reset)
  174. {
  175. Nan::HandleScope scope;
  176. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  177. XML_Char *encoding = NULL;
  178. if (info.Length() == 1 && info[0]->IsString())
  179. {
  180. Nan::Utf8String encodingArg(info[0]);
  181. encoding = new XML_Char[encodingArg.length() + 1];
  182. strcpy(encoding, *encodingArg);
  183. }
  184. int status = parser->reset(encoding);
  185. if (encoding)
  186. delete[] encoding;
  187. if (status)
  188. parser->attachHandlers();
  189. info.GetReturnValue().Set(status ? Nan::True() : Nan::False());
  190. }
  191. int reset(XML_Char *encoding)
  192. {
  193. return XML_ParserReset(parser, encoding) != 0;
  194. }
  195. const XML_LChar *getError()
  196. {
  197. enum XML_Error code;
  198. code = XML_GetErrorCode(parser);
  199. return XML_ErrorString(code);
  200. }
  201. static NAN_METHOD(GetCurrentLineNumber)
  202. {
  203. Nan::HandleScope scope;
  204. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  205. info.GetReturnValue().Set(Nan::New(parser->getCurrentLineNumber()));
  206. }
  207. uint32_t getCurrentLineNumber()
  208. {
  209. return XML_GetCurrentLineNumber(parser);
  210. }
  211. static NAN_METHOD(GetCurrentColumnNumber)
  212. {
  213. Nan::HandleScope scope;
  214. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  215. info.GetReturnValue().Set(Nan::New(parser->getCurrentColumnNumber()));
  216. }
  217. uint32_t getCurrentColumnNumber()
  218. {
  219. return XML_GetCurrentColumnNumber(parser);
  220. }
  221. static NAN_METHOD(GetCurrentByteIndex)
  222. {
  223. Nan::HandleScope scope;
  224. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  225. info.GetReturnValue().Set(Nan::New(parser->getCurrentByteIndex()));
  226. }
  227. int32_t getCurrentByteIndex()
  228. {
  229. return XML_GetCurrentByteIndex(parser);
  230. }
  231. private:
  232. /* expat instance */
  233. XML_Parser parser;
  234. /* no default ctor */
  235. Parser();
  236. /*** SAX callbacks ***/
  237. /* Should a local HandleScope be used in those callbacks? */
  238. static void StartElement(void *userData,
  239. const XML_Char *name, const XML_Char **atts)
  240. {
  241. Nan::HandleScope scope;
  242. Parser *parser = reinterpret_cast<Parser *>(userData);
  243. /* Collect atts into JS object */
  244. Local<Object> attr = Nan::New<Object>();
  245. for(const XML_Char **atts1 = atts; *atts1; atts1 += 2)
  246. attr->Set(Nan::New(atts1[0]).ToLocalChecked(), Nan::New(atts1[1]).ToLocalChecked());
  247. /* Trigger event */
  248. Handle<Value> argv[3] = { Nan::New("startElement").ToLocalChecked(),
  249. Nan::New(name).ToLocalChecked(),
  250. attr };
  251. parser->Emit(3, argv);
  252. }
  253. static void EndElement(void *userData,
  254. const XML_Char *name)
  255. {
  256. Nan::HandleScope scope;
  257. Parser *parser = reinterpret_cast<Parser *>(userData);
  258. /* Trigger event */
  259. Handle<Value> argv[2] = { Nan::New("endElement").ToLocalChecked(), Nan::New(name).ToLocalChecked() };
  260. parser->Emit(2, argv);
  261. }
  262. static void StartCdata(void *userData)
  263. {
  264. Nan::HandleScope scope;
  265. Parser *parser = reinterpret_cast<Parser *>(userData);
  266. /* Trigger event */
  267. Handle<Value> argv[1] = { Nan::New("startCdata").ToLocalChecked() };
  268. parser->Emit(1, argv);
  269. }
  270. static void EndCdata(void *userData)
  271. {
  272. Nan::HandleScope scope;
  273. Parser *parser = reinterpret_cast<Parser *>(userData);
  274. /* Trigger event */
  275. Handle<Value> argv[1] = { Nan::New("endCdata").ToLocalChecked() };
  276. parser->Emit(1, argv);
  277. }
  278. static void Text(void *userData,
  279. const XML_Char *s, int len)
  280. {
  281. Nan::HandleScope scope;
  282. Parser *parser = reinterpret_cast<Parser *>(userData);
  283. /* Trigger event */
  284. Handle<Value> argv[2] = { Nan::New("text").ToLocalChecked(),
  285. Nan::New(s, len).ToLocalChecked() };
  286. parser->Emit(2, argv);
  287. }
  288. static void ProcessingInstruction(void *userData,
  289. const XML_Char *target, const XML_Char *data)
  290. {
  291. Nan::HandleScope scope;
  292. Parser *parser = reinterpret_cast<Parser *>(userData);
  293. /* Trigger event */
  294. Handle<Value> argv[3] = { Nan::New("processingInstruction").ToLocalChecked(),
  295. Nan::New(target).ToLocalChecked(),
  296. Nan::New(data).ToLocalChecked() };
  297. parser->Emit(3, argv);
  298. }
  299. static void Comment(void *userData,
  300. const XML_Char *data)
  301. {
  302. Nan::HandleScope scope;
  303. Parser *parser = reinterpret_cast<Parser *>(userData);
  304. /* Trigger event */
  305. Handle<Value> argv[2] = { Nan::New("comment").ToLocalChecked(), Nan::New(data).ToLocalChecked() };
  306. parser->Emit(2, argv);
  307. }
  308. static void XmlDecl(void *userData,
  309. const XML_Char *version, const XML_Char *encoding,
  310. int standalone)
  311. {
  312. Nan::HandleScope scope;
  313. Parser *parser = reinterpret_cast<Parser *>(userData);
  314. /* Trigger event */
  315. Local<Value> argv[4];
  316. argv[0] = Nan::New("xmlDecl").ToLocalChecked();
  317. if (version) argv[1] = Nan::New(version).ToLocalChecked();
  318. else argv[1] = Nan::Null();
  319. if (encoding) argv[2] = Nan::New(encoding).ToLocalChecked();
  320. else argv[2] = Nan::Null();
  321. if (standalone) argv[3] = Nan::True();
  322. else argv[3] = Nan::False();
  323. parser->Emit(4, argv);
  324. }
  325. static void EntityDecl(void *userData, const XML_Char *entityName, int is_parameter_entity,
  326. const XML_Char *value, int value_length, const XML_Char *base,
  327. const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName)
  328. {
  329. Nan::HandleScope scope;
  330. Parser *parser = reinterpret_cast<Parser *>(userData);
  331. /* Trigger event */
  332. Local<Value> argv[8];
  333. argv[0] = Nan::New("entityDecl").ToLocalChecked();
  334. if (entityName) argv[1] = Nan::New(entityName).ToLocalChecked();
  335. else argv[1] = Nan::Null();
  336. if (is_parameter_entity) argv[2] = Nan::True();
  337. else argv[2] = Nan::False();
  338. if (value) argv[3] = Nan::New(value, value_length).ToLocalChecked();
  339. else argv[3] = Nan::Null();
  340. if (base) argv[4] = Nan::New(base).ToLocalChecked();
  341. else argv[4] = Nan::Null();
  342. if (systemId) argv[5] = Nan::New(systemId).ToLocalChecked();
  343. else argv[5] = Nan::Null();
  344. if (publicId) argv[6] = Nan::New(publicId).ToLocalChecked();
  345. else argv[6] = Nan::Null();
  346. if (notationName) argv[7] = Nan::New(notationName).ToLocalChecked();
  347. else argv[7] = Nan::Null();
  348. parser->Emit(8, argv);
  349. }
  350. XML_Encoding *xmlEncodingInfo;
  351. static int UnknownEncoding(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info)
  352. {
  353. Nan::HandleScope scope;
  354. Parser *parser = reinterpret_cast<Parser *>(encodingHandlerData);
  355. /* Trigger event */
  356. parser->xmlEncodingInfo = info;
  357. Local<Value> argv[2];
  358. argv[0] = Nan::New("unknownEncoding").ToLocalChecked();
  359. if (name) argv[1] = Nan::New(name).ToLocalChecked();
  360. else argv[1] = Nan::Null();
  361. parser->Emit(2, argv);
  362. /* Did no event handler invoke setUnknownEncoding()? */
  363. if (parser->xmlEncodingInfo) {
  364. parser->xmlEncodingInfo = NULL;
  365. return XML_STATUS_ERROR;
  366. } else {
  367. return XML_STATUS_OK;
  368. }
  369. }
  370. /**
  371. * Fills xmlEncodingInfo
  372. */
  373. static NAN_METHOD(SetUnknownEncoding)
  374. {
  375. Parser *parser = Nan::ObjectWrap::Unwrap<Parser>(info.This());
  376. Nan::HandleScope scope;
  377. if (!parser->xmlEncodingInfo)
  378. Nan::ThrowError("setUnknownEncoding() must be synchronously invoked from an unknownEncoding event handler");
  379. if (info.Length() >= 1 && info[0]->IsArray()) {
  380. Local<Array> map = info[0].As<Array>();
  381. /* Copy map */
  382. for(int i = 0; i < 256; i++) {
  383. Local<Value> m = map->Get(Nan::New(i));
  384. if (m->IsInt32())
  385. parser->xmlEncodingInfo->map[i] = m->Int32Value();
  386. else
  387. Nan::ThrowTypeError("UnknownEncoding map must consist of 256 ints");
  388. }
  389. } else
  390. Nan::ThrowTypeError("SetUnknownEncoding expects a map array");
  391. parser->xmlEncodingInfo = NULL;
  392. return;
  393. }
  394. void Emit(int argc, Handle<Value> argv[])
  395. {
  396. Nan::HandleScope scope;
  397. Handle<Object> handle = this->handle();
  398. Local<Function> emit = handle->Get(Nan::New("emit").ToLocalChecked()).As<Function>();
  399. emit->Call(handle, argc, argv);
  400. }
  401. };
  402. extern "C" {
  403. static void init (Handle<Object> target)
  404. {
  405. Parser::Initialize(target);
  406. }
  407. //Changed the name cause I couldn't load the module with - in their names
  408. NODE_MODULE(node_expat, init);
  409. };