Let's make (git) history!
This commit is contained in:
40
database/hdr/sqlite_modern_cpp/utility/function_traits.h
Normal file
40
database/hdr/sqlite_modern_cpp/utility/function_traits.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace sqlite
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
|
||||
template <typename> struct function_traits;
|
||||
|
||||
template <typename Function>
|
||||
struct function_traits : public function_traits<decltype(&std::remove_reference<Function>::type::operator())>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename ClassType, typename ReturnType, typename... Arguments>
|
||||
struct function_traits<ReturnType (ClassType::*)(Arguments...) const> : function_traits<ReturnType (*)(Arguments...)>
|
||||
{
|
||||
};
|
||||
|
||||
/* support the non-const operator ()
|
||||
* this will work with user defined functors */
|
||||
template <typename ClassType, typename ReturnType, typename... Arguments>
|
||||
struct function_traits<ReturnType (ClassType::*)(Arguments...)> : function_traits<ReturnType (*)(Arguments...)>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename ReturnType, typename... Arguments> struct function_traits<ReturnType (*)(Arguments...)>
|
||||
{
|
||||
typedef ReturnType result_type;
|
||||
|
||||
template <std::size_t Index> using argument = typename std::tuple_element<Index, std::tuple<Arguments...>>::type;
|
||||
|
||||
static const std::size_t arity = sizeof...(Arguments);
|
||||
};
|
||||
|
||||
} // namespace utility
|
||||
} // namespace sqlite
|
34
database/hdr/sqlite_modern_cpp/utility/uncaught_exceptions.h
Normal file
34
database/hdr/sqlite_modern_cpp/utility/uncaught_exceptions.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
|
||||
namespace sqlite
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
#ifdef __cpp_lib_uncaught_exceptions
|
||||
class UncaughtExceptionDetector
|
||||
{
|
||||
public:
|
||||
operator bool()
|
||||
{
|
||||
return count != std::uncaught_exceptions();
|
||||
}
|
||||
|
||||
private:
|
||||
int count = std::uncaught_exceptions();
|
||||
};
|
||||
#else
|
||||
class UncaughtExceptionDetector
|
||||
{
|
||||
public:
|
||||
operator bool()
|
||||
{
|
||||
return std::uncaught_exception();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
} // namespace utility
|
||||
} // namespace sqlite
|
45
database/hdr/sqlite_modern_cpp/utility/utf16_utf8.h
Normal file
45
database/hdr/sqlite_modern_cpp/utility/utf16_utf8.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../errors.h"
|
||||
|
||||
namespace sqlite
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
inline std::string utf16_to_utf8(const std::u16string &input)
|
||||
{
|
||||
struct : std::codecvt<char16_t, char, std::mbstate_t>
|
||||
{
|
||||
} codecvt;
|
||||
std::mbstate_t state{};
|
||||
std::string result((std::max)(input.size() * 3 / 2, std::size_t(4)), '\0');
|
||||
const char16_t *remaining_input = input.data();
|
||||
std::size_t produced_output = 0;
|
||||
while(true)
|
||||
{
|
||||
char *used_output;
|
||||
switch(codecvt.out(state, remaining_input, &input[input.size()], remaining_input, &result[produced_output],
|
||||
&result[result.size() - 1] + 1, used_output))
|
||||
{
|
||||
case std::codecvt_base::ok:
|
||||
result.resize(used_output - result.data());
|
||||
return result;
|
||||
case std::codecvt_base::noconv:
|
||||
// This should be unreachable
|
||||
case std::codecvt_base::error:
|
||||
throw errors::invalid_utf16("Invalid UTF-16 input", "");
|
||||
case std::codecvt_base::partial:
|
||||
if(used_output == result.data() + produced_output)
|
||||
throw errors::invalid_utf16("Unexpected end of input", "");
|
||||
produced_output = used_output - result.data();
|
||||
result.resize(result.size() +
|
||||
(std::max)((&input[input.size()] - remaining_input) * 3 / 2, std::ptrdiff_t(4)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace utility
|
||||
} // namespace sqlite
|
230
database/hdr/sqlite_modern_cpp/utility/variant.h
Normal file
230
database/hdr/sqlite_modern_cpp/utility/variant.h
Normal file
@ -0,0 +1,230 @@
|
||||
#pragma once
|
||||
|
||||
#include "../errors.h"
|
||||
#include <sqlite3.h>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
namespace sqlite::utility
|
||||
{
|
||||
template <typename... Options> struct VariantFirstNullable
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename T, typename... Options> struct VariantFirstNullable<T, Options...>
|
||||
{
|
||||
using type = typename VariantFirstNullable<Options...>::type;
|
||||
};
|
||||
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
|
||||
template <typename T, typename... Options> struct VariantFirstNullable<std::optional<T>, Options...>
|
||||
{
|
||||
using type = std::optional<T>;
|
||||
};
|
||||
#endif
|
||||
template <typename T, typename... Options> struct VariantFirstNullable<std::unique_ptr<T>, Options...>
|
||||
{
|
||||
using type = std::unique_ptr<T>;
|
||||
};
|
||||
template <typename... Options> struct VariantFirstNullable<std::nullptr_t, Options...>
|
||||
{
|
||||
using type = std::nullptr_t;
|
||||
};
|
||||
template <typename Callback, typename... Options> inline void variant_select_null(Callback &&callback)
|
||||
{
|
||||
if constexpr(std::is_same_v<typename VariantFirstNullable<Options...>::type, void>)
|
||||
{
|
||||
throw errors::mismatch("NULL is unsupported by this variant.", "", SQLITE_MISMATCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::forward<Callback>(callback)(typename VariantFirstNullable<Options...>::type());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Options> struct VariantFirstIntegerable
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename T, typename... Options> struct VariantFirstIntegerable<T, Options...>
|
||||
{
|
||||
using type = typename VariantFirstIntegerable<Options...>::type;
|
||||
};
|
||||
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
|
||||
template <typename T, typename... Options> struct VariantFirstIntegerable<std::optional<T>, Options...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_same_v<typename VariantFirstIntegerable<T, Options...>::type, T>,
|
||||
std::optional<T>, typename VariantFirstIntegerable<Options...>::type>;
|
||||
};
|
||||
#endif
|
||||
template <typename T, typename... Options>
|
||||
struct VariantFirstIntegerable<
|
||||
std::enable_if_t<std::is_same_v<typename VariantFirstIntegerable<T, Options...>::type, T>>, std::unique_ptr<T>,
|
||||
Options...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_same_v<typename VariantFirstIntegerable<T, Options...>::type, T>,
|
||||
std::unique_ptr<T>, typename VariantFirstIntegerable<Options...>::type>;
|
||||
};
|
||||
template <typename... Options> struct VariantFirstIntegerable<int, Options...>
|
||||
{
|
||||
using type = int;
|
||||
};
|
||||
template <typename... Options> struct VariantFirstIntegerable<sqlite_int64, Options...>
|
||||
{
|
||||
using type = sqlite_int64;
|
||||
};
|
||||
template <typename Callback, typename... Options> inline auto variant_select_integer(Callback &&callback)
|
||||
{
|
||||
if constexpr(std::is_same_v<typename VariantFirstIntegerable<Options...>::type, void>)
|
||||
{
|
||||
throw errors::mismatch("Integer is unsupported by this variant.", "", SQLITE_MISMATCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::forward<Callback>(callback)(typename VariantFirstIntegerable<Options...>::type());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Options> struct VariantFirstFloatable
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename T, typename... Options> struct VariantFirstFloatable<T, Options...>
|
||||
{
|
||||
using type = typename VariantFirstFloatable<Options...>::type;
|
||||
};
|
||||
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
|
||||
template <typename T, typename... Options> struct VariantFirstFloatable<std::optional<T>, Options...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_same_v<typename VariantFirstFloatable<T, Options...>::type, T>,
|
||||
std::optional<T>, typename VariantFirstFloatable<Options...>::type>;
|
||||
};
|
||||
#endif
|
||||
template <typename T, typename... Options> struct VariantFirstFloatable<std::unique_ptr<T>, Options...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_same_v<typename VariantFirstFloatable<T, Options...>::type, T>,
|
||||
std::unique_ptr<T>, typename VariantFirstFloatable<Options...>::type>;
|
||||
};
|
||||
template <typename... Options> struct VariantFirstFloatable<float, Options...>
|
||||
{
|
||||
using type = float;
|
||||
};
|
||||
template <typename... Options> struct VariantFirstFloatable<double, Options...>
|
||||
{
|
||||
using type = double;
|
||||
};
|
||||
template <typename Callback, typename... Options> inline auto variant_select_float(Callback &&callback)
|
||||
{
|
||||
if constexpr(std::is_same_v<typename VariantFirstFloatable<Options...>::type, void>)
|
||||
{
|
||||
throw errors::mismatch("Real is unsupported by this variant.", "", SQLITE_MISMATCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::forward<Callback>(callback)(typename VariantFirstFloatable<Options...>::type());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Options> struct VariantFirstTextable
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename T, typename... Options> struct VariantFirstTextable<T, Options...>
|
||||
{
|
||||
using type = typename VariantFirstTextable<void, Options...>::type;
|
||||
};
|
||||
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
|
||||
template <typename T, typename... Options> struct VariantFirstTextable<std::optional<T>, Options...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_same_v<typename VariantFirstTextable<T, Options...>::type, T>,
|
||||
std::optional<T>, typename VariantFirstTextable<Options...>::type>;
|
||||
};
|
||||
#endif
|
||||
template <typename T, typename... Options> struct VariantFirstTextable<std::unique_ptr<T>, Options...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_same_v<typename VariantFirstTextable<T, Options...>::type, T>,
|
||||
std::unique_ptr<T>, typename VariantFirstTextable<Options...>::type>;
|
||||
};
|
||||
template <typename... Options> struct VariantFirstTextable<std::string, Options...>
|
||||
{
|
||||
using type = std::string;
|
||||
};
|
||||
template <typename... Options> struct VariantFirstTextable<std::u16string, Options...>
|
||||
{
|
||||
using type = std::u16string;
|
||||
};
|
||||
template <typename Callback, typename... Options> inline void variant_select_text(Callback &&callback)
|
||||
{
|
||||
if constexpr(std::is_same_v<typename VariantFirstTextable<Options...>::type, void>)
|
||||
{
|
||||
throw errors::mismatch("Text is unsupported by this variant.", "", SQLITE_MISMATCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::forward<Callback>(callback)(typename VariantFirstTextable<Options...>::type());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Options> struct VariantFirstBlobable
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename T, typename... Options> struct VariantFirstBlobable<T, Options...>
|
||||
{
|
||||
using type = typename VariantFirstBlobable<Options...>::type;
|
||||
};
|
||||
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
|
||||
template <typename T, typename... Options> struct VariantFirstBlobable<std::optional<T>, Options...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_same_v<typename VariantFirstBlobable<T, Options...>::type, T>,
|
||||
std::optional<T>, typename VariantFirstBlobable<Options...>::type>;
|
||||
};
|
||||
#endif
|
||||
template <typename T, typename... Options> struct VariantFirstBlobable<std::unique_ptr<T>, Options...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_same_v<typename VariantFirstBlobable<T, Options...>::type, T>,
|
||||
std::unique_ptr<T>, typename VariantFirstBlobable<Options...>::type>;
|
||||
};
|
||||
template <typename T, typename A, typename... Options>
|
||||
struct VariantFirstBlobable<std::enable_if_t<std::is_pod_v<T>>, std::vector<T, A>, Options...>
|
||||
{
|
||||
using type = std::vector<T, A>;
|
||||
};
|
||||
template <typename Callback, typename... Options> inline auto variant_select_blob(Callback &&callback)
|
||||
{
|
||||
if constexpr(std::is_same_v<typename VariantFirstBlobable<Options...>::type, void>)
|
||||
{
|
||||
throw errors::mismatch("Blob is unsupported by this variant.", "", SQLITE_MISMATCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::forward<Callback>(callback)(typename VariantFirstBlobable<Options...>::type());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Options> inline auto variant_select(int type)
|
||||
{
|
||||
return [type](auto &&callback) {
|
||||
using Callback = decltype(callback);
|
||||
switch(type)
|
||||
{
|
||||
case SQLITE_NULL:
|
||||
variant_select_null<Callback, Options...>(std::forward<Callback>(callback));
|
||||
break;
|
||||
case SQLITE_INTEGER:
|
||||
variant_select_integer<Callback, Options...>(std::forward<Callback>(callback));
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
variant_select_float<Callback, Options...>(std::forward<Callback>(callback));
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
variant_select_text<Callback, Options...>(std::forward<Callback>(callback));
|
||||
break;
|
||||
case SQLITE_BLOB:
|
||||
variant_select_blob<Callback, Options...>(std::forward<Callback>(callback));
|
||||
break;
|
||||
default:;
|
||||
/* assert(false); */
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace sqlite::utility
|
Reference in New Issue
Block a user