File indexing completed on 2024-12-29 04:50:10

0001 /*
0002     SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "kitinerary_export.h"
0010 
0011 #include <QDebug>
0012 #include <QString>
0013 #include <QStringView>
0014 
0015 #include <cstdint>
0016 #include <functional>
0017 
0018 namespace KItinerary {
0019 namespace KnowledgeDb {
0020 
0021 ///@cond internal
0022 namespace Internal {
0023     // "private" API for the template code below
0024     KITINERARY_EXPORT uint32_t alphaIdFromString(QStringView s, int size);
0025     KITINERARY_EXPORT QString alphaIdToString(uint32_t id, int size);
0026 }
0027 ///@endcond
0028 
0029 /**
0030  *  Compact storage for fixed-size identifiers consisting out of uppercase latin letters,
0031  *  such as IATA airport codes or ISO 3166 country codes.
0032  */
0033 template <typename T, int N>
0034 class AlphaId {
0035     static_assert((N * 5) < (sizeof(T) * 8), "Not enough space to hold identifier.");
0036 public:
0037     inline constexpr AlphaId() = default;
0038     /** Create identifier from a literal. */
0039     inline explicit constexpr AlphaId(const char s[N])
0040     {
0041         for (int i = 0; i < N; ++i) {
0042             if (s[i] < 'A' || s[i] > 'Z') {
0043                 m_id = {};
0044                 return;
0045             }
0046             m_id |= (s[i] - '@') << (5 * (N-i-1));
0047         }
0048     }
0049     /** Create identifier from a QString. */
0050     inline explicit AlphaId(QStringView s)
0051     {
0052         m_id = Internal::alphaIdFromString(s, N);
0053     }
0054 
0055     /** Returns @c true if this is a valid identifier. */
0056     inline constexpr bool isValid() const
0057     {
0058         return m_id != 0;
0059     }
0060 
0061     inline constexpr bool operator<(AlphaId<T, N> rhs) const
0062     {
0063         return m_id < rhs.m_id;
0064     }
0065     inline constexpr bool operator==(AlphaId<T, N> other) const
0066     {
0067         return m_id == other.m_id;
0068     }
0069     inline constexpr bool operator!=(AlphaId<T, N> other) const
0070     {
0071         return m_id != other.m_id;
0072     }
0073 
0074     /** Returns a string representation of this identifier. */
0075     inline QString toString() const
0076     {
0077         return Internal::alphaIdToString(m_id, N);
0078     }
0079 
0080     /** @internal for std::hash */
0081     inline constexpr T value() const
0082     {
0083         return m_id;
0084     }
0085 private:
0086     T m_id = {};
0087 };
0088 
0089 }
0090 
0091 }
0092 
0093 template <typename T, int N>
0094 inline QDebug operator<<(QDebug dbg, KItinerary::KnowledgeDb::AlphaId<T, N> id)
0095 {
0096     dbg << id.toString();
0097     return dbg;
0098 }
0099 
0100 namespace std {
0101 template <typename T, int N> struct hash<KItinerary::KnowledgeDb::AlphaId<T, N>>
0102 {
0103     typedef KItinerary::KnowledgeDb::AlphaId<T, N> argument_type;
0104     typedef std::size_t result_type;
0105     result_type operator()(argument_type id) const noexcept
0106     {
0107         return std::hash<T>()(id.value());
0108     }
0109 };
0110 }