LiteLoaderBDS-1.16.40/LiteLoader/Header/DB/Any.h
2022-09-21 19:47:03 +08:00

728 lines
18 KiB
C++

#pragma once
#include "../Global.h"
#include "Types.h"
#pragma region AnyConversion
namespace DB
{
// Declare Any class
class Any;
} // namespace DB
/**
* @brief Function to convert Any to T.
*
* @tparam T The type to convert to
* @param v The Any object
* @return T The converted value
*/
template <typename T>
inline T any_to(const DB::Any& v)
{
throw std::bad_cast();
}
template <typename T>
inline std::vector<DB::Any> to_any_container(const std::vector<T>& v)
{
std::vector<DB::Any> result;
for (auto& i : v)
{
result.push_back(DB::Any(i));
}
return result;
}
template <typename T>
inline std::set<DB::Any> to_any_container(const std::set<T>& v)
{
std::set<DB::Any> result;
for (auto& i : v)
{
result.insert(DB::Any(i));
}
return result;
}
template <typename T>
inline std::list<DB::Any> to_any_container(const std::list<T>& v)
{
std::list<DB::Any> result;
for (auto& i : v)
{
result.push_back(DB::Any(i));
}
return result;
}
template <typename T>
inline std::unordered_set<DB::Any> to_any_container(const std::unordered_set<T>& v)
{
std::unordered_set<DB::Any> result;
for (auto& i : v)
{
result.insert(DB::Any(i));
}
return result;
}
template <typename K, typename V>
inline std::map<K, DB::Any> to_any_container(const std::map<K, V>& v)
{
std::map<K, DB::Any> result;
for (auto& i : v)
{
result.insert(std::make_pair(i.first, DB::Any(i.second)));
}
return result;
}
template <typename K, typename V>
inline std::unordered_map<K, DB::Any> to_any_unordered_map(const std::unordered_map<K, V>& v)
{
std::unordered_map<K, DB::Any> result;
for (auto& i : v)
{
result.insert(std::make_pair(i.first, DB::Any(i.second)));
}
return result;
}
#pragma endregion
namespace DB
{
/**
* @brief Any class to store some SQL basic types
*
*/
class Any
{
public:
union Value
{
bool boolean;
int64_t integer;
uint64_t uinteger;
double floating;
std::string* string;
Date* date;
Time* time;
DateTime* datetime;
ByteArray* blob;
} value; ///< Value
enum class Type : char
{
Null = 0,
Boolean = 1,
Integer = 2,
UInteger = 3,
Floating = 4,
String = 5,
Date = 6,
Time = 7,
DateTime = 8,
Blob = 9
} type = Type::Null; ///< Type of the value
/**
* @brief Construct a new Any object with null value.
*
*/
LIAPI Any();
/**
* @brief Construct a new Any object with boolean value.
*
* @param v The boolean value
*/
LIAPI Any(bool v);
/**
* @brief Construct a new Any object with int64 value.
*
* @param v The integer value
*/
LIAPI Any(int64_t v);
/**
* @brief Construct a new Any object with uint64 value.
*
* @param v The unsigned integer value
*/
LIAPI Any(uint64_t v);
/**
* @brief Construct a new Any object with double value.
*
* @param v The floating value
*/
LIAPI Any(double v);
/**
* @brief Construct a new Any object with string value.
*
* @param v The string value
*/
LIAPI Any(const std::string& v);
/**
* @brief Construct a new Any object with const char* value.
*
* @param v The const char* value
*/
LIAPI Any(const char* v);
/**
* @brief Construct a new Any object with char* value.
*
* @param v The char* value
* @param len The length of the char* value
*/
LIAPI Any(char* v, size_t len);
/**
* @brief Construct a new Any object with date value.
*
* @param v The Date object
*/
LIAPI Any(const Date& v);
/**
* @brief Construct a new Any object with time value.
*
* @param v The Time object
*/
LIAPI Any(const Time& v);
/**
* @brief Construct a new Any object with date time value.
*
* @param v The DateTime object
*/
LIAPI Any(const DateTime& v);
/**
* @brief Construct a new Any object with int8(char) value.
*
* @param v The char value
*/
LIAPI Any(char v);
/**
* @brief Construct a new Any object with uint8(unsigned char) value.
*
* @param v The unsigned char value
*/
LIAPI Any(unsigned char v);
/**
* @brief Construct a new Any object with int16(short) value.
*
* @param v The short value
*/
LIAPI Any(short v);
/**
* @brief Construct a new Any object with uint16(unsigned short) value.
*
* @param v The unsigned short value
*/
LIAPI Any(unsigned short v);
/**
* @brief Construct a new Any object with int32(int) value.
*
* @param v The int value
*/
LIAPI Any(int v);
/**
* @brief Construct a new Any object with uint32(unsigned int) value.
*
* @param v The unsigned int value
*/
LIAPI Any(unsigned int v);
/**
* @brief Construct a new Any object with long value.
*
* @param v The long value
*/
LIAPI Any(long v);
/**
* @brief Construct a new Any object with unsigned long value.
*
* @param v The unsigned long value
*/
LIAPI Any(unsigned long v);
/**
* @brief Construct a new Any object with float value.
*
* @param v The float value
*/
LIAPI Any(float v);
/**
* @brief Construct a new Any object with byte array value.
*
* @param v The byte array value
*/
LIAPI Any(const ByteArray& v);
/// Copy constructor
LIAPI Any(const Any& v);
/// Copy assignment operator
LIAPI Any& operator=(const Any& v);
/// Destructor
LIAPI ~Any();
/**
* @brief Get if the value is null.
*
*/
LIAPI bool is_null() const;
/**
* @brief Get if the value is boolean.
*
*/
LIAPI bool is_boolean() const;
/**
* @brief Get if the value is (unsigned) integer.
*
*/
LIAPI bool is_integer() const;
/**
* @brief Get if the value is unsigned integer.
*
*/
LIAPI bool is_uinteger() const;
/**
* @brief Get if the value is floating.
*
*/
LIAPI bool is_floating() const;
/**
* @brief Get if the value is string.
*
*/
LIAPI bool is_string() const;
/**
* @brief Get if the value is date.
*
*/
LIAPI bool is_date() const;
/**
* @brief Get if the value is time.
*
*/
LIAPI bool is_time() const;
/**
* @brief Get if the value is date time.
*
*/
LIAPI bool is_datetime() const;
/**
* @brief Get if the value is blob.
*
*/
LIAPI bool is_blob() const;
/**
* @brief Get if the value is floating or (unsigned) integer.
*
*/
LIAPI bool is_number() const;
/**
* @brief Get the number value as T
*
* @tparam T The C++ basic number type to convert to, such as int, long, double, etc.
* @return T The value
* @throws std::bad_cast If the value cannot be converted to T or the value is not a number
* @note You can use Any::is_number() to check if the value is a number before calling this function.
* @see is_number()
*/
template <typename T>
inline T get_number() const
{
switch (type)
{
#if !defined(DBANY_NO_NULL_CONVERSION)
case Type::Null:
return 0;
#endif
case Type::Boolean:
return static_cast<T>(value.boolean);
case Type::Integer:
case Type::UInteger:
return static_cast<T>(value.integer);
case Type::Floating:
return static_cast<T>(value.floating);
case Type::String:
case Type::Date:
case Type::Time:
case Type::DateTime:
case Type::Blob:
default:
throw std::bad_cast();
}
}
/**
* @brief Get the value as T.
*
* @tparam T The type of the value
* @return T The value
* @throws std::bad_cast If the value cannot be converted to T
* @par Custom Type Conversion
* Define a custom type conversion function for the type T
* @code
* template <>
* MyClass any_to(const Any& v) {
* MyClass result;
* switch (v.type) {
* case Any::Type::String:
* result.a = *v.value.string;
* default:
* throw std::bad_cast();
* }
* return result;
* }
* @endcode
* @note You can use `#define DBANY_NO_NULL_CONVERSION` to disable null conversion.
* (throw an exception when trying converting from a null type value)
* @see any_to
*/
template <typename T>
inline T get() const
{
return any_to<T>(*this);
}
/**
* @brief Get the value as string
*
* @tparam T = bool
* @return bool The value
* @throws std::bad_cast If the value cannot be converted to string
*/
template <>
inline bool get() const
{
switch (type)
{
#if !defined(DBANY_NO_NULL_CONVERSION)
case Type::Null:
return false;
#endif
case Type::Boolean:
return value.boolean;
case Type::Integer:
case Type::UInteger:
case Type::Floating:
return (bool)value.integer;
case Type::String:
case Type::Date:
case Type::Time:
case Type::DateTime:
case Type::Blob:
default:
throw std::bad_cast();
}
}
/**
* @brief Get the value as char
*
* @tparam T = char
* @return char The value
* @throws std::bad_cast If the value cannot be converted to char
*/
template <>
inline char get() const
{
return get_number<char>();
}
/**
* @brief Get the value as unsigned char
*
* @tparam T = unsigned char
* @return unsigned char The value
* @throws std::bad_cast If the value cannot be converted to unsigned char
*/
template <>
inline unsigned char get() const
{
return get_number<unsigned char>();
}
/**
* @brief Get the value as short
*
* @tparam T = short
* @return short The value
* @throws std::bad_cast If the value cannot be converted to short
*/
template <>
inline short get() const
{
return get_number<short>();
}
/**
* @brief Get the value as unsigned short
*
* @tparam T = unsigned short
* @return unsigned short The value
* @throws std::bad_cast If the value cannot be converted to unsigned short
*/
template <>
inline unsigned short get() const
{
return get_number<unsigned short>();
}
/**
* @brief Get the value as int
*
* @tparam T = int
* @return int The value
* @throws std::bad_cast If the value cannot be converted to int
*/
template <>
inline int get() const
{
return get_number<int>();
}
/**
* @brief Get the value as unsigned int
*
* @tparam T = unsigned int
* @return unsigned int The value
* @throws std::bad_cast If the value cannot be converted to unsigned int
*/
template <>
inline unsigned int get() const
{
return get_number<unsigned int>();
}
/**
* @brief Get the value as long
*
* @tparam T = long
* @return long The value
* @throws std::bad_cast If the value cannot be converted to long
*/
template <>
inline long get() const
{
return get_number<long>();
}
/**
* @brief Get the value as unsigned long
*
* @tparam T = unsigned long
* @return unsigned long The value
* @throws std::bad_cast If the value cannot be converted to unsigned long
*/
template <>
inline unsigned long get() const
{
return get_number<unsigned long>();
}
/**
* @brief Get the value as long long
*
* @tparam T = long long
* @return long long The value
* @throws std::bad_cast If the value cannot be converted to long long
*/
template <>
inline long long get() const
{
return get_number<long long>();
}
/**
* @brief Get the value as unsigned long long
*
* @tparam T = unsigned long long
* @return unsigned long long The value
* @throws std::bad_cast If the value cannot be converted to unsigned long long
*/
template <>
inline unsigned long long get() const
{
return get_number<unsigned long long>();
}
/**
* @brief Get the value as double.
*
* @tparam T = double
* @return double The value
* @throws std::bad_cast If the value cannot be converted to double
*/
template <>
inline double get() const
{
return get_number<double>();
}
/**
* @brief Get the value as float.
*
* @tparam T = float
* @return float The value
* @throws std::bad_cast If the value cannot be converted to float
*/
template <>
inline float get() const
{
return get_number<float>();
}
/**
* @brief Get the value as string.
*
* @tparam T = std::string
* @return std::string The value
* @throws std::bad_cast If the value cannot be converted to string
*/
template <>
std::string get() const
{
switch (type)
{
#if !defined(DBANY_NO_NULL_CONVERSION)
case Type::Null:
return "";
#endif
case Type::Boolean:
return value.boolean ? "true" : "false";
case Type::Integer:
return std::to_string(value.integer);
case Type::UInteger:
return std::to_string(value.uinteger);
case Type::Floating:
return std::to_string(value.floating);
case Type::String:
return *value.string;
case Type::Date:
return std::to_string(value.date->year) + "-" +
std::to_string(value.date->month) + "-" +
std::to_string(value.date->day);
break;
case Type::Time:
return std::to_string(value.time->hour) + ":" +
std::to_string(value.time->minute) + ":" +
std::to_string(value.time->second);
case Type::DateTime:
return std::to_string(value.datetime->date.year) + "-" +
std::to_string(value.datetime->date.month) + "-" +
std::to_string(value.datetime->date.day) + " " +
std::to_string(value.datetime->time.hour) + ":" +
std::to_string(value.datetime->time.minute) + ":" +
std::to_string(value.datetime->time.second);
case Type::Blob:
return std::string(value.blob->begin(), value.blob->end());
default:
throw std::bad_cast();
}
}
/**
* @brief Get the value as Date
*
* @tparam T = DB::Date
* @return DB::Date The value
* @throws std::bad_cast If the value cannot be converted to DB::Date
*/
template <>
Date get() const
{
switch (type)
{
case Type::Date:
return *value.date;
case Type::DateTime:
return value.datetime->date;
case Type::String:
case Type::Integer:
case Type::UInteger:
case Type::Floating:
case Type::Time:
case Type::Blob:
default:
throw std::bad_cast();
}
}
/**
* @brief Get the value as Time
*
* @tparam T = DB::Time
* @return DB::Time The value
* @throws std::bad_cast If the value cannot be converted to DB::Time
*/
template <>
Time get() const
{
switch (type)
{
case Type::Time:
return *value.time;
case Type::DateTime:
return value.datetime->time;
case Type::String:
case Type::Integer:
case Type::UInteger:
case Type::Floating:
case Type::Date:
case Type::Blob:
default:
throw std::bad_cast();
}
}
/**
* @brief Get the value as DateTime
*
* @tparam T = DB::DateTime
* @return DB::DateTime The value
* @throws std::bad_cast If the value cannot be converted to DB::DateTime
*/
template <>
DateTime get() const
{
switch (type)
{
case Type::DateTime:
return *value.datetime;
case Type::String:
case Type::Integer:
case Type::UInteger:
case Type::Floating:
case Type::Date:
case Type::Time:
case Type::Blob:
default:
throw std::bad_cast();
}
}
/**
* @brief Get the value as ByteArray
*
* @tparam T = DB::ByteArray
* @return DB::ByteArray The value
* @throws std::bad_cast If the value cannot be converted to DB::ByteArray
*/
template <>
ByteArray get() const
{
switch (type)
{
case Type::Blob:
return *value.blob;
case Type::String:
return ByteArray((unsigned char*)value.string->data(),
(unsigned char*)value.string->data() + value.string->size());
case Type::Integer:
case Type::UInteger:
case Type::Floating:
case Type::Date:
case Type::Time:
case Type::DateTime:
default:
throw std::bad_cast();
}
}
/**
* @brief Convert Any::Type to string.
*
* @param type The Any::Type value
* @return std::string The string value
*/
LIAPI static std::string type2str(Any::Type type);
/**
* @brief Convert string to Any.
*
* @param str The string
* @return Any The converted value
*/
LIAPI static Any str2any(const std::string& str);
};
} // namespace DB