Enforce sorting of QTZ backend availableTimeZoneIds()
Various pieces of QTZP and QTZ rely (by using std::set_union or std::set_intersection) on the backends supplying the list of available IDs in sorted order. As this isn't documented as part of public API behavior, document it internally and assert it. Add the missing sorting and uniquification for Android; although the Java API used does appear to return a sorted list, its specification [0] says nothing about its ordering, so make sure. In the process, rename a wantonly long variable so the uniquifying doesn't need a line-split. [0] https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html#getAvailableIDs-- Document, in the ICU backend, that the relevant API doesn't say what order it returns; but also make clear where the backend *does* take care of sorting it and rendering entries unique. Change-Id: I61b4ecf342044e2303b18889c600da5922aec278 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
This commit is contained in:
parent
7a8cefd6fb
commit
35066b28c8
@ -1486,8 +1486,18 @@ bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId)
|
||||
|| global_tz->backend->isTimeZoneIdAvailable(ianaId);
|
||||
}
|
||||
|
||||
[[maybe_unused]] static bool isUniqueSorted(const QList<QByteArray> &seq)
|
||||
{
|
||||
// Since [..., b, a, ...] isn't unique-sorted if a <= b, at least the
|
||||
// suggested implementations of is_sorted() and is_sorted_until() imply a
|
||||
// non-unique sorted list will fail is_sorted() with <= comparison.
|
||||
return std::is_sorted(seq.begin(), seq.end(), std::less_equal<QByteArray>());
|
||||
}
|
||||
|
||||
static QList<QByteArray> set_union(const QList<QByteArray> &l1, const QList<QByteArray> &l2)
|
||||
{
|
||||
Q_ASSERT(isUniqueSorted(l1));
|
||||
Q_ASSERT(isUniqueSorted(l2));
|
||||
QList<QByteArray> result;
|
||||
result.reserve(l1.size() + l2.size());
|
||||
std::set_union(l1.begin(), l1.end(),
|
||||
@ -1511,6 +1521,7 @@ static QList<QByteArray> set_union(const QList<QByteArray> &l1, const QList<QByt
|
||||
QList<QByteArray> QTimeZone::availableTimeZoneIds()
|
||||
{
|
||||
// Backends MUST implement availableTimeZoneIds().
|
||||
// The return from each backend MUST be sorted and unique.
|
||||
return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(),
|
||||
global_tz->backend->availableTimeZoneIds());
|
||||
}
|
||||
|
@ -203,14 +203,19 @@ QList<QByteArray> QAndroidTimeZonePrivate::availableTimeZoneIds() const
|
||||
{
|
||||
using namespace QtJniTypes;
|
||||
|
||||
const QJniArray androidAvailableIdList = TimeZone::callStaticMethod<String[]>("getAvailableIDs");
|
||||
const QJniArray androidAvailableIdList
|
||||
= TimeZone::callStaticMethod<String[]>("getAvailableIDs");
|
||||
// Does not document order of entries.
|
||||
|
||||
QList<QByteArray> availableTimeZoneIdList;
|
||||
availableTimeZoneIdList.reserve(androidAvailableIdList.size());
|
||||
QList<QByteArray> result;
|
||||
result.reserve(androidAvailableIdList.size());
|
||||
for (const auto &id : androidAvailableIdList)
|
||||
availableTimeZoneIdList.append(id.toString().toUtf8());
|
||||
result.append(id.toString().toUtf8());
|
||||
|
||||
return availableTimeZoneIdList;
|
||||
// Sort & uniquify (just to be sure; it appears to not need this, but we can't rely on that).
|
||||
std::sort(result.begin(), result.end());
|
||||
result.erase(std::unique(result.begin(), result.end()), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -408,9 +408,10 @@ QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds() const
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UEnumeration *uenum = ucal_openTimeZones(&status);
|
||||
// Does not document order of entries.
|
||||
QList<QByteArray> result;
|
||||
if (U_SUCCESS(status))
|
||||
result = uenumToIdList(uenum);
|
||||
result = uenumToIdList(uenum); // Ensures sorted, unique.
|
||||
uenum_close(uenum);
|
||||
return result;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user