update
This commit is contained in:
233
idasdk75/include/parsejson.hpp
Normal file
233
idasdk75/include/parsejson.hpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2020 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PARSEJSON_HPP
|
||||
#define PARSEJSON_HPP
|
||||
|
||||
/*! \file parsejson.hpp
|
||||
|
||||
\brief Tools for parsing JSON-formatted input
|
||||
|
||||
See also lex.hpp/parse.hpp for finer-grained functions & documentation.
|
||||
*/
|
||||
#include <lex.hpp>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
enum jtype_t
|
||||
{
|
||||
JT_UNKNOWN = 0,
|
||||
JT_NUM,
|
||||
JT_STR,
|
||||
JT_OBJ,
|
||||
JT_ARR,
|
||||
JT_BOOL,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
struct jobj_t;
|
||||
struct jarr_t;
|
||||
|
||||
#define DECLARE_JVALUE_HELPERS(decl) \
|
||||
decl void ida_export jvalue_t_clear(jvalue_t *); \
|
||||
decl void ida_export jvalue_t_copy(jvalue_t *, const jvalue_t &);
|
||||
|
||||
|
||||
struct jvalue_t;
|
||||
DECLARE_JVALUE_HELPERS(idaman)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct jvalue_t
|
||||
{
|
||||
jvalue_t() : _type(JT_UNKNOWN), _num(0) {}
|
||||
jvalue_t(const jvalue_t &o) : _type(JT_UNKNOWN) { jvalue_t_copy(this, o); }
|
||||
~jvalue_t() { clear(); }
|
||||
|
||||
void clear() { jvalue_t_clear(this); }
|
||||
|
||||
jvalue_t &operator=(const jvalue_t &o) { jvalue_t_copy(this, o); return *this; }
|
||||
|
||||
jtype_t type() const { return _type; }
|
||||
int64 num() const { QASSERT(1277, _type == JT_NUM); return _num; }
|
||||
const char *str() const { QASSERT(1278, _type == JT_STR); return _str->c_str(); }
|
||||
const qstring &qstr() const { QASSERT(1623, _type == JT_STR); return *_str; }
|
||||
const jobj_t &obj() const { QASSERT(1279, _type == JT_OBJ); return *_obj; }
|
||||
const jarr_t &arr() const { QASSERT(1280, _type == JT_ARR); return *_arr; }
|
||||
bool vbool() const { QASSERT(1281, _type == JT_BOOL); return _bool; }
|
||||
jobj_t &obj() { QASSERT(1282, _type == JT_OBJ); return *_obj; }
|
||||
jarr_t &arr() { QASSERT(1283, _type == JT_ARR); return *_arr; }
|
||||
|
||||
//lint -sem(jvalue_t::set_str, custodial(1)) function takes ownership of its argument
|
||||
//lint -sem(jvalue_t::set_obj, custodial(1)) function takes ownership of its argument
|
||||
//lint -sem(jvalue_t::set_arr, custodial(1)) function takes ownership of its argument
|
||||
void set_num(int64 i) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_NUM; _num = i; }
|
||||
void set_str(qstring *s) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_STR; _str = s; }
|
||||
void set_obj(jobj_t *o) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_OBJ; _obj = o; }
|
||||
void set_arr(jarr_t *a) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_ARR; _arr = a; }
|
||||
void set_bool(bool b) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_BOOL; _bool = b; }
|
||||
|
||||
jobj_t *extract_obj() { QASSERT(1624, _type == JT_OBJ); jobj_t *o = _obj; _obj = NULL; _type = JT_UNKNOWN; return o; }
|
||||
jarr_t *extract_arr() { QASSERT(1625, _type == JT_ARR); jarr_t *a = _arr; _arr = NULL; _type = JT_UNKNOWN; return a; }
|
||||
|
||||
private:
|
||||
DECLARE_JVALUE_HELPERS(friend)
|
||||
|
||||
jtype_t _type;
|
||||
|
||||
union
|
||||
{
|
||||
int64 _num;
|
||||
qstring *_str;
|
||||
jobj_t *_obj;
|
||||
jarr_t *_arr;
|
||||
bool _bool;
|
||||
};
|
||||
};
|
||||
DECLARE_TYPE_AS_MOVABLE(jvalue_t);
|
||||
typedef qvector<jvalue_t> jvalues_t;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
struct kvp_t
|
||||
{
|
||||
qstring key;
|
||||
jvalue_t value;
|
||||
};
|
||||
DECLARE_TYPE_AS_MOVABLE(kvp_t);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct jobj_t : public qvector<kvp_t>
|
||||
{
|
||||
bool has_value(const char *k) const { return get_value(k) != NULL; }
|
||||
jvalue_t *get_value(const char *k, jtype_t t=JT_UNKNOWN)
|
||||
{
|
||||
jvalue_t *v = NULL;
|
||||
for ( size_t i = 0, _n = size(); i < _n; ++i )
|
||||
{
|
||||
if ( at(i).key == k )
|
||||
{
|
||||
if ( t == JT_UNKNOWN || at(i).value.type() == t )
|
||||
v = &at(i).value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
const jvalue_t *get_value(const char *k, jtype_t t=JT_UNKNOWN) const
|
||||
{
|
||||
return ((jobj_t *) this)->get_value(k, t);
|
||||
}
|
||||
|
||||
const jvalue_t *get_value_or_fail(const char *k, jtype_t t=JT_UNKNOWN) const
|
||||
{
|
||||
const jvalue_t *v = get_value(k, t);
|
||||
QASSERT(1289, v != NULL);
|
||||
return v;
|
||||
}
|
||||
|
||||
jvalue_t *get_value_or_new(const char *key)
|
||||
{
|
||||
jvalue_t *v = get_value(key);
|
||||
if ( v == NULL )
|
||||
{
|
||||
kvp_t &kvp = push_back();
|
||||
kvp.key = key;
|
||||
v = &kvp.value;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int64 get_num(const char *k) const { return get_value_or_fail(k)->num(); }
|
||||
bool get_bool(const char *k) const { return get_value_or_fail(k)->vbool(); }
|
||||
const char *get_str(const char *k) const { return get_value_or_fail(k)->str(); }
|
||||
const jobj_t &get_obj(const char *k) const { return get_value_or_fail(k)->obj(); }
|
||||
const jarr_t &get_arr(const char *k) const { return get_value_or_fail(k)->arr(); }
|
||||
|
||||
#define DEFINE_FLAG_GETTER(Type, JType, GetExpr) \
|
||||
bool get(Type *out, const char *k) const \
|
||||
{ \
|
||||
const jvalue_t *v = get_value(k, JType); \
|
||||
bool ok = v != NULL; \
|
||||
if ( ok ) \
|
||||
*out = GetExpr; \
|
||||
return ok; \
|
||||
}
|
||||
#define DEFINE_DFLT_GETTER(Type, JType, GetExpr) \
|
||||
Type get(const char *k, Type dflt) const \
|
||||
{ \
|
||||
const jvalue_t *v = get_value(k, JType); \
|
||||
return v != NULL ? GetExpr : dflt; \
|
||||
}
|
||||
#define DEFINE_SETTER(Type, SetExpr) \
|
||||
void put(const char *key, Type value) \
|
||||
{ \
|
||||
jvalue_t *v = get_value_or_new(key); \
|
||||
SetExpr; \
|
||||
}
|
||||
#define DEFINE_ACCESSORS(Type, ConstType, JType, GetExpr, SetExpr) \
|
||||
DEFINE_FLAG_GETTER(ConstType, JType, GetExpr) \
|
||||
DEFINE_DFLT_GETTER(ConstType, JType, GetExpr) \
|
||||
DEFINE_SETTER(Type, SetExpr)
|
||||
|
||||
DEFINE_ACCESSORS(int, int, JT_NUM, v->num(), v->set_num(value));
|
||||
DEFINE_ACCESSORS(int64, int64, JT_NUM, v->num(), v->set_num(value));
|
||||
DEFINE_ACCESSORS(bool, bool, JT_BOOL, v->vbool(), v->set_bool(value));
|
||||
DEFINE_ACCESSORS(jarr_t *, const jarr_t *, JT_ARR, &v->arr(), v->set_arr(value)); // setter takes ownership
|
||||
DEFINE_ACCESSORS(jobj_t *, const jobj_t *, JT_OBJ, &v->obj(), v->set_obj(value)); // setter takes ownership
|
||||
DEFINE_ACCESSORS(const char *, const char *, JT_STR, v->str(), v->set_str(new qstring(value)));
|
||||
#undef DEFINE_ACCESSORS
|
||||
#undef DEFINE_SETTER
|
||||
#undef DEFINE_DFLT_GETTER
|
||||
#undef DEFINE_FLAG_GETTER
|
||||
};
|
||||
DECLARE_TYPE_AS_MOVABLE(jobj_t);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
struct jarr_t
|
||||
{
|
||||
jvalues_t values;
|
||||
|
||||
size_t count_items_with_type(jtype_t t) const
|
||||
{
|
||||
size_t cnt = 0;
|
||||
for ( size_t i = 0, n = values.size(); i < n; ++i )
|
||||
if ( values[i].type() == t )
|
||||
++cnt;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
bool is_homogeneous(jtype_t t) const
|
||||
{
|
||||
return count_items_with_type(t) == values.size();
|
||||
}
|
||||
};
|
||||
DECLARE_TYPE_AS_MOVABLE(jarr_t);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Note: If 'ungot_tokens' is not NULL, its contents will be used before fetching tokens from the lexer
|
||||
idaman THREAD_SAFE error_t ida_export parse_json(jvalue_t *out, lexer_t *lx, tokenstack_t *ungot_tokens = NULL);
|
||||
idaman THREAD_SAFE error_t ida_export parse_json_string(jvalue_t *out, const char *s);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
#define SJF_PRETTY 0x1
|
||||
idaman THREAD_SAFE bool ida_export serialize_json(
|
||||
qstring *out,
|
||||
const jvalue_t &v,
|
||||
uint32 flags=0);
|
||||
|
||||
inline THREAD_SAFE bool serialize_json(
|
||||
qstring *out,
|
||||
const jobj_t *o,
|
||||
uint32 flags=0)
|
||||
{
|
||||
jvalue_t v;
|
||||
v.set_obj((jobj_t *) o);
|
||||
bool rc = serialize_json(out, v, flags);
|
||||
v.extract_obj();
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif // PARSEJSON_HPP
|
||||
Reference in New Issue
Block a user