1 /******************** tabjson H Declares Source Code File (.H) *******************/
2 /*  Name: jsonudf.h   Version 1.4                                                */
3 /*                                                                               */
4 /*  (C) Copyright to the author Olivier BERTRAND          2015-2020              */
5 /*                                                                               */
6 /*  This file contains the JSON UDF function and class declares.                 */
7 /*********************************************************************************/
8 #pragma once
9 #include "global.h"
10 #include "plgdbsem.h"
11 #include "block.h"
12 #include "osutil.h"
13 #include "maputil.h"
14 #include "json.h"
15 
16 #define UDF_EXEC_ARGS \
17   UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*
18 
19 // BSON size should be equal on Linux and Windows
20 #define BMX 255
21 typedef struct BSON* PBSON;
22 
23 /***********************************************************************/
24 /*  Structure used to return binary json to Json UDF functions.        */
25 /***********************************************************************/
26 struct BSON {
27 	char    Msg[BMX + 1];
28 	char   *Filename;
29 	PGLOBAL G;
30 	int     Pretty;
31 	ulong   Reslen;
32 	my_bool Changed;
33 	PJSON   Top;
34 	PJSON   Jsp;
35 	PBSON   Bsp;
36 }; // end of struct BSON
37 
38 PBSON JbinAlloc(PGLOBAL g, UDF_ARGS* args, ulong len, PJSON jsp);
39 
40 /*********************************************************************************/
41 /*  The JSON tree node. Can be an Object or an Array.                     	  	 */
42 /*********************************************************************************/
43 typedef struct _jnode {
44 	PSZ   Key;                    // The key used for object
45 	OPVAL Op;                     // Operator used for this node
46 	PVAL  CncVal;                 // To cont value used for OP_CNC
47 	int   Rank;                   // The rank in array
48 	int   Rx;                     // Read row number
49 	int   Nx;                     // Next to read row number
50 } JNODE, *PJNODE;
51 
52 typedef class JSNX     *PJSNX;
53 
54 /*********************************************************************************/
55 /*  The JSON utility functions.                     	  	                       */
56 /*********************************************************************************/
57 bool    IsNum(PSZ s);
58 char   *NextChr(PSZ s, char sep);
59 char   *GetJsonNull(void);
60 uint    GetJsonGrpSize(void);
61 my_bool JsonSubSet(PGLOBAL g, my_bool b = false);
62 my_bool CalcLen(UDF_ARGS* args, my_bool obj, unsigned long& reslen,
63 	              unsigned long& memlen, my_bool mod = false);
64 my_bool JsonInit(UDF_INIT* initid, UDF_ARGS* args, char* message, my_bool mbn,
65 								 unsigned long reslen, unsigned long memlen,
66 								 unsigned long more = 0);
67 my_bool CheckMemory(PGLOBAL g, UDF_INIT* initid, UDF_ARGS* args, uint n,
68 	                  my_bool m, my_bool obj = false, my_bool mod = false);
69 PSZ     MakePSZ(PGLOBAL g, UDF_ARGS* args, int i);
70 int     IsJson(UDF_ARGS* args, uint i, bool b = false);
71 char   *GetJsonFile(PGLOBAL g, char* fn);
72 
73 /*********************************************************************************/
74 /*  The JSON UDF functions.                                               	  	 */
75 /*********************************************************************************/
76 extern "C" {
77 	DllExport my_bool jsonvalue_init(UDF_INIT*, UDF_ARGS*, char*);
78 	DllExport char *jsonvalue(UDF_EXEC_ARGS);
79 	DllExport void jsonvalue_deinit(UDF_INIT*);
80 
81 	DllExport my_bool json_make_array_init(UDF_INIT*, UDF_ARGS*, char*);
82 	DllExport char *json_make_array(UDF_EXEC_ARGS);
83 	DllExport void json_make_array_deinit(UDF_INIT*);
84 
85 	DllExport my_bool json_array_add_values_init(UDF_INIT*, UDF_ARGS*, char*);
86 	DllExport char *json_array_add_values(UDF_EXEC_ARGS);
87 	DllExport void json_array_add_values_deinit(UDF_INIT*);
88 
89 	DllExport my_bool json_array_add_init(UDF_INIT*, UDF_ARGS*, char*);
90 	DllExport char *json_array_add(UDF_EXEC_ARGS);
91 	DllExport void json_array_add_deinit(UDF_INIT*);
92 
93 	DllExport my_bool json_array_delete_init(UDF_INIT*, UDF_ARGS*, char*);
94 	DllExport char *json_array_delete(UDF_EXEC_ARGS);
95 	DllExport void json_array_delete_deinit(UDF_INIT*);
96 
97 	DllExport my_bool jsonsum_int_init(UDF_INIT*, UDF_ARGS*, char*);
98 	DllExport long long jsonsum_int(UDF_INIT*, UDF_ARGS*, char*, char*);
99 	DllExport void jsonsum_int_deinit(UDF_INIT*);
100 
101 	DllExport my_bool jsonsum_real_init(UDF_INIT*, UDF_ARGS*, char*);
102 	DllExport double jsonsum_real(UDF_INIT*, UDF_ARGS*, char*, char*);
103 	DllExport void jsonsum_real_deinit(UDF_INIT*);
104 
105 	DllExport my_bool jsonavg_real_init(UDF_INIT*, UDF_ARGS*, char*);
106 	DllExport double jsonavg_real(UDF_INIT*, UDF_ARGS*, char*, char*);
107 	DllExport void jsonavg_real_deinit(UDF_INIT*);
108 
109 	DllExport my_bool json_make_object_init(UDF_INIT*, UDF_ARGS*, char*);
110 	DllExport char *json_make_object(UDF_EXEC_ARGS);
111 	DllExport void json_make_object_deinit(UDF_INIT*);
112 
113 	DllExport my_bool json_object_nonull_init(UDF_INIT*, UDF_ARGS*, char*);
114 	DllExport char *json_object_nonull(UDF_EXEC_ARGS);
115 	DllExport void json_object_nonull_deinit(UDF_INIT*);
116 
117 	DllExport my_bool json_object_key_init(UDF_INIT*, UDF_ARGS*, char*);
118 	DllExport char *json_object_key(UDF_EXEC_ARGS);
119 	DllExport void json_object_key_deinit(UDF_INIT*);
120 
121 	DllExport my_bool json_object_add_init(UDF_INIT*, UDF_ARGS*, char*);
122 	DllExport char *json_object_add(UDF_EXEC_ARGS);
123 	DllExport void json_object_add_deinit(UDF_INIT*);
124 
125 	DllExport my_bool json_object_delete_init(UDF_INIT*, UDF_ARGS*, char*);
126 	DllExport char *json_object_delete(UDF_EXEC_ARGS);
127 	DllExport void json_object_delete_deinit(UDF_INIT*);
128 
129 	DllExport my_bool json_object_list_init(UDF_INIT*, UDF_ARGS*, char*);
130 	DllExport char *json_object_list(UDF_EXEC_ARGS);
131 	DllExport void json_object_list_deinit(UDF_INIT*);
132 
133 	DllExport my_bool json_object_values_init(UDF_INIT*, UDF_ARGS*, char*);
134 	DllExport char *json_object_values(UDF_EXEC_ARGS);
135 	DllExport void json_object_values_deinit(UDF_INIT*);
136 
137 	DllExport my_bool jsonset_grp_size_init(UDF_INIT*, UDF_ARGS*, char*);
138 	DllExport long long jsonset_grp_size(UDF_INIT*, UDF_ARGS*, char*, char*);
139 
140 	DllExport my_bool jsonget_grp_size_init(UDF_INIT*, UDF_ARGS*, char*);
141 	DllExport long long jsonget_grp_size(UDF_INIT*, UDF_ARGS*, char*, char*);
142 
143 	DllExport my_bool json_array_grp_init(UDF_INIT*, UDF_ARGS*, char*);
144 	DllExport void json_array_grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
145 	DllExport char *json_array_grp(UDF_EXEC_ARGS);
146 	DllExport void json_array_grp_clear(UDF_INIT *, char *, char *);
147 	DllExport void json_array_grp_deinit(UDF_INIT*);
148 
149 	DllExport my_bool json_object_grp_init(UDF_INIT*, UDF_ARGS*, char*);
150 	DllExport void json_object_grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
151 	DllExport char *json_object_grp(UDF_EXEC_ARGS);
152 	DllExport void json_object_grp_clear(UDF_INIT *, char *, char *);
153 	DllExport void json_object_grp_deinit(UDF_INIT*);
154 
155 	DllExport my_bool json_item_merge_init(UDF_INIT*, UDF_ARGS*, char*);
156 	DllExport char *json_item_merge(UDF_EXEC_ARGS);
157 	DllExport void json_item_merge_deinit(UDF_INIT*);
158 
159 	DllExport my_bool json_get_item_init(UDF_INIT*, UDF_ARGS*, char*);
160 	DllExport char *json_get_item(UDF_EXEC_ARGS);
161 	DllExport void json_get_item_deinit(UDF_INIT*);
162 
163 	DllExport my_bool jsonget_string_init(UDF_INIT*, UDF_ARGS*, char*);
164 	DllExport char *jsonget_string(UDF_EXEC_ARGS);
165 	DllExport void jsonget_string_deinit(UDF_INIT*);
166 
167 	DllExport my_bool jsonget_int_init(UDF_INIT*, UDF_ARGS*, char*);
168 	DllExport long long jsonget_int(UDF_INIT*, UDF_ARGS*, char*, char*);
169 	DllExport void jsonget_int_deinit(UDF_INIT*);
170 
171 	DllExport my_bool jsonget_real_init(UDF_INIT*, UDF_ARGS*, char*);
172 	DllExport double jsonget_real(UDF_INIT*, UDF_ARGS*, char*, char*);
173 	DllExport void jsonget_real_deinit(UDF_INIT*);
174 
175 	DllExport my_bool jsoncontains_init(UDF_INIT*, UDF_ARGS*, char*);
176 	DllExport long long jsoncontains(UDF_INIT*, UDF_ARGS*, char*, char*);
177 	DllExport void jsoncontains_deinit(UDF_INIT*);
178 
179 	DllExport my_bool jsonlocate_init(UDF_INIT*, UDF_ARGS*, char*);
180 	DllExport char *jsonlocate(UDF_EXEC_ARGS);
181 	DllExport void jsonlocate_deinit(UDF_INIT*);
182 
183 	DllExport my_bool json_locate_all_init(UDF_INIT*, UDF_ARGS*, char*);
184 	DllExport char *json_locate_all(UDF_EXEC_ARGS);
185 	DllExport void json_locate_all_deinit(UDF_INIT*);
186 
187 	DllExport my_bool jsoncontains_path_init(UDF_INIT*, UDF_ARGS*, char*);
188 	DllExport long long jsoncontains_path(UDF_INIT*, UDF_ARGS*, char*, char*);
189 	DllExport void jsoncontains_path_deinit(UDF_INIT*);
190 
191 	DllExport my_bool json_set_item_init(UDF_INIT*, UDF_ARGS*, char*);
192 	DllExport char *json_set_item(UDF_EXEC_ARGS);
193 	DllExport void json_set_item_deinit(UDF_INIT*);
194 
195 	DllExport my_bool json_insert_item_init(UDF_INIT*, UDF_ARGS*, char*);
196 	DllExport char *json_insert_item(UDF_EXEC_ARGS);
197 	DllExport void json_insert_item_deinit(UDF_INIT*);
198 
199 	DllExport my_bool json_update_item_init(UDF_INIT*, UDF_ARGS*, char*);
200 	DllExport char *json_update_item(UDF_EXEC_ARGS);
201 	DllExport void json_update_item_deinit(UDF_INIT*);
202 
203 	DllExport my_bool json_file_init(UDF_INIT*, UDF_ARGS*, char*);
204 	DllExport char *json_file(UDF_EXEC_ARGS);
205 	DllExport void json_file_deinit(UDF_INIT*);
206 
207 	DllExport my_bool jfile_make_init(UDF_INIT*, UDF_ARGS*, char*);
208 	DllExport char *jfile_make(UDF_EXEC_ARGS);
209 	DllExport void jfile_make_deinit(UDF_INIT*);
210 
211 	DllExport my_bool jbin_array_init(UDF_INIT*, UDF_ARGS*, char*);
212 	DllExport char *jbin_array(UDF_EXEC_ARGS);
213 	DllExport void jbin_array_deinit(UDF_INIT*);
214 
215 	DllExport my_bool jbin_array_add_values_init(UDF_INIT*, UDF_ARGS*, char*);
216 	DllExport char *jbin_array_add_values(UDF_EXEC_ARGS);
217 	DllExport void jbin_array_add_values_deinit(UDF_INIT*);
218 
219 	DllExport my_bool jbin_array_add_init(UDF_INIT*, UDF_ARGS*, char*);
220 	DllExport char *jbin_array_add(UDF_EXEC_ARGS);
221 	DllExport void jbin_array_add_deinit(UDF_INIT*);
222 
223 	DllExport my_bool jbin_array_delete_init(UDF_INIT*, UDF_ARGS*, char*);
224 	DllExport char *jbin_array_delete(UDF_EXEC_ARGS);
225 	DllExport void jbin_array_delete_deinit(UDF_INIT*);
226 
227 	DllExport my_bool jbin_object_init(UDF_INIT*, UDF_ARGS*, char*);
228 	DllExport char *jbin_object(UDF_EXEC_ARGS);
229 	DllExport void jbin_object_deinit(UDF_INIT*);
230 
231 	DllExport my_bool jbin_object_nonull_init(UDF_INIT*, UDF_ARGS*, char*);
232 	DllExport char *jbin_object_nonull(UDF_EXEC_ARGS);
233 	DllExport void jbin_object_nonull_deinit(UDF_INIT*);
234 
235 	DllExport my_bool jbin_object_key_init(UDF_INIT*, UDF_ARGS*, char*);
236 	DllExport char *jbin_object_key(UDF_EXEC_ARGS);
237 	DllExport void jbin_object_key_deinit(UDF_INIT*);
238 
239 	DllExport my_bool jbin_object_add_init(UDF_INIT*, UDF_ARGS*, char*);
240 	DllExport char *jbin_object_add(UDF_EXEC_ARGS);
241 	DllExport void jbin_object_add_deinit(UDF_INIT*);
242 
243 	DllExport my_bool jbin_object_delete_init(UDF_INIT*, UDF_ARGS*, char*);
244 	DllExport char *jbin_object_delete(UDF_EXEC_ARGS);
245 	DllExport void jbin_object_delete_deinit(UDF_INIT*);
246 
247 	DllExport my_bool jbin_object_list_init(UDF_INIT*, UDF_ARGS*, char*);
248 	DllExport char *jbin_object_list(UDF_EXEC_ARGS);
249 	DllExport void jbin_object_list_deinit(UDF_INIT*);
250 
251 	DllExport my_bool jbin_get_item_init(UDF_INIT*, UDF_ARGS*, char*);
252 	DllExport char *jbin_get_item(UDF_EXEC_ARGS);
253 	DllExport void jbin_get_item_deinit(UDF_INIT*);
254 
255 	DllExport my_bool jbin_item_merge_init(UDF_INIT*, UDF_ARGS*, char*);
256 	DllExport char *jbin_item_merge(UDF_EXEC_ARGS);
257 	DllExport void jbin_item_merge_deinit(UDF_INIT*);
258 
259 	DllExport my_bool jbin_set_item_init(UDF_INIT*, UDF_ARGS*, char*);
260 	DllExport char *jbin_set_item(UDF_EXEC_ARGS);
261 	DllExport void jbin_set_item_deinit(UDF_INIT*);
262 
263 	DllExport my_bool jbin_insert_item_init(UDF_INIT*, UDF_ARGS*, char*);
264 	DllExport char *jbin_insert_item(UDF_EXEC_ARGS);
265 	DllExport void jbin_insert_item_deinit(UDF_INIT*);
266 
267 	DllExport my_bool jbin_update_item_init(UDF_INIT*, UDF_ARGS*, char*);
268 	DllExport char *jbin_update_item(UDF_EXEC_ARGS);
269 	DllExport void jbin_update_item_deinit(UDF_INIT*);
270 
271 	DllExport my_bool jbin_file_init(UDF_INIT*, UDF_ARGS*, char*);
272 	DllExport char *jbin_file(UDF_EXEC_ARGS);
273 	DllExport void jbin_file_deinit(UDF_INIT*);
274 
275 	DllExport my_bool json_serialize_init(UDF_INIT*, UDF_ARGS*, char*);
276 	DllExport char *json_serialize(UDF_EXEC_ARGS);
277 	DllExport void json_serialize_deinit(UDF_INIT*);
278 
279 	DllExport my_bool jfile_convert_init(UDF_INIT*, UDF_ARGS*, char*);
280 	DllExport char* jfile_convert(UDF_EXEC_ARGS);
281 	DllExport void jfile_convert_deinit(UDF_INIT*);
282 
283 	DllExport my_bool jfile_bjson_init(UDF_INIT*, UDF_ARGS*, char*);
284 	DllExport char* jfile_bjson(UDF_EXEC_ARGS);
285 	DllExport void jfile_bjson_deinit(UDF_INIT*);
286 
287 	DllExport my_bool envar_init(UDF_INIT*, UDF_ARGS*, char*);
288 	DllExport char *envar(UDF_EXEC_ARGS);
289 
290 #if defined(DEVELOPMENT)
291 	DllExport my_bool uvar_init(UDF_INIT*, UDF_ARGS*, char*);
292 	DllExport char *uvar(UDF_EXEC_ARGS);
293 #endif   // DEVELOPMENT
294 
295 	DllExport my_bool countin_init(UDF_INIT*, UDF_ARGS*, char*);
296 	DllExport long long countin(UDF_INIT*, UDF_ARGS*, char*, char*);
297 } // extern "C"
298 
299 
300 /*********************************************************************************/
301 /*  Structure JPN. Used to make the locate path.                                 */
302 /*********************************************************************************/
303 typedef struct _jpn {
304 	int  Type;
305 	PCSZ Key;
306 	int  N;
307 } JPN, *PJPN;
308 
309 /*********************************************************************************/
310 /*  Class JSNX: JSON access method.                                              */
311 /*********************************************************************************/
312 class JSNX : public BLOCK {
313 public:
314 	// Constructors
315 	JSNX(PGLOBAL g, PJSON row, int type, int len = 64, int prec = 0, my_bool wr = false);
316 
317 	// Implementation
GetPrecision(void)318 	int     GetPrecision(void) {return Prec;}
GetValue(void)319 	PVAL    GetValue(void) {return Value;}
320 
321 	// Methods
322 	my_bool SetJpath(PGLOBAL g, char *path, my_bool jb = false);
323 	my_bool ParseJpath(PGLOBAL g);
324 	void    ReadValue(PGLOBAL g);
325 	PJVAL   GetRowValue(PGLOBAL g, PJSON row, int i, my_bool b = true);
326 	PJVAL   GetJson(PGLOBAL g);
327 	my_bool CheckPath(PGLOBAL g);
328 	my_bool WriteValue(PGLOBAL g, PJVAL jvalp);
329 	char   *Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k = 1);
330 	char   *LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx = 10);
331 
332 protected:
333 	my_bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
334 	PVAL    GetColumnValue(PGLOBAL g, PJSON row, int i);
335 	PVAL    ExpandArray(PGLOBAL g, PJAR arp, int n);
336 	PVAL    GetCalcValue(PGLOBAL g, PJAR bap, int n);
337 	PVAL    CalculateArray(PGLOBAL g, PJAR arp, int n);
338 	PJVAL   MakeJson(PGLOBAL g, PJSON jsp, int i);
339 	void    SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val);
340 	PJSON   GetRow(PGLOBAL g);
341 	my_bool CompareValues(PJVAL v1, PJVAL v2);
342 	my_bool LocateArray(PGLOBAL g, PJAR jarp);
343 	my_bool LocateObject(PGLOBAL g, PJOB jobp);
344 	my_bool LocateValue(PGLOBAL g, PJVAL jvp);
345 	my_bool LocateArrayAll(PGLOBAL g, PJAR jarp);
346 	my_bool LocateObjectAll(PGLOBAL g, PJOB jobp);
347 	my_bool LocateValueAll(PGLOBAL g, PJVAL jvp);
348 	my_bool CompareTree(PGLOBAL g, PJSON jp1, PJSON jp2);
349 	my_bool AddPath(void);
350 
351 	// Default constructor not to be used
JSNX(void)352 	JSNX(void) {}
353 
354 	// Members
355 	PJSON    Row;
356 	PJVAL    Jvalp;
357 	PJPN     Jpnp;
358 	JOUTSTR *Jp;
359 	JNODE   *Nodes;               // The intermediate objects
360 	PVAL     Value;
361 	//PVAL     MulVal;              // To value used by multiple column
362 	char    *Jpath;               // The json path
363 	int      Buf_Type;
364 	int      Long;
365 	int      Prec;
366 	int      Nod;                 // The number of intermediate objects
367 	int      Xnod;                // Index of multiple values
368 	int      K;										// Kth item to locate
369 	int      I;										// Index of JPN
370 	int      Imax;								// Max number of JPN's
371 	int      B;										// Index base
372 	my_bool  Xpd;                 // True for expandable column
373 	my_bool  Parsed;              // True when parsed
374 	my_bool  Found;								// Item found by locate
375 	my_bool  Wr;			  					// Write mode
376 	my_bool  Jb;			  					// Must return json item
377 }; // end of class JSNX
378 
379 /*********************************************************************************/
380 /*  Class JUP: used by jfile_convert to make a json file pretty = 0.             */
381 /*********************************************************************************/
382 class JUP : public BLOCK {
383 public:
384 	// Constructor
385 	JUP(PGLOBAL g);
386 
387 	// Implementation
AddBuff(char c)388 	void  AddBuff(char c) {
389 		if (k < recl)
390 			buff[k++] = c;
391 		else
392 			throw "Record size is too small";
393 	}	// end of AddBuff
394 
395 	// Methods
396 	char *UnprettyJsonFile(PGLOBAL g, char* fn, char* outfn, int lrecl);
397 	bool  unPretty(PGLOBAL g, int lrecl);
398 	void  CopyObject(PGLOBAL g);
399 	void  CopyArray(PGLOBAL g);
400 	void  CopyValue(PGLOBAL g);
401 	void  CopyString(PGLOBAL g);
402 	void  CopyNumeric(PGLOBAL g);
403 
404 	// Members
405 	FILE  *fs;
406 	char  *s;
407 	char  *buff;
408 	size_t len;
409 	uint   i;
410 	int    k, recl;
411 }; // end of class JUP
412