#pragma once #include #include "comptrie.h" class TTrieSet { private: TCompactTrie Trie; public: TTrieSet(const TBlob& blob) : Trie(blob) { } bool Has(const char* key) const { return Trie.Find(key, strlen(key)); } bool FindLongestPrefix(const char* key, size_t keylen, size_t* prefixLen) { return Trie.FindLongestPrefix(key, keylen, prefixLen); } }; template class TTrieSetWriter { private: TCompactTrieBuilder Builder; public: TTrieSetWriter(bool isSorted = sorted) : Builder(isSorted ? CTBF_PREFIX_GROUPED : CTBF_NONE) { } void Add(const char* key, size_t keylen) { Builder.Add(key, keylen, 0); assert(Has(((TString)key).substr(0, keylen).data())); } void Add(const char* key) { Add(key, strlen(key)); } bool Has(const char* key) const { ui64 dummy; return Builder.Find(key, strlen(key), &dummy); } void Save(IOutputStream& out) const { Builder.Save(out); } void Clear() { Builder.Clear(); } }; template struct TTrieSetG; template struct TTrieSetG { typedef TTrieSet T; }; template struct TTrieSetG { typedef TTrieSetWriter T; }; template class TTrieMap { private: TCompactTrie Trie; static_assert(sizeof(T) <= sizeof(ui64), "expect sizeof(T) <= sizeof(ui64)"); public: TTrieMap(const TBlob& blob) : Trie(blob) { } bool Get(const char* key, T* value) const { ui64 trieValue; if (Trie.Find(key, strlen(key), &trieValue)) { *value = ReadUnaligned(&trieValue); return true; } else { return false; } } T Get(const char* key, T def = T()) const { ui64 trieValue; if (Trie.Find(key, strlen(key), &trieValue)) { return ReadUnaligned(&trieValue); } else { return def; } } const TCompactTrie& GetTrie() const { return Trie; } }; template class TTrieMapWriter { private: typedef TCompactTrieBuilder TBuilder; TBuilder Builder; static_assert(sizeof(T) <= sizeof(ui64), "expect sizeof(T) <= sizeof(ui64)"); #ifndef NDEBUG bool IsSorted; #endif public: TTrieMapWriter(bool isSorted = sorted) : Builder(isSorted ? CTBF_PREFIX_GROUPED : CTBF_NONE) #ifndef NDEBUG , IsSorted(isSorted) #endif { } void Add(const char* key, const T& value) { ui64 intValue = 0; memcpy(&intValue, &value, sizeof(T)); Builder.Add(key, strlen(key), intValue); #ifndef NDEBUG /* if (!IsSorted) { T test; assert(Get(key, &test) && value == test); } */ #endif } void Add(const TString& s, const T& value) { ui64 intValue = 0; memcpy(&intValue, &value, sizeof(T)); Builder.Add(s.data(), s.size(), intValue); } bool Get(const char* key, T* value) const { ui64 trieValue; if (Builder.Find(key, strlen(key), &trieValue)) { *value = ReadUnaligned(&trieValue); return true; } else { return false; } } T Get(const char* key, T def = (T)0) const { ui64 trieValue; if (Builder.Find(key, strlen(key), &trieValue)) { return ReadUnaligned(&trieValue); } else { return def; } } void Save(IOutputStream& out, bool minimize = false) const { if (minimize) { CompactTrieMinimize(out, Builder, false); } else { Builder.Save(out); } } void Clear() { Builder.Clear(); } }; template class TTrieSortedMapWriter { private: typedef std::pair TValue; typedef TVector TValues; TValues Values; public: TTrieSortedMapWriter() = default; void Add(const char* key, const T& value) { Values.push_back(TValue(key, value)); } void Save(IOutputStream& out) { Sort(Values.begin(), Values.end()); TTrieMapWriter writer; for (typename TValues::const_iterator toValue = Values.begin(); toValue != Values.end(); ++toValue) writer.Add(toValue->first.data(), toValue->second); writer.Save(out); } void Clear() { Values.clear(); } }; template struct TTrieMapG; template struct TTrieMapG { typedef TTrieMap T; }; template struct TTrieMapG { typedef TTrieMapWriter T; };