chiark / gitweb /
69514160c291b8868968edb0c4b1078fb63d84f3
[elogind.git] / src / shared / json.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2014 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/types.h>
23 #include <math.h>
24 #include "macro.h"
25 #include "utf8.h"
26 #include "json.h"
27
28 int json_variant_new(JsonVariant **ret, JsonVariantType type) {
29         JsonVariant *v;
30         v = new0(JsonVariant, 1);
31         if (!v)
32                 return -ENOMEM;
33         v->type = type;
34         *ret = v;
35         return 0;
36 }
37
38 static int json_variant_deep_copy(JsonVariant *ret, JsonVariant *variant) {
39         assert(ret);
40         assert(variant);
41
42         ret->type = variant->type;
43         ret->size = variant->size;
44
45         if (variant->type == JSON_VARIANT_STRING) {
46                 ret->string = memdup(variant->string, variant->size+1);
47                 if (!ret->string)
48                         return -ENOMEM;
49         } else if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) {
50                 ret->objects = new0(JsonVariant, variant->size);
51                 if (!ret->objects)
52                         return -ENOMEM;
53
54                 for (unsigned i = 0; i < variant->size; ++i) {
55                         int r;
56                         r = json_variant_deep_copy(&ret->objects[i], &variant->objects[i]);
57                         if (r < 0)
58                                 return r;
59                 }
60         }
61         else
62                 ret->value = variant->value;
63
64         return 0;
65 }
66
67 static JsonVariant *json_object_unref(JsonVariant *variant);
68
69 static JsonVariant *json_variant_unref_inner(JsonVariant *variant) {
70         if (!variant)
71                 return NULL;
72
73         if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
74                 return json_object_unref(variant);
75
76         else if (variant->type == JSON_VARIANT_STRING)
77                 free(variant->string);
78
79         return NULL;
80 }
81
82 static JsonVariant *json_raw_unref(JsonVariant *variant, size_t size) {
83         if (!variant)
84                 return NULL;
85
86         for (size_t i = 0; i < size; ++i)
87                 json_variant_unref_inner(&variant[i]);
88
89         free(variant);
90         return NULL;
91 }
92
93 static JsonVariant *json_object_unref(JsonVariant *variant) {
94         assert(variant);
95         if (!variant->objects)
96                 return NULL;
97
98         for (unsigned i = 0; i < variant->size; ++i)
99                 json_variant_unref_inner(&variant->objects[i]);
100
101         free(variant->objects);
102         return NULL;
103 }
104
105 static JsonVariant **json_variant_array_unref(JsonVariant **variant) {
106         size_t i = 0;
107         JsonVariant *p = NULL;
108
109         if (!variant)
110                 return NULL;
111
112         while((p = (variant[i++])) != NULL) {
113                 if (p->type == JSON_VARIANT_STRING)
114                        free(p->string);
115                 free(p);
116         }
117
118         free(variant);
119
120         return NULL;
121 }
122 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant **, json_variant_array_unref);
123
124 JsonVariant *json_variant_unref(JsonVariant *variant) {
125         if (!variant)
126                 return NULL;
127
128         if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
129                 json_object_unref(variant);
130
131         else if (variant->type == JSON_VARIANT_STRING)
132                 free(variant->string);
133
134         free(variant);
135
136         return NULL;
137 }
138
139 char *json_variant_string(JsonVariant *variant){
140         assert(variant);
141         assert(variant->type == JSON_VARIANT_STRING);
142
143         return variant->string;
144 }
145
146 bool json_variant_bool(JsonVariant *variant) {
147         assert(variant);
148         assert(variant->type == JSON_VARIANT_BOOLEAN);
149
150         return variant->value.boolean;
151 }
152
153 intmax_t json_variant_integer(JsonVariant *variant) {
154         assert(variant);
155         assert(variant->type == JSON_VARIANT_INTEGER);
156
157         return variant->value.integer;
158 }
159
160 double json_variant_real(JsonVariant *variant) {
161         assert(variant);
162         assert(variant->type == JSON_VARIANT_REAL);
163
164         return variant->value.real;
165 }
166
167 JsonVariant *json_variant_element(JsonVariant *variant, unsigned index) {
168         assert(variant);
169         assert(variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT);
170         assert(index < variant->size);
171         assert(variant->objects);
172
173         return &variant->objects[index];
174 }
175
176 JsonVariant *json_variant_value(JsonVariant *variant, const char *key) {
177         assert(variant);
178         assert(variant->type == JSON_VARIANT_OBJECT);
179         assert(variant->objects);
180
181         for (unsigned i = 0; i < variant->size; i += 2) {
182                 JsonVariant *p = &variant->objects[i];
183                 if (p->type == JSON_VARIANT_STRING && streq(key, p->string))
184                         return &variant->objects[i + 1];
185         }
186
187         return NULL;
188 }
189
190 static void inc_lines(unsigned *line, const char *s, size_t n) {
191         const char *p = s;
192
193         if (!line)
194                 return;
195
196         for (;;) {
197                 const char *f;
198
199                 f = memchr(p, '\n', n);
200                 if (!f)
201                         return;
202
203                 n -= (f - p) + 1;
204                 p = f + 1;
205                 (*line)++;
206         }
207 }
208
209 static int unhex_ucs2(const char *c, uint16_t *ret) {
210         int aa, bb, cc, dd;
211         uint16_t x;
212
213         assert(c);
214         assert(ret);
215
216         aa = unhexchar(c[0]);
217         if (aa < 0)
218                 return -EINVAL;
219
220         bb = unhexchar(c[1]);
221         if (bb < 0)
222                 return -EINVAL;
223
224         cc = unhexchar(c[2]);
225         if (cc < 0)
226                 return -EINVAL;
227
228         dd = unhexchar(c[3]);
229         if (dd < 0)
230                 return -EINVAL;
231
232         x =     ((uint16_t) aa << 12) |
233                 ((uint16_t) bb << 8) |
234                 ((uint16_t) cc << 4) |
235                 ((uint16_t) dd);
236
237         if (x <= 0)
238                 return -EINVAL;
239
240         *ret = x;
241
242         return 0;
243 }
244
245 static int json_parse_string(const char **p, char **ret) {
246         _cleanup_free_ char *s = NULL;
247         size_t n = 0, allocated = 0;
248         const char *c;
249
250         assert(p);
251         assert(*p);
252         assert(ret);
253
254         c = *p;
255
256         if (*c != '"')
257                 return -EINVAL;
258
259         c++;
260
261         for (;;) {
262                 int len;
263
264                 /* Check for EOF */
265                 if (*c == 0)
266                         return -EINVAL;
267
268                 /* Check for control characters 0x00..0x1f */
269                 if (*c > 0 && *c < ' ')
270                         return -EINVAL;
271
272                 /* Check for control character 0x7f */
273                 if (*c == 0x7f)
274                         return -EINVAL;
275
276                 if (*c == '"') {
277                         if (!s) {
278                                 s = strdup("");
279                                 if (!s)
280                                         return -ENOMEM;
281                         } else
282                                 s[n] = 0;
283
284                         *p = c + 1;
285
286                         *ret = s;
287                         s = NULL;
288                         return JSON_STRING;
289                 }
290
291                 if (*c == '\\') {
292                         char ch = 0;
293                         c++;
294
295                         if (*c == 0)
296                                 return -EINVAL;
297
298                         if (IN_SET(*c, '"', '\\', '/'))
299                                 ch = *c;
300                         else if (*c == 'b')
301                                 ch = '\b';
302                         else if (*c == 'f')
303                                 ch = '\f';
304                         else if (*c == 'n')
305                                 ch = '\n';
306                         else if (*c == 'r')
307                                 ch = '\r';
308                         else if (*c == 't')
309                                 ch = '\t';
310                         else if (*c == 'u') {
311                                 uint16_t x;
312                                 int r;
313
314                                 r = unhex_ucs2(c + 1, &x);
315                                 if (r < 0)
316                                         return r;
317
318                                 c += 5;
319
320                                 if (!GREEDY_REALLOC(s, allocated, n + 4))
321                                         return -ENOMEM;
322
323                                 if (!utf16_is_surrogate(x))
324                                         n += utf8_encode_unichar(s + n, x);
325                                 else if (utf16_is_trailing_surrogate(x))
326                                         return -EINVAL;
327                                 else {
328                                         uint16_t y;
329
330                                         if (c[0] != '\\' || c[1] != 'u')
331                                                 return -EINVAL;
332
333                                         r = unhex_ucs2(c + 2, &y);
334                                         if (r < 0)
335                                                 return r;
336
337                                         c += 6;
338
339                                         if (!utf16_is_trailing_surrogate(y))
340                                                 return -EINVAL;
341
342                                         n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
343                                 }
344
345                                 continue;
346                         } else
347                                 return -EINVAL;
348
349                         if (!GREEDY_REALLOC(s, allocated, n + 2))
350                                 return -ENOMEM;
351
352                         s[n++] = ch;
353                         c ++;
354                         continue;
355                 }
356
357                 len = utf8_encoded_valid_unichar(c);
358                 if (len < 0)
359                         return len;
360
361                 if (!GREEDY_REALLOC(s, allocated, n + len + 1))
362                         return -ENOMEM;
363
364                 memcpy(s + n, c, len);
365                 n += len;
366                 c += len;
367         }
368 }
369
370 static int json_parse_number(const char **p, union json_value *ret) {
371         bool negative = false, exponent_negative = false, is_double = false;
372         double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
373         intmax_t i = 0;
374         const char *c;
375
376         assert(p);
377         assert(*p);
378         assert(ret);
379
380         c = *p;
381
382         if (*c == '-') {
383                 negative = true;
384                 c++;
385         }
386
387         if (*c == '0')
388                 c++;
389         else {
390                 if (!strchr("123456789", *c) || *c == 0)
391                         return -EINVAL;
392
393                 do {
394                         if (!is_double) {
395                                 int64_t t;
396
397                                 t = 10 * i + (*c - '0');
398                                 if (t < i) /* overflow */
399                                         is_double = false;
400                                 else
401                                         i = t;
402                         }
403
404                         x = 10.0 * x + (*c - '0');
405                         c++;
406                 } while (strchr("0123456789", *c) && *c != 0);
407         }
408
409         if (*c == '.') {
410                 is_double = true;
411                 c++;
412
413                 if (!strchr("0123456789", *c) || *c == 0)
414                         return -EINVAL;
415
416                 do {
417                         y = 10.0 * y + (*c - '0');
418                         shift = 10.0 * shift;
419                         c++;
420                 } while (strchr("0123456789", *c) && *c != 0);
421         }
422
423         if (*c == 'e' || *c == 'E') {
424                 is_double = true;
425                 c++;
426
427                 if (*c == '-') {
428                         exponent_negative = true;
429                         c++;
430                 } else if (*c == '+')
431                         c++;
432
433                 if (!strchr("0123456789", *c) || *c == 0)
434                         return -EINVAL;
435
436                 do {
437                         exponent = 10.0 * exponent + (*c - '0');
438                         c++;
439                 } while (strchr("0123456789", *c) && *c != 0);
440         }
441
442         *p = c;
443
444         if (is_double) {
445                 ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent);
446                 return JSON_REAL;
447         } else {
448                 ret->integer = negative ? -i : i;
449                 return JSON_INTEGER;
450         }
451 }
452
453 int json_tokenize(
454                 const char **p,
455                 char **ret_string,
456                 union json_value *ret_value,
457                 void **state,
458                 unsigned *line) {
459
460         const char *c;
461         int t;
462         int r;
463
464         enum {
465                 STATE_NULL,
466                 STATE_VALUE,
467                 STATE_VALUE_POST,
468         };
469
470         assert(p);
471         assert(*p);
472         assert(ret_string);
473         assert(ret_value);
474         assert(state);
475
476         t = PTR_TO_INT(*state);
477         c = *p;
478
479         if (t == STATE_NULL) {
480                 if (line)
481                         *line = 1;
482                 t = STATE_VALUE;
483         }
484
485         for (;;) {
486                 const char *b;
487
488                 b = c + strspn(c, WHITESPACE);
489                 if (*b == 0)
490                         return JSON_END;
491
492                 inc_lines(line, c, b - c);
493                 c = b;
494
495                 switch (t) {
496
497                 case STATE_VALUE:
498
499                         if (*c == '{') {
500                                 *ret_string = NULL;
501                                 *ret_value = JSON_VALUE_NULL;
502                                 *p = c + 1;
503                                 *state = INT_TO_PTR(STATE_VALUE);
504                                 return JSON_OBJECT_OPEN;
505
506                         } else if (*c == '}') {
507                                 *ret_string = NULL;
508                                 *ret_value = JSON_VALUE_NULL;
509                                 *p = c + 1;
510                                 *state = INT_TO_PTR(STATE_VALUE_POST);
511                                 return JSON_OBJECT_CLOSE;
512
513                         } else if (*c == '[') {
514                                 *ret_string = NULL;
515                                 *ret_value = JSON_VALUE_NULL;
516                                 *p = c + 1;
517                                 *state = INT_TO_PTR(STATE_VALUE);
518                                 return JSON_ARRAY_OPEN;
519
520                         } else if (*c == ']') {
521                                 *ret_string = NULL;
522                                 *ret_value = JSON_VALUE_NULL;
523                                 *p = c + 1;
524                                 *state = INT_TO_PTR(STATE_VALUE_POST);
525                                 return JSON_ARRAY_CLOSE;
526
527                         } else if (*c == '"') {
528                                 r = json_parse_string(&c, ret_string);
529                                 if (r < 0)
530                                         return r;
531
532                                 *ret_value = JSON_VALUE_NULL;
533                                 *p = c;
534                                 *state = INT_TO_PTR(STATE_VALUE_POST);
535                                 return r;
536
537                         } else if (strchr("-0123456789", *c)) {
538                                 r = json_parse_number(&c, ret_value);
539                                 if (r < 0)
540                                         return r;
541
542                                 *ret_string = NULL;
543                                 *p = c;
544                                 *state = INT_TO_PTR(STATE_VALUE_POST);
545                                 return r;
546
547                         } else if (startswith(c, "true")) {
548                                 *ret_string = NULL;
549                                 ret_value->boolean = true;
550                                 *p = c + 4;
551                                 *state = INT_TO_PTR(STATE_VALUE_POST);
552                                 return JSON_BOOLEAN;
553
554                         } else if (startswith(c, "false")) {
555                                 *ret_string = NULL;
556                                 ret_value->boolean = false;
557                                 *p = c + 5;
558                                 *state = INT_TO_PTR(STATE_VALUE_POST);
559                                 return JSON_BOOLEAN;
560
561                         } else if (startswith(c, "null")) {
562                                 *ret_string = NULL;
563                                 *ret_value = JSON_VALUE_NULL;
564                                 *p = c + 4;
565                                 *state = INT_TO_PTR(STATE_VALUE_POST);
566                                 return JSON_NULL;
567
568                         } else
569                                 return -EINVAL;
570
571                 case STATE_VALUE_POST:
572
573                         if (*c == ':') {
574                                 *ret_string = NULL;
575                                 *ret_value = JSON_VALUE_NULL;
576                                 *p = c + 1;
577                                 *state = INT_TO_PTR(STATE_VALUE);
578                                 return JSON_COLON;
579                         } else if (*c == ',') {
580                                 *ret_string = NULL;
581                                 *ret_value = JSON_VALUE_NULL;
582                                 *p = c + 1;
583                                 *state = INT_TO_PTR(STATE_VALUE);
584                                 return JSON_COMMA;
585                         } else if (*c == '}') {
586                                 *ret_string = NULL;
587                                 *ret_value = JSON_VALUE_NULL;
588                                 *p = c + 1;
589                                 *state = INT_TO_PTR(STATE_VALUE_POST);
590                                 return JSON_OBJECT_CLOSE;
591                         } else if (*c == ']') {
592                                 *ret_string = NULL;
593                                 *ret_value = JSON_VALUE_NULL;
594                                 *p = c + 1;
595                                 *state = INT_TO_PTR(STATE_VALUE_POST);
596                                 return JSON_ARRAY_CLOSE;
597                         } else
598                                 return -EINVAL;
599                 }
600
601         }
602 }
603
604 static bool json_is_value(JsonVariant *var) {
605         assert(var);
606
607         return var->type != JSON_VARIANT_CONTROL;
608 }
609
610 static int json_scoped_parse(JsonVariant **tokens, size_t *i, size_t n, JsonVariant *scope) {
611         bool arr = scope->type == JSON_VARIANT_ARRAY;
612         int terminator = arr ? JSON_ARRAY_CLOSE : JSON_OBJECT_CLOSE;
613         size_t allocated = 0, size = 0;
614         JsonVariant *key = NULL, *value = NULL, *var = NULL, *items = NULL;
615         enum {
616                 STATE_KEY,
617                 STATE_COLON,
618                 STATE_COMMA,
619                 STATE_VALUE
620         } state = arr ? STATE_VALUE : STATE_KEY;
621
622         assert(tokens);
623         assert(i);
624         assert(scope);
625
626         while((var = *i < n ? tokens[(*i)++] : NULL) != NULL) {
627                 bool stopper = !json_is_value(var) && var->value.integer == terminator;
628                 int r;
629
630                 if (stopper) {
631                         if (state != STATE_COMMA && size > 0)
632                                 goto error;
633
634                         goto out;
635                 }
636
637                 if (state == STATE_KEY) {
638                         if (var->type != JSON_VARIANT_STRING)
639                                 goto error;
640                         else {
641                                 key = var;
642                                 state = STATE_COLON;
643                         }
644                 }
645                 else if (state == STATE_COLON) {
646                         if (key == NULL)
647                                 goto error;
648
649                         if (json_is_value(var))
650                                 goto error;
651
652                         if (var->value.integer != JSON_COLON)
653                                 goto error;
654
655                         state = STATE_VALUE;
656                 }
657                 else if (state == STATE_VALUE) {
658                         _cleanup_jsonunref_ JsonVariant *v = NULL;
659                         size_t toadd = arr ? 1 : 2;
660
661                         if (!json_is_value(var)) {
662                                 int type = (var->value.integer == JSON_ARRAY_OPEN) ? JSON_VARIANT_ARRAY : JSON_VARIANT_OBJECT;
663
664                                 r = json_variant_new(&v, type);
665                                 if (r < 0)
666                                         goto error;
667
668                                 r = json_scoped_parse(tokens, i, n, v);
669                                 if (r < 0)
670                                         goto error;
671
672                                 value = v;
673                         }
674                         else
675                                 value = var;
676
677                         if(!GREEDY_REALLOC(items, allocated, size + toadd))
678                                 goto error;
679
680                         if (arr) {
681                                 r = json_variant_deep_copy(&items[size], value);
682                                 if (r < 0)
683                                         goto error;
684                         } else {
685                                 r = json_variant_deep_copy(&items[size], key);
686                                 if (r < 0)
687                                         goto error;
688
689                                 r = json_variant_deep_copy(&items[size+1], value);
690                                 if (r < 0)
691                                         goto error;
692                         }
693
694                         size += toadd;
695                         state = STATE_COMMA;
696                 }
697                 else if (state == STATE_COMMA) {
698                         if (json_is_value(var))
699                                 goto error;
700
701                         if (var->value.integer != JSON_COMMA)
702                                 goto error;
703
704                         key = NULL;
705                         value = NULL;
706
707                         state = arr ? STATE_VALUE : STATE_KEY;
708                 }
709         }
710
711 error:
712         json_raw_unref(items, size);
713         return -EBADMSG;
714
715 out:
716         scope->size = size;
717         scope->objects = items;
718
719         return scope->type;
720 }
721
722 static int json_parse_tokens(JsonVariant **tokens, size_t ntokens, JsonVariant **rv) {
723         size_t it = 0;
724         int r;
725         JsonVariant *e;
726         _cleanup_jsonunref_ JsonVariant *p = NULL;
727
728         assert(tokens);
729         assert(ntokens);
730
731         e = tokens[it++];
732         r = json_variant_new(&p, JSON_VARIANT_OBJECT);
733         if (r < 0)
734                 return r;
735
736         if (e->type != JSON_VARIANT_CONTROL && e->value.integer != JSON_OBJECT_OPEN)
737                 return -EBADMSG;
738
739         r = json_scoped_parse(tokens, &it, ntokens, p);
740         if (r < 0)
741                 return r;
742
743         *rv = p;
744         p = NULL;
745
746         return 0;
747 }
748
749 static int json_tokens(const char *string, size_t size, JsonVariant ***tokens, size_t *n) {
750         _cleanup_free_ char *buf = NULL;
751         _cleanup_(json_variant_array_unrefp) JsonVariant **items = NULL;
752         union json_value v = {};
753         void *json_state = NULL;
754         const char *p;
755         int t, r;
756         size_t allocated = 0, s = 0;
757
758         assert(string);
759         assert(n);
760
761         if (size <= 0)
762                 return -EBADMSG;
763
764         buf = strndup(string, size);
765         if (!buf)
766                 return -ENOMEM;
767
768         p = buf;
769         for (;;) {
770                 _cleanup_free_ char *rstr = NULL;
771                 _cleanup_jsonunref_ JsonVariant *var = NULL;
772
773                 t = json_tokenize(&p, &rstr, &v, &json_state, NULL);
774
775                 if (t < 0)
776                         return t;
777                 else if (t == JSON_END)
778                         break;
779
780                 if (t <= JSON_ARRAY_CLOSE) {
781                         r = json_variant_new(&var, JSON_VARIANT_CONTROL);
782                         if (r < 0)
783                                 return r;
784                         var->value.integer = t;
785                 } else {
786                         switch (t) {
787                         case JSON_STRING:
788                                 r = json_variant_new(&var, JSON_VARIANT_STRING);
789                                 if (r < 0)
790                                         return r;
791                                 var->size = strlen(rstr);
792                                 var->string = strdup(rstr);
793                                 if (!var->string) {
794                                         return -ENOMEM;
795                                 }
796                                 break;
797                         case JSON_INTEGER:
798                                 r = json_variant_new(&var, JSON_VARIANT_INTEGER);
799                                 if (r < 0)
800                                         return r;
801                                 var->value = v;
802                                 break;
803                         case JSON_REAL:
804                                 r = json_variant_new(&var, JSON_VARIANT_REAL);
805                                 if (r < 0)
806                                         return r;
807                                 var->value = v;
808                                 break;
809                         case JSON_BOOLEAN:
810                                 r = json_variant_new(&var, JSON_VARIANT_BOOLEAN);
811                                 if (r < 0)
812                                         return r;
813                                 var->value = v;
814                                 break;
815                         case JSON_NULL:
816                                 r = json_variant_new(&var, JSON_VARIANT_NULL);
817                                 if (r < 0)
818                                         return r;
819                                 break;
820                         }
821                 }
822
823                 if (!GREEDY_REALLOC(items, allocated, s+2))
824                         return -ENOMEM;
825
826                 items[s++] = var;
827                 items[s] = NULL;
828                 var = NULL;
829         }
830
831         *n = s;
832         *tokens = items;
833         items = NULL;
834
835         return 0;
836 }
837
838 int json_parse(const char *string, JsonVariant **rv) {
839         _cleanup_(json_variant_array_unrefp) JsonVariant **s = NULL;
840         JsonVariant *v = NULL;
841         size_t n = 0;
842         int r;
843
844         assert(string);
845         assert(rv);
846
847         r = json_tokens(string, strlen(string), &s, &n);
848         if (r < 0)
849                 return r;
850
851         r = json_parse_tokens(s, n, &v);
852         if (r < 0)
853                 return r;
854
855         *rv = v;
856         return 0;
857 }