-
Notifications
You must be signed in to change notification settings - Fork 23
/
vdf.js
129 lines (102 loc) · 3.6 KB
/
vdf.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
// a simple parser for Valve's KeyValue format
// https://developer.valvesoftware.com/wiki/KeyValues
//
// author: Rossen Popov, 2014
var VDF = {
parse: function(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;
},
stringify: function(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 this._dump(obj,pretty,0);
},
_dump: function(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( typeof obj[key] == "object" ) {
buf += [line_indent, '"', key, '"\n', line_indent, '{\n', this._dump(obj[key],pretty,level+1), line_indent, "}\n"].join('');
}
else {
buf += [line_indent, '"', key, '" "', String(obj[key]), '"\n'].join('');
}
}
return buf;
}
}