Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVFFileSystem.h
Go to the documentation of this file.
1//===- SVFFileSystem.h -- SVF IR Reader and Writer ------------------------===//
2//
3// SVF - Static Value-Flow Analysis Framework
4// SVF: Static Value-Flow Analysis
5//
6// Copyright (C) <2013-2023> <Yulei Sui>
7//
8
9// This program is free software: you can redistribute it and/or modify
10// it under the terms of the GNU Affero General Public License as published by
11// the Free Software Foundation, either version 3 of the License, or
12// (at your option) any later version.
13
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU Affero General Public License for more details.
18
19// You should have received a copy of the GNU Affero General Public License
20// along with this program. If not, see <http://www.gnu.org/licenses/>.
21//
22//===----------------------------------------------------------------------===//
23
24#ifndef INCLUDE_SVFFILESYSTEM_H_
25#define INCLUDE_SVFFILESYSTEM_H_
26
27#include "Graphs/GenericGraph.h"
28#include "Util/SVFUtil.h"
29#include "Util/cJSON.h"
30#include <type_traits>
31
32#define ABORT_MSG(reason) \
33 do \
34 { \
35 SVFUtil::errs() << __FILE__ << ':' << __LINE__ << ": " << reason \
36 << '\n'; \
37 abort(); \
38 } while (0)
39#define ABORT_IFNOT(condition, reason) \
40 do \
41 { \
42 if (!(condition)) \
43 ABORT_MSG(reason); \
44 } while (0)
45
46#define SVFIR_DEBUG 1 /* Turn this on if you're debugging SVFWriter */
47#if SVFIR_DEBUG
48# define ENSURE_NOT_VISITED(graph) \
49 do \
50 { \
51 static std::set<decltype(graph)> visited; \
52 bool inserted = visited.insert(graph).second; \
53 ABORT_IFNOT(inserted, #graph << " already visited!"); \
54 } while (0)
55#else
56# define ENSURE_NOT_VISITED(graph) \
57 do \
58 { \
59 } while (0)
60#endif
61#define FIELD_NAME_ITEM(field) #field, (field)
62
63#define JSON_FIELD_OR(json, field, default) ((json) ? (json)->field : default)
64#define JSON_KEY(json) JSON_FIELD_OR(json, string, "NULL")
65#define JSON_CHILD(json) JSON_FIELD_OR(json, child, nullptr)
66
67#define JSON_WRITE_FIELD(root, objptr, field) \
68 jsonAddJsonableToObject(root, #field, (objptr)->field)
69
70#define JSON_READ_OBJ_WITH_NAME(json, obj, name) \
71 do \
72 { \
73 ABORT_IFNOT(jsonKeyEquals(json, name), \
74 "Expect name '" << name << "', got " << JSON_KEY(json)); \
75 SVFIRReader::readJson(json, obj); \
76 } while (0)
77
78#define JSON_READ_OBJ_WITH_NAME_FWD(json, obj, name) \
79 do \
80 { \
81 JSON_READ_OBJ_WITH_NAME(json, obj, name); \
82 json = (json)->next; \
83 } while (0)
84
85#define JSON_READ_OBJ(json, obj) JSON_READ_OBJ_WITH_NAME(json, obj, #obj)
86#define JSON_READ_OBJ_FWD(json, obj) \
87 JSON_READ_OBJ_WITH_NAME_FWD(json, obj, #obj)
88#define JSON_DEF_READ_FWD(json, type, obj, ...) \
89 type obj __VA_ARGS__; \
90 JSON_READ_OBJ_FWD(json, obj)
91#define JSON_READ_FIELD_FWD(json, objptr, field) \
92 JSON_READ_OBJ_WITH_NAME_FWD(json, (objptr)->field, #field)
93#define CHECK_JSON_KEY_EQUALS(obj, key) \
94 ABORT_IFNOT(jsonKeyEquals(obj, key), \
95 "Expect json key: " << key << ", but get " << JSON_KEY(obj));
96#define CHECK_JSON_KEY(obj) CHECK_JSON_KEY_EQUALS(obj, #obj)
97
98namespace SVF
99{
102class NodeIDAllocator;
103// Classes created upon SVFMoudle construction
104class SVFType;
105class SVFPointerType;
106class SVFIntegerType;
107class SVFFunctionType;
108class SVFStructType;
109class SVFArrayType;
110class SVFOtherType;
111
112class StInfo; // Every SVFType is linked to a StInfo. It also references SVFType
113
114class SVFValue;
115class SVFFunction;
116class SVFBasicBlock;
117class SVFInstruction;
118class SVFCallInst;
119class SVFConstant;
120class SVFGlobalValue;
121class SVFArgument;
122class SVFConstantData;
123class SVFConstantInt;
124class SVFConstantFP;
125class SVFConstantNullPtr;
126class SVFBlackHoleValue;
127class SVFOtherValue;
128class SVFMetadataAsValue;
129
130class SVFLoopAndDomInfo; // Part of SVFFunction
131
132// Classes created upon buildSymbolTableInfo
133class MemObj;
134
135// Classes created upon ICFG construction
136class ICFGNode;
137class GlobalICFGNode;
138class IntraICFGNode;
139class InterICFGNode;
140class FunEntryICFGNode;
141class FunExitICFGNode;
142class CallICFGNode;
143class RetICFGNode;
144
145class ICFGEdge;
146class IntraCFGEdge;
147class CallCFGEdge;
148class RetCFGEdge;
149
150class SVFIR;
151class SVFIRWriter;
152class SVFLoop;
153class ICFG;
154class IRGraph;
155class CHGraph;
156class CommonCHGraph;
157class SymbolTableInfo;
158
159class SVFModule;
160
161class AccessPath;
162class ObjTypeInfo; // Need SVFType
163
164class SVFVar;
165class ValVar;
166class ObjVar;
167class GepValVar;
168class GepObjVar;
169class BaseObjVar;
170class RetPN;
171class VarArgPN;
172class DummyValVar;
173class DummyObjVar;
174
175class SVFStmt;
176class AssignStmt;
177class AddrStmt;
178class CopyStmt;
179class StoreStmt;
180class LoadStmt;
181class GepStmt;
182class CallPE;
183class RetPE;
184class MultiOpndStmt;
185class PhiStmt;
186class SelectStmt;
187class CmpStmt;
188class BinaryOPStmt;
189class UnaryOPStmt;
190class BranchStmt;
191class TDForkPE;
192class TDJoinPE;
193
194class CHNode;
195class CHEdge;
196class CHGraph;
197// End of forward declarations
199
200bool jsonIsBool(const cJSON* item);
201bool jsonIsBool(const cJSON* item, bool& flag);
202bool jsonIsNumber(const cJSON* item);
203bool jsonIsString(const cJSON* item);
204bool jsonIsNullId(const cJSON* item);
205bool jsonIsArray(const cJSON* item);
206bool jsonIsMap(const cJSON* item);
207bool jsonIsObject(const cJSON* item);
208bool jsonKeyEquals(const cJSON* item, const char* key);
209std::pair<const cJSON*, const cJSON*> jsonUnpackPair(const cJSON* item);
210double jsonGetNumber(const cJSON* item);
214cJSON* jsonCreateString(const char* str);
217cJSON* jsonCreateNumber(double num);
218bool jsonAddPairToMap(cJSON* obj, cJSON* key, cJSON* value);
219bool jsonAddItemToObject(cJSON* obj, const char* name, cJSON* item);
222bool jsonAddNumberToObject(cJSON* obj, const char* name, double number);
223bool jsonAddStringToObject(cJSON* obj, const char* name, const char* str);
224bool jsonAddStringToObject(cJSON* obj, const char* name, const std::string& s);
225#define jsonForEach(field, array) \
226 for (const cJSON* field = JSON_CHILD(array); field; field = field->next)
227
231template <typename T> class WriterPtrPool
232{
233private:
235 std::vector<const T*> ptrPool;
236
237public:
238 inline size_t getID(const T* ptr)
239 {
240 if (!ptr)
241 return 0;
242
243 typename decltype(ptrToId)::iterator it;
244 bool inserted;
245 std::tie(it, inserted) = ptrToId.emplace(ptr, 1 + ptrPool.size());
246 if (inserted)
247 ptrPool.push_back(ptr);
248 return it->second;
249 }
250
251 inline void saveID(const T* ptr)
252 {
253 getID(ptr);
254 }
255
256 inline const T* getPtr(size_t id) const
257 {
258 assert(id <= ptrPool.size() && "Invalid ID");
259 return id ? ptrPool[id - 1] : nullptr;
260 }
261
262 inline const std::vector<const T*>& getPool() const
263 {
264 return ptrPool;
265 }
266
267 inline size_t size() const
268 {
269 return ptrPool.size();
270 }
271
272 inline void reserve(size_t size)
273 {
274 ptrPool.reserve(size);
275 }
276
277 inline auto begin() const
278 {
279 return ptrPool.cbegin();
280 }
281
282 inline auto end() const
283 {
284 return ptrPool.cend();
285 }
286};
287
288template <typename NodeTy, typename EdgeTy> class GenericGraphWriter
289{
290 friend class SVFIRWriter;
291
292private:
296
297 // const GraphType* graph;
299
300public:
302 {
303 assert(graph && "Graph pointer should never be null");
304 edgePool.reserve(graph->getTotalEdgeNum());
305
306 for (const auto& pair : graph->IDToNodeMap)
307 {
308 const NodeType* node = pair.second;
309
310 for (const EdgeType* edge : node->getOutEdges())
311 {
313 }
314 }
315 }
316
317 inline size_t getEdgeID(const EdgeType* edge)
318 {
319 return edgePool.getID(edge);
320 }
321};
322
324
326{
327 friend class SVFIRWriter;
328
329private:
331
332public:
333 ICFGWriter(const ICFG* icfg);
334
335 inline size_t getSvfLoopID(const SVFLoop* loop)
336 {
337 return svfLoopPool.getID(loop);
338 }
339};
340
343
345{
346 friend class SVFIRWriter;
347
348private:
352
353public:
354 SVFModuleWriter(const SVFModule* svfModule);
355
356 inline size_t getSVFValueID(const SVFValue* value)
357 {
358 return svfValuePool.getID(value);
359 }
360 inline const SVFValue* getSVFValuePtr(size_t id) const
361 {
362 return svfValuePool.getPtr(id);
363 }
364 inline size_t getSVFTypeID(const SVFType* type)
365 {
366 return svfTypePool.getID(type);
367 }
368 inline size_t getStInfoID(const StInfo* stInfo)
369 {
370 return stInfoPool.getID(stInfo);
371 }
372 inline size_t sizeSVFValuePool() const
373 {
374 return svfValuePool.size();
375 }
376};
377
379{
380private:
381 const SVFIR* svfIR;
382
387
389
390public:
391 using autoJSON = std::unique_ptr<cJSON, decltype(&cJSON_Delete)>;
392 using autoCStr = std::unique_ptr<char, decltype(&cJSON_free)>;
393
395 SVFIRWriter(const SVFIR* svfir);
396
397 static void writeJsonToOstream(const SVFIR* svfir, std::ostream& os);
398 static void writeJsonToPath(const SVFIR* svfir, const std::string& path);
399
400private:
404
405 const char* numToStr(size_t n);
406
409 cJSON* toJson(const SVFModule* module);
410 cJSON* toJson(const SVFType* type);
411 cJSON* toJson(const SVFValue* value);
412 cJSON* toJson(const IRGraph* graph); // IRGraph Graph
413 cJSON* toJson(const SVFVar* var); // IRGraph Node
414 cJSON* toJson(const SVFStmt* stmt); // IRGraph Edge
415 cJSON* toJson(const ICFG* icfg); // ICFG Graph
416 cJSON* toJson(const ICFGNode* node); // ICFG Node
417 cJSON* toJson(const ICFGEdge* edge); // ICFG Edge
418 cJSON* toJson(const CommonCHGraph* graph); // CHGraph Graph
419 cJSON* toJson(const CHGraph* graph); // CHGraph Graph
420 cJSON* toJson(const CHNode* node); // CHGraph Node
421 cJSON* toJson(const CHEdge* edge); // CHGraph Edge
422
423 cJSON* toJson(const AccessPath& ap);
424 cJSON* toJson(const SVFLoop* loop);
425 cJSON* toJson(const MemObj* memObj);
426 cJSON* toJson(const ObjTypeInfo* objTypeInfo); // Only owned by MemObj
427 cJSON* toJson(const SVFLoopAndDomInfo* ldInfo); // Only owned by SVFFunction
428 cJSON* toJson(const StInfo* stInfo);
429
430 // No need for 'toJson(short)' because of promotion to int
431 static cJSON* toJson(bool flag);
432 static cJSON* toJson(unsigned number);
433 static cJSON* toJson(int number);
434 static cJSON* toJson(float number);
435 static cJSON* toJson(const std::string& str);
436 cJSON* toJson(unsigned long number);
437 cJSON* toJson(long long number);
438 cJSON* toJson(unsigned long long number);
439
444 cJSON* virtToJson(const SVFType* type);
445 cJSON* virtToJson(const SVFValue* value);
446 cJSON* virtToJson(const SVFVar* var);
447 cJSON* virtToJson(const SVFStmt* stmt);
448 cJSON* virtToJson(const ICFGNode* node);
449 cJSON* virtToJson(const ICFGEdge* edge);
450 cJSON* virtToJson(const CHNode* node);
451 cJSON* virtToJson(const CHEdge* edge);
452
453 // Classes inherited from SVFVar
454 cJSON* contentToJson(const SVFVar* var);
455 cJSON* contentToJson(const ValVar* var);
456 cJSON* contentToJson(const ObjVar* var);
460 cJSON* contentToJson(const RetPN* var);
464
465 // Classes inherited from SVFStmt
474 cJSON* contentToJson(const RetPE* edge);
484
485 // Classes inherited from ICFGNode
486 cJSON* contentToJson(const ICFGNode* node);
487 cJSON* contentToJson(const GlobalICFGNode* node);
488 cJSON* contentToJson(const IntraICFGNode* node);
489 cJSON* contentToJson(const InterICFGNode* node);
491 cJSON* contentToJson(const FunExitICFGNode* node);
492 cJSON* contentToJson(const CallICFGNode* node);
493 cJSON* contentToJson(const RetICFGNode* node);
494
495 // Classes inherited from ICFGEdge
500
501 // CHNode & CHEdge
502 cJSON* contentToJson(const CHNode* node);
504
512
513 cJSON* contentToJson(const SVFValue* value);
514 cJSON* contentToJson(const SVFFunction* value);
515 cJSON* contentToJson(const SVFBasicBlock* value);
516 cJSON* contentToJson(const SVFInstruction* value);
517 cJSON* contentToJson(const SVFCallInst* value);
518 cJSON* contentToJson(const SVFConstant* value);
519 cJSON* contentToJson(const SVFGlobalValue* value);
520 cJSON* contentToJson(const SVFArgument* value);
521 cJSON* contentToJson(const SVFConstantData* value);
522 cJSON* contentToJson(const SVFConstantInt* value);
523 cJSON* contentToJson(const SVFConstantFP* value);
526 cJSON* contentToJson(const SVFOtherValue* value);
528
529 // Other classes
531 cJSON* contentToJson(const MemObj* memObj); // Owned by SymbolTable->objMap
534
535 template <typename NodeTy, typename EdgeTy>
537 {
538 cJSON* root = jsonCreateObject();
539 JSON_WRITE_FIELD(root, node, id);
540 JSON_WRITE_FIELD(root, node, nodeKind);
541 JSON_WRITE_FIELD(root, node, InEdges);
542 JSON_WRITE_FIELD(root, node, OutEdges);
543 return root;
544 }
545
546 template <typename NodeTy>
548 {
549 cJSON* root = jsonCreateObject();
550 JSON_WRITE_FIELD(root, edge, edgeFlag);
551 JSON_WRITE_FIELD(root, edge, src);
552 JSON_WRITE_FIELD(root, edge, dst);
553 return root;
554 }
555
556 template <typename NodeTy, typename EdgeTy>
558 const std::vector<const EdgeTy*>& edgePool)
559 {
560 cJSON* root = jsonCreateObject();
561
563 for (const auto& pair : graph->IDToNodeMap)
564 {
565 NodeTy* node = pair.second;
566 cJSON* jsonNode = virtToJson(node);
568 }
569
571 for (const EdgeTy* edge : edgePool)
572 {
575 }
576
577 JSON_WRITE_FIELD(root, graph, nodeNum);
579 JSON_WRITE_FIELD(root, graph, edgeNum);
581
582 return root;
583 }
584
611 template <typename T, typename U> cJSON* toJson(const std::pair<T, U>& pair)
612 {
616 return obj;
617 }
618
619 template <typename T,
620 typename = std::enable_if_t<SVFUtil::is_iterable_v<T>>>
622 {
624 for (const auto& item : container)
625 {
628 }
629 return array;
630 }
631
632 template <typename T>
633 bool jsonAddJsonableToObject(cJSON* obj, const char* name, const T& item)
634 {
637 }
638
639 template <typename T>
640 bool jsonAddContentToObject(cJSON* obj, const char* name, const T& item)
641 {
644 }
645};
646
647/*
648 * Reader Part
649 */
650
654template <typename T, typename = void> struct KindBaseHelper
655{
656};
657#define KIND_BASE(B, KindGetter) \
658 template <typename T> \
659 struct KindBaseHelper<T, std::enable_if_t<std::is_base_of<B, T>::value>> \
660 { \
661 using type = B; \
662 static inline s64_t getKind(T* p) \
663 { \
664 return {p->KindGetter()}; \
665 } \
666 }
669KIND_BASE(SVFVar, getNodeKind);
670KIND_BASE(SVFStmt, getEdgeKind);
671KIND_BASE(ICFGNode, getNodeKind);
672KIND_BASE(ICFGEdge, getEdgeKind);
673KIND_BASE(CHNode, getNodeKind);
674KIND_BASE(CHEdge, getEdgeKind);
675#undef KIND_BASE
676
677template <typename T> using KindBaseT = typename KindBaseHelper<T>::type;
679
682template <typename T> class ReaderIDToObjMap
683{
684private:
687
688public:
689 template <typename IdObjCreator>
692 {
693 assert(idMap.empty() &&
694 "idToObjMap should be empty when creating objects");
695 ABORT_IFNOT(jsonIsArray(idObjArrayJson), "expects an array");
696
698 {
699 ABORT_IFNOT(jsonIsObject(objJson), "expects an object");
701 // creator is allowed to change objFieldJson
703 auto pair = std::pair<const cJSON*, T*>(objFieldJson, idObj.second);
704 bool inserted = idMap.emplace(idObj.first, pair).second;
705 ABORT_IFNOT(inserted, "ID " << idObj.first << " duplicated in "
706 << idObjArrayJson->string);
707 }
708 }
709
710 T* getPtr(unsigned id) const
711 {
712 auto it = idMap.find(id);
713 ABORT_IFNOT(it != idMap.end(), "ID " << id << " not found");
714 return it->second.second;
715 }
716
717 template <typename FillFunc> void fillObjs(FillFunc fillFunc)
718 {
719 for (auto& pair : idMap)
720 {
721 const cJSON* objFieldJson = pair.second.first;
722 T* obj = pair.second.second;
724
725 ABORT_IFNOT(!objFieldJson, "json should be consumed by filler, but "
726 << objFieldJson->string << " left");
727 }
728 }
729
730 inline size_t size() const
731 {
732 return idMap.size();
733 }
734
735 template <typename Map> void saveToIDToObjMap(Map& idToObjMap) const
736 {
737 for (auto& pair : idMap)
738 {
739 unsigned id = pair.first;
740 T* obj = pair.second.second;
741 assert(obj && "obj should not be null");
742 idToObjMap.insert(std::make_pair(id, obj));
743 }
744 }
745};
746
749template <typename T> class ReaderPtrPool
750{
751private:
752 std::vector<const cJSON*> jsonArray;
753 std::vector<T*> ptrPool;
754
755public:
756 inline void reserve(size_t size)
757 {
758 jsonArray.reserve(size);
759 ptrPool.reserve(size);
760 }
761
766 template <typename Creator>
768 {
769 assert(jsonArray.empty() &&
770 "jsonArray should be empty when creating objects");
771 ABORT_IFNOT(jsonIsArray(objArrayJson), "expects an array");
772
774 {
775 ABORT_IFNOT(jsonIsObject(objJson), "expects objects in array");
778 jsonArray.push_back(objFieldJson);
779 ptrPool.push_back(obj);
780 }
781 }
782
783 T* getPtr(size_t id) const
784 {
785 ABORT_IFNOT(id <= ptrPool.size(),
786 "Invalid ID " << id << ". Max ID = " << ptrPool.size());
787 return id ? ptrPool[id - 1] : nullptr;
788 }
789
790 template <typename FillFunc> void fillObjs(FillFunc fillFunc)
791 {
792 assert(jsonArray.size() == ptrPool.size() &&
793 "jsonArray and ptrPool should have same size");
794 for (size_t i = 0; i < jsonArray.size(); ++i)
795 {
796 const cJSON*& objFieldJson = jsonArray[i];
798 ABORT_IFNOT(!objFieldJson, "json should be consumed by filler, but "
799 << objFieldJson->string << " left");
800 }
801 jsonArray.clear();
802 jsonArray.shrink_to_fit();
803 }
804
805 inline size_t size() const
806 {
807 return ptrPool.size();
808 }
809
810 template <typename Set> void saveToSet(Set& set) const
811 {
812 for (T* obj : ptrPool)
813 {
814 set.insert(obj);
815 }
816 }
817};
818
819template <typename NodeTy, typename EdgeTy> class GenericGraphReader
820{
821private:
824
825protected:
826 const cJSON* graphFieldJson = nullptr;
827
828public:
829 template <typename NodeCreator, typename EdgeCreator>
832 {
833 // Read nodeNum
834 const cJSON* nodeNum = graphJson->child;
835 CHECK_JSON_KEY(nodeNum);
836 u32_t numOfNodes = jsonGetNumber(nodeNum);
837 (void)numOfNodes;
838
839 // Read allNode
840 const cJSON* allNode = nodeNum->next;
843 // TODO: ABORT_IFNOT(idToNodeMap.size() == numOfNodes, "nodeNum mismatch");
844
845 // Read edgeNum
846 const cJSON* edgeNum = allNode->next;
847 CHECK_JSON_KEY(edgeNum);
848 u32_t numOfEdges = jsonGetNumber(edgeNum);
849 (void)numOfEdges;
850
851 // Read allEdge
852 const cJSON* allEdge = edgeNum->next;
855 // TODO: ABORT_IFNOT(edgePool.size() == numOfEdges, "edgeNum mismatch");
856
857 // Rest fields
858 assert(!graphFieldJson && "graphFieldJson should be empty");
860 }
861
862 inline NodeTy* getNodePtr(unsigned id) const
863 {
864 return idToNodeMap.getPtr(id);
865 }
866
867 inline EdgeTy* getEdgePtr(unsigned id) const
868 {
869 return edgePool.getPtr(id);
870 }
871
872 template <typename NodeFiller, typename EdgeFiller>
874 {
875 // GenericNode<> contains field `InEdges` and `OutEdges`, which are
876 // ordered set of edges with comparator `GenericEdge::equalGEdge()`,
877 // which need operands `src` and `dst` to be non-null to get IDs, so we
878 // need to fill nodes first.
881 }
882
884 {
885 graph->edgeNum = edgePool.size();
886 graph->nodeNum = idToNodeMap.size();
888 }
889
890 const cJSON* getFieldJson() const
891 {
892 return graphFieldJson;
893 }
894};
895
897{
898 friend class SVFIRReader;
899
900private:
901 const cJSON* symTabFieldJson = nullptr;
903
904public:
905 inline MemObj* getMemObjPtr(unsigned id) const
906 {
907 return memObjMap.getPtr(id);
908 }
909
910 template <typename MemObjCreator>
912 {
913 assert(!symTabFieldJson && "symTabFieldJson should be empty");
914 ABORT_IFNOT(jsonIsObject(symTabJson), "symTableJson is not an object?");
915
916 const cJSON* const allMemObj = symTabJson->child;
918 memObjMap.createObjs(allMemObj, memObjCreator);
919
921 }
922
923 inline const cJSON* getFieldJson() const
924 {
925 return symTabFieldJson;
926 }
927};
928
932
934{
935 // friend class SVFIRReader;
936
937private:
939
940public:
941 template <typename NodeCreator, typename EdgeCreator, typename SVFLoopCreator>
952
953 inline SVFLoop* getSVFLoopPtr(size_t id) const
954 {
955 return svfLoopPool.getPtr(id);
956 }
957
958 template <typename NodeFiller, typename EdgeFiller, typename LoopFiller>
965};
966
968{
969 friend class SVFIRReader;
970
971private:
972 const cJSON* svfModuleFieldJson = nullptr;
976
977public:
978 template <typename SVFTypeCreator, typename SVFTypeFiller,
979 typename SVFValueCreator, typename SVFValueFiller,
980 typename StInfoCreator>
984 {
985 assert(!svfModuleFieldJson && "SVFModule Already created?");
987 "svfModuleJson not an JSON object?");
988
989 const cJSON* const allSVFType = svfModuleJson->child;
992
993 const cJSON* const allStInfo = allSVFType->next;
995 stInfoPool.createObjs(allStInfo, stInfoCreator); // Only need SVFType*
996
997 svfTypePool.fillObjs(typeFiller); // Only need SVFType* & StInfo*
998
999 const cJSON* const allSVFValue = allStInfo->next;
1002 svfValuePool.fillObjs(valueFiller); // Need SVFType* & SVFValue*
1003
1005 }
1006
1007 inline SVFValue* getSVFValuePtr(size_t id) const
1008 {
1009 return svfValuePool.getPtr(id);
1010 }
1011 inline SVFType* getSVFTypePtr(size_t id) const
1012 {
1013 return svfTypePool.getPtr(id);
1014 }
1015 inline StInfo* getStInfoPtr(size_t id) const
1016 {
1017 return stInfoPool.getPtr(id);
1018 }
1019
1020 const cJSON* getFieldJson() const
1021 {
1022 return svfModuleFieldJson;
1023 }
1024};
1025
1026/* SVFIRReader
1027 * Read SVFIR from JSON
1028 */
1029
1031{
1032private:
1038
1039public:
1040 static SVFIR* read(const std::string& path);
1041
1042 static void readJson(const cJSON* obj, bool& flag);
1043 static void readJson(const cJSON* obj, unsigned& val);
1044 static void readJson(const cJSON* obj, int& val);
1045 static void readJson(const cJSON* obj, short& val);
1046 static void readJson(const cJSON* obj, float& val);
1047 static void readJson(const cJSON* obj, unsigned long& val);
1048 static void readJson(const cJSON* obj, long long& val);
1049 static void readJson(const cJSON* obj, unsigned long long& val);
1050 static void readJson(const cJSON* obj, std::string& str);
1051
1052 // Helper functions
1053 static inline s64_t applyEdgeMask(u64_t edgeFlag)
1054 {
1055 return edgeFlag & GenericEdge<void>::EdgeKindMask;
1056 }
1057 template <typename T>
1058 static inline void setEdgeFlag(GenericEdge<T>* edge,
1059 typename GenericEdge<T>::GEdgeFlag edgeFlag)
1060 {
1061 edge->edgeFlag = edgeFlag;
1062 }
1063
1064private:
1065 using GNodeK = s32_t;
1069 static ICFGEdge* createICFGEdge(GEdgeKind kind);
1070 static CHNode* createCHNode(NodeID id, GNodeK kind);
1071 static CHEdge* createCHEdge(GEdgeKind kind);
1072 static SVFVar* createPAGNode(NodeID id, GNodeK kind);
1073 static SVFStmt* createPAGEdge(GEdgeKind kind);
1074
1075 template <typename EdgeCreator>
1077 {
1078 auto kind = SVFIRReader::applyEdgeMask(flag);
1079 auto edge = creator(kind);
1081 return edge;
1082 }
1083
1084 SVFIR* read(const cJSON* root);
1085 const cJSON* createObjs(const cJSON* root);
1086
1089 void readJson(IRGraph* graph); // IRGraph Graph
1090 void readJson(ICFG* icfg); // ICFG Graph
1091 void readJson(CHGraph* graph); // CHGraph Graph
1092 void readJson(SVFModule* module);
1093
1094 void readJson(const cJSON* obj, SVFType*& type);
1095 void readJson(const cJSON* obj, StInfo*& stInfo);
1096 void readJson(const cJSON* obj, SVFValue*& value);
1097
1098 void readJson(const cJSON* obj, SVFVar*& var); // IRGraph Node
1099 void readJson(const cJSON* obj, SVFStmt*& stmt); // IRGraph Edge
1100 void readJson(const cJSON* obj, ICFGNode*& node); // ICFG Node
1101 void readJson(const cJSON* obj, ICFGEdge*& edge); // ICFG Edge
1102 void readJson(const cJSON* obj, CHNode*& node); // CHGraph Node
1103 void readJson(const cJSON* obj, CHEdge*& edge); // CHGraph Edge
1104
1105 void readJson(const cJSON* obj, AccessPath& ap);
1106 void readJson(const cJSON* obj, SVFLoop*& loop);
1107 void readJson(const cJSON* obj, MemObj*& memObj);
1108 void readJson(const cJSON* obj,
1109 ObjTypeInfo*& objTypeInfo); // Only owned by MemObj
1110 void readJson(const cJSON* obj,
1111 SVFLoopAndDomInfo*& ldInfo); // Only owned by SVFFunction
1112
1113 template <unsigned ElementSize>
1115 {
1116 ABORT_IFNOT(jsonIsArray(obj), "SparseBitVector should be an array");
1118 {
1119 unsigned n;
1120 readJson(nObj, n);
1121 bv.set(n);
1122 }
1123 }
1124
1125 /* See comment of toJson(SparseBitVectorElement) for reason of commenting
1126 it out.
1127 template <unsigned ElementSize>
1128 inline void readJson(const cJSON* obj,
1129 SparseBitVectorElement<ElementSize>& element)
1130 {
1131 readJson(obj, element.Bits);
1132 }
1133 */
1134
1137 template <typename T>
1139 {
1140 // TODO: Can be optimized?
1143 if (!basePtr)
1144 return; // ptr is nullptr when read
1145 ptr = SVFUtil::dyn_cast<T>(basePtr);
1146 ABORT_IFNOT(ptr, "Cast: " << obj->string << " shouldn't have kind "
1148 }
1149
1151 template <typename T> inline void readJson(const cJSON* obj, const T*& cptr)
1152 {
1153 assert(!cptr && "const pointer should be NULL");
1154 T* ptr{};
1155 readJson(obj, ptr);
1156 cptr = ptr;
1157 }
1158
1159 template <typename T1, typename T2>
1160 void readJson(const cJSON* obj, std::pair<T1, T2>& pair)
1161 {
1162 auto jpair = jsonUnpackPair(obj);
1163 readJson(jpair.first, pair.first);
1164 readJson(jpair.second, pair.second);
1165 }
1166
1167 template <typename T, size_t N>
1168 void readJson(const cJSON* obj, T (&array)[N])
1169 {
1170 static_assert(N > 0, "array size should be greater than 0");
1171 ABORT_IFNOT(jsonIsArray(obj), "array expects an array");
1172 size_t i = 0;
1174 {
1176 if (++i >= N)
1177 break;
1178 }
1179 ABORT_IFNOT(i == N, "expect array of size " << N);
1180 }
1181
1182 template <typename C>
1183 std::enable_if_t<SVFUtil::is_sequence_container_v<C>> readJson(
1184 const cJSON* obj, C& container)
1185 {
1186 using T = typename C::value_type;
1187 assert(container.empty() && "container should be empty");
1188 ABORT_IFNOT(jsonIsArray(obj), "vector expects an array");
1190 {
1191 container.push_back(T{});
1192 readJson(elemJson, container.back());
1193 }
1194 }
1195
1196 template <typename C>
1197 std::enable_if_t<SVFUtil::is_map_v<C>> readJson(const cJSON* obj, C& map)
1198 {
1199 assert(map.empty() && "map should be empty");
1200 ABORT_IFNOT(jsonIsMap(obj), "expects an map (represented by array)");
1202 {
1204 typename C::key_type key{};
1205 readJson(jpair.first, key);
1206 auto it = map.emplace(std::move(key), typename C::mapped_type{});
1207 ABORT_IFNOT(it.second, "Duplicated map key");
1208 readJson(jpair.second, it.first->second);
1209 }
1210 }
1211
1212 template <typename C>
1213 std::enable_if_t<SVFUtil::is_set_v<C>> readJson(const cJSON* obj, C& set)
1214 {
1215 using T = typename C::value_type;
1216 assert(set.empty() && "set should be empty");
1217 ABORT_IFNOT(jsonIsArray(obj), "expects an array");
1219 {
1220 T elem{};
1222 auto inserted = set.insert(std::move(elem)).second;
1223 ABORT_IFNOT(inserted, "Duplicated set element");
1224 }
1225 }
1226
1227 // IGRaph
1228 void virtFill(const cJSON*& fieldJson, SVFVar* var);
1229 void fill(const cJSON*& fieldJson, SVFVar* var);
1230 void fill(const cJSON*& fieldJson, ValVar* var);
1231 void fill(const cJSON*& fieldJson, ObjVar* var);
1232 void fill(const cJSON*& fieldJson, GepValVar* var);
1233 void fill(const cJSON*& fieldJson, GepObjVar* var);
1234 void fill(const cJSON*& fieldJson, BaseObjVar* var);
1235 void fill(const cJSON*& fieldJson, RetPN* var);
1236 void fill(const cJSON*& fieldJson, VarArgPN* var);
1237 void fill(const cJSON*& fieldJson, DummyValVar* var);
1238 void fill(const cJSON*& fieldJson, DummyObjVar* var);
1239
1240 void virtFill(const cJSON*& fieldJson, SVFStmt* stmt);
1241 void fill(const cJSON*& fieldJson, SVFStmt* stmt);
1242 void fill(const cJSON*& fieldJson, AssignStmt* stmt);
1243 void fill(const cJSON*& fieldJson, AddrStmt* stmt);
1244 void fill(const cJSON*& fieldJson, CopyStmt* stmt);
1245 void fill(const cJSON*& fieldJson, StoreStmt* stmt);
1246 void fill(const cJSON*& fieldJson, LoadStmt* stmt);
1247 void fill(const cJSON*& fieldJson, GepStmt* stmt);
1248 void fill(const cJSON*& fieldJson, CallPE* stmt);
1249 void fill(const cJSON*& fieldJson, RetPE* stmt);
1250 void fill(const cJSON*& fieldJson, MultiOpndStmt* stmt);
1251 void fill(const cJSON*& fieldJson, PhiStmt* stmt);
1252 void fill(const cJSON*& fieldJson, SelectStmt* stmt);
1253 void fill(const cJSON*& fieldJson, CmpStmt* stmt);
1254 void fill(const cJSON*& fieldJson, BinaryOPStmt* stmt);
1255 void fill(const cJSON*& fieldJson, UnaryOPStmt* stmt);
1256 void fill(const cJSON*& fieldJson, BranchStmt* stmt);
1257 void fill(const cJSON*& fieldJson, TDForkPE* stmt);
1258 void fill(const cJSON*& fieldJson, TDJoinPE* stmt);
1259
1260 void fill(const cJSON*& fieldJson, MemObj* memObj);
1261 void fill(const cJSON*& fieldJson, StInfo* stInfo);
1262 // ICFG
1263 void virtFill(const cJSON*& fieldJson, ICFGNode* node);
1264 void fill(const cJSON*& fieldJson, ICFGNode* node);
1265 void fill(const cJSON*& fieldJson, GlobalICFGNode* node);
1266 void fill(const cJSON*& fieldJson, IntraICFGNode* node);
1267 void fill(const cJSON*& fieldJson, InterICFGNode* node);
1268 void fill(const cJSON*& fieldJson, FunEntryICFGNode* node);
1269 void fill(const cJSON*& fieldJson, FunExitICFGNode* node);
1270 void fill(const cJSON*& fieldJson, CallICFGNode* node);
1271 void fill(const cJSON*& fieldJson, RetICFGNode* node);
1272
1273 void virtFill(const cJSON*& fieldJson, ICFGEdge* node);
1274 void fill(const cJSON*& fieldJson, ICFGEdge* edge);
1275 void fill(const cJSON*& fieldJson, IntraCFGEdge* edge);
1276 void fill(const cJSON*& fieldJson, CallCFGEdge* edge);
1277 void fill(const cJSON*& fieldJson, RetCFGEdge* edge);
1278
1279 void fill(const cJSON*& fieldJson, SVFLoop* loop);
1280 // CHGraph
1281 void virtFill(const cJSON*& fieldJson, CHNode* node);
1282 void virtFill(const cJSON*& fieldJson, CHEdge* edge);
1283
1284 // SVFModule
1285 void virtFill(const cJSON*& fieldJson, SVFValue* value);
1286 void fill(const cJSON*& fieldJson, SVFValue* value);
1287 void fill(const cJSON*& fieldJson, SVFFunction* value);
1288 void fill(const cJSON*& fieldJson, SVFBasicBlock* value);
1289 void fill(const cJSON*& fieldJson, SVFInstruction* value);
1290 void fill(const cJSON*& fieldJson, SVFCallInst* value);
1291 void fill(const cJSON*& fieldJson, SVFConstant* value);
1292 void fill(const cJSON*& fieldJson, SVFGlobalValue* value);
1293 void fill(const cJSON*& fieldJson, SVFArgument* value);
1294 void fill(const cJSON*& fieldJson, SVFConstantData* value);
1295 void fill(const cJSON*& fieldJson, SVFConstantInt* value);
1296 void fill(const cJSON*& fieldJson, SVFConstantFP* value);
1297 void fill(const cJSON*& fieldJson, SVFConstantNullPtr* value);
1298 void fill(const cJSON*& fieldJson, SVFBlackHoleValue* value);
1299 void fill(const cJSON*& fieldJson, SVFOtherValue* value);
1300 void fill(const cJSON*& fieldJson, SVFMetadataAsValue* value);
1301
1302 void virtFill(const cJSON*& fieldJson, SVFType* type);
1303 void fill(const cJSON*& fieldJson, SVFType* type);
1304 void fill(const cJSON*& fieldJson, SVFPointerType* type);
1305 void fill(const cJSON*& fieldJson, SVFIntegerType* type);
1306 void fill(const cJSON*& fieldJson, SVFFunctionType* type);
1307 void fill(const cJSON*& fieldJson, SVFStructType* type);
1308 void fill(const cJSON*& fieldJson, SVFArrayType* type);
1309 void fill(const cJSON*& fieldJson, SVFOtherType* type);
1310
1311 template <typename NodeTy, typename EdgeTy>
1313 {
1314 // id and nodeKind have already been read.
1315 JSON_READ_FIELD_FWD(fieldJson, node, InEdges);
1316 JSON_READ_FIELD_FWD(fieldJson, node, OutEdges);
1317 }
1318
1319 template <typename NodeTy>
1321 {
1322 // edgeFlag has already been read.
1325 }
1326};
1327
1328} // namespace SVF
1329
1330#endif // !INCLUDE_SVFFILESYSTEM_H_
#define ABORT_IFNOT(condition, msg)
#define FIELD_NAME_ITEM(field)
#define jsonForEach(field, array)
#define JSON_READ_FIELD_FWD(json, objptr, field)
#define CHECK_JSON_KEY(obj)
#define JSON_WRITE_FIELD(root, objptr, field)
#define KIND_BASE(B, KindGetter)
set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) add_llvm_executable(wpa wpa.cpp) target_link_libraries(wpa PUBLIC $
Definition CMakeLists.txt:1
newitem type
Definition cJSON.cpp:2739
cJSON * n
Definition cJSON.cpp:2558
cJSON_Delete(null)
const char *const name
Definition cJSON.h:264
const char *const const double number
Definition cJSON.h:268
int index
Definition cJSON.h:170
cJSON * item
Definition cJSON.h:222
Common base for class hierarchy graph. Only implements what PointerAnalysis needs.
Definition CHG.h:51
EdgeTy * getEdgePtr(unsigned id) const
const cJSON * graphFieldJson
void createObjs(const cJSON *graphJson, NodeCreator nodeCreator, EdgeCreator edgeCreator)
ReaderIDToObjMap< NodeTy > idToNodeMap
void saveToGenericGraph(GenericGraph< NodeTy, EdgeTy > *graph) const
ReaderPtrPool< EdgeTy > edgePool
NodeTy * getNodePtr(unsigned id) const
const cJSON * getFieldJson() const
void fillObjs(NodeFiller nodeFiller, EdgeFiller edgeFiller)
GenericGraph< NodeType, EdgeType > GraphType
size_t getEdgeID(const EdgeType *edge)
WriterPtrPool< EdgeType > edgePool
GenericGraphWriter(const GraphType *graph)
u32_t edgeNum
total num of node
u32_t nodeNum
total num of edge
IDToNodeMapTy IDToNodeMap
node map
ReaderPtrPool< SVFLoop > svfLoopPool
SVFLoop * getSVFLoopPtr(size_t id) const
void fillObjs(NodeFiller nodeFiller, EdgeFiller edgeFiller, LoopFiller loopFiller)
void createObjs(const cJSON *icfgJson, NodeCreator nodeCreator, EdgeCreator edgeCreator, SVFLoopCreator svfLoopCreator)
WriterPtrPool< SVFLoop > svfLoopPool
size_t getSvfLoopID(const SVFLoop *loop)
Keeps a map from IDs to T objects, such as XXNode.
T * getPtr(unsigned id) const
void saveToIDToObjMap(Map &idToObjMap) const
void fillObjs(FillFunc fillFunc)
OrderedMap< unsigned, std::pair< const cJSON *, T * > > IDToPairMapTy
void createObjs(const cJSON *idObjArrayJson, IdObjCreator idObjCreator)
idObjcreator : (const cJSON*) -> (id, T*) with id set
Reverse of WriterPtrPool where T is object type without ID field.
std::vector< T * > ptrPool
std::vector< const cJSON * > jsonArray
void saveToSet(Set &set) const
T * getPtr(size_t id) const
size_t size() const
void reserve(size_t size)
void fillObjs(FillFunc fillFunc)
void createObjs(const cJSON *objArrayJson, Creator creator)
IRGraphReader irGraphReader
SVFModuleReader svfModuleReader
static CHNode * createCHNode(NodeID id, GNodeK kind)
static ICFGEdge * createICFGEdge(GEdgeKind kind)
void fill(const cJSON *&fieldJson, SVFVar *var)
void fill(const cJSON *&fieldJson, GenericNode< NodeTy, EdgeTy > *node)
GenericEdge< void >::GEdgeKind GEdgeKind
void readJson(const cJSON *obj, const T *&cptr)
Read a const pointer.
static void readJson(const cJSON *obj, bool &flag)
static ICFGNode * createICFGNode(NodeID id, GNodeK type)
static CHEdge * createCHEdge(GEdgeKind kind)
static SVFStmt * createPAGEdge(GEdgeKind kind)
void fill(const cJSON *&fieldJson, GenericEdge< NodeTy > *edge)
CHGraphReader chGraphReader
GenericEdge< void >::GEdgeFlag GEdgeFlag
void readJson(const cJSON *obj, SparseBitVector< ElementSize > &bv)
ICFGReader icfgReader
static s64_t applyEdgeMask(u64_t edgeFlag)
std::enable_if_t< SVFUtil::is_sequence_container_v< C > > readJson(const cJSON *obj, C &container)
static SVFIR * read(const std::string &path)
static auto createEdgeWithFlag(GEdgeFlag flag, EdgeCreator creator)
std::enable_if_t< SVFUtil::is_map_v< C > > readJson(const cJSON *obj, C &map)
SVFUtil::void_t< KindBaseT< T > > readJson(const cJSON *obj, T *&ptr)
Read a pointer of some child class of SVFType/SVFValue/SVFVar/SVFStmt/ICFGNode/ICFGEdge/CHNode/CHEdge...
const cJSON * createObjs(const cJSON *root)
void readJson(const cJSON *obj, std::pair< T1, T2 > &pair)
void readJson(const cJSON *obj, T(&array)[N])
static SVFVar * createPAGNode(NodeID id, GNodeK kind)
void virtFill(const cJSON *&fieldJson, SVFVar *var)
static void setEdgeFlag(GenericEdge< T > *edge, typename GenericEdge< T >::GEdgeFlag edgeFlag)
SymbolTableInfoReader symTableReader
std::enable_if_t< SVFUtil::is_set_v< C > > readJson(const cJSON *obj, C &set)
const char * numToStr(size_t n)
static void writeJsonToOstream(const SVFIR *svfir, std::ostream &os)
std::unique_ptr< char, decltype(&cJSON_free)> autoCStr
cJSON * toJson(const std::pair< T, U > &pair)
static void writeJsonToPath(const SVFIR *svfir, const std::string &path)
const SVFIR * svfIR
std::unique_ptr< cJSON, decltype(&cJSON_Delete)> autoJSON
bool jsonAddContentToObject(cJSON *obj, const char *name, const T &item)
cJSON * genericGraphToJson(const GenericGraph< NodeTy, EdgeTy > *graph, const std::vector< const EdgeTy * > &edgePool)
OrderedMap< size_t, std::string > numToStrMap
cJSON * genericNodeToJson(const GenericNode< NodeTy, EdgeTy > *node)
autoJSON generateJson()
Main logic to dump a SVFIR to a JSON object.
cJSON * toJson(const NodeIDAllocator *nodeIDAllocator)
IRGraphWriter irGraphWriter
SVFModuleWriter svfModuleWriter
cJSON * contentToJson(const SVFVar *var)
CHGraphWriter chgWriter
autoCStr generateJsonString()
cJSON * toJson(const T &container)
ICFGWriter icfgWriter
bool jsonAddJsonableToObject(cJSON *obj, const char *name, const T &item)
cJSON * virtToJson(const SVFType *type)
Parameter types of these functions are all pointers. When they are used as arguments of toJson(),...
cJSON * genericEdgeToJson(const GenericEdge< NodeTy > *edge)
SVFType * getSVFTypePtr(size_t id) const
ReaderPtrPool< SVFValue > svfValuePool
const cJSON * getFieldJson() const
StInfo * getStInfoPtr(size_t id) const
SVFValue * getSVFValuePtr(size_t id) const
const cJSON * svfModuleFieldJson
ReaderPtrPool< StInfo > stInfoPool
void createObjs(const cJSON *svfModuleJson, SVFTypeCreator typeCreator, SVFTypeFiller typeFiller, SVFValueCreator valueCreator, SVFValueFiller valueFiller, StInfoCreator stInfoCreator)
ReaderPtrPool< SVFType > svfTypePool
size_t getSVFValueID(const SVFValue *value)
size_t sizeSVFValuePool() const
WriterPtrPool< SVFValue > svfValuePool
size_t getStInfoID(const StInfo *stInfo)
size_t getSVFTypeID(const SVFType *type)
WriterPtrPool< StInfo > stInfoPool
WriterPtrPool< SVFType > svfTypePool
const SVFValue * getSVFValuePtr(size_t id) const
void set(unsigned Idx)
ReaderIDToObjMap< MemObj > memObjMap
const cJSON * getFieldJson() const
void createObjs(const cJSON *symTabJson, MemObjCreator memObjCreator)
MemObj * getMemObjPtr(unsigned id) const
Bookkeeping class to keep track of the IDs of objects that doesn't have any ID. E....
const T * getPtr(size_t id) const
const std::vector< const T * > & getPool() const
size_t getID(const T *ptr)
std::vector< const T * > ptrPool
void saveID(const T *ptr)
Map< const T *, size_t > ptrToId
void reserve(size_t size)
size_t size() const
typename make_void< Ts... >::type void_t
Definition SVFUtil.h:457
for isBitcode
Definition BasicTypes.h:68
bool jsonAddNumberToObject(cJSON *obj, const char *name, double number)
Helper function to write a number to a JSON object.
cJSON * jsonCreateNullId()
double jsonGetNumber(const cJSON *item)
cJSON * jsonCreateNumber(double num)
bool jsonKeyEquals(const cJSON *item, const char *key)
bool jsonIsNumber(const cJSON *item)
bool jsonIsNullId(const cJSON *item)
unsigned long long u64_t
Definition GeneralType.h:48
u32_t NodeID
Definition GeneralType.h:55
bool jsonAddPairToMap(cJSON *obj, cJSON *key, cJSON *value)
bool jsonIsMap(const cJSON *item)
cJSON * jsonCreateBool(bool flag)
bool jsonIsArray(const cJSON *item)
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
signed s32_t
Definition GeneralType.h:47
bool jsonAddItemToArray(cJSON *array, cJSON *item)
bool jsonAddStringToObject(cJSON *obj, const char *name, const char *str)
std::pair< const cJSON *, const cJSON * > jsonUnpackPair(const cJSON *item)
bool jsonIsObject(const cJSON *item)
cJSON * jsonCreateObject()
bool jsonAddItemToObject(cJSON *obj, const char *name, cJSON *item)
unsigned u32_t
Definition GeneralType.h:46
signed long long s64_t
Definition GeneralType.h:49
bool jsonIsBool(const cJSON *item)
cJSON * jsonCreateString(const char *str)
bool jsonIsString(const cJSON *item)
typename KindBaseHelper< T >::type KindBaseT
cJSON * jsonCreateIndex(size_t index)
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition GeneralType.h:96
cJSON * jsonCreateArray()
Type trait to get base type. Helper struct to detect inheritance from Node/Edge.
Definition cJSON.h:104
struct cJSON * child
Definition cJSON.h:109
struct cJSON * next
Definition cJSON.h:106