#ifndef LLVM_ADT_STRINGMAPENTRY_H
#define LLVM_ADT_STRINGMAPENTRY_H
#include "llvm/ADT/None.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/STLFunctionalExtras.h"
namespace llvm {
class StringMapEntryBase {
size_t keyLength;
public:
explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {}
size_t getKeyLength() const { return keyLength; }
protected:
template <typename AllocatorTy>
static void *allocateWithKey(size_t EntrySize, size_t EntryAlign,
StringRef Key, AllocatorTy &Allocator);
};
template <typename AllocatorTy>
void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign,
StringRef Key,
AllocatorTy &Allocator) {
size_t KeyLength = Key.size();
size_t AllocSize = EntrySize + KeyLength + 1;
void *Allocation = Allocator.Allocate(AllocSize, EntryAlign);
assert(Allocation && "Unhandled out-of-memory");
char *Buffer = reinterpret_cast<char *>(Allocation) + EntrySize;
if (KeyLength > 0)
::memcpy(Buffer, Key.data(), KeyLength);
Buffer[KeyLength] = 0; return Allocation;
}
template <typename ValueTy>
class StringMapEntryStorage : public StringMapEntryBase {
public:
ValueTy second;
explicit StringMapEntryStorage(size_t keyLength)
: StringMapEntryBase(keyLength), second() {}
template <typename... InitTy>
StringMapEntryStorage(size_t keyLength, InitTy &&... initVals)
: StringMapEntryBase(keyLength),
second(std::forward<InitTy>(initVals)...) {}
StringMapEntryStorage(StringMapEntryStorage &e) = delete;
const ValueTy &getValue() const { return second; }
ValueTy &getValue() { return second; }
void setValue(const ValueTy &V) { second = V; }
};
template <> class StringMapEntryStorage<NoneType> : public StringMapEntryBase {
public:
explicit StringMapEntryStorage(size_t keyLength, NoneType = None)
: StringMapEntryBase(keyLength) {}
StringMapEntryStorage(StringMapEntryStorage &entry) = delete;
NoneType getValue() const { return None; }
};
template <typename ValueTy>
class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
public:
using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
StringRef getKey() const {
return StringRef(getKeyData(), this->getKeyLength());
}
const char *getKeyData() const {
return reinterpret_cast<const char *>(this + 1);
}
StringRef first() const {
return StringRef(getKeyData(), this->getKeyLength());
}
template <typename AllocatorTy, typename... InitTy>
static StringMapEntry *Create(StringRef key, AllocatorTy &allocator,
InitTy &&... initVals) {
return new (StringMapEntryBase::allocateWithKey(
sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator))
StringMapEntry(key.size(), std::forward<InitTy>(initVals)...);
}
static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) {
char *ptr = const_cast<char *>(keyData) - sizeof(StringMapEntry<ValueTy>);
return *reinterpret_cast<StringMapEntry *>(ptr);
}
template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) {
size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1;
this->~StringMapEntry();
allocator.Deallocate(static_cast<void *>(this), AllocSize,
alignof(StringMapEntry));
}
};
}
#endif