1
0
Fork 0
mirror of https://gitlab.com/niansa/dpplogger.git synced 2025-03-06 20:48:29 +01:00

Initial commmit

This commit is contained in:
niansa/tuxifan 2023-01-07 00:05:43 +01:00
commit a47c1fe551
15 changed files with 1893 additions and 0 deletions

76
.gitignore vendored Normal file
View file

@ -0,0 +1,76 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
CMakeLists.txt.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe
CMakeLists.txt.user*

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "DPP"]
path = DPP
url = https://github.com/brainboxdotcc/DPP.git

14
CMakeLists.txt Normal file
View file

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.5)
project(dpplogger LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(DPP)
add_executable(dpplogger main.cpp)
target_link_libraries(dpplogger PUBLIC dpp sqlite3)
install(TARGETS dpplogger
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

1
DPP Submodule

@ -0,0 +1 @@
Subproject commit 788377d2b4fef949db3debd02d9acaea37344eff

102
main.cpp Normal file
View file

@ -0,0 +1,102 @@
#include "sqlite_modern_cpp/sqlite_modern_cpp.h"
#include <iostream>
#include <dpp/dpp.h>
int main() {
// Initialize Sqlite3
sqlite::database db("log.sqlite3");
// Create tables
{
db << "CREATE TABLE IF NOT EXISTS messages ("
" id TEXT PRIMARY KEY NOT NULL,"
" type INTEGER NOT NULL,"
" channel_id TEXT NOT NULL,"
" author_id TEXT NOT NULL,"
" replied_to_id TEXT,"
" is_deleted INTEGER DEFAULT 0 NOT NULL,"
" is_edited INTEGER DEFAULT 0 NOT NULL,"
" creation_timestamp TEXT NOT NULL,"
" update_timestamp TEXT DEFAULT '0' NOT NULL,"
" UNIQUE(id)"
");";
db << "CREATE TABLE IF NOT EXISTS message_contents ("
" message_id TEXT NOT NULL,"
" is_initial INTEGER DEFAULT 1 NOT NULL,"
" timestamp TEXT NOT NULL,"
" content TEXT NOT NULL"
");";
db << "CREATE TABLE IF NOT EXISTS users ("
" id TEXT NOT NULL,"
" is_initial INTEGER DEFAULT 1 NOT NULL,"
" timestamp TEXT NOT NULL,"
" full_username TEXT NOT NULL," // Username#Discriminator
" avatar TEXT,"
" bio TEXT,"
" has_nitro INTEGER NOT NULL,"
" is_bot INTEGER NOT NULL"
");";
db << "CREATE TABLE IF NOT EXISTS user_statuses ("
" user_id TEXT NOT NULL,"
" is_initial INTEGER DEFAULT 1 NOT NULL,"
" timestamp TEXT NOT NULL,"
" status TEXT," // JSON array or null if not updated: [int:online/dnd/afk/offline enum, ?:emoji (null/empty if none), string:text (empty if none)]
" presence TEXT" // Discord JSON presence object
");";
db << "CREATE TABLE IF NOT EXISTS members ("
" user_id TEXT NOT NULL,"
" guild_id TEXT NOT NULL,"
" is_initial INTEGER DEFAULT 1 NOT NULL,"
" timestamp TEXT NOT NULL,"
" nickname TEXT,"
" in_guild INTEGER NOT NULL,"
" is_untracked INTEGER NOT NULL"
");";
db << "CREATE TABLE IF NOT EXISTS member_voice_connections ("
" channel_id TEXT NOT NULL,"
" user_id TEXT NOT NULL,"
" is_initial INTEGER DEFAULT 1 NOT NULL,"
" timestamp TEXT NOT NULL,"
" voice_channel_id TEXT,"
" self_muted INTEGER NOT NULL,"
" self_deafened INTEGER NOT NULL,"
" server_muted INTEGER NOT NULL,"
" server_deafened INTEGER NOT NULL"
");";
db << "CREATE TABLE IF NOT EXISTS channels ("
" id TEXT NOT NULL,"
" guild_id TEXT NOT NULL,"
" category_channel_id TEXT NOT NULL,"
" timestamp TEXT NOT NULL,"
" is_initial INTEGER DEFAULT 1 NOT NULL,"
" type INTEGER NOT NULL,"
" name TEXT NOT NULL,"
" topic TEXT,"
" has_access INTEGER NOT NULL"
");";
db << "CREATE TABLE IF NOT EXISTS guilds ("
" id TEXT NOT NULL,"
" timestamp TEXT NOT NULL,"
" is_initial INTEGER DEFAULT 1 NOT NULL,"
" name TEXT NOT NULL,"
" icon TEXT,"
" owner_user_id TEXT NOT NULL"
");";
}
// Initialize bot
dpp::cluster cluster("token", dpp::i_all_intents);
// Set up callbacks
// Useful: https://discord.com/developers/docs/topics/gateway-events
cluster.on_guild_create([&](const dpp::guild_create_t& event) {
});
cluster.on_message_create([&](const dpp::message_create_t& event) {
});
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 aminroosta
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
#pragma once
#include <string>
#include <stdexcept>
#include <sqlite3.h>
namespace sqlite {
class sqlite_exception: public std::runtime_error {
public:
sqlite_exception(const char* msg, std::string sql, int code = -1): runtime_error(msg), code(code), sql(sql) {}
sqlite_exception(int code, std::string sql): runtime_error(sqlite3_errstr(code)), code(code), sql(sql) {}
int get_code() const {return code & 0xFF;}
int get_extended_code() const {return code;}
std::string get_sql() const {return sql;}
private:
int code;
std::string sql;
};
namespace errors {
//One more or less trivial derived error class for each SQLITE error.
//Note the following are not errors so have no classes:
//SQLITE_OK, SQLITE_NOTICE, SQLITE_WARNING, SQLITE_ROW, SQLITE_DONE
//
//Note these names are exact matches to the names of the SQLITE error codes.
#define SQLITE_MODERN_CPP_ERROR_CODE(NAME,name,derived) \
class name: public sqlite_exception { using sqlite_exception::sqlite_exception; };\
derived
#define SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BASE,SUB,base,sub) \
class base ## _ ## sub: public base { using base::base; };
#include "lists/error_codes.h"
#undef SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED
#undef SQLITE_MODERN_CPP_ERROR_CODE
//Some additional errors are here for the C++ interface
class more_rows: public sqlite_exception { using sqlite_exception::sqlite_exception; };
class no_rows: public sqlite_exception { using sqlite_exception::sqlite_exception; };
class more_statements: public sqlite_exception { using sqlite_exception::sqlite_exception; }; // Prepared statements can only contain one statement
class invalid_utf16: public sqlite_exception { using sqlite_exception::sqlite_exception; };
static void throw_sqlite_error(const int& error_code, const std::string &sql = "") {
switch(error_code & 0xFF) {
#define SQLITE_MODERN_CPP_ERROR_CODE(NAME,name,derived) \
case SQLITE_ ## NAME: switch(error_code) { \
derived \
default: throw name(error_code, sql); \
}
#define SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BASE,SUB,base,sub) \
case SQLITE_ ## BASE ## _ ## SUB: throw base ## _ ## sub(error_code, sql);
#include "lists/error_codes.h"
#undef SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED
#undef SQLITE_MODERN_CPP_ERROR_CODE
default: throw sqlite_exception(error_code, sql);
}
}
}
namespace exceptions = errors;
}

View file

@ -0,0 +1,93 @@
#if SQLITE_VERSION_NUMBER < 3010000
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
#endif
SQLITE_MODERN_CPP_ERROR_CODE(ERROR,error,)
SQLITE_MODERN_CPP_ERROR_CODE(INTERNAL,internal,)
SQLITE_MODERN_CPP_ERROR_CODE(PERM,perm,)
SQLITE_MODERN_CPP_ERROR_CODE(ABORT,abort,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(ABORT,ROLLBACK,abort,rollback)
)
SQLITE_MODERN_CPP_ERROR_CODE(BUSY,busy,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BUSY,RECOVERY,busy,recovery)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BUSY,SNAPSHOT,busy,snapshot)
)
SQLITE_MODERN_CPP_ERROR_CODE(LOCKED,locked,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(LOCKED,SHAREDCACHE,locked,sharedcache)
)
SQLITE_MODERN_CPP_ERROR_CODE(NOMEM,nomem,)
SQLITE_MODERN_CPP_ERROR_CODE(READONLY,readonly,)
SQLITE_MODERN_CPP_ERROR_CODE(INTERRUPT,interrupt,)
SQLITE_MODERN_CPP_ERROR_CODE(IOERR,ioerr,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,READ,ioerr,read)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,SHORT_READ,ioerr,short_read)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,WRITE,ioerr,write)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,FSYNC,ioerr,fsync)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,DIR_FSYNC,ioerr,dir_fsync)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,TRUNCATE,ioerr,truncate)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,FSTAT,ioerr,fstat)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,UNLOCK,ioerr,unlock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,RDLOCK,ioerr,rdlock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,DELETE,ioerr,delete)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,BLOCKED,ioerr,blocked)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,NOMEM,ioerr,nomem)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,ACCESS,ioerr,access)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,CHECKRESERVEDLOCK,ioerr,checkreservedlock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,LOCK,ioerr,lock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,CLOSE,ioerr,close)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,DIR_CLOSE,ioerr,dir_close)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,SHMOPEN,ioerr,shmopen)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,SHMSIZE,ioerr,shmsize)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,SHMLOCK,ioerr,shmlock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,SHMMAP,ioerr,shmmap)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,SEEK,ioerr,seek)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,DELETE_NOENT,ioerr,delete_noent)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,MMAP,ioerr,mmap)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,GETTEMPPATH,ioerr,gettemppath)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,CONVPATH,ioerr,convpath)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,VNODE,ioerr,vnode)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR,AUTH,ioerr,auth)
)
SQLITE_MODERN_CPP_ERROR_CODE(CORRUPT,corrupt,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CORRUPT,VTAB,corrupt,vtab)
)
SQLITE_MODERN_CPP_ERROR_CODE(NOTFOUND,notfound,)
SQLITE_MODERN_CPP_ERROR_CODE(FULL,full,)
SQLITE_MODERN_CPP_ERROR_CODE(CANTOPEN,cantopen,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CANTOPEN,NOTEMPDIR,cantopen,notempdir)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CANTOPEN,ISDIR,cantopen,isdir)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CANTOPEN,FULLPATH,cantopen,fullpath)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CANTOPEN,CONVPATH,cantopen,convpath)
)
SQLITE_MODERN_CPP_ERROR_CODE(PROTOCOL,protocol,)
SQLITE_MODERN_CPP_ERROR_CODE(EMPTY,empty,)
SQLITE_MODERN_CPP_ERROR_CODE(SCHEMA,schema,)
SQLITE_MODERN_CPP_ERROR_CODE(TOOBIG,toobig,)
SQLITE_MODERN_CPP_ERROR_CODE(CONSTRAINT,constraint,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,CHECK,constraint,check)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,COMMITHOOK,constraint,commithook)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,FOREIGNKEY,constraint,foreignkey)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,FUNCTION,constraint,function)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,NOTNULL,constraint,notnull)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,PRIMARYKEY,constraint,primarykey)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,TRIGGER,constraint,trigger)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,UNIQUE,constraint,unique)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,VTAB,constraint,vtab)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT,ROWID,constraint,rowid)
)
SQLITE_MODERN_CPP_ERROR_CODE(MISMATCH,mismatch,)
SQLITE_MODERN_CPP_ERROR_CODE(MISUSE,misuse,)
SQLITE_MODERN_CPP_ERROR_CODE(NOLFS,nolfs,)
SQLITE_MODERN_CPP_ERROR_CODE(AUTH,auth,
)
SQLITE_MODERN_CPP_ERROR_CODE(FORMAT,format,)
SQLITE_MODERN_CPP_ERROR_CODE(RANGE,range,)
SQLITE_MODERN_CPP_ERROR_CODE(NOTADB,notadb,)
SQLITE_MODERN_CPP_ERROR_CODE(NOTICE,notice,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(NOTICE,RECOVER_WAL,notice,recover_wal)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(NOTICE,RECOVER_ROLLBACK,notice,recover_rollback)
)
SQLITE_MODERN_CPP_ERROR_CODE(WARNING,warning,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(WARNING,AUTOINDEX,warning,autoindex)
)

View file

@ -0,0 +1,101 @@
#include "errors.h"
#include <sqlite3.h>
#include <utility>
#include <tuple>
#include <type_traits>
namespace sqlite {
namespace detail {
template<class>
using void_t = void;
template<class T, class = void>
struct is_callable : std::false_type {};
template<class Functor, class ...Arguments>
struct is_callable<Functor(Arguments...), void_t<decltype(std::declval<Functor>()(std::declval<Arguments>()...))>> : std::true_type {};
template<class Functor, class ...Functors>
class FunctorOverload: public Functor, public FunctorOverload<Functors...> {
public:
template<class Functor1, class ...Remaining>
FunctorOverload(Functor1 &&functor, Remaining &&... remaining):
Functor(std::forward<Functor1>(functor)),
FunctorOverload<Functors...>(std::forward<Remaining>(remaining)...) {}
using Functor::operator();
using FunctorOverload<Functors...>::operator();
};
template<class Functor>
class FunctorOverload<Functor>: public Functor {
public:
template<class Functor1>
FunctorOverload(Functor1 &&functor):
Functor(std::forward<Functor1>(functor)) {}
using Functor::operator();
};
template<class Functor>
class WrapIntoFunctor: public Functor {
public:
template<class Functor1>
WrapIntoFunctor(Functor1 &&functor):
Functor(std::forward<Functor1>(functor)) {}
using Functor::operator();
};
template<class ReturnType, class ...Arguments>
class WrapIntoFunctor<ReturnType(*)(Arguments...)> {
ReturnType(*ptr)(Arguments...);
public:
WrapIntoFunctor(ReturnType(*ptr)(Arguments...)): ptr(ptr) {}
ReturnType operator()(Arguments... arguments) { return (*ptr)(std::forward<Arguments>(arguments)...); }
};
inline void store_error_log_data_pointer(std::shared_ptr<void> ptr) {
static std::shared_ptr<void> stored;
stored = std::move(ptr);
}
template<class T>
std::shared_ptr<typename std::decay<T>::type> make_shared_inferred(T &&t) {
return std::make_shared<typename std::decay<T>::type>(std::forward<T>(t));
}
}
template<class Handler>
typename std::enable_if<!detail::is_callable<Handler(const sqlite_exception&)>::value>::type
error_log(Handler &&handler);
template<class Handler>
typename std::enable_if<detail::is_callable<Handler(const sqlite_exception&)>::value>::type
error_log(Handler &&handler);
template<class ...Handler>
typename std::enable_if<sizeof...(Handler)>=2>::type
error_log(Handler &&...handler) {
return error_log(detail::FunctorOverload<detail::WrapIntoFunctor<typename std::decay<Handler>::type>...>(std::forward<Handler>(handler)...));
}
template<class Handler>
typename std::enable_if<!detail::is_callable<Handler(const sqlite_exception&)>::value>::type
error_log(Handler &&handler) {
return error_log(std::forward<Handler>(handler), [](const sqlite_exception&) {});
}
template<class Handler>
typename std::enable_if<detail::is_callable<Handler(const sqlite_exception&)>::value>::type
error_log(Handler &&handler) {
auto ptr = detail::make_shared_inferred([handler = std::forward<Handler>(handler)](int error_code, const char *errstr) mutable {
switch(error_code & 0xFF) {
#define SQLITE_MODERN_CPP_ERROR_CODE(NAME,name,derived) \
case SQLITE_ ## NAME: switch(error_code) { \
derived \
default: handler(errors::name(errstr, "", error_code)); \
};break;
#define SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BASE,SUB,base,sub) \
case SQLITE_ ## BASE ## _ ## SUB: \
handler(errors::base ## _ ## sub(errstr, "", error_code)); \
break;
#include "lists/error_codes.h"
#undef SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED
#undef SQLITE_MODERN_CPP_ERROR_CODE
default: handler(sqlite_exception(errstr, "", error_code)); \
}
});
sqlite3_config(SQLITE_CONFIG_LOG, (void(*)(void*,int,const char*))[](void *functor, int error_code, const char *errstr) {
(*static_cast<decltype(ptr.get())>(functor))(error_code, errstr);
}, ptr.get());
detail::store_error_log_data_pointer(std::move(ptr));
}
}

View file

@ -0,0 +1,44 @@
#pragma once
#ifndef SQLITE_HAS_CODEC
#define SQLITE_HAS_CODEC
#endif
#include "../sqlite_modern_cpp.h"
namespace sqlite {
struct sqlcipher_config : public sqlite_config {
std::string key;
};
class sqlcipher_database : public database {
public:
sqlcipher_database(std::string db, const sqlcipher_config &config): database(db, config) {
set_key(config.key);
}
sqlcipher_database(std::u16string db, const sqlcipher_config &config): database(db, config) {
set_key(config.key);
}
void set_key(const std::string &key) {
if(auto ret = sqlite3_key(_db.get(), key.data(), key.size()))
errors::throw_sqlite_error(ret);
}
void set_key(const std::string &key, const std::string &db_name) {
if(auto ret = sqlite3_key_v2(_db.get(), db_name.c_str(), key.data(), key.size()))
errors::throw_sqlite_error(ret);
}
void rekey(const std::string &new_key) {
if(auto ret = sqlite3_rekey(_db.get(), new_key.data(), new_key.size()))
errors::throw_sqlite_error(ret);
}
void rekey(const std::string &new_key, const std::string &db_name) {
if(auto ret = sqlite3_rekey_v2(_db.get(), db_name.c_str(), new_key.data(), new_key.size()))
errors::throw_sqlite_error(ret);
}
};
}

View file

@ -0,0 +1,55 @@
#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);
};
}
}

View file

@ -0,0 +1,27 @@
#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
}
}

View file

@ -0,0 +1,42 @@
#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

View file

@ -0,0 +1,201 @@
#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); */
}
};
}
}