mirror of
https://github.com/opnsense/src.git
synced 2026-02-28 04:10:49 -05:00
765 lines
18 KiB
C++
765 lines
18 KiB
C++
//===-- StructuredData.h ----------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef liblldb_StructuredData_h_
|
|
#define liblldb_StructuredData_h_
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
#include <functional>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
// Other libraries and framework includes
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
// Project includes
|
|
#include "lldb/lldb-defines.h"
|
|
#include "lldb/Core/ConstString.h"
|
|
#include "lldb/Core/Stream.h"
|
|
|
|
namespace lldb_private {
|
|
|
|
//----------------------------------------------------------------------
|
|
/// @class StructuredData StructuredData.h "lldb/Core/StructuredData.h"
|
|
/// @brief A class which can hold structured data
|
|
///
|
|
/// The StructuredData class is designed to hold the data from a JSON
|
|
/// or plist style file -- a serialized data structure with dictionaries
|
|
/// (maps, hashes), arrays, and concrete values like integers, floating
|
|
/// point numbers, strings, booleans.
|
|
///
|
|
/// StructuredData does not presuppose any knowledge of the schema for
|
|
/// the data it is holding; it can parse JSON data, for instance, and
|
|
/// other parts of lldb can iterate through the parsed data set to find
|
|
/// keys and values that may be present.
|
|
//----------------------------------------------------------------------
|
|
|
|
class StructuredData
|
|
{
|
|
public:
|
|
class Object;
|
|
class Array;
|
|
class Integer;
|
|
class Float;
|
|
class Boolean;
|
|
class String;
|
|
class Dictionary;
|
|
class Generic;
|
|
|
|
typedef std::shared_ptr<Object> ObjectSP;
|
|
typedef std::shared_ptr<Array> ArraySP;
|
|
typedef std::shared_ptr<Integer> IntegerSP;
|
|
typedef std::shared_ptr<Float> FloatSP;
|
|
typedef std::shared_ptr<Boolean> BooleanSP;
|
|
typedef std::shared_ptr<String> StringSP;
|
|
typedef std::shared_ptr<Dictionary> DictionarySP;
|
|
typedef std::shared_ptr<Generic> GenericSP;
|
|
|
|
enum class Type
|
|
{
|
|
eTypeInvalid = -1,
|
|
eTypeNull = 0,
|
|
eTypeGeneric,
|
|
eTypeArray,
|
|
eTypeInteger,
|
|
eTypeFloat,
|
|
eTypeBoolean,
|
|
eTypeString,
|
|
eTypeDictionary
|
|
};
|
|
|
|
class Object :
|
|
public std::enable_shared_from_this<Object>
|
|
{
|
|
public:
|
|
|
|
Object (Type t = Type::eTypeInvalid) :
|
|
m_type (t)
|
|
{
|
|
}
|
|
|
|
virtual ~Object() = default;
|
|
|
|
virtual bool
|
|
IsValid() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual void
|
|
Clear ()
|
|
{
|
|
m_type = Type::eTypeInvalid;
|
|
}
|
|
|
|
Type
|
|
GetType () const
|
|
{
|
|
return m_type;
|
|
}
|
|
|
|
void
|
|
SetType (Type t)
|
|
{
|
|
m_type = t;
|
|
}
|
|
|
|
Array *
|
|
GetAsArray ()
|
|
{
|
|
return ((m_type == Type::eTypeArray) ? static_cast<Array *>(this) : nullptr);
|
|
}
|
|
|
|
Dictionary *
|
|
GetAsDictionary ()
|
|
{
|
|
return ((m_type == Type::eTypeDictionary) ? static_cast<Dictionary *>(this) : nullptr);
|
|
}
|
|
|
|
Integer *
|
|
GetAsInteger ()
|
|
{
|
|
return ((m_type == Type::eTypeInteger) ? static_cast<Integer *>(this) : nullptr);
|
|
}
|
|
|
|
uint64_t
|
|
GetIntegerValue (uint64_t fail_value = 0)
|
|
{
|
|
Integer *integer = GetAsInteger ();
|
|
return ((integer != nullptr) ? integer->GetValue() : fail_value);
|
|
}
|
|
|
|
Float *
|
|
GetAsFloat ()
|
|
{
|
|
return ((m_type == Type::eTypeFloat) ? static_cast<Float *>(this) : nullptr);
|
|
}
|
|
|
|
double
|
|
GetFloatValue (double fail_value = 0.0)
|
|
{
|
|
Float *f = GetAsFloat ();
|
|
return ((f != nullptr) ? f->GetValue() : fail_value);
|
|
}
|
|
|
|
Boolean *
|
|
GetAsBoolean ()
|
|
{
|
|
return ((m_type == Type::eTypeBoolean) ? static_cast<Boolean *>(this) : nullptr);
|
|
}
|
|
|
|
bool
|
|
GetBooleanValue (bool fail_value = false)
|
|
{
|
|
Boolean *b = GetAsBoolean ();
|
|
return ((b != nullptr) ? b->GetValue() : fail_value);
|
|
}
|
|
|
|
String *
|
|
GetAsString ()
|
|
{
|
|
return ((m_type == Type::eTypeString) ? static_cast<String *>(this) : nullptr);
|
|
}
|
|
|
|
std::string
|
|
GetStringValue(const char *fail_value = nullptr)
|
|
{
|
|
String *s = GetAsString ();
|
|
if (s)
|
|
return s->GetValue();
|
|
|
|
if (fail_value && fail_value[0])
|
|
return std::string(fail_value);
|
|
|
|
return std::string();
|
|
}
|
|
|
|
Generic *
|
|
GetAsGeneric()
|
|
{
|
|
return ((m_type == Type::eTypeGeneric) ? static_cast<Generic *>(this) : nullptr);
|
|
}
|
|
|
|
ObjectSP
|
|
GetObjectForDotSeparatedPath (llvm::StringRef path);
|
|
|
|
void DumpToStdout() const;
|
|
|
|
virtual void
|
|
Dump (Stream &s) const = 0;
|
|
|
|
private:
|
|
Type m_type;
|
|
};
|
|
|
|
class Array : public Object
|
|
{
|
|
public:
|
|
Array () :
|
|
Object (Type::eTypeArray)
|
|
{
|
|
}
|
|
|
|
~Array() override = default;
|
|
|
|
bool
|
|
ForEach (std::function <bool(Object* object)> const &foreach_callback) const
|
|
{
|
|
for (const auto &object_sp : m_items)
|
|
{
|
|
if (foreach_callback(object_sp.get()) == false)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
size_t
|
|
GetSize() const
|
|
{
|
|
return m_items.size();
|
|
}
|
|
|
|
ObjectSP
|
|
operator[](size_t idx)
|
|
{
|
|
if (idx < m_items.size())
|
|
return m_items[idx];
|
|
return ObjectSP();
|
|
}
|
|
|
|
ObjectSP
|
|
GetItemAtIndex(size_t idx) const
|
|
{
|
|
assert(idx < GetSize());
|
|
if (idx < m_items.size())
|
|
return m_items[idx];
|
|
return ObjectSP();
|
|
}
|
|
|
|
template <class IntType>
|
|
bool
|
|
GetItemAtIndexAsInteger(size_t idx, IntType &result) const
|
|
{
|
|
ObjectSP value_sp = GetItemAtIndex(idx);
|
|
if (value_sp.get())
|
|
{
|
|
if (auto int_value = value_sp->GetAsInteger())
|
|
{
|
|
result = static_cast<IntType>(int_value->GetValue());
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template <class IntType>
|
|
bool
|
|
GetItemAtIndexAsInteger(size_t idx, IntType &result, IntType default_val) const
|
|
{
|
|
bool success = GetItemAtIndexAsInteger(idx, result);
|
|
if (!success)
|
|
result = default_val;
|
|
return success;
|
|
}
|
|
|
|
bool
|
|
GetItemAtIndexAsString(size_t idx, std::string &result) const
|
|
{
|
|
ObjectSP value_sp = GetItemAtIndex(idx);
|
|
if (value_sp.get())
|
|
{
|
|
if (auto string_value = value_sp->GetAsString())
|
|
{
|
|
result = string_value->GetValue();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
GetItemAtIndexAsString(size_t idx, std::string &result, const std::string &default_val) const
|
|
{
|
|
bool success = GetItemAtIndexAsString(idx, result);
|
|
if (!success)
|
|
result = default_val;
|
|
return success;
|
|
}
|
|
|
|
bool
|
|
GetItemAtIndexAsString(size_t idx, ConstString &result) const
|
|
{
|
|
ObjectSP value_sp = GetItemAtIndex(idx);
|
|
if (value_sp.get()) {
|
|
if (auto string_value = value_sp->GetAsString())
|
|
{
|
|
result = ConstString(string_value->GetValue());
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
GetItemAtIndexAsString(size_t idx, ConstString &result, const char *default_val) const
|
|
{
|
|
bool success = GetItemAtIndexAsString(idx, result);
|
|
if (!success)
|
|
result.SetCString(default_val);
|
|
return success;
|
|
}
|
|
|
|
bool
|
|
GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const
|
|
{
|
|
result = nullptr;
|
|
ObjectSP value_sp = GetItemAtIndex(idx);
|
|
if (value_sp.get())
|
|
{
|
|
result = value_sp->GetAsDictionary();
|
|
return (result != nullptr);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
GetItemAtIndexAsArray(size_t idx, Array *&result) const
|
|
{
|
|
result = nullptr;
|
|
ObjectSP value_sp = GetItemAtIndex(idx);
|
|
if (value_sp.get())
|
|
{
|
|
result = value_sp->GetAsArray();
|
|
return (result != nullptr);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
Push(ObjectSP item)
|
|
{
|
|
m_items.push_back(item);
|
|
}
|
|
|
|
void
|
|
AddItem(ObjectSP item)
|
|
{
|
|
m_items.push_back(item);
|
|
}
|
|
|
|
void Dump(Stream &s) const override;
|
|
|
|
protected:
|
|
typedef std::vector<ObjectSP> collection;
|
|
collection m_items;
|
|
};
|
|
|
|
class Integer : public Object
|
|
{
|
|
public:
|
|
Integer (uint64_t i = 0) :
|
|
Object (Type::eTypeInteger),
|
|
m_value (i)
|
|
{
|
|
}
|
|
|
|
~Integer() override = default;
|
|
|
|
void
|
|
SetValue (uint64_t value)
|
|
{
|
|
m_value = value;
|
|
}
|
|
|
|
uint64_t
|
|
GetValue ()
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
void Dump(Stream &s) const override;
|
|
|
|
protected:
|
|
uint64_t m_value;
|
|
};
|
|
|
|
class Float : public Object
|
|
{
|
|
public:
|
|
Float (double d = 0.0) :
|
|
Object (Type::eTypeFloat),
|
|
m_value (d)
|
|
{
|
|
}
|
|
|
|
~Float() override = default;
|
|
|
|
void
|
|
SetValue (double value)
|
|
{
|
|
m_value = value;
|
|
}
|
|
|
|
double
|
|
GetValue ()
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
void Dump(Stream &s) const override;
|
|
|
|
protected:
|
|
double m_value;
|
|
};
|
|
|
|
class Boolean : public Object
|
|
{
|
|
public:
|
|
Boolean (bool b = false) :
|
|
Object (Type::eTypeBoolean),
|
|
m_value (b)
|
|
{
|
|
}
|
|
|
|
~Boolean() override = default;
|
|
|
|
void
|
|
SetValue (bool value)
|
|
{
|
|
m_value = value;
|
|
}
|
|
|
|
bool
|
|
GetValue ()
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
void Dump(Stream &s) const override;
|
|
|
|
protected:
|
|
bool m_value;
|
|
};
|
|
|
|
class String : public Object
|
|
{
|
|
public:
|
|
String(const char *cstr = nullptr) :
|
|
Object (Type::eTypeString),
|
|
m_value ()
|
|
{
|
|
if (cstr)
|
|
m_value = cstr;
|
|
}
|
|
|
|
String (const std::string &s) :
|
|
Object (Type::eTypeString),
|
|
m_value (s)
|
|
{
|
|
}
|
|
|
|
String (const std::string &&s) :
|
|
Object (Type::eTypeString),
|
|
m_value (s)
|
|
{
|
|
}
|
|
|
|
void
|
|
SetValue (const std::string &string)
|
|
{
|
|
m_value = string;
|
|
}
|
|
|
|
const std::string &
|
|
GetValue ()
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
void Dump(Stream &s) const override;
|
|
|
|
protected:
|
|
std::string m_value;
|
|
};
|
|
|
|
class Dictionary : public Object
|
|
{
|
|
public:
|
|
|
|
Dictionary () :
|
|
Object (Type::eTypeDictionary),
|
|
m_dict ()
|
|
{
|
|
}
|
|
|
|
~Dictionary() override = default;
|
|
|
|
size_t
|
|
GetSize() const
|
|
{
|
|
return m_dict.size();
|
|
}
|
|
|
|
void
|
|
ForEach (std::function <bool(ConstString key, Object* object)> const &callback) const
|
|
{
|
|
for (const auto &pair : m_dict)
|
|
{
|
|
if (callback (pair.first, pair.second.get()) == false)
|
|
break;
|
|
}
|
|
}
|
|
|
|
ObjectSP
|
|
GetKeys() const
|
|
{
|
|
ObjectSP object_sp(new Array ());
|
|
Array *array = object_sp->GetAsArray();
|
|
collection::const_iterator iter;
|
|
for (iter = m_dict.begin(); iter != m_dict.end(); ++iter)
|
|
{
|
|
ObjectSP key_object_sp(new String());
|
|
key_object_sp->GetAsString()->SetValue(iter->first.AsCString());
|
|
array->Push(key_object_sp);
|
|
}
|
|
return object_sp;
|
|
}
|
|
|
|
ObjectSP
|
|
GetValueForKey(llvm::StringRef key) const
|
|
{
|
|
ObjectSP value_sp;
|
|
if (!key.empty())
|
|
{
|
|
ConstString key_cs(key);
|
|
for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter)
|
|
{
|
|
if (key_cs == iter->first)
|
|
{
|
|
value_sp = iter->second;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return value_sp;
|
|
}
|
|
|
|
template <class IntType>
|
|
bool
|
|
GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const
|
|
{
|
|
ObjectSP value_sp = GetValueForKey(key);
|
|
if (value_sp) {
|
|
if (auto int_value = value_sp->GetAsInteger())
|
|
{
|
|
result = static_cast<IntType>(int_value->GetValue());
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template <class IntType>
|
|
bool
|
|
GetValueForKeyAsInteger(llvm::StringRef key, IntType &result, IntType default_val) const
|
|
{
|
|
bool success = GetValueForKeyAsInteger<IntType>(key, result);
|
|
if (!success)
|
|
result = default_val;
|
|
return success;
|
|
}
|
|
|
|
bool
|
|
GetValueForKeyAsString(llvm::StringRef key, std::string &result) const
|
|
{
|
|
ObjectSP value_sp = GetValueForKey(key);
|
|
if (value_sp.get())
|
|
{
|
|
if (auto string_value = value_sp->GetAsString())
|
|
{
|
|
result = string_value->GetValue();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
GetValueForKeyAsString(llvm::StringRef key, std::string &result, const char *default_val) const
|
|
{
|
|
bool success = GetValueForKeyAsString(key, result);
|
|
if (!success)
|
|
{
|
|
if (default_val)
|
|
result = default_val;
|
|
else
|
|
result.clear();
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool
|
|
GetValueForKeyAsString(llvm::StringRef key, ConstString &result) const
|
|
{
|
|
ObjectSP value_sp = GetValueForKey(key);
|
|
if (value_sp.get())
|
|
{
|
|
if (auto string_value = value_sp->GetAsString())
|
|
{
|
|
result = ConstString(string_value->GetValue());
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
GetValueForKeyAsString(llvm::StringRef key, ConstString &result, const char *default_val) const
|
|
{
|
|
bool success = GetValueForKeyAsString(key, result);
|
|
if (!success)
|
|
result.SetCString(default_val);
|
|
return success;
|
|
}
|
|
|
|
bool
|
|
GetValueForKeyAsDictionary(llvm::StringRef key, Dictionary *&result) const
|
|
{
|
|
result = nullptr;
|
|
ObjectSP value_sp = GetValueForKey(key);
|
|
if (value_sp.get())
|
|
{
|
|
result = value_sp->GetAsDictionary();
|
|
return (result != nullptr);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const
|
|
{
|
|
result = nullptr;
|
|
ObjectSP value_sp = GetValueForKey(key);
|
|
if (value_sp.get())
|
|
{
|
|
result = value_sp->GetAsArray();
|
|
return (result != nullptr);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
HasKey(llvm::StringRef key) const
|
|
{
|
|
ConstString key_cs(key);
|
|
collection::const_iterator search = m_dict.find(key_cs);
|
|
return search != m_dict.end();
|
|
}
|
|
|
|
void
|
|
AddItem (llvm::StringRef key, ObjectSP value_sp)
|
|
{
|
|
ConstString key_cs(key);
|
|
m_dict[key_cs] = value_sp;
|
|
}
|
|
|
|
void
|
|
AddIntegerItem (llvm::StringRef key, uint64_t value)
|
|
{
|
|
AddItem (key, ObjectSP (new Integer(value)));
|
|
}
|
|
|
|
void
|
|
AddFloatItem (llvm::StringRef key, double value)
|
|
{
|
|
AddItem (key, ObjectSP (new Float(value)));
|
|
}
|
|
|
|
void
|
|
AddStringItem (llvm::StringRef key, std::string value)
|
|
{
|
|
AddItem (key, ObjectSP (new String(std::move(value))));
|
|
}
|
|
|
|
void
|
|
AddBooleanItem (llvm::StringRef key, bool value)
|
|
{
|
|
AddItem (key, ObjectSP (new Boolean(value)));
|
|
}
|
|
|
|
void Dump(Stream &s) const override;
|
|
|
|
protected:
|
|
typedef std::map<ConstString, ObjectSP> collection;
|
|
collection m_dict;
|
|
};
|
|
|
|
class Null : public Object
|
|
{
|
|
public:
|
|
Null () :
|
|
Object (Type::eTypeNull)
|
|
{
|
|
}
|
|
|
|
~Null() override = default;
|
|
|
|
bool
|
|
IsValid() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void Dump(Stream &s) const override;
|
|
};
|
|
|
|
class Generic : public Object
|
|
{
|
|
public:
|
|
explicit Generic(void *object = nullptr) :
|
|
Object (Type::eTypeGeneric),
|
|
m_object (object)
|
|
{
|
|
}
|
|
|
|
void
|
|
SetValue(void *value)
|
|
{
|
|
m_object = value;
|
|
}
|
|
|
|
void *
|
|
GetValue() const
|
|
{
|
|
return m_object;
|
|
}
|
|
|
|
bool
|
|
IsValid() const override
|
|
{
|
|
return m_object != nullptr;
|
|
}
|
|
|
|
void Dump(Stream &s) const override;
|
|
|
|
private:
|
|
void *m_object;
|
|
};
|
|
|
|
static ObjectSP
|
|
ParseJSON (std::string json_text);
|
|
};
|
|
|
|
} // namespace lldb_private
|
|
|
|
#endif // liblldb_StructuredData_h_
|