File indexing completed on 2024-05-12 04:42:19
0001 /* 0002 SPDX-FileCopyrightText: 2020-2021 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef KOSM_STRINGPOOL_H 0008 #define KOSM_STRINGPOOL_H 0009 0010 #include <kosm_export.h> 0011 0012 #include <cstring> 0013 #include <vector> 0014 0015 namespace OSM { 0016 0017 enum class StringMemory { Persistent, Transient }; 0018 0019 /** @internal */ 0020 class KOSM_EXPORT StringKeyRegistryBase 0021 { 0022 protected: 0023 explicit StringKeyRegistryBase(); 0024 StringKeyRegistryBase(StringKeyRegistryBase&&) noexcept; 0025 StringKeyRegistryBase& operator=(StringKeyRegistryBase&&) noexcept; 0026 ~StringKeyRegistryBase(); 0027 0028 [[nodiscard]] const char* makeKeyInternal(const char *name, std::size_t len, StringMemory memOpt); 0029 [[nodiscard]] const char* keyInternal(const char *name) const; 0030 0031 std::vector<char*> m_pool; 0032 std::vector<const char*> m_registry; 0033 }; 0034 0035 /** Registry of unique string keys. 0036 * @tparam T Sub-classes of StringKey, to have a compile-time check against comparing keys from different pools. 0037 */ 0038 template <typename T> 0039 class StringKeyRegistry : protected StringKeyRegistryBase 0040 { 0041 public: 0042 explicit StringKeyRegistry() = default; 0043 StringKeyRegistry(const StringKeyRegistry&) = delete; 0044 StringKeyRegistry(StringKeyRegistry&&) = default; 0045 ~StringKeyRegistry() = default; 0046 StringKeyRegistry& operator=(const StringKeyRegistry&) = delete; 0047 StringKeyRegistry& operator=(StringKeyRegistry&&) = default; 0048 0049 /** Add a new string to the registry if needed, or returns an existing one if already present. */ 0050 inline T makeKey(const char *name, StringMemory memOpt) 0051 { 0052 return makeKey(name, std::strlen(name), memOpt); 0053 } 0054 inline T makeKey(const char *name, std::size_t len, StringMemory memOpt) 0055 { 0056 T key; 0057 key.key = makeKeyInternal(name, len, memOpt); 0058 return key; 0059 } 0060 0061 /** Looks up an existing key, if that doesn't exist an null key is returned. */ 0062 inline T key(const char *name) const 0063 { 0064 T key; 0065 key.key = keyInternal(name); 0066 return key; 0067 } 0068 }; 0069 0070 /** Base class for unique string keys. */ 0071 class StringKey 0072 { 0073 public: 0074 constexpr inline StringKey() = default; 0075 constexpr inline const char* name() const { return key; } 0076 constexpr inline bool isNull() const { return !key; } 0077 0078 // yes, pointer compare is enough here 0079 inline constexpr bool operator<(StringKey other) const { return key < other.key; } 0080 inline constexpr bool operator==(StringKey other) const { return key == other.key; } 0081 inline constexpr bool operator!=(StringKey other) const { return key != other.key; } 0082 0083 protected: 0084 explicit constexpr inline StringKey(const char *keyData) : key(keyData) {} 0085 0086 private: 0087 template <typename T> friend class StringKeyRegistry; 0088 const char* key = nullptr; 0089 }; 0090 0091 } 0092 0093 #endif // KOSM_STRINGPOOL_H