mirror of
https://github.com/antonmedv/fx
synced 2024-11-03 15:40:12 +00:00
Fix bug in stream processor
This commit is contained in:
parent
47b5bb2366
commit
bfb8aa4534
@ -6,7 +6,7 @@ _* Function eXecution_
|
||||
[![Build Status](https://travis-ci.org/antonmedv/fx.svg?branch=master)](https://travis-ci.org/antonmedv/fx)
|
||||
[![Npm Version](https://img.shields.io/npm/v/fx.svg)](https://www.npmjs.com/package/fx)
|
||||
[![Brew Version](https://img.shields.io/homebrew/v/fx.svg)](https://formulae.brew.sh/formula/fx)
|
||||
[![Snap Version](https://img.shields.io/badge/snap-12.0.0-blue.svg)](https://snapcraft.io/fx)
|
||||
[![Snap Version](https://img.shields.io/badge/snap-12.0.2-blue.svg)](https://snapcraft.io/fx)
|
||||
|
||||
Command-line JSON processing tool
|
||||
|
||||
|
74
index.js
74
index.js
@ -14,6 +14,7 @@ try {
|
||||
|
||||
const print = require('./print')
|
||||
const reduce = require('./reduce')
|
||||
const stream = require('./stream')
|
||||
|
||||
const usage = `
|
||||
Usage
|
||||
@ -54,7 +55,7 @@ void function main() {
|
||||
return
|
||||
}
|
||||
|
||||
const reader = stream()
|
||||
const reader = stream(stdin, apply)
|
||||
|
||||
stdin.on('readable', reader.read)
|
||||
stdin.on('end', () => {
|
||||
@ -130,74 +131,3 @@ function select(cb) {
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function stream() {
|
||||
let buff = ''
|
||||
let len = 0
|
||||
let depth = 0
|
||||
let isString = false
|
||||
|
||||
let count = 0
|
||||
let head = ''
|
||||
const check = (i) => {
|
||||
if (depth <= 0) {
|
||||
const input = buff.substring(0, len + i + 1)
|
||||
|
||||
if (count > 0) {
|
||||
if (head !== '') {
|
||||
const json = JSON.parse(head)
|
||||
apply(json)
|
||||
head = ''
|
||||
}
|
||||
|
||||
const json = JSON.parse(input)
|
||||
apply(json)
|
||||
} else {
|
||||
head = input
|
||||
}
|
||||
|
||||
buff = buff.substring(len + i + 1)
|
||||
len = buff.length
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isStream() {
|
||||
return count > 1
|
||||
},
|
||||
value() {
|
||||
return head + buff
|
||||
},
|
||||
read() {
|
||||
let chunk
|
||||
|
||||
while ((chunk = stdin.read())) {
|
||||
len = buff.length
|
||||
buff += chunk
|
||||
|
||||
for (let i = 0; i < chunk.length; i++) {
|
||||
if (isString) {
|
||||
if (chunk[i] === '"') {
|
||||
if ((i === 0 && buff[len - 1] !== '\\') || (i > 0 && chunk[i - 1] !== '\\')) {
|
||||
isString = false
|
||||
check(i)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (chunk[i] === '{' || chunk[i] === '[') {
|
||||
depth++
|
||||
} else if (chunk[i] === '}' || chunk[i] === ']') {
|
||||
depth--
|
||||
check(i)
|
||||
} else if (chunk[i] === '"') {
|
||||
isString = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,8 @@
|
||||
"fx.js",
|
||||
"index.js",
|
||||
"print.js",
|
||||
"reduce.js"
|
||||
"reduce.js",
|
||||
"stream.js"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "ava",
|
||||
|
74
stream.js
Normal file
74
stream.js
Normal file
@ -0,0 +1,74 @@
|
||||
'use strict'
|
||||
|
||||
function stream(from, cb) {
|
||||
let buff = ''
|
||||
let lastChar = ''
|
||||
let len = 0
|
||||
let depth = 0
|
||||
let isString = false
|
||||
|
||||
let count = 0
|
||||
let head = ''
|
||||
const check = (i) => {
|
||||
if (depth <= 0) {
|
||||
const input = buff.substring(0, len + i + 1)
|
||||
|
||||
if (count > 0) {
|
||||
if (head !== '') {
|
||||
const json = JSON.parse(head)
|
||||
cb(json)
|
||||
head = ''
|
||||
}
|
||||
|
||||
const json = JSON.parse(input)
|
||||
cb(json)
|
||||
} else {
|
||||
head = input
|
||||
}
|
||||
|
||||
buff = buff.substring(len + i + 1)
|
||||
len = -i - 1
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isStream() {
|
||||
return count > 1
|
||||
},
|
||||
value() {
|
||||
return head + buff
|
||||
},
|
||||
read() {
|
||||
let chunk
|
||||
|
||||
while ((chunk = from.read())) {
|
||||
len = buff.length
|
||||
buff += chunk
|
||||
|
||||
for (let i = 0; i < chunk.length; i++) {
|
||||
if (isString) {
|
||||
if (chunk[i] === '"' && ((i === 0 && lastChar !== '\\') || (i > 0 && chunk[i - 1] !== '\\'))) {
|
||||
isString = false
|
||||
check(i)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (chunk[i] === '{' || chunk[i] === '[') {
|
||||
depth++
|
||||
} else if (chunk[i] === '}' || chunk[i] === ']') {
|
||||
depth--
|
||||
check(i)
|
||||
} else if (chunk[i] === '"') {
|
||||
isString = true
|
||||
}
|
||||
}
|
||||
|
||||
lastChar = chunk[chunk.length - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = stream
|
28
test.js
28
test.js
@ -1,6 +1,7 @@
|
||||
'use strict'
|
||||
const test = require('ava')
|
||||
const {execSync} = require('child_process')
|
||||
const stream = require('./stream')
|
||||
|
||||
function fx(json, code = '') {
|
||||
return execSync(`echo '${JSON.stringify(json)}' | node index.js ${code}`).toString('utf8')
|
||||
@ -45,3 +46,30 @@ test('file argument', t => {
|
||||
const r = execSync(`node index.js package.json .name`).toString('utf8')
|
||||
t.deepEqual(r, 'fx\n')
|
||||
})
|
||||
|
||||
test('stream', t => {
|
||||
const input = `
|
||||
{"index": 0} {"index": 1}
|
||||
{"index": 2, "quote": "\\""}
|
||||
{"index": 3} "Hello" "world"
|
||||
{"index": 6, "key": "one \\"two\\" three"}
|
||||
`
|
||||
t.plan(7 * (input.length - 1))
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
const parts = [input.substring(0, i), input.substring(i)]
|
||||
|
||||
const reader = stream(
|
||||
{
|
||||
read() {
|
||||
return parts.shift()
|
||||
}
|
||||
},
|
||||
json => {
|
||||
t.pass()
|
||||
}
|
||||
)
|
||||
|
||||
reader.read()
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user