char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
70adb1b4c
char/aliceai-t5-moe
1#pragma once 2 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 library 19// the underlay library is pimpl, we are using nlohmann::json for now 20// 21// many features of the library are deliberately left out, to keep this interface small and generic and to keep compile time down 22// 23// some main differences compared to nlohmann::json : 24// - object keys keep the order in which they are added 25// - errors are always throw as common_json_error 26// - obj.push_back({key, val}) is intentionally unsupported to avoid confusion with push_back on a vector; write it as obj[key] = val for clarity 27// - a braced pair in value position does not build, e.g. {"key", {"a", "b"}}; write array({"a", "b"}) where nlohmann made an array 28// 29// in doubt, search the code base for an existing usage example; do not add anything to this header unless absolutely necessary 30 31class common_json ; 32 33// common_json_value holds a list of these, and each of them holds a value, so one must come first 34struct common_json_item ; 35 36struct common_json_error :std ::runtime_error { 37using std ::runtime_error ::runtime_error ; 38}; 39 40// one value, tagged so that this header stays free of the backing library 41// note: a value that holds a tree is single use, the second use gives null 42struct common_json_value { 43enum value_type { 44VAL_NULL , 45VAL_BOOL , 46VAL_INT , 47VAL_UINT , 48VAL_DOUBLE , 49VAL_STRING , 50VAL_JSON , 51 }; 52 53value_type type = VAL_NULL ; 54 55union { 56bool val_bool ; 57int64_t val_int ; 58uint64_t val_uint = 0 ; 59double val_double ; 60 }; 61 62std ::string val_string ; 63std ::shared_ptr < common_json > val_json ; 64 65common_json_value (std ::nullptr_t = nullptr) :type (VAL_NULL ) {} 66common_json_value (bool val ) :type (VAL_BOOL ),val_bool (val ) {} 67common_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 recurses 69common_json_value (std ::string_view val ) :type (VAL_STRING ),val_string (val ) {} 70common_json_value (const char * val ); 71common_json_value (const common_json & val ); 72common_json_value (common_json && val ); 73// only for the types instantiated in json.cpp, the rest fails at link time 74template < typename T > common_json_value (const std ::vector < T > & vals ); 75// a set becomes an array, in the set's own order 76template < typename T > common_json_value (const std ::set < T > & vals ); 77// a map becomes an object, keyed in the map's own order 78template < typename T > common_json_value (const std ::map < std ::string ,T > & vals ); 79template < 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 array 83common_json_value (std ::initializer_list < common_json_item > items ); 84 85template < typename T ,typename std ::enable_if < std ::is_integral < T > ::value && !std ::is_same < T ,bool > ::value ,int > ::type = 0 > 86common_json_value (T val ) :type (std ::is_signed < T > ::value ?VAL_INT :VAL_UINT ) { 87if (std ::is_signed < T > ::value ) { 88val_int = (int64_t )val ; 89 }else { 90val_uint = (uint64_t )val ; 91 } 92 } 93 94template < typename T ,typename std ::enable_if < std ::is_floating_point < T > ::value ,int > ::type = 0 > 95common_json_value (T val ) :type (VAL_DOUBLE ),val_double (( double ) val) {} 96}; 97 98struct common_json_item { 99std :: string key ; 100common_json_value val ; 101 102template < typename T > 103common_json_item ( std ::string key, T && val) : 104key (std:: move (key)), val ( std ::forward < T > (val)) {} 105 106// a braced list cannot deduce T, so it needs its own overload 107common_json_item(std::string key, std ::initializer_list < common_json_item > items) : 108key(std:: move (key)), val ( items ) {} 109}; 110 111// the types common_json_value holds on its own 112// anything else reaches its common_json ctor and recurses forever 113template < typename T > struct common_json_is_value : std::integral_constant < bool, 114std ::is_arithmetic < T > ::value || 115std::is_same < T , std ::nullptr_t > ::value || 116std::is_same < T , std ::string > ::value || 117std::is_same < T , std ::string_view > ::value || 118std::is_same < T , char *> ::value || 119std::is_same < T , const char *> :: value || 120std ::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 { 135public : 136common_json (); 137common_json( const common_json & other); 138common_json( common_json && other) noexcept ; 139common_json( std :: initializer_list < common_json_item > items); 140common_json( const common_json_value & val); 141 142// direct, a value would need two conversions in a row 143common_json( std :: nullptr_t ); 144 145// one step, so that "abc" or a vector can go straight into a common_json 146template < 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 > 148common_json ( T && val) : common_json ( common_json_value (std::forward < T > (val))) { 149static_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 library 154// the right side is copied before the left side can invalidate it, e.g. msg["a"] = msg.at("b") 155common_json & operator = ( common_json other) noexcept; 156 157~ common_json (); 158 159// throws common_json_error if the text is not valid JSON 160static common_json parse ( const std ::string & text); 161 162// gives a discarded value instead of throwing, check it with is_discarded() 163static common_json parse_no_throw ( const std ::string & text); 164 165bool is_discarded () const ; 166 167static common_json array (); 168static common_json array ( std ::initializer_list < common_json_value > vals); 169static common_json object (); 170static common_json object ( std ::initializer_list < common_json_item > items); 171 172// holds a single value, e.g. make("abc").dump() gives "\"abc\"" 173static common_json make ( const common_json_value & val); 174 175bool is_null () const; 176bool is_object () const; 177bool is_array () const; 178bool is_string () const; 179bool is_boolean () const; 180bool is_number () const; 181bool is_number_integer () const; 182bool is_number_float () const; 183 184bool empty () const; 185size_t size () const; 186 187bool contains ( const std ::string & key) const; 188 189bool operator == ( const common_json_value & val) const ; 190bool operator != ( const common_json_value & val) const ; 191 192// at() throws common_json_error if the key is missing, operator[] adds a null value instead 193// note: a const operator[] cannot add, it throws like at() 194common_json & at ( const std ::string & key); 195const common_json & at ( const std ::string & key) const; 196common_json & at ( size_t idx); 197const common_json & at ( size_t idx) const; 198 199common_json & operator[]( const std ::string & key); 200const common_json & operator[]( const std ::string & key) const; 201common_json & operator[]( const char * key) { return ( * this)[std:: string (key)]; } 202const common_json & operator[]( const char * key) const { return ( * this)[std:: string (key)]; } 203common_json & operator[](int idx) { return ( * this)[ to_idx (idx)]; } 204const common_json & operator[]( int idx) const { return ( * this)[ to_idx (idx)]; } 205common_json & operator[](size_t idx) ; 206const common_json & operator []( size_t idx ) const ; 207 208common_json & front (); 209const common_json & front () const ; 210common_json & back (); 211const common_json & back () const ; 212 213void clear (); 214 215void erase ( const std :: string & key ); 216void erase ( size_t idx ); 217 218// only for the types instantiated in json.cpp, the rest fails at link time 219template < typename T > T get () const ; 220 221// implicit get<T>() for plain values, so they can be assigned to their C++ type directly 222// note: kept to this short list on purpose, a wider one makes j["key"] ambiguous 223// note: a numeric one would make "str = json;" ambiguous, a number converts to char too 224operator std :: string () const ; 225 226template < typename T > 227T value ( const std :: string & key , T def ) const { 228return contains ( key ) ? at ( key ). get < T >() : def ; 229} 230 231std :: string value ( const std :: string & key , const char * def ) const ; 232 233// a JSON default needs no get<T>(), it is already the right type 234common_json value ( const std :: string & key , const common_json & def ) const { 235return contains ( key ) ? at ( key ) : def ; 236} 237 238void assign ( const common_json_value & val ); 239void set ( const common_json_item & item ); 240void push_back ( const common_json_value & val ); 241 242// appends one object, e.g. push_back({{"a", 1}}) 243void push_back ( std :: initializer_list < common_json_item > items ); 244 245// 1 if the key is there, 0 if not 246size_t count ( const std :: string & key ) const ; 247 248// appends every value of another array; inserting an array into itself throws 249void insert ( const common_json & vals ); 250 251// a common_json goes through the copy assignment above, everything else becomes a value 252template < typename T , typename std :: enable_if <! std :: is_same < typename std :: decay < T >:: type , common_json >:: value , int >:: type = 0 > 253common_json & operator =( T && val ) { 254assign ( common_json_value ( std :: forward < T >( val ))); 255return * this ; 256} 257 258std :: string dump ( int indent = -1 ) const ; 259 260// same as dump(), but bad UTF-8 gets replaced instead of throwing 261std :: string dump_safe ( int indent = -1 ) const ; 262 263// walks an array by index, or an object in insertion order 264// a plain value gives itself once, same as the backing library 265class iterator { 266public : 267using iterator_category = std :: forward_iterator_tag ; 268using value_type = common_json ; 269using difference_type = std :: ptrdiff_t ; 270using pointer = common_json *; 271using reference = common_json &; 272 273iterator ( common_json * node , size_t idx ) : node ( node ), idx ( idx ) {} 274 275common_json & operator *( ) const ; 276common_json & value () const { return ** this ; } 277std ::string key () const ; 278 279iterator & operator ++ () { 280idx ++ ; 281return * this ; 282} 283 284bool operator != ( const iterator & other ) const { return idx != other . idx ; } 285bool operator == ( const iterator & other ) const { return idx == other . idx ; } 286 287private : 288common_json * node ; 289size_t idx ; 290}; 291 292iterator begin () const ; 293iterator end () const ; 294 295// allows: for (const auto & [key, val] : obj.items()) 296class items_view { 297public : 298// the members are public, so an entry also works with structured bindings 299struct entry { 300std :: string k ; 301common_json & v ; 302 303const std:: string & key () const { return k ; } 304common_json & value () const { return v ; } 305}; 306 307items_view ( common_json * node , size_t n ) : node( node ), n (n) {} 308 309class iterator { 310public : 311iterator ( common_json * node , size_t idx ) : node ( node ), idx ( idx ) {} 312 313entry operator * () const ; 314 315iterator & operator ++ () { 316idx ++ ; 317return * this; 318} 319 320bool operator != ( const iterator & other) const { return idx != other. idx ; } 321 322private : 323common_json * node; 324size_t idx; 325}; 326 327iterator begin () const { return iterator (node, 0 ); } 328iterator end () const { return iterator (node, n); } 329 330private : 331common_json * node; 332size_t n; 333}; 334 335items_view items () const ; 336 337private : 338// a negative index must not turn into a huge size_t 339static size_t to_idx ( int idx) { 340if (idx < 0 ) { 341throw common_json_error( "negative array index" ); 342} 343return ( size_t ) idx; 344} 345 346// the backing value is built here, json.cpp checks that it fits 347// it cannot be a pointer: a value inside a tree would then not be a common_json 348// at() could then only give back a copy instead of a real reference 349alignas( 8 ) unsigned char storage[ 32 ]; 350}; 351 352using common_json_entry = common_json::items_view::entry ;