/* Copyright 2022-2023 René Ferdinand Rivera Morell Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) */ #ifndef BOOST_JAM_VALUE_H #define BOOST_JAM_VALUE_H #include "config.h" #include "strview.h" #include #include #include #include #include #include namespace b2 { struct object { virtual ~object() {} }; struct value { struct str_view { const char * str; std::size_t size; inline const char * begin() const { return str; } inline const char * end() const { return str + size; } }; enum class type : char { null = '\0', string = 's', number = 'n', object = 'o' }; mutable std::uint64_t hash64 = 0; virtual ~value() {} virtual type get_type() const = 0; virtual bool equal_to(const value & o) const = 0; virtual int compare_to(const value & o) const = 0; virtual str_view as_string() const = 0; virtual double as_number() const = 0; virtual object * as_object() const = 0; virtual value * to_string() = 0; inline const char * str() { return as_string().str; } static value * make(const char * str, std::size_t size); static inline value * make(const char * str) { return make(str, str ? strlen(str) : 0); } static inline value * make(const char * begin, const char * end) { return make(begin, end - begin); } static inline value * make(const std::string & str) { return make(str.c_str(), str.size()); } static inline value * make(string_view str) { return make(str.data(), str.length()); } static value * make(object * obj); static value * make(double v); static inline value * copy(value * v) { return v; } static inline void free(value *& v) { v = nullptr; } static void done(); inline bool has_value() const { return get_type() == type::null; } template static inline value * as_string(T v) { return value::make(std::to_string(v)); } template static inline value * format(const char * f, Args... args) { auto size = std::snprintf(nullptr, 0, f, args...); std::unique_ptr s(new char[size + 1]); std::snprintf(s.get(), size + 1, f, args...); return value::make(s.get(), size); } inline int compare(const value & other) const { if (get_type() != other.get_type()) return int(get_type()) - int(other.get_type()); return compare_to(other); } }; typedef value * value_ptr; struct value_ref { inline value_ref() : val(nullptr) {} inline value_ref(const value_ref & a) : val(value::copy(a.val)) {} inline value_ref(value_ptr a) : val(value::copy(a)) {} inline value_ref(const char * s) : val(value::make(s)) {} inline value_ref(const std::string & s) : val(value::make(s.c_str())) {} inline value_ref(const string_view & sv) : val(value::make(sv)) {} inline ~value_ref() { if (val) value::free(val); } inline value_ptr release() { value_ptr r = val; val = nullptr; return r; } inline operator value_ptr() const { return val; } inline operator std::string() const { return val->str(); } inline bool operator==(value_ptr b) const { return val->equal_to(*b); } inline bool operator==(const char * v) const { return (*this) == value_ref(v); } template inline bool operator!=(T v) const { return !((*this) == v); } inline value_ptr operator->() const { return val; } inline value & operator*() const { return *val; } inline bool has_value() const { return val != nullptr; } inline value_ref operator+(const std::string & v) const { return value_ref((*this)->str() + v); } friend inline value_ref operator+(const std::string & a, value_ref b) { const char * c = b.has_value() ? b->str() : ""; return value_ref(a + c); } struct hash_function { inline std::size_t operator()(const value_ref & a) const { return (std::size_t)( (std::numeric_limits::max)() & a->hash64); } }; struct equal_function { inline bool operator()(const value_ref & a, const value_ref & b) const { return (a->hash64 == b->hash64) && a->equal_to(*b); } }; private: value_ptr val = nullptr; }; } // namespace b2 #endif