1 | #! /usr/bin/env node
|
2 |
|
3 | var Parser = require('jsonparse')
|
4 | , through = require('through')
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | exports.parse = function (path, map) {
|
16 |
|
17 | var parser = new Parser()
|
18 | var stream = through(function (chunk) {
|
19 | if('string' === typeof chunk)
|
20 | chunk = new Buffer(chunk)
|
21 | parser.write(chunk)
|
22 | },
|
23 | function (data) {
|
24 | if(data)
|
25 | stream.write(data)
|
26 | stream.queue(null)
|
27 | })
|
28 |
|
29 | if('string' === typeof path)
|
30 | path = path.split('.').map(function (e) {
|
31 | if (e === '*')
|
32 | return true
|
33 | else if (e === '')
|
34 | return {recurse: true}
|
35 | else
|
36 | return e
|
37 | })
|
38 |
|
39 |
|
40 | var count = 0, _key
|
41 | if(!path || !path.length)
|
42 | path = null
|
43 |
|
44 | parser.onValue = function () {
|
45 | if (!this.root && this.stack.length == 1)
|
46 | stream.root = this.value
|
47 |
|
48 | if(! path) return
|
49 |
|
50 | var i = 0
|
51 | var j = 0
|
52 | while (i < path.length) {
|
53 | var key = path[i]
|
54 | var c
|
55 | j++
|
56 |
|
57 | if (key && !key.recurse) {
|
58 | c = (j === this.stack.length) ? this : this.stack[j]
|
59 | if (!c) return
|
60 | if (! check(key, c.key)) return
|
61 | i++
|
62 | } else {
|
63 | i++
|
64 | var nextKey = path[i]
|
65 | if (! nextKey) return
|
66 | while (true) {
|
67 | c = (j === this.stack.length) ? this : this.stack[j]
|
68 | if (!c) return
|
69 | if (check(nextKey, c.key)) { i++; break}
|
70 | j++
|
71 | }
|
72 | }
|
73 | }
|
74 | if (j !== this.stack.length) return
|
75 |
|
76 | count ++
|
77 | var data = this.value[this.key]
|
78 | if(null != data)
|
79 | if(null != (data = map ? map(data) : data))
|
80 | stream.queue(data)
|
81 | delete this.value[this.key]
|
82 | }
|
83 | parser._onToken = parser.onToken;
|
84 |
|
85 | parser.onToken = function (token, value) {
|
86 | parser._onToken(token, value);
|
87 | if (this.stack.length === 0) {
|
88 | if (stream.root) {
|
89 | if(!path)
|
90 | stream.queue(stream.root)
|
91 | stream.emit('root', stream.root, count)
|
92 | count = 0;
|
93 | stream.root = null;
|
94 | }
|
95 | }
|
96 | }
|
97 |
|
98 | parser.onError = function (err) {
|
99 | stream.emit('error', err)
|
100 | }
|
101 |
|
102 |
|
103 | return stream
|
104 | }
|
105 |
|
106 | function check (x, y) {
|
107 | if ('string' === typeof x)
|
108 | return y == x
|
109 | else if (x && 'function' === typeof x.exec)
|
110 | return x.exec(y)
|
111 | else if ('boolean' === typeof x)
|
112 | return x
|
113 | else if ('function' === typeof x)
|
114 | return x(y)
|
115 | return false
|
116 | }
|
117 |
|
118 | exports.stringify = function (op, sep, cl, indent) {
|
119 | indent = indent || 0
|
120 | if (op === false){
|
121 | op = ''
|
122 | sep = '\n'
|
123 | cl = ''
|
124 | } else if (op == null) {
|
125 |
|
126 | op = '[\n'
|
127 | sep = '\n,\n'
|
128 | cl = '\n]\n'
|
129 |
|
130 | }
|
131 |
|
132 |
|
133 |
|
134 | var stream
|
135 | , first = true
|
136 | , anyData = false
|
137 | stream = through(function (data) {
|
138 | anyData = true
|
139 | var json = JSON.stringify(data, null, indent)
|
140 | if(first) { first = false ; stream.queue(op + json)}
|
141 | else stream.queue(sep + json)
|
142 | },
|
143 | function (data) {
|
144 | if(!anyData)
|
145 | stream.queue(op)
|
146 | stream.queue(cl)
|
147 | stream.queue(null)
|
148 | })
|
149 |
|
150 | return stream
|
151 | }
|
152 |
|
153 | exports.stringifyObject = function (op, sep, cl, indent) {
|
154 | indent = indent || 0
|
155 | if (op === false){
|
156 | op = ''
|
157 | sep = '\n'
|
158 | cl = ''
|
159 | } else if (op == null) {
|
160 |
|
161 | op = '{\n'
|
162 | sep = '\n,\n'
|
163 | cl = '\n}\n'
|
164 |
|
165 | }
|
166 |
|
167 |
|
168 |
|
169 | var first = true
|
170 | , anyData = false
|
171 | stream = through(function (data) {
|
172 | anyData = true
|
173 | var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1], null, indent)
|
174 | if(first) { first = false ; this.queue(op + json)}
|
175 | else this.queue(sep + json)
|
176 | },
|
177 | function (data) {
|
178 | if(!anyData) this.queue(op)
|
179 | this.queue(cl)
|
180 |
|
181 | this.queue(null)
|
182 | })
|
183 |
|
184 | return stream
|
185 | }
|
186 |
|
187 | if(!module.parent && process.title !== 'browser') {
|
188 | process.stdin
|
189 | .pipe(exports.parse(process.argv[2]))
|
190 | .pipe(exports.stringify('[', ',\n', ']\n', 2))
|
191 | .pipe(process.stdout)
|
192 | }
|