• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
mapfile(const char * fn,size_t * size)44  static 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;
68  out:
69  	close(fd);
70  	return map;
71  }
72  
unmapfile(char * map,size_t size)73  static 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   */
parse_json(const char * fn,char ** map,size_t * size,int * len)83  jsmntok_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;
108  error_free:
109  	free(tokens);
110  error:
111  	unmapfile(*map, *size);
112  	return NULL;
113  }
114  
free_json(char * map,size_t size,jsmntok_t * tokens)115  void free_json(char *map, size_t size, jsmntok_t *tokens)
116  {
117  	free(tokens);
118  	unmapfile(map, size);
119  }
120  
countchar(char * map,char c,int end)121  static 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 */
json_line(char * map,jsmntok_t * t)132  int json_line(char *map, jsmntok_t *t)
133  {
134  	return countchar(map, '\n', t->start) + 1;
135  }
136  
137  static 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 */
json_name(jsmntok_t * t)147  const char *json_name(jsmntok_t *t)
148  {
149  	return LOOKUP(jsmn_types, t->type);
150  }
151  
json_len(jsmntok_t * t)152  int json_len(jsmntok_t *t)
153  {
154  	return t->end - t->start;
155  }
156  
157  /* Is string t equal to s? */
json_streq(char * map,jsmntok_t * t,const char * s)158  int 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  }
163