#ifndef HM_JSON_VALUE_H #define HM_JSON_VALUE_H #define IS_TYPE(type_a, type_b) std::is_same::value #define GET_VALUE(type, pointer) *((type *) pointer) #define DIFFERENT_TYPE_ERR(type_name) std::logic_error("Error: expected type is <" + type_name + ">") #include #include #include #include #include namespace json { class Value; enum TYPE { NullType, BoolType, IntType, DecimalType, StringType, ListType, DictType }; std::string const _typeIdToName[] = {"Null", "Bool", "Int", "Decimal", "String", "List", "Dict"}; // NOLINT using null_type = char; using bool_type = bool; using int_type = long; using decimal_type = double; using string_type = std::string; using list_type = std::vector; using dict_type = std::map; class Value { public: Value(); explicit Value(bool_type const &value); explicit Value(int const &value); explicit Value(int_type const &value); explicit Value(decimal_type const &value); explicit Value(string_type const &value); explicit Value(const char *value); explicit Value(list_type const &value); explicit Value(dict_type const &value); template [[nodiscard]] T &value(); [[nodiscard]] constexpr TYPE type_id() const; [[nodiscard]] std::string type_name() const; [[nodiscard]] constexpr bool is_basic() const; [[nodiscard]] std::string str(bool const &format_need = false, int const &indent = 2, int layer = 1); void push_back(Value const &value); void pop_back(); void erase(int const &index); void erase(std::string const &key); Value &operator[](int const &index); Value &operator[](std::string const &key); private: // null: string using data_type = std::variant; TYPE _type; data_type _data; void *_value(); }; template T &Value::value() { if constexpr (IS_TYPE(T, null_type)) { if (_type != NullType) throw DIFFERENT_TYPE_ERR(_typeIdToName[NullType]); } else if constexpr (IS_TYPE(T, bool_type)) { if (_type != BoolType) throw DIFFERENT_TYPE_ERR(_typeIdToName[BoolType]); } else if constexpr (IS_TYPE(T, int_type)) { if (_type != IntType) throw DIFFERENT_TYPE_ERR(_typeIdToName[IntType]); } else if constexpr (IS_TYPE(T, decimal_type)) { if (_type != DecimalType) throw DIFFERENT_TYPE_ERR(_typeIdToName[DecimalType]); } else if constexpr (IS_TYPE(T, string_type)) { if (_type != StringType) throw DIFFERENT_TYPE_ERR(_typeIdToName[StringType]); } else if constexpr (IS_TYPE(T, list_type)) { if (_type != ListType) throw DIFFERENT_TYPE_ERR(_typeIdToName[ListType]); } else if constexpr (IS_TYPE(T, dict_type)) { if (_type != DictType) throw DIFFERENT_TYPE_ERR(_typeIdToName[DictType]); } return *((T *) _value()); } } #endif //HM_JSON_VALUE_H