IDA C++ SDK 9.2
Loading...
Searching...
No Matches
parsejson.hpp
Go to the documentation of this file.
1/*
2 * Interactive disassembler (IDA).
3 * Copyright (c) 1990-2025 Hex-Rays
4 * ALL RIGHTS RESERVED.
5 *
6 */
7
8#ifndef PARSEJSON_HPP
9#define PARSEJSON_HPP
10
17#include <lex.hpp>
18
19//---------------------------------------------------------------------------
31
32//---------------------------------------------------------------------------
33struct jobj_t;
34struct jarr_t;
35
36#define DECLARE_JVALUE_HELPERS(decl) \
37 decl void ida_export jvalue_t_clear(jvalue_t *); \
38 decl void ida_export jvalue_t_copy(jvalue_t *, const jvalue_t &);
39
40
41struct jvalue_t;
43
44//-------------------------------------------------------------------------
45struct jvalue_t
46{
47 jvalue_t() : _type(JT_UNKNOWN), _num(0) {}
48 jvalue_t(const jvalue_t &o) : _type(JT_UNKNOWN) { jvalue_t_copy(this, o); }
49 ~jvalue_t() { clear(); }
50
51 void clear() { jvalue_t_clear(this); }
52
53 jvalue_t &operator=(const jvalue_t &o) { jvalue_t_copy(this, o); return *this; }
54
55 jtype_t type() const { return _type; }
56 int64 num() const { QASSERT(1277, _type == JT_NUM); return _num; }
57 const char *str() const { QASSERT(1278, _type == JT_STR); return _str->c_str(); }
58 const qstring &qstr() const { QASSERT(1623, _type == JT_STR); return *_str; }
59 const jobj_t &obj() const { QASSERT(1279, _type == JT_OBJ); return *_obj; }
60 const jarr_t &arr() const { QASSERT(1280, _type == JT_ARR); return *_arr; }
61 bool vbool() const { QASSERT(1281, _type == JT_BOOL); return _bool; }
62 double vdouble() const { QASSERT(2928, _type == JT_DBL); return _double; }
63 jobj_t &obj() { QASSERT(1282, _type == JT_OBJ); return *_obj; }
64 jarr_t &arr() { QASSERT(1283, _type == JT_ARR); return *_arr; }
65
66 bool is_null() const { QASSERT(2929, _type == JT_NULL); return true; }
67
68 //lint -sem(jvalue_t::set_str, custodial(1)) function takes ownership of its argument
69 //lint -sem(jvalue_t::set_obj, custodial(1)) function takes ownership of its argument
70 //lint -sem(jvalue_t::set_arr, custodial(1)) function takes ownership of its argument
71 void set_num(int64 i) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_NUM; _num = i; }
72 void set_double(double dbl) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_DBL; _double = dbl; }
73 void set_str(const char *s) { set_str(new qstring(s)); }
74 void set_str(qstring *s) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_STR; _str = s; }
75 void set_obj(jobj_t *o) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_OBJ; _obj = o; }
76 void set_arr(jarr_t *a) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_ARR; _arr = a; }
77 void set_bool(bool b) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_BOOL; _bool = b; }
78 void set_null() { if ( _type != JT_UNKNOWN ) clear(); _type = JT_NULL; }
79
80 jobj_t *extract_obj() { QASSERT(1624, _type == JT_OBJ); jobj_t *o = _obj; _obj = nullptr; _type = JT_UNKNOWN; return o; }
81 jarr_t *extract_arr() { QASSERT(1625, _type == JT_ARR); jarr_t *a = _arr; _arr = nullptr; _type = JT_UNKNOWN; return a; }
82
83 void swap(jvalue_t &r)
84 {
85 qswap(_type, r._type);
86 qswap(_str, r._str);
87 }
88
89private:
91
92 jtype_t _type;
93
94 union
95 {
96 int64 _num;
97 double _double;
98 qstring *_str;
99 jobj_t *_obj;
100 jarr_t *_arr;
101 bool _bool;
102 };
103};
106
107//---------------------------------------------------------------------------
108struct kvp_t
109{
111 jvalue_t value;
112};
114
115//-------------------------------------------------------------------------
116struct jobj_t : public qvector<kvp_t>
117{
118 bool has_value(const char *k) const { return get_value(k) != nullptr; }
119 jvalue_t *get_value(const char *k, jtype_t t=JT_UNKNOWN)
120 {
121 jvalue_t *v = nullptr;
122 for ( size_t i = 0, _n = size(); i < _n; ++i )
123 {
124 if ( at(i).key == k )
125 {
126 if ( t == JT_UNKNOWN || at(i).value.type() == t )
127 v = &at(i).value;
128 break;
129 }
130 }
131 return v;
132 }
133
134 const jvalue_t *get_value(const char *k, jtype_t t=JT_UNKNOWN) const
135 {
136 return ((jobj_t *) this)->get_value(k, t);
137 }
138
139 const jvalue_t *get_value_or_fail(const char *k, jtype_t t=JT_UNKNOWN) const
140 {
141 const jvalue_t *v = get_value(k, t);
142 QASSERT(1289, v != nullptr);
143 return v;
144 }
145
146 jvalue_t *get_value_or_new(const char *key)
147 {
148 jvalue_t *v = get_value(key);
149 if ( v == nullptr )
150 {
151 kvp_t &kvp = push_back();
152 kvp.key = key;
153 v = &kvp.value;
154 }
155 return v;
156 }
157
158 bool del_value(const char *k)
159 {
160 for ( size_t i = 0, _n = size(); i < _n; ++i )
161 {
162 if ( at(i).key == k )
163 {
164 erase(begin() + i);
165 return true;
166 }
167 }
168 return false;
169 }
170
171 int64 get_num(const char *k) const { return get_value_or_fail(k)->num(); }
172 bool get_bool(const char *k) const { return get_value_or_fail(k)->vbool(); }
173 double get_double(const char *k) const { return get_value_or_fail(k)->vdouble(); }
174 const char *get_str(const char *k) const { return get_value_or_fail(k)->str(); }
175 const jobj_t &get_obj(const char *k) const { return get_value_or_fail(k)->obj(); }
176 const jarr_t &get_arr(const char *k) const { return get_value_or_fail(k)->arr(); }
177
178#define DEFINE_FLAG_GETTER(Type, JType, GetExpr) \
179 bool get(Type *out, const char *k) const \
180 { \
181 const jvalue_t *v = get_value(k, JType); \
182 bool ok = v != nullptr; \
183 if ( ok ) \
184 *out = GetExpr; \
185 return ok; \
186 }
187#define DEFINE_DFLT_GETTER(Type, JType, GetExpr) \
188 Type get(const char *k, Type dflt) const \
189 { \
190 const jvalue_t *v = get_value(k, JType); \
191 return v != nullptr ? GetExpr : dflt; \
192 }
193#define DEFINE_SETTER(Type, SetExpr) \
194 void put(const char *key, Type value) \
195 { \
196 jvalue_t *v = get_value_or_new(key); \
197 SetExpr; \
198 }
199#define DEFINE_ACCESSORS(Type, ConstType, JType, GetExpr, SetExpr) \
200 DEFINE_FLAG_GETTER(ConstType, JType, GetExpr) \
201 DEFINE_DFLT_GETTER(ConstType, JType, GetExpr) \
202 DEFINE_SETTER(Type, SetExpr)
203
204 DEFINE_ACCESSORS(int, int, JT_NUM, v->num(), v->set_num(value));
205 DEFINE_ACCESSORS(int64, int64, JT_NUM, v->num(), v->set_num(value));
206 DEFINE_ACCESSORS(double, double, JT_DBL, v->vdouble(), v->set_double(value));
207 DEFINE_ACCESSORS(bool, bool, JT_BOOL, v->vbool(), v->set_bool(value));
208 //lint -sem(jobj_t::put(const char *, struct jarr_t *), custodial(2)) function takes ownership of its argument
209 DEFINE_ACCESSORS(jarr_t *, const jarr_t *, JT_ARR, &v->arr(), v->set_arr(value));
210 //lint -sem(jobj_t::put(const char *, struct jobj_t *), custodial(2)) function takes ownership of its argument
211 DEFINE_ACCESSORS(jobj_t *, const jobj_t *, JT_OBJ, &v->obj(), v->set_obj(value));
212 DEFINE_ACCESSORS(const char *, const char *, JT_STR, v->str(), v->set_str(new qstring(value)));
213#undef DEFINE_ACCESSORS
214#undef DEFINE_SETTER
215#undef DEFINE_DFLT_GETTER
216#undef DEFINE_FLAG_GETTER
217
218 bool get(qstring *out, const char *k) const
219 {
220 const jvalue_t *v = get_value(k, JT_STR);
221 bool ok = v != nullptr;
222 if ( ok )
223 *out = v->qstr();
224 return ok;
225 }
226
227 const qstring &get(const char *k, const qstring &dflt) const
228 {
229 const jvalue_t *v = get_value(k, JT_STR);
230 return v != nullptr ? v->qstr() : dflt;
231 }
232
233 void put(const char *key, const qstring &value)
234 {
235 jvalue_t *v = get_value_or_new(key);
236 v->set_str(new qstring(value));
237 }
238
239 void put(const char *key, const jobj_t &value)
240 {
241 jvalue_t *v = get_value_or_new(key);
242 v->set_obj(new jobj_t(value));
243 }
244};
246
247//---------------------------------------------------------------------------
248struct jarr_t
249{
251
253 {
254 size_t cnt = 0;
255 for ( size_t i = 0, n = values.size(); i < n; ++i )
256 if ( values[i].type() == t )
257 ++cnt;
258 return cnt;
259 }
260
262 {
263 return count_items_with_type(t) == values.size();
264 }
265};
267
268//---------------------------------------------------------------------------
269// Note: If 'ungot_tokens' is not nullptr, its contents will be used before fetching tokens from the lexer
270idaman THREAD_SAFE error_t ida_export parse_json(jvalue_t *out, lexer_t *lx, tokenstack_t *ungot_tokens = nullptr);
271idaman THREAD_SAFE error_t ida_export parse_json_string(jvalue_t *out, const char *s, qstring *errbuf = nullptr, const char *file_path = nullptr);
272idaman THREAD_SAFE error_t ida_export parse_json_file(jvalue_t *out, const char *path, qstring *errbuf = nullptr);
273
274//-------------------------------------------------------------------------
275#define SJF_PRETTY 0x1
276#define SJF_SORTED_KEYS 0x2
277idaman THREAD_SAFE bool ida_export serialize_json(
278 qstring *out,
279 const jvalue_t &v,
280 uint32 flags=0);
281
282inline THREAD_SAFE bool serialize_json(
283 qstring *out,
284 const jobj_t *o,
285 uint32 flags=0)
286{
287 jvalue_t v;
288 v.set_obj((jobj_t *) o);
289 bool rc = serialize_json(out, v, flags);
290 v.extract_obj();
291 return rc;
292}
293
294#endif // PARSEJSON_HPP
Reimplementation of vector class from STL.
Definition pro.h:2250
iterator erase(iterator it)
Definition pro.h:2678
const kvp_t & at(size_t _idx) const
Definition pro.h:2427
qvector(void)
Definition pro.h:2328
iterator begin(void)
Definition pro.h:2609
void push_back(kvp_t &&x)
Definition pro.h:2361
size_t size(void) const
Definition pro.h:2423
idaman size_t n
Definition pro.h:997
const tinfo_t & type
Definition hexrays.hpp:7301
bool ok
Definition kernwin.hpp:7006
ssize_t rc
Definition kernwin.hpp:7101
Tools for parsing C-like input.
qstack< token_t > tokenstack_t
see get_token(), unget_token()
Definition lex.hpp:329
__int64 int64
Definition llong.hpp:14
jtype_t
Definition parsejson.hpp:21
@ JT_NUM
Definition parsejson.hpp:23
@ JT_DBL
Definition parsejson.hpp:29
@ JT_OBJ
Definition parsejson.hpp:25
@ JT_NULL
Definition parsejson.hpp:28
@ JT_BOOL
Definition parsejson.hpp:27
@ JT_ARR
Definition parsejson.hpp:26
@ JT_UNKNOWN
Definition parsejson.hpp:22
@ JT_STR
Definition parsejson.hpp:24
idaman THREAD_SAFE error_t ida_export parse_json_string(jvalue_t *out, const char *s, qstring *errbuf=nullptr, const char *file_path=nullptr)
idaman THREAD_SAFE bool ida_export serialize_json(qstring *out, const jvalue_t &v, uint32 flags=0)
idaman THREAD_SAFE error_t ida_export parse_json(jvalue_t *out, lexer_t *lx, tokenstack_t *ungot_tokens=nullptr)
DECLARE_TYPE_AS_MOVABLE(jvalue_t)
idaman THREAD_SAFE error_t ida_export parse_json_file(jvalue_t *out, const char *path, qstring *errbuf=nullptr)
qvector< jvalue_t > jvalues_t
Definition parsejson.hpp:105
DECLARE_JVALUE_HELPERS(idaman) struct jvalue_t
Definition parsejson.hpp:42
idaman size_t const char time_t t
Definition pro.h:602
THREAD_SAFE void * extract_obj(T &v, void *destbuf, size_t destsize)
Definition pro.h:1996
unsigned int uint32
unsigned 32 bit value
Definition pro.h:348
THREAD_SAFE void qswap(T &a, T &b)
Swap 2 objects of the same type using memory copies.
Definition pro.h:1715
int error_t
Error code (errno)
Definition pro.h:458
_qstring< char > qstring
regular string
Definition pro.h:3694
Definition parsejson.hpp:249
bool is_homogeneous(jtype_t t) const
Definition parsejson.hpp:261
size_t count_items_with_type(jtype_t t) const
Definition parsejson.hpp:252
jvalues_t values
Definition parsejson.hpp:250
Definition parsejson.hpp:117
DEFINE_ACCESSORS(double, double, JT_DBL, v->vdouble(), v->set_double(value))
DEFINE_ACCESSORS(bool, bool, JT_BOOL, v->vbool(), v->set_bool(value))
jvalue_t * get_value(const char *k, jtype_t t=JT_UNKNOWN)
Definition parsejson.hpp:119
const jarr_t & get_arr(const char *k) const
Definition parsejson.hpp:176
const jvalue_t * get_value_or_fail(const char *k, jtype_t t=JT_UNKNOWN) const
Definition parsejson.hpp:139
const qstring & get(const char *k, const qstring &dflt) const
Definition parsejson.hpp:227
int64 get_num(const char *k) const
Definition parsejson.hpp:171
DEFINE_ACCESSORS(jarr_t *, const jarr_t *, JT_ARR, &v->arr(), v->set_arr(value))
DEFINE_ACCESSORS(jobj_t *, const jobj_t *, JT_OBJ, &v->obj(), v->set_obj(value))
void put(const char *key, const qstring &value)
Definition parsejson.hpp:233
DEFINE_ACCESSORS(int, int, JT_NUM, v->num(), v->set_num(value))
bool del_value(const char *k)
Definition parsejson.hpp:158
DEFINE_ACCESSORS(const char *, const char *, JT_STR, v->str(), v->set_str(new qstring(value)))
double get_double(const char *k) const
Definition parsejson.hpp:173
jvalue_t * get_value_or_new(const char *key)
Definition parsejson.hpp:146
bool get(qstring *out, const char *k) const
Definition parsejson.hpp:218
bool has_value(const char *k) const
Definition parsejson.hpp:118
void put(const char *key, const jobj_t &value)
Definition parsejson.hpp:239
const jobj_t & get_obj(const char *k) const
Definition parsejson.hpp:175
const char * get_str(const char *k) const
Definition parsejson.hpp:174
bool get_bool(const char *k) const
Definition parsejson.hpp:172
const jvalue_t * get_value(const char *k, jtype_t t=JT_UNKNOWN) const
Definition parsejson.hpp:134
DEFINE_ACCESSORS(int64, int64, JT_NUM, v->num(), v->set_num(value))
Definition parsejson.hpp:109
qstring key
Definition parsejson.hpp:110
jvalue_t value
Definition parsejson.hpp:111