You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					101 lines
				
				2.5 KiB
			
		
		
			
		
	
	
					101 lines
				
				2.5 KiB
			| 
											3 years ago
										 | var hasExcape = /~/ | ||
|  | var escapeMatcher = /~[01]/g | ||
|  | function escapeReplacer (m) { | ||
|  |   switch (m) { | ||
|  |     case '~1': return '/' | ||
|  |     case '~0': return '~' | ||
|  |   } | ||
|  |   throw new Error('Invalid tilde escape: ' + m) | ||
|  | } | ||
|  | 
 | ||
|  | function untilde (str) { | ||
|  |   if (!hasExcape.test(str)) return str | ||
|  |   return str.replace(escapeMatcher, escapeReplacer) | ||
|  | } | ||
|  | 
 | ||
|  | function setter (obj, pointer, value) { | ||
|  |   var part | ||
|  |   var hasNextPart | ||
|  | 
 | ||
|  |   for (var p = 1, len = pointer.length; p < len;) { | ||
|  |     if (pointer[p] === 'constructor' || pointer[p] === 'prototype' || pointer[p] === '__proto__') return obj | ||
|  | 
 | ||
|  |     part = untilde(pointer[p++]) | ||
|  |     hasNextPart = len > p | ||
|  | 
 | ||
|  |     if (typeof obj[part] === 'undefined') { | ||
|  |       // support setting of /-
 | ||
|  |       if (Array.isArray(obj) && part === '-') { | ||
|  |         part = obj.length | ||
|  |       } | ||
|  | 
 | ||
|  |       // support nested objects/array when setting values
 | ||
|  |       if (hasNextPart) { | ||
|  |         if ((pointer[p] !== '' && pointer[p] < Infinity) || pointer[p] === '-') obj[part] = [] | ||
|  |         else obj[part] = {} | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     if (!hasNextPart) break | ||
|  |     obj = obj[part] | ||
|  |   } | ||
|  | 
 | ||
|  |   var oldValue = obj[part] | ||
|  |   if (value === undefined) delete obj[part] | ||
|  |   else obj[part] = value | ||
|  |   return oldValue | ||
|  | } | ||
|  | 
 | ||
|  | function compilePointer (pointer) { | ||
|  |   if (typeof pointer === 'string') { | ||
|  |     pointer = pointer.split('/') | ||
|  |     if (pointer[0] === '') return pointer | ||
|  |     throw new Error('Invalid JSON pointer.') | ||
|  |   } else if (Array.isArray(pointer)) { | ||
|  |     for (const part of pointer) { | ||
|  |       if (typeof part !== 'string' && typeof part !== 'number') { | ||
|  |         throw new Error('Invalid JSON pointer. Must be of type string or number.') | ||
|  |       } | ||
|  |     } | ||
|  |     return pointer | ||
|  |   } | ||
|  | 
 | ||
|  |   throw new Error('Invalid JSON pointer.') | ||
|  | } | ||
|  | 
 | ||
|  | function get (obj, pointer) { | ||
|  |   if (typeof obj !== 'object') throw new Error('Invalid input object.') | ||
|  |   pointer = compilePointer(pointer) | ||
|  |   var len = pointer.length | ||
|  |   if (len === 1) return obj | ||
|  | 
 | ||
|  |   for (var p = 1; p < len;) { | ||
|  |     obj = obj[untilde(pointer[p++])] | ||
|  |     if (len === p) return obj | ||
|  |     if (typeof obj !== 'object' || obj === null) return undefined | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function set (obj, pointer, value) { | ||
|  |   if (typeof obj !== 'object') throw new Error('Invalid input object.') | ||
|  |   pointer = compilePointer(pointer) | ||
|  |   if (pointer.length === 0) throw new Error('Invalid JSON pointer for set.') | ||
|  |   return setter(obj, pointer, value) | ||
|  | } | ||
|  | 
 | ||
|  | function compile (pointer) { | ||
|  |   var compiled = compilePointer(pointer) | ||
|  |   return { | ||
|  |     get: function (object) { | ||
|  |       return get(object, compiled) | ||
|  |     }, | ||
|  |     set: function (object, value) { | ||
|  |       return set(object, compiled, value) | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | exports.get = get | ||
|  | exports.set = set | ||
|  | exports.compile = compile |