| #include "mvm/UTF8.h" |
| #include "mvm/PrintBuffer.h" |
| |
| using namespace mvm; |
| |
| void UTF8::print(PrintBuffer *pb) const { |
| pb->writeUTF8(this); |
| } |
| |
| |
| const UTF8* UTF8::extract(UTF8Map* map, uint32 start, uint32 end) const { |
| uint32 len = end - start; |
| uint16* buf = (uint16*)alloca(sizeof(uint16) * len); |
| |
| for (uint32 i = 0; i < len; i++) { |
| buf[i] = elements[i + start]; |
| } |
| |
| return map->lookupOrCreateReader(buf, len); |
| } |
| |
| static uint32 asciizHasher(const char* asciiz, sint32 size) { |
| uint32 r0 = 0, r1 = 0; |
| for (sint32 i = 0; i < size; i++) { |
| char c = asciiz[i]; |
| r0 += c; |
| r1 ^= c; |
| } |
| return (r1 & 255) + ((r0 & 255) << 8); |
| } |
| |
| uint32 UTF8::readerHasher(const uint16* buf, sint32 size) { |
| uint32 r0 = 0, r1 = 0; |
| for (sint32 i = 0; i < size; i++) { |
| uint16 c = buf[i]; |
| r0 += c; |
| r1 ^= c; |
| } |
| return (r1 & 255) + ((r0 & 255) << 8); |
| } |
| |
| static bool asciizEqual(const UTF8* val, const char* asciiz, sint32 size) { |
| sint32 len = val->size; |
| if (len != size) return false; |
| else { |
| for (sint32 i = 0; i < len; i++) { |
| if (asciiz[i] != val->elements[i]) return false; |
| } |
| return true; |
| } |
| } |
| |
| static bool readerEqual(const UTF8* val, const uint16* buf, sint32 size) { |
| sint32 len = val->size; |
| if (len != size) return false; |
| else return !(memcmp(val->elements, buf, len * sizeof(uint16))); |
| } |
| |
| void UTF8Map::replace(const UTF8* oldUTF8, const UTF8* newUTF8) { |
| lock.lock(); |
| uint32 key = oldUTF8->hash(); |
| std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key); |
| |
| for (UTF8Map::iterator i = p.first; i != p.second; i++) { |
| if (i->second == oldUTF8) { |
| map.erase(i); |
| break; |
| } |
| } |
| map.insert(std::make_pair(key, newUTF8)); |
| lock.unlock(); |
| |
| } |
| |
| const UTF8* UTF8Map::lookupOrCreateAsciiz(const char* asciiz) { |
| sint32 size = strlen(asciiz); |
| uint32 key = asciizHasher(asciiz, size); |
| const UTF8* res = 0; |
| lock.lock(); |
| |
| std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key); |
| |
| for (UTF8Map::iterator i = p.first; i != p.second; i++) { |
| if (asciizEqual(i->second, asciiz, size)) { |
| res = i->second; |
| break; |
| } |
| } |
| |
| if (res == 0) { |
| UTF8* tmp = new(allocator, size) UTF8(size); |
| for (sint32 i = 0; i < size; i++) { |
| tmp->elements[i] = asciiz[i]; |
| } |
| res = (const UTF8*)tmp; |
| map.insert(std::make_pair(key, res)); |
| } |
| |
| lock.unlock(); |
| return res; |
| } |
| |
| const UTF8* UTF8Map::lookupOrCreateReader(const uint16* buf, uint32 len) { |
| sint32 size = (sint32)len; |
| uint32 key = UTF8::readerHasher(buf, size); |
| const UTF8* res = 0; |
| lock.lock(); |
| |
| std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key); |
| |
| for (UTF8Map::iterator i = p.first; i != p.second; i++) { |
| if (readerEqual(i->second, buf, size)) { |
| res = i->second; |
| break; |
| } |
| } |
| |
| if (res == 0) { |
| UTF8* tmp = new(allocator, size) UTF8(size); |
| memcpy(tmp->elements, buf, len * sizeof(uint16)); |
| res = (const UTF8*)tmp; |
| map.insert(std::make_pair(key, res)); |
| } |
| |
| lock.unlock(); |
| return res; |
| } |
| |
| const UTF8* UTF8Map::lookupAsciiz(const char* asciiz) { |
| sint32 size = strlen(asciiz); |
| uint32 key = asciizHasher(asciiz, size); |
| const UTF8* res = 0; |
| lock.lock(); |
| |
| std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key); |
| |
| for (UTF8Map::iterator i = p.first; i != p.second; i++) { |
| if (asciizEqual(i->second, asciiz, size)) { |
| res = i->second; |
| break; |
| } |
| } |
| |
| lock.unlock(); |
| return res; |
| } |
| |
| const UTF8* UTF8Map::lookupReader(const uint16* buf, uint32 len) { |
| sint32 size = (sint32)len; |
| uint32 key = UTF8::readerHasher(buf, size); |
| const UTF8* res = 0; |
| lock.lock(); |
| |
| std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key); |
| |
| for (UTF8Map::iterator i = p.first; i != p.second; i++) { |
| if (readerEqual(i->second, buf, size)) { |
| res = i->second; |
| break; |
| } |
| } |
| |
| lock.unlock(); |
| return res; |
| } |
| |
| void UTF8Map::insert(const UTF8* val) { |
| map.insert(std::make_pair(val->hash(), val)); |
| } |