148c779cdSXin LI /*- 248c779cdSXin LI * Copyright (c) 2018 Christos Zoulas 348c779cdSXin LI * All rights reserved. 448c779cdSXin LI * 548c779cdSXin LI * Redistribution and use in source and binary forms, with or without 648c779cdSXin LI * modification, are permitted provided that the following conditions 748c779cdSXin LI * are met: 848c779cdSXin LI * 1. Redistributions of source code must retain the above copyright 948c779cdSXin LI * notice, this list of conditions and the following disclaimer. 1048c779cdSXin LI * 2. Redistributions in binary form must reproduce the above copyright 1148c779cdSXin LI * notice, this list of conditions and the following disclaimer in the 1248c779cdSXin LI * documentation and/or other materials provided with the distribution. 1348c779cdSXin LI * 1448c779cdSXin LI * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1548c779cdSXin LI * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1648c779cdSXin LI * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1748c779cdSXin LI * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 1848c779cdSXin LI * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1948c779cdSXin LI * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2048c779cdSXin LI * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2148c779cdSXin LI * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2248c779cdSXin LI * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2348c779cdSXin LI * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2448c779cdSXin LI * POSSIBILITY OF SUCH DAMAGE. 2548c779cdSXin LI */ 2648c779cdSXin LI 2748c779cdSXin LI /* 2848c779cdSXin LI * Parse JSON object serialization format (RFC-7159) 2948c779cdSXin LI */ 3048c779cdSXin LI 3148c779cdSXin LI #ifndef TEST 3248c779cdSXin LI #include "file.h" 3348c779cdSXin LI 3448c779cdSXin LI #ifndef lint 35*a2dfb722SXin LI FILE_RCSID("@(#)$File: is_json.c,v 1.26 2022/09/13 18:46:07 christos Exp $") 3648c779cdSXin LI #endif 3748c779cdSXin LI 3848c779cdSXin LI #include "magic.h" 39a4d6d3b8SXin LI #else 40a4d6d3b8SXin LI #include <stdio.h> 41a4d6d3b8SXin LI #include <stddef.h> 4248c779cdSXin LI #endif 43a4d6d3b8SXin LI #include <string.h> 4448c779cdSXin LI 4548c779cdSXin LI #ifdef DEBUG 4648c779cdSXin LI #include <stdio.h> 4748c779cdSXin LI #define DPRINTF(a, b, c) \ 48a4d6d3b8SXin LI printf("%*s%s [%.2x/%c] %.*s\n", (int)lvl, "", (a), *(b), *(b), \ 49a4d6d3b8SXin LI (int)(b - c), (const char *)(c)) 50a4d6d3b8SXin LI #define __file_debugused 5148c779cdSXin LI #else 5248c779cdSXin LI #define DPRINTF(a, b, c) do { } while (/*CONSTCOND*/0) 53a4d6d3b8SXin LI #define __file_debugused __attribute__((__unused__)) 5448c779cdSXin LI #endif 5548c779cdSXin LI 5648c779cdSXin LI #define JSON_ARRAY 0 5748c779cdSXin LI #define JSON_CONSTANT 1 5848c779cdSXin LI #define JSON_NUMBER 2 5948c779cdSXin LI #define JSON_OBJECT 3 6048c779cdSXin LI #define JSON_STRING 4 6148c779cdSXin LI #define JSON_ARRAYN 5 6248c779cdSXin LI #define JSON_MAX 6 6348c779cdSXin LI 6448c779cdSXin LI /* 6548c779cdSXin LI * if JSON_COUNT != 0: 6648c779cdSXin LI * count all the objects, require that we have the whole data file 6748c779cdSXin LI * otherwise: 6848c779cdSXin LI * stop if we find an object or an array 6948c779cdSXin LI */ 7048c779cdSXin LI #ifndef JSON_COUNT 7148c779cdSXin LI #define JSON_COUNT 0 7248c779cdSXin LI #endif 7348c779cdSXin LI 7448c779cdSXin LI static int json_parse(const unsigned char **, const unsigned char *, size_t *, 7548c779cdSXin LI size_t); 7648c779cdSXin LI 7748c779cdSXin LI static int 7848c779cdSXin LI json_isspace(const unsigned char uc) 7948c779cdSXin LI { 8048c779cdSXin LI switch (uc) { 8148c779cdSXin LI case ' ': 8248c779cdSXin LI case '\n': 8348c779cdSXin LI case '\r': 8448c779cdSXin LI case '\t': 8548c779cdSXin LI return 1; 8648c779cdSXin LI default: 8748c779cdSXin LI return 0; 8848c779cdSXin LI } 8948c779cdSXin LI } 9048c779cdSXin LI 9148c779cdSXin LI static int 9248c779cdSXin LI json_isdigit(unsigned char uc) 9348c779cdSXin LI { 9448c779cdSXin LI switch (uc) { 9548c779cdSXin LI case '0': case '1': case '2': case '3': case '4': 9648c779cdSXin LI case '5': case '6': case '7': case '8': case '9': 9748c779cdSXin LI return 1; 9848c779cdSXin LI default: 9948c779cdSXin LI return 0; 10048c779cdSXin LI } 10148c779cdSXin LI } 10248c779cdSXin LI 10348c779cdSXin LI static int 10448c779cdSXin LI json_isxdigit(unsigned char uc) 10548c779cdSXin LI { 10648c779cdSXin LI if (json_isdigit(uc)) 10748c779cdSXin LI return 1; 10848c779cdSXin LI switch (uc) { 10948c779cdSXin LI case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 11048c779cdSXin LI case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 11148c779cdSXin LI return 1; 11248c779cdSXin LI default: 11348c779cdSXin LI return 0; 11448c779cdSXin LI } 11548c779cdSXin LI } 11648c779cdSXin LI 11748c779cdSXin LI static const unsigned char * 11848c779cdSXin LI json_skip_space(const unsigned char *uc, const unsigned char *ue) 11948c779cdSXin LI { 12048c779cdSXin LI while (uc < ue && json_isspace(*uc)) 12148c779cdSXin LI uc++; 12248c779cdSXin LI return uc; 12348c779cdSXin LI } 12448c779cdSXin LI 125*a2dfb722SXin LI /*ARGSUSED*/ 12648c779cdSXin LI static int 127a4d6d3b8SXin LI json_parse_string(const unsigned char **ucp, const unsigned char *ue, 128a4d6d3b8SXin LI size_t lvl __file_debugused) 12948c779cdSXin LI { 13048c779cdSXin LI const unsigned char *uc = *ucp; 13148c779cdSXin LI size_t i; 13248c779cdSXin LI 13348c779cdSXin LI DPRINTF("Parse string: ", uc, *ucp); 13448c779cdSXin LI while (uc < ue) { 13548c779cdSXin LI switch (*uc++) { 13648c779cdSXin LI case '\0': 13748c779cdSXin LI goto out; 13848c779cdSXin LI case '\\': 13948c779cdSXin LI if (uc == ue) 14048c779cdSXin LI goto out; 14148c779cdSXin LI switch (*uc++) { 14248c779cdSXin LI case '\0': 14348c779cdSXin LI goto out; 14448c779cdSXin LI case '"': 14548c779cdSXin LI case '\\': 14648c779cdSXin LI case '/': 14748c779cdSXin LI case 'b': 14848c779cdSXin LI case 'f': 14948c779cdSXin LI case 'n': 15048c779cdSXin LI case 'r': 15148c779cdSXin LI case 't': 15248c779cdSXin LI continue; 15348c779cdSXin LI case 'u': 15448c779cdSXin LI if (ue - uc < 4) { 15548c779cdSXin LI uc = ue; 15648c779cdSXin LI goto out; 15748c779cdSXin LI } 15848c779cdSXin LI for (i = 0; i < 4; i++) 15948c779cdSXin LI if (!json_isxdigit(*uc++)) 16048c779cdSXin LI goto out; 16148c779cdSXin LI continue; 16248c779cdSXin LI default: 16348c779cdSXin LI goto out; 16448c779cdSXin LI } 16548c779cdSXin LI case '"': 1662726a701SXin LI DPRINTF("Good string: ", uc, *ucp); 167a4d6d3b8SXin LI *ucp = uc; 16848c779cdSXin LI return 1; 16948c779cdSXin LI default: 17048c779cdSXin LI continue; 17148c779cdSXin LI } 17248c779cdSXin LI } 17348c779cdSXin LI out: 17448c779cdSXin LI DPRINTF("Bad string: ", uc, *ucp); 17548c779cdSXin LI *ucp = uc; 17648c779cdSXin LI return 0; 17748c779cdSXin LI } 17848c779cdSXin LI 17948c779cdSXin LI static int 18048c779cdSXin LI json_parse_array(const unsigned char **ucp, const unsigned char *ue, 18148c779cdSXin LI size_t *st, size_t lvl) 18248c779cdSXin LI { 18348c779cdSXin LI const unsigned char *uc = *ucp; 18448c779cdSXin LI 18548c779cdSXin LI DPRINTF("Parse array: ", uc, *ucp); 18648c779cdSXin LI while (uc < ue) { 187*a2dfb722SXin LI uc = json_skip_space(uc, ue); 188*a2dfb722SXin LI if (uc == ue) 189*a2dfb722SXin LI goto out; 1902726a701SXin LI if (*uc == ']') 1912726a701SXin LI goto done; 19248c779cdSXin LI if (!json_parse(&uc, ue, st, lvl + 1)) 19348c779cdSXin LI goto out; 19448c779cdSXin LI if (uc == ue) 19548c779cdSXin LI goto out; 19648c779cdSXin LI switch (*uc) { 19748c779cdSXin LI case ',': 19848c779cdSXin LI uc++; 19948c779cdSXin LI continue; 20048c779cdSXin LI case ']': 2012726a701SXin LI done: 20248c779cdSXin LI st[JSON_ARRAYN]++; 2032726a701SXin LI DPRINTF("Good array: ", uc, *ucp); 204a4d6d3b8SXin LI *ucp = uc + 1; 20548c779cdSXin LI return 1; 20648c779cdSXin LI default: 20748c779cdSXin LI goto out; 20848c779cdSXin LI } 20948c779cdSXin LI } 21048c779cdSXin LI out: 21148c779cdSXin LI DPRINTF("Bad array: ", uc, *ucp); 21248c779cdSXin LI *ucp = uc; 21348c779cdSXin LI return 0; 21448c779cdSXin LI } 21548c779cdSXin LI 21648c779cdSXin LI static int 21748c779cdSXin LI json_parse_object(const unsigned char **ucp, const unsigned char *ue, 21848c779cdSXin LI size_t *st, size_t lvl) 21948c779cdSXin LI { 22048c779cdSXin LI const unsigned char *uc = *ucp; 22148c779cdSXin LI DPRINTF("Parse object: ", uc, *ucp); 22248c779cdSXin LI while (uc < ue) { 22348c779cdSXin LI uc = json_skip_space(uc, ue); 22448c779cdSXin LI if (uc == ue) 22548c779cdSXin LI goto out; 2262726a701SXin LI if (*uc == '}') { 2272726a701SXin LI uc++; 2282726a701SXin LI goto done; 2292726a701SXin LI } 23048c779cdSXin LI if (*uc++ != '"') { 23148c779cdSXin LI DPRINTF("not string", uc, *ucp); 23248c779cdSXin LI goto out; 23348c779cdSXin LI } 23448c779cdSXin LI DPRINTF("next field", uc, *ucp); 235a4d6d3b8SXin LI if (!json_parse_string(&uc, ue, lvl)) { 23648c779cdSXin LI DPRINTF("not string", uc, *ucp); 23748c779cdSXin LI goto out; 23848c779cdSXin LI } 23948c779cdSXin LI uc = json_skip_space(uc, ue); 24048c779cdSXin LI if (uc == ue) 24148c779cdSXin LI goto out; 24248c779cdSXin LI if (*uc++ != ':') { 24348c779cdSXin LI DPRINTF("not colon", uc, *ucp); 24448c779cdSXin LI goto out; 24548c779cdSXin LI } 24648c779cdSXin LI if (!json_parse(&uc, ue, st, lvl + 1)) { 24748c779cdSXin LI DPRINTF("not json", uc, *ucp); 24848c779cdSXin LI goto out; 24948c779cdSXin LI } 25048c779cdSXin LI if (uc == ue) 25148c779cdSXin LI goto out; 25248c779cdSXin LI switch (*uc++) { 25348c779cdSXin LI case ',': 25448c779cdSXin LI continue; 25548c779cdSXin LI case '}': /* { */ 2562726a701SXin LI done: 25748c779cdSXin LI DPRINTF("Good object: ", uc, *ucp); 258a4d6d3b8SXin LI *ucp = uc; 25948c779cdSXin LI return 1; 26048c779cdSXin LI default: 26148c779cdSXin LI DPRINTF("not more", uc, *ucp); 262a4d6d3b8SXin LI *ucp = uc - 1; 26348c779cdSXin LI goto out; 26448c779cdSXin LI } 26548c779cdSXin LI } 26648c779cdSXin LI out: 26748c779cdSXin LI DPRINTF("Bad object: ", uc, *ucp); 26848c779cdSXin LI *ucp = uc; 26948c779cdSXin LI return 0; 27048c779cdSXin LI } 27148c779cdSXin LI 272*a2dfb722SXin LI /*ARGSUSED*/ 27348c779cdSXin LI static int 274a4d6d3b8SXin LI json_parse_number(const unsigned char **ucp, const unsigned char *ue, 275a4d6d3b8SXin LI size_t lvl __file_debugused) 27648c779cdSXin LI { 27748c779cdSXin LI const unsigned char *uc = *ucp; 27848c779cdSXin LI int got = 0; 27948c779cdSXin LI 28048c779cdSXin LI DPRINTF("Parse number: ", uc, *ucp); 28148c779cdSXin LI if (uc == ue) 28248c779cdSXin LI return 0; 28348c779cdSXin LI if (*uc == '-') 28448c779cdSXin LI uc++; 28548c779cdSXin LI 28648c779cdSXin LI for (; uc < ue; uc++) { 28748c779cdSXin LI if (!json_isdigit(*uc)) 28848c779cdSXin LI break; 28948c779cdSXin LI got = 1; 29048c779cdSXin LI } 29148c779cdSXin LI if (uc == ue) 29248c779cdSXin LI goto out; 29348c779cdSXin LI if (*uc == '.') 29448c779cdSXin LI uc++; 29548c779cdSXin LI for (; uc < ue; uc++) { 29648c779cdSXin LI if (!json_isdigit(*uc)) 29748c779cdSXin LI break; 29848c779cdSXin LI got = 1; 29948c779cdSXin LI } 30048c779cdSXin LI if (uc == ue) 30148c779cdSXin LI goto out; 30248c779cdSXin LI if (got && (*uc == 'e' || *uc == 'E')) { 30348c779cdSXin LI uc++; 30448c779cdSXin LI got = 0; 30548c779cdSXin LI if (uc == ue) 30648c779cdSXin LI goto out; 30748c779cdSXin LI if (*uc == '+' || *uc == '-') 30848c779cdSXin LI uc++; 30948c779cdSXin LI for (; uc < ue; uc++) { 31048c779cdSXin LI if (!json_isdigit(*uc)) 31148c779cdSXin LI break; 31248c779cdSXin LI got = 1; 31348c779cdSXin LI } 31448c779cdSXin LI } 31548c779cdSXin LI out: 31648c779cdSXin LI if (!got) 31748c779cdSXin LI DPRINTF("Bad number: ", uc, *ucp); 31848c779cdSXin LI else 31948c779cdSXin LI DPRINTF("Good number: ", uc, *ucp); 32048c779cdSXin LI *ucp = uc; 32148c779cdSXin LI return got; 32248c779cdSXin LI } 32348c779cdSXin LI 324*a2dfb722SXin LI /*ARGSUSED*/ 32548c779cdSXin LI static int 32648c779cdSXin LI json_parse_const(const unsigned char **ucp, const unsigned char *ue, 327a4d6d3b8SXin LI const char *str, size_t len, size_t lvl __file_debugused) 32848c779cdSXin LI { 32948c779cdSXin LI const unsigned char *uc = *ucp; 33048c779cdSXin LI 33148c779cdSXin LI DPRINTF("Parse const: ", uc, *ucp); 332*a2dfb722SXin LI *ucp += --len - 1; 333*a2dfb722SXin LI if (*ucp > ue) 334*a2dfb722SXin LI *ucp = ue; 335*a2dfb722SXin LI for (; uc < ue && --len;) { 336*a2dfb722SXin LI if (*uc++ != *++str) { 33748c779cdSXin LI DPRINTF("Bad const: ", uc, *ucp); 338*a2dfb722SXin LI return 0; 339*a2dfb722SXin LI } 340*a2dfb722SXin LI } 341*a2dfb722SXin LI DPRINTF("Good const: ", uc, *ucp); 342*a2dfb722SXin LI return 1; 34348c779cdSXin LI } 34448c779cdSXin LI 34548c779cdSXin LI static int 34648c779cdSXin LI json_parse(const unsigned char **ucp, const unsigned char *ue, 34748c779cdSXin LI size_t *st, size_t lvl) 34848c779cdSXin LI { 349*a2dfb722SXin LI const unsigned char *uc, *ouc; 35048c779cdSXin LI int rv = 0; 35148c779cdSXin LI int t; 35248c779cdSXin LI 353*a2dfb722SXin LI ouc = uc = json_skip_space(*ucp, ue); 35448c779cdSXin LI if (uc == ue) 35548c779cdSXin LI goto out; 35648c779cdSXin LI 35748c779cdSXin LI // Avoid recursion 358a4d6d3b8SXin LI if (lvl > 500) { 359a4d6d3b8SXin LI DPRINTF("Too many levels", uc, *ucp); 36048c779cdSXin LI return 0; 361a4d6d3b8SXin LI } 36248c779cdSXin LI #if JSON_COUNT 36348c779cdSXin LI /* bail quickly if not counting */ 36448c779cdSXin LI if (lvl > 1 && (st[JSON_OBJECT] || st[JSON_ARRAYN])) 36548c779cdSXin LI return 1; 36648c779cdSXin LI #endif 36748c779cdSXin LI 36848c779cdSXin LI DPRINTF("Parse general: ", uc, *ucp); 36948c779cdSXin LI switch (*uc++) { 37048c779cdSXin LI case '"': 371a4d6d3b8SXin LI rv = json_parse_string(&uc, ue, lvl + 1); 37248c779cdSXin LI t = JSON_STRING; 37348c779cdSXin LI break; 37448c779cdSXin LI case '[': 37548c779cdSXin LI rv = json_parse_array(&uc, ue, st, lvl + 1); 37648c779cdSXin LI t = JSON_ARRAY; 37748c779cdSXin LI break; 37848c779cdSXin LI case '{': /* '}' */ 37948c779cdSXin LI rv = json_parse_object(&uc, ue, st, lvl + 1); 38048c779cdSXin LI t = JSON_OBJECT; 38148c779cdSXin LI break; 38248c779cdSXin LI case 't': 383a4d6d3b8SXin LI rv = json_parse_const(&uc, ue, "true", sizeof("true"), lvl + 1); 38448c779cdSXin LI t = JSON_CONSTANT; 38548c779cdSXin LI break; 38648c779cdSXin LI case 'f': 387a4d6d3b8SXin LI rv = json_parse_const(&uc, ue, "false", sizeof("false"), 388a4d6d3b8SXin LI lvl + 1); 38948c779cdSXin LI t = JSON_CONSTANT; 39048c779cdSXin LI break; 39148c779cdSXin LI case 'n': 392a4d6d3b8SXin LI rv = json_parse_const(&uc, ue, "null", sizeof("null"), lvl + 1); 39348c779cdSXin LI t = JSON_CONSTANT; 39448c779cdSXin LI break; 39548c779cdSXin LI default: 39648c779cdSXin LI --uc; 397a4d6d3b8SXin LI rv = json_parse_number(&uc, ue, lvl + 1); 39848c779cdSXin LI t = JSON_NUMBER; 39948c779cdSXin LI break; 40048c779cdSXin LI } 40148c779cdSXin LI if (rv) 40248c779cdSXin LI st[t]++; 40348c779cdSXin LI uc = json_skip_space(uc, ue); 40448c779cdSXin LI out: 40548c779cdSXin LI DPRINTF("End general: ", uc, *ucp); 406a4d6d3b8SXin LI *ucp = uc; 407*a2dfb722SXin LI if (lvl == 0) { 408*a2dfb722SXin LI if (!rv) 409*a2dfb722SXin LI return 0; 410*a2dfb722SXin LI if (uc == ue) 411*a2dfb722SXin LI return (st[JSON_ARRAYN] || st[JSON_OBJECT]) ? 1 : 0; 412*a2dfb722SXin LI if (*ouc == *uc && json_parse(&uc, ue, st, 1)) 413*a2dfb722SXin LI return (st[JSON_ARRAYN] || st[JSON_OBJECT]) ? 2 : 0; 414*a2dfb722SXin LI else 415*a2dfb722SXin LI return 0; 416*a2dfb722SXin LI } 41748c779cdSXin LI return rv; 41848c779cdSXin LI } 41948c779cdSXin LI 42048c779cdSXin LI #ifndef TEST 42148c779cdSXin LI int 42248c779cdSXin LI file_is_json(struct magic_set *ms, const struct buffer *b) 42348c779cdSXin LI { 42448c779cdSXin LI const unsigned char *uc = CAST(const unsigned char *, b->fbuf); 42548c779cdSXin LI const unsigned char *ue = uc + b->flen; 42648c779cdSXin LI size_t st[JSON_MAX]; 42748c779cdSXin LI int mime = ms->flags & MAGIC_MIME; 428*a2dfb722SXin LI int jt; 42948c779cdSXin LI 43048c779cdSXin LI 43148c779cdSXin LI if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0) 43248c779cdSXin LI return 0; 43348c779cdSXin LI 43448c779cdSXin LI memset(st, 0, sizeof(st)); 43548c779cdSXin LI 436*a2dfb722SXin LI if ((jt = json_parse(&uc, ue, st, 0)) == 0) 43748c779cdSXin LI return 0; 43848c779cdSXin LI 43948c779cdSXin LI if (mime == MAGIC_MIME_ENCODING) 44048c779cdSXin LI return 1; 44148c779cdSXin LI if (mime) { 442*a2dfb722SXin LI if (file_printf(ms, "application/%s", 443*a2dfb722SXin LI jt == 1 ? "json" : "x-ndjason") == -1) 44448c779cdSXin LI return -1; 44548c779cdSXin LI return 1; 44648c779cdSXin LI } 447*a2dfb722SXin LI if (file_printf(ms, "%sJSON text data", 448*a2dfb722SXin LI jt == 1 ? "" : "New Line Delimited ") == -1) 44948c779cdSXin LI return -1; 45048c779cdSXin LI #if JSON_COUNT 45148c779cdSXin LI #define P(n) st[n], st[n] > 1 ? "s" : "" 45248c779cdSXin LI if (file_printf(ms, " (%" SIZE_T_FORMAT "u object%s, %" SIZE_T_FORMAT 45348c779cdSXin LI "u array%s, %" SIZE_T_FORMAT "u string%s, %" SIZE_T_FORMAT 45448c779cdSXin LI "u constant%s, %" SIZE_T_FORMAT "u number%s, %" SIZE_T_FORMAT 45548c779cdSXin LI "u >1array%s)", 45648c779cdSXin LI P(JSON_OBJECT), P(JSON_ARRAY), P(JSON_STRING), P(JSON_CONSTANT), 45748c779cdSXin LI P(JSON_NUMBER), P(JSON_ARRAYN)) 45848c779cdSXin LI == -1) 45948c779cdSXin LI return -1; 46048c779cdSXin LI #endif 46148c779cdSXin LI return 1; 46248c779cdSXin LI } 46348c779cdSXin LI 46448c779cdSXin LI #else 46548c779cdSXin LI 46648c779cdSXin LI #include <sys/types.h> 46748c779cdSXin LI #include <sys/stat.h> 46848c779cdSXin LI #include <stdio.h> 46948c779cdSXin LI #include <fcntl.h> 47048c779cdSXin LI #include <unistd.h> 47148c779cdSXin LI #include <stdlib.h> 47248c779cdSXin LI #include <stdint.h> 47348c779cdSXin LI #include <err.h> 47448c779cdSXin LI 47548c779cdSXin LI int 47648c779cdSXin LI main(int argc, char *argv[]) 47748c779cdSXin LI { 47848c779cdSXin LI int fd, rv; 47948c779cdSXin LI struct stat st; 48048c779cdSXin LI unsigned char *p; 48148c779cdSXin LI size_t stats[JSON_MAX]; 48248c779cdSXin LI 48348c779cdSXin LI if ((fd = open(argv[1], O_RDONLY)) == -1) 48448c779cdSXin LI err(EXIT_FAILURE, "Can't open `%s'", argv[1]); 48548c779cdSXin LI 48648c779cdSXin LI if (fstat(fd, &st) == -1) 48748c779cdSXin LI err(EXIT_FAILURE, "Can't stat `%s'", argv[1]); 48848c779cdSXin LI 489a4d6d3b8SXin LI if ((p = CAST(char *, malloc(st.st_size))) == NULL) 49048c779cdSXin LI err(EXIT_FAILURE, "Can't allocate %jd bytes", 49148c779cdSXin LI (intmax_t)st.st_size); 49248c779cdSXin LI if (read(fd, p, st.st_size) != st.st_size) 49348c779cdSXin LI err(EXIT_FAILURE, "Can't read %jd bytes", 49448c779cdSXin LI (intmax_t)st.st_size); 49548c779cdSXin LI memset(stats, 0, sizeof(stats)); 49648c779cdSXin LI printf("is json %d\n", json_parse((const unsigned char **)&p, 49748c779cdSXin LI p + st.st_size, stats, 0)); 49848c779cdSXin LI return 0; 49948c779cdSXin LI } 50048c779cdSXin LI #endif 501