Skip to content

Commit 000de2d

Browse files
committed
performance improvement
- replace substr with direct char code comparison - improve tagExpWithClosingIndex
1 parent 6473af0 commit 000de2d

1 file changed

Lines changed: 40 additions & 30 deletions

File tree

src/xmlparser/OrderedObjParser.js

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ const parseXml = function (xmlData) {
310310
if (ch === '<') {
311311
// const nextIndex = i+1;
312312
// const _2ndChar = xmlData[nextIndex];
313-
if (xmlData[i + 1] === '/') {//Closing Tag
313+
const c1 = xmlData.charCodeAt(i + 1);
314+
if (c1 === 47) {//Closing Tag '/'
314315
const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.")
315316
let tagName = xmlData.substring(i + 2, closeIndex).trim();
316317

@@ -344,7 +345,7 @@ const parseXml = function (xmlData) {
344345
currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope
345346
textData = "";
346347
i = closeIndex;
347-
} else if (xmlData[i + 1] === '?') {
348+
} else if (c1 === 63) { //'?'
348349

349350
let tagData = readTagExp(xmlData, i, false, "?>");
350351
if (!tagData) throw new Error("Pi Tag is not closed.");
@@ -365,7 +366,9 @@ const parseXml = function (xmlData) {
365366

366367

367368
i = tagData.closeIndex + 1;
368-
} else if (xmlData.substr(i + 1, 3) === '!--') {
369+
} else if (c1 === 33
370+
&& xmlData.charCodeAt(i + 2) === 45
371+
&& xmlData.charCodeAt(i + 3) === 45) { //'!--'
369372
const endIndex = findClosingIndex(xmlData, "-->", i + 4, "Comment is not closed.")
370373
if (this.options.commentPropName) {
371374
const comment = xmlData.substring(i + 4, endIndex - 2);
@@ -375,11 +378,13 @@ const parseXml = function (xmlData) {
375378
currentNode.add(this.options.commentPropName, [{ [this.options.textNodeName]: comment }]);
376379
}
377380
i = endIndex;
378-
} else if (xmlData.substr(i + 1, 2) === '!D') {
381+
} else if (c1 === 33
382+
&& xmlData.charCodeAt(i + 2) === 68) { //'!D'
379383
const result = docTypeReader.readDocType(xmlData, i);
380384
this.docTypeEntities = result.entities;
381385
i = result.i;
382-
} else if (xmlData.substr(i + 1, 2) === '![') {
386+
} else if (c1 === 33
387+
&& xmlData.charCodeAt(i + 2) === 91) { // '!['
383388
const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
384389
const tagExp = xmlData.substring(i + 9, closeIndex);
385390

@@ -735,32 +740,33 @@ function isItStopNode(stopNodeExpressions, matcher) {
735740
* @returns
736741
*/
737742
function tagExpWithClosingIndex(xmlData, i, closingChar = ">") {
738-
let attrBoundary;
739-
let tagExp = "";
740-
for (let index = i; index < xmlData.length; index++) {
741-
let ch = xmlData[index];
743+
let attrBoundary = 0;
744+
const chars = [];
745+
const len = xmlData.length;
746+
const closeCode0 = closingChar.charCodeAt(0);
747+
const closeCode1 = closingChar.length > 1 ? closingChar.charCodeAt(1) : -1;
748+
749+
for (let index = i; index < len; index++) {
750+
const code = xmlData.charCodeAt(index);
751+
742752
if (attrBoundary) {
743-
if (ch === attrBoundary) attrBoundary = "";//reset
744-
} else if (ch === '"' || ch === "'") {
745-
attrBoundary = ch;
746-
} else if (ch === closingChar[0]) {
747-
if (closingChar[1]) {
748-
if (xmlData[index + 1] === closingChar[1]) {
749-
return {
750-
data: tagExp,
751-
index: index
752-
}
753+
if (code === attrBoundary) attrBoundary = 0;
754+
} else if (code === 34 || code === 39) { // " or '
755+
attrBoundary = code;
756+
} else if (code === closeCode0) {
757+
if (closeCode1 !== -1) {
758+
if (xmlData.charCodeAt(index + 1) === closeCode1) {
759+
return { data: String.fromCharCode(...chars), index };
753760
}
754761
} else {
755-
return {
756-
data: tagExp,
757-
index: index
758-
}
762+
return { data: String.fromCharCode(...chars), index };
759763
}
760-
} else if (ch === '\t') {
761-
ch = " "
764+
} else if (code === 9) { // \t
765+
chars.push(32); // space
766+
continue;
762767
}
763-
tagExp += ch;
768+
769+
chars.push(code);
764770
}
765771
}
766772

@@ -816,7 +822,8 @@ function readStopNodeData(xmlData, tagName, i) {
816822

817823
for (; i < xmlData.length; i++) {
818824
if (xmlData[i] === "<") {
819-
if (xmlData[i + 1] === "/") {//close tag
825+
const c1 = xmlData.charCodeAt(i + 1);
826+
if (c1 === 47) {//close tag '/'
820827
const closeIndex = findClosingIndex(xmlData, ">", i, `${tagName} is not closed`);
821828
let closeTagName = xmlData.substring(i + 2, closeIndex).trim();
822829
if (closeTagName === tagName) {
@@ -829,13 +836,16 @@ function readStopNodeData(xmlData, tagName, i) {
829836
}
830837
}
831838
i = closeIndex;
832-
} else if (xmlData[i + 1] === '?') {
839+
} else if (c1 === 63) { //?
833840
const closeIndex = findClosingIndex(xmlData, "?>", i + 1, "StopNode is not closed.")
834841
i = closeIndex;
835-
} else if (xmlData.substr(i + 1, 3) === '!--') {
842+
} else if (c1 === 33
843+
&& xmlData.charCodeAt(i + 2) === 45
844+
&& xmlData.charCodeAt(i + 3) === 45) { // '!--'
836845
const closeIndex = findClosingIndex(xmlData, "-->", i + 3, "StopNode is not closed.")
837846
i = closeIndex;
838-
} else if (xmlData.substr(i + 1, 2) === '![') {
847+
} else if (c1 === 33
848+
&& xmlData.charCodeAt(i + 2) === 91) { // '!['
839849
const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2;
840850
i = closeIndex;
841851
} else {

0 commit comments

Comments
 (0)