summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/time/qcalendar.cpp125
-rw-r--r--src/corelib/time/qcalendar.h16
-rw-r--r--src/corelib/time/qcalendarbackend_p.h8
-rw-r--r--src/corelib/time/qgregoriancalendar.cpp2
-rw-r--r--src/corelib/time/qislamiccivilcalendar.cpp4
-rw-r--r--src/corelib/time/qjalalicalendar.cpp4
-rw-r--r--src/corelib/time/qjuliancalendar.cpp4
-rw-r--r--src/corelib/time/qmilankoviccalendar.cpp4
8 files changed, 107 insertions, 60 deletions
diff --git a/src/corelib/time/qcalendar.cpp b/src/corelib/time/qcalendar.cpp
index be0ea5e202..4a245f6d3f 100644
--- a/src/corelib/time/qcalendar.cpp
+++ b/src/corelib/time/qcalendar.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -81,7 +81,6 @@ inline size_t qHash(const CalendarName &key, size_t seed = 0) noexcept
return qHash(key.toLower(), seed);
}
-constexpr size_t invalidBackendId = ~size_t(0);
static QBasicMutex registryMutex; // Protects registry from concurrent access
struct Registry
@@ -106,7 +105,7 @@ struct Registry
bool registerName(QCalendarBackend *calendar, const QString &name)
{
Q_ASSERT(!name.isEmpty());
- if (status.loadRelaxed() > 1 || name.isEmpty() || calendar->calendarId() == invalidBackendId)
+ if (status.loadRelaxed() > 1 || name.isEmpty() || !calendar->calendarId().isValid())
return false;
const auto lock = qt_scoped_lock(registryMutex);
@@ -127,18 +126,18 @@ struct Registry
If \a id is QCalendar::System::User, a new unique ID is allocated;
otherwise, \a id must be a member of the QCalendar::System enumeration
and the \a calendar is registered with that as its ID unless this ID is
- already in use, in which case registration fails and \c{~size_t(0)} is
- returned. In (only) this last case, the caller is responsible for
- destruction. Otherwise, registry destruction will take care of it on
- program exit.
+ already in use, in which case registration fails and
+ \c{~QCalendar::SystemId(0)} is returned. In (only) this last case, the
+ caller is responsible for destruction. Otherwise, registry destruction
+ will take care of it on program exit.
*/
size_t registerId(QCalendarBackend *calendar, QCalendar::System system)
{
if (status.loadRelaxed() > 1)
- return invalidBackendId;
+ return QCalendar::SystemId().index();
const auto lock = qt_scoped_lock(registryMutex);
- size_t index = size_t(system);
+ auto index = size_t(system);
if (system == QCalendar::System::User) {
index = byId.size();
byId.push_back(calendar);
@@ -148,7 +147,7 @@ struct Registry
Q_ASSERT(byId[index] == nullptr);
byId[index] = calendar;
} else {
- return invalidBackendId;
+ return QCalendar::SystemId().index();
}
if (system == QCalendar::System::Gregorian) {
// Only the first QGregorianCalendar can get here, so this should succeed:
@@ -173,7 +172,7 @@ struct Registry
return;
const auto lock = qt_scoped_lock(registryMutex);
- const size_t id = calendar->calendarId();
+ const size_t id = calendar->calendarId().index();
if (~id && byId[id] == calendar)
byId[id] = nullptr; // potentially purge nullptr entries from tail of byId[Last+1:] ?
for (auto i = byName.begin(); i != byName.end(); ) {
@@ -250,7 +249,7 @@ static const QCalendarBackend *backendFromEnum(QCalendar::System system)
if (!backend)
return backend;
// Check for successful registration:
- if (~backend->calendarId()) {
+ if (backend->calendarId().isValid()) {
#if defined(QT_FORCE_ASSERTS) || !defined(QT_NO_DEBUG)
const auto lock = qt_scoped_lock(registryMutex);
Q_ASSERT(backend == calendarRegistry->byId[size_t(system)]);
@@ -326,8 +325,8 @@ static const QCalendarBackend *backendFromEnum(QCalendar::System system)
the registry in which QCalendar records backends.
The single exception to this is that each backend's instantiator should
- verify that it was registered successfully. If its calendarId() is
- \c{~size_t(0)}, it has not been registered and attempts to register aliases
+ verify that it was registered successfully. If its calendarId()'s isValid()
+ is \c{false}, it has not been registered and attempts to register aliases
for it shall fail. In such a case, the instantiator retains ownership of the
backend instance; it will not be accessible to QCalendar. Note that (since
Qt 6.1) a backend may be successfully registered by ID without being
@@ -339,8 +338,8 @@ static const QCalendarBackend *backendFromEnum(QCalendar::System system)
other code should ever instantiate one. As noted above, such a backend must
be a singleton. Its constructor passes down the \c enum member that
identifies it as \c system to the base-class constructor; this is also its
- calendarSystem(). Its unique ID (see \l calendarId()) shall be the \c size_t
- equivalent to this \c system value.
+ calendarSystem(). Its unique ID (see \l calendarId()) shall be the \c
+ QCalendar::SystemId equivalent to this \c system value.
The shareable base-classes for backends, QRomanCalendar and QHijriCalendar,
are not themselves identified by QCalendar::System and may be used as
@@ -357,16 +356,16 @@ static const QCalendarBackend *backendFromEnum(QCalendar::System system)
On successful registration, the calendar backend registry takes over
ownership of the instance and shall delete it on program exit in the course
of the registry's own destruction. The instance can determine whether it was
- successfully registered by testing \c{~calendarId()}: this shall be zero
- precisely if registration failed. QCalendar cannot use an unregistered
+ successfully registered by testing \c{calendarId().isValid()}: this shall be
+ zero precisely if registration failed. QCalendar cannot use an unregistered
backend and the code that instantiated it is responsible for deleting it.
The \a system is optional and should only be passed by built-in
implementations of the standard calendars documented in \l
QCalendar::System. When \a system is passed, unless a backend is already
registered for this \c enum value, the backend is registered with
- \c{size_t(system)} as its ID. Custom backends should not pass \a
- system. When it is not passed, the backend is allocated a unique calendar
+ \c{QCalendar::SystemId(system)} as its ID. Custom backends should not pass
+ \a system. When it is not passed, the backend is allocated a unique calendar
ID, which shall be accessible as \l calendarId(). This ID can (since Qt 6.1)
be used to instantiate a QCalendar using the given backend, avoiding
problems with potential clashes of name or alias.
@@ -419,7 +418,7 @@ QCalendarBackend::QCalendarBackend(const QString &name, QCalendar::System system
if (!name.isEmpty())
calendarRegistry->registerName(this, name);
} else {
- Q_ASSERT(size_t(system) <= size_t(QCalendar::System::Last));
+ Q_ASSERT(QCalendar::SystemId(system).isInEnum());
}
}
@@ -432,8 +431,8 @@ QCalendarBackend::QCalendarBackend(const QString &name, QCalendar::System system
successfully-registered backend otherwise may leave existing QCalendar
instances referencing the destroyed calendar, with undefined results.
- However, if a backend, when instantiated, has calendarId() equal to
- \c{~size_t(0)}, it has not been registered and cannot be accessed by
+ However, if a backend, when instantiated, has a calendarId() whose \c
+ isValid() is \c{false}, it has not been registered and cannot be accessed by
QCalendar. Code that instantiates backends must check for this and delete
the unusable backend object, as it shall be leaked otherwise. This is the
only case in which client code needs to delete a backend.
@@ -447,16 +446,16 @@ QCalendarBackend::QCalendarBackend(const QString &name, QCalendar::System system
QCalendarBackend::~QCalendarBackend()
{
// No registration to undo unless registry exists and gave this a valid ID:
- if (calendarRegistry.exists() && ~calendarId())
+ if (calendarRegistry.exists() && calendarId().isValid())
calendarRegistry->unRegister(this);
}
/*!
\since 6.2
- \fn size_t QCalendarBackend::calendarId() const
+ \fn QCalendar::SystemId QCalendarBackend::calendarId() const
Each backend is allocated an ID when successfully registered as part of
- instantiation. A backend for which calendarId() is \c{~size_t(0)} has not
+ instantiation. A backend whose calendarId() has isValid() \c{false} has not
been successfully registered and the code that created it must take care to
ensure it is deleted; it also cannot be used, as it is not known to any of
the available ways to create a QCalendar.
@@ -478,9 +477,7 @@ QCalendarBackend::~QCalendarBackend()
*/
QCalendar::System QCalendarBackend::calendarSystem() const
{
- if (m_id > size_t(QCalendar::System::Last))
- return QCalendar::System::User;
- return QCalendar::System(m_id);
+ return m_id.isInEnum() ? QCalendar::System(m_id.index()) : QCalendar::System::User;
}
/*!
@@ -929,14 +926,15 @@ const QCalendarBackend *QCalendarBackend::fromName(QLatin1String name)
\sa fromEnum(), calendarId()
*/
-const QCalendarBackend *QCalendarBackend::fromId(size_t id)
+const QCalendarBackend *QCalendarBackend::fromId(QCalendar::SystemId id)
{
- if (calendarRegistry.isDestroyed() || !~id)
+ if (calendarRegistry.isDestroyed() || !id.isValid())
return nullptr;
- if (auto *c = id < calendarRegistry->byId.size() ? calendarRegistry->byId[id] : nullptr)
+ const size_t i = id.index();
+ if (auto *c = i < calendarRegistry->byId.size() ? calendarRegistry->byId[i] : nullptr)
return c;
- if (id <= size_t(QCalendar::System::Last))
- return fromEnum(QCalendar::System(id));
+ if (id.isInEnum())
+ return fromEnum(QCalendar::System(id.index()));
return nullptr;
}
@@ -952,20 +950,20 @@ const QCalendarBackend *QCalendarBackend::fromId(size_t id)
*/
const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
{
- Q_ASSERT(system == QCalendar::System::User
- || size_t(system) <= size_t(QCalendar::System::Last));
+ const auto systemId = QCalendar::SystemId(system);
+ Q_ASSERT(system == QCalendar::System::User || systemId.isInEnum());
if (calendarRegistry.isDestroyed() || system == QCalendar::System::User)
return nullptr;
{
const auto registryLock = qt_scoped_lock(registryMutex);
- Q_ASSERT(calendarRegistry->byId.size() > size_t(system));
- if (auto *c = calendarRegistry->byId[size_t(system)])
+ Q_ASSERT(calendarRegistry->byId.size() > systemId.index());
+ if (auto *c = calendarRegistry->byId[systemId.index()])
return c;
}
if (auto *result = backendFromEnum(system))
return result;
const auto registryLock = qt_scoped_lock(registryMutex);
- return calendarRegistry->byId[size_t(system)];
+ return calendarRegistry->byId[systemId.index()];
}
/*!
@@ -1008,10 +1006,47 @@ const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
\omitvalue Last
\omitvalue User
+ \sa QCalendar, QCalendar::SystemId
+*/
+
+/*!
+ \class QCalendar::SystemId
+ \since 6.2
+
+ This is an opaque type used to identify custom calendar implementations. The
+ only supported source for values of this type is the backend's \c
+ calendarId() method. A value of this type whose isValid() is false does not
+ identify a successfully-registered backend. The only valid consumer of
+ values of this type is a QCalendar constructor, which will only produce a
+ valid QCalendar instance if the ID passed to it is valid.
+
+ \sa QCalendar, QCalendar::System
+*/
+
+/*!
+ \fn QCalendar::SystemId::isValid()
+
+ Returns true if this is a valid calendar implementation identifier, else
+ false.
+
\sa QCalendar
*/
/*!
+ \internal
+ \fn QCalendar::SystemId::SystemId()
+
+ Constructs an invalid calendar system identifier.
+*/
+
+/*!
+ \internal
+ \fn QCalendar::SystemId::index()
+
+ Returns the internal representation of the identifier.
+*/
+
+/*!
\fn QCalendar::QCalendar()
\fn QCalendar::QCalendar(QCalendar::System system)
\fn QCalendar::QCalendar(QLatin1String name)
@@ -1040,7 +1075,7 @@ QCalendar::QCalendar()
delete fresh;
Q_ASSERT(d);
}
- Q_ASSERT(~d->calendarId());
+ Q_ASSERT(d->calendarId().isValid());
}
QCalendar::QCalendar(QCalendar::System system)
@@ -1048,7 +1083,7 @@ QCalendar::QCalendar(QCalendar::System system)
{
// If system is valid, we should get a valid d for that system.
Q_ASSERT(uint(system) > uint(QCalendar::System::Last)
- || (d && d->calendarId() == size_t(system)));
+ || (d && d->calendarId().index() == size_t(system)));
}
/*!
@@ -1062,22 +1097,22 @@ QCalendar::QCalendar(QCalendar::System system)
QCalendar using that backend. This can be useful when the backend is not
registered by name.
*/
-QCalendar::QCalendar(size_t id)
+QCalendar::QCalendar(QCalendar::SystemId id)
: d(QCalendarBackend::fromId(id))
{
- Q_ASSERT(!d || d->calendarId() == id);
+ Q_ASSERT(!d || d->calendarId().index() == id.index());
}
QCalendar::QCalendar(QLatin1String name)
: d(QCalendarBackend::fromName(name))
{
- Q_ASSERT(!d || ~d->calendarId());
+ Q_ASSERT(!d || d->calendarId().isValid());
}
QCalendar::QCalendar(QStringView name)
: d(QCalendarBackend::fromName(name))
{
- Q_ASSERT(!d || ~d->calendarId());
+ Q_ASSERT(!d || d->calendarId().isValid());
}
/*!
diff --git a/src/corelib/time/qcalendar.h b/src/corelib/time/qcalendar.h
index e6907f6a17..c3d8800db8 100644
--- a/src/corelib/time/qcalendar.h
+++ b/src/corelib/time/qcalendar.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -130,12 +130,24 @@ public:
// New entries must be added to the \enum doc in qcalendar.cpp and
// handled in QCalendarBackend::fromEnum()
Q_ENUM(System)
+ class SystemId
+ {
+ const size_t id;
+ friend class QCalendarBackend;
+ constexpr bool isInEnum() const { return id <= size_t(QCalendar::System::Last); }
+ constexpr SystemId(QCalendar::System e) : id(size_t(e)) {}
+ constexpr SystemId(size_t i) : id(i) {}
+ public:
+ constexpr SystemId() : id(~size_t(0)) {}
+ constexpr size_t index() const noexcept { return id; }
+ constexpr bool isValid() const noexcept { return ~id; }
+ };
explicit QCalendar(); // Gregorian, optimised
explicit QCalendar(System system);
explicit QCalendar(QLatin1String name);
explicit QCalendar(QStringView name);
- explicit QCalendar(size_t id);
+ explicit QCalendar(SystemId id);
// QCalendar is a trivially copyable value type.
bool isValid() const { return d != nullptr; }
diff --git a/src/corelib/time/qcalendarbackend_p.h b/src/corelib/time/qcalendarbackend_p.h
index b011fa0f62..c3f57e7f74 100644
--- a/src/corelib/time/qcalendarbackend_p.h
+++ b/src/corelib/time/qcalendarbackend_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -93,7 +93,7 @@ public:
virtual ~QCalendarBackend();
virtual QString name() const = 0;
QCalendar::System calendarSystem() const;
- size_t calendarId() const { return m_id; }
+ QCalendar::SystemId calendarId() const { return m_id; }
// Date queries:
virtual int daysInMonth(int month, int year = QCalendar::Unspecified) const = 0;
virtual int daysInYear(int year) const;
@@ -143,11 +143,11 @@ protected:
bool registerAlias(const QString &name);
private:
- const size_t m_id = ~size_t(0);
+ const QCalendar::SystemId m_id;
// QCalendar's access to its registry:
static const QCalendarBackend *fromName(QStringView name);
static const QCalendarBackend *fromName(QLatin1String name);
- static const QCalendarBackend *fromId(size_t id);
+ static const QCalendarBackend *fromId(QCalendar::SystemId id);
// QCalendar's access to singletons:
static const QCalendarBackend *fromEnum(QCalendar::System system);
};
diff --git a/src/corelib/time/qgregoriancalendar.cpp b/src/corelib/time/qgregoriancalendar.cpp
index f562413dd1..6d0c3ac925 100644
--- a/src/corelib/time/qgregoriancalendar.cpp
+++ b/src/corelib/time/qgregoriancalendar.cpp
@@ -63,7 +63,7 @@ using namespace QRoundingDown;
QGregorianCalendar::QGregorianCalendar()
: QRomanCalendar(QStringLiteral("Gregorian"), QCalendar::System::Gregorian)
{
- if (~calendarId()) {
+ if (calendarId().isValid()) {
Q_ASSERT(calendarSystem() == QCalendar::System::Gregorian);
registerAlias(QStringLiteral("gregory"));
} // else: being ignored in favor of a duplicate created at the same time
diff --git a/src/corelib/time/qislamiccivilcalendar.cpp b/src/corelib/time/qislamiccivilcalendar.cpp
index 16204cce25..b3e00fe4e3 100644
--- a/src/corelib/time/qislamiccivilcalendar.cpp
+++ b/src/corelib/time/qislamiccivilcalendar.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -75,7 +75,7 @@ using namespace QRoundingDown;
QIslamicCivilCalendar::QIslamicCivilCalendar()
: QHijriCalendar(QStringLiteral("Islamic Civil"), QCalendar::System::IslamicCivil)
{
- if (~calendarId()) {
+ if (calendarId().isValid()) {
Q_ASSERT(calendarSystem() == QCalendar::System::IslamicCivil);
registerAlias(QStringLiteral("islamic-civil")); // CLDR name
registerAlias(QStringLiteral("islamicc")); // old CLDR name, still (2018) used by Mozilla
diff --git a/src/corelib/time/qjalalicalendar.cpp b/src/corelib/time/qjalalicalendar.cpp
index 6ec7f9598a..a93474840b 100644
--- a/src/corelib/time/qjalalicalendar.cpp
+++ b/src/corelib/time/qjalalicalendar.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -116,7 +116,7 @@ qint64 firstDayOfYear(int year, int cycleNo)
QJalaliCalendar::QJalaliCalendar()
: QCalendarBackend(QStringLiteral("Jalali"), QCalendar::System::Jalali)
{
- if (~calendarId()) {
+ if (calendarId().isValid()) {
Q_ASSERT(calendarSystem() == QCalendar::System::Jalali);
registerAlias(QStringLiteral("Persian"));
} // else: being ignored in favor of a duplicate created at the same time
diff --git a/src/corelib/time/qjuliancalendar.cpp b/src/corelib/time/qjuliancalendar.cpp
index 81bf72cee5..8d59e940b3 100644
--- a/src/corelib/time/qjuliancalendar.cpp
+++ b/src/corelib/time/qjuliancalendar.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -78,7 +78,7 @@ using namespace QRoundingDown;
QJulianCalendar::QJulianCalendar()
: QRomanCalendar(QStringLiteral("Julian"), QCalendar::System::Julian)
{
- Q_ASSERT(calendarSystem() == QCalendar::System::Julian || !~calendarId());
+ Q_ASSERT(calendarSystem() == QCalendar::System::Julian || !calendarId().isValid());
}
QString QJulianCalendar::name() const
diff --git a/src/corelib/time/qmilankoviccalendar.cpp b/src/corelib/time/qmilankoviccalendar.cpp
index a01df5ec3f..3d6750f3aa 100644
--- a/src/corelib/time/qmilankoviccalendar.cpp
+++ b/src/corelib/time/qmilankoviccalendar.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -76,7 +76,7 @@ using namespace QRoundingDown;
QMilankovicCalendar::QMilankovicCalendar()
: QRomanCalendar(QStringLiteral("Milankovic"), QCalendar::System::Milankovic)
{
- Q_ASSERT(calendarSystem() == QCalendar::System::Milankovic || !~calendarId());
+ Q_ASSERT(calendarSystem() == QCalendar::System::Milankovic || !calendarId().isValid());
}
QString QMilankovicCalendar::name() const