eerimoq / simba
1
/*
2
 * The MIT License (MIT)
3
 *
4
 * Copyright (c) 2014-2018, Erik Moqvist
5
 *
6
 * Permission is hereby granted, free of charge, to any person
7
 * obtaining a copy of this software and associated documentation
8
 * files (the "Software"), to deal in the Software without
9
 * restriction, including without limitation the rights to use, copy,
10
 * modify, merge, publish, distribute, sublicense, and/or sell copies
11
 * of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be
15
 * included in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
 * SOFTWARE.
25
 *
26
 * This file is part of the Simba project.
27
 */
28

29
/*
30
  This module is based on the MIT Licensed JSMN implementation.
31

32
  http://zserge.com/jsmn.html
33

34
  Copyright (c) 2010 Serge A. Zaitsev
35

36
  Permission is hereby granted, free of charge, to any person
37
  obtaining a copy of this software and associated documentation files
38
  (the "Software"), to deal in the Software without restriction,
39
  including without limitation the rights to use, copy, modify, merge,
40
  publish, distribute, sublicense, and/or sell copies of the Software,
41
  and to permit persons to whom the Software is furnished to do so,
42
  subject to the following conditions:
43

44
  The above copyright notice and this permission notice shall be
45
  included in all copies or substantial portions of the Software.
46

47
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
51
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
52
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
53
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54
  SOFTWARE.
55
*/
56

57
#include "simba.h"
58

59
struct dump_t {
60
    struct json_t *self_p;
61
    struct json_tok_t *tokens_p;
62
    int num_tokens;
63
    void *out_p;
64
};
65

66
struct string_t {
67
    struct chan_t base;
68
    ssize_t pos;
69
    char *buf_p;
70
};
71

72
static ssize_t dump(struct dump_t *state_p);
73

74
/**
75
 * Copy given buffer to the output buffer. It is not null terminated.
76
 */
77 1
static ssize_t string_write(void *chan_p, const void *buf_p, size_t size)
78
{
79
    struct string_t *string_p;
80

81 1
    string_p = chan_p;
82 1
    memcpy(&string_p->buf_p[string_p->pos], buf_p, size);
83 1
    string_p->pos += size;
84

85 1
    return (size);
86
}
87

88
/**
89
 * Allocates a fresh unused token from the token pull.
90
 */
91 1
static struct json_tok_t *alloc_token(struct json_t *self_p)
92
{
93
    struct json_tok_t *tok_p;
94

95 1
    if (self_p->toknext >= self_p->num_tokens) {
96 1
        return NULL;
97
    }
98

99 1
    tok_p = &self_p->tokens_p[self_p->toknext++];
100 1
    tok_p->buf_p = NULL;
101 1
    tok_p->size = -1;
102 1
    tok_p->num_tokens = 0;
103
#ifdef JSON_PARENT_LINKS
104
    tok_p->parent = -1;
105
#endif
106

107 1
    return (tok_p);
108
}
109

110
/**
111
 * Fills token type and boundaries.
112
 */
113 1
static void fill_token(struct json_tok_t *token_p,
114
                       enum json_type_t type,
115
                       const void *buf_p,
116
                       int size)
117
{
118 1
    token_p->type = type;
119 1
    token_p->buf_p = buf_p;
120 1
    token_p->size = size;
121 1
    token_p->num_tokens = 0;
122
}
123

124
/**
125
 * Recursively dump given object token and its children.
126
 */
127 1
static ssize_t dump_object(struct dump_t *state_p,
128
                           struct json_tok_t *token_p)
129
{
130
    ssize_t size, res, i;
131
    const char *delim_p;
132

133 1
    std_fprintf(state_p->out_p, FSTR("{"));
134 1
    size = 2;
135 1
    delim_p = FSTR("");
136

137 1
    for (i = 0; i < token_p->num_tokens; i++) {
138
        /* Delimiter. */
139 1
        res = std_fprintf(state_p->out_p, delim_p);
140 1
        size += res;
141

142
        /* Key. */
143

144
        /* The key must be a string or primitive type. */
145 1
        if (!((state_p->tokens_p->type == JSON_STRING)
146 1
              || (state_p->tokens_p->type == JSON_PRIMITIVE))) {
147 1
            return (-1);
148
        }
149

150 1
        res = dump(state_p);
151

152 1
        if (res < 0) {
153 1
            return (res);
154
        }
155

156 1
        size += res;
157

158
        /* Key-value pair colon. */
159 1
        std_fprintf(state_p->out_p, FSTR(":"));
160 1
        size++;
161

162
        /* Value. */
163 1
        res = dump(state_p);
164

165 1
        if (res < 0) {
166 1
            return (-1);
167
        }
168

169 1
        size += res;
170 1
        delim_p = FSTR(",");
171
    }
172

173 1
    std_fprintf(state_p->out_p, FSTR("}"));
174

175 1
    return (size);
176
}
177

178
/**
179
 * Recursively dump given array token and its children.
180
 */
181 1
static ssize_t dump_array(struct dump_t *state_p,
182
                          struct json_tok_t *token_p)
183
{
184
    ssize_t size, res, i;
185
    const char *delim_p;
186

187 1
    std_fprintf(state_p->out_p, FSTR("["));
188 1
    size = 2;
189 1
    delim_p = FSTR("");
190

191 1
    for (i = 0; i < token_p->num_tokens; i++) {
192
        /* Delimiter. */
193 1
        res = std_fprintf(state_p->out_p, delim_p);
194 1
        size += res;
195

196 1
        res = dump(state_p);
197

198 1
        if (res < 0) {
199 1
            return (-1);
200
        }
201

202 1
        size += res;
203 1
        delim_p = FSTR(",");
204
    }
205

206 1
    std_fprintf(state_p->out_p, FSTR("]"));
207

208 1
    return (size);
209
}
210

211
/**
212
 * Dump given string token.
213
 */
214 1
static ssize_t dump_string(struct dump_t *state_p,
215
                           struct json_tok_t *token_p)
216
{
217
    int i;
218

219 1
    std_fprintf(state_p->out_p, FSTR("\""));
220

221 1
    for (i = 0; i < token_p->size; i++) {
222 1
        if (!isprint((int)token_p->buf_p[i])) {
223 1
            return (-1);
224
        }
225

226 1
        std_fprintf(state_p->out_p, FSTR("%c"), token_p->buf_p[i]);
227
    }
228

229 1
    std_fprintf(state_p->out_p, FSTR("\""));
230

231 1
    return (token_p->size + 2);
232
}
233

234
/**
235
 * Dump given primitive token.
236
 */
237 1
static ssize_t dump_primitive(struct dump_t *state_p,
238
                              struct json_tok_t *token_p)
239
{
240
    int i;
241

242 1
    for (i = 0; i < token_p->size; i++) {
243 1
        std_fprintf(state_p->out_p, FSTR("%c"), token_p->buf_p[i]);
244
    }
245

246 1
    return (token_p->size);
247
}
248

249
/**
250
 * Recursively dumps one token and it's children.
251
 */
252 1
static ssize_t dump(struct dump_t *state_p)
253
{
254
    ssize_t size;
255
    struct json_tok_t *token_p;
256

257 1
    if (state_p->num_tokens == 0) {
258 1
        return (-1);
259
    }
260

261 1
    token_p = state_p->tokens_p;
262 1
    state_p->num_tokens--;
263 1
    state_p->tokens_p++;
264

265 1
    switch (token_p->type) {
266

267
    case JSON_OBJECT:
268 1
        size = dump_object(state_p, token_p);
269 1
        break;
270

271
    case JSON_ARRAY:
272 1
        size = dump_array(state_p, token_p);
273 1
        break;
274

275
    case JSON_STRING:
276 1
        size = dump_string(state_p, token_p);
277 1
        break;
278

279
    case JSON_PRIMITIVE:
280 1
        size = dump_primitive(state_p, token_p);
281 1
        break;
282

283
    default:
284 1
        size = -1;
285 1
        break;
286
    }
287

288 1
    return (size);
289
}
290

291
/**
292
 * Fills next available token with JSON primitive.
293
 */
294 1
static int parse_primitive(struct json_t *self_p,
295
                           const char *js_p,
296
                           size_t len)
297
{
298
    struct json_tok_t *token_p;
299
    int start;
300

301 1
    start = self_p->pos;
302

303 1
    for (; ((self_p->pos < len)
304 1
            && (js_p[self_p->pos] != '\0')); self_p->pos++) {
305 1
        switch (js_p[self_p->pos]) {
306

307
#ifndef JSON_STRICT
308
        case ':':
309
            /* In strict mode primitive must be followed by "," or "}"
310
               or "]" */
311
#endif
312

313
        case '\t':
314
        case '\r':
315
        case '\n':
316
        case ' ':
317
        case ',':
318
        case ']':
319
        case '}' :
320 1
            goto found;
321
        }
322

323 1
        if ((js_p[self_p->pos] < 32) || (js_p[self_p->pos] >= 127)) {
324 1
            self_p->pos = start;
325

326 1
            return (JSON_ERROR_INVAL);
327
        }
328
    }
329

330
#ifdef JSON_STRICT
331
    /* In strict mode primitive must be followed by a comma/object/array */
332
    self_p->pos = start;
333

334
    return (JSON_ERROR_PART);
335
#endif
336

337
 found:
338

339 1
    if (self_p->tokens_p == NULL) {
340 1
        self_p->pos--;
341 1
        return (0);
342
    }
343

344 1
    token_p = alloc_token(self_p);
345

346 1
    if (token_p == NULL) {
347 1
        self_p->pos = start;
348

349 1
        return (JSON_ERROR_NOMEM);
350
    }
351

352 1
    fill_token(token_p, JSON_PRIMITIVE, js_p + start, self_p->pos - start);
353

354
#ifdef JSON_PARENT_LINKS
355
    token_p->parent = self_p->toksuper;
356
#endif
357

358 1
    self_p->pos--;
359

360 1
    return (0);
361
}
362

363
/**
364
 * Fills next token with JSON string.
365
 */
366 1
static int parse_string(struct json_t *self_p,
367
                        const char *js_p,
368
                        size_t len)
369
{
370
    struct json_tok_t *token_p;
371

372 1
    int start = self_p->pos;
373

374 1
    self_p->pos++;
375

376
    /* Skip starting quote */
377 1
    for (; ((self_p->pos < len)
378 1
            && (js_p[self_p->pos] != '\0')); self_p->pos++) {
379 1
        char c = js_p[self_p->pos];
380

381
        /* Quote: end of string */
382 1
        if (c == '\"') {
383 1
            if (self_p->tokens_p == NULL) {
384 1
                return (0);
385
            }
386

387 1
            token_p = alloc_token(self_p);
388

389 1
            if (token_p == NULL) {
390 1
                self_p->pos = start;
391

392 1
                return (JSON_ERROR_NOMEM);
393
            }
394

395 1
            fill_token(token_p,
396
                       JSON_STRING,
397 1
                       js_p + start + 1,
398 1
                       self_p->pos - start - 1);
399
#ifdef JSON_PARENT_LINKS
400
            token_p->parent = self_p->toksuper;
401
#endif
402

403 1
            return (0);
404
        }
405

406
        /* Backslash: Quoted symbol expected */
407 1
        if ((c == '\\') && (self_p->pos + 1 < len)) {
408
            int i;
409

410 1
            self_p->pos++;
411

412 1
            switch (js_p[self_p->pos]) {
413

414
                /* Allowed escaped symbols */
415
            case '\"':
416
            case '/':
417
            case '\\':
418
            case 'b':
419
            case 'f':
420
            case 'r':
421
            case 'n':
422
            case 't':
423 1
                break;
424

425
                /* Allows escaped symbol \uXXXX */
426
            case 'u':
427 1
                self_p->pos++;
428

429 1
                for(i = 0; ((i < 4)
430 1
                            && (self_p->pos < len)
431 1
                            && (js_p[self_p->pos] != '\0')); i++) {
432
                    /* If it isn't a hex character we have an error */
433 1
                    if(!(((js_p[self_p->pos] >= 48)
434 1
                          && (js_p[self_p->pos] <= 57))
435 1
                         || /* 0-9 */
436 1
                         ((js_p[self_p->pos] >= 65)
437 1
                          && (js_p[self_p->pos] <= 70))
438
                         || /* A-F */
439 1
                         ((js_p[self_p->pos] >= 97)
440 1
                          && (js_p[self_p->pos] <= 102)))) { /* a-f */
441 1
                        self_p->pos = start;
442

443 1
                        return (JSON_ERROR_INVAL);
444
                    }
445

446 1
                    self_p->pos++;
447
                }
448

449 1
                self_p->pos--;
450 1
                break;
451

452
                /* Unexpected symbol */
453
            default:
454 1
                self_p->pos = start;
455

456 1
                return (JSON_ERROR_INVAL);
457
            }
458
        }
459
    }
460

461 1
    self_p->pos = start;
462

463 1
    return (JSON_ERROR_PART);
464
}
465

466
/**
467
 * Recursively get the number of child tokens of given token.
468
 */
469 1
static int get_number_of_children(struct json_tok_t *token_p)
470
{
471
    int i;
472
    int number_of_children;
473
    struct json_tok_t *child_p;
474

475 1
    number_of_children = 0;
476

477 1
    for (i = 0; i < token_p->num_tokens; i++) {
478 1
        child_p = &token_p[number_of_children + 1 + i];
479

480 1
        if (child_p->num_tokens > 0) {
481 1
            number_of_children += get_number_of_children(child_p);
482
        }
483
    }
484

485 1
    number_of_children += token_p->num_tokens;
486

487 1
    return (number_of_children);
488
}
489

490 1
static struct json_tok_t *object_get(struct json_t *self_p,
491
                                     const char *key_p,
492
                                     struct json_tok_t *object_p,
493
                                     int type)
494
{
495 1
    ASSERTNRN(self_p != NULL, EINVAL);
496 1
    ASSERTNRN(key_p != NULL, EINVAL);
497

498
    int i;
499
    int key_length;
500
    int number_of_children;
501
    struct json_tok_t *token_p;
502

503
    /* Return immediatly if no object is found. */
504 1
    if (object_p == NULL) {
505 1
        return (NULL);
506
    }
507

508
    /* Check that the token is an object. */
509 1
    if (object_p->type != JSON_OBJECT) {
510 1
        return (NULL);
511
    }
512

513 1
    key_length = strlen(key_p);
514

515
    /* The first child token. */
516 1
    token_p = (object_p + 1);
517

518
    /* Find given key in the object. */
519 1
    for (i = 0; i < object_p->num_tokens; i++) {
520 1
        if (token_p->type == type) {
521 1
            if (strncmp(key_p, token_p->buf_p, key_length) == 0) {
522 1
                return (token_p + 1);
523
            }
524
        }
525

526
        /* Get the next child token. */
527 1
        number_of_children = get_number_of_children(token_p);
528 1
        token_p += (number_of_children + 1);
529
    }
530

531 1
    return (NULL);
532
}
533

534 1
int json_init(struct json_t *self_p,
535
              struct json_tok_t *tokens_p,
536
              int num_tokens)
537
{
538 1
    ASSERTN(self_p != NULL, EINVAL);
539 1
    ASSERTN(((tokens_p != NULL) && (num_tokens > 0))
540
            || (num_tokens == 0), EINVAL);
541

542 1
    self_p->pos = 0;
543 1
    self_p->toknext = 0;
544 1
    self_p->toksuper = -1;
545 1
    self_p->tokens_p = tokens_p;
546 1
    self_p->num_tokens = num_tokens;
547

548 1
    return (0);
549
}
550

551 1
int json_parse(struct json_t *self_p,
552
               const char *js_p,
553
               size_t len)
554
{
555 1
    ASSERTN(self_p != NULL, EINVAL);
556 1
    ASSERTN(js_p != NULL, EINVAL);
557 1
    ASSERTN(len > 0, EINVAL);
558

559
    int r;
560
    int i;
561
    struct json_tok_t *token_p;
562
    int count;
563

564 1
    count = self_p->toknext;
565

566 1
    for (; ((self_p->pos < len)
567 1
            && (js_p[self_p->pos] != '\0')); self_p->pos++) {
568
        char c;
569
        enum json_type_t type;
570

571 1
        c = js_p[self_p->pos];
572

573 1
        switch (c) {
574

575
        case '{':
576
        case '[':
577 1
            count++;
578

579 1
            if (self_p->tokens_p == NULL) {
580 1
                break;
581
            }
582

583 1
            token_p = alloc_token(self_p);
584

585 1
            if (token_p == NULL) {
586 1
                return (JSON_ERROR_NOMEM);
587
            }
588

589 1
            if (self_p->toksuper != -1) {
590 1
                self_p->tokens_p[self_p->toksuper].num_tokens++;
591
#ifdef JSON_PARENT_LINKS
592
                token_p->parent = self_p->toksuper;
593
#endif
594
            }
595

596 1
            token_p->type = (c == '{' ? JSON_OBJECT : JSON_ARRAY);
597 1
            token_p->buf_p = js_p + self_p->pos;
598 1
            self_p->toksuper = self_p->toknext - 1;
599 1
            break;
600

601
        case '}':
602
        case ']':
603 1
            if (self_p->tokens_p == NULL) {
604 1
                break;
605
            }
606

607 1
            type = (c == '}' ? JSON_OBJECT : JSON_ARRAY);
608

609
#ifdef JSON_PARENT_LINKS
610
            if (self_p->toknext < 1) {
611
                return (JSON_ERROR_INVAL);
612
            }
613

614
            token = &tokens_p[self_p->toknext - 1];
615

616
            for (;;) {
617
                if ((token_p->start != -1) && (token_p->end == -1)) {
618
                    if (token_p->type != type) {
619
                        return (JSON_ERROR_INVAL);
620
                    }
621

622
                    token_p->size = (&js_p[self_p->pos]
623
                                     - self_p->buf_p + 1);
624
                    self_p->toksuper = token_p->parent;
625
                    break;
626
                }
627

628
                if (token_p->parent == -1) {
629
                    break;
630
                }
631

632
                token = &tokens_p[token_p->parent];
633
            }
634
#else
635 1
            for (i = self_p->toknext - 1; i >= 0; i--) {
636 1
                token_p = &self_p->tokens_p[i];
637

638 1
                if ((token_p->buf_p != NULL) && (token_p->size == -1)) {
639 1
                    if (token_p->type != type) {
640 1
                        return (JSON_ERROR_INVAL);
641
                    }
642

643 1
                    self_p->toksuper = -1;
644 1
                    token_p->size = (&js_p[self_p->pos]
645 1
                                     - token_p->buf_p + 1);
646 1
                    break;
647
                }
648
            }
649

650
            /* Error if unmatched closing bracket */
651 1
            if (i == -1) {
652 1
                return (JSON_ERROR_INVAL);
653
            }
654

655 1
            for (; i >= 0; i--) {
656 1
                token_p = &self_p->tokens_p[i];
657

658 1
                if ((token_p->buf_p != NULL) && (token_p->size == -1)) {
659 1
                    self_p->toksuper = i;
660 1
                    break;
661
                }
662
            }
663
#endif
664 1
            break;
665
        case '\"':
666 1
            r = parse_string(self_p, js_p, len);
667

668 1
            if (r < 0) {
669 1
                return (r);
670
            }
671

672 1
            count++;
673

674 1
            if ((self_p->toksuper != -1) && (self_p->tokens_p != NULL)) {
675 1
                self_p->tokens_p[self_p->toksuper].num_tokens++;
676
            }
677

678 1
            break;
679

680
        case '\t':
681
        case '\r':
682
        case '\n':
683
        case ' ':
684 1
            break;
685

686
        case ':':
687 1
            self_p->toksuper = self_p->toknext - 1;
688 1
            break;
689

690
        case ',':
691 1
            if ((self_p->tokens_p != NULL)
692 1
                && (self_p->toksuper != -1)
693 1
                && (self_p->tokens_p[self_p->toksuper].type != JSON_ARRAY)
694 1
                && (self_p->tokens_p[self_p->toksuper].type != JSON_OBJECT)) {
695
#ifdef JSON_PARENT_LINKS
696
                self_p->toksuper = tokens_p[self_p->toksuper].parent;
697
#else
698 1
                for (i = self_p->toknext - 1; i >= 0; i--) {
699 1
                    if ((self_p->tokens_p[i].type == JSON_ARRAY)
700 1
                        || (self_p->tokens_p[i].type == JSON_OBJECT)) {
701 1
                        if ((self_p->tokens_p[i].buf_p != NULL)
702 1
                            && (self_p->tokens_p[i].size == -1)) {
703 1
                            self_p->toksuper = i;
704 1
                            break;
705
                        }
706
                    }
707
                }
708
#endif
709
            }
710 1
            break;
711

712
#ifdef JSON_STRICT
713
            /* In strict mode primitives are: numbers and booleans */
714
        case '-':
715
        case '0':
716
        case '1':
717
        case '2':
718
        case '3':
719
        case '4':
720
        case '5':
721
        case '6':
722
        case '7':
723
        case '8':
724
        case '9':
725
        case 't':
726
        case 'f':
727
        case 'n':
728
            /* And they must not be keys of the object */
729
            if ((tokens != NULL) && (self_p->toksuper != -1)) {
730
                struct json_tok_t *t = &tokens_p[self_p->toksuper];
731

732
                if ((t_p->type == JSON_OBJECT)
733
                    || ((t_p->type == JSON_STRING)
734
                        && (t_p->size != 0))) {
735
                    return (JSON_ERROR_INVAL);
736
                }
737
            }
738
#else
739

740
            /* In non-strict mode every unquoted value is a primitive */
741
        default:
742
#endif
743 1
            r = parse_primitive(self_p, js_p, len);
744

745 1
            if (r < 0) {
746 1
                return (r);
747
            }
748

749 1
            count++;
750

751 1
            if ((self_p->toksuper != -1) && (self_p->tokens_p != NULL)) {
752 1
                self_p->tokens_p[self_p->toksuper].num_tokens++;
753
            }
754

755 1
            break;
756

757
#ifdef JSON_STRICT
758

759
            /* Unexpected char in strict mode */
760
        default:
761
            return (JSON_ERROR_INVAL);
762
#endif
763
        }
764
    }
765

766 1
    if (self_p->tokens_p != NULL) {
767 1
        for (i = self_p->toknext - 1; i >= 0; i--) {
768
            /* Unmatched opened object or array */
769 1
            if ((self_p->tokens_p[i].buf_p != NULL) && (self_p->tokens_p[i].size == -1)) {
770 1
                return (JSON_ERROR_PART);
771
            }
772
        }
773
    }
774

775 1
    return (count);
776
}
777

778 1
ssize_t json_dumps(struct json_t *self_p,
779
                   struct json_tok_t *tokens_p,
780
                   char *js_p)
781
{
782 1
    ASSERTN(self_p != NULL, EINVAL);
783 1
    ASSERTN(js_p != NULL, EINVAL);
784

785
    ssize_t res;
786
    struct string_t string;
787

788 1
    chan_init(&string.base, chan_read_null, string_write, chan_size_null);
789 1
    string.buf_p = js_p;
790 1
    string.pos = 0;
791

792 1
    res = json_dump(self_p, tokens_p, &string);
793

794 1
    if (res < 0) {
795 1
        return (res);
796
    }
797

798 1
    return (chan_write(&string, "\0", 1) == 1 ? res : -1);
799
}
800

801 1
ssize_t json_dump(struct json_t *self_p,
802
                  struct json_tok_t *tokens_p,
803
                  void *out_p)
804
{
805 1
    ASSERTN(self_p != NULL, EINVAL);
806 1
    ASSERTN(out_p != NULL, EINVAL);
807

808
    struct dump_t state;
809

810 1
    if (tokens_p == NULL) {
811 1
        tokens_p = self_p->tokens_p;
812
    }
813

814
    /* The first token must be an object or an array. */
815 1
    if (!((tokens_p->type == JSON_OBJECT)
816 1
          || (tokens_p->type == JSON_ARRAY))) {
817 1
        return (-1);
818
    }
819

820 1
    state.tokens_p = tokens_p;
821 1
    state.num_tokens = self_p->num_tokens;
822 1
    state.out_p = out_p;
823

824 1
    return (dump(&state));
825
}
826

827 1
struct json_tok_t *json_root(struct json_t *self_p)
828
{
829 1
    return (self_p->tokens_p);
830
}
831

832 1
struct json_tok_t *json_object_get(struct json_t *self_p,
833
                                   const char *key_p,
834
                                   struct json_tok_t *object_p)
835
{
836 1
    return (object_get(self_p, key_p, object_p, JSON_STRING));
837
}
838

839 1
struct json_tok_t *json_object_get_primitive(struct json_t *self_p,
840
                                             const char *key_p,
841
                                             struct json_tok_t *object_p)
842
{
843 1
    return (object_get(self_p, key_p, object_p, JSON_PRIMITIVE));
844
}
845

846 1
struct json_tok_t *json_array_get(struct json_t *self_p,
847
                                  int index,
848
                                  struct json_tok_t *array_p)
849
{
850 1
    ASSERTNRN(self_p != NULL, EINVAL);
851 1
    ASSERTNRN(index >= 0, EINVAL);
852

853
    int i;
854
    int number_of_children;
855
    struct json_tok_t *token_p;
856

857
    /* Return immediatly if no array is found. */
858 1
    if (array_p == NULL) {
859 1
        return (NULL);
860
    }
861

862
    /* Check that the token is an array. */
863 1
    if (array_p->type != JSON_ARRAY) {
864 1
        return (NULL);
865
    }
866

867
    /* The first child token. */
868 1
    token_p = (array_p + 1);
869

870
    /* Find given key in the object. */
871 1
    for (i = 0; i < array_p->num_tokens; i++) {
872 1
        if (i == index) {
873 1
            return (token_p);
874
        }
875

876
        /* Get the next child token. */
877 1
        number_of_children = get_number_of_children(token_p);
878 1
        token_p += (number_of_children + 1);
879
    }
880

881 1
    return (NULL);
882
}
883

884 1
void json_token_object(struct json_tok_t *token_p,
885
                       int num_keys)
886
{
887 1
    token_p->type = JSON_OBJECT;
888 1
    token_p->buf_p = NULL;
889 1
    token_p->size = -1;
890 1
    token_p->num_tokens = num_keys;
891
}
892

893 1
void json_token_array(struct json_tok_t *token_p,
894
                      int num_elements)
895
{
896 1
    token_p->type = JSON_ARRAY;
897 1
    token_p->buf_p = NULL;
898 1
    token_p->size = -1;
899 1
    token_p->num_tokens = num_elements;
900
}
901

902 1
void json_token_true(struct json_tok_t *token_p)
903
{
904 1
    token_p->type = JSON_PRIMITIVE;
905 1
    token_p->buf_p = "true";
906 1
    token_p->size = 4;
907 1
    token_p->num_tokens = -1;
908
}
909

910 1
void json_token_false(struct json_tok_t *token_p)
911
{
912 1
    token_p->type = JSON_PRIMITIVE;
913 1
    token_p->buf_p = "false";
914 1
    token_p->size = 5;
915 1
    token_p->num_tokens = -1;
916
}
917

918 1
void json_token_null(struct json_tok_t *token_p)
919
{
920 1
    token_p->type = JSON_PRIMITIVE;
921 1
    token_p->buf_p = "null";
922 1
    token_p->size = 4;
923 1
    token_p->num_tokens = -1;
924
}
925

926 1
void json_token_number(struct json_tok_t *token_p,
927
                       const char *buf_p,
928
                       size_t size)
929
{
930 1
    token_p->type = JSON_PRIMITIVE;
931 1
    token_p->buf_p = buf_p;
932 1
    token_p->size = size;
933 1
    token_p->num_tokens = -1;
934
}
935

936 1
void json_token_string(struct json_tok_t *token_p,
937
                       const char *buf_p,
938
                       size_t size)
939
{
940 1
    token_p->type = JSON_STRING;
941 1
    token_p->buf_p = buf_p;
942 1
    token_p->size = size;
943 1
    token_p->num_tokens = -1;
944
}

Read our documentation on viewing source code .

Loading