.replace(/([a-z])([A-Z])/g, function(m0, m1, m2) {
return "" + m1 + " " + m2.toLowerCase();
})
.toLowerCase();
},
stringifyValue: function(value) {
return v.prettify(value);
},
isString: function(value) {
return typeof value === 'string';
},
isArray: function(value) {
return {}.toString.call(value) === '[object Array]';
},
contains: function(obj, value) {
if (!v.isDefined(obj)) {
return false;
}
if (v.isArray(obj)) {
return obj.indexOf(value) !== -1;
}
return value in obj;
},
forEachKeyInKeypath: function(object, keypath, callback) {
if (!v.isString(keypath)) {
return undefined;
}
var key = ""
, i
, escape = false;
for (i = 0; i < keypath.length; ++i) {
switch (keypath[i]) {
case '.':
if (escape) {
escape = false;
key += '.';
} else {
object = callback(object, key, false);
key = "";
}
break;
case '\\':
if (escape) {
escape = false;
key += '\\';
} else {
escape = true;
}
break;
default:
escape = false;
key += keypath[i];
break;
}
}
return callback(object, key, true);
},
getDeepObjectValue: function(obj, keypath) {
if (!v.isObject(obj)) {
return undefined;
}
return v.forEachKeyInKeypath(obj, keypath, function(obj, key) {
if (v.isObject(obj)) {
return obj[key];
}
});
},