Skip to content

Commit

Permalink
perf: introduce a specialized version of captureWhile
Browse files Browse the repository at this point in the history
captureName performs faster for those cases where we just want to capture the
characters in an XML name.
  • Loading branch information
lddubeau committed Aug 23, 2018
1 parent 97bc5da commit 04855d6
Showing 1 changed file with 32 additions and 34 deletions.
66 changes: 32 additions & 34 deletions lib/saxes.js
Original file line number Diff line number Diff line change
Expand Up @@ -571,12 +571,7 @@ class SaxesParser {
*/

/**
* Capture characters into a buffer while a condition is true. A sequence of
* ``write`` calls may require the capture of text into a buffer as multiple
* "fragments". For instance, given ``write("<x>Multiple")`` and
* ``write("parts</x>")``, the text which is part of the ``x`` element will be
* recorded in two steps: one recording ``"Multiple"`` and one recording
* ``"parts"``. These are two fragments.
* Capture characters into a buffer while a condition is true.
*
* @private
*
Expand Down Expand Up @@ -607,6 +602,35 @@ class SaxesParser {
return undefined;
}

/**
* Capture characters that satisfy ``isNameChar`` into a buffer.
*
* @private
*
* @param {ChunkState} chunkState The current chunk state.
*
* @param {string} buffer The name of the buffer to save into.
*
* @return {string|undefined} The character that made the test fail, or
* ``undefined`` if we hit the end of the chunk.
*/
captureName(chunkState, buffer) {
const { limit, chunk, i: start } = chunkState;
while (chunkState.i < limit) {
const c = this.getCode(chunkState);
if (!isNameChar(c)) {
// This is faster than adding codepoints one by one.
this[buffer] += chunk.substring(start,
chunkState.i - (c <= 0xFFFF ? 1 : 2));
return c;
}
}

// This is faster than adding codepoints one by one.
this[buffer] += chunk.substring(start);
return undefined;
}

/**
* Skip characters while a condition is true.
*
Expand Down Expand Up @@ -1223,20 +1247,7 @@ class SaxesParser {
sOpenTag(chunkState) {
// We don't need to check with isNameStartChar here because the first
// character of tagName is fed elsewhere, and the check is done there.
const c = this.captureWhile(
chunkState,
(cx) => {
if (cx !== GREATER && !isS(cx) && cx !== FORWARD_SLASH) {
if (!isNameChar(cx)) {
this.fail("disallowed character in tag name.");
}

return true;
}

return false;
},
"tagName");
const c = this.captureName(chunkState, "tagName");
if (!c) {
return;
}
Expand Down Expand Up @@ -1305,20 +1316,7 @@ class SaxesParser {
sAttribName(chunkState) {
// We don't need to check with isNameStartChar here because the first
// character of attribute is fed elsewhere, and the check is done there.
const c = this.captureWhile(
chunkState,
(cx) => {
if (cx !== EQUAL && !isS(cx) && cx !== GREATER) {
if (!isNameChar(cx)) {
this.fail("disallowed characer in attribute name.");
}

return true;
}

return false;
},
"attribName");
const c = this.captureName(chunkState, "attribName");
if (c === EQUAL) {
this.state = S_ATTRIB_VALUE;
}
Expand Down

0 comments on commit 04855d6

Please sign in to comment.