summaryrefslogtreecommitdiffstats
path: root/include/jsmn.h
blob: 156ae2086439e90e9b93a83e76905d270538ca8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// SPDX-License-Identifier: MIT
/*
 * Copyright (c) 2010 Serge Zaitsev
 */
#ifndef __JSMN_H_
#define __JSMN_H_

#define JSMN_STRICT
#define JSMN_PARENT_LINKS

#include <stddef.h>
#include <errno.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef JSMN_STATIC
#define JSMN_API static
#else
#define JSMN_API extern
#endif

/**
 * JSON type identifier. Basic types are:
 * 	o Object
 * 	o Array
 * 	o String
 * 	o Other primitive: number, boolean (true/false) or null
 */
typedef enum {
	JSMN_UNDEFINED = 0,
	JSMN_OBJECT = 1 << 0,
	JSMN_ARRAY = 1 << 1,
	JSMN_STRING = 1 << 2,
	JSMN_PRIMITIVE = 1 << 3
} jsmntype_t;

enum jsmnerr {
	/* Not enough tokens were provided */
	JSMN_ERROR_NOMEM = -ENOMEM,
	/* Invalid character inside JSON string */
	JSMN_ERROR_INVAL = -EINVAL,
	/* The string is not a full JSON packet, more bytes expected */
	JSMN_ERROR_PART = -EMSGSIZE
};

/**
 * JSON token description.
 * type		type (object, array, string etc.)
 * start	start position in JSON data string
 * end		end position in JSON data string
 */
typedef struct jsmntok {
	jsmntype_t type;
	int start;
	int end;
	int size;
#ifdef JSMN_PARENT_LINKS
	int parent;
#endif
} jsmntok_t;

/**
 * JSON parser. Contains an array of token blocks available. Also stores
 * the string being parsed now and current position in that string.
 */
typedef struct jsmn_parser {
	unsigned int pos;     /* offset in the JSON string */
	unsigned int toknext; /* next token to allocate */
	int toksuper;         /* superior token node, e.g. parent object or array */
} jsmn_parser;

/**
 * Create JSON parser over an array of tokens
 */
JSMN_API void jsmn_init(jsmn_parser *parser);

/**
 * Run JSON parser. It parses a JSON data string into and array of tokens, each
 * describing
 * a single JSON object.
 */
JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
			jsmntok_t *tokens, const unsigned int num_tokens);

/**
 * Like jsmn_parse, but allocates tokens dynamically.
 */
JSMN_API jsmntok_t *jsmn_parse_alloc(const char *js, const size_t len,
				     unsigned int *num_tokens);

static inline int jsmn_token_size(const jsmntok_t *token)
{
	return token->end - token->start;
}

/** Returns `true` if `token` is a string and equal to `str`. */
JSMN_API bool jsmn_str_eq(const char *str, const char *json, const jsmntok_t *token);

/** Returns `true` if `token` is to `str`. */
JSMN_API bool jsmn_eq(const char *val, const char *json, const jsmntok_t *token);

/** Returns `true` if `token` is equal to `str`, ignoring case. */
JSMN_API bool jsmn_strcase_eq(const char *str, const char *json, const jsmntok_t *token);

/** Returns the token after the value at `tokens[0]`. */
JSMN_API const jsmntok_t *jsmn_skip_value(const jsmntok_t *tokens);

/**
 * Returns a pointer to the value associated with `key` inside `json` starting
 * at `tokens[0]`, which is expected to be an object, or returns `NULL` if `key`
 * cannot be found.
 */
JSMN_API const jsmntok_t *jsmn_find_value(const char *key, const char *json,
					  const jsmntok_t *tokens);

/**
 * Locate the token at `path` inside `json` in a manner similar to JSONPath.
 *
 * Example:
 * \code
 * {
 *   "date": "...",
 *   "product": {
 *	 "serial": "1234",
 *   }
 * }
 * \endcode
 *
 * To locate the serial number in the JSON object above, you would use the
 * JSONPath expression "$.product.serial". The same thing can be accomplished
 * with this call:
 *
 * \code
 * const char *path[] = {"product", "serial", NULL};
 * const jsmntok_t *token = jsmn_locate(path, json, tokens);
 * \endcode
 *
 * \remark This function cannot search inside arrays.
 *
 * @param path		Null-terminated list of path elements.
 * @param json		JSON string to search in.
 * @param tokens	Tokens for `json`.
 *
 * @return Pointer to the value token or `NULL` if the token could not be found.
 */
JSMN_API const jsmntok_t *jsmn_locate(const char *path[], const char *json,
				      const jsmntok_t *tokens);

/**
 * Similar to `jsmn_locate` but returns a copy of the value or `NULL` if the
 * value does not exist or is not a string. The caller takes ownership of the
 * pointer returned.
 */
JSMN_API char *jsmn_strdup(const char *path[], const char *json, const jsmntok_t *tokens);

#ifdef __cplusplus
}
#endif

#endif /* JSMN_H */