1if exists('g:loaded_msgpack_autoload')
2  finish
3endif
4let g:loaded_msgpack_autoload = 1
5
6""
7" Check that given value is an integer. Respects |msgpack-special-dict|.
8function msgpack#is_int(v) abort
9  return type(a:v) == type(0) || (
10        \type(a:v) == type({}) && get(a:v, '_TYPE') is# v:msgpack_types.integer)
11endfunction
12
13""
14" Check that given value is an unsigned integer. Respects
15" |msgpack-special-dict|.
16function msgpack#is_uint(v) abort
17  return msgpack#is_int(a:v) && (type(a:v) == type(0)
18                                \? a:v >= 0
19                                \: a:v._VAL[0] > 0)
20endfunction
21
22""
23" True if s:msgpack_init_python() function was already run.
24let s:msgpack_python_initialized = 0
25
26""
27" Cached return of s:msgpack_init_python() used when
28" s:msgpack_python_initialized is true.
29let s:msgpack_python_type = 0
30
31""
32" Create Python functions that are necessary for work. Also defines functions
33" s:msgpack_dict_strftime(format, timestamp) and s:msgpack_dict_strptime(format,
34" string).
35"
36" @return Zero in case no Python is available, empty string if Python-2 is
37"         available and string `"3"` if Python-3 is available.
38function s:msgpack_init_python() abort
39  if s:msgpack_python_initialized
40    return s:msgpack_python_type
41  endif
42  let s:msgpack_python_initialized = 1
43  for suf in (has('win32') ? ['3'] : ['', '3'])
44    try
45      execute 'python' . suf
46              \. "\n"
47              \. "def shada_dict_strftime():\n"
48              \. "  import datetime\n"
49              \. "  import vim\n"
50              \. "  fmt = vim.eval('a:format')\n"
51              \. "  timestamp = vim.eval('a:timestamp')\n"
52              \. "  timestamp = [int(v) for v in timestamp['_VAL']]\n"
53              \. "  timestamp = timestamp[0] * (timestamp[1] << 62\n"
54              \. "                              | timestamp[2] << 31\n"
55              \. "                              | timestamp[3])\n"
56              \. "  time = datetime.datetime.fromtimestamp(timestamp)\n"
57              \. "  return time.strftime(fmt)\n"
58              \. "def shada_dict_strptime():\n"
59              \. "  import datetime\n"
60              \. "  import vim\n"
61              \. "  fmt = vim.eval('a:format')\n"
62              \. "  timestr = vim.eval('a:string')\n"
63              \. "  timestamp = datetime.datetime.strptime(timestr, fmt)\n"
64              \. "  try:\n"
65              \. "    timestamp = int(timestamp.timestamp())\n"
66              \. "  except:\n"
67              \. "    timestamp = int(timestamp.strftime('%s'))\n"
68              \. "  if timestamp > 2 ** 31:\n"
69              \. "    tsabs = abs(timestamp)\n"
70              \. "    return ('{\"_TYPE\": v:msgpack_types.integer,'\n"
71              \. "            + '\"_VAL\": [{sign},{v1},{v2},{v3}]}').format(\n"
72              \. "              sign=(1 if timestamp >= 0 else -1),\n"
73              \. "              v1=((tsabs >> 62) & 0x3),\n"
74              \. "              v2=((tsabs >> 31) & (2 ** 31 - 1)),\n"
75              \. "              v3=(tsabs & (2 ** 31 - 1)))\n"
76              \. "  else:\n"
77              \. "    return str(timestamp)\n"
78      execute  "function s:msgpack_dict_strftime(format, timestamp) abort\n"
79            \. "  return py" . suf . "eval('shada_dict_strftime()')\n"
80            \. "endfunction\n"
81            \. "function s:msgpack_dict_strptime(format, string)\n"
82            \. "  return eval(py" . suf . "eval('shada_dict_strptime()'))\n"
83            \. "endfunction\n"
84      let s:msgpack_python_type = suf
85      return suf
86    catch
87      continue
88    endtry
89  endfor
90
91  ""
92  " strftime() function for |msgpack-special-dict| values.
93  "
94  " @param[in]  format     String according to which time should be formatted.
95  " @param[in]  timestamp  Timestamp (seconds since epoch) to format.
96  "
97  " @return Formatted timestamp.
98  "
99  " @warning Without +python or +python3 this function does not work correctly.
100  "          The VimL code contains “reference” implementation which does not
101  "          really work because of precision loss.
102  function s:msgpack_dict_strftime(format, timestamp)
103    return msgpack#strftime(a:format, +msgpack#int_dict_to_str(a:timestamp))
104  endfunction
105
106  ""
107  " Function that parses given string according to given format.
108  "
109  " @param[in]  format  String according to which string was formatted.
110  " @param[in]  string  Time formatted according to format.
111  "
112  " @return Timestamp.
113  "
114  " @warning Without +python or +python3 this function is able to work only with
115  "          31-bit (32-bit signed) timestamps that have format
116  "          `%Y-%m-%dT%H:%M:%S`.
117  function s:msgpack_dict_strptime(format, string)
118    let fmt = '%Y-%m-%dT%H:%M:%S'
119    if a:format isnot# fmt
120      throw 'notimplemented-format:Only ' . fmt . ' format is supported'
121    endif
122    let match = matchlist(a:string,
123                         \'\v\C^(\d+)\-(\d+)\-(\d+)T(\d+)\:(\d+)\:(\d+)$')
124    if empty(match)
125      throw 'invalid-string:Given string does not match format ' . a:format
126    endif
127    call map(match, 'str2nr(v:val, 10)')
128    let [year, month, day, hour, minute, second] = match[1:6]
129    " Bisection start and end:
130    "
131    " Start: 365 days in year, 28 days in month, -12 hours tz offset.
132    let bisect_ts_start = (((((year - 1970) * 365
133                             \+ (month - 1) * 28
134                             \+ (day - 1)) * 24
135                            \+ hour - 12) * 60
136                           \+ minute) * 60
137                          \+ second)
138    if bisect_ts_start < 0
139      let bisect_ts_start = 0
140    endif
141    let start_string = strftime(fmt, bisect_ts_start)
142    if start_string is# a:string
143      return bisect_ts_start
144    endif
145    " End: 366 days in year, 31 day in month, +14 hours tz offset.
146    let bisect_ts_end = (((((year - 1970) * 366
147                           \+ (month - 1) * 31
148                           \+ (day - 1)) * 24
149                          \+ hour + 14) * 60
150                         \+ minute) * 60
151                        \+ second)
152    let end_string = strftime(fmt, bisect_ts_end)
153    if end_string is# a:string
154      return bisect_ts_end
155    endif
156    if start_string ># end_string
157      throw 'internal-start-gt:Internal error: start > end'
158    endif
159    if start_string is# end_string
160      throw printf('internal-start-eq:Internal error: '
161                  \. 'start(%u)==end(%u), but start(%s)!=string(%s)',
162                  \bisect_ts_start, bisect_ts_end,
163                  \string(start_string), string(a:string))
164    endif
165    if start_string ># a:string
166      throw 'internal-start-string:Internal error: start > string'
167    endif
168    if end_string <# a:string
169      throw 'internal-end-string:Internal error: end < string'
170    endif
171    while 1
172      let bisect_ts_middle = (bisect_ts_start/2) + (bisect_ts_end/2)
173      let middle_string = strftime(fmt, bisect_ts_middle)
174      if a:string is# middle_string
175        return bisect_ts_middle
176      elseif a:string ># middle_string
177        if bisect_ts_middle == bisect_ts_start
178          let bisect_ts_start += 1
179        else
180          let bisect_ts_start = bisect_ts_middle
181        endif
182      else
183        if bisect_ts_middle == bisect_ts_end
184          let bisect_ts_end -= 1
185        else
186          let bisect_ts_end = bisect_ts_middle
187        endif
188      endif
189      if bisect_ts_start >= bisect_ts_end
190        throw 'not-found:Unable to find timestamp'
191      endif
192    endwhile
193  endfunction
194
195  return 0
196endfunction
197
198""
199" Wrapper for strftime() that respects |msgpack-special-dict|. May actually use
200" non-standard strftime() implementations for |msgpack-special-dict| values.
201"
202" @param[in]  format     Format string.
203" @param[in]  timestamp  Formatted timestamp.
204function msgpack#strftime(format, timestamp) abort
205  if type(a:timestamp) == type({})
206    call s:msgpack_init_python()
207    return s:msgpack_dict_strftime(a:format, a:timestamp)
208  else
209    return strftime(a:format, a:timestamp)
210  endif
211endfunction
212
213""
214" Parse string according to the format.
215"
216" Requires +python available. If it is not then only supported format is
217" `%Y-%m-%dT%H:%M:%S` because this is the format used by ShaDa plugin. Also in
218" this case bisection will be used (timestamps tried with strftime() up until
219" result matches the string) and only 31-bit (signed 32-bit: with negative
220" timestamps being useless this leaves 31 bits) timestamps will be supported.
221"
222" @param[in]  format  Time format.
223" @param[in]  string  Parsed time string. Must match given format.
224"
225" @return Timestamp. Possibly as |msgpack-special-dict|.
226function msgpack#strptime(format, string) abort
227  call s:msgpack_init_python()
228  return s:msgpack_dict_strptime(a:format, a:string)
229endfunction
230
231let s:MSGPACK_HIGHEST_BIT = 1
232let s:MSGPACK_HIGHEST_BIT_NR = 0
233while s:MSGPACK_HIGHEST_BIT * 2 > 0
234  let s:MSGPACK_HIGHEST_BIT = s:MSGPACK_HIGHEST_BIT * 2
235  let s:MSGPACK_HIGHEST_BIT_NR += 1
236endwhile
237
238""
239" Shift given number by given amount of bits
240function s:shift(n, s) abort
241  if a:s == 0
242    return a:n
243  elseif a:s < 0
244    let ret = a:n
245    for _ in range(-a:s)
246      let ret = ret / 2
247    endfor
248    return ret
249  else
250    let ret = a:n
251    for i in range(a:s)
252      let new_ret = ret * 2
253      if new_ret < ret
254        " Overflow: remove highest bit
255        let ret = xor(s:MSGPACK_HIGHEST_BIT, ret) * 2
256      endif
257      let ret = new_ret
258    endfor
259    return ret
260  endif
261endfunction
262
263let s:msgpack_mask_cache = {
264      \s:MSGPACK_HIGHEST_BIT_NR : s:MSGPACK_HIGHEST_BIT - 1}
265
266""
267" Apply a mask where first m bits are ones and other are zeroes to a given
268" number
269function s:mask1(n, m) abort
270  if a:m > s:MSGPACK_HIGHEST_BIT_NR + 1
271    let m = s:MSGPACK_HIGHEST_BIT_NR + 1
272  else
273    let m = a:m
274  endif
275  if !has_key(s:msgpack_mask_cache, m)
276    let p = 0
277    for _ in range(m)
278      let p = p * 2 + 1
279    endfor
280    let s:msgpack_mask_cache[m] = p
281  endif
282  return and(a:n, s:msgpack_mask_cache[m])
283endfunction
284
285""
286" Convert |msgpack-special-dict| that represents integer value to a string. Uses
287" hexadecimal representation starting with 0x because it is the easiest to
288" convert to.
289function msgpack#int_dict_to_str(v) abort
290  let v = a:v._VAL
291  " 64-bit number:
292  " 0000000001111111111222222222233333333334444444444555555555566666
293  " 1234567890123456789012345678901234567890123456789012345678901234
294  " Split in _VAL:
295  " 0000000001111111111222222222233 3333333344444444445555555555666 66
296  " 1234567890123456789012345678901 2345678901234567890123456789012 34
297  " Split by hex digits:
298  " 0000 0000 0111 1111 1112 2222 2222 2333 3333 3334 4444 4444 4555 5555 5556 6666
299  " 1234 5678 9012 3456 7890 1234 5678 9012 3456 7890 1234 5678 9012 3456 7890 1234
300  "
301  " Total split:
302  "                _VAL[3]                              _VAL[2]                      _VAL[1]
303  " ______________________________________  _______________________________________  __
304  " 0000 0000 0111 1111 1112 2222 2222 233  3 3333 3334 4444 4444 4555 5555 5556 66  66
305  " 1234 5678 9012 3456 7890 1234 5678 901  2 3456 7890 1234 5678 9012 3456 7890 12  34
306  " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^
307  "                g4                    g3                  g2                    g1
308  " ********************************** ***  * ********************************** **  **
309  "                1                    2   3                4                   5   6
310  " 1: s:mask1(v[3], 28): first 28 bits of _VAL[3]
311  " 2: s:shift(v[3], -28): last 3 bits of _VAL[3]
312  " 3: s:mask1(v[2], 1): first bit of _VAL[2]
313  " 4: s:mask1(s:shift(v[2], -1), 28): bits 2 .. 29 of _VAL[2]
314  " 5: s:shift(v[2], -29): last 2 bits of _VAL[2]
315  " 6: s:shift(v[1], 2): _VAL[1]
316  let g4 = printf('%07x', s:mask1(v[3], 28))
317  let g3 = printf('%01x', or(s:shift(v[3], -28), s:shift(s:mask1(v[2], 1), 3)))
318  let g2 = printf('%07x', s:mask1(s:shift(v[2], -1), 28))
319  let g1 = printf('%01x', or(s:shift(v[2], -29), s:shift(v[1], 2)))
320  return ((v[0] < 0 ? '-' : '') . '0x' . g1 . g2 . g3 . g4)
321endfunction
322
323""
324" True boolean value.
325let g:msgpack#true = {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}
326lockvar! g:msgpack#true
327
328""
329" False boolean value.
330let g:msgpack#false = {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}
331lockvar! g:msgpack#false
332
333""
334" NIL value.
335let g:msgpack#nil = {'_TYPE': v:msgpack_types.nil, '_VAL': 0}
336lockvar! g:msgpack#nil
337
338""
339" Deduce type of |msgpack-special-dict|.
340"
341" @return zero if given dictionary is not special or name of the key in
342"         v:msgpack_types dictionary.
343function msgpack#special_type(v) abort
344  if type(a:v) != type({}) || !has_key(a:v, '_TYPE')
345    return 0
346  endif
347  for [k, v] in items(v:msgpack_types)
348    if a:v._TYPE is v
349      return k
350    endif
351  endfor
352  return 0
353endfunction
354
355""
356" Mapping that maps type() output to type names.
357let s:MSGPACK_STANDARD_TYPES = {
358  \type(0): 'integer',
359  \type(0.0): 'float',
360  \type(''): 'binary',
361  \type([]): 'array',
362  \type({}): 'map',
363  \type(v:true): 'boolean',
364  \type(v:null): 'nil',
365\}
366
367""
368" Deduce type of one of items returned by msgpackparse().
369"
370" @return Name of a key in v:msgpack_types.
371function msgpack#type(v) abort
372  let special_type = msgpack#special_type(a:v)
373  if special_type is 0
374    return s:MSGPACK_STANDARD_TYPES[type(a:v)]
375  endif
376  return special_type
377endfunction
378
379""
380" Dump nil value.
381function s:msgpack_dump_nil(v) abort
382  return 'NIL'
383endfunction
384
385""
386" Dump boolean value.
387function s:msgpack_dump_boolean(v) abort
388  return (a:v is v:true || (a:v isnot v:false && a:v._VAL)) ? 'TRUE' : 'FALSE'
389endfunction
390
391""
392" Dump integer msgpack value.
393function s:msgpack_dump_integer(v) abort
394  if type(a:v) == type({})
395    return msgpack#int_dict_to_str(a:v)
396  else
397    return string(a:v)
398  endif
399endfunction
400
401""
402" Dump floating-point value.
403function s:msgpack_dump_float(v) abort
404  return substitute(string(type(a:v) == type({}) ? a:v._VAL : a:v),
405                   \'\V\^\(-\)\?str2float(''\(inf\|nan\)'')\$', '\1\2', '')
406endfunction
407
408""
409" Dump |msgpack-special-dict| that represents a string. If any additional
410" parameter is given then it dumps binary string.
411function s:msgpack_dump_string(v, ...) abort
412  let ret = [a:0 ? '"' : '="']
413  for v in a:v._VAL
414    call add(
415          \ret,
416          \substitute(
417            \substitute(v, '["\\]', '\\\0', 'g'),
418            \'\n', '\\0', 'g'))
419    call add(ret, '\n')
420  endfor
421  let ret[-1] = '"'
422  return join(ret, '')
423endfunction
424
425""
426" Dump binary string.
427function s:msgpack_dump_binary(v) abort
428  if type(a:v) == type({})
429    return s:msgpack_dump_string(a:v, 1)
430  else
431    return s:msgpack_dump_string({'_VAL': split(a:v, "\n", 1)}, 1)
432  endif
433endfunction
434
435""
436" Dump array value.
437function s:msgpack_dump_array(v) abort
438  let val = type(a:v) == type({}) ? a:v._VAL : a:v
439  return '[' . join(map(val[:], 'msgpack#string(v:val)'), ', ') . ']'
440endfunction
441
442""
443" Dump dictionary value.
444function s:msgpack_dump_map(v) abort
445  let ret = ['{']
446  if msgpack#special_type(a:v) is 0
447    for [k, v] in items(a:v)
448      let ret += [s:msgpack_dump_string({'_VAL': split(k, "\n", 1)}),
449                 \': ',
450                 \msgpack#string(v),
451                 \', ']
452      unlet v
453    endfor
454    if !empty(a:v)
455      call remove(ret, -1)
456    endif
457  else
458    for [k, v] in sort(copy(a:v._VAL))
459      let ret += [msgpack#string(k),
460                 \': ',
461                 \msgpack#string(v),
462                 \', ']
463      unlet k
464      unlet v
465    endfor
466    if !empty(a:v._VAL)
467      call remove(ret, -1)
468    endif
469  endif
470  let ret += ['}']
471  return join(ret, '')
472endfunction
473
474""
475" Dump extension value.
476function s:msgpack_dump_ext(v) abort
477  return printf('+(%i)%s', a:v._VAL[0],
478               \s:msgpack_dump_string({'_VAL': a:v._VAL[1]}, 1))
479endfunction
480
481""
482" Convert msgpack object to a string, like string() function does. Result of the
483" conversion may be passed to msgpack#eval().
484function msgpack#string(v) abort
485  if type(a:v) == type({})
486    let type = msgpack#special_type(a:v)
487    if type is 0
488      let type = 'map'
489    endif
490  else
491    let type = get(s:MSGPACK_STANDARD_TYPES, type(a:v), 0)
492    if type is 0
493      throw printf('msgpack:invtype: Unable to convert value %s', string(a:v))
494    endif
495  endif
496  return s:msgpack_dump_{type}(a:v)
497endfunction
498
499""
500" Copy msgpack object like deepcopy() does, but leave types intact
501function msgpack#deepcopy(obj) abort
502  if type(a:obj) == type([])
503    return map(copy(a:obj), 'msgpack#deepcopy(v:val)')
504  elseif type(a:obj) == type({})
505    let special_type = msgpack#special_type(a:obj)
506    if special_type is 0
507      return map(copy(a:obj), 'msgpack#deepcopy(v:val)')
508    else
509      return {
510        \'_TYPE': v:msgpack_types[special_type],
511        \'_VAL': msgpack#deepcopy(a:obj._VAL)
512      \}
513    endif
514  else
515    return copy(a:obj)
516  endif
517endfunction
518
519""
520" Convert an escaped character to needed value
521function s:msgpack_eval_str_sub(ch) abort
522  if a:ch is# 'n'
523    return '", "'
524  elseif a:ch is# '0'
525    return '\n'
526  else
527    return '\' . a:ch
528  endif
529endfunction
530
531let s:MSGPACK_SPECIAL_OBJECTS = {
532  \'NIL': '{''_TYPE'': v:msgpack_types.nil, ''_VAL'': 0}',
533  \'TRUE': '{''_TYPE'': v:msgpack_types.boolean, ''_VAL'': 1}',
534  \'FALSE': '{''_TYPE'': v:msgpack_types.boolean, ''_VAL'': 0}',
535  \'nan': '(-(1.0/0.0-1.0/0.0))',
536  \'inf': '(1.0/0.0)',
537\}
538
539""
540" Convert msgpack object dumped by msgpack#string() to a VimL object suitable
541" for msgpackdump().
542"
543" @param[in]  s             String to evaluate.
544" @param[in]  special_objs  Additional special objects, in the same format as
545"                           s:MSGPACK_SPECIAL_OBJECTS.
546"
547" @return Any value that msgpackparse() may return.
548function msgpack#eval(s, special_objs) abort
549  let s = a:s
550  let expr = []
551  let context = []
552  while !empty(s)
553    let s = substitute(s, '^\s*', '', '')
554    if s[0] =~# '\v^\h$'
555      let name = matchstr(s, '\v\C^\w+')
556      if has_key(s:MSGPACK_SPECIAL_OBJECTS, name)
557        call add(expr, s:MSGPACK_SPECIAL_OBJECTS[name])
558      elseif has_key(a:special_objs, name)
559        call add(expr, a:special_objs[name])
560      else
561        throw 'name-unknown:Unknown name ' . name . ': ' . s
562      endif
563      let s = s[len(name):]
564    elseif (s[0] is# '-' && s[1] =~# '\v^\d$') || s[0] =~# '\v^\d$'
565      let sign = 1
566      if s[0] is# '-'
567        let s = s[1:]
568        let sign = -1
569      endif
570      if s[0:1] is# '0x'
571        " See comment in msgpack#int_dict_to_str().
572        let s = s[2:]
573        let hexnum = matchstr(s, '\v\C^\x+')
574        if empty(hexnum)
575          throw '0x-empty:Must have number after 0x: ' . s
576        elseif len(hexnum) > 16
577          throw '0x-long:Must have at most 16 hex digits: ' . s
578        endif
579        let s = s[len(hexnum):]
580        let hexnum = repeat('0', 16 - len(hexnum)) . hexnum
581        let g1 = str2nr(hexnum[0], 16)
582        let g2 = str2nr(hexnum[1:7], 16)
583        let g3 = str2nr(hexnum[8], 16)
584        let g4 = str2nr(hexnum[9:15], 16)
585        let v1 = s:shift(g1, -2)
586        let v2 = or(or(s:shift(s:mask1(g1, 2), 29), s:shift(g2, 1)),
587                   \s:mask1(s:shift(g3, -3), 1))
588        let v3 = or(s:shift(s:mask1(g3, 3), 28), g4)
589        call add(expr, printf('{''_TYPE'': v:msgpack_types.integer, '.
590                             \'''_VAL'': [%i, %u, %u, %u]}',
591                             \sign, v1, v2, v3))
592      else
593        let num = matchstr(s, '\v\C^\d+')
594        let s = s[len(num):]
595        if sign == -1
596          call add(expr, '-')
597        endif
598        call add(expr, num)
599        if s[0] is# '.'
600          let dec = matchstr(s, '\v\C^\.\d+%(e[+-]?\d+)?')
601          if empty(dec)
602            throw '0.-nodigits:Decimal dot must be followed by digit(s): ' . s
603          endif
604          let s = s[len(dec):]
605          call add(expr, dec)
606        endif
607      endif
608    elseif s =~# '\v^\-%(inf|nan)'
609      call add(expr, '-')
610      call add(expr, s:MSGPACK_SPECIAL_OBJECTS[s[1:3]])
611      let s = s[4:]
612    elseif stridx('="+', s[0]) != -1
613      let match = matchlist(s, '\v\C^(\=|\+\((\-?\d+)\)|)(\"%(\\.|[^\\"]+)*\")')
614      if empty(match)
615        throw '"-invalid:Invalid string: ' . s
616      endif
617      call add(expr, '{''_TYPE'': v:msgpack_types.')
618      if empty(match[1])
619        call add(expr, 'binary')
620      elseif match[1] is# '='
621        call add(expr, 'string')
622      else
623        call add(expr, 'ext')
624      endif
625      call add(expr, ', ''_VAL'': [')
626      if match[1][0] is# '+'
627        call add(expr, match[2] . ', [')
628      endif
629      call add(expr, substitute(match[3], '\v\C\\(.)',
630                               \'\=s:msgpack_eval_str_sub(submatch(1))', 'g'))
631      if match[1][0] is# '+'
632        call add(expr, ']')
633      endif
634      call add(expr, ']}')
635      let s = s[len(match[0]):]
636    elseif s[0] is# '{'
637      call add(context, 'map')
638      call add(expr, '{''_TYPE'': v:msgpack_types.map, ''_VAL'': [')
639      call add(expr, '[')
640      let s = s[1:]
641    elseif s[0] is# '['
642      call add(context, 'array')
643      call add(expr, '[')
644      let s = s[1:]
645    elseif s[0] is# ':'
646      call add(expr, ',')
647      let s = s[1:]
648    elseif s[0] is# ','
649      if context[-1] is# 'array'
650        call add(expr, ',')
651      else
652        call add(expr, '], [')
653      endif
654      let s = s[1:]
655    elseif s[0] is# ']'
656      call remove(context, -1)
657      call add(expr, ']')
658      let s = s[1:]
659    elseif s[0] is# '}'
660      call remove(context, -1)
661      if expr[-1] is# "\x5B"
662        call remove(expr, -1)
663      else
664        call add(expr, ']')
665      endif
666      call add(expr, ']}')
667      let s = s[1:]
668    elseif s[0] is# ''''
669      let char = matchstr(s, '\v\C^\''\zs%(\\\d+|.)\ze\''')
670      if empty(char)
671        throw 'char-invalid:Invalid integer character literal format: ' . s
672      endif
673      if char[0] is# '\'
674        call add(expr, +char[1:])
675      else
676        call add(expr, char2nr(char))
677      endif
678      let s = s[len(char) + 2:]
679    else
680      throw 'unknown:Invalid non-space character: ' . s
681    endif
682  endwhile
683  if empty(expr)
684    throw 'empty:Parsed string is empty'
685  endif
686  return eval(join(expr, ''))
687endfunction
688
689""
690" Check whether two msgpack values are equal
691function msgpack#equal(a, b)
692  let atype = msgpack#type(a:a)
693  let btype = msgpack#type(a:b)
694  if atype isnot# btype
695    return 0
696  endif
697  let aspecial = msgpack#special_type(a:a)
698  let bspecial = msgpack#special_type(a:b)
699  if aspecial is# bspecial
700    if aspecial is# 0
701      if type(a:a) == type({})
702        if len(a:a) != len(a:b)
703          return 0
704        endif
705        if !empty(filter(keys(a:a), '!has_key(a:b, v:val)'))
706          return 0
707        endif
708        for [k, v] in items(a:a)
709          if !msgpack#equal(v, a:b[k])
710            return 0
711          endif
712          unlet v
713        endfor
714        return 1
715      elseif type(a:a) == type([])
716        if len(a:a) != len(a:b)
717          return 0
718        endif
719        let i = 0
720        for asubval in a:a
721          if !msgpack#equal(asubval, a:b[i])
722            return 0
723          endif
724          let i += 1
725          unlet asubval
726        endfor
727        return 1
728      elseif type(a:a) == type(0.0)
729        return (a:a == a:a ? a:a == a:b : string(a:a) ==# string(a:b))
730      else
731        return a:a ==# a:b
732      endif
733    elseif aspecial is# 'map' || aspecial is# 'array'
734      if len(a:a._VAL) != len(a:b._VAL)
735        return 0
736      endif
737      let alist = aspecial is# 'map' ? sort(copy(a:a._VAL)) : a:a._VAL
738      let blist = bspecial is# 'map' ? sort(copy(a:b._VAL)) : a:b._VAL
739      let i = 0
740      for asubval in alist
741        let bsubval = blist[i]
742        if aspecial is# 'map'
743          if !(msgpack#equal(asubval[0], bsubval[0])
744              \&& msgpack#equal(asubval[1], bsubval[1]))
745            return 0
746          endif
747        else
748          if !msgpack#equal(asubval, bsubval)
749            return 0
750          endif
751        endif
752        let i += 1
753        unlet asubval
754        unlet bsubval
755      endfor
756      return 1
757    elseif aspecial is# 'nil'
758      return 1
759    elseif aspecial is# 'float'
760      return (a:a._VAL == a:a._VAL
761             \? (a:a._VAL == a:b._VAL)
762             \: (string(a:a._VAL) ==# string(a:b._VAL)))
763    else
764      return a:a._VAL ==# a:b._VAL
765    endif
766  else
767    if atype is# 'array'
768      let a = aspecial is 0 ? a:a : a:a._VAL
769      let b = bspecial is 0 ? a:b : a:b._VAL
770      return msgpack#equal(a, b)
771    elseif atype is# 'binary'
772      let a = (aspecial is 0 ? split(a:a, "\n", 1) : a:a._VAL)
773      let b = (bspecial is 0 ? split(a:b, "\n", 1) : a:b._VAL)
774      return a ==# b
775    elseif atype is# 'map'
776      if aspecial is 0
777        let akeys = copy(a:a)
778        if len(a:b._VAL) != len(akeys)
779          return 0
780        endif
781        for [k, v] in a:b._VAL
782          if msgpack#type(k) isnot# 'string'
783            " Non-special mapping cannot have non-string keys
784            return 0
785          endif
786          if (empty(k._VAL)
787             \|| k._VAL ==# [""]
788             \|| !empty(filter(copy(k._VAL), 'stridx(v:val, "\n") != -1')))
789            " Non-special mapping cannot have zero byte in key or an empty key
790            return 0
791          endif
792          let kstr = join(k._VAL, "\n")
793          if !has_key(akeys, kstr)
794            " Protects from both missing and duplicate keys
795            return 0
796          endif
797          if !msgpack#equal(akeys[kstr], v)
798            return 0
799          endif
800          call remove(akeys, kstr)
801          unlet k
802          unlet v
803        endfor
804        return 1
805      else
806        return msgpack#equal(a:b, a:a)
807      endif
808    elseif atype is# 'float'
809      let a = aspecial is 0 ? a:a : a:a._VAL
810      let b = bspecial is 0 ? a:b : a:b._VAL
811      return (a == a ? a == b : string(a) ==# string(b))
812    elseif atype is# 'integer'
813      if aspecial is 0
814        let sign = a:a >= 0 ? 1 : -1
815        let a = sign * a:a
816        let v1 = s:mask1(s:shift(a, -62), 2)
817        let v2 = s:mask1(s:shift(a, -31), 31)
818        let v3 = s:mask1(a, 31)
819        return [sign, v1, v2, v3] == a:b._VAL
820      else
821        return msgpack#equal(a:b, a:a)
822      endif
823    else
824      throw printf('internal-invalid-type: %s == %s, but special %s /= %s',
825                  \atype, btype, aspecial, bspecial)
826    endif
827  endif
828endfunction
829