#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 #include #include namespace matador::utils { class identifier_serializer { public: virtual ~identifier_serializer() = default; 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 struct identifier_type_traits; template struct identifier_type_traits>> { static bool is_valid(Type value) { return value > 0; } static std::string to_string(const Type value) { return std::to_string(value); } }; template struct identifier_type_traits>> { 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 { static bool is_valid() { return false; } static std::string to_string() { return "null"; } }; template<> struct identifier_type_traits { static bool is_valid(const char *value); static std::string to_string(const char *value); }; namespace detail { template size_t hash(const Type &value) { return std::hash()(value); } size_t hash(const char *value); } class identifier { private: struct base { 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; [[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; [[nodiscard]] virtual std::string str() const = 0; [[nodiscard]] virtual size_t hash() const = 0; std::type_index type_index_; basic_type type_{basic_type::type_null}; }; template struct pk final : base { using self = pk; explicit pk(const IdType &id) : base(std::type_index(typeid(IdType)), data_type_traits::type(1)) , id_(id) , size_(sizeof(IdType)) {} [[nodiscard]] base *copy() const override { return new self(id_); } [[nodiscard]] bool equal_to(const base &x) const override { return static_cast(x).id_ == id_; } [[nodiscard]] bool less(const base &x) const override { return id_ < static_cast(x).id_; } [[nodiscard]] bool is_valid() const override { return identifier_type_traits::is_valid(id_); } [[nodiscard]] std::string str() const override { return identifier_type_traits::to_string(id_); } void serialize(identifier_serializer &s) override { s.serialize(id_, size_); } [[nodiscard]] size_t hash() const override { return detail::hash(id_); } IdType id_; size_t size_{}; }; struct null_pk final : base { null_pk(); [[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 explicit identifier(const Type &id) : id_(std::make_shared>(id)) {} explicit identifier(const char *id) : id_(std::make_shared>(id)) {} identifier(const identifier &x); identifier &operator=(const identifier &x); identifier(identifier &&x) noexcept ; identifier &operator=(identifier &&x) noexcept; template identifier& operator=(const Type &value) { id_ = std::make_shared>(value); return *this; } identifier& operator=(const char *value) { id_ = std::make_shared>(value); return *this; } ~identifier() = default; bool operator==(const identifier &x) const; bool operator!=(const identifier &x) const; bool operator<(const identifier &x) const; bool operator<=(const identifier &x) const; bool operator>(const identifier &x) const; bool operator>=(const identifier &x) const; [[nodiscard]] std::string str() const; [[nodiscard]] const std::type_index &type_index() const; [[nodiscard]] basic_type type() const; [[nodiscard]] identifier share() const; [[nodiscard]] 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; [[nodiscard]] bool is_valid() const; void clear(); void serialize(identifier_serializer &s) const; [[nodiscard]] size_t hash() const; friend std::ostream &operator<<(std::ostream &out, const identifier &id); private: explicit identifier(const std::shared_ptr& id); private: std::shared_ptr id_; }; static identifier null_identifier{}; /// @cond MATADOR_DEV struct id_pk_hash { size_t operator()(const identifier &id) const; }; /// @endcond } #endif //MATADOR_IDENTIFIER_HPP