remove RSA's md4.c, replace by DP's
[xonotic/netradiant.git] / libs / string / pooledstring.h
1
2 #if !defined(INCLUDED_POOLEDSTRING_H)
3 #define INCLUDED_POOLEDSTRING_H
4
5 #include <map>
6 #include "generic/static.h"
7 #include "string/string.h"
8 #include "container/hashtable.h"
9 #include "container/hashfunc.h"
10
11 /// \brief The string pool class.
12 class StringPool : public HashTable<char*, std::size_t, RawStringHash, RawStringEqual>
13 {
14 };
15
16 inline void StringPool_analyse(StringPool& pool)
17 {
18   typedef std::multimap<std::size_t, const char*> Ordered;
19   Ordered ordered;
20   std::size_t total = 0;
21   std::size_t pooled = 0;
22   for(StringPool::iterator i = pool.begin(); i != pool.end(); ++i)
23   {
24     std::size_t size =  string_length((*i).key) + 1;
25     total += size * (*i).value;
26     pooled += size + 20;
27     ordered.insert(Ordered::value_type((*i).value, (*i).key));
28   }
29   globalOutputStream() << "total: " << Unsigned(total) << " pooled:" << Unsigned(pooled) << "\n";
30   for(Ordered::iterator i = ordered.begin(); i != ordered.end(); ++i)
31   {
32     globalOutputStream() << (*i).second << " " << Unsigned((*i).first) << "\n";
33   }
34 }
35
36
37 /// \brief A string which can be copied with zero memory cost and minimal runtime cost.
38 ///
39 /// \param PoolContext The string pool context to use.
40 template<typename PoolContext>
41 class PooledString
42 {
43   StringPool::iterator m_i;
44   static StringPool::iterator increment(StringPool::iterator i)
45   {
46     ++(*i).value;
47     return i;
48   }
49   static StringPool::iterator insert(const char* string)
50   {
51     StringPool::iterator i = PoolContext::instance().find(const_cast<char*>(string));
52     if(i == PoolContext::instance().end())
53     {
54       return PoolContext::instance().insert(string_clone(string), 1);
55     }
56     return increment(i);
57   }
58   static void erase(StringPool::iterator i)
59   {
60     if(--(*i).value == 0)
61     {
62       char* string = (*i).key;
63       PoolContext::instance().erase(i);
64       string_release(string, string_length(string));
65     }
66   }
67 public:
68   PooledString() : m_i(insert(""))
69   {
70   }
71   PooledString(const PooledString& other) : m_i(increment(other.m_i))
72   {
73   }
74   PooledString(const char* string) : m_i(insert(string))
75   {
76   }
77   ~PooledString()
78   {
79     erase(m_i);
80   }
81   PooledString& operator=(const PooledString& other)
82   {
83     PooledString tmp(other);
84     tmp.swap(*this);
85     return *this;
86   }
87   PooledString& operator=(const char* string)
88   {
89     PooledString tmp(string);
90     tmp.swap(*this);
91     return *this;
92   }
93   void swap(PooledString& other)
94   {
95     std::swap(m_i, other.m_i);
96   }
97   bool operator==(const PooledString& other) const
98   {
99     return m_i == other.m_i;
100   }
101   const char* c_str() const
102   {
103     return (*m_i).key;
104   }
105 };
106
107
108 #endif