Skip to content

Commit

Permalink
Converted from a generator to many() for perf.
Browse files Browse the repository at this point in the history
  • Loading branch information
uhop committed Oct 25, 2024
1 parent ebbb22d commit 11c2b3c
Showing 1 changed file with 42 additions and 41 deletions.
83 changes: 42 additions & 41 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

'use strict';

const {flushable, gen, none} = require('stream-chain');
const {flushable, gen, many, none} = require('stream-chain');
const fixUtf8Stream = require('stream-chain/utils/fixUtf8Stream.js');

const patterns = {
Expand Down Expand Up @@ -59,24 +59,27 @@ const jsonParser = options => {

let done = false,
expect = jsonStreaming ? 'done' : 'value',
stack = [],
parent = '',
openNumber = false,
accumulator = '',
buffer = '';

return flushable(function* (buf) {
const stack = [];

return flushable(buf => {
const tokens = [];

if (buf === none) {
done = true;
if (openNumber) {
if (streamNumbers) yield {name: 'endNumber'};
if (streamNumbers) tokens.push( {name: 'endNumber'});
openNumber = false;
if (packNumbers) {
yield {name: 'numberValue', value: accumulator};
tokens.push( {name: 'numberValue', value: accumulator});
accumulator = '';
}
}
return;
return tokens.length ? many(tokens) : none;
}

buffer += buf;
Expand All @@ -101,49 +104,47 @@ const jsonParser = options => {
value = match[0];
switch (value) {
case '"':
if (streamStrings) yield {name: 'startString'};
if (streamStrings) tokens.push( {name: 'startString'});
expect = 'string';
break;
case '{':
yield {name: 'startObject'};
tokens.push( {name: 'startObject'});
stack.push(parent);
parent = 'object';
expect = 'key1';
break;
case '[':
yield {name: 'startArray'};
tokens.push( {name: 'startArray'});
stack.push(parent);
parent = 'array';
expect = 'value1';
break;
case ']':
if (expect !== 'value1') throw new Error("Parser cannot parse input: unexpected token ']'");
if (openNumber) {
if (streamNumbers) yield {name: 'endNumber'};
if (streamNumbers) tokens.push( {name: 'endNumber'});
openNumber = false;
if (packNumbers) {
yield {name: 'numberValue', value: accumulator};
tokens.push( {name: 'numberValue', value: accumulator});
accumulator = '';
}
}
yield {name: 'endArray'};
tokens.push( {name: 'endArray'});
parent = stack.pop();
expect = expected[parent];
break;
case '-':
openNumber = true;
if (streamNumbers) {
yield {name: 'startNumber'};
yield {name: 'numberChunk', value: '-'};
tokens.push( {name: 'startNumber'},{name: 'numberChunk', value: '-'});
}
packNumbers && (accumulator = '-');
expect = 'numberStart';
break;
case '0':
openNumber = true;
if (streamNumbers) {
yield {name: 'startNumber'};
yield {name: 'numberChunk', value: '0'};
tokens.push( {name: 'startNumber'},{name: 'numberChunk', value: '0'});
}
packNumbers && (accumulator = '0');
expect = 'numberFraction';
Expand All @@ -159,8 +160,7 @@ const jsonParser = options => {
case '9':
openNumber = true;
if (streamNumbers) {
yield {name: 'startNumber'};
yield {name: 'numberChunk', value: value};
tokens.push( {name: 'startNumber'}, {name: 'numberChunk', value: value});
}
packNumbers && (accumulator = value);
expect = 'numberDigit';
Expand All @@ -169,7 +169,7 @@ const jsonParser = options => {
case 'false':
case 'null':
if (buffer.length - index === value.length && !done) break main; // wait for more input
yield {name: value + 'Value', value: values[value]};
tokens.push( {name: value + 'Value', value: values[value]});
expect = expected[parent];
break;
// default: // ws
Expand All @@ -188,31 +188,31 @@ const jsonParser = options => {
value = match[0];
if (value === '"') {
if (expect === 'keyVal') {
if (streamKeys) yield {name: 'endKey'};
if (streamKeys) tokens.push( {name: 'endKey'});
if (packKeys) {
yield {name: 'keyValue', value: accumulator};
tokens.push( {name: 'keyValue', value: accumulator});
accumulator = '';
}
expect = 'colon';
} else {
if (streamStrings) yield {name: 'endString'};
if (streamStrings) tokens.push( {name: 'endString'});
if (packStrings) {
yield {name: 'stringValue', value: accumulator};
tokens.push( {name: 'stringValue', value: accumulator});
accumulator = '';
}
expect = expected[parent];
}
} else if (value.length > 1 && value.charAt(0) === '\\') {
const t = value.length == 2 ? codes[value.charAt(1)] : fromHex(value);
if (expect === 'keyVal' ? streamKeys : streamStrings) {
yield {name: 'stringChunk', value: t};
tokens.push( {name: 'stringChunk', value: t});
}
if (expect === 'keyVal' ? packKeys : packStrings) {
accumulator += t;
}
} else {
if (expect === 'keyVal' ? streamKeys : streamStrings) {
yield {name: 'stringChunk', value: value};
tokens.push( {name: 'stringChunk', value: value});
}
if (expect === 'keyVal' ? packKeys : packStrings) {
accumulator += value;
Expand All @@ -230,11 +230,11 @@ const jsonParser = options => {
}
value = match[0];
if (value === '"') {
if (streamKeys) yield {name: 'startKey'};
if (streamKeys) tokens.push( {name: 'startKey'});
expect = 'keyVal';
} else if (value === '}') {
if (expect !== 'key1') throw new Error("Parser cannot parse input: unexpected token '}'");
yield {name: 'endObject'};
tokens.push( {name: 'endObject'});
parent = stack.pop();
expect = expected[parent];
}
Expand All @@ -260,10 +260,10 @@ const jsonParser = options => {
break main; // wait for more input
}
if (openNumber) {
if (streamNumbers) yield {name: 'endNumber'};
if (streamNumbers) tokens.push( {name: 'endNumber'});
openNumber = false;
if (packNumbers) {
yield {name: 'numberValue', value: accumulator};
tokens.push( {name: 'numberValue', value: accumulator});
accumulator = '';
}
}
Expand All @@ -274,7 +274,7 @@ const jsonParser = options => {
if (value === '}' ? expect === 'arrayStop' : expect !== 'arrayStop') {
throw new Error("Parser cannot parse input: expected '" + (expect === 'arrayStop' ? ']' : '}') + "'");
}
yield {name: value === '}' ? 'endObject' : 'endArray'};
tokens.push( {name: value === '}' ? 'endObject' : 'endArray'});
parent = stack.pop();
expect = expected[parent];
}
Expand All @@ -289,7 +289,7 @@ const jsonParser = options => {
break main; // wait for more input
}
value = match[0];
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
expect = value === '0' ? 'numberFraction' : 'numberDigit';
index += value.length;
Expand All @@ -303,7 +303,7 @@ const jsonParser = options => {
}
value = match[0];
if (value) {
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
index += value.length;
} else {
Expand All @@ -329,7 +329,7 @@ const jsonParser = options => {
break main; // wait for more input
}
value = match[0];
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
expect = value === '.' ? 'numberFracStart' : 'numberExpSign';
index += value.length;
Expand All @@ -342,7 +342,7 @@ const jsonParser = options => {
break main; // wait for more input
}
value = match[0];
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
expect = 'numberFracDigit';
index += value.length;
Expand All @@ -352,7 +352,7 @@ const jsonParser = options => {
match = patterns.numberFracDigit.exec(buffer);
value = match[0];
if (value) {
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
index += value.length;
} else {
Expand Down Expand Up @@ -382,7 +382,7 @@ const jsonParser = options => {
break main; // wait for more input
}
value = match[0];
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
expect = 'numberExpSign';
index += value.length;
Expand All @@ -399,7 +399,7 @@ const jsonParser = options => {
break main; // wait for more input
}
value = match[0];
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
expect = 'numberExpStart';
index += value.length;
Expand All @@ -412,7 +412,7 @@ const jsonParser = options => {
break main; // wait for more input
}
value = match[0];
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
expect = 'numberExpDigit';
index += value.length;
Expand All @@ -422,7 +422,7 @@ const jsonParser = options => {
match = patterns.numberExpDigit.exec(buffer);
value = match[0];
if (value) {
if (streamNumbers) yield {name: 'numberChunk', value: value};
if (streamNumbers) tokens.push( {name: 'numberChunk', value: value});
packNumbers && (accumulator += value);
index += value.length;
} else {
Expand All @@ -448,10 +448,10 @@ const jsonParser = options => {
}
value = match[0];
if (openNumber) {
if (streamNumbers) yield {name: 'endNumber'};
if (streamNumbers) tokens.push( {name: 'endNumber'});
openNumber = false;
if (packNumbers) {
yield {name: 'numberValue', value: accumulator};
tokens.push( {name: 'numberValue', value: accumulator});
accumulator = '';
}
}
Expand All @@ -460,6 +460,7 @@ const jsonParser = options => {
}
}
buffer = buffer.slice(index);
return tokens.length ? many(tokens) : none;
});
};

Expand Down

0 comments on commit 11c2b3c

Please sign in to comment.