Let's make (git) history!

This commit is contained in:
2018-11-03 17:12:20 +01:00
commit 3bfebfe8a8
212 zmienionych plików z 11970 dodań i 0 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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