]>
Commit | Line | Data |
---|---|---|
9dae56ea | 1 | /* |
14957cd0 A |
2 | * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) |
3 | * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
4 | * Copyright (C) 2009 Google Inc. All rights reserved. | |
9dae56ea | 5 | * |
14957cd0 A |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2 of the License, or (at your option) any later version. | |
9dae56ea | 10 | * |
14957cd0 A |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Library General Public License for more details. | |
9dae56ea | 15 | * |
14957cd0 A |
16 | * You should have received a copy of the GNU Library General Public License |
17 | * along with this library; see the file COPYING.LIB. If not, write to | |
18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
19 | * Boston, MA 02110-1301, USA. | |
9dae56ea A |
20 | * |
21 | */ | |
22 | ||
23 | #ifndef UString_h | |
24 | #define UString_h | |
25 | ||
14957cd0 | 26 | #include <wtf/text/StringImpl.h> |
9dae56ea A |
27 | |
28 | namespace JSC { | |
29 | ||
14957cd0 A |
30 | class UString { |
31 | public: | |
32 | // Construct a null string, distinguishable from an empty string. | |
33 | UString() { } | |
9dae56ea | 34 | |
14957cd0 A |
35 | // Construct a string with UTF-16 data. |
36 | UString(const UChar* characters, unsigned length); | |
9dae56ea | 37 | |
14957cd0 A |
38 | // Construct a string with UTF-16 data, from a null-terminated source. |
39 | UString(const UChar*); | |
ba379fdc | 40 | |
14957cd0 A |
41 | // Construct a string with latin1 data. |
42 | UString(const char* characters, unsigned length); | |
9dae56ea | 43 | |
14957cd0 A |
44 | // Construct a string with latin1 data, from a null-terminated source. |
45 | UString(const char* characters); | |
9dae56ea | 46 | |
14957cd0 A |
47 | // Construct a string referencing an existing StringImpl. |
48 | UString(StringImpl* impl) : m_impl(impl) { } | |
49 | UString(PassRefPtr<StringImpl> impl) : m_impl(impl) { } | |
50 | UString(RefPtr<StringImpl> impl) : m_impl(impl) { } | |
9dae56ea | 51 | |
14957cd0 A |
52 | // Inline the destructor. |
53 | ALWAYS_INLINE ~UString() { } | |
9dae56ea | 54 | |
14957cd0 | 55 | void swap(UString& o) { m_impl.swap(o.m_impl); } |
9dae56ea | 56 | |
14957cd0 A |
57 | template<size_t inlineCapacity> |
58 | static UString adopt(Vector<UChar, inlineCapacity>& vector) { return StringImpl::adopt(vector); } | |
9dae56ea | 59 | |
14957cd0 A |
60 | bool isNull() const { return !m_impl; } |
61 | bool isEmpty() const { return !m_impl || !m_impl->length(); } | |
9dae56ea | 62 | |
14957cd0 | 63 | StringImpl* impl() const { return m_impl.get(); } |
9dae56ea | 64 | |
14957cd0 | 65 | unsigned length() const |
f9bf01c6 | 66 | { |
14957cd0 | 67 | if (!m_impl) |
4e4e5a6f | 68 | return 0; |
14957cd0 | 69 | return m_impl->length(); |
9dae56ea A |
70 | } |
71 | ||
14957cd0 | 72 | const UChar* characters() const |
9dae56ea | 73 | { |
14957cd0 | 74 | if (!m_impl) |
4e4e5a6f | 75 | return 0; |
14957cd0 | 76 | return m_impl->characters(); |
9dae56ea A |
77 | } |
78 | ||
14957cd0 A |
79 | CString ascii() const; |
80 | CString latin1() const; | |
81 | CString utf8(bool strict = false) const; | |
82 | ||
83 | UChar operator[](unsigned index) const | |
9dae56ea | 84 | { |
14957cd0 | 85 | if (!m_impl || index >= m_impl->length()) |
4e4e5a6f | 86 | return 0; |
14957cd0 A |
87 | return m_impl->characters()[index]; |
88 | } | |
f9bf01c6 | 89 | |
14957cd0 A |
90 | static UString number(int); |
91 | static UString number(unsigned); | |
92 | static UString number(long); | |
93 | static UString number(long long); | |
94 | static UString number(double); | |
95 | ||
96 | // Find a single character or string, also with match function & latin1 forms. | |
97 | size_t find(UChar c, unsigned start = 0) const | |
98 | { return m_impl ? m_impl->find(c, start) : notFound; } | |
99 | size_t find(const UString& str, unsigned start = 0) const | |
100 | { return m_impl ? m_impl->find(str.impl(), start) : notFound; } | |
101 | size_t find(const char* str, unsigned start = 0) const | |
102 | { return m_impl ? m_impl->find(str, start) : notFound; } | |
103 | ||
104 | // Find the last instance of a single character or string. | |
105 | size_t reverseFind(UChar c, unsigned start = UINT_MAX) const | |
106 | { return m_impl ? m_impl->reverseFind(c, start) : notFound; } | |
107 | size_t reverseFind(const UString& str, unsigned start = UINT_MAX) const | |
108 | { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; } | |
109 | ||
110 | UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const; | |
111 | ||
112 | private: | |
113 | RefPtr<StringImpl> m_impl; | |
114 | }; | |
115 | ||
116 | ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2) | |
117 | { | |
118 | StringImpl* rep1 = s1.impl(); | |
119 | StringImpl* rep2 = s2.impl(); | |
120 | unsigned size1 = 0; | |
121 | unsigned size2 = 0; | |
122 | ||
123 | if (rep1 == rep2) // If they're the same rep, they're equal. | |
124 | return true; | |
125 | ||
126 | if (rep1) | |
127 | size1 = rep1->length(); | |
128 | ||
129 | if (rep2) | |
130 | size2 = rep2->length(); | |
131 | ||
132 | if (size1 != size2) // If the lengths are not the same, we're done. | |
133 | return false; | |
134 | ||
135 | if (!size1) | |
136 | return true; | |
137 | ||
138 | // At this point we know | |
139 | // (a) that the strings are the same length and | |
140 | // (b) that they are greater than zero length. | |
141 | const UChar* d1 = rep1->characters(); | |
142 | const UChar* d2 = rep2->characters(); | |
143 | ||
144 | if (d1 == d2) // Check to see if the data pointers are the same. | |
145 | return true; | |
146 | ||
147 | // Do quick checks for sizes 1 and 2. | |
148 | switch (size1) { | |
149 | case 1: | |
150 | return d1[0] == d2[0]; | |
151 | case 2: | |
152 | return (d1[0] == d2[0]) & (d1[1] == d2[1]); | |
153 | default: | |
154 | return memcmp(d1, d2, size1 * sizeof(UChar)) == 0; | |
9dae56ea | 155 | } |
14957cd0 | 156 | } |
9dae56ea | 157 | |
f9bf01c6 | 158 | |
14957cd0 A |
159 | inline bool operator!=(const UString& s1, const UString& s2) |
160 | { | |
161 | return !JSC::operator==(s1, s2); | |
162 | } | |
9dae56ea | 163 | |
14957cd0 A |
164 | bool operator<(const UString& s1, const UString& s2); |
165 | bool operator>(const UString& s1, const UString& s2); | |
f9bf01c6 | 166 | |
14957cd0 | 167 | bool operator==(const UString& s1, const char* s2); |
9dae56ea | 168 | |
14957cd0 A |
169 | inline bool operator!=(const UString& s1, const char* s2) |
170 | { | |
171 | return !JSC::operator==(s1, s2); | |
172 | } | |
f9bf01c6 | 173 | |
14957cd0 A |
174 | inline bool operator==(const char *s1, const UString& s2) |
175 | { | |
176 | return operator==(s2, s1); | |
177 | } | |
9dae56ea | 178 | |
14957cd0 A |
179 | inline bool operator!=(const char *s1, const UString& s2) |
180 | { | |
181 | return !JSC::operator==(s1, s2); | |
182 | } | |
f9bf01c6 | 183 | |
14957cd0 A |
184 | inline int codePointCompare(const UString& s1, const UString& s2) |
185 | { | |
186 | return codePointCompare(s1.impl(), s2.impl()); | |
187 | } | |
9dae56ea | 188 | |
14957cd0 A |
189 | struct UStringHash { |
190 | static unsigned hash(StringImpl* key) { return key->hash(); } | |
191 | static bool equal(const StringImpl* a, const StringImpl* b) | |
4e4e5a6f | 192 | { |
14957cd0 A |
193 | if (a == b) |
194 | return true; | |
195 | if (!a || !b) | |
196 | return false; | |
4e4e5a6f | 197 | |
14957cd0 A |
198 | unsigned aLength = a->length(); |
199 | unsigned bLength = b->length(); | |
200 | if (aLength != bLength) | |
201 | return false; | |
4e4e5a6f | 202 | |
14957cd0 A |
203 | // FIXME: perhaps we should have a more abstract macro that indicates when |
204 | // going 4 bytes at a time is unsafe | |
205 | #if CPU(ARM) || CPU(SH4) || CPU(MIPS) | |
206 | const UChar* aChars = a->characters(); | |
207 | const UChar* bChars = b->characters(); | |
208 | for (unsigned i = 0; i != aLength; ++i) { | |
209 | if (*aChars++ != *bChars++) | |
210 | return false; | |
211 | } | |
212 | return true; | |
213 | #else | |
214 | /* Do it 4-bytes-at-a-time on architectures where it's safe */ | |
215 | const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters()); | |
216 | const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters()); | |
217 | ||
218 | unsigned halfLength = aLength >> 1; | |
219 | for (unsigned i = 0; i != halfLength; ++i) | |
220 | if (*aChars++ != *bChars++) | |
221 | return false; | |
222 | ||
223 | if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars)) | |
224 | return false; | |
4e4e5a6f | 225 | |
14957cd0 A |
226 | return true; |
227 | #endif | |
4e4e5a6f A |
228 | } |
229 | ||
14957cd0 A |
230 | static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); } |
231 | static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) | |
4e4e5a6f | 232 | { |
14957cd0 | 233 | return equal(a.get(), b.get()); |
4e4e5a6f A |
234 | } |
235 | ||
14957cd0 A |
236 | static unsigned hash(const UString& key) { return key.impl()->hash(); } |
237 | static bool equal(const UString& a, const UString& b) | |
4e4e5a6f | 238 | { |
14957cd0 | 239 | return equal(a.impl(), b.impl()); |
4e4e5a6f A |
240 | } |
241 | ||
14957cd0 A |
242 | static const bool safeToCompareToEmptyOrDeleted = false; |
243 | }; | |
4e4e5a6f | 244 | |
9dae56ea A |
245 | } // namespace JSC |
246 | ||
247 | namespace WTF { | |
248 | ||
14957cd0 A |
249 | // UStringHash is the default hash for UString |
250 | template<typename T> struct DefaultHash; | |
251 | template<> struct DefaultHash<JSC::UString> { | |
252 | typedef JSC::UStringHash Hash; | |
253 | }; | |
9dae56ea | 254 | |
14957cd0 | 255 | template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits { }; |
9dae56ea | 256 | |
9dae56ea A |
257 | } // namespace WTF |
258 | ||
259 | #endif | |
14957cd0 | 260 |