-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparseLengthPrefixed.js
More file actions
78 lines (73 loc) · 2.37 KB
/
parseLengthPrefixed.js
File metadata and controls
78 lines (73 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
const parseLengthPrefixed = (str) => {
const parents = []
let parent = {subvalues: []}, buffer = '', mode = 'SubvalueCount', subvalueCounts = [], subvalueCount = 0, affixLength = 0
for (let i = 0; i < str.length; ++i) {
const c = str[i]
if (mode === 'SubvalueCount') {
if (c === ':') {
if (subvalueCount > 0) subvalueCounts.push(subvalueCount)
subvalueCount = +buffer
buffer = ''
if (subvalueCount > 0) mode = 'PrefixLength'
else mode = 'SuffixLength'
} else if ('0123456789'.includes(c)) buffer += c
else throw Error('expected number')
} else if (mode === 'PrefixLength') {
if (c === ':') {
affixLength = +buffer
buffer = ''
if (affixLength > 0) mode = 'Prefix'
else {
mode = 'SubvalueCount'
}
} else if ('0123456789'.includes(c)) buffer += c
else throw Error('expected number')
} else if (mode === 'Prefix') {
buffer += c
--affixLength
if (affixLength === 0) {
const value = {subvalues: []}
parent.subvalues.push({prefix: buffer, value})
parents.push(parent)
parent = value
buffer = ''
mode = 'SubvalueCount'
}
} else if (mode === 'SuffixLength') {
if (c === ':') {
affixLength = +buffer
buffer = ''
if (affixLength > 0) mode = 'Suffix'
else mode = 'PrefixLength' // or SL if last subvalue
} else if ('0123456789'.includes(c)) buffer += c
else throw Error('expected number')
} else if (mode === 'Suffix') {
buffer += c
--affixLength
if (affixLength === 0) {
parent.suffix = buffer
buffer = ''
if (parents.length < 1) throw Error('Unexpected close!')
parent = parents.pop()
--subvalueCount
if (subvalueCount === 0) mode = 'SuffixLength'
else mode = 'PrefixLength'
}
}
if (c === open) {
const value = {subvalues: []}
parent.subvalues.push({prefix: buffer, value})
parents.push(parent)
parent = value
buffer = ''
} else if (c === close) {
parent.suffix = buffer
buffer = ''
if (parents.length < 1) throw Error('Unexpected close!')
parent = parents.pop()
} else {buffer += c}
}
if (mode !== 'END' || parents.length > 0) throw Error('Unexpected end!')
parent.suffix = buffer
return parent
}