2 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
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.
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.
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.
25 #include <wtf/Optional.h>
26 #include <wtf/ThreadSpecific.h>
27 #include <wtf/WTFThreadData.h>
28 #include <wtf/text/CString.h>
29 #include <wtf/text/UniquedStringImpl.h>
30 #include <wtf/text/WTFString.h>
36 ALWAYS_INLINE
bool isIndex(uint32_t index
)
38 return index
!= 0xFFFFFFFFU
;
41 template <typename CharType
>
42 ALWAYS_INLINE Optional
<uint32_t> parseIndex(const CharType
* characters
, unsigned length
)
44 // An empty string is not a number.
48 // Get the first character, turning it into a digit.
49 uint32_t value
= characters
[0] - '0';
53 // Check for leading zeros. If the first characher is 0, then the
54 // length of the string must be one - e.g. "042" is not equal to "42".
55 if (!value
&& length
> 1)
59 // Multiply value by 10, checking for overflow out of 32 bits.
60 if (value
> 0xFFFFFFFFU
/ 10)
64 // Get the next character, turning it into a digit.
65 uint32_t newValue
= *(++characters
) - '0';
69 // Add in the old value, checking for overflow out of 32 bits.
81 ALWAYS_INLINE Optional
<uint32_t> parseIndex(StringImpl
& impl
)
84 return parseIndex(impl
.characters8(), impl
.length());
85 return parseIndex(impl
.characters16(), impl
.length());
89 friend class Structure
;
92 enum EmptyIdentifierFlag
{ EmptyIdentifier
};
93 Identifier(EmptyIdentifierFlag
) : m_string(StringImpl::empty()) { ASSERT(m_string
.impl()->isAtomic()); }
95 const String
& string() const { return m_string
; }
96 UniquedStringImpl
* impl() const { return static_cast<UniquedStringImpl
*>(m_string
.impl()); }
98 int length() const { return m_string
.length(); }
100 CString
ascii() const { return m_string
.ascii(); }
101 CString
utf8() const { return m_string
.utf8(); }
103 // There's 2 functions to construct Identifier from string, (1) fromString and (2) fromUid.
104 // They have different meanings in keeping or discarding symbol-ness of strings.
106 // Just construct Identifier from string. String held by Identifier is always atomized.
107 // Symbol-ness of StringImpl*, which represents that the string is inteded to be used for ES6 Symbols, is discarded.
108 // So a constructed Identifier never represents a symbol.
110 // `StringImpl* uid` represents ether String or Symbol property.
111 // fromUid keeps symbol-ness of provided StringImpl* while fromString discards it.
112 // Use fromUid when constructing Identifier from StringImpl* which may represent symbols.
114 // Only to be used with string literals.
115 template<unsigned charactersCount
>
116 static Identifier
fromString(VM
*, const char (&characters
)[charactersCount
]);
117 template<unsigned charactersCount
>
118 static Identifier
fromString(ExecState
*, const char (&characters
)[charactersCount
]);
119 static Identifier
fromString(VM
*, const LChar
*, int length
);
120 static Identifier
fromString(VM
*, const UChar
*, int length
);
121 static Identifier
fromString(VM
*, const String
&);
122 static Identifier
fromString(ExecState
*, AtomicStringImpl
*);
123 static Identifier
fromString(ExecState
*, const AtomicString
&);
124 static Identifier
fromString(ExecState
*, const String
&);
125 static Identifier
fromString(ExecState
*, const char*);
127 static Identifier
fromUid(VM
*, UniquedStringImpl
* uid
);
128 static Identifier
fromUid(ExecState
*, UniquedStringImpl
* uid
);
129 static Identifier
fromUid(const PrivateName
&);
131 static Identifier
createLCharFromUChar(VM
* vm
, const UChar
* s
, int length
) { return Identifier(vm
, add8(vm
, s
, length
)); }
133 JS_EXPORT_PRIVATE
static Identifier
from(ExecState
*, unsigned y
);
134 JS_EXPORT_PRIVATE
static Identifier
from(ExecState
*, int y
);
135 static Identifier
from(ExecState
*, double y
);
136 static Identifier
from(VM
*, unsigned y
);
137 static Identifier
from(VM
*, int y
);
138 static Identifier
from(VM
*, double y
);
140 bool isNull() const { return m_string
.isNull(); }
141 bool isEmpty() const { return m_string
.isEmpty(); }
142 bool isSymbol() const { return !isNull() && impl()->isSymbol(); }
144 friend bool operator==(const Identifier
&, const Identifier
&);
145 friend bool operator!=(const Identifier
&, const Identifier
&);
147 friend bool operator==(const Identifier
&, const LChar
*);
148 friend bool operator==(const Identifier
&, const char*);
149 friend bool operator!=(const Identifier
&, const LChar
*);
150 friend bool operator!=(const Identifier
&, const char*);
152 static bool equal(const StringImpl
*, const LChar
*);
153 static inline bool equal(const StringImpl
*a
, const char*b
) { return Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
)); };
154 static bool equal(const StringImpl
*, const LChar
*, unsigned length
);
155 static bool equal(const StringImpl
*, const UChar
*, unsigned length
);
156 static bool equal(const StringImpl
* a
, const StringImpl
* b
) { return ::equal(a
, b
); }
158 // Only to be used with string literals.
159 JS_EXPORT_PRIVATE
static Ref
<StringImpl
> add(VM
*, const char*);
160 JS_EXPORT_PRIVATE
static Ref
<StringImpl
> add(ExecState
*, const char*);
162 void dump(PrintStream
&) const;
167 // Only to be used with string literals.
168 template<unsigned charactersCount
>
169 Identifier(VM
* vm
, const char (&characters
)[charactersCount
]) : m_string(add(vm
, characters
)) { ASSERT(m_string
.impl()->isAtomic()); }
171 Identifier(VM
* vm
, const LChar
* s
, int length
) : m_string(add(vm
, s
, length
)) { ASSERT(m_string
.impl()->isAtomic()); }
172 Identifier(VM
* vm
, const UChar
* s
, int length
) : m_string(add(vm
, s
, length
)) { ASSERT(m_string
.impl()->isAtomic()); }
173 Identifier(ExecState
*, AtomicStringImpl
*);
174 Identifier(ExecState
*, const AtomicString
&);
175 Identifier(VM
* vm
, const String
& string
) : m_string(add(vm
, string
.impl())) { ASSERT(m_string
.impl()->isAtomic()); }
176 Identifier(VM
* vm
, StringImpl
* rep
) : m_string(add(vm
, rep
)) { ASSERT(m_string
.impl()->isAtomic()); }
178 Identifier(SymbolImpl
& uid
)
183 template <typename CharType
>
184 ALWAYS_INLINE
static uint32_t toUInt32FromCharacters(const CharType
* characters
, unsigned length
, bool& ok
);
186 static bool equal(const Identifier
& a
, const Identifier
& b
) { return a
.m_string
.impl() == b
.m_string
.impl(); }
187 static bool equal(const Identifier
& a
, const LChar
* b
) { return equal(a
.m_string
.impl(), b
); }
189 template <typename T
> static Ref
<StringImpl
> add(VM
*, const T
*, int length
);
190 static Ref
<StringImpl
> add8(VM
*, const UChar
*, int length
);
191 template <typename T
> ALWAYS_INLINE
static bool canUseSingleCharacterString(T
);
193 static Ref
<StringImpl
> add(ExecState
*, StringImpl
*);
194 static Ref
<StringImpl
> add(VM
*, StringImpl
*);
197 JS_EXPORT_PRIVATE
static void checkCurrentAtomicStringTable(ExecState
*);
198 JS_EXPORT_PRIVATE
static void checkCurrentAtomicStringTable(VM
*);
200 JS_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH
static void checkCurrentAtomicStringTable(ExecState
*);
201 JS_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH
static void checkCurrentAtomicStringTable(VM
*);
205 template <> ALWAYS_INLINE
bool Identifier::canUseSingleCharacterString(LChar
)
207 ASSERT(maxSingleCharacterString
== 0xff);
211 template <> ALWAYS_INLINE
bool Identifier::canUseSingleCharacterString(UChar c
)
213 return (c
<= maxSingleCharacterString
);
216 template <typename T
>
217 Ref
<StringImpl
> Identifier::add(VM
* vm
, const T
* s
, int length
)
221 if (canUseSingleCharacterString(c
))
222 return *vm
->smallStrings
.singleCharacterStringRep(c
);
225 return *StringImpl::empty();
227 return *AtomicStringImpl::add(s
, length
);
230 inline bool operator==(const Identifier
& a
, const Identifier
& b
)
232 return Identifier::equal(a
, b
);
235 inline bool operator!=(const Identifier
& a
, const Identifier
& b
)
237 return !Identifier::equal(a
, b
);
240 inline bool operator==(const Identifier
& a
, const LChar
* b
)
242 return Identifier::equal(a
, b
);
245 inline bool operator==(const Identifier
& a
, const char* b
)
247 return Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
));
250 inline bool operator!=(const Identifier
& a
, const LChar
* b
)
252 return !Identifier::equal(a
, b
);
255 inline bool operator!=(const Identifier
& a
, const char* b
)
257 return !Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
));
260 inline bool Identifier::equal(const StringImpl
* r
, const LChar
* s
)
262 return WTF::equal(r
, s
);
265 inline bool Identifier::equal(const StringImpl
* r
, const LChar
* s
, unsigned length
)
267 return WTF::equal(r
, s
, length
);
270 inline bool Identifier::equal(const StringImpl
* r
, const UChar
* s
, unsigned length
)
272 return WTF::equal(r
, s
, length
);
275 ALWAYS_INLINE Optional
<uint32_t> parseIndex(const Identifier
& identifier
)
277 auto uid
= identifier
.impl();
282 return parseIndex(*uid
);
285 struct IdentifierRepHash
: PtrHash
<RefPtr
<UniquedStringImpl
>> {
286 static unsigned hash(const RefPtr
<UniquedStringImpl
>& key
) { return key
->existingSymbolAwareHash(); }
287 static unsigned hash(UniquedStringImpl
* key
) { return key
->existingSymbolAwareHash(); }
290 struct IdentifierMapIndexHashTraits
: HashTraits
<int> {
291 static int emptyValue() { return std::numeric_limits
<int>::max(); }
292 static const bool emptyValueIsZero
= false;
295 typedef HashMap
<RefPtr
<UniquedStringImpl
>, int, IdentifierRepHash
, HashTraits
<RefPtr
<UniquedStringImpl
>>, IdentifierMapIndexHashTraits
> IdentifierMap
;
296 typedef HashMap
<UniquedStringImpl
*, int, IdentifierRepHash
, HashTraits
<UniquedStringImpl
*>, IdentifierMapIndexHashTraits
> BorrowedIdentifierMap
;
302 template <> struct VectorTraits
<JSC::Identifier
> : SimpleClassVectorTraits
{ };
306 #endif // Identifier_h