source: webkit/trunk/JavaScriptCore/kjs/ustring.h@ 35906

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

Reviewed by Geoff Garen.

Add consistency checks to UString to document and enforce its design.

  • kjs/ustring.cpp: (KJS::UString::Rep::create): (KJS::UString::Rep::destroy): (KJS::UString::Rep::checkConsistency): (KJS::UString::expandCapacity): (KJS::UString::expandPreCapacity): (KJS::UString::UString): (KJS::UString::spliceSubstringsWithSeparators): (KJS::UString::append):
  • kjs/ustring.h: (KJS::UString::Rep::checkConsistency):
  • Property svn:eol-style set to native
File size: 12.1 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
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#ifndef _KJS_USTRING_H_
23#define _KJS_USTRING_H_
24
25#include "collector.h"
26#include <stdint.h>
27#include <string.h>
28#include <wtf/Assertions.h>
29#include <wtf/FastMalloc.h>
30#include <wtf/PassRefPtr.h>
31#include <wtf/RefPtr.h>
32#include <wtf/Vector.h>
33#include <wtf/unicode/Unicode.h>
34
35namespace KJS {
36
37 using WTF::PlacementNewAdoptType;
38 using WTF::PlacementNewAdopt;
39
40 class IdentifierTable;
41
42 class CString {
43 public:
44 CString()
45 : m_length(0)
46 , m_data(0)
47 {
48 }
49
50 CString(const char*);
51 CString(const char*, size_t);
52 CString(const CString&);
53
54 ~CString();
55
56 static CString adopt(char*, size_t); // buffer should be allocated with new[].
57
58 CString& append(const CString&);
59 CString& operator=(const char* c);
60 CString& operator=(const CString&);
61 CString& operator+=(const CString& c) { return append(c); }
62
63 size_t size() const { return m_length; }
64 const char* c_str() const { return m_data; }
65
66 private:
67 size_t m_length;
68 char* m_data;
69 };
70
71 typedef Vector<char, 32> CStringBuffer;
72
73 class UString {
74 friend bool operator==(const UString&, const UString&);
75
76 public:
77 struct Rep {
78 static PassRefPtr<Rep> create(UChar*, int);
79 static PassRefPtr<Rep> createCopying(const UChar*, int);
80 static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length);
81
82 // Constructs a string from a UTF-8 string, using strict conversion (see comments in UTF8.h).
83 // Returns UString::Rep::null for null input or conversion failure.
84 static PassRefPtr<Rep> createFromUTF8(const char*);
85
86 void destroy();
87
88 bool baseIsSelf() const { return baseString == this; }
89 UChar* data() const { return baseString->buf + baseString->preCapacity + offset; }
90 int size() const { return len; }
91
92 unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; }
93 unsigned computedHash() const { ASSERT(_hash); return _hash; } // fast path for Identifiers
94
95 static unsigned computeHash(const UChar*, int length);
96 static unsigned computeHash(const char*, int length);
97 static unsigned computeHash(const char* s) { return computeHash(s, strlen(s)); }
98
99 IdentifierTable* identifierTable() const { return reinterpret_cast<IdentifierTable*>(m_identifierTable & ~static_cast<uintptr_t>(1)); }
100 void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTable = reinterpret_cast<intptr_t>(table); }
101
102 bool isStatic() const { return m_identifierTable & 1; }
103 void setStatic(bool v) { ASSERT(!identifierTable()); m_identifierTable = v; }
104
105 Rep* ref() { ++rc; return this; }
106 ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); }
107
108 void checkConsistency() const;
109
110 // unshared data
111 int offset;
112 int len;
113 int rc; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted.
114 mutable unsigned _hash;
115 intptr_t m_identifierTable; // A pointer to identifier table. The lowest bit is used to indicate whether the string is static (null or empty).
116 UString::Rep* baseString;
117 size_t reportedCost;
118
119 // potentially shared data. 0 if backed up by a base string.
120 UChar* buf;
121 int usedCapacity;
122 int capacity;
123 int usedPreCapacity;
124 int preCapacity;
125
126 static Rep null;
127 static Rep empty;
128 };
129
130 public:
131 UString();
132 UString(const char*);
133 UString(const UChar*, int length);
134 UString(UChar*, int length, bool copy);
135
136 UString(const UString& s)
137 : m_rep(s.m_rep)
138 {
139 }
140
141 UString(const Vector<UChar>& buffer);
142
143 // Concatenation constructor. Makes operator+ more efficient.
144 UString(const UString&, const UString&);
145
146 ~UString()
147 {
148 }
149
150 // Special constructor for cases where we overwrite an object in place.
151 UString(PlacementNewAdoptType)
152 : m_rep(PlacementNewAdopt)
153 {
154 }
155
156 static UString from(int);
157 static UString from(unsigned int);
158 static UString from(long);
159 static UString from(double);
160
161 struct Range {
162 public:
163 Range(int pos, int len)
164 : position(pos)
165 , length(len)
166 {
167 }
168
169 Range()
170 {
171 }
172
173 int position;
174 int length;
175 };
176
177 UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const;
178
179 UString& append(const UString&);
180 UString& append(const char*);
181 UString& append(UChar);
182 UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); }
183 UString& append(const UChar*, int size);
184
185 bool getCString(CStringBuffer&) const;
186
187 // NOTE: This method should only be used for *debugging* purposes as it
188 // is neither Unicode safe nor free from side effects nor thread-safe.
189 char* ascii() const;
190
191 /**
192 * Convert the string to UTF-8, assuming it is UTF-16 encoded.
193 * In non-strict mode, this function is tolerant of badly formed UTF-16, it
194 * can create UTF-8 strings that are invalid because they have characters in
195 * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is
196 * guaranteed to be otherwise valid.
197 * In strict mode, error is returned as null CString.
198 */
199 CString UTF8String(bool strict = false) const;
200
201 UString& operator=(const char*c);
202
203 UString& operator+=(const UString& s) { return append(s); }
204 UString& operator+=(const char* s) { return append(s); }
205
206 const UChar* data() const { return m_rep->data(); }
207
208 bool isNull() const { return (m_rep == &Rep::null); }
209 bool isEmpty() const { return (!m_rep->len); }
210
211 bool is8Bit() const;
212
213 int size() const { return m_rep->size(); }
214
215 UChar operator[](int pos) const;
216
217 double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const;
218 double toDouble(bool tolerateTrailingJunk) const;
219 double toDouble() const;
220
221 uint32_t toUInt32(bool* ok = 0) const;
222 uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const;
223 uint32_t toStrictUInt32(bool* ok = 0) const;
224
225 unsigned toArrayIndex(bool* ok = 0) const;
226
227 int find(const UString& f, int pos = 0) const;
228 int find(UChar, int pos = 0) const;
229 int rfind(const UString& f, int pos) const;
230 int rfind(UChar, int pos) const;
231
232 UString substr(int pos = 0, int len = -1) const;
233
234 static const UString& null();
235
236 Rep* rep() const { return m_rep.get(); }
237
238 UString(PassRefPtr<Rep> r)
239 : m_rep(r)
240 {
241 ASSERT(m_rep);
242 }
243
244 size_t cost() const;
245
246 private:
247 size_t expandedSize(size_t size, size_t otherSize) const;
248 int usedCapacity() const;
249 int usedPreCapacity() const;
250 void expandCapacity(int requiredLength);
251 void expandPreCapacity(int requiredPreCap);
252
253 RefPtr<Rep> m_rep;
254 };
255
256 bool operator==(const UString& s1, const UString& s2);
257
258 inline bool operator!=(const UString& s1, const UString& s2)
259 {
260 return !KJS::operator==(s1, s2);
261 }
262
263 bool operator<(const UString& s1, const UString& s2);
264 bool operator>(const UString& s1, const UString& s2);
265
266 bool operator==(const UString& s1, const char* s2);
267
268 inline bool operator!=(const UString& s1, const char* s2)
269 {
270 return !KJS::operator==(s1, s2);
271 }
272
273 inline bool operator==(const char *s1, const UString& s2)
274 {
275 return operator==(s2, s1);
276 }
277
278 inline bool operator!=(const char *s1, const UString& s2)
279 {
280 return !KJS::operator==(s1, s2);
281 }
282
283 bool operator==(const CString& s1, const CString& s2);
284
285 inline UString operator+(const UString& s1, const UString& s2)
286 {
287 return UString(s1, s2);
288 }
289
290 int compare(const UString&, const UString&);
291
292 bool equal(const UString::Rep*, const UString::Rep*);
293
294#ifdef NDEBUG
295 inline void UString::Rep::checkConsistency() const
296 {
297 }
298#endif
299
300 inline UString::UString()
301 : m_rep(&Rep::null)
302 {
303 }
304
305 // Rule from ECMA 15.2 about what an array index is.
306 // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
307 inline unsigned UString::toArrayIndex(bool* ok) const
308 {
309 unsigned i = toStrictUInt32(ok);
310 if (ok && i >= 0xFFFFFFFFU)
311 *ok = false;
312 return i;
313 }
314
315 // We'd rather not do shared substring append for small strings, since
316 // this runs too much risk of a tiny initial string holding down a
317 // huge buffer.
318 // FIXME: this should be size_t but that would cause warnings until we
319 // fix UString sizes to be size_t instead of int
320 static const int minShareSize = Heap::minExtraCostSize / sizeof(UChar);
321
322 inline size_t UString::cost() const
323 {
324 size_t capacity = (m_rep->baseString->capacity + m_rep->baseString->preCapacity) * sizeof(UChar);
325 size_t reportedCost = m_rep->baseString->reportedCost;
326 ASSERT(capacity >= reportedCost);
327
328 size_t capacityDelta = capacity - reportedCost;
329
330 if (capacityDelta < static_cast<size_t>(minShareSize))
331 return 0;
332
333 m_rep->baseString->reportedCost = capacity;
334
335 return capacityDelta;
336 }
337
338} // namespace KJS
339
340namespace WTF {
341
342 template<typename T> struct DefaultHash;
343 template<typename T> struct StrHash;
344
345 template<> struct StrHash<KJS::UString::Rep*> {
346 static unsigned hash(const KJS::UString::Rep* key) { return key->hash(); }
347 static bool equal(const KJS::UString::Rep* a, const KJS::UString::Rep* b) { return KJS::equal(a, b); }
348 static const bool safeToCompareToEmptyOrDeleted = false;
349 };
350
351 template<> struct StrHash<RefPtr<KJS::UString::Rep> > : public StrHash<KJS::UString::Rep*> {
352 using StrHash<KJS::UString::Rep*>::hash;
353 static unsigned hash(const RefPtr<KJS::UString::Rep>& key) { return key->hash(); }
354 using StrHash<KJS::UString::Rep*>::equal;
355 static bool equal(const RefPtr<KJS::UString::Rep>& a, const RefPtr<KJS::UString::Rep>& b) { return KJS::equal(a.get(), b.get()); }
356 static bool equal(const KJS::UString::Rep* a, const RefPtr<KJS::UString::Rep>& b) { return KJS::equal(a, b.get()); }
357 static bool equal(const RefPtr<KJS::UString::Rep>& a, const KJS::UString::Rep* b) { return KJS::equal(a.get(), b); }
358
359 static const bool safeToCompareToEmptyOrDeleted = false;
360 };
361
362 template<> struct DefaultHash<KJS::UString::Rep*> {
363 typedef StrHash<KJS::UString::Rep*> Hash;
364 };
365
366 template<> struct DefaultHash<RefPtr<KJS::UString::Rep> > {
367 typedef StrHash<RefPtr<KJS::UString::Rep> > Hash;
368 };
369} // namespace WTF
370
371#endif
Note: See TracBrowser for help on using the repository browser.