ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/src/shstr.C
Revision: 1.1
Committed: Tue Aug 28 17:18:26 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Log Message:
added new files

File Contents

# User Rev Content
1 pippijn 1.1 #include <ermyth/shstr.h>
2    
3     shstr::shstr (char const * const str)
4     {
5     insert (str);
6     }
7    
8     shstr::shstr (const shstr &rhs)
9     {
10     insert (rhs.m_str);
11     }
12    
13     shstr::~shstr ()
14     {
15     erase ();
16     }
17    
18     char const * const
19     shstr::c_str () const
20     {
21     return m_str;
22     }
23    
24     shstr::size_type
25     shstr::length () const
26     {
27     return m_len;
28     }
29    
30     shstr &
31     shstr::operator = (char const * const rhs)
32     {
33     erase ();
34     insert (rhs);
35    
36     return *this;
37     }
38    
39     shstr &
40     shstr::operator = (const shstr &rhs)
41     {
42     if (m_str == rhs.m_str)
43     return *this;
44    
45     erase ();
46     insert (rhs.m_str);
47    
48     return *this;
49     }
50    
51     bool
52     shstr::operator == (const shstr &rhs) const
53     {
54     return m_str == rhs.m_str;
55     }
56    
57     bool
58     shstr::operator != (const shstr &rhs) const
59     {
60     return m_str != rhs.m_str;
61     }
62    
63     // string manager functions
64     shentry *
65     shstr::prepare (char const * const str)
66     {
67     size_t n = hash (str);
68     pairs::iterator it = find (str, n);
69    
70     shentry *entry;
71    
72     if (it == m_buckets[n].end ())
73     {
74     entry = new shentry (str, n);
75     m_buckets[n].push_back (entry);
76     }
77     else
78     entry = *it;
79    
80     return entry;
81     }
82    
83     bool
84     shstr::unref (char const * const str)
85     {
86     size_t n = hash (str);
87     pairs::iterator it = find (str, n);
88    
89     if (it == m_buckets[n].end ())
90     return false;
91     else
92     {
93     shentry *entry = *it;
94    
95     --entry->m_refcnt;
96    
97     if (entry->m_refcnt == 0)
98     {
99     m_buckets[n].erase (it);
100     delete entry;
101     return true;
102     }
103     else
104     return false;
105     }
106     }
107    
108     const shentry *
109     shstr::get (char const * const str)
110     {
111     size_t n = hash (str);
112     pairs::iterator it = find (str, n);
113     if (it == m_buckets[n].end ())
114     return NULL;
115     else
116     return *it;
117     }
118    
119     shstr::pairs::iterator
120     shstr::find (char const * const str, size_t n)
121     {
122     pairs &bucket = m_buckets[n];
123     pairs::iterator it = bucket.begin ();
124     pairs::iterator et = bucket.end ();
125    
126     while (it != et)
127     {
128     /* we first check hash equality, because if the hash is not
129     * equal, then the string most definately is not
130     */
131     if (n == (*it)->m_hash && __builtin_expect (!strcmp ((*it)->m_str, str), 0))
132     return it;
133     ++it;
134     }
135    
136     return et;
137     }
138    
139     size_t
140     shstr::hash (char const * const str)
141     {
142     char const *s = str;
143     unsigned long hash = 0;
144    
145     // use the one-at-a-time hash function
146     // see http://burtleburtle.net/bob/hash/doobs.html
147     while (*s)
148     {
149     hash += *s++;
150     hash += hash << 10;
151     hash ^= hash >> 6;
152     }
153    
154     hash += hash << 3;
155     hash ^= hash >> 11;
156     hash += hash << 15;
157    
158     return hash % m_bucketcnt;
159     }
160    
161     char const * const
162     shstr::insert (char const * const str, size_t *size)
163     {
164     shentry *entry = prepare (str);
165     ++entry->m_refcnt;
166    
167     if (entry->m_refcnt == 1)
168     ++m_cnt;
169     *size = entry->m_len;
170    
171     return entry->m_str;
172     }
173    
174     void
175     shstr::erase (char const * const str)
176     {
177     bool removed = unref (str);
178     if (removed)
179     --m_cnt;
180     }
181    
182     size_t
183     shstr::refs (char const * const str)
184     {
185     const shentry *entry = get (str);
186     if (entry == NULL)
187     return 0;
188     else
189     return entry->m_refcnt;
190     }
191    
192     size_t
193     shstr::strcnt ()
194     {
195     return m_cnt;
196     }
197    
198     size_t shstr::m_cnt = 0;
199     size_t shstr::m_bucketcnt = 1024;
200     shstr::pairs *shstr::m_buckets;