]> git.saurik.com Git - apple/javascriptcore.git/blob - kjs/identifier.cpp
JavaScriptCore-466.1.tar.gz
[apple/javascriptcore.git] / kjs / identifier.cpp
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