2 * This file is part of the KDE libraries
3 * Copyright (C) 2003 Apple Computer, Inc
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.
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.
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.
24 #include "identifier.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>
35 template<typename T
> struct DefaultHash
;
36 template<typename T
> struct StrHash
;
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;
44 template<> struct DefaultHash
<KJS::UString::Rep
*> {
45 typedef StrHash
<KJS::UString::Rep
*> Hash
;
52 typedef HashSet
<UString::Rep
*> IdentifierTable
;
53 static IdentifierTable
*table
;
55 static inline IdentifierTable
& identifierTable()
57 ASSERT(JSLock::lockCount() > 0);
60 table
= new IdentifierTable
;
65 bool Identifier::equal(const UString::Rep
*r
, const char *s
)
68 const UChar
*d
= r
->data();
69 for (int i
= 0; i
!= length
; ++i
)
70 if (d
[i
].uc
!= (unsigned char)s
[i
])
72 return s
[length
] == 0;
75 bool Identifier::equal(const UString::Rep
*r
, const UChar
*s
, int length
)
79 const UChar
*d
= r
->data();
80 for (int i
= 0; i
!= length
; ++i
)
81 if (d
[i
].uc
!= s
[i
].uc
)
86 bool Identifier::equal(const UString::Rep
*r
, const UString::Rep
*b
)
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
)
99 struct CStringTranslator
101 static unsigned hash(const char *c
)
103 return UString::Rep::computeHash(c
);
106 static bool equal(UString::Rep
*r
, const char *s
)
108 return Identifier::equal(r
, s
);
111 static void translate(UString::Rep
*& location
, const char *c
, unsigned hash
)
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
++)
118 UString::Rep
*r
= UString::Rep::create(d
, static_cast<int>(length
)).releaseRef();
127 PassRefPtr
<UString::Rep
> Identifier::add(const char *c
)
130 UString::Rep::null
.hash();
131 return &UString::Rep::null
;
135 UString::Rep::empty
.hash();
136 return &UString::Rep::empty
;
139 return *identifierTable().add
<const char *, CStringTranslator
>(c
).first
;
147 struct UCharBufferTranslator
149 static unsigned hash(const UCharBuffer
& buf
)
151 return UString::Rep::computeHash(buf
.s
, buf
.length
);
154 static bool equal(UString::Rep
*str
, const UCharBuffer
& buf
)
156 return Identifier::equal(str
, buf
.s
, buf
.length
);
159 static void translate(UString::Rep
*& location
, const UCharBuffer
& buf
, unsigned hash
)
161 UChar
*d
= static_cast<UChar
*>(fastMalloc(sizeof(UChar
) * buf
.length
));
162 for (unsigned i
= 0; i
!= buf
.length
; i
++)
165 UString::Rep
*r
= UString::Rep::create(d
, buf
.length
).releaseRef();
174 PassRefPtr
<UString::Rep
> Identifier::add(const UChar
*s
, int length
)
177 UString::Rep::empty
.hash();
178 return &UString::Rep::empty
;
181 UCharBuffer buf
= {s
, length
};
182 return *identifierTable().add
<UCharBuffer
, UCharBufferTranslator
>(buf
).first
;
185 PassRefPtr
<UString::Rep
> Identifier::addSlowCase(UString::Rep
*r
)
187 ASSERT(!r
->isIdentifier
);
190 UString::Rep::empty
.hash();
191 return &UString::Rep::empty
;
194 UString::Rep
*result
= *identifierTable().add(r
).first
;
196 r
->isIdentifier
= true;
200 void Identifier::remove(UString::Rep
*r
)
202 identifierTable().remove(r
);