-
Notifications
You must be signed in to change notification settings - Fork 0
/
FFJSON.h
executable file
·604 lines (546 loc) · 17.2 KB
/
FFJSON.h
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
/*
* Gowtham Kudupudi 29/09/2013
* MIT License
*/
#ifndef FFJSON_H
#define FFJSON_H
#define MAX_ORDERED_MEMBERS 1000
#define MAX_MEM_ITER_UPDATE 100
#include "config.h"
#include <logger.h>
#include <ferrybase/FerryTimeStamp.h>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <exception>
#include <list>
#include <set>
#include <stdint.h>
#include <cstring>
using namespace std;
enum _ffj_log_level {
FFJ_MAIN = 1 << 0
};
class DLLExport FFJSON {
public:
enum OBJ_TYPE : uint8_t {
UNDEFINED,
STRING,
XML,
NUMBER,
BOOL,
OBJECT,
ARRAY,
LINK,
BINARY,
BIG_OBJECT,
TIME,
NUL
};
enum QUERY_TYPE : uint32_t {
/**
* To clear query type
*/
NONE = 0 << 8,
QUERY = 1 << 8,
SET = 2 << 8,
DEL = 3 << 8,
UPDATE = 4 << 8
};
enum E_FLAGS : uint32_t {
ENONE = 0,
B64ENCODE = 1 << 16,
B64ENCODE_CHILDREN = 1 << 17,
B64ENCODE_STOP = 1 << 18,
COMMENT = 1 << 19,
HAS_COMMENT = 1 << 20,
EXTENDED = 1 << 21, //ARRAY N OBJECT //FM
LONG_LAST_LN = 1 << 21, //STRING //NO_FM
PRECISION = 1 << 22, //NUMBER //FM
EXT_VIA_PARENT = 1 << 22, //ARRAY N OBJECT //FM
ONE_SHORT_LAST_LN = 1 << 22, //STRING //NO_FM
HAS_CHILDREN = 1 << 23, //ARRAY N OBJECT //FM
STRING_INIT = 1 << 23, //STRING //FM
FILE = 1 << 24 //FILE //FM
};
enum COPY_FLAGS : uint32_t {
COPY_NONE = 0,
COPY_QUERIES = 1 << 0,
COPY_EFLAGS = 1 << 1,
COPY_ALL = 0xffffffff
};
enum FeaturedMemType : uint32_t {
FM_TABHEAD = 1,
FM_PRECISION = 1,
FM_WIDTH = 1,
FM_LINK = 2,
FM_PARENT = 3,
FM_CHILDREN = 4,
FM_MAP_SEQUENCE = 5,
FM_MULTI_LN = 6,
FM_UPDATE_TIMESTAMP = 7,
FM_FILE = 8
};
class Exception : exception {
public:
Exception(string e) : identifier(e)
{}
const char* what() const throw () {
return this->identifier.c_str();
}
~Exception() throw ()
{}
private:
string identifier;
};
class Iterator {
public:
Iterator ();
Iterator (const Iterator& orig);
Iterator (const FFJSON& orig, bool end = false);
Iterator (map<string, FFJSON*>::iterator pi);
Iterator (vector<FFJSON*>::iterator ai);
Iterator (
vector<map<string, FFJSON*>::iterator >::iterator pai,
vector<map<string,FFJSON*>::iterator>* pMapItVec
);
virtual ~Iterator ();
void init (const FFJSON& orig, bool end = false);
Iterator& operator ++ ();
Iterator operator ++ (int);
Iterator& operator -- ();
Iterator operator -- (int);
Iterator& operator = (const Iterator& i);
Iterator& operator + (int i);
bool operator == (const Iterator& i);
bool operator != (const Iterator& i);
FFJSON* operator -> ();
FFJSON& operator * ();
operator const char* ();
/**
* Should be only used on OBJECT type iterators
* @return name in the name-value pair of the iterator of the OBJECT
*/
string GetIndex();
/**
* Should be only use on ARRAY type iterators
* @param rCurrArray should be the FFJSON Object of the iterator
* @return index of the iterator of the ARRAY
*/
int GetIndex(const FFJSON& rCurrArray);
private:
uint8_t type;
void copy (const Iterator& i);
union IteratorUnion {
map<string, FFJSON*>::iterator pi;
vector<FFJSON*>::iterator ai;
vector<map<string, FFJSON*>::iterator >::iterator pai;
IteratorUnion () {
memset(this, 0, sizeof (IteratorUnion));
}
IteratorUnion (const IteratorUnion& rFIt) {
memcpy(this, &rFIt, sizeof (IteratorUnion));
}
IteratorUnion (IteratorUnion&& rFIt) {
memcpy(this, &rFIt, sizeof (IteratorUnion));
}
~IteratorUnion ()
{}
IteratorUnion (
const vector<map<string, FFJSON*>::iterator >::iterator&
itMapVector
) {
pai = itMapVector;
}
IteratorUnion (const vector<FFJSON*>::iterator& itVec) {
ai = itVec;
}
IteratorUnion (const map<string, FFJSON*>::iterator& itMap) {
pi = itMap;
}
IteratorUnion& operator = (const IteratorUnion& rFIt) {
memcpy(this, &rFIt, sizeof (IteratorUnion));
return *this;
}
IteratorUnion& operator = (IteratorUnion&& rFIt) {
memcpy(this, &rFIt, sizeof (IteratorUnion));
return *this;
}
friend bool operator < (
const IteratorUnion& lhs,
const IteratorUnion& rhs
) {
return true;
}
} ui;
union ContainerPs {
map<string, FFJSON*>* m_pMap;
vector<FFJSON*>* m_pVector;
vector<map<string, FFJSON*>::iterator>* m_pMapVector;
} m_uContainerPs;
};
struct FeaturedMemHook;
typedef vector<string> Link;
union FeaturedMember {
Link* link;
map<string, int>* tabHead;
FFJSON* m_pParent;
/**
* used to store the number precision
*/
unsigned int precision = 0;
/**
* used to store the width of the string
*/
unsigned int width;
/**
* used to link another Featured member
*/
FeaturedMemHook* m_pFMH;
/**
* used for multiline buffer while parsing
*/
string* m_psMultiLnBuffer;
/**
* used to mark a multi line array during init
*/
bool m_bIsMultiLineArray;
/**
* array of links of all children. these links must be deleted up on
* change.
*/
vector<FFJSON*>* m_pvChildren;
/**
* Its a vector of names in a map for the order
*/
vector<map<string, FFJSON*>::iterator>* m_pvpsMapSequence;
/**
* file name
*/
char* m_sFileName;
FerryTimeStamp* m_pTimeStamp;
FeaturedMember() : link {NULL}
{}
};
struct FeaturedMemHook {
FeaturedMemHook() {
m_uFM.m_pFMH = NULL;
m_pFMH.m_pFMH = NULL;
}
FeaturedMember m_uFM;
FeaturedMember m_pFMH;
};
struct FFJSONExt {
FFJSON* base = NULL;
};
struct FFJSONPObj {
const string* name;
FFJSON* value = NULL;
FFJSONPObj* pObj = NULL;
vector<map<string, FFJSON*>::iterator>* m_pvpsMapSequence;
};
struct FFJSONPrettyPrintPObj : FFJSONPObj {
FFJSONPrettyPrintPObj (
map<const string*, const string*>* m_mpDeps,
list<string>* m_lsFFPairLst,
map<string*, const string*>* m_mpMemKeyFFPairMap,
map<const string*, list<string>::iterator>*
pKeyPrettyStringMap
);
bool m_bHeaded = false;
/**
* to get the parent of object
*/
map<const string*, const string*>* m_mpDeps = NULL;
list<string>* m_lsFFPairLst = NULL;
map<string*, const string*>* m_mpMemKeyFFPairMap = NULL;
map<const string*, list<string>::iterator>*
m_pKeyPrettyStringItMap = NULL;
/**
* Holds column widths for tabular members
*/
map<string, vector<int> >* m_msviClWidths = NULL;
/**
* If this flag is set returns 1st line of string
*/
bool m_bGiveFirstLine = false;
};
union FFJSONIterator {
map<string, FFJSON*>::iterator m_itMap;
unsigned int m_uiIndex;
FFJSONIterator () {
memset(this, 0, sizeof (FFJSONIterator));
}
FFJSONIterator (const FFJSONIterator& rFIt) {
memcpy(this, &rFIt, sizeof (FFJSONIterator));
}
FFJSONIterator (FFJSONIterator&& rFIt) {
memcpy(this, &rFIt, sizeof (FFJSONIterator));
}
~FFJSONIterator ()
{}
FFJSONIterator (const map<string, FFJSON*>::iterator& itMap) {
m_itMap = itMap;
}
FFJSONIterator (const unsigned int uiIndex) {
m_uiIndex = uiIndex;
}
FFJSONIterator& operator = (const FFJSONIterator& rFIt) {
memcpy(this, &rFIt, sizeof (FFJSONIterator));
return *this;
}
FFJSONIterator& operator = (FFJSONIterator&& rFIt) {
memcpy(this, &rFIt, sizeof (FFJSONIterator));
return *this;
}
friend bool operator < (
const FFJSONIterator& lhs,
const FFJSONIterator& rhs
) {
return true;
}
};
struct LinkNRef {
FFJSON* m_pRef = 0;
string m_sLink;
};
union FFValue {
char* string;
vector<FFJSON*>* array;
map<std::string, FFJSON*>* pairs;
double number;
bool boolean;
FFJSON* fptr;
uint8_t* vptr;
FerryTimeStamp* m_pFerryTimeStamp;
FFValue() : string {NULL}
{}
} val;
/**
* creates an UNRECOGNIZED FFJSON object. Any FFJSON object can be
* assigned any other type of FFJSON object.
*/
FFJSON ();
/**
* Copy constructor. Creates a copy of FFJSON object
* @param orig is the object one wants to create a copy
*/
FFJSON (
const FFJSON& orig, COPY_FLAGS cf = COPY_ALL,
FFJSONPObj* pObj = NULL
);
/**
* Creates a FFJSON object from a FFJSON string.
* @param ffjson is the FFJSON string to be parsed.
* @param ci is the offset in FFJSON string to be considered. Its 0 by
* default.
*/
FFJSON (
const string& ffjson, int* ci = NULL, int indent = 0,
FFJSONPObj* pObj = NULL
);
void init (
const string& ffjson, int* ci = NULL, int indent = 0,
FFJSONPObj* pObj = NULL
);
/**
* Creates an empty FFJSON object of type @param t. It throws an Exception
* if @param t is UNRECOGNIZED or anything else other FFJSON_OBJ_TYPE
* @param t
*/
FFJSON(OBJ_TYPE t);
~FFJSON();
/**
* Emptys the FFJSON object. For example If you want delete objects in an
* array or an object, invoke it.
*/
void freeObj(bool bAssignment=false);
static const FeaturedMemType m_FM_LAST = FM_PARENT;
static const char OBJ_STR[10][15];
static map<string, uint8_t> STR_OBJ;
static FFJSON* MarkAsUpdatable(string link, const FFJSON& rParent);
static FFJSON* UnMarkUpdatable(string link, const FFJSON& rParent);
void insertFeaturedMember (FeaturedMember& fms, FeaturedMemType fMT);
FeaturedMember getFeaturedMember (FeaturedMemType fMT) const;
void destroyAllFeaturedMembers (bool bExemptQueries = false);
void deleteFeaturedMember (FeaturedMemType fmt);
/**
* It holds the size of the FFJSON object. array size, object properties,
* string length. Do not change it!! Its made public only for reading
* convenience.
*/
unsigned int size = 0;
/**
* If the object is of type @param t, it returns true else false.
* @param t : type to check
* @return true if type matched
*/
bool isType (OBJ_TYPE t) const;
/**
* Sets type of the object to t
* @param t
*/
void setType (OBJ_TYPE t);
OBJ_TYPE getType () const;
bool isQType (QUERY_TYPE t) const;
void setQType (QUERY_TYPE t);
QUERY_TYPE getQType () const;
bool isEFlagSet (E_FLAGS t) const;
void setEFlag (E_FLAGS t);
E_FLAGS getEFlags () const;
void clearEFlag (E_FLAGS t);
void setFMCount (uint32_t iFMCount);
/**
* Removes leading and trailing white spaces; sapces and tabs from a string.
* @param s
*/
static void trimWhites (string& s);
/**
* Removes leading and trailing quotes in a string.
* @param s
*/
static void trimQuotes (string& s);
/**
* Trying to read an object property that doesn't exist creates the property
* with unrecognized object.
* @param f
*/
void trim ();
/**
* Gives FFJSON object type of FFJSON string.
* @param ffjson is the FFJSON string.
* @return FFJSON object type.
*/
OBJ_TYPE objectType (string ffjson);
/**
* Converts FFJSON object into FFJSON string.
* @return FFJSON string.
*/
string stringify (
bool json = false, bool GetQueryStr = false,
FFJSONPrettyPrintPObj* pObj = NULL
) const;
#define GetQueryString(...) stringify(false,true,NULL);
/**
* Converts FFJSON object into FFJSON pretty string that has indents where
* they needed
* @param indent : Dont bother about it! Its 0 by default which you need. If
* you insist, it prepends its value number of indents to the output. To get
* an idea on what I'm saying, jst try it with non zero positive value.
* @return A pretty string :)
*/
string prettyString (
bool json = false, bool printComments = false,
unsigned int indent = 0, FFJSONPrettyPrintPObj* pObj = NULL,
bool printFilePath = false, bool save = false
) const;
/**
* Generates a query string which can be used to query a FFJSON tree. Query
* string is constructed based on SET, QUERY and DELETE marks on the FFJSON
* objects.
* E.g.
* {animals:{horses:{count:?,colors:?}}} can be used to query horses count
* and colors available!
* @return Query string.
*/
string queryString();
/**
* Generates an answer string for a query object from the FFJSON tree. Query
* object is the FFJSON object returned by FFJSON(queryString).
* E.g.
* {animals:{horses:{count:35,colors:["white","black","brown"]}}}
* can be the answer string for
* {animals:{horses:{count:?,colors:?}}}
* query string.
* @param queryStirng
* @return Answer string
*/
FFJSON* answerString (FFJSON& queryObject);
FFJSON* answerObject (
FFJSON* queryObject, FFJSONPObj* pObj = NULL,
FerryTimeStamp lastUpdateTime = FerryTimeStamp()
);
void erase (string name);
void erase (int index);
void erase (FFJSON* value);
int save () const;
Iterator begin ();
Iterator end();
Iterator find(string key);
void headTheHeader(FFJSONPrettyPrintPObj& lfpo);
void SelfTest();
FFJSON& addLink (FFJSON* obj, string label);
FFJSON& operator [] (const char* prop);
FFJSON& operator [] (const string& prop);
FFJSON& operator [] (const int index);
/**
* returns null FFJSON object if invalid pointer. Deletes the object on
* deleting this FFJSON object if its the last reference.
* @param t pointer to any object
* @return FFJSON object of BINARY type
*/
template <typename T>
FFJSON& operator = (T const& t) {
freeObj ();
ffl_debug (FFJ_MAIN, "size:%d", sizeof(T));
size = sizeof (T);
val .vptr = (uint8_t*) new T (t);
setType (BINARY);
return *this;
}
FFJSON& operator = (const char* s);
FFJSON& operator = (const string& s);
FFJSON& operator = (const int& i);
FFJSON& operator = (const unsigned int& i);
FFJSON& operator = (const double& d);
FFJSON& operator = (const float& f);
FFJSON& operator = (const short& s);
FFJSON& operator = (const long& l);
FFJSON& operator = (const bool& b);
FFJSON& operator = (const FFJSON& f);
FFJSON& operator = (FFJSON* f);
template<typename T>
operator T& () {
ffl_debug (FFJ_MAIN, "size:%d",sizeof(T));
cout << sizeof(T) << endl;
if (isType(BINARY) && size == sizeof(T)) {
return *reinterpret_cast<T*> (val.vptr);
} else {
ffl_err (FFJ_MAIN, "Illegal cast! Type miss match");
return *reinterpret_cast<T*> (val.vptr);
}
}
operator const char* ();
operator double ();
operator float ();
operator bool ();
operator int ();
operator unsigned int ();
private:
uint32_t flags = 0;
FeaturedMember m_uFM;
void copy (
const FFJSON& orig, COPY_FLAGS cf = COPY_NONE,
FFJSONPObj* pObj = NULL
);
static int getIndent (const char* ffjson, int* ci, int indent);
static void strObjMapInit ();
static bool inline isWhiteSpace (char c);
static bool inline isTerminatingChar (char c);
static bool inline isInitializingChar (char c);
static std::map<FFJSON*, set<FFJSONIterator> > sm_mUpdateObjs;
FFJSON* returnNameIfDeclared (vector<string>& prop, FFJSONPObj* fpo) const;
FFJSON* markTheNameIfExtended (FFJSONPrettyPrintPObj* fpo);
bool inherit (FFJSON& obj, FFJSONPObj* pFPObj);
void ReadMultiLinesInContainers (
const string& ffjson, int& i,
FFJSONPObj& pObj
);
string ConstructMultiLineStringArray (
vector<FFJSON*>& vpfMulLnStrs,
int indent, vector<int>& vClWidths) const;
LinkNRef GetLinkString(FFJSONPObj* pObj);
};
ostream& operator << (ostream& out, const FFJSON& f);
#endif