summaryrefslogtreecommitdiffstats
path: root/include/import/mjson.h
blob: b96fd3fbb6a8c62903aa3de9b2b0d05b0f513c86 (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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// Copyright (c) 2018-2020 Cesanta Software Limited
// All rights reserved
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#ifndef MJSON_H
#define MJSON_H

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#ifndef MJSON_ENABLE_PRINT
#define MJSON_ENABLE_PRINT 1
#endif

#ifndef MJSON_ENABLE_RPC
#define MJSON_ENABLE_RPC 1
#endif

#ifndef MJSON_ENABLE_BASE64
#define MJSON_ENABLE_BASE64 1
#endif

#ifndef MJSON_ENABLE_MERGE
#define MJSON_ENABLE_MERGE 0
#elif MJSON_ENABLE_MERGE
#define MJSON_ENABLE_NEXT 1
#endif

#ifndef MJSON_ENABLE_PRETTY
#define MJSON_ENABLE_PRETTY 0
#elif MJSON_ENABLE_PRETTY
#define MJSON_ENABLE_NEXT 1
#endif

#ifndef MJSON_ENABLE_NEXT
#define MJSON_ENABLE_NEXT 0
#endif

#ifndef MJSON_RPC_LIST_NAME
#define MJSON_RPC_LIST_NAME "rpc.list"
#endif

#ifndef MJSON_DYNBUF_CHUNK
#define MJSON_DYNBUF_CHUNK 256  // Allocation granularity for print_dynamic_buf
#endif

#ifdef __cplusplus
extern "C" {
#endif

enum {
  MJSON_ERROR_INVALID_INPUT = -1,
  MJSON_ERROR_TOO_DEEP = -2,
};

enum mjson_tok {
  MJSON_TOK_INVALID = 0,
  MJSON_TOK_KEY = 1,
  MJSON_TOK_STRING = 11,
  MJSON_TOK_NUMBER = 12,
  MJSON_TOK_TRUE = 13,
  MJSON_TOK_FALSE = 14,
  MJSON_TOK_NULL = 15,
  MJSON_TOK_ARRAY = 91,
  MJSON_TOK_OBJECT = 123,
};
#define MJSON_TOK_IS_VALUE(t) ((t) > 10 && (t) < 20)

typedef int (*mjson_cb_t)(int ev, const char *s, int off, int len, void *ud);

#ifndef MJSON_MAX_DEPTH
#define MJSON_MAX_DEPTH 20
#endif

int mjson(const char *s, int len, mjson_cb_t cb, void *ud);
enum mjson_tok mjson_find(const char *s, int len, const char *jp,
                          const char **tokptr, int *toklen);
int mjson_get_number(const char *s, int len, const char *path, double *v);
int mjson_get_bool(const char *s, int len, const char *path, int *v);
int mjson_get_string(const char *s, int len, const char *path, char *to, int n);
int mjson_get_hex(const char *s, int len, const char *path, char *to, int n);

#if MJSON_ENABLE_NEXT
int mjson_next(const char *s, int n, int off, int *koff, int *klen, int *voff,
               int *vlen, int *vtype);
#endif

#if MJSON_ENABLE_BASE64
int mjson_get_base64(const char *s, int len, const char *path, char *to, int n);
int mjson_base64_dec(const char *src, int n, char *dst, int dlen);
#endif

#if MJSON_ENABLE_PRINT
typedef int (*mjson_print_fn_t)(const char *buf, int len, void *userdata);
typedef int (*mjson_vprint_fn_t)(mjson_print_fn_t, void *, va_list *);

struct mjson_fixedbuf {
  char *ptr;
  int size, len;
};

int mjson_printf(mjson_print_fn_t, void *, const char *fmt, ...);
int mjson_vprintf(mjson_print_fn_t, void *, const char *fmt, va_list ap);
int mjson_print_str(mjson_print_fn_t, void *, const char *s, int len);
int mjson_print_int(mjson_print_fn_t, void *, int value, int is_signed);
int mjson_print_long(mjson_print_fn_t, void *, long value, int is_signed);
int mjson_print_buf(mjson_print_fn_t fn, void *, const char *buf, int len);

int mjson_print_null(const char *ptr, int len, void *userdata);
int mjson_print_fixed_buf(const char *ptr, int len, void *userdata);
int mjson_print_dynamic_buf(const char *ptr, int len, void *userdata);

#if MJSON_ENABLE_PRETTY
int mjson_pretty(const char *, int, const char *, mjson_print_fn_t, void *);
#endif

#if MJSON_ENABLE_MERGE
int mjson_merge(const char *, int, const char *, int, mjson_print_fn_t, void *);
#endif

#endif  // MJSON_ENABLE_PRINT

#if MJSON_ENABLE_RPC

void jsonrpc_init(mjson_print_fn_t, void *userdata);
int mjson_globmatch(const char *s1, int n1, const char *s2, int n2);

struct jsonrpc_request {
  struct jsonrpc_ctx *ctx;
  const char *frame;    // Points to the whole frame
  int frame_len;        // Frame length
  const char *params;   // Points to the "params" in the request frame
  int params_len;       // Length of the "params"
  const char *id;       // Points to the "id" in the request frame
  int id_len;           // Length of the "id"
  const char *method;   // Points to the "method" in the request frame
  int method_len;       // Length of the "method"
  mjson_print_fn_t fn;  // Printer function
  void *fndata;         // Printer function data
  void *userdata;       // Callback's user data as specified at export time
};

struct jsonrpc_method {
  const char *method;
  int method_sz;
  void (*cb)(struct jsonrpc_request *);
  struct jsonrpc_method *next;
};

// Main RPC context, stores current request information and a list of
// exported RPC methods.
struct jsonrpc_ctx {
  struct jsonrpc_method *methods;
  mjson_print_fn_t response_cb;
  void *response_cb_data;
};

// Registers function fn under the given name within the given RPC context
#define jsonrpc_ctx_export(ctx, name, fn)                                 \
  do {                                                                    \
    static struct jsonrpc_method m = {(name), sizeof(name) - 1, (fn), 0}; \
    m.next = (ctx)->methods;                                              \
    (ctx)->methods = &m;                                                  \
  } while (0)

void jsonrpc_ctx_init(struct jsonrpc_ctx *ctx, mjson_print_fn_t, void *);
void jsonrpc_return_error(struct jsonrpc_request *r, int code,
                          const char *message, const char *data_fmt, ...);
void jsonrpc_return_success(struct jsonrpc_request *r, const char *result_fmt,
                            ...);
void jsonrpc_ctx_process(struct jsonrpc_ctx *ctx, const char *req, int req_sz,
                         mjson_print_fn_t fn, void *fndata, void *userdata);

extern struct jsonrpc_ctx jsonrpc_default_context;

#define jsonrpc_export(name, fn) \
  jsonrpc_ctx_export(&jsonrpc_default_context, (name), (fn))

#define jsonrpc_process(buf, len, fn, fnd, ud) \
  jsonrpc_ctx_process(&jsonrpc_default_context, (buf), (len), (fn), (fnd), (ud))

#define JSONRPC_ERROR_INVALID -32700    /* Invalid JSON was received */
#define JSONRPC_ERROR_NOT_FOUND -32601  /* The method does not exist */
#define JSONRPC_ERROR_BAD_PARAMS -32602 /* Invalid params passed */
#define JSONRPC_ERROR_INTERNAL -32603   /* Internal JSON-RPC error */

#endif  // MJSON_ENABLE_RPC
#ifdef __cplusplus
}
#endif
#endif  // MJSON_H