This repository has been archived by the owner on Jun 24, 2019. It is now read-only.
forked from rossengeorgiev/vdf-parser
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
139 lines (110 loc) · 3 KB
/
index.js
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// a simple parser for Valve's KeyValue format
// https://developer.valvesoftware.com/wiki/KeyValues
//
// author: Rossen Popov, 2014-2016
// contributor: Tom Shaver, 2017
function parse (text) {
if (typeof text !== 'string') {
throw new TypeError('VDF.parse: Expecting parameter to be a string')
}
var lines = text.split('\n')
var obj = {}
var stack = [obj]
var expectBracket = false
var line = ''
var m = ''
var reKV = new RegExp(
'^("((?:\\\\.|[^\\\\"])+)"|([a-z0-9\\-\\_]+))' +
'([ \t]*(' +
'"((?:\\\\.|[^\\\\"])*)(")?' +
'|([a-z0-9\\-\\_]+)' +
'))?'
)
var i = 0
var j = lines.length
for (; i < j; i++) {
line = lines[i].trim()
// skip empty and comment lines
if (line === '' || line[0] === '/') {
continue
}
// one level deeper
if (line[0] === '{') {
expectBracket = false
continue
}
if (expectBracket) {
throw new SyntaxError('VDF.parse: expected bracket on line ' + (i + 1))
}
// one level back
if (line[ 0 ] === '}') {
stack.pop()
continue
}
let done = false
// parse keyvalue pairs
while (!done) {
m = reKV.exec(line)
if (m === null) {
throw new SyntaxError('VDF.parse: invalid syntax on line ' + (i + 1))
}
// qkey = 2
// key = 3
// qval = 6
// vq_end = 7
// val = 8
var key = (typeof m[ 2 ] !== 'undefined') ? m[ 2 ] : m[ 3 ]
var val = (typeof m[ 6 ] !== 'undefined') ? m[ 6 ] : m[ 8 ]
if (typeof val === 'undefined') {
// chain (merge) duplicate key
if (!stack[stack.length - 1][ key ]) {
stack[stack.length - 1][ key ] = {}
}
stack.push(stack[stack.length - 1][ key ])
expectBracket = true
} else {
if (!m[ 7 ] && !m[ 8 ]) {
line += '\n' + lines[ ++i ]
continue
}
stack[stack.length - 1][ key ] = val
}
done = true
}
}
if (stack.length !== 1) {
throw new SyntaxError('VDF.parse: open parentheses somewhere')
}
return obj
}
function _dump (obj, pretty, level) {
if (typeof obj !== 'object') {
throw new TypeError('VDF.stringify: a key has value of type other than string or object')
}
var indent = '\t'
var buf = ''
var lineIndent = ''
if (pretty) {
for (var i = 0; i < level; i++) {
lineIndent += indent
}
}
for (let key in obj) {
if (typeof obj[ key ] === 'object') {
buf += [lineIndent, '"', key, '"\n', lineIndent, '{\n', _dump(obj[key], pretty, level + 1), lineIndent, '}\n'].join('')
} else {
buf += [lineIndent, '"', key, '"', indent, indent, '"', String(obj[ key ]), '"\n'].join('')
}
}
return buf
}
function stringify (obj, pretty) {
if (typeof obj !== 'object') {
throw new TypeError('VDF.stringify: First input parameter is not an object')
}
pretty = (typeof pretty === 'boolean' && pretty)
return _dump(obj, pretty, 0)
}
exports.parse = parse
exports.dump = stringify
exports.stringify = stringify