]>
Commit | Line | Data |
---|---|---|
b37bf2e1 A |
1 | /* |
2 | * This file is part of the KDE libraries | |
3 | * Copyright (C) 2003 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., 51 Franklin Street, Fifth Floor, | |
18 | * Boston, MA 02110-1301, USA. | |
19 | * | |
20 | */ | |
21 | ||
22 | #include "config.h" | |
23 | ||
24 | #include "identifier.h" | |
25 | ||
26 | #include "JSLock.h" | |
27 | #include <new> // for placement new | |
28 | #include <string.h> // for strlen | |
29 | #include <wtf/Assertions.h> | |
30 | #include <wtf/FastMalloc.h> | |
31 | #include <wtf/HashSet.h> | |
32 | ||
33 | namespace WTF { | |
34 | ||
35 | template<typename T> struct DefaultHash; | |
36 | template<typename T> struct StrHash; | |
37 | ||
38 | template<> struct StrHash<KJS::UString::Rep *> { | |
39 | static unsigned hash(const KJS::UString::Rep *key) { return key->hash(); } | |
40 | static bool equal(const KJS::UString::Rep *a, const KJS::UString::Rep *b) { return KJS::Identifier::equal(a, b); } | |
41 | static const bool safeToCompareToEmptyOrDeleted = false; | |
42 | }; | |
43 | ||
44 | template<> struct DefaultHash<KJS::UString::Rep *> { | |
45 | typedef StrHash<KJS::UString::Rep *> Hash; | |
46 | }; | |
47 | ||
48 | } | |
49 | ||
50 | namespace KJS { | |
51 | ||
52 | typedef HashSet<UString::Rep *> IdentifierTable; | |
53 | static IdentifierTable *table; | |
54 | ||
55 | static inline IdentifierTable& identifierTable() | |
56 | { | |
57 | ASSERT(JSLock::lockCount() > 0); | |
58 | ||
59 | if (!table) | |
60 | table = new IdentifierTable; | |
61 | return *table; | |
62 | } | |
63 | ||
64 | ||
65 | bool Identifier::equal(const UString::Rep *r, const char *s) | |
66 | { | |
67 | int length = r->len; | |
68 | const UChar *d = r->data(); | |
69 | for (int i = 0; i != length; ++i) | |
70 | if (d[i].uc != (unsigned char)s[i]) | |
71 | return false; | |
72 | return s[length] == 0; | |
73 | } | |
74 | ||
75 | bool Identifier::equal(const UString::Rep *r, const UChar *s, int length) | |
76 | { | |
77 | if (r->len != length) | |
78 | return false; | |
79 | const UChar *d = r->data(); | |
80 | for (int i = 0; i != length; ++i) | |
81 | if (d[i].uc != s[i].uc) | |
82 | return false; | |
83 | return true; | |
84 | } | |
85 | ||
86 | bool Identifier::equal(const UString::Rep *r, const UString::Rep *b) | |
87 | { | |
88 | int length = r->len; | |
89 | if (length != b->len) | |
90 | return false; | |
91 | const UChar *d = r->data(); | |
92 | const UChar *s = b->data(); | |
93 | for (int i = 0; i != length; ++i) | |
94 | if (d[i].uc != s[i].uc) | |
95 | return false; | |
96 | return true; | |
97 | } | |
98 | ||
99 | struct CStringTranslator | |
100 | { | |
101 | static unsigned hash(const char *c) | |
102 | { | |
103 | return UString::Rep::computeHash(c); | |
104 | } | |
105 | ||
106 | static bool equal(UString::Rep *r, const char *s) | |
107 | { | |
108 | return Identifier::equal(r, s); | |
109 | } | |
110 | ||
111 | static void translate(UString::Rep*& location, const char *c, unsigned hash) | |
112 | { | |
113 | size_t length = strlen(c); | |
114 | UChar *d = static_cast<UChar *>(fastMalloc(sizeof(UChar) * length)); | |
115 | for (size_t i = 0; i != length; i++) | |
116 | d[i] = c[i]; | |
117 | ||
118 | UString::Rep *r = UString::Rep::create(d, static_cast<int>(length)).releaseRef(); | |
119 | r->isIdentifier = 1; | |
120 | r->rc = 0; | |
121 | r->_hash = hash; | |
122 | ||
123 | location = r; | |
124 | } | |
125 | }; | |
126 | ||
127 | PassRefPtr<UString::Rep> Identifier::add(const char *c) | |
128 | { | |
129 | if (!c) { | |
130 | UString::Rep::null.hash(); | |
131 | return &UString::Rep::null; | |
132 | } | |
133 | ||
134 | if (!c[0]) { | |
135 | UString::Rep::empty.hash(); | |
136 | return &UString::Rep::empty; | |
137 | } | |
138 | ||
139 | return *identifierTable().add<const char *, CStringTranslator>(c).first; | |
140 | } | |
141 | ||
142 | struct UCharBuffer { | |
143 | const UChar *s; | |
144 | unsigned int length; | |
145 | }; | |
146 | ||
147 | struct UCharBufferTranslator | |
148 | { | |
149 | static unsigned hash(const UCharBuffer& buf) | |
150 | { | |
151 | return UString::Rep::computeHash(buf.s, buf.length); | |
152 | } | |
153 | ||
154 | static bool equal(UString::Rep *str, const UCharBuffer& buf) | |
155 | { | |
156 | return Identifier::equal(str, buf.s, buf.length); | |
157 | } | |
158 | ||
159 | static void translate(UString::Rep *& location, const UCharBuffer& buf, unsigned hash) | |
160 | { | |
161 | UChar *d = static_cast<UChar *>(fastMalloc(sizeof(UChar) * buf.length)); | |
162 | for (unsigned i = 0; i != buf.length; i++) | |
163 | d[i] = buf.s[i]; | |
164 | ||
165 | UString::Rep *r = UString::Rep::create(d, buf.length).releaseRef(); | |
166 | r->isIdentifier = 1; | |
167 | r->rc = 0; | |
168 | r->_hash = hash; | |
169 | ||
170 | location = r; | |
171 | } | |
172 | }; | |
173 | ||
174 | PassRefPtr<UString::Rep> Identifier::add(const UChar *s, int length) | |
175 | { | |
176 | if (!length) { | |
177 | UString::Rep::empty.hash(); | |
178 | return &UString::Rep::empty; | |
179 | } | |
180 | ||
181 | UCharBuffer buf = {s, length}; | |
182 | return *identifierTable().add<UCharBuffer, UCharBufferTranslator>(buf).first; | |
183 | } | |
184 | ||
185 | PassRefPtr<UString::Rep> Identifier::addSlowCase(UString::Rep *r) | |
186 | { | |
187 | ASSERT(!r->isIdentifier); | |
188 | ||
189 | if (r->len == 0) { | |
190 | UString::Rep::empty.hash(); | |
191 | return &UString::Rep::empty; | |
192 | } | |
193 | ||
194 | UString::Rep *result = *identifierTable().add(r).first; | |
195 | if (result == r) | |
196 | r->isIdentifier = true; | |
197 | return result; | |
198 | } | |
199 | ||
200 | void Identifier::remove(UString::Rep *r) | |
201 | { | |
202 | identifierTable().remove(r); | |
203 | } | |
204 | ||
205 | } // namespace KJS |