source: webkit/trunk/JavaScriptCore/kjs/identifier.cpp@ 34946

Last change on this file since 34946 was 34611, checked in by [email protected], 17 years ago

Trying to fix Windows build.

  • kjs/PropertyNameArray.h:
  • kjs/identifier.cpp: Include ExecState.h
  • Property svn:eol-style set to native
File size: 6.2 KB
Line 
1/*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#include "config.h"
22
23#include "identifier.h"
24
25#include "ExecState.h"
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
33namespace KJS {
34
35typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable;
36
37class IdentifierTable {
38public:
39 ~IdentifierTable()
40 {
41 HashSet<UString::Rep*>::iterator end = m_table.end();
42 for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter)
43 (*iter)->identifierTable = 0;
44 }
45
46 std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value)
47 {
48 std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add(value);
49 (*result.first)->identifierTable = this;
50 return result;
51 }
52
53 template<typename U, typename V>
54 std::pair<HashSet<UString::Rep*>::iterator, bool> add(U value)
55 {
56 std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add<U, V>(value);
57 (*result.first)->identifierTable = this;
58 return result;
59 }
60
61 void remove(UString::Rep* r) { m_table.remove(r); }
62
63 LiteralIdentifierTable& literalTable() { return m_literalTable; }
64
65private:
66 HashSet<UString::Rep*> m_table;
67 LiteralIdentifierTable m_literalTable;
68};
69
70IdentifierTable* createIdentifierTable()
71{
72 return new IdentifierTable;
73}
74
75void deleteIdentifierTable(IdentifierTable* table)
76{
77 delete table;
78}
79
80bool Identifier::equal(const UString::Rep *r, const char *s)
81{
82 int length = r->len;
83 const UChar *d = r->data();
84 for (int i = 0; i != length; ++i)
85 if (d[i] != (unsigned char)s[i])
86 return false;
87 return s[length] == 0;
88}
89
90bool Identifier::equal(const UString::Rep *r, const UChar *s, int length)
91{
92 if (r->len != length)
93 return false;
94 const UChar *d = r->data();
95 for (int i = 0; i != length; ++i)
96 if (d[i] != s[i])
97 return false;
98 return true;
99}
100
101struct CStringTranslator
102{
103 static unsigned hash(const char *c)
104 {
105 return UString::Rep::computeHash(c);
106 }
107
108 static bool equal(UString::Rep *r, const char *s)
109 {
110 return Identifier::equal(r, s);
111 }
112
113 static void translate(UString::Rep*& location, const char *c, unsigned hash)
114 {
115 size_t length = strlen(c);
116 UChar *d = static_cast<UChar *>(fastMalloc(sizeof(UChar) * length));
117 for (size_t i = 0; i != length; i++)
118 d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
119
120 UString::Rep *r = UString::Rep::create(d, static_cast<int>(length)).releaseRef();
121 r->rc = 0;
122 r->_hash = hash;
123
124 location = r;
125 }
126};
127
128PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c)
129{
130 if (!c) {
131 UString::Rep::null.hash();
132 return &UString::Rep::null;
133 }
134
135 if (!c[0]) {
136 UString::Rep::empty.hash();
137 return &UString::Rep::empty;
138 }
139
140 IdentifierTable& identifierTable = *globalData->identifierTable;
141 LiteralIdentifierTable& literalIdentifierTable = identifierTable.literalTable();
142
143 const LiteralIdentifierTable::iterator& iter = literalIdentifierTable.find(c);
144 if (iter != literalIdentifierTable.end())
145 return iter->second;
146
147 UString::Rep* addedString = *identifierTable.add<const char*, CStringTranslator>(c).first;
148 literalIdentifierTable.add(c, addedString);
149
150 return addedString;
151}
152
153PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const char* c)
154{
155 return add(&exec->globalData(), c);
156}
157
158struct UCharBuffer {
159 const UChar *s;
160 unsigned int length;
161};
162
163struct UCharBufferTranslator
164{
165 static unsigned hash(const UCharBuffer& buf)
166 {
167 return UString::Rep::computeHash(buf.s, buf.length);
168 }
169
170 static bool equal(UString::Rep *str, const UCharBuffer& buf)
171 {
172 return Identifier::equal(str, buf.s, buf.length);
173 }
174
175 static void translate(UString::Rep *& location, const UCharBuffer& buf, unsigned hash)
176 {
177 UChar *d = static_cast<UChar *>(fastMalloc(sizeof(UChar) * buf.length));
178 for (unsigned i = 0; i != buf.length; i++)
179 d[i] = buf.s[i];
180
181 UString::Rep *r = UString::Rep::create(d, buf.length).releaseRef();
182 r->rc = 0;
183 r->_hash = hash;
184
185 location = r;
186 }
187};
188
189PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* s, int length)
190{
191 if (!length) {
192 UString::Rep::empty.hash();
193 return &UString::Rep::empty;
194 }
195
196 UCharBuffer buf = {s, length};
197 return *globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf).first;
198}
199
200PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int length)
201{
202 return add(&exec->globalData(), s, length);
203}
204
205PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r)
206{
207 ASSERT(!r->identifierTable);
208
209 if (r->len == 0) {
210 UString::Rep::empty.hash();
211 return &UString::Rep::empty;
212 }
213
214 return *globalData->identifierTable->add(r).first;
215}
216
217PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep* r)
218{
219 return addSlowCase(&exec->globalData(), r);
220}
221
222void Identifier::remove(UString::Rep *r)
223{
224 r->identifierTable->remove(r);
225}
226
227} // namespace KJS
Note: See TracBrowser for help on using the repository browser.