forked from fluffy-mods/vdf-parser
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
133 lines (105 loc) · 3.35 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
// a simple parser for Valve's KeyValue format
// https://developer.valvesoftware.com/wiki/KeyValues
//
// author: Rossen Popov, 2014-2016
function parse(text) {
if(typeof text != "string") {
throw new TypeError("VDF.parse: Expecting parameter to be a string");
}
lines = text.split("\n");
var obj = {};
var stack = [obj];
var expect_bracket = false;
var name = "";
var re_kv = new RegExp(
'^("((?:\\\\.|[^\\\\"])+)"|([a-z0-9\\-\\_]+))' +
'([ \t]*(' +
'"((?:\\\\.|[^\\\\"])*)(")?' +
'|([a-z0-9\\-\\_]+)' +
'))?'
);
var i = 0, 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] == "{" ) {
expect_bracket = false;
continue;
}
if(expect_bracket) {
throw new SyntaxError("VDF.parse: invalid syntax on line " + (i+1));
}
// one level back
if( line[0] == "}" ) {
stack.pop();
continue;
}
// parse keyvalue pairs
while(true) {
m = re_kv.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 = (m[2] !== undefined) ? m[2] : m[3];
var val = (m[6] !== undefined) ? m[6] : m[8];
if(val === undefined) {
// chain (merge) duplicate key
if(stack[stack.length-1][key] === undefined)
stack[stack.length-1][key] = {};
stack.push(stack[stack.length-1][key]);
expect_bracket = true;
}
else {
if(m[7] === undefined && m[8] === undefined) {
line += "\n" + lines[++i];
continue;
}
stack[stack.length-1][key] = val;
}
break;
}
}
if(stack.length != 1) throw new SyntaxError("VDF.parse: open parentheses somewhere");
return obj;
}
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) ? true : false;
return _dump(obj,pretty,0);
}
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 line_indent = "";
if(pretty) {
for(var i = 0; i < level; i++ ) {
line_indent += indent;
}
}
for(key in obj) {
if (obj.hasOwnProperty(key)){
if( typeof obj[key] == "object" ) {
buf += [line_indent, '"', key, '"\n', line_indent, '{\n', _dump(obj[key],pretty,level+1), line_indent, "}\n"].join('');
}
else {
buf += [line_indent, '"', key, '" "', String(obj[key]), '"\n'].join('');
}
}
}
return buf;
}
exports.parse = parse;
exports.stringify = stringify;
exports.dump = stringify;