]> de.git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/mediasource/netradiant-src/libs/string/pooledstring.h
Move the netradiant and fteqcc sources
[voretournament/voretournament.git] / misc / mediasource / netradiant-src / libs / string / pooledstring.h
diff --git a/misc/mediasource/netradiant-src/libs/string/pooledstring.h b/misc/mediasource/netradiant-src/libs/string/pooledstring.h
new file mode 100644 (file)
index 0000000..4ff2d61
--- /dev/null
@@ -0,0 +1,108 @@
+
+#if !defined(INCLUDED_POOLEDSTRING_H)
+#define INCLUDED_POOLEDSTRING_H
+
+#include <map>
+#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<char*, std::size_t, RawStringHash, RawStringEqual>
+{
+};
+
+inline void StringPool_analyse(StringPool& pool)
+{
+  typedef std::multimap<std::size_t, const char*> 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<typename PoolContext>
+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<char*>(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