const ESCAPED_SUBS = '@xR25$e!#fda8f623'; function preserve_escaped(value:string) { return value.split('..').join(ESCAPED_SUBS); } function unpreserve_escaped(value:string) { return value.split(ESCAPED_SUBS).join('.'); } function boundary_to_dot(value: string) { return value.split('][').join('.').split('[').join('.'); } function strip_braces(value: string) { return value.split('[').join('.').split(']').join(''); } function escape_dots(value: string) { let val = value.split('\''); return (val.length < 3) ? val.join('\'') : val.map(function(seg) { if (seg.length < 3) return seg; if ((seg[0] === '.') || (seg[seg.length - 1] === '.')) return seg; return seg.split('.').join('&&'); }).join(''); } function unescape_dots(value: string) { return unpreserve_escaped(value.split('&&').join('.')); } function partify(value: string) { if (!value) return; return escape_dots(strip_braces(boundary_to_dot( preserve_escaped('' + value)))).split('.'); } export interface Cloneable { __CLONE__: (b: B) => B; } function canClone(o: any): o is Cloneable { return (typeof o.__CLONE__ === 'function'); } function clone(o: B): B { if ((typeof o !== 'object') || (o === null)) return o; if (Array.isArray(o)) return o.map(clone); return (canClone(o)) ? o.__CLONE__(clone) : (o.constructor !== Object) ? o : Object.keys(o).reduce(function(pre: any, k: string) { pre[k] = (typeof (o)[k] === 'object') ? clone((o)[k]) : (o)[k]; return pre; }, {}); } export function get(path: string, o: B): A { var parts = partify(path); var first; if (typeof o === 'object') { if (parts.length === 1) return (o)[unescape_dots(parts[0])]; if (parts.length === 0) return; first = (o)[parts.shift()]; return ((typeof o === 'object') && (o !== null)) ? parts.reduce(function(target, prop) { if (target == null) return target; return target[unescape_dots(prop)]; }, first) : null; } else { throw new TypeError('get(): expects an object got ' + typeof o); } }; export function set(path: string, value: A, obj: B): B { var parts = partify(path); if ((typeof obj !== 'object') || (obj == null)) { return clone(obj); } else { return _set(obj, value, parts); } }; function _set(obj: B, value: A, parts: string[]): B { var o; var k; if (parts.length === 0) return value; o = ((typeof obj !== 'object') || (obj === null)) ? {} : clone(obj); k = unescape_dots(parts[0]); (o)[k] = _set((o)[k], value, parts.slice(1)); return o; } export default function (k: string, v: A | B, o?: A) { if (o == null) return get(k, v); else return set(k, v, o); };