1 /*
2  *
3  *   Copyright (C) 2012-2018 by C.H. Huang
4  *   plushuang.tw@gmail.com
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2.1 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  *  ---
21  *
22  *  In addition, as a special exception, the copyright holders give
23  *  permission to link the code of portions of this program with the
24  *  OpenSSL library under certain conditions as described in each
25  *  individual source file, and distribute linked combinations
26  *  including the two.
27  *  You must obey the GNU Lesser General Public License in all respects
28  *  for all of the code used other than OpenSSL.  If you modify
29  *  file(s) with this exception, you may extend this exception to your
30  *  version of the file(s), but you are not obligated to do so.  If you
31  *  do not wish to do so, delete this exception statement from your
32  *  version.  If you delete this exception statement from all source
33  *  files in the program, then also delete it here.
34  *
35  */
36 
37 #ifndef UG_JSON_H
38 #define UG_JSON_H
39 
40 #include <stdint.h>     // int64_t
41 #include <UgBuffer.h>
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 // ----------------------------------------------------------------------------
48 // UgJsonType & UgJsonError
49 
50 typedef enum {
51 	UG_JSON_NULL,       // null
52 	UG_JSON_TRUE,       // true
53 	UG_JSON_FALSE,      // false
54 	UG_JSON_NUMBER,     // 1234, 0.567
55 	UG_JSON_STRING,     // "string"
56 	UG_JSON_OBJECT,     // {
57 	UG_JSON_ARRAY,      // [
58 
59 	UG_JSON_N_TYPE,     // numbers of UgJsonType
60 } UgJsonType;
61 
62 typedef enum {
63 	UG_JSON_ERROR_NONE              =  0,
64 
65 	// error code < 0, JSON format error
66 	UG_JSON_ERROR_UNKNOWN           = -1,
67 	UG_JSON_ERROR_INVALID_NAME      = -2,
68 	UG_JSON_ERROR_EXCESS_NAME       = -3,   // get 2 names in 1 element
69 	UG_JSON_ERROR_BEFORE_COLON      = -4,   // no name before colon in object
70 	UG_JSON_ERROR_EXCESS_COLON      = -5,   // get 2 colons in 1 element
71 //	UG_JSON_ERROR_NO_VALUE          = -6,
72 	UG_JSON_ERROR_INVALID_VALUE     = -7,   // not true, false, null, string, and number.
73 	UG_JSON_ERROR_EXCESS_VALUE      = -8,   // get 2 values in 1 element
74 	UG_JSON_ERROR_INVALID_CONTROL   = -9,   // unknown control character after '\'
75 	UG_JSON_ERROR_INVALID_UNICODE   = -10,
76 	UG_JSON_ERROR_INVALID_NUMBER    = -11,
77 
78 	UG_JSON_ERROR_IN_OBJECT         = -12,
79 	UG_JSON_ERROR_IN_ARRAY          = -13,
80 	UG_JSON_ERROR_IN_SEPARATOR      = -14,  // ','
81 
82 	UG_JSON_ERROR_UNCOMPLETED       = -15,
83 
84 	// --------------------------------
85 	// JSON-RPC error code
86 	UG_JSON_ERROR_RPC_INVALID       = -32,
87 
88 	// --------------------------------
89 	// error code > 0, user (application) error
90 	// used by user parser (e.g. UgArray, UgList, UgEntry)
91 	UG_JSON_ERROR_TYPE_NOT_MATCH    = 1,
92 	UG_JSON_ERROR_NO_DESTINATION    = 2,
93 	UG_JSON_ERROR_OUT_OF_MEMORY     = 3,
94 	UG_JSON_ERROR_CUSTOM            = 4,
95 } UgJsonError;
96 
97 // ----------------------------------------------------------------------------
98 // UgJson: a simple JSON parser & writer
99 
100 typedef struct	UgJson          UgJson;
101 
102 // UgJsonParseFunc : a callback function to parse data
103 typedef UgJsonError  (*UgJsonParseFunc) (UgJson* json,
104                                          const char* name, const char* value,
105                                          void* dest, void* data);
106 typedef void         (*UgJsonWriteFunc) (UgJson* json, void* src, void* data);
107 
108 // ----------------------------------------------------------------------------
109 // JSON initialize & finalize functions
110 
111 void  ug_json_init (UgJson* json);
112 void  ug_json_final (UgJson* json);
113 
114 // ----------------------------------------------------------------------------
115 // JSON Parser functions
116 
117 void         ug_json_begin_parse (UgJson* json);
118 UgJsonError  ug_json_end_parse   (UgJson* json);
119 
120 UgJsonError  ug_json_parse (UgJson* json, const char* string, int len);
121 
122 // Don't call ug_json_pop() directly.
123 void         ug_json_set  (UgJson* json, UgJsonParseFunc func, void* dest, void* data);
124 void         ug_json_push (UgJson* json, UgJsonParseFunc func, void* dest, void* data);
125 void         ug_json_pop  (UgJson* json);
126 
127 // UgJsonParseFunc for JSON that starting with array.
128 // This parser will be popped if JSON start with array, otherwise it pop parser twice.
129 // User must push it after UserParseFunc. Below is sample code.
130 // ug_json_push (json, UserParseFunc, UserData1, UserData2);
131 // ug_json_push (json, ug_json_parse_array, NULL, NULL);
132 UgJsonError  ug_json_parse_array (UgJson* json,
133                                   const char* name, const char* value,
134                                   void* dest, void* data);
135 // UgJsonParseFunc for JSON that starting with object.
136 // This parser will be popped if JSON start with object, otherwise it pop parser twice.
137 // User must push it after UserParseFunc. Below is sample code.
138 // ug_json_push (json, UserParseFunc, UserData1, UserData2);
139 // ug_json_push (json, ug_json_parse_object, NULL, NULL);
140 UgJsonError  ug_json_parse_object (UgJson* json,
141                                    const char* name, const char* value,
142                                    void* dest, void* data);
143 // UgJsonParseFunc for unknown object or array.
144 // User must push this function in UserParseFunc if you get unknown object or array.
145 // ug_json_push (json, ug_json_parse_unknown, NULL, NULL);
146 UgJsonError  ug_json_parse_unknown (UgJson* json,
147                                     const char* name, const char* value,
148                                     void* dest, void* data);
149 
150 // ----------------------------------------------------------------------------
151 // JSON Writer functions
152 
153 // UgJson.state = UgJsonFormat
154 // UgJson.index[0] = level
155 // UgJson.stack.at[0] = UgBuffer
156 
157 typedef enum
158 {
159 	UG_JSON_FORMAT_INDENT = 1,
160 	UG_JSON_FORMAT_UTF8   = 2,
161 	UG_JSON_FORMAT_ALL    = UG_JSON_FORMAT_INDENT | UG_JSON_FORMAT_UTF8
162 } UgJsonFormat;
163 
164 // UgJson Writer functions
165 void    ug_json_begin_write (UgJson* json, UgJsonFormat format, UgBuffer* buffer);
166 void    ug_json_end_write   (UgJson* json);
167 
168 void    ug_json_write_head (UgJson* json, char ch);
169 void    ug_json_write_tail (UgJson* json, char ch);
170 
171 // void ug_json_write_object_head (UgJson* json)
172 // void ug_json_write_object_tail (UgJson* json)
173 // void ug_json_write_array_head (UgJson* json)
174 // void ug_json_write_array_tail (UgJson* json)
175 #define ug_json_write_object_head(json)		ug_json_write_head (json, '{')
176 #define ug_json_write_object_tail(json)		ug_json_write_tail (json, '}')
177 #define ug_json_write_array_head(json)		ug_json_write_head (json, '[')
178 #define ug_json_write_array_tail(json)		ug_json_write_tail (json, ']')
179 
180 void    ug_json_write_null   (UgJson* json);
181 void    ug_json_write_bool   (UgJson* json, int value);
182 
183 void    ug_json_write_number (UgJson* json, const char* format, ...);
184 void    ug_json_write_string (UgJson* json, const char* Cstring);
185 
186 // void ug_json_write_int    (UgJson* json, int value);
187 // void ug_json_write_uint   (UgJson* json, unsigned int value);
188 // void ug_json_write_int64  (UgJson* json, int64_t  value);
189 // void ug_json_write_uint64 (UgJson* json, uint64_t value);
190 // void ug_json_write_double (UgJson* json, double   value);
191 #define ug_json_write_int(json, value)      ug_json_write_number (json, "%d", value)
192 #define ug_json_write_uint(json, value)     ug_json_write_number (json, "%u", value)
193 #define ug_json_write_double(json, value)   ug_json_write_number (json, "%f", value)
194 #if defined (_MSC_VER) || defined (__MINGW32__)
195 #define ug_json_write_int64(json, value)    ug_json_write_number (json, "%I64d", value)
196 #define ug_json_write_uint64(json, value)   ug_json_write_number (json, "%I64u", value)
197 #else
198 #define ug_json_write_int64(json, value)    ug_json_write_number (json, "%lld", (long long) (value))
199 #define ug_json_write_uint64(json, value)   ug_json_write_number (json, "%llu", (unsigned long long) (value))
200 #endif
201 
202 #ifdef __cplusplus
203 }
204 #endif
205 
206 struct UgJson
207 {
208 	// buffer is used by parser & writer
209 	struct {
210 		char*  at;
211 		int    length;
212 		int    allocated;
213 	} buf;
214 
215 	// stack can store state, function, and data.
216 	struct {
217 		void** at;
218 		int    length;
219 		int    allocated;
220 	} stack;
221 
222 	// User's parser can read type and scope only.
223 	// used by parser & writer
224 	uint8_t  scope;                 // UG_JSON_OBJECT or UG_JSON_ARRAY
225 	uint8_t  state;                 // Parser state, Writer UgJsonFormat
226 	int8_t   error;
227 	// temporary state
228 	uint8_t  type;                  // UgJsonType
229 	uint8_t  count;                 // count value (true, false, null, unicode) length
230 	uint8_t  colon:1;               // boolean, has ':' in object.
231 	uint8_t  numberPoint:1;         // boolean, has '.' in number.
232 	uint8_t  numberEe:1;            // boolean, has 'E' or 'e' in number.
233 	uint8_t  numberPm:1;            // boolean, has '+' or '-' in number.
234 
235 	// parser index[0] = index of name
236 	//        index[1] = index of value
237 	// writer index[0] = level
238 	int       index[2];
239 
240 #ifdef __cplusplus
241 // C++11 standard-layout
UgJsonUgJson242 	inline UgJson (void)
243 		{ ug_json_init (this); }
~UgJsonUgJson244 	inline ~UgJson (void)
245 		{ ug_json_final (this); }
246 
initUgJson247 	inline void init (void)
248 		{ ug_json_init (this); }
finalUgJson249 	inline void final (void)
250 		{ ug_json_final (this); }
251 
252 	// parser
beginParseUgJson253 	inline void  beginParse(void)
254 		{ ug_json_begin_parse (this); }
endParseUgJson255 	inline void  endParse (void)
256 		{ ug_json_end_parse (this); }
parseUgJson257 	inline void  parse (const char* string, int length)
258 		{ ug_json_parse (this, string, length); }
pushUgJson259 	inline void  push (UgJsonParseFunc func, void* dest, void* data)
260 		{ ug_json_push (this, func, dest, data); }
popUgJson261 	inline void  pop (void)
262 		{ ug_json_pop (this); }
263 
264 	// writer
beginWriteUgJson265 	inline void  beginWrite (UgJsonFormat format, UgBuffer* buffer)
266 		{ ug_json_begin_write (this, format, buffer); }
endWriteUgJson267 	inline void  endWrite (void)
268 		{ ug_json_end_write (this); }
269 
270 //	inline void  writeHead (char ch)
271 //		{ ug_json_write_head (this, ch); }
272 //	inline void  writeTail (char ch)
273 //		{ ug_json_write_tail (this, ch); }
writeObjectHeadUgJson274 	inline void  writeObjectHead (void)
275 		{ ug_json_write_object_head (this); }
writeObjectTailUgJson276 	inline void  writeObjectTail (void)
277 		{ ug_json_write_object_tail (this); }
writeArrayHeadUgJson278 	inline void  writeArrayHead (void)
279 		{ ug_json_write_array_head (this); }
writeArrayTailUgJson280 	inline void  writeArrayTail (void)
281 		{ ug_json_write_array_tail (this); }
282 
writeNullUgJson283 	inline void  writeNull (void)
284 		{ ug_json_write_null (this); }
writeBoolUgJson285 	inline void  writeBool (int value)
286 		{ ug_json_write_bool (this, value); }
287 //	void  writeNumber (const char* format, ...)
writeStringUgJson288 	inline void  writeString (const char* Cstring)
289 		{ ug_json_write_string (this, Cstring); }
290 
writeIntUgJson291 	inline void  writeInt (int value)
292 		{ ug_json_write_int (this, value); }
writeUintUgJson293 	inline void  writeUint (unsigned int value)
294 		{ ug_json_write_uint (this, value); }
writeInt64UgJson295 	inline void  writeInt64 (int64_t value)
296 		{ ug_json_write_int64 (this, value); }
writeDoubleUgJson297 	inline void  writeDouble (double value)
298 		{ ug_json_write_double (this, value); }
299 #endif // __cplusplus
300 };
301 
302 
303 // ----------------------------------------------------------------------------
304 // C++11 standard-layout
305 
306 #ifdef __cplusplus
307 
308 namespace Ug
309 {
310 // This one is for directly use only. You can NOT derived it.
311 typedef struct UgJson    Json;
312 };  // namespace Ug
313 
314 #endif  // __cplusplus
315 
316 
317 #endif  // UG_JSON_H
318 
319