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