aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetaenum.cpp')
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.cpp423
1 files changed, 423 insertions, 0 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
new file mode 100644
index 000000000..780170c22
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
@@ -0,0 +1,423 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "abstractmetaenum.h"
+#include "abstractmetalang.h"
+#include "documentation.h"
+#include "enumtypeentry.h"
+#include "parser/enumvalue.h"
+
+#include "qtcompat.h"
+
+#include <QtCore/QDebug>
+
+#include <algorithm>
+
+using namespace Qt::StringLiterals;
+
+class AbstractMetaEnumValueData : public QSharedData
+{
+public:
+ QString m_name;
+ QString m_stringValue;
+ EnumValue m_value;
+ Documentation m_doc;
+ bool m_deprecated = false;
+};
+
+AbstractMetaEnumValue::AbstractMetaEnumValue() :
+ d(new AbstractMetaEnumValueData)
+{
+}
+
+AbstractMetaEnumValue::AbstractMetaEnumValue(const AbstractMetaEnumValue &) = default;
+AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(const AbstractMetaEnumValue &) = default;
+AbstractMetaEnumValue::AbstractMetaEnumValue(AbstractMetaEnumValue &&) noexcept = default;
+AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(AbstractMetaEnumValue &&) noexcept = default;
+AbstractMetaEnumValue::~AbstractMetaEnumValue() = default;
+
+EnumValue AbstractMetaEnumValue::value() const
+{
+ return d->m_value;
+}
+
+void AbstractMetaEnumValue::setValue(EnumValue value)
+{
+ if (d->m_value != value)
+ d->m_value = value;
+}
+
+QString AbstractMetaEnumValue::stringValue() const
+{
+ return d->m_stringValue;
+}
+
+void AbstractMetaEnumValue::setStringValue(const QString &v)
+{
+ if (d->m_stringValue != v)
+ d->m_stringValue = v;
+}
+
+QString AbstractMetaEnumValue::name() const
+{
+ return d->m_name;
+}
+
+void AbstractMetaEnumValue::setName(const QString &name)
+{
+ if (d->m_name != name)
+ d->m_name = name;
+}
+
+bool AbstractMetaEnumValue::isDeprecated() const
+{
+ return d->m_deprecated;
+}
+
+void AbstractMetaEnumValue::setDeprecated(bool deprecated)
+{
+ if (d->m_deprecated != deprecated)
+ d->m_deprecated = deprecated;
+}
+
+Documentation AbstractMetaEnumValue::documentation() const
+{
+ return d->m_doc;
+}
+
+void AbstractMetaEnumValue::setDocumentation(const Documentation &doc)
+{
+ if (d->m_doc != doc)
+ d->m_doc = doc;
+}
+
+// --------------------- AbstractMetaEnum
+
+class AbstractMetaEnumData : public QSharedData
+{
+public:
+ AbstractMetaEnumData() : m_deprecated(false),
+ m_hasQenumsDeclaration(false), m_signed(true)
+ {
+ }
+
+ int unsignedUsedBits() const;
+ int signedUsedBits() const;
+
+ AbstractMetaEnumValueList m_enumValues;
+
+ EnumTypeEntryCPtr m_typeEntry;
+ Documentation m_doc;
+ QString m_underlyingType;
+
+ EnumKind m_enumKind = CEnum;
+ Access m_access = Access::Public;
+ uint m_deprecated : 1;
+ uint m_hasQenumsDeclaration : 1;
+ uint m_signed : 1;
+};
+
+static int _usedBits(uint64_t v)
+{
+ return (v >> 32) ? 64 : (v >> 16) ? 32 : (v >> 8) ? 16 : 8;
+}
+
+static int _usedBits(int64_t v)
+{
+ return (v >> 31) ? 64 : (v >> 15) ? 32 : (v >> 7) ? 16 : 8;
+}
+
+int AbstractMetaEnumData::unsignedUsedBits() const
+{
+ uint64_t maxValue = 0;
+ for (const auto &v : m_enumValues) {
+ if (const auto uv = v.value().unsignedValue(); uv > maxValue)
+ maxValue = uv;
+ }
+ return _usedBits(maxValue);
+}
+
+int AbstractMetaEnumData::signedUsedBits() const
+{
+ int64_t maxValue = 0;
+ for (const auto &v : m_enumValues) {
+ const auto sv = v.value().value();
+ const auto absV = sv < 0 ? ~sv : sv;
+ if (absV > maxValue)
+ maxValue = absV;
+ }
+ return _usedBits(maxValue);
+}
+
+AbstractMetaEnum::AbstractMetaEnum() : d(new AbstractMetaEnumData)
+{
+}
+
+AbstractMetaEnum::AbstractMetaEnum(const AbstractMetaEnum &) = default;
+AbstractMetaEnum &AbstractMetaEnum::operator=(const AbstractMetaEnum&) = default;
+AbstractMetaEnum::AbstractMetaEnum(AbstractMetaEnum &&) noexcept = default;
+AbstractMetaEnum &AbstractMetaEnum::operator=(AbstractMetaEnum &&) noexcept = default;
+AbstractMetaEnum::~AbstractMetaEnum() = default;
+
+const AbstractMetaEnumValueList &AbstractMetaEnum::values() const
+{
+ return d->m_enumValues;
+}
+
+AbstractMetaEnumValueList AbstractMetaEnum::nonRejectedValues() const
+{
+ auto te = d->m_typeEntry;
+ AbstractMetaEnumValueList result = d->m_enumValues;
+ auto pred = [te](const AbstractMetaEnumValue &v) {
+ return te->isEnumValueRejected(v.name()); };
+ result.erase(std::remove_if(result.begin(), result.end(), pred), result.end());
+ return result;
+}
+
+void AbstractMetaEnum::addEnumValue(const AbstractMetaEnumValue &enumValue)
+{
+ d->m_enumValues << enumValue;
+}
+
+std::optional<AbstractMetaEnumValue>
+ findMatchingEnumValue(const AbstractMetaEnumValueList &list, QStringView value)
+{
+ for (const AbstractMetaEnumValue &enumValue : list) {
+ if (enumValue.name() == value)
+ return enumValue;
+ }
+ return {};
+}
+
+// Find enum values for "enum Enum { e1 }" either for "e1" or "Enum::e1"
+std::optional<AbstractMetaEnumValue>
+ AbstractMetaEnum::findEnumValue(QStringView value) const
+{
+ if (isAnonymous())
+ return findMatchingEnumValue(d->m_enumValues, value);
+ const int sepPos = value.indexOf(u"::");
+ if (sepPos == -1)
+ return findMatchingEnumValue(d->m_enumValues, value);
+ if (name() == value.left(sepPos))
+ return findMatchingEnumValue(d->m_enumValues, value.right(value.size() - sepPos - 2));
+ return {};
+}
+
+QString AbstractMetaEnum::name() const
+{
+ return d->m_typeEntry->targetLangEntryName();
+}
+
+QString AbstractMetaEnum::qualifiedCppName() const
+{
+ return enclosingClass()
+ ? enclosingClass()->qualifiedCppName() + u"::"_s + name()
+ : name();
+}
+
+Access AbstractMetaEnum::access() const
+{
+ return d->m_access;
+}
+
+void AbstractMetaEnum::setAccess(Access a)
+{
+ if (a != d->m_access)
+ d->m_access = a;
+}
+
+bool AbstractMetaEnum::isDeprecated() const
+{
+ return d->m_deprecated;
+}
+
+void AbstractMetaEnum::setDeprecated(bool deprecated)
+{
+ if (d->m_deprecated != deprecated)
+ d->m_deprecated = deprecated;
+}
+
+static bool isDeprecatedValue(const AbstractMetaEnumValue &v)
+{
+ return v.isDeprecated();
+};
+
+bool AbstractMetaEnum::hasDeprecatedValues() const
+{
+ return std::any_of(d->m_enumValues.cbegin(), d->m_enumValues.cend(),
+ isDeprecatedValue);
+}
+
+AbstractMetaEnumValueList AbstractMetaEnum::deprecatedValues() const
+{
+ AbstractMetaEnumValueList result;
+ std::copy_if(d->m_enumValues.cbegin(), d->m_enumValues.cend(),
+ std::back_inserter(result), isDeprecatedValue);
+ return result;
+}
+
+const Documentation &AbstractMetaEnum::documentation() const
+{
+ return d->m_doc;
+}
+
+void AbstractMetaEnum::setDocumentation(const Documentation &doc)
+{
+ if (d->m_doc != doc)
+ d->m_doc = doc;
+}
+
+QString AbstractMetaEnum::qualifier() const
+{
+ return d->m_typeEntry->targetLangQualifier();
+}
+
+QString AbstractMetaEnum::package() const
+{
+ return d->m_typeEntry->targetLangPackage();
+}
+
+QString AbstractMetaEnum::fullName() const
+{
+ return package() + u'.' + qualifier() + u'.' + name();
+}
+
+EnumKind AbstractMetaEnum::enumKind() const
+{
+ return d->m_enumKind;
+}
+
+void AbstractMetaEnum::setEnumKind(EnumKind kind)
+{
+ if (d->m_enumKind != kind)
+ d->m_enumKind = kind;
+}
+
+bool AbstractMetaEnum::isAnonymous() const
+{
+ return d->m_enumKind == AnonymousEnum;
+}
+
+bool AbstractMetaEnum::hasQEnumsDeclaration() const
+{
+ return d->m_hasQenumsDeclaration;
+}
+
+void AbstractMetaEnum::setHasQEnumsDeclaration(bool on)
+{
+ if (d->m_hasQenumsDeclaration != on)
+ d->m_hasQenumsDeclaration = on;
+}
+
+EnumTypeEntryCPtr AbstractMetaEnum::typeEntry() const
+{
+ return d->m_typeEntry;
+}
+
+void AbstractMetaEnum::setTypeEntry(const EnumTypeEntryCPtr &entry)
+{
+ if (d->m_typeEntry != entry)
+ d->m_typeEntry = entry;
+}
+
+bool AbstractMetaEnum::isSigned() const
+{
+ return d->m_signed;
+}
+
+void AbstractMetaEnum::setSigned(bool s)
+{
+ if (d->m_signed != s)
+ d->m_signed = s;
+}
+
+QString AbstractMetaEnum::underlyingType() const
+{
+ return d->m_underlyingType;
+}
+
+void AbstractMetaEnum::setUnderlyingType(const QString &underlyingType)
+{
+ if (d->m_underlyingType != underlyingType)
+ d->m_underlyingType = underlyingType;
+}
+
+int AbstractMetaEnum::usedBits() const
+{
+ return isSigned() ? d->signedUsedBits() : d->unsignedUsedBits();
+}
+
+QString AbstractMetaEnum::intTypeForSize(int usedBits, bool isSigned)
+{
+ QString result = u"int"_s + QString::number(usedBits) + u"_t"_s;
+ return isSigned ? result : u'u' + result;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue &v, bool forceHex = false)
+{
+ d << v.name() << '=';
+ if (forceHex)
+ v.value().formatDebugHex(d);
+ else
+ v.value().formatDebug(d);
+ if (v.isDeprecated())
+ d << " (deprecated)";
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaEnumValue &v)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaEnumValue(";
+ formatMetaEnumValue(d, v);
+ d << ')';
+ return d;
+}
+
+static void formatMetaEnum(QDebug &d, const AbstractMetaEnum &e)
+{
+ d << '"' << e.fullName() << '"';
+ if (e.isDeprecated())
+ d << " (deprecated)";
+ d << " \"" << e.underlyingType() << '"';
+ if (!e.isSigned())
+ d << " (unsigned)";
+ d << " [";
+ const AbstractMetaEnumValueList &values = e.values();
+ const bool hasFlags = e.typeEntry()->flags() != nullptr;
+ for (qsizetype i = 0, count = values.size(); i < count; ++i) {
+ if (i)
+ d << ", ";
+ formatMetaEnumValue(d, values.at(i), hasFlags);
+ }
+ d << ']';
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaEnum *ae)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaEnum(";
+ if (ae)
+ formatMetaEnum(d, *ae);
+ else
+ d << '0';
+ d << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaEnum &ae)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaEnum(";
+ formatMetaEnum(d, ae);
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM