text: 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;) {
          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)) {
          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') 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
  