2 * (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
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.
22 #ifndef PlatformString_h
23 #define PlatformString_h
25 // This file would be called String.h, but that conflicts with <string.h>
26 // on systems without case-sensitive file systems.
28 #include "StringImpl.h"
30 #include <wtf/PassRefPtr.h>
33 #include <runtime/Identifier.h>
35 // runtime/Identifier.h includes HashMap.h and HashSet.h. We explicitly include
36 // them in the case of non-JSC builds to keep things consistent.
37 #include <wtf/HashMap.h>
38 #include <wtf/HashSet.h>
41 #if PLATFORM(CF) || (PLATFORM(QT) && PLATFORM(DARWIN))
42 typedef const struct __CFString
* CFStringRef
;
63 String() { } // gives null string, distinguishable from an empty string
64 String(const UChar
*, unsigned length
);
65 String(const UChar
*); // Specifically for null terminated UTF-16
67 String(const JSC::Identifier
&);
68 String(const JSC::UString
&);
71 String(const char*, unsigned length
);
72 String(StringImpl
* i
) : m_impl(i
) { }
73 String(PassRefPtr
<StringImpl
> i
) : m_impl(i
) { }
74 String(RefPtr
<StringImpl
> i
) : m_impl(i
) { }
76 void swap(String
& o
) { m_impl
.swap(o
.m_impl
); }
78 // Hash table deleted values, which are only constructed and never copied or destroyed.
79 String(WTF::HashTableDeletedValueType
) : m_impl(WTF::HashTableDeletedValue
) { }
80 bool isHashTableDeletedValue() const { return m_impl
.isHashTableDeletedValue(); }
82 static String
adopt(StringBuffer
& buffer
) { return StringImpl::adopt(buffer
); }
83 static String
adopt(Vector
<UChar
>& vector
) { return StringImpl::adopt(vector
); }
86 operator JSC::UString() const;
89 unsigned length() const;
90 const UChar
* characters() const;
91 const UChar
* charactersWithNullTermination();
93 UChar
operator[](unsigned i
) const; // if i >= length(), returns 0
94 UChar32
characterStartingAt(unsigned) const; // Ditto.
96 bool contains(UChar c
) const { return find(c
) != -1; }
97 bool contains(const char* str
, bool caseSensitive
= true) const { return find(str
, 0, caseSensitive
) != -1; }
98 bool contains(const String
& str
, bool caseSensitive
= true) const { return find(str
, 0, caseSensitive
) != -1; }
100 int find(UChar c
, int start
= 0) const
101 { return m_impl
? m_impl
->find(c
, start
) : -1; }
102 int find(CharacterMatchFunctionPtr matchFunction
, int start
= 0) const
103 { return m_impl
? m_impl
->find(matchFunction
, start
) : -1; }
104 int find(const char* str
, int start
= 0, bool caseSensitive
= true) const
105 { return m_impl
? m_impl
->find(str
, start
, caseSensitive
) : -1; }
106 int find(const String
& str
, int start
= 0, bool caseSensitive
= true) const
107 { return m_impl
? m_impl
->find(str
.impl(), start
, caseSensitive
) : -1; }
109 int reverseFind(UChar c
, int start
= -1) const
110 { return m_impl
? m_impl
->reverseFind(c
, start
) : -1; }
111 int reverseFind(const String
& str
, int start
= -1, bool caseSensitive
= true) const
112 { return m_impl
? m_impl
->reverseFind(str
.impl(), start
, caseSensitive
) : -1; }
114 bool startsWith(const String
& s
, bool caseSensitive
= true) const
115 { return m_impl
? m_impl
->startsWith(s
.impl(), caseSensitive
) : s
.isEmpty(); }
116 bool endsWith(const String
& s
, bool caseSensitive
= true) const
117 { return m_impl
? m_impl
->endsWith(s
.impl(), caseSensitive
) : s
.isEmpty(); }
119 void append(const String
&);
122 void append(const UChar
*, unsigned length
);
123 void insert(const String
&, unsigned pos
);
124 void insert(const UChar
*, unsigned length
, unsigned pos
);
126 String
& replace(UChar a
, UChar b
) { if (m_impl
) m_impl
= m_impl
->replace(a
, b
); return *this; }
127 String
& replace(UChar a
, const String
& b
) { if (m_impl
) m_impl
= m_impl
->replace(a
, b
.impl()); return *this; }
128 String
& replace(const String
& a
, const String
& b
) { if (m_impl
) m_impl
= m_impl
->replace(a
.impl(), b
.impl()); return *this; }
129 String
& replace(unsigned index
, unsigned len
, const String
& b
) { if (m_impl
) m_impl
= m_impl
->replace(index
, len
, b
.impl()); return *this; }
131 void truncate(unsigned len
);
132 void remove(unsigned pos
, int len
= 1);
134 String
substring(unsigned pos
, unsigned len
= UINT_MAX
) const;
135 String
left(unsigned len
) const { return substring(0, len
); }
136 String
right(unsigned len
) const { return substring(length() - len
, len
); }
138 // Returns a lowercase/uppercase version of the string
139 String
lower() const;
140 String
upper() const;
142 String
stripWhiteSpace() const;
143 String
simplifyWhiteSpace() const;
145 String
removeCharacters(CharacterMatchFunctionPtr
) const;
147 // Return the string with case folded for case insensitive comparison.
148 String
foldCase() const;
150 static String
number(short);
151 static String
number(unsigned short);
152 static String
number(int);
153 static String
number(unsigned);
154 static String
number(long);
155 static String
number(unsigned long);
156 static String
number(long long);
157 static String
number(unsigned long long);
158 static String
number(double);
160 static String
format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
162 void split(const String
& separator
, Vector
<String
>& result
) const;
163 void split(const String
& separator
, bool allowEmptyEntries
, Vector
<String
>& result
) const;
164 void split(UChar separator
, Vector
<String
>& result
) const;
165 void split(UChar separator
, bool allowEmptyEntries
, Vector
<String
>& result
) const;
167 int toIntStrict(bool* ok
= 0, int base
= 10) const;
168 unsigned toUIntStrict(bool* ok
= 0, int base
= 10) const;
169 int64_t toInt64Strict(bool* ok
= 0, int base
= 10) const;
170 uint64_t toUInt64Strict(bool* ok
= 0, int base
= 10) const;
172 int toInt(bool* ok
= 0) const;
173 unsigned toUInt(bool* ok
= 0) const;
174 int64_t toInt64(bool* ok
= 0) const;
175 uint64_t toUInt64(bool* ok
= 0) const;
176 double toDouble(bool* ok
= 0) const;
177 float toFloat(bool* ok
= 0) const;
179 bool percentage(int& percentage
) const;
181 // Makes a deep copy. Helpful only if you need to use a String on another thread.
182 // Since the underlying StringImpl objects are immutable, there's no other reason
183 // to ever prefer copy() over plain old assignment.
186 // Makes a deep copy like copy() but only for a substring.
187 // (This ensures that you always get something suitable for a thread while subtring
188 // may not. For example, in the empty string case, StringImpl::substring returns
189 // empty() which is not safe for another thread.)
190 String
substringCopy(unsigned pos
, unsigned len
= UINT_MAX
) const;
192 bool isNull() const { return !m_impl
; }
193 bool isEmpty() const;
195 StringImpl
* impl() const { return m_impl
.get(); }
197 #if PLATFORM(CF) || (PLATFORM(QT) && PLATFORM(DARWIN))
199 CFStringRef
createCFString() const;
205 // This conversion maps NULL to "", which loses the meaning of NULL, but we
206 // need this mapping because AppKit crashes when passed nil NSStrings.
207 operator NSString
*() const { if (!m_impl
) return @
""; return *m_impl
; }
211 String(const QString
&);
212 String(const QStringRef
&);
213 operator QString() const;
217 String(const wxString
&);
218 operator wxString() const;
222 Vector
<char> ascii() const;
225 CString
latin1() const;
226 CString
utf8() const;
228 static String
fromUTF8(const char*, size_t);
229 static String
fromUTF8(const char*);
231 // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3.
232 WTF::Unicode::Direction
defaultWritingDirection() const { return m_impl
? m_impl
->defaultWritingDirection() : WTF::Unicode::LeftToRight
; }
235 RefPtr
<StringImpl
> m_impl
;
238 String
operator+(const String
&, const String
&);
239 String
operator+(const String
&, const char*);
240 String
operator+(const char*, const String
&);
242 inline String
& operator+=(String
& a
, const String
& b
) { a
.append(b
); return a
; }
244 inline bool operator==(const String
& a
, const String
& b
) { return equal(a
.impl(), b
.impl()); }
245 inline bool operator==(const String
& a
, const char* b
) { return equal(a
.impl(), b
); }
246 inline bool operator==(const char* a
, const String
& b
) { return equal(a
, b
.impl()); }
248 inline bool operator!=(const String
& a
, const String
& b
) { return !equal(a
.impl(), b
.impl()); }
249 inline bool operator!=(const String
& a
, const char* b
) { return !equal(a
.impl(), b
); }
250 inline bool operator!=(const char* a
, const String
& b
) { return !equal(a
, b
.impl()); }
252 inline bool equalIgnoringCase(const String
& a
, const String
& b
) { return equalIgnoringCase(a
.impl(), b
.impl()); }
253 inline bool equalIgnoringCase(const String
& a
, const char* b
) { return equalIgnoringCase(a
.impl(), b
); }
254 inline bool equalIgnoringCase(const char* a
, const String
& b
) { return equalIgnoringCase(a
, b
.impl()); }
256 inline bool operator!(const String
& str
) { return str
.isNull(); }
258 inline void swap(String
& a
, String
& b
) { a
.swap(b
); }
262 bool charactersAreAllASCII(const UChar
*, size_t);
264 int charactersToIntStrict(const UChar
*, size_t, bool* ok
= 0, int base
= 10);
265 unsigned charactersToUIntStrict(const UChar
*, size_t, bool* ok
= 0, int base
= 10);
266 int64_t charactersToInt64Strict(const UChar
*, size_t, bool* ok
= 0, int base
= 10);
267 uint64_t charactersToUInt64Strict(const UChar
*, size_t, bool* ok
= 0, int base
= 10);
269 int charactersToInt(const UChar
*, size_t, bool* ok
= 0); // ignores trailing garbage
270 unsigned charactersToUInt(const UChar
*, size_t, bool* ok
= 0); // ignores trailing garbage
271 int64_t charactersToInt64(const UChar
*, size_t, bool* ok
= 0); // ignores trailing garbage
272 uint64_t charactersToUInt64(const UChar
*, size_t, bool* ok
= 0); // ignores trailing garbage
274 double charactersToDouble(const UChar
*, size_t, bool* ok
= 0);
275 float charactersToFloat(const UChar
*, size_t, bool* ok
= 0);
277 int find(const UChar
*, size_t, UChar
, int startPosition
= 0);
278 int reverseFind(const UChar
*, size_t, UChar
, int startPosition
= -1);
281 // This is for situations in WebKit where the long standing behavior has been
282 // "nil if empty", so we try to maintain longstanding behavior for the sake of
283 // entrenched clients
284 inline NSString
* nsStringNilIfEmpty(const String
& str
) { return str
.isEmpty() ? nil
: (NSString
*)str
; }
287 inline bool charactersAreAllASCII(const UChar
* characters
, size_t length
)
290 for (size_t i
= 0; i
< length
; ++i
)
291 ored
|= characters
[i
];
292 return !(ored
& 0xFF80);
295 inline int find(const UChar
* characters
, size_t length
, UChar character
, int startPosition
)
297 if (startPosition
>= static_cast<int>(length
))
299 for (size_t i
= startPosition
; i
< length
; ++i
) {
300 if (characters
[i
] == character
)
301 return static_cast<int>(i
);
306 inline int find(const UChar
* characters
, size_t length
, CharacterMatchFunctionPtr matchFunction
, int startPosition
)
308 if (startPosition
>= static_cast<int>(length
))
310 for (size_t i
= startPosition
; i
< length
; ++i
) {
311 if (matchFunction(characters
[i
]))
312 return static_cast<int>(i
);
317 inline int reverseFind(const UChar
* characters
, size_t length
, UChar character
, int startPosition
)
319 if (startPosition
>= static_cast<int>(length
) || !length
)
321 if (startPosition
< 0)
322 startPosition
+= static_cast<int>(length
);
324 if (characters
[startPosition
] == character
)
325 return startPosition
;
330 ASSERT_NOT_REACHED();
334 inline void append(Vector
<UChar
>& vector
, const String
& string
)
336 vector
.append(string
.characters(), string
.length());
339 inline void appendNumber(Vector
<UChar
>& vector
, unsigned char number
)
341 int numberLength
= number
> 99 ? 3 : (number
> 9 ? 2 : 1);
342 size_t vectorSize
= vector
.size();
343 vector
.grow(vectorSize
+ numberLength
);
345 switch (numberLength
) {
347 vector
[vectorSize
+ 2] = number
% 10 + '0';
351 vector
[vectorSize
+ 1] = number
% 10 + '0';
355 vector
[vectorSize
] = number
% 10 + '0';
361 PassRefPtr
<SharedBuffer
> utf8Buffer(const String
&);
363 } // namespace WebCore
367 // StringHash is the default hash for String
368 template<typename T
> struct DefaultHash
;
369 template<> struct DefaultHash
<WebCore::String
> {
370 typedef WebCore::StringHash Hash
;