// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include #include #include #include #include namespace Sqlite { template class BasicId { template friend class CompoundBasicId; public: using IsBasicId = std::true_type; using DatabaseType = InternalIntegerType; constexpr explicit BasicId() = default; static constexpr BasicId create(InternalIntegerType idNumber) { BasicId id; id.id = idNumber; return id; } template static constexpr BasicId createSpecialState(Enumeration specialState) { BasicId id; id.id = ::Utils::to_underlying(specialState); return id; } friend constexpr bool compareInvalidAreTrue(BasicId first, BasicId second) { return first.id == second.id; } friend constexpr bool operator==(BasicId first, BasicId second) { return first.id == second.id && first.isValid(); } friend constexpr auto operator<=>(BasicId first, BasicId second) = default; constexpr friend InternalIntegerType operator-(BasicId first, BasicId second) { return first.id - second.id; } constexpr bool isValid() const { return id > 0; } constexpr bool isNull() const { return id == 0; } template constexpr bool hasSpecialState(Enumeration specialState) const { return id == ::Utils::to_underlying(specialState); } explicit operator bool() const { return isValid(); } explicit operator std::size_t() const { return static_cast(id); } constexpr InternalIntegerType internalId() const { return id; } [[noreturn, deprecated]] InternalIntegerType operator&() const { throw std::exception{}; } template friend void convertToString(String &string, BasicId id) { NanotraceHR::convertToString(string, id.id); } friend bool compareId(BasicId first, BasicId second) { return first.id == second.id; } protected: InternalIntegerType id = 0; }; template class CompoundBasicId { public: using IsBasicId = std::true_type; using DatabaseType = long long; using MainId = BasicId; using ContextId = BasicId; constexpr explicit CompoundBasicId() = default; static constexpr CompoundBasicId create(MainId id, ContextId contextId) { CompoundBasicId compoundId; compoundId.id = (static_cast(contextId.id) << 32) | static_cast(id.id); return compoundId; } static constexpr CompoundBasicId create(long long idNumber) { CompoundBasicId id; id.id = idNumber; return id; } constexpr MainId mainId() const { return MainId::create(id); } constexpr ContextId contextId() const { return ContextId::create(id >> 32); } friend constexpr bool compareInvalidAreTrue(CompoundBasicId first, CompoundBasicId second) { return first.id == second.id; } friend constexpr bool operator==(CompoundBasicId first, CompoundBasicId second) { return first.id == second.id && first.isValid(); } friend constexpr auto operator<=>(CompoundBasicId first, CompoundBasicId second) = default; constexpr bool isValid() const { return id != 0; } constexpr bool isNull() const { return id == 0; } explicit operator bool() const { return isValid(); } long long internalId() const { return id; } explicit operator std::size_t() const { return static_cast(id | 0xFFFFFFFFULL); } template friend void convertToString(String &string, CompoundBasicId id) { int mainId = id.id; int contextId = id.id >> 32; convertToString(string, mainId); convertToString(string, contextId); } friend bool compareId(CompoundBasicId first, CompoundBasicId second) { return first.id == second.id; } protected: long long id = 0; }; template auto toIntegers(const Container &container) { using DataType = typename Container::value_type::DatabaseType; const DataType *data = reinterpret_cast(container.data()); return Utils::span{data, container.size()}; } } // namespace Sqlite namespace std { template struct hash> { auto operator()(const Sqlite::BasicId &id) const { return std::hash{}(id.internalId()); } }; } // namespace std