json.c (4026B)
1/* Parse JSON files using the JSMN parser. */ 2 3/* 4 * Copyright (c) 2014, Intel Corporation 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 * OF THE POSSIBILITY OF SUCH DAMAGE. 29*/ 30 31#include <stdlib.h> 32#include <string.h> 33#include <sys/mman.h> 34#include <sys/stat.h> 35#include <fcntl.h> 36#include <stdio.h> 37#include <errno.h> 38#include <unistd.h> 39#include "jsmn.h" 40#include "json.h" 41#include <linux/kernel.h> 42 43 44static char *mapfile(const char *fn, size_t *size) 45{ 46 unsigned ps = sysconf(_SC_PAGESIZE); 47 struct stat st; 48 char *map = NULL; 49 int err; 50 int fd = open(fn, O_RDONLY); 51 52 if (fd < 0 && verbose > 0 && fn) { 53 pr_err("Error opening events file '%s': %s\n", fn, 54 strerror(errno)); 55 } 56 57 if (fd < 0) 58 return NULL; 59 err = fstat(fd, &st); 60 if (err < 0) 61 goto out; 62 *size = st.st_size; 63 map = mmap(NULL, 64 (st.st_size + ps - 1) & ~(ps - 1), 65 PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 66 if (map == MAP_FAILED) 67 map = NULL; 68out: 69 close(fd); 70 return map; 71} 72 73static void unmapfile(char *map, size_t size) 74{ 75 unsigned ps = sysconf(_SC_PAGESIZE); 76 munmap(map, roundup(size, ps)); 77} 78 79/* 80 * Parse json file using jsmn. Return array of tokens, 81 * and mapped file. Caller needs to free array. 82 */ 83jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len) 84{ 85 jsmn_parser parser; 86 jsmntok_t *tokens; 87 jsmnerr_t res; 88 unsigned sz; 89 90 *map = mapfile(fn, size); 91 if (!*map) 92 return NULL; 93 /* Heuristic */ 94 sz = *size * 16; 95 tokens = malloc(sz); 96 if (!tokens) 97 goto error; 98 jsmn_init(&parser); 99 res = jsmn_parse(&parser, *map, *size, tokens, 100 sz / sizeof(jsmntok_t)); 101 if (res != JSMN_SUCCESS) { 102 pr_err("%s: json error %s\n", fn, jsmn_strerror(res)); 103 goto error_free; 104 } 105 if (len) 106 *len = parser.toknext; 107 return tokens; 108error_free: 109 free(tokens); 110error: 111 unmapfile(*map, *size); 112 return NULL; 113} 114 115void free_json(char *map, size_t size, jsmntok_t *tokens) 116{ 117 free(tokens); 118 unmapfile(map, size); 119} 120 121static int countchar(char *map, char c, int end) 122{ 123 int i; 124 int count = 0; 125 for (i = 0; i < end; i++) 126 if (map[i] == c) 127 count++; 128 return count; 129} 130 131/* Return line number of a jsmn token */ 132int json_line(char *map, jsmntok_t *t) 133{ 134 return countchar(map, '\n', t->start) + 1; 135} 136 137static const char * const jsmn_types[] = { 138 [JSMN_PRIMITIVE] = "primitive", 139 [JSMN_ARRAY] = "array", 140 [JSMN_OBJECT] = "object", 141 [JSMN_STRING] = "string" 142}; 143 144#define LOOKUP(a, i) ((i) < (sizeof(a)/sizeof(*(a))) ? ((a)[i]) : "?") 145 146/* Return type name of a jsmn token */ 147const char *json_name(jsmntok_t *t) 148{ 149 return LOOKUP(jsmn_types, t->type); 150} 151 152int json_len(jsmntok_t *t) 153{ 154 return t->end - t->start; 155} 156 157/* Is string t equal to s? */ 158int json_streq(char *map, jsmntok_t *t, const char *s) 159{ 160 unsigned len = json_len(t); 161 return len == strlen(s) && !strncasecmp(map + t->start, s, len); 162}