- //===- llvm/ADT/CachedHashString.h - Prehashed string/StringRef -*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- /// 
- /// \file 
- /// This file defines CachedHashString and CachedHashStringRef.  These are 
- /// owning and not-owning string types that store their hash in addition to 
- /// their string data. 
- /// 
- /// Unlike std::string, CachedHashString can be used in DenseSet/DenseMap 
- /// (because, unlike std::string, CachedHashString lets us have empty and 
- /// tombstone values). 
- /// 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_ADT_CACHEDHASHSTRING_H 
- #define LLVM_ADT_CACHEDHASHSTRING_H 
-   
- #include "llvm/ADT/DenseMapInfo.h" 
- #include "llvm/ADT/StringRef.h" 
-   
- namespace llvm { 
-   
- /// A container which contains a StringRef plus a precomputed hash. 
- class CachedHashStringRef { 
-   const char *P; 
-   uint32_t Size; 
-   uint32_t Hash; 
-   
- public: 
-   // Explicit because hashing a string isn't free. 
-   explicit CachedHashStringRef(StringRef S) 
-       : CachedHashStringRef(S, DenseMapInfo<StringRef>::getHashValue(S)) {} 
-   
-   CachedHashStringRef(StringRef S, uint32_t Hash) 
-       : P(S.data()), Size(S.size()), Hash(Hash) { 
-     assert(S.size() <= std::numeric_limits<uint32_t>::max()); 
-   } 
-   
-   StringRef val() const { return StringRef(P, Size); } 
-   const char *data() const { return P; } 
-   uint32_t size() const { return Size; } 
-   uint32_t hash() const { return Hash; } 
- }; 
-   
- template <> struct DenseMapInfo<CachedHashStringRef> { 
-   static CachedHashStringRef getEmptyKey() { 
-     return CachedHashStringRef(DenseMapInfo<StringRef>::getEmptyKey(), 0); 
-   } 
-   static CachedHashStringRef getTombstoneKey() { 
-     return CachedHashStringRef(DenseMapInfo<StringRef>::getTombstoneKey(), 1); 
-   } 
-   static unsigned getHashValue(const CachedHashStringRef &S) { 
-     assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!"); 
-     assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!"); 
-     return S.hash(); 
-   } 
-   static bool isEqual(const CachedHashStringRef &LHS, 
-                       const CachedHashStringRef &RHS) { 
-     return LHS.hash() == RHS.hash() && 
-            DenseMapInfo<StringRef>::isEqual(LHS.val(), RHS.val()); 
-   } 
- }; 
-   
- /// A container which contains a string, which it owns, plus a precomputed hash. 
- /// 
- /// We do not null-terminate the string. 
- class CachedHashString { 
-   friend struct DenseMapInfo<CachedHashString>; 
-   
-   char *P; 
-   uint32_t Size; 
-   uint32_t Hash; 
-   
-   static char *getEmptyKeyPtr() { return DenseMapInfo<char *>::getEmptyKey(); } 
-   static char *getTombstoneKeyPtr() { 
-     return DenseMapInfo<char *>::getTombstoneKey(); 
-   } 
-   
-   bool isEmptyOrTombstone() const { 
-     return P == getEmptyKeyPtr() || P == getTombstoneKeyPtr(); 
-   } 
-   
-   struct ConstructEmptyOrTombstoneTy {}; 
-   
-   CachedHashString(ConstructEmptyOrTombstoneTy, char *EmptyOrTombstonePtr) 
-       : P(EmptyOrTombstonePtr), Size(0), Hash(0) { 
-     assert(isEmptyOrTombstone()); 
-   } 
-   
-   // TODO: Use small-string optimization to avoid allocating. 
-   
- public: 
-   explicit CachedHashString(const char *S) : CachedHashString(StringRef(S)) {} 
-   
-   // Explicit because copying and hashing a string isn't free. 
-   explicit CachedHashString(StringRef S) 
-       : CachedHashString(S, DenseMapInfo<StringRef>::getHashValue(S)) {} 
-   
-   CachedHashString(StringRef S, uint32_t Hash) 
-       : P(new char[S.size()]), Size(S.size()), Hash(Hash) { 
-     memcpy(P, S.data(), S.size()); 
-   } 
-   
-   // Ideally this class would not be copyable.  But SetVector requires copyable 
-   // keys, and we want this to be usable there. 
-   CachedHashString(const CachedHashString &Other) 
-       : Size(Other.Size), Hash(Other.Hash) { 
-     if (Other.isEmptyOrTombstone()) { 
-       P = Other.P; 
-     } else { 
-       P = new char[Size]; 
-       memcpy(P, Other.P, Size); 
-     } 
-   } 
-   
-   CachedHashString &operator=(CachedHashString Other) { 
-     swap(*this, Other); 
-     return *this; 
-   } 
-   
-   CachedHashString(CachedHashString &&Other) noexcept 
-       : P(Other.P), Size(Other.Size), Hash(Other.Hash) { 
-     Other.P = getEmptyKeyPtr(); 
-   } 
-   
-   ~CachedHashString() { 
-     if (!isEmptyOrTombstone()) 
-       delete[] P; 
-   } 
-   
-   StringRef val() const { return StringRef(P, Size); } 
-   uint32_t size() const { return Size; } 
-   uint32_t hash() const { return Hash; } 
-   
-   operator StringRef() const { return val(); } 
-   operator CachedHashStringRef() const { 
-     return CachedHashStringRef(val(), Hash); 
-   } 
-   
-   friend void swap(CachedHashString &LHS, CachedHashString &RHS) { 
-     using std::swap; 
-     swap(LHS.P, RHS.P); 
-     swap(LHS.Size, RHS.Size); 
-     swap(LHS.Hash, RHS.Hash); 
-   } 
- }; 
-   
- template <> struct DenseMapInfo<CachedHashString> { 
-   static CachedHashString getEmptyKey() { 
-     return CachedHashString(CachedHashString::ConstructEmptyOrTombstoneTy(), 
-                             CachedHashString::getEmptyKeyPtr()); 
-   } 
-   static CachedHashString getTombstoneKey() { 
-     return CachedHashString(CachedHashString::ConstructEmptyOrTombstoneTy(), 
-                             CachedHashString::getTombstoneKeyPtr()); 
-   } 
-   static unsigned getHashValue(const CachedHashString &S) { 
-     assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!"); 
-     assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!"); 
-     return S.hash(); 
-   } 
-   static bool isEqual(const CachedHashString &LHS, 
-                       const CachedHashString &RHS) { 
-     if (LHS.hash() != RHS.hash()) 
-       return false; 
-     if (LHS.P == CachedHashString::getEmptyKeyPtr()) 
-       return RHS.P == CachedHashString::getEmptyKeyPtr(); 
-     if (LHS.P == CachedHashString::getTombstoneKeyPtr()) 
-       return RHS.P == CachedHashString::getTombstoneKeyPtr(); 
-   
-     // This is safe because if RHS.P is the empty or tombstone key, it will have 
-     // length 0, so we'll never dereference its pointer. 
-     return LHS.val() == RHS.val(); 
-   } 
- }; 
-   
- } // namespace llvm 
-   
- #endif 
-