/**************************************************************************** ** ** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "sqliteexception.h" #include #include #include #pragma once namespace Sqlite { enum class ValueType : unsigned char { Integer, Float, String }; template class ValueBase { public: using VariantType = Utils::variant; explicit ValueBase(VariantType &&value) : value(value) {} explicit ValueBase(const char *value) : value(Utils::SmallStringView{value}) {} explicit ValueBase(long long value) : value(value) {} explicit ValueBase(int value) : value(static_cast(value)) {} explicit ValueBase(uint value) : value(static_cast(value)) {} explicit ValueBase(double value) : value(value) {} explicit ValueBase(Utils::SmallStringView value) : value(value) {} long long toInteger() const { return Utils::get(value); } double toFloat() const { return Utils::get(value); } Utils::SmallStringView toStringView() const { return Utils::get(value); } explicit operator QVariant() const { switch (type()) { case ValueType::Integer: return QVariant(toInteger()); case ValueType::Float: return QVariant(toFloat()); case ValueType::String: return QVariant(QString(toStringView())); } return {}; } friend bool operator==(const ValueBase &first, long long second) { auto maybeInteger = Utils::get_if(&first.value); return maybeInteger && *maybeInteger == second; } friend bool operator==(long long first, const ValueBase &second) { return second == first; } friend bool operator==(const ValueBase &first, double second) { auto maybeInteger = Utils::get_if(&first.value); return maybeInteger && *maybeInteger == second; } friend bool operator==(const ValueBase &first, int second) { return first == static_cast(second); } friend bool operator==(int first, const ValueBase &second) { return second == first; } friend bool operator==(const ValueBase &first, uint second) { return first == static_cast(second); } friend bool operator==(uint first, const ValueBase &second) { return second == first; } friend bool operator==(double first, const ValueBase &second) { return second == first; } friend bool operator==(const ValueBase &first, Utils::SmallStringView second) { auto maybeInteger = Utils::get_if(&first.value); return maybeInteger && *maybeInteger == second; } friend bool operator==(Utils::SmallStringView first, const ValueBase &second) { return second == first; } friend bool operator==(const ValueBase &first, const QString &second) { auto maybeInteger = Utils::get_if(&first.value); return maybeInteger && second == QLatin1String{maybeInteger->data(), int(maybeInteger->size())}; } friend bool operator==(const QString &first, const ValueBase &second) { return second == first; } friend bool operator==(const ValueBase &first, const char *second) { return first == Utils::SmallStringView{second}; } friend bool operator==(const char *first, const ValueBase &second) { return second == first; } friend bool operator==(const ValueBase &first, const ValueBase &second) { return first.value == second.value; } friend bool operator!=(const ValueBase &first, const ValueBase &second) { return !(first.value == second.value); } ValueType type() const { switch (value.index()) { case 0: return ValueType::Integer; case 1: return ValueType::Float; case 2: return ValueType::String; } return {}; } public: VariantType value; }; class ValueView : public ValueBase { public: explicit ValueView(ValueBase &&base) : ValueBase(std::move(base)) {} template static ValueView create(Type &&value) { return ValueView{ValueBase{value}}; } }; class Value : public ValueBase { using Base = ValueBase; public: using Base::Base; explicit Value(ValueView view) : ValueBase(convert(view)) {} explicit Value(const QVariant &value) : ValueBase(convert(value)) {} explicit Value(Utils::SmallString &&value) : ValueBase(VariantType{std::move(value)}) {} explicit Value(const Utils::SmallString &value) : ValueBase(Utils::SmallStringView(value)) {} explicit Value(const QString &value) : ValueBase(VariantType{Utils::SmallString(value)}) {} friend bool operator!=(const Value &first, const Value &second) { return !(first.value == second.value); } template friend bool operator!=(const Value &first, const Type &second) { return !(first == second); } template friend bool operator!=(const Type &first, const Value &second) { return !(first == second); } friend bool operator==(const Value &first, const ValueView &second) { if (first.type() != second.type()) return false; switch (first.type()) { case ValueType::Integer: return first.toInteger() == second.toInteger(); case ValueType::Float: return first.toFloat() == second.toFloat(); case ValueType::String: return first.toStringView() == second.toStringView(); } return false; } friend bool operator==(const ValueView &first, const Value &second) { return second == first; } private: static Base::VariantType convert(const QVariant &value) { switch (value.type()) { case QVariant::Int: return VariantType{static_cast(value.toInt())}; case QVariant::LongLong: return VariantType{value.toLongLong()}; case QVariant::UInt: return VariantType{static_cast(value.toUInt())}; case QVariant::Double: return VariantType{value.toFloat()}; case QVariant::String: return VariantType{value.toString()}; default: throw CannotConvert("Cannot convert this QVariant to a ValueBase"); } } static Base::VariantType convert(ValueView view) { switch (view.type()) { case ValueType::Integer: return VariantType{view.toInteger()}; case ValueType::Float: return VariantType{view.toFloat()}; case ValueType::String: return VariantType{view.toStringView()}; default: throw CannotConvert("Cannot convert this QVariant to a ValueBase"); } } }; using Values = std::vector; } // namespace Sqlite