git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / include / formats / rjson.h
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (rjson.h).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #ifndef __LIBRETRO_SDK_FORMAT_RJSON_H__
24 #define __LIBRETRO_SDK_FORMAT_RJSON_H__
25
26 #include <retro_common_api.h>
27 #include <boolean.h> /* bool */
28 #include <stddef.h> /* size_t */
29
30 RETRO_BEGIN_DECLS
31
32 /* List of possible element types returned by rjson_next */
33 enum rjson_type
34 {
35    RJSON_DONE,
36    RJSON_OBJECT, RJSON_ARRAY, RJSON_OBJECT_END, RJSON_ARRAY_END,
37    RJSON_STRING, RJSON_NUMBER, RJSON_TRUE, RJSON_FALSE, RJSON_NULL,
38    RJSON_ERROR
39 };
40
41 /* Options that can be passed to rjson_set_options */
42 enum rjson_option
43 {
44    /* Allow UTF-8 byte order marks */
45    RJSON_OPTION_ALLOW_UTF8BOM                      = (1<<0),
46    /* Allow JavaScript style comments in the stream */
47    RJSON_OPTION_ALLOW_COMMENTS                     = (1<<1),
48    /* Allow unescaped control characters in strings (bytes 0x00 - 0x1F) */
49    RJSON_OPTION_ALLOW_UNESCAPED_CONTROL_CHARACTERS = (1<<2),
50    /* Ignore invalid Unicode escapes and don't validate UTF-8 codes */
51    RJSON_OPTION_IGNORE_INVALID_ENCODING            = (1<<3),
52    /* Replace invalid Unicode escapes and UTF-8 codes with a '?' character */
53    RJSON_OPTION_REPLACE_INVALID_ENCODING           = (1<<4),
54    /* Ignore carriage return (\r escape sequence) in strings */
55    RJSON_OPTION_IGNORE_STRING_CARRIAGE_RETURN      = (1<<5),
56    /* Allow data after the end of the top JSON object/array/value */
57    RJSON_OPTION_ALLOW_TRAILING_DATA                = (1<<6)
58 };
59
60 /* Custom data input callback
61  * Should return > 0 and <= len on success, 0 on file end and < 0 on error. */
62 typedef int (*rjson_io_t)(void* buf, int len, void *user_data);
63 typedef struct rjson rjson_t;
64 struct intfstream_internal;
65 struct RFILE;
66
67 /* Create a new parser instance from various sources */
68 rjson_t *rjson_open_stream(struct intfstream_internal *stream);
69 rjson_t *rjson_open_rfile(struct RFILE *rfile);
70 rjson_t *rjson_open_buffer(const void *buffer, size_t size);
71 rjson_t *rjson_open_string(const char *string, size_t len);
72 rjson_t *rjson_open_user(rjson_io_t io, void *user_data, int io_block_size);
73
74 /* Free the parser instance created with rjson_open_* */
75 void rjson_free(rjson_t *json);
76
77 /* Set one or more enum rjson_option, will override previously set options.
78  * Use bitwise OR to concatenate multiple options.
79  * By default none of the options are set. */
80 void rjson_set_options(rjson_t *json, char rjson_option_flags);
81
82 /* Sets the maximum context depth, recursion inside arrays and objects.
83  * By default this is set to 50. */
84 void rjson_set_max_depth(rjson_t *json, unsigned int max_depth);
85
86 /* Parse to the next JSON element and return the type of it.
87  * Will return RJSON_DONE when successfully reaching the end or
88  * RJSON_ERROR when an error was encountered. */
89 enum rjson_type rjson_next(rjson_t *json);
90
91 /* Get the current string, null-terminated unescaped UTF-8 encoded.
92  * Can only be used when the current element is RJSON_STRING or RJSON_NUMBER.
93  * The returned pointer is only valid until the parsing continues. */
94 const char *rjson_get_string(rjson_t *json, size_t *length);
95
96 /* Returns the current number (or string) converted to double or int */
97 double rjson_get_double(rjson_t *json);
98 int    rjson_get_int(rjson_t *json);
99
100 /* Returns a string describing the error once rjson_next/rjson_parse
101  * has returned an unrecoverable RJSON_ERROR (otherwise returns ""). */
102 const char *rjson_get_error(rjson_t *json);
103
104 /* Can be used to set a custom error description on an invalid JSON structure.
105  * Maximum length of 79 characters and once set the parsing can't continue. */
106 void rjson_set_error(rjson_t *json, const char* error);
107
108 /* Functions to get the current position in the source stream as well as */
109 /* a bit of source json arround the current position for additional detail
110  * when parsing has failed with RJSON_ERROR.
111  * Intended to be used with printf style formatting like:
112  * printf("Invalid JSON at line %d, column %d - %s - Source: ...%.*s...\n",
113  *       (int)rjson_get_source_line(json), (int)rjson_get_source_column(json),
114  *       rjson_get_error(json), rjson_get_source_context_len(json),
115  *       rjson_get_source_context_buf(json)); */
116 size_t      rjson_get_source_line(rjson_t *json);
117 size_t      rjson_get_source_column(rjson_t *json);
118 int         rjson_get_source_context_len(rjson_t *json);
119 const char* rjson_get_source_context_buf(rjson_t *json);
120
121 /* Confirm the parsing context stack, for example calling
122    rjson_check_context(json, 2, RJSON_OBJECT, RJSON_ARRAY)
123    returns true when inside "{ [ ..." but not for "[ .." or "{ [ { ..." */
124 bool rjson_check_context(rjson_t *json, unsigned int depth, ...);
125
126 /* Returns the current level of nested objects/arrays */
127 unsigned int rjson_get_context_depth(rjson_t *json);
128
129 /* Return the current parsing context, that is, RJSON_OBJECT if we are inside
130  * an object, RJSON_ARRAY if we are inside an array, and RJSON_DONE or 
131  * RJSON_ERROR if we are not yet/anymore in either. */
132 enum rjson_type rjson_get_context_type(rjson_t *json);
133
134 /* While inside an object or an array, this return the number of parsing
135  * events that have already been observed at this level with rjson_next.
136  * In particular, inside an object, an odd number would indicate that the just
137  * observed RJSON_STRING event is a member name. */
138 size_t rjson_get_context_count(rjson_t *json);
139
140 /* Parse an entire JSON stream with a list of element specific handlers.
141  * Each of the handlers can be passed a function or NULL to ignore it.
142  * If a handler returns false, the parsing will abort and the returned
143  * rjson_type will indicate on which element type parsing was aborted.
144  * Otherwise the return value will be RJSON_DONE or RJSON_ERROR. */
145 enum rjson_type rjson_parse(rjson_t *json, void* context,
146       bool (*object_member_handler)(void *context, const char *str, size_t len),
147       bool (*string_handler       )(void *context, const char *str, size_t len),
148       bool (*number_handler       )(void *context, const char *str, size_t len),
149       bool (*start_object_handler )(void *context),
150       bool (*end_object_handler   )(void *context),
151       bool (*start_array_handler  )(void *context),
152       bool (*end_array_handler    )(void *context),
153       bool (*boolean_handler      )(void *context, bool value),
154       bool (*null_handler         )(void *context));
155
156 /* A simpler interface to parse a JSON in memory. This will avoid any memory
157  * allocations unless the document contains strings longer than 512 characters.
158  * In the error handler, error will be "" if any of the other handlers aborted. */
159 bool rjson_parse_quick(const char *string, size_t len, void* context, char option_flags,
160       bool (*object_member_handler)(void *context, const char *str, size_t len),
161       bool (*string_handler       )(void *context, const char *str, size_t len),
162       bool (*number_handler       )(void *context, const char *str, size_t len),
163       bool (*start_object_handler )(void *context),
164       bool (*end_object_handler   )(void *context),
165       bool (*start_array_handler  )(void *context),
166       bool (*end_array_handler    )(void *context),
167       bool (*boolean_handler      )(void *context, bool value),
168       bool (*null_handler         )(void *context),
169       void (*error_handler        )(void *context, int line, int col, const char* error));
170
171 /* ------------------------------------------------------------------------- */
172
173 /* Options that can be passed to rjsonwriter_set_options */
174 enum rjsonwriter_option
175 {
176    /* Don't write spaces, tabs or newlines to the output (except in strings) */
177    RJSONWRITER_OPTION_SKIP_WHITESPACE = (1<<0)
178 };
179
180 /* Custom data output callback
181  * Should return len on success and < len on a write error. */
182 typedef int (*rjsonwriter_io_t)(const void* buf, int len, void *user_data);
183 typedef struct rjsonwriter rjsonwriter_t;
184
185 /* Create a new writer instance to various targets */
186 rjsonwriter_t *rjsonwriter_open_stream(struct intfstream_internal *stream);
187 rjsonwriter_t *rjsonwriter_open_rfile(struct RFILE *rfile);
188 rjsonwriter_t *rjsonwriter_open_memory(void);
189 rjsonwriter_t *rjsonwriter_open_user(rjsonwriter_io_t io, void *user_data);
190
191 /* When opened with rjsonwriter_open_memory, will return the generated JSON.
192  * Result is always null-terminated. Passed len can be NULL if not needed,
193  * otherwise returned len will be string length without null-terminator.
194  * Returns NULL if writing ran out of memory or not opened from memory.
195  * Returned buffer is only valid until writer is modified or freed. */
196 char* rjsonwriter_get_memory_buffer(rjsonwriter_t *writer, int* len);
197
198 /* When opened with rjsonwriter_open_memory, will return current length */
199 int rjsonwriter_count_memory_buffer(rjsonwriter_t *writer);
200
201 /* When opened with rjsonwriter_open_memory, will clear the buffer.
202    The buffer will be partially erased if keep_len is > 0.
203    No memory is freed or re-allocated with this function. */
204 void rjsonwriter_erase_memory_buffer(rjsonwriter_t *writer, int keep_len);
205
206 /* Free rjsonwriter handle and return result of final rjsonwriter_flush call */
207 bool rjsonwriter_free(rjsonwriter_t *writer);
208
209 /* Set one or more enum rjsonwriter_option, will override previously set options.
210  * Use bitwise OR to concatenate multiple options.
211  * By default none of the options are set. */
212 void rjsonwriter_set_options(rjsonwriter_t *writer, int rjsonwriter_option_flags);
213
214 /* Flush any buffered output data to the output stream.
215  * Returns true if the data was successfully written. Once writing fails once,
216  * no more data will be written and flush will always returns false */
217 bool rjsonwriter_flush(rjsonwriter_t *writer);
218
219 /* Returns a string describing an error or "" if there was none.
220  * The only error possible is "output error" after the io function failed.
221  * If rjsonwriter_rawf were used manually, "out of memory" is also possible. */
222 const char *rjsonwriter_get_error(rjsonwriter_t *writer);
223
224 /* Used by the inline functions below to append raw data */
225 void rjsonwriter_raw(rjsonwriter_t *writer, const char *buf, int len);
226 void rjsonwriter_rawf(rjsonwriter_t *writer, const char *fmt, ...);
227
228 /* Add a UTF-8 encoded string
229  * Special and control characters are automatically escaped.
230  * If NULL is passed an empty string will be written (not JSON null). */
231 void rjsonwriter_add_string(rjsonwriter_t *writer, const char *value);
232 void rjsonwriter_add_string_len(rjsonwriter_t *writer, const char *value, int len);
233
234 void rjsonwriter_add_double(rjsonwriter_t *writer, double value);
235
236 void rjsonwriter_add_spaces(rjsonwriter_t *writer, int count);
237
238 void rjsonwriter_add_tabs(rjsonwriter_t *writer, int count);
239
240 RETRO_END_DECLS
241
242 #endif