|
4 | 4 |
|
5 | 5 | const {many, none} = require('stream-chain');
|
6 | 6 |
|
7 |
| -const filterBase = require('./filter-base.js'); |
| 7 | +const {filterBase, makeStackDiffer} = require('./filter-base.js'); |
8 | 8 | const withParser = require('../utils/with-parser.js');
|
9 | 9 |
|
10 | 10 | const filter = options => {
|
11 |
| - const specialAction = options?.acceptObjects ? 'accept' : 'accept-token'; |
12 |
| - let previousStack = []; |
| 11 | + const specialAction = options?.acceptObjects ? 'accept' : 'accept-token', |
| 12 | + stackDiffer = makeStackDiffer(); |
13 | 13 | return filterBase({
|
14 | 14 | specialAction,
|
15 | 15 | transition(stack, chunk, _action, options) {
|
16 |
| - const returnTokens = []; |
17 |
| - |
18 |
| - // find the common part |
19 |
| - let commonLength = 0; |
20 |
| - for (const n = Math.min(stack.length, previousStack.length); commonLength < n && stack[commonLength] === previousStack[commonLength]; ++commonLength); |
21 |
| - |
22 |
| - // close old objects |
23 |
| - for (let i = previousStack.length - 1; i > commonLength; --i) { |
24 |
| - returnTokens.push({name: typeof previousStack[i] == 'number' ? 'endArray' : 'endObject'}); |
25 |
| - } |
26 |
| - |
27 |
| - // update the index |
28 |
| - if (commonLength < previousStack.length) { |
29 |
| - if (commonLength < stack.length) { |
30 |
| - const key = stack[commonLength]; |
31 |
| - if (typeof key == 'string') { |
32 |
| - if (options?.streamKeys) { |
33 |
| - returnTokens.push({name: 'startKey'}, {name: 'stringChunk', value: key}, {name: 'endKey'}); |
34 |
| - } |
35 |
| - if (options?.packKeys || !options?.streamKeys) { |
36 |
| - returnTokens.push({name: 'keyValue', value: key}); |
37 |
| - } |
38 |
| - } else if (typeof key == 'number' && options?.skippedArrayValue) { |
39 |
| - for (let i = Math.max(0, previousStack[commonLength] + 1); i < key; ++i) { |
40 |
| - returnTokens.push(...options.skippedArrayValue); |
41 |
| - } |
42 |
| - } |
43 |
| - previousStack[commonLength] = key; |
44 |
| - ++commonLength; |
45 |
| - } else { |
46 |
| - returnTokens.push({name: typeof previousStack[commonLength] == 'number' ? 'endArray' : 'endObject'}); |
47 |
| - } |
48 |
| - } |
49 |
| - |
50 |
| - // remove old elements |
51 |
| - previousStack.splice(commonLength); |
52 |
| - |
53 |
| - // open new objects |
54 |
| - for (let i = commonLength; i < stack.length; ++i) { |
55 |
| - const key = stack[i]; |
56 |
| - previousStack.push(key); |
57 |
| - if (typeof key == 'number') { |
58 |
| - if (key >= 0) { |
59 |
| - returnTokens.push({name: 'startArray'}); |
60 |
| - if (options?.skippedArrayValue) { |
61 |
| - for (let j = 0; j < key; ++j) { |
62 |
| - returnTokens.push(...options.skippedArrayValue); |
63 |
| - } |
64 |
| - } |
65 |
| - } |
66 |
| - } else if (typeof key == 'string') { |
67 |
| - returnTokens.push({name: 'startObject'}); |
68 |
| - if (options?.streamKeys) { |
69 |
| - returnTokens.push({name: 'startKey'}, {name: 'stringChunk', value: key}, {name: 'endKey'}); |
70 |
| - } |
71 |
| - if (options?.packKeys || !options?.streamKeys) { |
72 |
| - returnTokens.push({name: 'keyValue', value: key}); |
73 |
| - } |
74 |
| - } |
75 |
| - } |
76 |
| - |
77 |
| - // save the stack |
78 |
| - switch (chunk?.name) { |
79 |
| - case 'startObject': |
80 |
| - previousStack.push(null); |
81 |
| - break; |
82 |
| - case 'startArray': |
83 |
| - previousStack.push(-1); |
84 |
| - break; |
85 |
| - } |
86 |
| - |
87 |
| - return many(returnTokens); |
| 16 | + return stackDiffer(stack, chunk, options); |
88 | 17 | }
|
89 | 18 | })(options);
|
90 | 19 | };
|
|
0 commit comments