blob: 66124f035045de79fdea3f05dcdd12a52926217b [file] [log] [blame]
#ifndef _UTF8_INTERNAL_H_
#define _UTF8_INTERNAL_H_
#include <map>
#include <iostream>
#include <string>
#include "vmkit/Allocator.h"
#include "vmkit/VmkitDenseMap.h"
#include "vmkit/VmkitDenseSet.h"
namespace vmkit {
class UTF8Map;
class UTF8 {
friend class UTF8Map;
private:
/// operator new - Redefines the new operator of this class to allocate
/// its objects in permanent memory, not with the garbage collector.
void* operator new(size_t sz, vmkit::BumpPtrAllocator& allocator, sint32 n) {
return allocator.Allocate(sizeof(UTF8) + (n - 1) * sizeof(uint16), "UTF8");
}
public:
/// size - The (constant) size of the UTF8.
int32_t size;
/// elements - Elements of this UTF8.
/// The size should be set to zero, but this is invalid C99.
uint16 elements[1];
/// extract - Extracts an UTF8 from the current UTF8
const UTF8* extract(UTF8Map* map, uint32 start, uint32 len) const;
/// equals - Are the two UTF8s equal?
bool equals(const UTF8* other) const {
if (other == this) return true;
else if (size != other->size) return false;
else return !memcmp(elements, other->elements, size * sizeof(uint16));
}
/// equals - Does the UTF8 equal to the buffer?
bool equals(const uint16* buf, sint32 len) const {
if (size != len) return false;
else return !memcmp(elements, buf, size * sizeof(uint16));
}
/// lessThan - strcmp-like function for UTF8s, used by hash tables.
bool lessThan(const UTF8* other) const {
if (size < other->size) return true;
else if (size > other->size) return false;
else return memcmp((const char*)elements, (const char*)other->elements,
size * sizeof(uint16)) < 0;
}
static uint32_t readerHasher(const uint16* buf, sint32 size);
uint32_t hash() const {
return readerHasher(elements, size);
}
UTF8(sint32 n) {
size = n;
}
friend std::ostream& operator << (std::ostream&, const UTF8&);
void dump() const __attribute__((noinline));
int compare(const char *) const;
std::string& toString(std::string& buffer) const;
};
extern "C" const UTF8 TombstoneKey;
extern "C" const UTF8 EmptyKey;
struct UTF8MapKey {
ssize_t length;
const uint16_t* data;
UTF8MapKey(const uint16_t* d, ssize_t l) {
data = d;
length = l;
}
};
// Provide VmkitDenseMapInfo for UTF8.
template<>
struct VmkitDenseMapInfo<const UTF8*> {
static inline const UTF8* getEmptyKey() {
return &EmptyKey;
}
static inline const UTF8* getTombstoneKey() {
return &TombstoneKey;
}
static unsigned getHashValue(const UTF8* PtrVal) {
return PtrVal->hash();
}
static bool vmkIsEqual(const UTF8* LHS, const UTF8* RHS) { return LHS->equals(RHS); }
static bool vmkIsEqualKey(const UTF8* LHS, const UTF8MapKey& Key) {
return LHS->equals(Key.data, Key.length);
}
static UTF8MapKey toKey(const UTF8* utf8) {
return UTF8MapKey(utf8->elements, utf8->size);
}
};
// Provide VmkitDenseMapInfo for UTF8MapKey.
template<>
struct VmkitDenseMapInfo<UTF8MapKey> {
static inline const UTF8MapKey getEmptyKey() {
static UTF8MapKey EmptyKey(NULL, -1);
return EmptyKey;
}
static inline const UTF8MapKey getTombstoneKey() {
static UTF8MapKey TombstoneKey(NULL, -2);
return TombstoneKey;
}
static unsigned getHashValue(const UTF8MapKey& key) {
return UTF8::readerHasher(key.data, key.length);
}
static bool vmkIsEqual(const UTF8MapKey& LHS, const UTF8MapKey& RHS) {
if (LHS.data == RHS.data) return true;
if (LHS.length != RHS.length) return false;
return !memcmp(LHS.data, RHS.data, RHS.length * sizeof(uint16));
}
};
class UTF8Map : public vmkit::PermanentObject {
public:
typedef VmkitDenseSet<UTF8MapKey, const UTF8*>::iterator iterator;
LockNormal lock;
BumpPtrAllocator& allocator;
VmkitDenseSet<UTF8MapKey, const UTF8*> map;
const UTF8* lookupOrCreateAsciiz(const char* asciiz);
const UTF8* lookupOrCreateReader(const uint16* buf, uint32 size);
const UTF8* lookupAsciiz(const char* asciiz);
const UTF8* lookupReader(const uint16* buf, uint32 size);
UTF8Map(BumpPtrAllocator& A) : allocator(A) {}
UTF8Map(BumpPtrAllocator& A, VmkitDenseSet<UTF8MapKey, const UTF8*>* m)
: allocator(A), map(*m) {}
~UTF8Map() {
for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
allocator.Deallocate((void*)*i);
}
}
};
class UTF8Builder {
uint16 *buf;
uint32 cur;
uint32 size;
public:
UTF8Builder(size_t size) {
size = (size < 4) ? 4 : size;
this->buf = new uint16[size];
this->size = size;
}
UTF8Builder *append(const UTF8 *utf8, uint32 start=0, ssize_t length=-1) {
length = length == -1 ? utf8->size : length;
uint32 req = cur + length;
if(req > size) {
uint32 newSize = size<<1;
while(req < newSize)
newSize <<= 1;
uint16 *newBuf = new uint16[newSize];
memcpy(newBuf, buf, cur<<1);
delete []buf;
buf = newBuf;
size = newSize;
}
memcpy(buf + cur, &utf8->elements + start, length<<1);
cur = req;
return this;
}
const UTF8 *toUTF8(UTF8Map *map) {
return map->lookupOrCreateReader(buf, size);
}
~UTF8Builder() {
delete [] buf;
}
};
} // end namespace vmkit
#endif