#if !defined(INCLUDED_POOLEDSTRING_H) #define INCLUDED_POOLEDSTRING_H #include #include "generic/static.h" #include "string/string.h" #include "container/hashtable.h" #include "container/hashfunc.h" /// \brief The string pool class. class StringPool : public HashTable { }; inline void StringPool_analyse(StringPool& pool) { typedef std::multimap Ordered; Ordered ordered; std::size_t total = 0; std::size_t pooled = 0; for(StringPool::iterator i = pool.begin(); i != pool.end(); ++i) { std::size_t size = string_length((*i).key) + 1; total += size * (*i).value; pooled += size + 20; ordered.insert(Ordered::value_type((*i).value, (*i).key)); } globalOutputStream() << "total: " << Unsigned(total) << " pooled:" << Unsigned(pooled) << "\n"; for(Ordered::iterator i = ordered.begin(); i != ordered.end(); ++i) { globalOutputStream() << (*i).second << " " << Unsigned((*i).first) << "\n"; } } /// \brief A string which can be copied with zero memory cost and minimal runtime cost. /// /// \param PoolContext The string pool context to use. template class PooledString { StringPool::iterator m_i; static StringPool::iterator increment(StringPool::iterator i) { ++(*i).value; return i; } static StringPool::iterator insert(const char* string) { StringPool::iterator i = PoolContext::instance().find(const_cast(string)); if(i == PoolContext::instance().end()) { return PoolContext::instance().insert(string_clone(string), 1); } return increment(i); } static void erase(StringPool::iterator i) { if(--(*i).value == 0) { char* string = (*i).key; PoolContext::instance().erase(i); string_release(string, string_length(string)); } } public: PooledString() : m_i(insert("")) { } PooledString(const PooledString& other) : m_i(increment(other.m_i)) { } PooledString(const char* string) : m_i(insert(string)) { } ~PooledString() { erase(m_i); } PooledString& operator=(const PooledString& other) { PooledString tmp(other); tmp.swap(*this); return *this; } PooledString& operator=(const char* string) { PooledString tmp(string); tmp.swap(*this); return *this; } void swap(PooledString& other) { std::swap(m_i, other.m_i); } bool operator==(const PooledString& other) const { return m_i == other.m_i; } const char* c_str() const { return (*m_i).key; } }; #endif