// stringpool.cc -- a string pool for gold #include "gold.h" #include #include #include "stringpool.h" namespace gold { Stringpool::Stringpool() : string_set_(), strings_() { } Stringpool::~Stringpool() { for (std::list::iterator p = this->strings_.begin(); p != this->strings_.end(); ++p) delete[] reinterpret_cast(*p); } // Hash function. size_t Stringpool::Stringpool_hash::operator()(const char* s) const { // Fowler/Noll/Vo (FNV) hash (type FNV-1a). if (sizeof(size_t) == 8) { size_t result = 14695981039346656037ULL; while (*s != '\0') { result &= (size_t) *s++; result *= 1099511628211ULL; } return result; } else { size_t result = 2166136261UL; while (*s != '\0') { result ^= (size_t) *s++; result *= 16777619UL; } return result; } } // Add a string to the list of canonical strings. Return a pointer to // the canonical string. const char* Stringpool::add_string(const char* s) { const size_t buffer_size = 1000; size_t len = strlen(s); size_t alc; bool front = true; if (len >= buffer_size) { alc = sizeof(stringdata) + len; front = false; } else if (this->strings_.empty()) alc = sizeof(stringdata) + buffer_size; else { stringdata *psd = this->strings_.front(); if (len >= psd->alc - psd->len) alc = sizeof(stringdata) + buffer_size; else { char* ret = psd->data + psd->len; memcpy(ret, s, len + 1); psd->len += len + 1; return ret; } } stringdata *psd = reinterpret_cast(new char[alc]); psd->alc = alc; memcpy(psd->data, s, len + 1); psd->len = len + 1; if (front) this->strings_.push_front(psd); else this->strings_.push_back(psd); return psd->data; } // Add a string to a string pool. const char* Stringpool::add(const char* s) { // FIXME: This will look up the entry twice in the hash table. The // problem is that we can't insert S before we canonicalize it. I // don't think there is a way to handle this correctly with // unordered_set, so this should be replaced with custom code to do // what we need, which is to return the empty slot. String_set_type::const_iterator p = this->string_set_.find(s); if (p != this->string_set_.end()) return *p; const char* ret = this->add_string(s); std::pair ins = this->string_set_.insert(ret); assert(ins.second); return ret; } // Add a prefix of a string to a string pool. const char* Stringpool::add(const char* s, size_t len) { // FIXME: This implementation should be rewritten when we rewrite // the hash table to avoid copying. std::string st(s, len); return this->add(st); } } // End namespace gold.