char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Xuan-Son Nguyencommon: json.h: fix clang lto (#27575)70adb1b4c

char/aliceai-t5-moe
14.3 KiB433 linesraw
1#include "json.h"
2
3#include "ggml.h"
4
5#define JSON_ASSERT GGML_ASSERT
6#include <nlohmann/json.hpp>
7
8#include <iterator>
9#include <new>
10#include <set>
11#include <unordered_map>
12#include <vector>
13
14using nlohmann::ordered_json;
15
16// a common_json is the backing value, so any value of a tree can be used as a common_json
17static_assert(sizeof(ordered_json)  <= sizeof(common_json),  "common_json storage is too small");
18static_assert(alignof(ordered_json) <= alignof(common_json), "common_json alignment is too weak");
19
20// runs fn and gives every error of the backing library as a common_json_error
21template <typename F>
22static decltype(auto) guard(F && fn) {
23    try {
24        return fn();
25    } catch (const ordered_json::exception & e) {
26        throw common_json_error(e.what());
27    }
28}
29
30static ordered_json & as_json(common_json * self) {
31    return *reinterpret_cast<ordered_json *>(self);
32}
33
34static const ordered_json & as_json(const common_json * self) {
35    return *reinterpret_cast<const ordered_json *>(self);
36}
37
38static common_json & as_common(ordered_json & json) {
39    return *reinterpret_cast<common_json *>(&json);
40}
41
42static const common_json & as_common(const ordered_json & json) {
43    return *reinterpret_cast<const common_json *>(&json);
44}
45
46static ordered_json to_json(const common_json_value & val) {
47    switch (val.type) {
48        case common_json_value::VAL_NULL:   return nullptr;
49        case common_json_value::VAL_BOOL:   return val.val_bool;
50        case common_json_value::VAL_INT:    return val.val_int;
51        case common_json_value::VAL_UINT:   return val.val_uint;
52        case common_json_value::VAL_DOUBLE: return val.val_double;
53        case common_json_value::VAL_STRING: return val.val_string;
54        case common_json_value::VAL_JSON:
55            // one owner means no one else can see this tree, so it is safe to move it out
56            // note: this makes a value single use, same as the json_ref of the backing library
57            if (val.val_json.use_count() == 1) {
58                return std::move(as_json(val.val_json.get()));
59            }
60            return as_json(val.val_json.get());
61    }
62
63    return nullptr;
64}
65
66common_json_value::common_json_value(const char * val) {
67    if (val) {
68        type       = VAL_STRING;
69        val_string = val;
70    } else {
71        type = VAL_NULL;
72    }
73}
74
75common_json_value::common_json_value(const common_json & val) :
76    type(VAL_JSON), val_json(std::make_shared<common_json>(val)) {}
77
78common_json_value::common_json_value(common_json && val) :
79    type(VAL_JSON), val_json(std::make_shared<common_json>(std::move(val))) {}
80
81// the ctors and get<T>() below are explicit specializations, giving strong symbols
82// an explicit instantiation is a weak symbol, dropped by some LTO builds (clang-cl)
83template <typename T>
84static std::shared_ptr<common_json> set_json(const std::set<T> & vals) {
85    common_json out = common_json::array();
86
87    for (const auto & val : vals) {
88        out.push_back(val);
89    }
90
91    return std::make_shared<common_json>(std::move(out));
92}
93
94// a set value is usable only for the types below
95#define COMMON_JSON_SET(...) template <> common_json_value::common_json_value(const std::set<__VA_ARGS__> & vals) : type(VAL_JSON), val_json(set_json(vals)) {}
96
97COMMON_JSON_SET(int)
98COMMON_JSON_SET(std::string)
99
100#undef COMMON_JSON_SET
101
102template <typename T>
103static std::shared_ptr<common_json> map_json(const T & vals) {
104    common_json out = common_json::object();
105
106    for (const auto & val : vals) {
107        out.set({ val.first, val.second });
108    }
109
110    return std::make_shared<common_json>(std::move(out));
111}
112
113// a map value is usable only for the types below
114#define COMMON_JSON_MAP(...) template <> common_json_value::common_json_value(const std::map<std::string, __VA_ARGS__> & vals) : type(VAL_JSON), val_json(map_json(vals)) {}
115
116COMMON_JSON_MAP(bool)
117COMMON_JSON_MAP(std::string)
118
119#undef COMMON_JSON_MAP
120
121// an unordered map value is usable only for the types below
122#define COMMON_JSON_UMAP(...) template <> common_json_value::common_json_value(const std::unordered_map<std::string, __VA_ARGS__> & vals) : type(VAL_JSON), val_json(map_json(vals)) {}
123
124COMMON_JSON_UMAP(size_t)
125
126#undef COMMON_JSON_UMAP
127
128template <typename T>
129static std::shared_ptr<common_json> vec_json(const std::vector<T> & vals) {
130    common_json out = common_json::array();
131
132    for (const auto & val : vals) {
133        out.push_back(val);
134    }
135
136    return std::make_shared<common_json>(std::move(out));
137}
138
139// a vector value is usable only for the types below
140// note: std::vector<bool> is not here, its proxy reference does not convert
141#define COMMON_JSON_VEC(...) template <> common_json_value::common_json_value(const std::vector<__VA_ARGS__> & vals) : type(VAL_JSON), val_json(vec_json(vals)) {}
142
143COMMON_JSON_VEC(int)
144COMMON_JSON_VEC(unsigned char)
145COMMON_JSON_VEC(unsigned int)
146COMMON_JSON_VEC(long)
147COMMON_JSON_VEC(unsigned long)
148COMMON_JSON_VEC(long long)
149COMMON_JSON_VEC(unsigned long long)
150COMMON_JSON_VEC(float)
151COMMON_JSON_VEC(double)
152COMMON_JSON_VEC(std::string)
153COMMON_JSON_VEC(std::vector<float>)
154COMMON_JSON_VEC(common_json)
155
156#undef COMMON_JSON_VEC
157
158common_json_value::common_json_value(std::initializer_list<common_json_item> items) :
159    type(VAL_JSON), val_json(std::make_shared<common_json>(items)) {}
160
161// null, same as the backing library
162// operator[] turns it into an object, push_back() into an array
163common_json::common_json() {
164    new (storage) ordered_json();
165}
166
167common_json::common_json(const common_json & other) {
168    new (storage) ordered_json(as_json(&other));
169}
170
171common_json::common_json(common_json && other) noexcept {
172    new (storage) ordered_json(std::move(as_json(&other)));
173}
174
175common_json::common_json(std::initializer_list<common_json_item> items) {
176    new (storage) ordered_json(ordered_json::object());
177
178    for (const auto & item : items) {
179        set(item);
180    }
181}
182
183common_json::common_json(const common_json_value & val) {
184    new (storage) ordered_json(to_json(val));
185}
186
187common_json::common_json(std::nullptr_t) {
188    new (storage) ordered_json(nullptr);
189}
190
191common_json & common_json::operator=(common_json other) noexcept {
192    as_json(this).swap(as_json(&other));
193
194    return *this;
195}
196
197common_json::~common_json() {
198    as_json(this).~basic_json();
199}
200
201common_json common_json::parse(const std::string & text) {
202    try {
203        // the assignment moves the parsed tree in, it does not copy
204        common_json out;
205        as_json(&out) = ordered_json::parse(text);
206        return out;
207    } catch (const std::exception & e) {
208        throw common_json_error(e.what());
209    }
210}
211
212common_json common_json::parse_no_throw(const std::string & text) {
213    common_json out;
214    as_json(&out) = ordered_json::parse(text, nullptr, false);
215    return out;
216}
217
218bool common_json::is_discarded() const {
219    return as_json(this).is_discarded();
220}
221
222common_json common_json::array() {
223    common_json out;
224    as_json(&out) = ordered_json::array();
225    return out;
226}
227
228common_json common_json::array(std::initializer_list<common_json_value> vals) {
229    common_json out;
230    ordered_json & arr = as_json(&out);
231    arr = ordered_json::array();
232
233    for (const auto & val : vals) {
234        arr.push_back(to_json(val));
235    }
236
237    return out;
238}
239
240common_json common_json::object() {
241    common_json out;
242    as_json(&out) = ordered_json::object();
243    return out;
244}
245
246common_json common_json::object(std::initializer_list<common_json_item> items) {
247    return common_json(items);
248}
249
250common_json common_json::make(const common_json_value & val) {
251    return common_json(val);
252}
253
254bool common_json::is_null()           const { return as_json(this).is_null(); }
255bool common_json::is_object()         const { return as_json(this).is_object(); }
256bool common_json::is_array()          const { return as_json(this).is_array(); }
257bool common_json::is_string()         const { return as_json(this).is_string(); }
258bool common_json::is_boolean()        const { return as_json(this).is_boolean(); }
259bool common_json::is_number()         const { return as_json(this).is_number(); }
260bool common_json::is_number_integer() const { return as_json(this).is_number_integer(); }
261bool common_json::is_number_float()   const { return as_json(this).is_number_float(); }
262
263bool   common_json::empty() const { return as_json(this).empty(); }
264size_t common_json::size()  const { return as_json(this).size(); }
265
266bool common_json::contains(const std::string & key) const {
267    return as_json(this).contains(key);
268}
269
270bool common_json::operator==(const common_json_value & val) const {
271    // compare a tree in place, to_json() would copy it
272    if (val.type == common_json_value::VAL_JSON) {
273        return as_json(this) == as_json(val.val_json.get());
274    }
275    return as_json(this) == to_json(val);
276}
277
278bool common_json::operator!=(const common_json_value & val) const {
279    return !(*this == val);
280}
281
282common_json       & common_json::at(const std::string & key)       { return guard([&]() -> common_json       & { return as_common(as_json(this).at(key)); }); }
283const common_json & common_json::at(const std::string & key) const { return guard([&]() -> const common_json & { return as_common(as_json(this).at(key)); }); }
284common_json       & common_json::at(size_t idx)                    { return guard([&]() -> common_json       & { return as_common(as_json(this).at(idx)); }); }
285const common_json & common_json::at(size_t idx)              const { return guard([&]() -> const common_json & { return as_common(as_json(this).at(idx)); }); }
286
287common_json       & common_json::operator[](const std::string & key)       { return guard([&]() -> common_json       & { return as_common(as_json(this)[key]); }); }
288const common_json & common_json::operator[](const std::string & key) const { return guard([&]() -> const common_json & { return as_common(as_json(this).at(key)); }); }
289common_json       & common_json::operator[](size_t idx)                    { return guard([&]() -> common_json       & { return as_common(as_json(this)[idx]); }); }
290const common_json & common_json::operator[](size_t idx)              const { return guard([&]() -> const common_json & { return as_common(as_json(this).at(idx)); }); }
291
292common_json       & common_json::front()       { return as_common(as_json(this).front()); }
293const common_json & common_json::front() const { return as_common(as_json(this).front()); }
294common_json       & common_json::back()        { return as_common(as_json(this).back()); }
295const common_json & common_json::back()  const { return as_common(as_json(this).back()); }
296
297void common_json::clear() {
298    as_json(this).clear();
299}
300
301void common_json::erase(const std::string & key) {
302    guard([&] { as_json(this).erase(key); });
303}
304
305void common_json::erase(size_t idx) {
306    guard([&] { as_json(this).erase(idx); });
307}
308
309void common_json::assign(const common_json_value & val) {
310    as_json(this) = to_json(val);
311}
312
313void common_json::set(const common_json_item & item) {
314    guard([&] { as_json(this)[item.key] = to_json(item.val); });
315}
316
317void common_json::push_back(const common_json_value & val) {
318    guard([&] { as_json(this).push_back(to_json(val)); });
319}
320
321void common_json::push_back(std::initializer_list<common_json_item> items) {
322    common_json val(items);
323
324    guard([&] { as_json(this).push_back(std::move(as_json(&val))); });
325}
326
327size_t common_json::count(const std::string & key) const {
328    return as_json(this).count(key);
329}
330
331void common_json::insert(const common_json & vals) {
332    guard([&] {
333        ordered_json & self = as_json(this);
334
335        self.insert(self.end(), as_json(&vals).begin(), as_json(&vals).end());
336    });
337}
338
339std::string common_json::dump(int indent) const {
340    return guard([&] { return as_json(this).dump(indent); });
341}
342
343std::string common_json::dump_safe(int indent) const {
344    return as_json(this).dump(indent, ' ', false, ordered_json::error_handler_t::replace);
345}
346
347// an array is indexed directly, an object needs a walk from the start
348common_json & common_json::iterator::operator*() const {
349    return guard([&]() -> common_json & {
350        ordered_json & j = as_json(node);
351
352        if (j.is_object()) {
353            return as_common(std::next(j.begin(), idx).value());
354        }
355        if (j.is_array()) {
356            return as_common(j[idx]);
357        }
358
359        // a plain value gives itself once, same as the backing library
360        return *node;
361    });
362}
363
364std::string common_json::iterator::key() const {
365    return guard([&] { return std::next(as_json(node).begin(), idx).key(); });
366}
367
368common_json::iterator common_json::begin() const {
369    return iterator(const_cast<common_json *>(this), 0);
370}
371
372common_json::iterator common_json::end() const {
373    return iterator(const_cast<common_json *>(this), size());
374}
375
376// the keys follow the backing library: the index for an array, "" for a plain value
377common_json::items_view::entry common_json::items_view::iterator::operator*() const {
378    return guard([&]() -> entry {
379        ordered_json & j = as_json(node);
380
381        if (j.is_object()) {
382            auto it = std::next(j.begin(), idx);
383
384            return { it.key(), as_common(it.value()) };
385        }
386        if (j.is_array()) {
387            return { std::to_string(idx), as_common(j[idx]) };
388        }
389
390        return { std::string(), *node };
391    });
392}
393
394common_json::items_view common_json::items() const {
395    return items_view(const_cast<common_json *>(this), size());
396}
397
398// the backing library cannot build a common_json, so this one is just a copy
399template <> common_json common_json::get<common_json>() const {
400    return *this;
401}
402
403// get<T>() is usable only for the types below
404
405#define COMMON_JSON_GET(...) template <> __VA_ARGS__ common_json::get<__VA_ARGS__>() const { return guard([&] { return as_json(this).get<__VA_ARGS__>(); }); }
406
407COMMON_JSON_GET(bool)
408COMMON_JSON_GET(int)
409COMMON_JSON_GET(unsigned int)
410COMMON_JSON_GET(long)
411COMMON_JSON_GET(unsigned long)
412COMMON_JSON_GET(long long)
413COMMON_JSON_GET(unsigned long long)
414COMMON_JSON_GET(float)
415COMMON_JSON_GET(double)
416COMMON_JSON_GET(std::string)
417COMMON_JSON_GET(std::vector<float>)
418COMMON_JSON_GET(std::vector<std::string>)
419COMMON_JSON_GET(std::set<std::string>)
420COMMON_JSON_GET(std::vector<int>)
421COMMON_JSON_GET(std::vector<size_t>)
422COMMON_JSON_GET(std::unordered_map<std::string, size_t>)
423
424#undef COMMON_JSON_GET
425
426// must stay below the get<std::string> specialization
427common_json::operator std::string() const {
428    return get<std::string>();
429}
430
431std::string common_json::value(const std::string & key, const char * def) const {
432    return contains(key) ? at(key).get<std::string>() : std::string(def);
433}