You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
3.8 KiB
JavaScript
189 lines
3.8 KiB
JavaScript
var Parser = require('jsonparse')
|
|
, Stream = require('stream').Stream
|
|
, through = require('through')
|
|
|
|
/*
|
|
|
|
the value of this.stack that creationix's jsonparse has is weird.
|
|
|
|
it makes this code ugly, but his problem is way harder that mine,
|
|
so i'll forgive him.
|
|
|
|
*/
|
|
|
|
exports.parse = function (path) {
|
|
|
|
var parser = new Parser()
|
|
var stream = through(function (chunk) {
|
|
if('string' === typeof chunk) {
|
|
if (process.browser) {
|
|
var buf = new Array(chunk.length)
|
|
for (var i = 0; i < chunk.length; i++) buf[i] = chunk.charCodeAt(i)
|
|
chunk = new Int32Array(buf)
|
|
} else {
|
|
chunk = new Buffer(chunk)
|
|
}
|
|
}
|
|
parser.write(chunk)
|
|
},
|
|
function (data) {
|
|
if(data)
|
|
stream.write(data)
|
|
stream.queue(null)
|
|
})
|
|
|
|
if('string' === typeof path)
|
|
path = path.split('.').map(function (e) {
|
|
if (e === '*')
|
|
return true
|
|
else if (e === '') // '..'.split('.') returns an empty string
|
|
return {recurse: true}
|
|
else
|
|
return e
|
|
})
|
|
|
|
|
|
var count = 0, _key
|
|
if(!path || !path.length)
|
|
path = null
|
|
|
|
parser.onValue = function () {
|
|
if (!this.root && this.stack.length == 1)
|
|
stream.root = this.value
|
|
|
|
if(! path) return
|
|
|
|
var i = 0 // iterates on path
|
|
var j = 0 // iterates on stack
|
|
while (i < path.length) {
|
|
var key = path[i]
|
|
var c
|
|
j++
|
|
|
|
if (key && !key.recurse) {
|
|
c = (j === this.stack.length) ? this : this.stack[j]
|
|
if (!c) return
|
|
if (! check(key, c.key)) return
|
|
i++
|
|
} else {
|
|
i++
|
|
var nextKey = path[i]
|
|
if (! nextKey) return
|
|
while (true) {
|
|
c = (j === this.stack.length) ? this : this.stack[j]
|
|
if (!c) return
|
|
if (check(nextKey, c.key)) { i++; break}
|
|
j++
|
|
}
|
|
}
|
|
}
|
|
if (j !== this.stack.length) return
|
|
|
|
count ++
|
|
if(null != this.value[this.key])
|
|
stream.queue(this.value[this.key])
|
|
delete this.value[this.key]
|
|
}
|
|
parser._onToken = parser.onToken;
|
|
|
|
parser.onToken = function (token, value) {
|
|
parser._onToken(token, value);
|
|
if (this.stack.length === 0) {
|
|
if (stream.root) {
|
|
if(!path)
|
|
stream.queue(stream.root)
|
|
stream.emit('root', stream.root, count)
|
|
count = 0;
|
|
stream.root = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
parser.onError = function (err) {
|
|
stream.emit('error', err)
|
|
}
|
|
|
|
|
|
return stream
|
|
}
|
|
|
|
function check (x, y) {
|
|
if ('string' === typeof x)
|
|
return y == x
|
|
else if (x && 'function' === typeof x.exec)
|
|
return x.exec(y)
|
|
else if ('boolean' === typeof x)
|
|
return x
|
|
else if ('function' === typeof x)
|
|
return x(y)
|
|
return false
|
|
}
|
|
|
|
exports.stringify = function (op, sep, cl) {
|
|
if (op === false){
|
|
op = ''
|
|
sep = '\n'
|
|
cl = ''
|
|
} else if (op == null) {
|
|
|
|
op = '[\n'
|
|
sep = '\n,\n'
|
|
cl = '\n]\n'
|
|
|
|
}
|
|
|
|
//else, what ever you like
|
|
|
|
var stream
|
|
, first = true
|
|
, anyData = false
|
|
stream = through(function (data) {
|
|
anyData = true
|
|
var json = JSON.stringify(data)
|
|
if(first) { first = false ; stream.queue(op + json)}
|
|
else stream.queue(sep + json)
|
|
},
|
|
function (data) {
|
|
if(!anyData)
|
|
stream.queue(op)
|
|
stream.queue(cl)
|
|
stream.queue(null)
|
|
})
|
|
|
|
return stream
|
|
}
|
|
|
|
exports.stringifyObject = function (op, sep, cl) {
|
|
if (op === false){
|
|
op = ''
|
|
sep = '\n'
|
|
cl = ''
|
|
} else if (op == null) {
|
|
|
|
op = '{\n'
|
|
sep = '\n,\n'
|
|
cl = '\n}\n'
|
|
|
|
}
|
|
|
|
//else, what ever you like
|
|
|
|
var stream = new Stream ()
|
|
, first = true
|
|
, anyData = false
|
|
stream = through(function (data) {
|
|
anyData = true
|
|
var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1])
|
|
if(first) { first = false ; stream.queue(op + json)}
|
|
else stream.queue(sep + json)
|
|
},
|
|
function (data) {
|
|
if(!anyData) stream.queue(op)
|
|
stream.queue(cl)
|
|
|
|
stream.queue(null)
|
|
})
|
|
|
|
return stream
|
|
}
|