1 | /*
|
---|
2 | * This file is part of the KDE libraries
|
---|
3 | * Copyright (C) 2002 Apple Computer, Inc
|
---|
4 | *
|
---|
5 | * This library is free software; you can redistribute it and/or
|
---|
6 | * modify it under the terms of the GNU Library General Public
|
---|
7 | * License as published by the Free Software Foundation; either
|
---|
8 | * version 2 of the License, or (at your option) any later version.
|
---|
9 | *
|
---|
10 | * This library is distributed in the hope that it will be useful,
|
---|
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
13 | * Library General Public License for more details.
|
---|
14 | *
|
---|
15 | * You should have received a copy of the GNU Library General Public License
|
---|
16 | * along with this library; see the file COPYING.LIB. If not, write to
|
---|
17 | * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
---|
18 | * Boston, MA 02111-1307, USA.
|
---|
19 | *
|
---|
20 | */
|
---|
21 |
|
---|
22 | #include "identifier.h"
|
---|
23 |
|
---|
24 | namespace KJS {
|
---|
25 |
|
---|
26 | Identifier Identifier::null;
|
---|
27 |
|
---|
28 | extern const Identifier argumentsPropertyName("arguments");
|
---|
29 | extern const Identifier calleePropertyName("callee");
|
---|
30 | extern const Identifier constructorPropertyName("constructor");
|
---|
31 | extern const Identifier lengthPropertyName("length");
|
---|
32 | extern const Identifier messagePropertyName("message");
|
---|
33 | extern const Identifier namePropertyName("name");
|
---|
34 | extern const Identifier prototypePropertyName("prototype");
|
---|
35 | extern const Identifier specialPrototypePropertyName("__proto__");
|
---|
36 | extern const Identifier toLocaleStringPropertyName("toLocaleString");
|
---|
37 | extern const Identifier toStringPropertyName("toString");
|
---|
38 | extern const Identifier valueOfPropertyName("valueOf");
|
---|
39 |
|
---|
40 | const int _minTableSize = 64;
|
---|
41 |
|
---|
42 | UString::Rep **Identifier::_table;
|
---|
43 | int Identifier::_tableSize;
|
---|
44 | int Identifier::_tableSizeMask;
|
---|
45 | int Identifier::_keyCount;
|
---|
46 |
|
---|
47 | bool Identifier::equal(UString::Rep *r, const char *s)
|
---|
48 | {
|
---|
49 | int length = r->len;
|
---|
50 | const UChar *d = r->dat;
|
---|
51 | for (int i = 0; i != length; ++i)
|
---|
52 | if (d[i].unicode() != (unsigned char)s[i])
|
---|
53 | return false;
|
---|
54 | return s[length] == 0;
|
---|
55 | }
|
---|
56 |
|
---|
57 | bool Identifier::equal(UString::Rep *r, const UChar *s, int length)
|
---|
58 | {
|
---|
59 | if (r->len != length)
|
---|
60 | return false;
|
---|
61 | const UChar *d = r->dat;
|
---|
62 | for (int i = 0; i != length; ++i)
|
---|
63 | if (d[i].unicode() != s[i].unicode())
|
---|
64 | return false;
|
---|
65 | return true;
|
---|
66 | }
|
---|
67 |
|
---|
68 | bool Identifier::equal(UString::Rep *r, UString::Rep *b)
|
---|
69 | {
|
---|
70 | int length = r->len;
|
---|
71 | if (length != b->len)
|
---|
72 | return false;
|
---|
73 | const UChar *d = r->dat;
|
---|
74 | const UChar *s = b->dat;
|
---|
75 | for (int i = 0; i != length; ++i)
|
---|
76 | if (d[i].unicode() != s[i].unicode())
|
---|
77 | return false;
|
---|
78 | return true;
|
---|
79 | }
|
---|
80 |
|
---|
81 | UString::Rep *Identifier::add(const char *c)
|
---|
82 | {
|
---|
83 | if (!c)
|
---|
84 | return &UString::Rep::null;
|
---|
85 | int length = strlen(c);
|
---|
86 | if (length == 0)
|
---|
87 | return &UString::Rep::empty;
|
---|
88 |
|
---|
89 | if (!_table)
|
---|
90 | expand();
|
---|
91 |
|
---|
92 | unsigned hash = UString::Rep::computeHash(c);
|
---|
93 |
|
---|
94 | int i = hash & _tableSizeMask;
|
---|
95 | while (UString::Rep *key = _table[i]) {
|
---|
96 | if (equal(key, c))
|
---|
97 | return key;
|
---|
98 | i = (i + 1) & _tableSizeMask;
|
---|
99 | }
|
---|
100 |
|
---|
101 | UChar *d = new UChar[length];
|
---|
102 | for (int j = 0; j != length; j++)
|
---|
103 | d[j] = c[j];
|
---|
104 |
|
---|
105 | UString::Rep *r = new UString::Rep;
|
---|
106 | r->dat = d;
|
---|
107 | r->len = length;
|
---|
108 | r->capacity = UString::Rep::capacityForIdentifier;
|
---|
109 | r->rc = 0;
|
---|
110 | r->_hash = hash;
|
---|
111 |
|
---|
112 | _table[i] = r;
|
---|
113 | ++_keyCount;
|
---|
114 |
|
---|
115 | if (_keyCount * 2 >= _tableSize)
|
---|
116 | expand();
|
---|
117 |
|
---|
118 | return r;
|
---|
119 | }
|
---|
120 |
|
---|
121 | UString::Rep *Identifier::add(const UChar *s, int length)
|
---|
122 | {
|
---|
123 | if (length == 0)
|
---|
124 | return &UString::Rep::empty;
|
---|
125 |
|
---|
126 | if (!_table)
|
---|
127 | expand();
|
---|
128 |
|
---|
129 | unsigned hash = UString::Rep::computeHash(s, length);
|
---|
130 |
|
---|
131 | int i = hash & _tableSizeMask;
|
---|
132 | while (UString::Rep *key = _table[i]) {
|
---|
133 | if (equal(key, s, length))
|
---|
134 | return key;
|
---|
135 | i = (i + 1) & _tableSizeMask;
|
---|
136 | }
|
---|
137 |
|
---|
138 | UChar *d = new UChar[length];
|
---|
139 | for (int j = 0; j != length; j++)
|
---|
140 | d[j] = s[j];
|
---|
141 |
|
---|
142 | UString::Rep *r = new UString::Rep;
|
---|
143 | r->dat = d;
|
---|
144 | r->len = length;
|
---|
145 | r->capacity = UString::Rep::capacityForIdentifier;
|
---|
146 | r->rc = 0;
|
---|
147 | r->_hash = hash;
|
---|
148 |
|
---|
149 | _table[i] = r;
|
---|
150 | ++_keyCount;
|
---|
151 |
|
---|
152 | if (_keyCount * 2 >= _tableSize)
|
---|
153 | expand();
|
---|
154 |
|
---|
155 | return r;
|
---|
156 | }
|
---|
157 |
|
---|
158 | UString::Rep *Identifier::add(UString::Rep *r)
|
---|
159 | {
|
---|
160 | if (r->capacity == UString::Rep::capacityForIdentifier)
|
---|
161 | return r;
|
---|
162 | if (r->len == 0)
|
---|
163 | return &UString::Rep::empty;
|
---|
164 |
|
---|
165 | if (!_table)
|
---|
166 | expand();
|
---|
167 |
|
---|
168 | unsigned hash = r->hash();
|
---|
169 |
|
---|
170 | int i = hash & _tableSizeMask;
|
---|
171 | while (UString::Rep *key = _table[i]) {
|
---|
172 | if (equal(key, r))
|
---|
173 | return key;
|
---|
174 | i = (i + 1) & _tableSizeMask;
|
---|
175 | }
|
---|
176 |
|
---|
177 | r->capacity = UString::Rep::capacityForIdentifier;
|
---|
178 |
|
---|
179 | _table[i] = r;
|
---|
180 | ++_keyCount;
|
---|
181 |
|
---|
182 | if (_keyCount * 2 >= _tableSize)
|
---|
183 | expand();
|
---|
184 |
|
---|
185 | return r;
|
---|
186 | }
|
---|
187 |
|
---|
188 | inline void Identifier::insert(UString::Rep *key)
|
---|
189 | {
|
---|
190 | unsigned hash = key->hash();
|
---|
191 |
|
---|
192 | int i = hash & _tableSizeMask;
|
---|
193 | while (_table[i])
|
---|
194 | i = (i + 1) & _tableSizeMask;
|
---|
195 |
|
---|
196 | _table[i] = key;
|
---|
197 | }
|
---|
198 |
|
---|
199 | void Identifier::remove(UString::Rep *r)
|
---|
200 | {
|
---|
201 | unsigned hash = r->hash();
|
---|
202 |
|
---|
203 | UString::Rep *key;
|
---|
204 |
|
---|
205 | int i = hash & _tableSizeMask;
|
---|
206 | while ((key = _table[i])) {
|
---|
207 | if (equal(key, r))
|
---|
208 | break;
|
---|
209 | i = (i + 1) & _tableSizeMask;
|
---|
210 | }
|
---|
211 | if (!key)
|
---|
212 | return;
|
---|
213 |
|
---|
214 | _table[i] = 0;
|
---|
215 | --_keyCount;
|
---|
216 |
|
---|
217 | if (_keyCount * 3 < _tableSize && _tableSize > _minTableSize) {
|
---|
218 | shrink();
|
---|
219 | return;
|
---|
220 | }
|
---|
221 |
|
---|
222 | // Reinsert all the items to the right in the same cluster.
|
---|
223 | while (1) {
|
---|
224 | i = (i + 1) & _tableSizeMask;
|
---|
225 | key = _table[i];
|
---|
226 | if (!key)
|
---|
227 | break;
|
---|
228 | _table[i] = 0;
|
---|
229 | insert(key);
|
---|
230 | }
|
---|
231 | }
|
---|
232 |
|
---|
233 | void Identifier::expand()
|
---|
234 | {
|
---|
235 | rehash(_tableSize == 0 ? _minTableSize : _tableSize * 2);
|
---|
236 | }
|
---|
237 |
|
---|
238 | void Identifier::shrink()
|
---|
239 | {
|
---|
240 | rehash(_tableSize / 2);
|
---|
241 | }
|
---|
242 |
|
---|
243 | void Identifier::rehash(int newTableSize)
|
---|
244 | {
|
---|
245 | int oldTableSize = _tableSize;
|
---|
246 | UString::Rep **oldTable = _table;
|
---|
247 |
|
---|
248 | _tableSize = newTableSize;
|
---|
249 | _tableSizeMask = newTableSize - 1;
|
---|
250 | _table = (UString::Rep **)calloc(newTableSize, sizeof(UString::Rep *));
|
---|
251 |
|
---|
252 | for (int i = 0; i != oldTableSize; ++i)
|
---|
253 | if (UString::Rep *key = oldTable[i])
|
---|
254 | insert(key);
|
---|
255 |
|
---|
256 | free(oldTable);
|
---|
257 | }
|
---|
258 |
|
---|
259 | } // namespace KJS
|
---|