CoolFace
Modelpublic

Felipe97/llama-cpp-compiled

sourceHugging Faceupdated 3d agoView on Hugging Face
0likes1.1kdownloads
json.h353 linesDownload Raw Back to common
1#pragma once2 3#include <cstddef>4#include <cstdint>5#include <initializer_list>6#include <iterator>7#include <map>8#include <memory>9#include <set>10#include <stdexcept>11#include <string>12#include <string_view>13#include <type_traits>14#include <unordered_map>15#include <utility>16#include <vector>17 18// common_json, a thin wrapper around vendor json library19// the underlay library is pimpl, we are using nlohmann::json for now20//21// many features of the library are deliberately left out, to keep this interface small and generic and to keep compile time down22//23// some main differences compared to nlohmann::json :24// - object keys keep the order in which they are added25// - errors are always throw as common_json_error26// - obj.push_back({key, val}) is intentionally unsupported to avoid confusion with push_back on a vector; write it as obj[key] = val for clarity27// - a braced pair in value position does not build, e.g. {"key", {"a", "b"}}; write array({"a", "b"}) where nlohmann made an array28//29// in doubt, search the code base for an existing usage example; do not add anything to this header unless absolutely necessary30 31class common_json;32 33// common_json_value holds a list of these, and each of them holds a value, so one must come first34struct common_json_item;35 36struct common_json_error : std::runtime_error {37    using std::runtime_error::runtime_error;38};39 40// one value, tagged so that this header stays free of the backing library41// note: a value that holds a tree is single use, the second use gives null42struct common_json_value {43    enum value_type {44        VAL_NULL,45        VAL_BOOL,46        VAL_INT,47        VAL_UINT,48        VAL_DOUBLE,49        VAL_STRING,50        VAL_JSON,51    };52 53    value_type type = VAL_NULL;54 55    union {56        bool     val_bool;57        int64_t  val_int;58        uint64_t val_uint = 0;59        double   val_double;60    };61 62    std::string                  val_string;63    std::shared_ptr<common_json> val_json;64 65    common_json_value(std::nullptr_t = nullptr) : type(VAL_NULL) {}66    common_json_value(bool val) : type(VAL_BOOL), val_bool(val) {}67    common_json_value(std::string val) : type(VAL_STRING), val_string(std::move(val)) {}68    // without this a string_view lands on the common_json ctor below and recurses69    common_json_value(std::string_view val) : type(VAL_STRING), val_string(val) {}70    common_json_value(const char * val);71    common_json_value(const common_json & val);72    common_json_value(common_json && val);73    // only for the types instantiated in json.cpp, the rest fails at link time74    template <typename T> common_json_value(const std::vector<T> & vals);75    // a set becomes an array, in the set's own order76    template <typename T> common_json_value(const std::set<T> & vals);77    // a map becomes an object, keyed in the map's own order78    template <typename T> common_json_value(const std::map<std::string, T> & vals);79    template <typename T> common_json_value(const std::unordered_map<std::string, T> & vals);80 81    // nested object, e.g. {"fn", {{"name", "x"}}}82    // note: a nested pair {"a", "b"} does not build, use common_json::array({"a", "b"}) for an array83    common_json_value(std::initializer_list<common_json_item> items);84 85    template <typename T, typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, int>::type = 0>86    common_json_value(T val) : type(std::is_signed<T>::value ? VAL_INT : VAL_UINT) {87        if (std::is_signed<T>::value) {88            val_int = (int64_t) val;89        } else {90            val_uint = (uint64_t) val;91        }92    }93 94    template <typename T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>95    common_json_value(T val) : type(VAL_DOUBLE), val_double((double) val) {}96};97 98struct common_json_item {99    std::string       key;100    common_json_value val;101 102    template <typename T>103    common_json_item(std::string key, T && val) :104        key(std::move(key)), val(std::forward<T>(val)) {}105 106    // a braced list cannot deduce T, so it needs its own overload107    common_json_item(std::string key, std::initializer_list<common_json_item> items) :108        key(std::move(key)), val(items) {}109};110 111// the types common_json_value holds on its own112// anything else reaches its common_json ctor and recurses forever113template <typename T> struct common_json_is_value : std::integral_constant<bool,114    std::is_arithmetic<T>::value ||115    std::is_same<T, std::nullptr_t>::value ||116    std::is_same<T, std::string>::value ||117    std::is_same<T, std::string_view>::value ||118    std::is_same<T, char *>::value ||119    std::is_same<T, const char *>::value ||120    std::is_same<T, common_json>::value> {};121 122template <typename T, typename A>123struct common_json_is_value<std::vector<T, A>> : std::true_type {};124 125template <typename T, typename C, typename A>126struct common_json_is_value<std::set<T, C, A>> : std::true_type {};127 128template <typename V, typename C, typename A>129struct common_json_is_value<std::map<std::string, V, C, A>> : std::true_type {};130 131template <typename V, typename H, typename E, typename A>132struct common_json_is_value<std::unordered_map<std::string, V, H, E, A>> : std::true_type {};133 134class common_json {135  public:136    common_json();137    common_json(const common_json & other);138    common_json(common_json && other) noexcept;139    common_json(std::initializer_list<common_json_item> items);140    common_json(const common_json_value & val);141 142    // direct, a value would need two conversions in a row143    common_json(std::nullptr_t);144 145    // one step, so that "abc" or a vector can go straight into a common_json146    template <typename T, typename std::enable_if<!std::is_same<typename std::decay<T>::type, common_json>::value &&147                                                  !std::is_same<typename std::decay<T>::type, common_json_value>::value, int>::type = 0>148    common_json(T && val) : common_json(common_json_value(std::forward<T>(val))) {149        static_assert(common_json_is_value<typename std::decay<T>::type>::value,150                      "no common_json_value ctor holds this type, add one instead of letting it recurse");151    }152 153    // by value, same as the backing library154    // the right side is copied before the left side can invalidate it, e.g. msg["a"] = msg.at("b")155    common_json & operator=(common_json other) noexcept;156 157    ~common_json();158 159    // throws common_json_error if the text is not valid JSON160    static common_json parse(const std::string & text);161 162    // gives a discarded value instead of throwing, check it with is_discarded()163    static common_json parse_no_throw(const std::string & text);164 165    bool is_discarded() const;166 167    static common_json array();168    static common_json array(std::initializer_list<common_json_value> vals);169    static common_json object();170    static common_json object(std::initializer_list<common_json_item> items);171 172    // holds a single value, e.g. make("abc").dump() gives "\"abc\""173    static common_json make(const common_json_value & val);174 175    bool is_null()    const;176    bool is_object()  const;177    bool is_array()   const;178    bool is_string()  const;179    bool is_boolean() const;180    bool is_number()  const;181    bool is_number_integer() const;182    bool is_number_float()   const;183 184    bool   empty() const;185    size_t size()  const;186 187    bool contains(const std::string & key) const;188 189    bool operator==(const common_json_value & val) const;190    bool operator!=(const common_json_value & val) const;191 192    // at() throws common_json_error if the key is missing, operator[] adds a null value instead193    // note: a const operator[] cannot add, it throws like at()194    common_json       & at(const std::string & key);195    const common_json & at(const std::string & key) const;196    common_json       & at(size_t idx);197    const common_json & at(size_t idx) const;198 199    common_json       & operator[](const std::string & key);200    const common_json & operator[](const std::string & key) const;201    common_json       & operator[](const char * key)       { return (*this)[std::string(key)]; }202    const common_json & operator[](const char * key) const { return (*this)[std::string(key)]; }203    common_json       & operator[](int idx)       { return (*this)[to_idx(idx)]; }204    const common_json & operator[](int idx) const { return (*this)[to_idx(idx)]; }205    common_json       & operator[](size_t idx);206    const common_json & operator[](size_t idx) const;207 208    common_json       & front();209    const common_json & front() const;210    common_json       & back();211    const common_json & back()  const;212 213    void clear();214 215    void erase(const std::string & key);216    void erase(size_t idx);217 218    // only for the types instantiated in json.cpp, the rest fails at link time219    template <typename T> T get() const;220 221    // implicit get<T>() for plain values, so they can be assigned to their C++ type directly222    // note: kept to this short list on purpose, a wider one makes j["key"] ambiguous223    // note: a numeric one would make "str = json;" ambiguous, a number converts to char too224    operator std::string() const;225 226    template <typename T>227    T value(const std::string & key, T def) const {228        return contains(key) ? at(key).get<T>() : def;229    }230 231    std::string value(const std::string & key, const char * def) const;232 233    // a JSON default needs no get<T>(), it is already the right type234    common_json value(const std::string & key, const common_json & def) const {235        return contains(key) ? at(key) : def;236    }237 238    void assign(const common_json_value & val);239    void set(const common_json_item & item);240    void push_back(const common_json_value & val);241 242    // appends one object, e.g. push_back({{"a", 1}})243    void push_back(std::initializer_list<common_json_item> items);244 245    // 1 if the key is there, 0 if not246    size_t count(const std::string & key) const;247 248    // appends every value of another array; inserting an array into itself throws249    void insert(const common_json & vals);250 251    // a common_json goes through the copy assignment above, everything else becomes a value252    template <typename T, typename std::enable_if<!std::is_same<typename std::decay<T>::type, common_json>::value, int>::type = 0>253    common_json & operator=(T && val) {254        assign(common_json_value(std::forward<T>(val)));255        return *this;256    }257 258    std::string dump(int indent = -1) const;259 260    // same as dump(), but bad UTF-8 gets replaced instead of throwing261    std::string dump_safe(int indent = -1) const;262 263    // walks an array by index, or an object in insertion order264    // a plain value gives itself once, same as the backing library265    class iterator {266      public:267        using iterator_category = std::forward_iterator_tag;268        using value_type        = common_json;269        using difference_type   = std::ptrdiff_t;270        using pointer           = common_json *;271        using reference         = common_json &;272 273        iterator(common_json * node, size_t idx) : node(node), idx(idx) {}274 275        common_json & operator*() const;276        common_json & value()     const { return **this; }277        std::string   key()       const;278 279        iterator & operator++() {280            idx++;281            return *this;282        }283 284        bool operator!=(const iterator & other) const { return idx != other.idx; }285        bool operator==(const iterator & other) const { return idx == other.idx; }286 287      private:288        common_json * node;289        size_t        idx;290    };291 292    iterator begin() const;293    iterator end()   const;294 295    // allows: for (const auto & [key, val] : obj.items())296    class items_view {297      public:298        // the members are public, so an entry also works with structured bindings299        struct entry {300            std::string   k;301            common_json & v;302 303            const std::string & key()   const { return k; }304            common_json &       value() const { return v; }305        };306 307        items_view(common_json * node, size_t n) : node(node), n(n) {}308 309        class iterator {310          public:311            iterator(common_json * node, size_t idx) : node(node), idx(idx) {}312 313            entry operator*() const;314 315            iterator & operator++() {316                idx++;317                return *this;318            }319 320            bool operator!=(const iterator & other) const { return idx != other.idx; }321 322          private:323            common_json * node;324            size_t        idx;325        };326 327        iterator begin() const { return iterator(node, 0); }328        iterator end()   const { return iterator(node, n); }329 330      private:331        common_json * node;332        size_t        n;333    };334 335    items_view items() const;336 337  private:338    // a negative index must not turn into a huge size_t339    static size_t to_idx(int idx) {340        if (idx < 0) {341            throw common_json_error("negative array index");342        }343        return (size_t) idx;344    }345 346    // the backing value is built here, json.cpp checks that it fits347    // it cannot be a pointer: a value inside a tree would then not be a common_json348    // at() could then only give back a copy instead of a real reference349    alignas(8) unsigned char storage[32];350};351 352using common_json_entry = common_json::items_view::entry;353