From efcea3a80da7c4479d5fe168435ecc9fd06bdc72 Mon Sep 17 00:00:00 2001 From: John Turner Date: Sun, 14 Sep 2025 00:16:10 -0400 Subject: Squashed 'subprojects/boost-sqlite/' content from commit 3378e35 git-subtree-dir: subprojects/boost-sqlite git-subtree-split: 3378e353705271e569cf4ba15c467b840a39798c --- include/boost/sqlite/json.hpp | 140 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 include/boost/sqlite/json.hpp (limited to 'include/boost/sqlite/json.hpp') diff --git a/include/boost/sqlite/json.hpp b/include/boost/sqlite/json.hpp new file mode 100644 index 0000000..3409e56 --- /dev/null +++ b/include/boost/sqlite/json.hpp @@ -0,0 +1,140 @@ +// +// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_SQLITE_JSON_HPP +#define BOOST_SQLITE_JSON_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +BOOST_SQLITE_BEGIN_NAMESPACE + +struct resultset; +struct field; +struct value; + +/// @brief The subtype value used by the sqlite json extension. See the [sqlite reference](https://www.sqlite.org/json1.html) +constexpr int json_subtype = static_cast('J'); + +inline void tag_invoke(const struct set_result_tag &, sqlite3_context * ctx, const json::value & value) +{ + json::serializer ser; + ser.reset(&value); + + sqlite3_int64 len = 4096; + unique_ptr c{static_cast(sqlite3_malloc64(len))}; + + len = sqlite3_msize(c.get()); + auto v = ser.read(c.get(), len); + + while (!ser.done()) + { + auto l = v.size(); + len *= 2; + c.reset(static_cast(sqlite3_realloc(c.release(), len))); + v = ser.read(c.get() + l, len); + } + + sqlite3_result_text(ctx, c.release(), v.size(), sqlite3_free); + sqlite3_result_subtype(ctx, json_subtype); +} + +///@{ +/// @brief Check if the value or field is a json. @ingroup reference +inline bool is_json(const value & v) { return v.type() == value_type::text && v.subtype() == json_subtype; } +inline bool is_json(const field & f) { return f.type() == value_type::text && f.get_value().subtype() == json_subtype; } +///@} + +///@{ +/// @brief Convert the value or field to a json. @ingroup reference +inline json::value as_json(const value & v, json::storage_ptr ptr = {}) +{ + return json::parse(v.get_text(), ptr); +} +inline json::value as_json(const field & f, json::storage_ptr ptr = {}) +{ + return json::parse(f.get_text(), ptr); +} +///@} + + +inline void tag_invoke( const json::value_from_tag &, json::value& val, const value & f) +{ + switch (f.type()) + { + case value_type::integer: + val.emplace_int64() = f.get_int(); + break; + case value_type::floating: + val.emplace_double() = f.get_double(); + break; + case value_type::text: + { + auto txt = f.get_text(); + if (f.subtype() == json_subtype) + val = json::parse(txt, val.storage()); + else + val.emplace_string() = txt; + } + break; + case value_type::blob: + throw_exception(std::invalid_argument("cannot convert blob to json")); + case value_type::null: + default: + val.emplace_null(); + } +} + +inline void tag_invoke( const json::value_from_tag &, json::value& val, const field & f) +{ + switch (f.type()) + { + case value_type::integer: + val.emplace_int64() = f.get_int(); + break; + case value_type::floating: + val.emplace_double() = f.get_double(); + break; + case value_type::text: + { + auto txt = f.get_text(); + if (f.get_value().subtype() == json_subtype) + val = json::parse(txt, val.storage()); + else + val.emplace_string() = txt; + } + break; + case value_type::blob: + throw_exception(std::invalid_argument("cannot convert blob to json")); + case value_type::null: + default: + val.emplace_null(); + } +} + +inline void tag_invoke( const json::value_from_tag &, json::value& val, resultset && rs) +{ + auto & obj = val.emplace_array(); + + for (auto r : rs) + { + auto & row = obj.emplace_back(json::object(obj.storage())).get_object(); + for (auto c : r) + row[c.column_name()] = json::value_from(c, row.storage()); + } +} + +BOOST_SQLITE_END_NAMESPACE + + +#endif //BOOST_SQLITE_JSON_HPP -- cgit v1.2.3