stdlib/keyvalues.js
/**
* Wrapper class for interop with Source Engine
*
* Usage:<br>
* ```let a = new KeyValues();```<br>
* ```a["color"] = new Color();```<br>
* ```b["userData"] = new KeyValues();```<br>
* ```b["userData"]["foo"] = "bar";```
*/
export class KeyValues {
/**
* Serializes this KeyValues into a format supported by the Source Engine
* @param {string} name - The key name of this KeyValues
* @type {string}
*/
_serialize(name) {
if (!name)
throw new Error("name parameter not set");
var result = "\"" + name + "\"\n{\n";
var keys = Object.keys(this);
for(var i = 0; i < keys.length; i++) {
let key = keys[i];
let value = this[key];
if (value instanceof KeyValues) {
result += value._serialize(key);
} else if (value instanceof Color) {
result += "\"" + key + "\" \"" + value.r + " " + value.g + " " + value.b + " " + value.a + "\"\n";
} else {
result += "\"" + key + "\" \"" + value + "\"\n";
}
}
result += "}\n";
return result;
}
/**
* Creates a new construction context
*/
static __startContext() {
if (KeyValues.__current !== undefined) {
throw new Error("Another KeyValues construction is busy, unable to start a second context.");
}
KeyValues.__current = [new KeyValues()];
}
/**
* Destroys the current context and returns the constructed KeyValues
* @type {KeyValues}
*/
static __stopContext() {
if (KeyValues.__current === undefined) {
throw new Error("No context started, please create a new one using __startContent");
}
if (KeyValues.__current.length != 1) {
throw new Error("Too many values on the stack, please pop until the root node");
}
let result = KeyValues.__current[0];
KeyValues.__current = undefined;
return result;
}
/**
* Creates a new child node and pushes it on the construction stack
* This is now the current active node
* @param {string} name
*/
static __pushNode(name) {
let node = new KeyValues();
let cur = KeyValues.__current[KeyValues.__current.length - 1];
cur[name] = node;
KeyValues.__current.push(node);
}
/**
* Pops a node from the construction stack
*/
static __popNode() {
KeyValues.__current.pop();
}
/**
* Sets a value for a given key
* @param {string} name
* @param value
*/
static __setValue(name, value) {
let cur = KeyValues.__current[KeyValues.__current.length - 1];
cur[name] = value;
}
static fromObject(object) {
if (!object)
throw new Error("Object property not set");
var result = new KeyValues()
var keys = Object.keys(object);
for(var i = 0; i < keys.length; i++) {
var k = keys[i];
var prop = object[k];
if (prop instanceof Object)
result[k] = KeyValues.fromObject(k, prop);
else
result[k] = prop;
}
return result
}
}