kopia lustrzana https://github.com/backface/turtlestitch
Speed up parser
About an order of magnitude faster (268.5 ms => 31.3 ms).pull/3/merge
rodzic
e1b104948b
commit
6fbd2f2789
119
xml.js
119
xml.js
|
@ -61,7 +61,7 @@
|
|||
|
||||
*/
|
||||
|
||||
/*global modules, isString, detect, Node, isNil*/
|
||||
/*global modules, detect, Node, isNil*/
|
||||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -85,7 +85,8 @@ function ReadStream(arrayOrString) {
|
|||
|
||||
// ReadStream constants:
|
||||
|
||||
ReadStream.prototype.space = /[\s]/;
|
||||
ReadStream.prototype.nonSpace = /\S|$/g;
|
||||
ReadStream.prototype.nonWord = /[\s\>\/\=]|$/g;
|
||||
|
||||
// ReadStream accessing:
|
||||
|
||||
|
@ -115,46 +116,26 @@ ReadStream.prototype.atEnd = function () {
|
|||
|
||||
// ReadStream accessing String contents:
|
||||
|
||||
ReadStream.prototype.upTo = function (regex) {
|
||||
var i, start;
|
||||
if (!isString(this.contents)) {return ''; }
|
||||
i = this.contents.substr(this.index).search(regex);
|
||||
if (i === -1) {
|
||||
return '';
|
||||
}
|
||||
start = this.index;
|
||||
this.index += i;
|
||||
return this.contents.substring(start, this.index);
|
||||
ReadStream.prototype.upTo = function (str) {
|
||||
var i = this.contents.indexOf(str, this.index);
|
||||
return i === -1 ? '' : this.contents.slice(this.index, this.index = i);
|
||||
};
|
||||
|
||||
ReadStream.prototype.peekUpTo = function (regex) {
|
||||
if (!isString(this.contents)) {return ''; }
|
||||
var i = this.contents.substr(this.index).search(regex);
|
||||
if (i === -1) {
|
||||
return '';
|
||||
}
|
||||
return this.contents.substring(this.index, this.index + i);
|
||||
ReadStream.prototype.peekUpTo = function (str) {
|
||||
var i = this.contents.indexOf(str, this.index);
|
||||
return i === -1 ? '' : this.contents.slice(this.index, i);
|
||||
};
|
||||
|
||||
ReadStream.prototype.skipSpace = function () {
|
||||
if (!isString(this.contents)) {return ''; }
|
||||
var ch = this.peek();
|
||||
while (this.space.test(ch) && ch !== '') {
|
||||
this.skip();
|
||||
ch = this.peek();
|
||||
}
|
||||
this.nonSpace.lastIndex = this.index;
|
||||
var result = this.nonSpace.exec(this.contents);
|
||||
if (result) this.index = result.index;
|
||||
};
|
||||
|
||||
ReadStream.prototype.word = function () {
|
||||
var i, start;
|
||||
if (!isString(this.contents)) {return ''; }
|
||||
i = this.contents.substr(this.index).search(/[\s\>\/\=]|$/);
|
||||
if (i === -1) {
|
||||
return '';
|
||||
}
|
||||
start = this.index;
|
||||
this.index += i;
|
||||
return this.contents.substring(start, this.index);
|
||||
this.nonWord.lastIndex = this.index;
|
||||
var result = this.nonWord.exec(this.contents);
|
||||
return result ? this.contents.slice(this.index, this.index = result.index) : '';
|
||||
};
|
||||
|
||||
// XML_Element ///////////////////////////////////////////////////////////
|
||||
|
@ -190,9 +171,7 @@ XML_Element.prototype.init = function (tag, contents, parent) {
|
|||
XML_Element.uber.init.call(this);
|
||||
|
||||
// override inherited properties
|
||||
if (parent instanceof XML_Element) {
|
||||
parent.addChild(this);
|
||||
}
|
||||
if (parent) parent.addChild(this);
|
||||
};
|
||||
|
||||
// XML_Element DOM navigation: (aside from what's inherited from Node)
|
||||
|
@ -318,51 +297,18 @@ XML_Element.prototype.escape = function (string, ignoreQuotes) {
|
|||
};
|
||||
|
||||
XML_Element.prototype.unescape = function (string) {
|
||||
var stream = new ReadStream(string),
|
||||
result = '',
|
||||
ch,
|
||||
esc;
|
||||
|
||||
function nextPut(str) {
|
||||
result += str;
|
||||
stream.upTo(';');
|
||||
stream.skip();
|
||||
}
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
ch = stream.next();
|
||||
if (ch === '&') {
|
||||
esc = stream.peekUpTo(';');
|
||||
switch (esc) {
|
||||
case 'apos':
|
||||
nextPut('\'');
|
||||
break;
|
||||
case 'quot':
|
||||
nextPut('\"');
|
||||
break;
|
||||
case 'lt':
|
||||
nextPut('<');
|
||||
break;
|
||||
case 'gt':
|
||||
nextPut('>');
|
||||
break;
|
||||
case 'amp':
|
||||
nextPut('&');
|
||||
break;
|
||||
case '#xD':
|
||||
nextPut('\n');
|
||||
break;
|
||||
case '#126':
|
||||
nextPut('~');
|
||||
break;
|
||||
default:
|
||||
result += ch;
|
||||
}
|
||||
} else {
|
||||
result += ch;
|
||||
return string.replace(/&(amp|apos|quot|lt|gt|#xD|#126);/g, function(_, name) {
|
||||
switch (name) {
|
||||
case 'amp': return '&';
|
||||
case 'apos': return '\'';
|
||||
case 'quot': return '"';
|
||||
case 'lt': return '<';
|
||||
case 'gt': return '>';
|
||||
case '#xD': return '\n';
|
||||
case '#126': return '~';
|
||||
default: console.warn('unreachable');
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
};
|
||||
|
||||
// XML_Element parsing:
|
||||
|
@ -375,10 +321,7 @@ XML_Element.prototype.parseString = function (string) {
|
|||
};
|
||||
|
||||
XML_Element.prototype.parseStream = function (stream) {
|
||||
var key,
|
||||
value,
|
||||
ch,
|
||||
child;
|
||||
var key, value, ch, child;
|
||||
|
||||
// tag:
|
||||
this.tag = stream.word();
|
||||
|
@ -395,9 +338,7 @@ XML_Element.prototype.parseStream = function (stream) {
|
|||
stream.skipSpace();
|
||||
ch = stream.next();
|
||||
if (ch !== '"' && ch !== "'") {
|
||||
throw new Error(
|
||||
'Expected single- or double-quoted attribute value'
|
||||
);
|
||||
throw new Error('Expected single- or double-quoted attribute value');
|
||||
}
|
||||
value = stream.upTo(ch);
|
||||
stream.skip(1);
|
||||
|
@ -407,7 +348,7 @@ XML_Element.prototype.parseStream = function (stream) {
|
|||
}
|
||||
|
||||
// empty tag:
|
||||
if (stream.peek() === '/') {
|
||||
if (ch === '/') {
|
||||
stream.skip();
|
||||
if (stream.next() !== '>') {
|
||||
throw new Error('Expected ">" after "/" in empty tag');
|
||||
|
|
Ładowanie…
Reference in New Issue