initial matador ng commit
This commit is contained in:
@@ -1,19 +1,22 @@
|
||||
#ifndef QUERY_ACCESS_HPP
|
||||
#define QUERY_ACCESS_HPP
|
||||
#ifndef OOS_ACCESS_HPP
|
||||
#define OOS_ACCESS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace matador::utils {
|
||||
namespace matador {
|
||||
|
||||
enum class cascade_type;
|
||||
|
||||
template < class Type, template < class ... > class ContainerType >
|
||||
class container;
|
||||
|
||||
namespace utils {
|
||||
class field_attributes;
|
||||
class foreign_attributes;
|
||||
}
|
||||
|
||||
namespace access {
|
||||
|
||||
template<class Operator, class Type>
|
||||
void process(Operator &op, Type &object) {
|
||||
object.process(op);
|
||||
@@ -40,12 +43,12 @@ void revision(Operator &op, const char *id, unsigned long long &value) {
|
||||
}
|
||||
|
||||
template<class Operator, class Type>
|
||||
void attribute(Operator &op, const char *id, Type &value, const field_attributes &attr) {
|
||||
void attribute(Operator &op, const char *id, Type &value, const utils::field_attributes &attr) {
|
||||
op.on_attribute(id, value, attr);
|
||||
}
|
||||
|
||||
template<class Operator, class Type>
|
||||
void attribute(Operator &op, const char *id, std::optional<Type> &value, const field_attributes &attr) {
|
||||
void attribute(Operator &op, const char *id, std::optional<Type> &value, const utils::field_attributes &attr) {
|
||||
op.on_attribute(id, value, attr);
|
||||
}
|
||||
|
||||
@@ -55,32 +58,67 @@ void attribute(Operator &op, const char *id, Type &value) {
|
||||
}
|
||||
|
||||
template<class Operator, class Type>
|
||||
void has_one(Operator &op, const char *id, Type &value, const foreign_attributes &attr) {
|
||||
void has_one(Operator &op, const char *id, Type &value, const utils::foreign_attributes &attr) {
|
||||
op.on_has_one(id, value, attr);
|
||||
}
|
||||
|
||||
template<class Operator, class Type>
|
||||
void belongs_to(Operator &op, const char *id, Type &value, const foreign_attributes &attr) {
|
||||
void has_one(Operator &op, const char *id, Type &value) {
|
||||
op.on_has_one(id, value);
|
||||
}
|
||||
|
||||
template<class Operator, class Type>
|
||||
void belongs_to(Operator &op, const char *id, Type &value, const utils::foreign_attributes &attr) {
|
||||
op.on_belongs_to(id, value, attr);
|
||||
}
|
||||
|
||||
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||
void has_many(Operator &op, ContainerType<Type> &container, const char *join_column, const foreign_attributes &attr) {
|
||||
op.on_has_many(container, join_column, attr);
|
||||
template<class Operator, class Type>
|
||||
void belongs_to(Operator &op, const char *id, Type &value) {
|
||||
op.on_belongs_to(id, value);
|
||||
}
|
||||
|
||||
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||
void has_many_to_many(Operator &op, const char *id, ContainerType<Type> &container, const char *join_column, const char *inverse_join_column, const foreign_attributes &attr) {
|
||||
op.on_has_many_to_many(id, container, join_column, inverse_join_column, attr);
|
||||
void has_many(Operator &op, const char *id, container<Type, ContainerType> &c, const char *join_column, const utils::foreign_attributes &attr) {
|
||||
op.on_has_many(id, c, join_column, attr);
|
||||
}
|
||||
|
||||
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||
void has_many_to_many(Operator &op, const char *id, ContainerType<Type> &container, const foreign_attributes &attr) {
|
||||
op.on_has_many_to_many(id, container, attr);
|
||||
void has_many(Operator &op, const char *id, container<Type, ContainerType> &c, const char *join_column) {
|
||||
op.on_has_many(id, c, join_column);
|
||||
}
|
||||
|
||||
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||
void has_many(Operator &op, const char *id, container<Type, ContainerType> &c, const utils::foreign_attributes &attr) {
|
||||
op.on_has_many(id, c, attr);
|
||||
}
|
||||
|
||||
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||
void has_many(Operator &op, const char *id, container<Type, ContainerType> &c) {
|
||||
op.on_has_many(id, c);
|
||||
}
|
||||
|
||||
template<class Operator, class ContainerType>
|
||||
void has_many_to_many(Operator &op, const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &attr) {
|
||||
op.on_has_many_to_many(id, c, join_column, inverse_join_column, attr);
|
||||
}
|
||||
|
||||
template<class Operator, class ContainerType>
|
||||
void has_many_to_many(Operator &op, const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column) {
|
||||
op.on_has_many_to_many(id, c, join_column, inverse_join_column);
|
||||
}
|
||||
|
||||
template<class Operator, class ContainerType>
|
||||
void has_many_to_many(Operator &op, const char *id, ContainerType &c, const utils::foreign_attributes &attr) {
|
||||
op.on_has_many_to_many(id, c, attr);
|
||||
}
|
||||
|
||||
template<class Operator, class ContainerType>
|
||||
void has_many_to_many(Operator &op, const char *id, ContainerType &c) {
|
||||
op.on_has_many_to_many(id, c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_ACCESS_HPP
|
||||
#endif //OOS_ACCESS_HPP
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef MATADOR_ATTRIBUTE_READER_HPP
|
||||
#define MATADOR_ATTRIBUTE_READER_HPP
|
||||
|
||||
#include "matador/utils/types.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
namespace matador {
|
||||
class date;
|
||||
class time;
|
||||
}
|
||||
namespace matador::utils {
|
||||
|
||||
class value;
|
||||
|
||||
class attribute_reader
|
||||
{
|
||||
public:
|
||||
virtual ~attribute_reader() = default;
|
||||
|
||||
virtual void read_value(const char *id, size_t index, int8_t &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, int16_t &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, int32_t &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, int64_t &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, uint8_t &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, uint16_t &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, uint32_t &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, uint64_t &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, bool &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, float &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, double &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, time &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, date &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, char *value, size_t size) = 0;
|
||||
virtual void read_value(const char *id, size_t index, std::string &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, std::string &value, size_t size) = 0;
|
||||
virtual void read_value(const char *id, size_t index, blob &value) = 0;
|
||||
virtual void read_value(const char *id, size_t index, value &value, size_t size) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //MATADOR_ATTRIBUTE_READER_HPP
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef MATADOR_ATTRIBUTE_BINDER_HPP
|
||||
#define MATADOR_ATTRIBUTE_BINDER_HPP
|
||||
|
||||
#include "matador/utils/types.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace matador {
|
||||
class date;
|
||||
class time;
|
||||
}
|
||||
namespace matador::utils {
|
||||
|
||||
class value;
|
||||
|
||||
class attribute_writer
|
||||
{
|
||||
public:
|
||||
virtual ~attribute_writer() = default;
|
||||
|
||||
virtual void write_value(size_t pos, const int8_t &x) = 0;
|
||||
virtual void write_value(size_t pos, const int16_t &x) = 0;
|
||||
virtual void write_value(size_t pos, const int32_t &x) = 0;
|
||||
virtual void write_value(size_t pos, const int64_t &x) = 0;
|
||||
virtual void write_value(size_t pos, const uint8_t &x) = 0;
|
||||
virtual void write_value(size_t pos, const uint16_t &x) = 0;
|
||||
virtual void write_value(size_t pos, const uint32_t &x) = 0;
|
||||
virtual void write_value(size_t pos, const uint64_t &x) = 0;
|
||||
virtual void write_value(size_t pos, const bool &x) = 0;
|
||||
virtual void write_value(size_t pos, const float &x) = 0;
|
||||
virtual void write_value(size_t pos, const double &x) = 0;
|
||||
virtual void write_value(size_t pos, const time &x) = 0;
|
||||
virtual void write_value(size_t pos, const date &x) = 0;
|
||||
virtual void write_value(size_t pos, const char *x) = 0;
|
||||
virtual void write_value(size_t pos, const char *x, size_t size) = 0;
|
||||
virtual void write_value(size_t pos, const std::string &x) = 0;
|
||||
virtual void write_value(size_t pos, const std::string &x, size_t size) = 0;
|
||||
virtual void write_value(size_t pos, const blob &x) = 0;
|
||||
virtual void write_value(size_t pos, const value &x, size_t size) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //MATADOR_ATTRIBUTE_BINDER_HPP
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef BASE_CLASS_HPP
|
||||
#define BASE_CLASS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace matador {
|
||||
|
||||
/**
|
||||
* @brief Safely casts a given derived class to its base class
|
||||
*
|
||||
* @tparam B The base class type
|
||||
* @tparam D The class type of the derived class
|
||||
* @param derived The derived object
|
||||
* @return The casted object
|
||||
*/
|
||||
template < class B, class D>
|
||||
const B* base_class(const D *derived)
|
||||
{
|
||||
static_assert(!std::is_same_v<B, D>, "class B must not be of same type as class D");
|
||||
static_assert(std::is_base_of_v<B, D>, "class B must be base of class D");
|
||||
return static_cast<const B*>(derived);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Safely casts a given derived class to its base class
|
||||
*
|
||||
* @tparam B The base class type
|
||||
* @tparam D The class type of the derived class
|
||||
* @param derived The derived object
|
||||
* @return The casted object
|
||||
*/
|
||||
template < class B, class D>
|
||||
B* base_class(D *derived)
|
||||
{
|
||||
static_assert(!std::is_same_v<B, D>, "class B must not be of same type as class D");
|
||||
static_assert(std::is_base_of_v<B, D>, "class B must be base of class D");
|
||||
return static_cast<B*>(derived);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* BASE_CLASS_HPP */
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef QUERY_ANY_TYPE_TO_VISITOR_HPP
|
||||
#define QUERY_ANY_TYPE_TO_VISITOR_HPP
|
||||
|
||||
#include "matador/utils/convert.hpp"
|
||||
|
||||
#include <cstdbool>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// namespace matador {
|
||||
//class date;
|
||||
//class time;
|
||||
//}
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
template < typename Type >
|
||||
class basic_type_converter {
|
||||
public:
|
||||
static result<Type, conversion_error> convert_value(const database_type& from) {
|
||||
basic_type_converter converter;
|
||||
std::visit(converter, const_cast<database_type&>(from));
|
||||
|
||||
return converter.result_;
|
||||
}
|
||||
|
||||
void operator()(int8_t &x) { this->convert(x); }
|
||||
void operator()(int16_t &x) { this->convert(x); }
|
||||
void operator()(int32_t &x) { this->convert(x); }
|
||||
void operator()(int64_t &x) { this->convert(x); }
|
||||
void operator()(uint8_t &x) { this->convert(x); }
|
||||
void operator()(uint16_t &x) { this->convert(x); }
|
||||
void operator()(uint32_t &x) { this->convert(x); }
|
||||
void operator()(uint64_t &x) { this->convert(x); }
|
||||
void operator()(bool &x) { this->convert(x); }
|
||||
void operator()(float &x) { this->convert(x); }
|
||||
void operator()(double &x) { this->convert(x); }
|
||||
void operator()(const char *x) { this->convert(x); }
|
||||
void operator()(std::string &x) { this->convert(x); }
|
||||
// void operator()(date &x) { this->convert(result, x); }
|
||||
// void operator()(time &x) { this->convert(result, x); }
|
||||
void operator()(blob &x) { this->convert(x); }
|
||||
|
||||
private:
|
||||
result<Type, conversion_error> result_{};
|
||||
|
||||
template< typename FromType >
|
||||
void convert(FromType &from) {
|
||||
result_ = utils::to<Type>(from);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_ANY_TYPE_TO_VISITOR_HPP
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef BASIC_TYPES_HPP
|
||||
#define BASIC_TYPES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
/**
|
||||
* @brief Enumeration type of all supported basic data types
|
||||
*/
|
||||
enum class basic_type : uint8_t {
|
||||
type_int8 = 0, /*!< Data type int8 */
|
||||
type_int16, /*!< Data type int16 */
|
||||
type_int32, /*!< Data type int32 */
|
||||
type_int64, /*!< Data type int64 */
|
||||
type_uint8, /*!< Data type unsigned int8 */
|
||||
type_uint16, /*!< Data type unsigned int16 */
|
||||
type_uint32, /*!< Data type unsigned int32 */
|
||||
type_uint64, /*!< Data type unsigned int64 */
|
||||
type_float, /*!< Data type float */
|
||||
type_double, /*!< Data type double */
|
||||
type_bool, /*!< Data type bool */
|
||||
type_varchar, /*!< Data type varchar */
|
||||
type_text, /*!< Data type text */
|
||||
type_date, /*!< Data type date */
|
||||
type_time, /*!< Data type time */
|
||||
type_blob, /*!< Data type blob */
|
||||
type_null /*!< Data type null */
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //BASIC_TYPES_HPP
|
||||
@@ -1,14 +1,12 @@
|
||||
#ifndef QUERY_CASCADE_TYPE_HPP
|
||||
#define QUERY_CASCADE_TYPE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#ifndef OOS_CASCADE_TYPE_HPP
|
||||
#define OOS_CASCADE_TYPE_HPP
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
/**
|
||||
* @brief Cascade types for database actions
|
||||
*/
|
||||
enum class cascade_type : uint8_t
|
||||
enum class cascade_type
|
||||
{
|
||||
NONE = 0, /**< Cascade type none */
|
||||
REMOVE = 1, /**< Cascade type remove */
|
||||
@@ -26,5 +24,4 @@ inline cascade_type& operator&= (cascade_type& a, cascade_type b) { return (casc
|
||||
inline cascade_type& operator^= (cascade_type& a, cascade_type b) { return (cascade_type&)((int&)a ^= (int)b); }
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_CASCADE_TYPE_HPP
|
||||
#endif //OOS_CASCADE_TYPE_HPP
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
#ifndef QUERY_CONSTRAINTS_HPP
|
||||
#define QUERY_CONSTRAINTS_HPP
|
||||
#ifndef MATADOR_CONSTRAINTS_HPP
|
||||
#define MATADOR_CONSTRAINTS_HPP
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
enum class constraints : unsigned char {
|
||||
NONE = 0,
|
||||
INDEX = 1 << 1,
|
||||
UNIQUE = 1 << 2,
|
||||
PRIMARY_KEY = 1 << 3,
|
||||
FOREIGN_KEY = 1 << 4,
|
||||
DEFAULT = 1 << 5,
|
||||
AUTO_INCREMENT = 1 << 6
|
||||
NONE = 0,
|
||||
// NOT_NULL = 1 << 0,
|
||||
INDEX = 1 << 1,
|
||||
UNIQUE = 1 << 2,
|
||||
PRIMARY_KEY = 1 << 3,
|
||||
FOREIGN_KEY = 1 << 4,
|
||||
DEFAULT = 1 << 5
|
||||
// UNIQUE_NOT_NULL = UNIQUE | NOT_NULL
|
||||
};
|
||||
|
||||
//static std::unordered_map<constraints, std::string> constraints_to_name_map();
|
||||
|
||||
inline constraints operator|(constraints a, constraints b)
|
||||
{
|
||||
return static_cast<constraints>(static_cast<unsigned int>(a) | static_cast<unsigned int>(b));
|
||||
@@ -34,4 +33,5 @@ inline bool is_constraint_set(constraints source, constraints needle)
|
||||
}
|
||||
|
||||
}
|
||||
#endif //QUERY_CONSTRAINTS_HPP
|
||||
|
||||
#endif //MATADOR_CONSTRAINTS_HPP
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
#ifndef MATADOR_CONVERT_HPP
|
||||
#define MATADOR_CONVERT_HPP
|
||||
|
||||
#include "matador/utils/types.hpp"
|
||||
#include "matador/utils/result.hpp"
|
||||
//#include "matador/utils/date.hpp"
|
||||
//#include "matador/utils/time.hpp"
|
||||
|
||||
//#include "matador/utils/placeholder.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <charconv>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
/*
|
||||
* Conversion matrix
|
||||
* from> | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | bool | float | double | string | date | time | blob | placeholder | null
|
||||
* to | | | | | | | | | | | | | | | | |
|
||||
* ------------+------+-------+-------+-------+-------+--------+--------+--------+------+-------+--------+--------+------+------+------+-------------+-----
|
||||
* int8 | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | ok | ok | try | N/A | N/A
|
||||
* int16 | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | ok | ok | try | N/A | N/A
|
||||
* int32 | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | ok | ok | try | N/A | N/A
|
||||
* int64 | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | ok | ok | try | N/A | N/A
|
||||
* uint8 | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | ok | ok | try | N/A | N/A
|
||||
* uint16 | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | ok | ok | try | N/A | N/A
|
||||
* uint32 | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | ok | ok | try | N/A | N/A
|
||||
* uint64 | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | ok | ok | try | N/A | N/A
|
||||
* bool | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | N/A | N/A | try | N/A | N/A
|
||||
* float | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | N/A | N/A | try | N/A | N/A
|
||||
* double | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | try | N/A | N/A | try | N/A | N/A
|
||||
* string | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | N/A | N/A | N/A
|
||||
* date | ok | ok | ok | ok | ok | ok | ok | ok | N/A | N/A | N/A | try | ok | ok | N/A | N/A | N/A
|
||||
* time | ok | ok | ok | ok | ok | ok | ok | ok | N/A | N/A | N/A | try | ok | ok | N/A | N/A | N/A
|
||||
* blob | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | ok | N/A | N/A
|
||||
* placeholder | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | ok | N/A
|
||||
* null | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | ok
|
||||
*
|
||||
* from integral to date/time works, value is interpreted as std::chrono::timepoint
|
||||
* from integral to blob works, bytes of integral data will converted to blob
|
||||
* from boolean to blob works, byte of bool data will converted to blob
|
||||
* from floating point to blob works, bytes of floating point data will converted to blob
|
||||
* from date to blob works, bytes of date will converted to blob
|
||||
* from time to blob works, bytes of time will converted to blob
|
||||
* from string to blob works, bytes of string data will converted to blob
|
||||
* from floating point to integral works, fractions are truncated
|
||||
* from date/time to integral works, value will be converted from std::chrono::timepoint
|
||||
* from blob to integral works, value will be converted missing is filled with zero, rest is omitted
|
||||
* from blob to floating point works, value will be converted missing is filled with zero, rest is omitted
|
||||
* from blob to boolean works, value will be converted missing is filled with zero, rest is omitted
|
||||
*/
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
enum class conversion_error {
|
||||
Ok,
|
||||
NotConvertable,
|
||||
MissingData
|
||||
};
|
||||
|
||||
enum class conversion_policy {
|
||||
Strict,
|
||||
Relax
|
||||
};
|
||||
|
||||
|
||||
// template < typename DestType, typename SourceType >
|
||||
// result<DestType, conversion_error> to(const SourceType &/*from*/);
|
||||
// result<DestType, conversion_error> to(const SourceType &/*from*/, conversion_policy /*policy*/ = conversion_policy::Strict);
|
||||
|
||||
// {
|
||||
// return failure(conversion_error::NotConvertable);
|
||||
// }
|
||||
|
||||
/*
|
||||
* Integral, Floating point & bool conversion
|
||||
*/
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_arithmetic_v<DestType> && std::is_arithmetic_v<SourceType>>* = nullptr)
|
||||
{
|
||||
return ok(static_cast<DestType>(source));
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_same_v<std::string, DestType> && std::is_same_v<std::string, SourceType>>* = nullptr)
|
||||
{
|
||||
return ok(source);
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_integral_v<SourceType> && !std::is_same_v<bool, SourceType> && std::is_same_v<DestType, std::string>>* = nullptr)
|
||||
{
|
||||
std::array<char, 128> buffer{};
|
||||
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), source, 10);
|
||||
if (ec == std::errc{}) {
|
||||
return ok(std::string(buffer.data(), ptr));
|
||||
}
|
||||
|
||||
// return failure({ec, "couldn't convert value to std::string"});
|
||||
return failure(conversion_error::NotConvertable/*, "couldn't convert value to std::string"}*/);
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_floating_point_v<SourceType> && std::is_same_v<DestType, std::string>>* = nullptr)
|
||||
{
|
||||
std::array<char, 128> buffer{};
|
||||
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), source, std::chars_format::general);
|
||||
if (ec == std::errc{}) {
|
||||
return ok(std::string(buffer.data(), ptr));
|
||||
}
|
||||
|
||||
// return failure({ec, "couldn't convert value to std::string"});
|
||||
return failure(conversion_error::NotConvertable/*, "couldn't convert value to std::string"}*/);
|
||||
}
|
||||
|
||||
template < typename DestType >
|
||||
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_integral_v<DestType> && std::is_signed_v<DestType>>* = nullptr)
|
||||
{
|
||||
if (source.empty()) {
|
||||
return failure(conversion_error::MissingData/*, "failed to convert empty string"}*/);
|
||||
}
|
||||
char *end;
|
||||
errno = 0;
|
||||
const auto result = strtoll(source.c_str(), &end, 10);
|
||||
if (errno == ERANGE) {
|
||||
return failure(conversion_error::NotConvertable/*, "failed to convert string value"}*/);
|
||||
}
|
||||
|
||||
return ok(static_cast<DestType>(result));
|
||||
}
|
||||
|
||||
template < typename DestType >
|
||||
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_integral_v<DestType> && std::is_unsigned_v<DestType>>* = nullptr)
|
||||
{
|
||||
if (source.empty()) {
|
||||
return failure(conversion_error::MissingData/*, "failed to convert empty string"}*/);
|
||||
}
|
||||
char *end;
|
||||
errno = 0;
|
||||
const auto result = strtoull(source.c_str(), &end, 10);
|
||||
if (errno == ERANGE) {
|
||||
return failure(conversion_error::NotConvertable/*, "failed to convert string value"}*/);
|
||||
}
|
||||
|
||||
return ok(static_cast<DestType>(result));
|
||||
}
|
||||
|
||||
template < typename DestType >
|
||||
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_floating_point_v<DestType>>* = nullptr)
|
||||
{
|
||||
if (source.empty()) {
|
||||
return failure(conversion_error::MissingData/*, "failed to convert empty string"}*/);
|
||||
}
|
||||
char *end;
|
||||
errno = 0;
|
||||
const auto result = strtod(source.c_str(), &end);
|
||||
if (errno == ERANGE) {
|
||||
return failure(conversion_error::NotConvertable/*, "failed to convert string value"}*/);
|
||||
}
|
||||
|
||||
return ok(static_cast<DestType>(result));
|
||||
}
|
||||
|
||||
template < typename DestType >
|
||||
result<DestType, conversion_error> to(const blob &source, std::enable_if_t<std::is_same_v<DestType, blob>>* = nullptr) {
|
||||
return ok(source);
|
||||
}
|
||||
|
||||
static std::unordered_map<std::string, bool> string_to_bool_map = {
|
||||
{"true", true},
|
||||
{"on", true},
|
||||
{"1", true},
|
||||
{"false", false},
|
||||
{"off", false},
|
||||
{"0", false}
|
||||
};
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_same_v<SourceType, std::string> &&std::is_same_v<DestType, bool>>* = nullptr) {
|
||||
if (source.empty()) {
|
||||
return failure(conversion_error::MissingData);
|
||||
}
|
||||
const auto it = string_to_bool_map.find(source);
|
||||
if (it == string_to_bool_map.end()) {
|
||||
return failure(conversion_error::NotConvertable);
|
||||
}
|
||||
return ok(it->second);
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_same_v<SourceType, bool> &&std::is_same_v<DestType, std::string>>* = nullptr) {
|
||||
return ok(std::string(source ? "true" : "false"));
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_same_v<SourceType, blob> &&std::is_same_v<DestType, std::string>>* = nullptr) {
|
||||
return failure(conversion_error::NotConvertable);
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_same_v<SourceType, const char*> &&std::is_same_v<DestType, std::string>>* = nullptr) {
|
||||
return ok(std::string(source));
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_arithmetic_v<DestType> && std::is_same_v<SourceType, blob>>* = nullptr) {
|
||||
return failure(conversion_error::NotConvertable);
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_integral_v<SourceType> && std::is_same_v<DestType, blob>>* = nullptr) {
|
||||
DestType result;
|
||||
result.resize(sizeof(source));
|
||||
std::memcpy(result.data(), &source, sizeof(source));
|
||||
|
||||
return ok(result);
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_floating_point_v<SourceType> && std::is_same_v<DestType, blob>>* = nullptr) {
|
||||
return failure(conversion_error::NotConvertable);
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_same_v<SourceType, std::string> && std::is_same_v<DestType, blob>>* = nullptr) {
|
||||
return failure(conversion_error::NotConvertable);
|
||||
}
|
||||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_same_v<SourceType, const char*> && std::is_same_v<DestType, blob>>* = nullptr) {
|
||||
return failure(conversion_error::NotConvertable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //MATADOR_CONVERT_HPP
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef BASIC_TYPE_TRAITS_HPP
|
||||
#define BASIC_TYPE_TRAITS_HPP
|
||||
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
class attribute_reader;
|
||||
class attribute_writer;
|
||||
|
||||
/**
|
||||
* @tparam Type The type of the traits
|
||||
* @brief Type traits for database types
|
||||
*
|
||||
* This class is used to determine and
|
||||
* provide the correct size information
|
||||
* for a data type
|
||||
*/
|
||||
template < class Type, class Enable = void >
|
||||
struct data_type_traits;
|
||||
|
||||
}
|
||||
#endif //BASIC_TYPE_TRAITS_HPP
|
||||
@@ -0,0 +1,168 @@
|
||||
#ifndef MATADOR_DEFAULT_TYPE_TRAITS_HPP
|
||||
#define MATADOR_DEFAULT_TYPE_TRAITS_HPP
|
||||
|
||||
#include "matador/utils/data_type_traits.hpp"
|
||||
#include "matador/utils/types.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
/// @cond MATADOR_DEV
|
||||
template <> struct data_type_traits<nullptr_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/) { return basic_type::type_null; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, nullptr_t &/*value*/);
|
||||
static void bind_value(attribute_writer &binder, size_t index, nullptr_t &/*value*/);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<int8_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_int8; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, int8_t &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const int8_t &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<int16_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_int16; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, int16_t &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const int16_t &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<int32_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_int32; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, int32_t &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const int32_t &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<int64_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_int64; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, int64_t &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const int64_t &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<uint8_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_uint8; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, uint8_t &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const uint8_t &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<uint16_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_uint16; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, uint16_t &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const uint16_t &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<uint32_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_uint32; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, uint32_t &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const uint32_t &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<uint64_t, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_uint64; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, uint64_t &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const uint64_t &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<bool, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_bool; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, bool &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const bool &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<float, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_float; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, float &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const float &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<double, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_double; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, double &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const double &value);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<const char*, void>
|
||||
{
|
||||
static basic_type type(const std::size_t size) { return size == 0 ? basic_type::type_text : basic_type::type_varchar; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, const char* value, size_t size);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const char *value, size_t size = 0);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<char*, void>
|
||||
{
|
||||
static basic_type type(const std::size_t size) { return size == 0 ? basic_type::type_text : basic_type::type_varchar; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, char *value, size_t size);
|
||||
static void bind_value(attribute_writer &binder, size_t index, const char *value, size_t size = 0);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<char[], void>
|
||||
{
|
||||
static basic_type type(const std::size_t size) { return size == 0 ? basic_type::type_text : basic_type::type_varchar; }
|
||||
template < int N >
|
||||
static void read_value(attribute_reader &reader, const char *id, const size_t index, char (&value)[N], const size_t size) {
|
||||
data_type_traits<const char*>::read_value(reader, id, index, value, size);
|
||||
}
|
||||
template < int N >
|
||||
static void bind_value(attribute_writer &binder, const size_t index, char *value, const size_t size = 0) {
|
||||
data_type_traits<const char*>::bind_value(binder, index, value, size);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<std::string, void>
|
||||
{
|
||||
static basic_type type(const std::size_t size) { return size == 0 ? basic_type::type_text : basic_type::type_varchar; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, std::string &value, size_t size);
|
||||
static void bind_value(attribute_writer &binder, size_t index, std::string &value, size_t size = 0);
|
||||
};
|
||||
|
||||
template <> struct data_type_traits<utils::blob, void>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/) { return basic_type::type_blob; }
|
||||
static void read_value(attribute_reader &reader, const char *id, size_t index, utils::blob &value);
|
||||
static void bind_value(attribute_writer &binder, size_t index, utils::blob &value);
|
||||
};
|
||||
|
||||
//template <> struct data_type_traits<matador::date, void>
|
||||
//{
|
||||
// static basic_type type(std::size_t /*size*/) { return basic_type::type_date; }
|
||||
// static void read_value(attribute_reader &reader, const char *id, size_t index, matador::date &value);
|
||||
// static void bind_value(attribute_writer &binder, size_t index, matador::date &value);
|
||||
//};
|
||||
//
|
||||
//template <> struct data_type_traits<matador::time, void>
|
||||
//{
|
||||
// static basic_type type(std::size_t /*size*/) { return basic_type::type_time; }
|
||||
// static void read_value(attribute_reader &reader, const char *id, size_t index, matador::time &value);
|
||||
// static void bind_value(attribute_writer &binder, size_t index, matador::time &value);
|
||||
//};
|
||||
|
||||
template < typename EnumType >
|
||||
struct data_type_traits<EnumType, std::enable_if_t<std::is_enum_v<EnumType>>>
|
||||
{
|
||||
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::type_int32; }
|
||||
static void read_value(attribute_reader &reader, const char *id, const size_t index, EnumType &value)
|
||||
{
|
||||
data_type_traits<int>::read_value(reader, id, index, reinterpret_cast<int&>(value));
|
||||
}
|
||||
static void bind_value(attribute_writer &binder, const size_t index, EnumType &value)
|
||||
{
|
||||
data_type_traits<int>::bind_value(binder, index, static_cast<int &>(value));
|
||||
}
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
}
|
||||
#endif //MATADOR_DEFAULT_TYPE_TRAITS_HPP
|
||||
@@ -0,0 +1,385 @@
|
||||
#ifndef MATADOR_DI_HPP
|
||||
#define MATADOR_DI_HPP
|
||||
|
||||
#include "matador/utils/singleton.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <typeindex>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace matador::utils::di {
|
||||
/**
|
||||
* Interface for the dependency injection
|
||||
* creation strategy.
|
||||
*
|
||||
* The injected service
|
||||
*/
|
||||
class strategy
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~strategy() = default;
|
||||
|
||||
/**
|
||||
* @brief Acquires an instance
|
||||
*
|
||||
* Acquires an instance based on the internal strategy
|
||||
* and returns an anonymous pointer to the object
|
||||
*
|
||||
* @return The current injected object depending on the strategy
|
||||
*/
|
||||
virtual void *acquire() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the transient dependency injection
|
||||
* strategy. When ever injected a new instance
|
||||
* is created.
|
||||
*
|
||||
* @tparam T Type of the object to be injected
|
||||
*/
|
||||
template<class T>
|
||||
class transient_strategy final : public strategy
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new transient strategy object
|
||||
*
|
||||
* @tparam Args Type of arguments for constructor
|
||||
* @param args Arguments for constructor
|
||||
*/
|
||||
template<typename ...Args>
|
||||
explicit transient_strategy(Args &&...args) {
|
||||
creator_ = [args..., this]() {
|
||||
instances_.push_back(std::make_unique<T>(args...));
|
||||
return instances_.back().get();
|
||||
};
|
||||
}
|
||||
|
||||
void *acquire() override {
|
||||
return creator_();
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<T *()> creator_{};
|
||||
std::vector<std::unique_ptr<T>> instances_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements the singleton strategy
|
||||
*
|
||||
* The singleton strategy provides only one
|
||||
* instance of the type.
|
||||
*
|
||||
* @tparam T Type of the object to be injected
|
||||
*/
|
||||
template<class T>
|
||||
class singleton_strategy : public strategy
|
||||
{
|
||||
public:
|
||||
template<typename ...Args>
|
||||
explicit singleton_strategy(Args &&...args) {
|
||||
creator_ = [args..., this]() {
|
||||
if (!instance_) {
|
||||
instance_ = std::make_unique<T>(args...);
|
||||
}
|
||||
return instance_.get();
|
||||
};
|
||||
}
|
||||
|
||||
void *acquire() override {
|
||||
return creator_();
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<T *()> creator_{};
|
||||
std::unique_ptr<T> instance_;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class singleton_per_thread_strategy : public strategy
|
||||
{
|
||||
public:
|
||||
template<typename ...Args>
|
||||
explicit singleton_per_thread_strategy(Args &&...args) {
|
||||
creator_ = [args..., this]() {
|
||||
thread_local auto instance = std::make_unique<T>(args...);
|
||||
std::lock_guard<std::mutex> lock(instance_mutex_);
|
||||
auto it = instance_map_.insert({std::this_thread::get_id(), std::move(instance)}).first;
|
||||
return it->second.get();
|
||||
};
|
||||
}
|
||||
|
||||
void *acquire() override {
|
||||
return creator_();
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<T *()> creator_{};
|
||||
std::mutex instance_mutex_;
|
||||
std::unordered_map<std::thread::id, std::unique_ptr<T>> instance_map_;
|
||||
};
|
||||
/**
|
||||
* @brief Provides a specific instance on injection
|
||||
*
|
||||
* @tparam T
|
||||
*/
|
||||
template<class T>
|
||||
class instance_strategy : public strategy
|
||||
{
|
||||
public:
|
||||
explicit instance_strategy(T &&obj)
|
||||
: instance_(obj) {}
|
||||
|
||||
void* acquire() override {
|
||||
return &instance_;
|
||||
}
|
||||
|
||||
private:
|
||||
T &instance_;
|
||||
};
|
||||
|
||||
class proxy_base
|
||||
{
|
||||
public:
|
||||
virtual ~proxy_base() = default;
|
||||
|
||||
template<typename T>
|
||||
T* get() const {
|
||||
return static_cast<T *>(strategy_->acquire());
|
||||
}
|
||||
|
||||
protected:
|
||||
void initialize_strategy(std::unique_ptr<strategy> &&strategy) {
|
||||
strategy_ = std::move(strategy);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<strategy> strategy_;
|
||||
};
|
||||
|
||||
template<typename I>
|
||||
class proxy : public proxy_base
|
||||
{
|
||||
public:
|
||||
template<typename T, typename ...Args, std::enable_if_t<std::is_base_of_v<I, T>> * = nullptr>
|
||||
void to( Args &&...args) {
|
||||
initialize_strategy(std::make_unique<transient_strategy<T>>(std::forward<Args &&>(args)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void to_instance(T &&obj) {
|
||||
initialize_strategy(std::make_unique<instance_strategy<T>>(obj));
|
||||
}
|
||||
|
||||
template<typename T, typename ...Args, std::enable_if_t<std::is_base_of_v<I, T>> * = nullptr>
|
||||
void to_singleton(Args &&...args) {
|
||||
initialize_strategy(std::make_unique<singleton_strategy<T>>(std::forward<Args &&>(args)...));
|
||||
}
|
||||
|
||||
template<typename T, typename ...Args, std::enable_if_t<std::is_base_of_v<I, T>> * = nullptr>
|
||||
void to_singleton_per_thread(Args &&...args) {
|
||||
initialize_strategy(std::make_unique<singleton_per_thread_strategy<T>>(std::forward<Args &&>(args)...));
|
||||
}
|
||||
};
|
||||
|
||||
class module
|
||||
{
|
||||
private:
|
||||
using t_type_proxy_map = std::unordered_map<std::type_index, std::shared_ptr<proxy_base>>;
|
||||
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
default_map_.clear();
|
||||
module_map_.clear();
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
std::shared_ptr<proxy<I>> bind() {
|
||||
return bind<I>(default_map_);
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
std::shared_ptr<proxy<I>> bind(const std::string &name) {
|
||||
auto i = module_map_.find(name);
|
||||
if (i == module_map_.end()) {
|
||||
i = module_map_.insert(std::make_pair(name, t_type_proxy_map{})).first;
|
||||
}
|
||||
return bind<I>(i->second);
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
I* resolve() {
|
||||
return resolve<I>(default_map_);
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
I* resolve(const std::string &name) {
|
||||
auto i = module_map_.find(name);
|
||||
if (i == module_map_.end()) {
|
||||
throw std::logic_error("unknown name " + name);
|
||||
}
|
||||
return resolve<I>(i->second);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename I>
|
||||
std::shared_ptr<proxy<I>> bind(t_type_proxy_map &type_proxy_map) {
|
||||
auto di_proxy_ptr = std::make_shared<proxy<I>>();
|
||||
auto i = type_proxy_map.insert(std::make_pair(std::type_index(typeid(I)), di_proxy_ptr));
|
||||
return std::static_pointer_cast<proxy<I>>(i.first->second);
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
static I* resolve(t_type_proxy_map &type_proxy_map) {
|
||||
const auto i = type_proxy_map.find(std::type_index(typeid(I)));
|
||||
if (i == type_proxy_map.end()) {
|
||||
throw std::logic_error("unknown type");
|
||||
}
|
||||
return i->second->get<I>();
|
||||
}
|
||||
|
||||
private:
|
||||
t_type_proxy_map default_map_;
|
||||
|
||||
std::unordered_map<std::string, t_type_proxy_map> module_map_ {};
|
||||
};
|
||||
|
||||
class repository : public utils::singleton<repository>
|
||||
{
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
module_.clear();
|
||||
}
|
||||
|
||||
void install(const std::function<void(module&)>& builder)
|
||||
{
|
||||
module_.clear();
|
||||
builder(module_);
|
||||
}
|
||||
|
||||
void append(const std::function<void(module&)>& builder)
|
||||
{
|
||||
builder(module_);
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
I* resolve() {
|
||||
return module_.resolve<I>();
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
I* resolve(const std::string &name) {
|
||||
return module_.resolve<I>(name);
|
||||
}
|
||||
|
||||
private:
|
||||
module module_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Resolves and provides the requested service
|
||||
*
|
||||
* The class inject acts a holder for the
|
||||
* requested service. On construction, it
|
||||
* tries to resolve the given template type
|
||||
* within the global service repository.
|
||||
*
|
||||
* @tparam T Type of the interface
|
||||
*/
|
||||
template<class T>
|
||||
class inject
|
||||
{
|
||||
public:
|
||||
inject()
|
||||
: obj(repository::instance().resolve<T>())
|
||||
{}
|
||||
|
||||
explicit inject(const std::string &name)
|
||||
: obj(repository::instance().resolve<T>(name))
|
||||
{}
|
||||
|
||||
explicit inject(module &m)
|
||||
: obj(m.resolve<T>())
|
||||
{}
|
||||
|
||||
inject(module &m, const std::string &name)
|
||||
: obj(m.resolve<T>(name))
|
||||
{}
|
||||
|
||||
inject(const inject &x) : obj(x.obj) {}
|
||||
|
||||
inject& operator=(const inject &x) {
|
||||
if (this != &x) {
|
||||
obj = x.obj;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inject(inject &&x) noexcept : obj(x.obj) {
|
||||
x.obj = nullptr;
|
||||
}
|
||||
|
||||
inject& operator=(inject &&x) noexcept {
|
||||
obj = x.obj;
|
||||
x.obj = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const inject &x) const {
|
||||
return obj == x.obj;
|
||||
}
|
||||
|
||||
bool operator!=(const inject &x) const {
|
||||
return obj != x.obj;
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
return obj;
|
||||
}
|
||||
|
||||
T* get() const {
|
||||
return obj;
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
return *obj;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return obj != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T* obj;
|
||||
};
|
||||
|
||||
inline void clear_module()
|
||||
{
|
||||
repository::instance().clear();
|
||||
}
|
||||
|
||||
inline void install_module(const std::function<void(module&)>& builder)
|
||||
{
|
||||
repository::instance().clear();
|
||||
repository::instance().install(builder);
|
||||
}
|
||||
|
||||
inline void append_module(const std::function<void(module&)>& builder)
|
||||
{
|
||||
repository::instance().append(builder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //MATADOR_DI_HPP
|
||||
@@ -11,7 +11,7 @@ template < typename EnumType, class Enable = void >
|
||||
class enum_mapper;
|
||||
|
||||
template < typename EnumType>
|
||||
class enum_mapper<EnumType, typename std::enable_if<std::is_enum<EnumType>::value>::type>
|
||||
class enum_mapper<EnumType, std::enable_if_t<std::is_enum_v<EnumType>>>
|
||||
{
|
||||
public:
|
||||
using enum_to_string_map = std::unordered_map<EnumType, std::string>;
|
||||
@@ -33,17 +33,18 @@ public:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string to_string(EnumType enum_value) const {
|
||||
const std::string& to_string(EnumType enum_value) const {
|
||||
if (const auto it = enum_to_string_map_.find(enum_value); it != enum_to_string_map_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return {};
|
||||
return empty_;
|
||||
}
|
||||
|
||||
private:
|
||||
enum_to_string_map enum_to_string_map_;
|
||||
string_to_enum_map string_to_enum_map_;
|
||||
std::string empty_{};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef ERROR_HPP
|
||||
#define ERROR_HPP
|
||||
|
||||
#include "matador/utils/export.hpp"
|
||||
|
||||
#include <system_error>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <ostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
class MATADOR_UTILS_API error final {
|
||||
public:
|
||||
error() = default;
|
||||
template <class ErrorEnumType, std::enable_if_t<std::is_error_code_enum_v<ErrorEnumType>, int> = 0>
|
||||
explicit error(ErrorEnumType err, const std::string& msg = "")
|
||||
: error(err, std::vector<error>{}, msg)
|
||||
{}
|
||||
template <class ErrorEnumType, std::enable_if_t<std::is_error_code_enum_v<ErrorEnumType>, int> = 0>
|
||||
error(ErrorEnumType err, std::vector<error> trace, std::string msg = "")
|
||||
: ec_(make_error_code(err))
|
||||
, error_message_(std::move(msg))
|
||||
, error_trace_(std::move(trace))
|
||||
{}
|
||||
template <class ErrorEnumType, std::enable_if_t<std::is_error_code_enum_v<ErrorEnumType>, int> = 0>
|
||||
error(ErrorEnumType err, error error_trace, const std::string& msg = "")
|
||||
: error(err, std::vector{std::move(error_trace)}, msg)
|
||||
{}
|
||||
template <class ErrorEnumType, std::enable_if_t<std::is_error_code_enum_v<ErrorEnumType>, int> = 0>
|
||||
error(ErrorEnumType err, std::unordered_map<std::string, std::string> infos, std::string msg = "")
|
||||
: ec_(make_error_code(err))
|
||||
, error_message_(std::move(msg))
|
||||
, error_infos_(std::move(infos))
|
||||
{}
|
||||
|
||||
error(const error&) = default;
|
||||
error(error&&) noexcept = default;
|
||||
error& operator=(const error&) = default;
|
||||
error& operator=(error&&) noexcept = default;
|
||||
~error() = default;
|
||||
|
||||
friend bool operator==(const error &lhs, const error &rhs);
|
||||
friend bool operator==(const error &lhs, const std::error_code &rhs);
|
||||
friend bool operator==(const error &lhs, const std::error_condition &rhs);
|
||||
friend bool operator!=(const error &lhs, const error &rhs);
|
||||
friend bool operator!=(const error &lhs, const std::error_code &rhs);
|
||||
friend bool operator!=(const error &lhs, const std::error_condition &rhs);
|
||||
friend bool operator<(const error &lhs, const error &rhs);
|
||||
friend bool operator<(const error &lhs, const std::error_code &rhs);
|
||||
|
||||
// friend std::ostream& operator<<(std::ostream &out, const error &err);
|
||||
|
||||
[[nodiscard]] std::string message() const;
|
||||
[[nodiscard]] std::string category() const;
|
||||
[[nodiscard]] std::error_code ec() const;
|
||||
[[nodiscard]] const std::vector<error>& error_trace() const;
|
||||
[[nodiscard]] std::optional<std::string> error_info(const std::string &key) const;
|
||||
void add_error_info(const std::string &key, std::string value);
|
||||
void remove_error_info(const std::string &key);
|
||||
[[nodiscard]] std::vector<std::string> error_info_keys() const;
|
||||
|
||||
private:
|
||||
std::error_code ec_;
|
||||
std::string error_message_;
|
||||
std::vector<error> error_trace_;
|
||||
std::unordered_map<std::string, std::string> error_infos_;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //ERROR_HPP
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef ERRORS_HPP
|
||||
#define ERRORS_HPP
|
||||
|
||||
#include "matador/utils/export.hpp"
|
||||
|
||||
#include <system_error>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
enum class utils_error {
|
||||
InvalidVersionString,
|
||||
};
|
||||
|
||||
class utils_category_impl final : public std::error_category
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] const char* name() const noexcept override;
|
||||
[[nodiscard]] std::string message(int ev) const override;
|
||||
};
|
||||
|
||||
const std::error_category& utils_category();
|
||||
std::error_code make_error_code(utils_error e);
|
||||
std::error_condition make_error_condition(utils_error e);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct std::is_error_code_enum<matador::utils::utils_error> : true_type {};
|
||||
|
||||
#endif //ERRORS_HPP
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef MATADOR_UTILS_EXPORT_HPP
|
||||
#define MATADOR_UTILS_EXPORT_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define MATADOR_UTILS_API
|
||||
// #ifdef matador_utils_EXPORTS
|
||||
// #define MATADOR_UTILS_API __declspec(dllexport)
|
||||
// #define EXPIMP_UTILS_TEMPLATE
|
||||
// #else
|
||||
// #define MATADOR_UTILS_API __declspec(dllimport)
|
||||
// #define EXPIMP_UTILS_TEMPLATE extern
|
||||
// #endif
|
||||
#define MATADOR_UTILS_API
|
||||
#pragma warning(disable: 4251)
|
||||
#else
|
||||
#define MATADOR_UTILS_API
|
||||
#endif
|
||||
|
||||
#endif //MATADOR_UTILS_EXPORT_HPP
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef QUERY_FETCH_TYPE_HPP
|
||||
#define QUERY_FETCH_TYPE_HPP
|
||||
#ifndef MATADOR_FETCH_TYPE_HPP
|
||||
#define MATADOR_FETCH_TYPE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -18,4 +18,4 @@ enum class fetch_type : uint8_t
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_FETCH_TYPE_HPP
|
||||
#endif //MATADOR_FETCH_TYPE_HPP
|
||||
|
||||
@@ -1,27 +1,72 @@
|
||||
#ifndef QUERY_FIELD_ATTRIBUTES_HPP
|
||||
#define QUERY_FIELD_ATTRIBUTES_HPP
|
||||
#ifndef MATADOR_FIELD_ATTRIBUTES_HPP
|
||||
#define MATADOR_FIELD_ATTRIBUTES_HPP
|
||||
|
||||
#include "constraints.hpp"
|
||||
#include "matador/utils/constraints.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
/**
|
||||
* This class represents field attributes in
|
||||
* form of size and constraints for a database
|
||||
* field (column)
|
||||
*
|
||||
* Currently the size is only applied
|
||||
* to a field of type string leading
|
||||
* to VARCHAR(size).
|
||||
*/
|
||||
class field_attributes
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates field_attributes instance
|
||||
* with size 0 (zero) and no constraints.
|
||||
*/
|
||||
field_attributes() = default;
|
||||
/**
|
||||
* Creates field_attributes instance
|
||||
* with given size and no constraints.
|
||||
*
|
||||
* @param size Size of the attribute
|
||||
*/
|
||||
field_attributes(size_t size); // NOLINT(*-explicit-constructor)
|
||||
/**
|
||||
* Creates field_attributes instance
|
||||
* with size 0 (zero) and given constraints.
|
||||
*
|
||||
* @param options Constraints to apply to field
|
||||
*/
|
||||
field_attributes(constraints options); // NOLINT(*-explicit-constructor)
|
||||
/**
|
||||
* Creates field_attributes instance
|
||||
* with given size and constraints.
|
||||
*
|
||||
* @param size Size of the attribute
|
||||
* @param options Constraints to apply to field
|
||||
*/
|
||||
field_attributes(size_t size, constraints options);
|
||||
field_attributes(const field_attributes &x) = default;
|
||||
field_attributes& operator=(const field_attributes &x) = default;
|
||||
field_attributes(field_attributes &&x) = default;
|
||||
field_attributes& operator=(field_attributes &&x) = default;
|
||||
~field_attributes() = default;
|
||||
|
||||
field_attributes(const field_attributes &) = default;
|
||||
field_attributes(field_attributes &&) = default;
|
||||
field_attributes &operator=(const field_attributes &) = default;
|
||||
field_attributes &operator=(field_attributes &&) = default;
|
||||
|
||||
field_attributes& operator=(size_t size);
|
||||
field_attributes& operator=(constraints opt);
|
||||
/**
|
||||
* Returns the size of the field
|
||||
*
|
||||
* @return Size of the field
|
||||
*/
|
||||
[[nodiscard]] size_t size() const;
|
||||
void size(size_t size);
|
||||
|
||||
/**
|
||||
* Returns the constraints of the field
|
||||
*
|
||||
* @return Constraints of the field
|
||||
*/
|
||||
[[nodiscard]] constraints options() const;
|
||||
|
||||
private:
|
||||
@@ -32,4 +77,4 @@ private:
|
||||
const field_attributes null_attributes {};
|
||||
|
||||
}
|
||||
#endif //QUERY_FIELD_ATTRIBUTES_HPP
|
||||
#endif //MATADOR_FIELD_ATTRIBUTES_HPP
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef QUERY_FOREIGN_ATTRIBUTES_HPP
|
||||
#define QUERY_FOREIGN_ATTRIBUTES_HPP
|
||||
#ifndef MATADOR_FOREIGN_ATTRIBUTES_HPP
|
||||
#define MATADOR_FOREIGN_ATTRIBUTES_HPP
|
||||
|
||||
#include "matador/utils/fetch_type.hpp"
|
||||
#include "matador/utils/cascade_type.hpp"
|
||||
@@ -13,8 +13,8 @@ public:
|
||||
foreign_attributes(cascade_type cascade); // NOLINT(*-explicit-constructor)
|
||||
foreign_attributes(fetch_type fetch); // NOLINT(*-explicit-constructor)
|
||||
foreign_attributes(cascade_type cascade, fetch_type fetch);
|
||||
foreign_attributes(const foreign_attributes &x) = default;
|
||||
foreign_attributes& operator=(const foreign_attributes &x) = default;
|
||||
foreign_attributes(const utils::foreign_attributes &x) = default;
|
||||
foreign_attributes& operator=(const utils::foreign_attributes &x) = default;
|
||||
foreign_attributes(foreign_attributes &&x) = default;
|
||||
foreign_attributes& operator=(foreign_attributes &&x) = default;
|
||||
~foreign_attributes() = default;
|
||||
@@ -27,8 +27,8 @@ private:
|
||||
fetch_type fetch_{fetch_type::LAZY};
|
||||
};
|
||||
|
||||
const foreign_attributes default_foreign_attributes {};
|
||||
const utils::foreign_attributes default_foreign_attributes {};
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_FOREIGN_ATTRIBUTES_HPP
|
||||
#endif //MATADOR_FOREIGN_ATTRIBUTES_HPP
|
||||
|
||||
@@ -1,178 +1,177 @@
|
||||
#ifndef QUERY_IDENTIFIER_HPP
|
||||
#define QUERY_IDENTIFIER_HPP
|
||||
#ifndef MATADOR_IDENTIFIER_HPP
|
||||
#define MATADOR_IDENTIFIER_HPP
|
||||
|
||||
#include "matador/utils/default_type_traits.hpp"
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
#include "matador/utils/types.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
#include <type_traits>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
struct null_type_t {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
enum class identifier_type_t : unsigned int {
|
||||
INTEGRAL_TYPE,
|
||||
STRING_TYPE,
|
||||
NULL_TYPE
|
||||
};
|
||||
|
||||
template<typename Type, class Enabled = void>
|
||||
struct identifier_type_traits;
|
||||
|
||||
template<typename Type>
|
||||
struct identifier_type_traits<Type, typename std::enable_if<std::is_integral<Type>::value>::type> {
|
||||
static identifier_type_t type() { return identifier_type_t::INTEGRAL_TYPE; }
|
||||
static std::string type_string() { return "integral"; }
|
||||
static bool is_valid(Type value) { return value > 0; }
|
||||
static std::string to_string(Type value) { return std::to_string(value); }
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct identifier_type_traits<Type, typename std::enable_if<std::is_same<Type, std::string>::value>::type> {
|
||||
static identifier_type_t type() { return identifier_type_t::STRING_TYPE; }
|
||||
static std::string type_string() { return "string"; }
|
||||
static bool is_valid(const Type &value) { return !value.empty(); }
|
||||
static std::string to_string(Type value) { return value; }
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct identifier_type_traits<Type, typename std::enable_if<std::is_same<Type, null_type_t>::value>::type> {
|
||||
static identifier_type_t type() { return identifier_type_t::NULL_TYPE; }
|
||||
static std::string type_string() { return "null"; }
|
||||
static bool is_valid() { return false; }
|
||||
static std::string to_string() { return "null_pk"; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class identifier_serializer
|
||||
{
|
||||
public:
|
||||
virtual ~identifier_serializer() = default;
|
||||
|
||||
virtual void serialize(short &, const field_attributes &) = 0;
|
||||
virtual void serialize(int &, const field_attributes &) = 0;
|
||||
virtual void serialize(long &, const field_attributes &) = 0;
|
||||
virtual void serialize(long long &, const field_attributes &) = 0;
|
||||
virtual void serialize(unsigned short &, const field_attributes &) = 0;
|
||||
virtual void serialize(unsigned int &, const field_attributes &) = 0;
|
||||
virtual void serialize(unsigned long &, const field_attributes &) = 0;
|
||||
virtual void serialize(unsigned long long &, const field_attributes &) = 0;
|
||||
virtual void serialize(int8_t &, const field_attributes &) = 0;
|
||||
virtual void serialize(int16_t &, const field_attributes &) = 0;
|
||||
virtual void serialize(int32_t &, const field_attributes &) = 0;
|
||||
virtual void serialize(int64_t &, const field_attributes &) = 0;
|
||||
virtual void serialize(uint8_t &, const field_attributes &) = 0;
|
||||
virtual void serialize(uint16_t &, const field_attributes &) = 0;
|
||||
virtual void serialize(uint32_t &, const field_attributes &) = 0;
|
||||
virtual void serialize(uint64_t &, const field_attributes &) = 0;
|
||||
virtual void serialize(const char*, const field_attributes &) = 0;
|
||||
virtual void serialize(std::string &, const field_attributes &) = 0;
|
||||
virtual void serialize(null_type_t &, const field_attributes &) = 0;
|
||||
};
|
||||
|
||||
template<typename Type, class Enabled = void>
|
||||
struct identifier_type_traits;
|
||||
|
||||
template<typename Type>
|
||||
struct identifier_type_traits<Type, std::enable_if_t<std::is_integral_v<Type>>> {
|
||||
static bool is_valid(Type value) { return value > 0; }
|
||||
static std::string to_string(const Type value) { return std::to_string(value); }
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct identifier_type_traits<Type, std::enable_if_t<std::is_same_v<Type, std::string>>> {
|
||||
static bool is_valid(const Type &value) { return !value.empty(); }
|
||||
static std::string to_string(const Type &value) { return value; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct identifier_type_traits<null_type_t, void> {
|
||||
static bool is_valid() { return false; }
|
||||
static std::string to_string() { return "null"; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct identifier_type_traits<const char*, void> {
|
||||
static bool is_valid(const char *value);
|
||||
static std::string to_string(const char *value);
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename Type>
|
||||
size_t hash(const Type &value) {
|
||||
return std::hash<Type>()(value);
|
||||
}
|
||||
|
||||
size_t hash(const char *value);
|
||||
|
||||
}
|
||||
|
||||
class identifier
|
||||
{
|
||||
private:
|
||||
struct base
|
||||
{
|
||||
explicit base(const std::type_index &ti, detail::identifier_type_t id_type);
|
||||
base(const std::type_index &ti, basic_type type);
|
||||
base(const base &x) = delete;
|
||||
base &operator=(const base &x) = delete;
|
||||
base(base &&x) = delete;
|
||||
base &operator=(base &&x) = delete;
|
||||
virtual ~base() = default;
|
||||
|
||||
template<typename Type>
|
||||
bool is_similar_type() const
|
||||
{
|
||||
return identifier_type_ == detail::identifier_type_traits<Type>::type();
|
||||
}
|
||||
|
||||
bool is_similar_type(const base &x) const;
|
||||
detail::identifier_type_t type() const;
|
||||
|
||||
virtual base *copy() const = 0;
|
||||
virtual bool equal_to(const base &x) const = 0;
|
||||
virtual bool less(const base &x) const = 0;
|
||||
virtual bool is_valid() const = 0;
|
||||
[[nodiscard]] virtual base *copy() const = 0;
|
||||
[[nodiscard]] virtual bool equal_to(const base &x) const = 0;
|
||||
[[nodiscard]] virtual bool less(const base &x) const = 0;
|
||||
[[nodiscard]] virtual bool is_valid() const = 0;
|
||||
virtual void serialize(identifier_serializer &s) = 0;
|
||||
virtual std::string str() const = 0;
|
||||
virtual size_t hash() const = 0;
|
||||
[[nodiscard]] virtual std::string str() const = 0;
|
||||
[[nodiscard]] virtual size_t hash() const = 0;
|
||||
|
||||
std::type_index type_index_;
|
||||
detail::identifier_type_t identifier_type_;
|
||||
basic_type type_{basic_type::type_null};
|
||||
};
|
||||
|
||||
template<class IdType>
|
||||
struct pk : public base
|
||||
struct pk final : base
|
||||
{
|
||||
using self = pk<IdType>;
|
||||
using self = pk;
|
||||
|
||||
explicit pk(const IdType &id, size_t size = 0) : base(std::type_index(typeid(IdType)), detail::identifier_type_traits<IdType>::type())
|
||||
, id_(id)
|
||||
, size_(size) {}
|
||||
explicit pk(const IdType &id)
|
||||
: base(std::type_index(typeid(IdType)), data_type_traits<IdType>::type(1))
|
||||
, id_(id)
|
||||
, size_(sizeof(IdType)) {}
|
||||
|
||||
base *copy() const final {
|
||||
return new self(id_, size_);
|
||||
[[nodiscard]] base *copy() const override {
|
||||
return new self(id_);
|
||||
}
|
||||
|
||||
bool equal_to(const base &x) const final {
|
||||
return static_cast<const pk<IdType> &>(x).id_ == id_;
|
||||
[[nodiscard]] bool equal_to(const base &x) const override {
|
||||
return static_cast<const pk&>(x).id_ == id_;
|
||||
}
|
||||
|
||||
bool less(const base &x) const final {
|
||||
return static_cast<const pk<IdType> &>(x).id_ < id_;
|
||||
[[nodiscard]] bool less(const base &x) const override {
|
||||
return id_ < static_cast<const pk&>(x).id_;
|
||||
}
|
||||
|
||||
bool is_valid() const final
|
||||
{
|
||||
return detail::identifier_type_traits<IdType>::is_valid(id_);
|
||||
[[nodiscard]] bool is_valid() const override {
|
||||
return identifier_type_traits<IdType>::is_valid(id_);
|
||||
}
|
||||
|
||||
std::string str() const final
|
||||
{
|
||||
return detail::identifier_type_traits<IdType>::to_string(id_);
|
||||
[[nodiscard]] std::string str() const override {
|
||||
return identifier_type_traits<IdType>::to_string(id_);
|
||||
}
|
||||
|
||||
void serialize(identifier_serializer &s) final {
|
||||
void serialize(identifier_serializer &s) override {
|
||||
s.serialize(id_, size_);
|
||||
}
|
||||
|
||||
size_t hash() const final {
|
||||
std::hash<IdType> hash_func;
|
||||
return hash_func(id_);
|
||||
[[nodiscard]] size_t hash() const override {
|
||||
return detail::hash(id_);
|
||||
}
|
||||
|
||||
IdType id_;
|
||||
size_t size_{};
|
||||
};
|
||||
|
||||
struct null_pk : public base
|
||||
struct null_pk final : base
|
||||
{
|
||||
null_pk();
|
||||
base *copy() const final;
|
||||
bool equal_to(const base &x) const final;
|
||||
bool less(const base &x) const final;
|
||||
bool is_valid() const final;
|
||||
void serialize(identifier_serializer &s) final;
|
||||
std::string str() const final;
|
||||
size_t hash() const final;
|
||||
[[nodiscard]] base *copy() const override;
|
||||
[[nodiscard]] bool equal_to(const base &x) const override;
|
||||
[[nodiscard]] bool less(const base &x) const override;
|
||||
[[nodiscard]] bool is_valid() const override;
|
||||
void serialize(identifier_serializer &s) override;
|
||||
[[nodiscard]] std::string str() const override;
|
||||
[[nodiscard]] size_t hash() const override;
|
||||
null_type_t null_;
|
||||
};
|
||||
|
||||
public:
|
||||
identifier();
|
||||
template<typename Type>
|
||||
explicit identifier(const Type &id, long size = -1)
|
||||
: id_(std::make_shared<pk<Type>>(id, size)) {}
|
||||
explicit identifier(const Type &id)
|
||||
: id_(std::make_shared<pk<Type>>(id)) {}
|
||||
explicit identifier(const char *id)
|
||||
: id_(std::make_shared<pk<const char*>>(id)) {}
|
||||
identifier(const identifier &x);
|
||||
identifier &operator=(const identifier &x);
|
||||
identifier(identifier &&x) noexcept ;
|
||||
identifier &operator=(identifier &&x) noexcept;
|
||||
|
||||
template<typename Type>
|
||||
identifier &operator=(const Type &value)
|
||||
identifier& operator=(const Type &value)
|
||||
{
|
||||
id_ = std::make_shared<pk<Type>>(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
identifier& operator=(const char *value)
|
||||
{
|
||||
id_ = std::make_shared<pk<const char*>>(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~identifier() = default;
|
||||
|
||||
bool operator==(const identifier &x) const;
|
||||
@@ -182,26 +181,28 @@ public:
|
||||
bool operator>(const identifier &x) const;
|
||||
bool operator>=(const identifier &x) const;
|
||||
|
||||
bool is_similar_type(const identifier &x) const;
|
||||
template<typename Type>
|
||||
bool is_similar_type() const
|
||||
{
|
||||
return id_->is_similar_type<Type>();
|
||||
}
|
||||
[[nodiscard]] std::string str() const;
|
||||
[[nodiscard]] const std::type_index &type_index() const;
|
||||
[[nodiscard]] basic_type type() const;
|
||||
|
||||
std::string str() const;
|
||||
const std::type_index &type_index() const;
|
||||
[[nodiscard]] identifier share() const;
|
||||
[[nodiscard]] size_t use_count() const;
|
||||
|
||||
identifier share() const;
|
||||
size_t use_count() const;
|
||||
[[nodiscard]] bool is_integer() const;
|
||||
[[nodiscard]] bool is_floating_point() const;
|
||||
[[nodiscard]] bool is_bool() const;
|
||||
[[nodiscard]] bool is_varchar() const;
|
||||
[[nodiscard]] bool is_date() const;
|
||||
[[nodiscard]] bool is_time() const;
|
||||
[[nodiscard]] bool is_blob() const;
|
||||
[[nodiscard]] bool is_null() const;
|
||||
|
||||
bool is_null() const;
|
||||
bool is_valid() const;
|
||||
[[nodiscard]] bool is_valid() const;
|
||||
void clear();
|
||||
|
||||
void serialize(identifier_serializer &s);
|
||||
void serialize(identifier_serializer &s) const;
|
||||
|
||||
size_t hash() const;
|
||||
[[nodiscard]] size_t hash() const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &out, const identifier &id);
|
||||
|
||||
@@ -214,10 +215,12 @@ private:
|
||||
|
||||
static identifier null_identifier{};
|
||||
|
||||
/// @cond MATADOR_DEV
|
||||
struct id_pk_hash
|
||||
{
|
||||
size_t operator()(const identifier &id) const;
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
}
|
||||
#endif //QUERY_IDENTIFIER_HPP
|
||||
|
||||
#endif //MATADOR_IDENTIFIER_HPP
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef QUERY_LIBRARY_HPP
|
||||
#define QUERY_LIBRARY_HPP
|
||||
#ifndef LIBRARY_HPP
|
||||
#define LIBRARY_HPP
|
||||
|
||||
#include "matador/utils/export.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -16,7 +18,7 @@ namespace matador::utils {
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
typedef FARPROC func_ptr;
|
||||
#else
|
||||
typedef void *func_ptr;
|
||||
typedef void* func_ptr;
|
||||
#endif
|
||||
#endif /* MATADOR_DOXYGEN_DOC */
|
||||
|
||||
@@ -28,26 +30,24 @@ typedef void *func_ptr;
|
||||
* This class represents a loader and un-loader
|
||||
* for an external library. The path to the library
|
||||
* is given by a string.
|
||||
* It can be loaded and unloaded. Furthermore it
|
||||
* provides a method to get a pointer to an function
|
||||
* It can be loaded and unloaded. Furthermore, it
|
||||
* provides a method to get a pointer to a function
|
||||
* exported by the library. The function is identified
|
||||
* by a name.
|
||||
*/
|
||||
class library
|
||||
class MATADOR_UTILS_API library
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a unspecified library serializable
|
||||
*/
|
||||
library() = default;
|
||||
|
||||
/**
|
||||
* Create a library for the given lib path
|
||||
*
|
||||
* @param lib The path to the library to map.
|
||||
*/
|
||||
explicit library(std::string lib);
|
||||
|
||||
~library();
|
||||
|
||||
/**
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
bool load(const std::string &lib);
|
||||
|
||||
/**
|
||||
* Unload an loaded library. If
|
||||
* Unload a loaded library. If
|
||||
* the library isn't loaded or an
|
||||
* error occurred while unloading
|
||||
* false is returned.
|
||||
@@ -104,4 +104,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_LIBRARY_HPP
|
||||
#endif /* LIBRARY_HPP */
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
#ifndef QUERY_LOGGER_HPP
|
||||
#define QUERY_LOGGER_HPP
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
enum class log_level
|
||||
{
|
||||
LVL_FATAL, /**< If a serious error occurred use FATAL level */
|
||||
LVL_ERROR, /**< On error use ERROR level */
|
||||
LVL_WARN, /**< Warnings should use WARN level */
|
||||
LVL_INFO, /**< Information should go with INFO level */
|
||||
LVL_DEBUG, /**< Debug output should use DEBUG level */
|
||||
LVL_TRACE, /**< Trace information should use TRACE level */
|
||||
LVL_ALL /**< This level represents all log levels and should be used for logging */
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple file logger
|
||||
*/
|
||||
class logger
|
||||
{
|
||||
public:
|
||||
logger(const std::string &path, std::string source);
|
||||
logger(FILE *file, std::string source);
|
||||
logger(const logger &x);
|
||||
logger& operator=(const logger &x);
|
||||
logger(logger &&x) noexcept;
|
||||
logger& operator=(logger &&x) noexcept;
|
||||
|
||||
template<typename ... Args>
|
||||
void info(const std::string &what, Args const &... args) const { info(what.c_str(), args...); }
|
||||
template<typename ... Args>
|
||||
void info(const char *what, Args const &... args) const { log(log_level::LVL_INFO, what, args...); }
|
||||
|
||||
template<typename ... Args>
|
||||
void debug(const std::string &what, Args const &... args) const { debug(what.c_str(), args...); }
|
||||
template<typename ... Args>
|
||||
void debug(const char *what, Args const &... args) const { log(log_level::LVL_DEBUG, what, args...); }
|
||||
|
||||
template<typename ... Args>
|
||||
void warn(const std::string &what, Args const &... args) const { warn(what.c_str(), args...); }
|
||||
template<typename ... Args>
|
||||
void warn(const char *what, Args const &... args) const { log(log_level::LVL_WARN, what, args...); }
|
||||
|
||||
template<typename ... Args>
|
||||
void error(const std::string &what, Args const &... args) const { error(what.c_str(), args...); }
|
||||
template<typename ... Args>
|
||||
void error(const char *what, Args const &... args) const { log(log_level::LVL_ERROR, what, args...); }
|
||||
|
||||
template<typename ... Args>
|
||||
void fatal(const std::string &what, Args const &... args) const { fatal(what.c_str(), args...); }
|
||||
template<typename ... Args>
|
||||
void fatal(const char *what, Args const &... args) const { log(log_level::LVL_FATAL, what, args...); }
|
||||
|
||||
template<typename ... Args>
|
||||
void log(log_level lvl, const char *what, Args const &... args) const;
|
||||
void log(log_level lvl, const char *message) const;
|
||||
|
||||
private:
|
||||
void write(const char *message, size_t size) const;
|
||||
void close();
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
FILE *stream = nullptr;
|
||||
mutable std::mutex mutex_;
|
||||
std::string source_;
|
||||
};
|
||||
|
||||
template<typename... ARGS>
|
||||
void logger::log(log_level lvl, const char *what, ARGS const &... args) const
|
||||
{
|
||||
char message_buffer[16384];
|
||||
|
||||
#ifdef _MSC_VER
|
||||
sprintf_s(message_buffer, 16384, what, args...);
|
||||
#else
|
||||
sprintf(message_buffer, what, args...);
|
||||
#endif
|
||||
|
||||
log(lvl, message_buffer);
|
||||
}
|
||||
|
||||
}
|
||||
#endif //QUERY_LOGGER_HPP
|
||||
@@ -1,42 +0,0 @@
|
||||
#ifndef QUERY_MACRO_MAP_HPP
|
||||
#define QUERY_MACRO_MAP_HPP
|
||||
|
||||
#define EVAL0(...) __VA_ARGS__
|
||||
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
|
||||
#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
|
||||
#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
|
||||
#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
|
||||
#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
|
||||
|
||||
#define MAP_END(...)
|
||||
#define MAP_OUT
|
||||
#define MAP_COMMA ,
|
||||
|
||||
#define MAP_GET_END2() 0, MAP_END
|
||||
#define MAP_GET_END1(...) MAP_GET_END2
|
||||
#define MAP_GET_END(...) MAP_GET_END1
|
||||
#define MAP_NEXT0(test, next, ...) next MAP_OUT
|
||||
#define MAP_NEXT1(test, next) MAP_NEXT0(test, next, 0)
|
||||
#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next)
|
||||
|
||||
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP1)(f, peek, __VA_ARGS__)
|
||||
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP0)(f, peek, __VA_ARGS__)
|
||||
|
||||
#define MAP_LIST_NEXT1(test, next) MAP_NEXT0(test, MAP_COMMA next, 0)
|
||||
#define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next)
|
||||
|
||||
#define MAP_LIST0(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST1)(f, peek, __VA_ARGS__)
|
||||
#define MAP_LIST1(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST0)(f, peek, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Applies the function macro `f` to each of the remaining parameters.
|
||||
*/
|
||||
#define MAP(f, ...) EVAL(MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||
|
||||
/**
|
||||
* Applies the function macro `f` to each of the remaining parameters and
|
||||
* inserts commas between the results.
|
||||
*/
|
||||
#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||
|
||||
#endif //QUERY_MACRO_MAP_HPP
|
||||
@@ -1,44 +1,105 @@
|
||||
#ifndef QUERY_OS_HPP
|
||||
#define QUERY_OS_HPP
|
||||
#ifndef MATADOR_OS_HPP
|
||||
#define MATADOR_OS_HPP
|
||||
|
||||
#include "matador/utils/export.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace matador::utils::os {
|
||||
enum class override_env_value {
|
||||
KeepValue,
|
||||
OverrideValue
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
extern char DIR_SEPARATOR;
|
||||
extern const char* DIR_SEPARATOR_STRING;
|
||||
#else
|
||||
extern char DIR_SEPARATOR;
|
||||
extern const char* DIR_SEPARATOR_STRING;
|
||||
std::string error_string(unsigned long error);
|
||||
#endif
|
||||
|
||||
std::string error_string(unsigned long error);
|
||||
|
||||
void setenv(const char *name, const char *value, override_env_value override_value);
|
||||
std::string getenv(const char* name);
|
||||
void unsetenv(const char *name);
|
||||
}
|
||||
|
||||
[[maybe_unused]] std::string getenv(const std::string &name);
|
||||
namespace matador::os {
|
||||
|
||||
FILE* fopen(const std::string &path, const char *modes);
|
||||
FILE* fopen(const char *path, const char *modes);
|
||||
/// @cond MATADOR_DEV
|
||||
|
||||
std::string get_current_dir();
|
||||
#ifdef _WIN32
|
||||
MATADOR_UTILS_API extern char DIR_SEPARATOR;
|
||||
MATADOR_UTILS_API extern const char* DIR_SEPARATOR_STRING;
|
||||
#else
|
||||
MATADOR_UTILS_API extern char DIR_SEPARATOR;
|
||||
MATADOR_UTILS_API extern const char* DIR_SEPARATOR_STRING;
|
||||
#endif
|
||||
|
||||
bool mkdir(const std::string &dirname);
|
||||
bool mkdir(const char *dirname);
|
||||
MATADOR_UTILS_API FILE* fopen(const std::string &path, const char *modes);
|
||||
MATADOR_UTILS_API FILE* fopen(const char *path, const char *modes);
|
||||
|
||||
bool chdir(const std::string &dirname);
|
||||
bool chdir(const char *dirname);
|
||||
MATADOR_UTILS_API FILE* freopen(const std::string &path, const char *modes, FILE *stream);
|
||||
MATADOR_UTILS_API FILE* freopen(const char *path, const char *modes, FILE *stream);
|
||||
|
||||
bool rmdir(const std::string &dirname);
|
||||
bool rmdir(const char *dirname);
|
||||
MATADOR_UTILS_API bool fclose(FILE *f);
|
||||
|
||||
bool mkpath(const std::string &path);
|
||||
bool mkpath(const char *path);
|
||||
MATADOR_UTILS_API bool remove(const std::string &name);
|
||||
MATADOR_UTILS_API bool remove(const char *name);
|
||||
|
||||
bool rmpath(const std::string &path);
|
||||
bool rmpath(const char *path);
|
||||
MATADOR_UTILS_API bool rename(const std::string &old_name, const std::string &new_name);
|
||||
MATADOR_UTILS_API bool rename(const char *old_name, const char *new_name);
|
||||
|
||||
MATADOR_UTILS_API bool access(const std::string &path, int mode);
|
||||
MATADOR_UTILS_API bool access(const char *path, int mode);
|
||||
|
||||
MATADOR_UTILS_API int dup(FILE *stream);
|
||||
|
||||
MATADOR_UTILS_API bool mkdir(const std::string &dirname);
|
||||
MATADOR_UTILS_API bool mkdir(const char *dirname);
|
||||
|
||||
MATADOR_UTILS_API bool chdir(const std::string &dirname);
|
||||
MATADOR_UTILS_API bool chdir(const char *dirname);
|
||||
|
||||
MATADOR_UTILS_API bool rmdir(const std::string &dirname);
|
||||
MATADOR_UTILS_API bool rmdir(const char *dirname);
|
||||
|
||||
MATADOR_UTILS_API std::string get_current_dir();
|
||||
|
||||
MATADOR_UTILS_API bool mkpath(const std::string &path);
|
||||
MATADOR_UTILS_API bool mkpath(const char *path);
|
||||
|
||||
MATADOR_UTILS_API bool rmpath(const std::string &path);
|
||||
MATADOR_UTILS_API bool rmpath(const char *path);
|
||||
|
||||
MATADOR_UTILS_API bool is_readable(const std::string &path);
|
||||
MATADOR_UTILS_API bool is_readable(const char *path);
|
||||
MATADOR_UTILS_API bool is_writable(const std::string &path);
|
||||
MATADOR_UTILS_API bool is_writable(const char *path);
|
||||
MATADOR_UTILS_API bool exists(const std::string &path);
|
||||
MATADOR_UTILS_API bool exists(const char *path);
|
||||
|
||||
MATADOR_UTILS_API size_t file_size(FILE *stream);
|
||||
|
||||
MATADOR_UTILS_API std::string build_path(const std::string &a, const std::string &b);
|
||||
|
||||
template <typename ...T>
|
||||
std::string build_path(const std::string &a, const std::string &b, T& ...arg)
|
||||
{
|
||||
return build_path(build_path(a, b), arg...);
|
||||
}
|
||||
|
||||
template<typename... ARGS>
|
||||
int sprintf(char* str, size_t s, const char* format, ARGS const&... args)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return sprintf_s(str, s, format, args...);
|
||||
#else
|
||||
return ::snprintf(str, s, format, args...);
|
||||
#endif
|
||||
}
|
||||
|
||||
MATADOR_UTILS_API char* strerror(int err, char* errbuf, size_t bufsize);
|
||||
|
||||
/// @endcond
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_OS_HPP
|
||||
#endif //MATADOR_OS_HPP
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef QUERY_PLACEHOLDER_HPP
|
||||
#define QUERY_PLACEHOLDER_HPP
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
struct placeholder {};
|
||||
|
||||
inline constexpr bool operator==(const placeholder&, const placeholder&) { return true; }
|
||||
|
||||
static constexpr placeholder _;
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_PLACEHOLDER_HPP
|
||||
@@ -2,6 +2,9 @@
|
||||
#define QUERY_RESULT_HPP
|
||||
|
||||
#include <variant>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
@@ -30,14 +33,22 @@ private:
|
||||
ValueType value_;
|
||||
};
|
||||
|
||||
template <>
|
||||
class ok<void>
|
||||
{
|
||||
public:
|
||||
using value_type = void;
|
||||
explicit constexpr ok() = default;
|
||||
};
|
||||
|
||||
template < typename ErrorType >
|
||||
class error
|
||||
class failure
|
||||
{
|
||||
public:
|
||||
using value_type = ErrorType;
|
||||
|
||||
explicit constexpr error(const ErrorType &error) : error_(error) {}
|
||||
explicit constexpr error(ErrorType &&error) : error_(std::move(error)) {}
|
||||
explicit constexpr failure(const ErrorType &error) : error_(error) {}
|
||||
explicit constexpr failure(ErrorType &&error) : error_(std::move(error)) {}
|
||||
|
||||
constexpr ErrorType&& release() { return std::move(error_); }
|
||||
const ErrorType& value() const { return error_; }
|
||||
@@ -51,51 +62,68 @@ template < typename ValueType, typename ErrorType >
|
||||
class result
|
||||
{
|
||||
public:
|
||||
using value_type = ok<ValueType>;
|
||||
using error_type = error<ErrorType>;
|
||||
using value_type = ValueType;
|
||||
using error_type = ErrorType;
|
||||
|
||||
result() : result_(ValueType{}) {}
|
||||
result(value_type value) : result_(std::move(value)) {} // NOLINT(*-explicit-constructor)
|
||||
result(error_type error) : result_(std::move(error)) {} // NOLINT(*-explicit-constructor)
|
||||
result(const result<ValueType, ErrorType> &x) = default;
|
||||
result& operator=(const result<ValueType, ErrorType> &x) = default;
|
||||
result(result<ValueType, ErrorType> &&x) = default;
|
||||
result& operator=(result<ValueType, ErrorType> &&x) = default;
|
||||
result(ok<value_type> value) : result_(std::move(value.release())) {} // NOLINT(*-explicit-constructor)
|
||||
result(failure<error_type> error) : result_(std::move(error.release())) {} // NOLINT(*-explicit-constructor)
|
||||
result(const result &x) = default;
|
||||
result& operator=(const result &x) = default;
|
||||
result(result &&x) = default;
|
||||
result& operator=(result &&x) = default;
|
||||
|
||||
operator bool() const { return is_ok(); } // NOLINT(*-explicit-constructor)
|
||||
|
||||
[[nodiscard]] bool is_ok() const { return std::holds_alternative<value_type>(result_); }
|
||||
[[nodiscard]] bool is_error() const { return std::holds_alternative<error_type>(result_); }
|
||||
|
||||
ValueType&& release() { return std::get<value_type>(result_).release(); }
|
||||
ErrorType&& release_error() { return std::get<error_type>(result_).release(); }
|
||||
ValueType&& release() { return std::move(std::get<value_type>(result_)); }
|
||||
ErrorType&& release_error() { return std::move(std::get<error_type>(result_)); }
|
||||
|
||||
const ValueType& value() const { return std::get<value_type>(result_).value(); }
|
||||
const ErrorType& err() const { return std::get<error_type>(result_).value(); }
|
||||
ErrorType err() { return std::get<error_type>(result_).value(); }
|
||||
const ValueType& value() const { return std::get<value_type>(result_); }
|
||||
ValueType& value() { return std::get<value_type>(result_); }
|
||||
const ErrorType& err() const { return std::get<error_type>(result_); }
|
||||
ErrorType err() { return std::get<error_type>(result_); }
|
||||
|
||||
constexpr const ValueType* operator->() const { return &value(); }
|
||||
constexpr ValueType* operator->() { return &std::get<value_type>(result_).value(); }
|
||||
constexpr ValueType* operator->() { return &std::get<value_type>(result_); }
|
||||
|
||||
template<typename Func, typename SecondValueType = typename std::invoke_result_t<Func, ValueType >>
|
||||
result<SecondValueType, ErrorType> transform(Func &&f) {
|
||||
constexpr const ValueType& operator*() const& noexcept { return value(); }
|
||||
constexpr ValueType& operator*() & noexcept { return value(); }
|
||||
|
||||
template<typename Func,
|
||||
typename SecondValueType = std::invoke_result_t<Func, ValueType >>
|
||||
result<SecondValueType, ErrorType> map(Func &&f) {
|
||||
if (is_ok()) {
|
||||
return result<SecondValueType, ErrorType>(ok(f(release())));
|
||||
}
|
||||
|
||||
return result<SecondValueType, ErrorType>(error(release_error()));
|
||||
return result<SecondValueType, ErrorType>(failure(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func, typename SecondValueType = typename std::invoke_result_t<Func, ValueType >::value_type::value_type>
|
||||
template<typename Func,
|
||||
typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::value_type>
|
||||
result<SecondErrorType, ErrorType> map_error(Func &&f) {
|
||||
if (!is_ok()) {
|
||||
return result<SecondErrorType, ErrorType>(ok(release()));
|
||||
}
|
||||
|
||||
return result<SecondErrorType, ErrorType>(error(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func,
|
||||
typename SecondValueType = typename std::invoke_result_t<Func, ValueType>::value_type>
|
||||
result<SecondValueType, ErrorType> and_then(Func &&f) {
|
||||
if (is_ok()) {
|
||||
return f(release());
|
||||
}
|
||||
|
||||
return result<SecondValueType, ErrorType>(error(release_error()));
|
||||
return result<SecondValueType, ErrorType>(failure(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func, typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::error_type::value_type>
|
||||
template<typename Func,
|
||||
typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::value_type>
|
||||
result<ValueType, SecondErrorType> or_else(Func &&f) {
|
||||
if (is_error()) {
|
||||
return f(err());
|
||||
@@ -108,6 +136,62 @@ private:
|
||||
std::variant<value_type, error_type> result_;
|
||||
};
|
||||
|
||||
template < typename ErrorType >
|
||||
class result<void, ErrorType>
|
||||
{
|
||||
public:
|
||||
using value_type = void;
|
||||
using error_type = ErrorType;
|
||||
|
||||
result() = default;
|
||||
result(ok<void> /*value*/) {}
|
||||
result(failure<error_type> error) : result_(std::move(error.release())) {} // NOLINT(*-explicit-constructor)
|
||||
result(const result &x) = default;
|
||||
result& operator=(const result &x) = default;
|
||||
result(result &&x) = default;
|
||||
result& operator=(result &&x) = default;
|
||||
|
||||
operator bool() const { return is_ok(); } // NOLINT(*-explicit-constructor)
|
||||
|
||||
[[nodiscard]] bool is_ok() const { return !result_.has_value(); }
|
||||
[[nodiscard]] bool is_error() const { return result_.has_value(); }
|
||||
|
||||
ErrorType&& release_error() { return result_->release(); }
|
||||
|
||||
const ErrorType& err() const { return result_.value(); }
|
||||
ErrorType err() { return result_.value(); }
|
||||
|
||||
template<typename Func, typename SecondValueType = std::invoke_result_t<Func>>
|
||||
result<SecondValueType, ErrorType> map(Func &&f) {
|
||||
if (is_ok()) {
|
||||
return result<SecondValueType, ErrorType>(ok(f()));
|
||||
}
|
||||
|
||||
return result<SecondValueType, ErrorType>(error(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
result and_then(Func &&f) {
|
||||
if (is_ok()) {
|
||||
return f();
|
||||
}
|
||||
|
||||
return result(error(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func, typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::value_type>
|
||||
result<void, SecondErrorType> or_else(Func &&f) {
|
||||
if (is_error()) {
|
||||
return f(err());
|
||||
}
|
||||
|
||||
return result<void, SecondErrorType>(ok<void>());
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<error_type> result_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_RESULT_HPP
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef SINGLETON_HPP
|
||||
#define SINGLETON_HPP
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
/**
|
||||
* @class singleton
|
||||
* @brief Provides only one instance of a type.
|
||||
* @tparam T The type of the singleton.
|
||||
*
|
||||
* This class implements the singleton pattern.
|
||||
* It ensures that only one instance of a class
|
||||
* exists.
|
||||
* @note The derived class must add a friend declaration
|
||||
* for the concrete singleton type.
|
||||
*/
|
||||
template < typename T >
|
||||
class singleton
|
||||
{
|
||||
public:
|
||||
typedef T value_type; /**< Shortcut for the singletons type */
|
||||
|
||||
/**
|
||||
* @brief Access the instance of the class.
|
||||
*
|
||||
* The static instance method provides
|
||||
* the access to the one instance of the
|
||||
* concrete class.
|
||||
*
|
||||
* @return The one instance of the class.
|
||||
*/
|
||||
static value_type& instance ()
|
||||
{
|
||||
static value_type instance_;
|
||||
return instance_;
|
||||
}
|
||||
virtual ~singleton() = default;
|
||||
|
||||
protected:
|
||||
singleton() = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SINGLETON_HPP */
|
||||
@@ -1,13 +1,37 @@
|
||||
#ifndef QUERY_STRING_HPP
|
||||
#define QUERY_STRING_HPP
|
||||
#ifndef STRING_HPP
|
||||
#define STRING_HPP
|
||||
|
||||
#include "matador/utils/convert.hpp"
|
||||
#include "matador/utils/export.hpp"
|
||||
#include "matador/utils/types.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
/**
|
||||
* Converts each byte of the given binary data
|
||||
* into is hex string representation and return
|
||||
* all bytes of blob as string.
|
||||
*
|
||||
* @param data Binary data to be converted
|
||||
* @return Binary data as string
|
||||
*/
|
||||
MATADOR_UTILS_API std::string to_string(const blob &data);
|
||||
|
||||
/**
|
||||
* Splits a string by a delimiter and
|
||||
* add the string tokens to a vector. The
|
||||
* size of the vector is returned.
|
||||
*
|
||||
* @param str The string to split.
|
||||
* @param delim The delimiter character.
|
||||
* @param values The result vector.
|
||||
* @return The size of the vector.
|
||||
*/
|
||||
MATADOR_UTILS_API size_t split(const std::string &str, char delim, std::vector<std::string> &values);
|
||||
|
||||
/**
|
||||
* Splits a string by a delimiter and
|
||||
* add the string tokens to a vector. The
|
||||
@@ -15,9 +39,32 @@ namespace matador::utils {
|
||||
*
|
||||
* @param str The string to split.
|
||||
* @param delim The delimiter character.
|
||||
* @return The the vector with split strings.
|
||||
* @return The vector with split strings.
|
||||
*/
|
||||
std::vector<std::string> split(const std::string &str, char delim);
|
||||
MATADOR_UTILS_API std::vector<std::string> split(const std::string &str, char delim);
|
||||
|
||||
/**
|
||||
* Splits a string by a delimiter and
|
||||
* add the string tokens to a list. The
|
||||
* size of the list is returned.
|
||||
*
|
||||
* @param str The string to split.
|
||||
* @param delim The delimiter character.
|
||||
* @param values The result list.
|
||||
* @return The size of the list.
|
||||
*/
|
||||
MATADOR_UTILS_API size_t split(const std::string &str, char delim, std::list<std::string> &values);
|
||||
|
||||
/**
|
||||
* @fn std::string trim(const std::string& str, const std::string&)
|
||||
* Trims a string by removing leading and trailing characters
|
||||
* The default characters are spaces and tabs
|
||||
*
|
||||
* @param str The string to be trimmed
|
||||
* @param whitespace The trimming characters
|
||||
* @return the trimmed string
|
||||
*/
|
||||
MATADOR_UTILS_API std::string trim(const std::string& str, const std::string& whitespace = " \t");
|
||||
|
||||
/**
|
||||
* Replaces all occurrences of string from in given string
|
||||
@@ -27,23 +74,28 @@ std::vector<std::string> split(const std::string &str, char delim);
|
||||
* @param from The string to be replaced
|
||||
* @param to The new string
|
||||
*/
|
||||
void replace_all(std::string &in, const std::string &from, const std::string &to);
|
||||
|
||||
const std::string& to_string(const std::string &str);
|
||||
std::string to_string(const blob &data);
|
||||
MATADOR_UTILS_API void replace_all(std::string &in, const std::string &from, const std::string &to);
|
||||
|
||||
template <typename Type >
|
||||
std::string to_string(const Type &value) {
|
||||
const auto res = to<std::string>(value);
|
||||
if (res.is_ok()) {
|
||||
return *res;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
/**
|
||||
* Joins a range of elements as string within a list
|
||||
* with a given delimiter and writes it to the
|
||||
* given stream
|
||||
*
|
||||
* @tparam R Type og the range (e.g. map, list, vector, etc)
|
||||
* @tparam Range Type og the range (e.g. map, list, vector, etc)
|
||||
* @param range The range with the elements to join_left
|
||||
* @param delim The delimiter for the elements
|
||||
* @return The ostream reference
|
||||
*/
|
||||
template < class R >
|
||||
std::string join(R &range, const std::string &delim)
|
||||
template < class Range >
|
||||
std::string join(const Range &range, const std::string &delim)
|
||||
{
|
||||
std::string result {};
|
||||
if (range.size() < 2) {
|
||||
@@ -61,4 +113,4 @@ std::string join(R &range, const std::string &delim)
|
||||
}
|
||||
|
||||
}
|
||||
#endif //QUERY_STRING_HPP
|
||||
#endif //STRING_HPP
|
||||
|
||||
@@ -1,13 +1,31 @@
|
||||
#ifndef QUERY_UTILS_TYPES_HPP
|
||||
#define QUERY_UTILS_TYPES_HPP
|
||||
#ifndef MATADOR_TYPES_HPP
|
||||
#define MATADOR_TYPES_HPP
|
||||
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
enum class basic_type : uint8_t;
|
||||
|
||||
using byte = unsigned char;
|
||||
using blob = std::vector<byte>;
|
||||
|
||||
using database_type = std::variant<
|
||||
uint8_t, uint16_t, uint32_t, uint64_t,
|
||||
int8_t, int16_t, int32_t, int64_t,
|
||||
float, double,
|
||||
bool,
|
||||
std::string,
|
||||
blob,
|
||||
nullptr_t>;
|
||||
|
||||
struct null_type_t {};
|
||||
|
||||
void initialize_by_basic_type(basic_type type, database_type &val);
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_UTILS_TYPES_HPP
|
||||
#endif //MATADOR_TYPES_HPP
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef QUERY_VALUE_HPP
|
||||
#define QUERY_VALUE_HPP
|
||||
|
||||
#include "matador/utils/basic_type_converter.hpp"
|
||||
#include "matador/utils/default_type_traits.hpp"
|
||||
#include "matador/utils/types.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
namespace detail {
|
||||
template<typename Type>
|
||||
size_t determine_size(const Type &/*val*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
size_t determine_size(const std::string &val);
|
||||
size_t determine_size(const char *val);
|
||||
size_t determine_size(const blob &val);
|
||||
|
||||
}
|
||||
|
||||
class value
|
||||
{
|
||||
public:
|
||||
value() = default;
|
||||
template<typename Type>
|
||||
explicit value(Type value, size_t size = 0)
|
||||
: value_(value)
|
||||
, size_(size)
|
||||
, type_(data_type_traits<Type>::type(size)) {}
|
||||
explicit value(basic_type data_type, size_t size = 0);
|
||||
value(const value &x) = default;
|
||||
value& operator=(const value &x) = default;
|
||||
template<typename Type>
|
||||
value& operator=(Type val) {
|
||||
value_ = val;
|
||||
size_ = detail::determine_size(val);
|
||||
type_ = data_type_traits<Type>::type(size_);
|
||||
return *this;
|
||||
}
|
||||
value(value &&x) noexcept;
|
||||
value& operator=(value &&x) noexcept;
|
||||
|
||||
template<class Type>
|
||||
std::optional<Type> as() const {
|
||||
if (std::holds_alternative<Type>(value_)) {
|
||||
return std::get<Type>(value_);
|
||||
}
|
||||
const auto res = basic_type_converter<Type>::convert_value(value_);
|
||||
if (!res.is_ok()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return *res;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
std::optional<std::reference_wrapper<Type>> ref() {
|
||||
if (std::holds_alternative<Type>(value_)) {
|
||||
return std::get<Type>(value_);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string str() const;
|
||||
|
||||
[[nodiscard]] size_t size() const;
|
||||
[[nodiscard]] basic_type type() const;
|
||||
|
||||
[[nodiscard]] bool is_integer() const;
|
||||
[[nodiscard]] bool is_floating_point() const;
|
||||
[[nodiscard]] bool is_bool() const;
|
||||
[[nodiscard]] bool is_string() const;
|
||||
[[nodiscard]] bool is_varchar() const;
|
||||
[[nodiscard]] bool is_date() const;
|
||||
[[nodiscard]] bool is_time() const;
|
||||
[[nodiscard]] bool is_blob() const;
|
||||
[[nodiscard]] bool is_null() const;
|
||||
|
||||
private:
|
||||
utils::database_type value_;
|
||||
size_t size_{};
|
||||
basic_type type_{basic_type::type_null};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif //QUERY_VALUE_HPP
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef MATADOR_VERSION_HPP
|
||||
#define MATADOR_VERSION_HPP
|
||||
|
||||
#include "matador/utils/result.hpp"
|
||||
#include "matador/utils/error.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
class version {
|
||||
public:
|
||||
version() = default;
|
||||
~version() =default;
|
||||
version(unsigned int major, unsigned int minor, unsigned int patch);
|
||||
version(const version& x) = default;
|
||||
version& operator=(const version& x) = default;
|
||||
version(version&& x) noexcept = default;
|
||||
version& operator=(version&& x) noexcept = default;
|
||||
|
||||
bool operator==(const version &x) const;
|
||||
bool operator!=(const version &x) const;
|
||||
bool operator>(const version &x) const;
|
||||
bool operator>=(const version &x) const;
|
||||
bool operator<(const version &x) const;
|
||||
bool operator<=(const version &x) const;
|
||||
|
||||
[[nodiscard]] std::string str() const;
|
||||
friend std::ostream& operator<<(std::ostream &out, const version &v);
|
||||
|
||||
static result<version, error> from_string(const std::string &version_string);
|
||||
|
||||
[[nodiscard]] unsigned int major() const;
|
||||
[[nodiscard]] unsigned int minor() const;
|
||||
[[nodiscard]] unsigned int patch() const;
|
||||
|
||||
void major(unsigned int m);
|
||||
void minor(unsigned int m);
|
||||
void patch(unsigned int p);
|
||||
|
||||
private:
|
||||
unsigned int major_{};
|
||||
unsigned int minor_{};
|
||||
unsigned int patch_{};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //MATADOR_VERSION_HPP
|
||||
Reference in New Issue
Block a user