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 }