]>
Commit | Line | Data |
---|---|---|
4e4e5a6f A |
1 | /* |
2 | * Copyright (C) 2009 Apple Inc. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #ifndef JSStringBuilder_h | |
27 | #define JSStringBuilder_h | |
28 | ||
29 | #include "ExceptionHelpers.h" | |
30 | #include "JSString.h" | |
6fe7ccc8 | 31 | #include <wtf/Vector.h> |
4e4e5a6f A |
32 | |
33 | namespace JSC { | |
34 | ||
35 | class JSStringBuilder { | |
36 | public: | |
37 | JSStringBuilder() | |
38 | : m_okay(true) | |
6fe7ccc8 | 39 | , m_is8Bit(true) |
4e4e5a6f A |
40 | { |
41 | } | |
42 | ||
43 | void append(const UChar u) | |
44 | { | |
6fe7ccc8 A |
45 | if (m_is8Bit) { |
46 | if (u < 0xff) { | |
47 | LChar c = u; | |
48 | m_okay &= buffer8.tryAppend(&c, 1); | |
49 | return; | |
50 | } | |
51 | upConvert(); | |
52 | } | |
53 | m_okay &= buffer16.tryAppend(&u, 1); | |
4e4e5a6f A |
54 | } |
55 | ||
56 | void append(const char* str) | |
57 | { | |
58 | append(str, strlen(str)); | |
59 | } | |
60 | ||
61 | void append(const char* str, size_t len) | |
62 | { | |
6fe7ccc8 A |
63 | if (m_is8Bit) { |
64 | m_okay &= buffer8.tryAppend(reinterpret_cast<const LChar*>(str), len); | |
65 | return; | |
66 | } | |
67 | m_okay &= buffer8.tryReserveCapacity(buffer16.size() + len); | |
4e4e5a6f A |
68 | for (size_t i = 0; i < len; i++) { |
69 | UChar u = static_cast<unsigned char>(str[i]); | |
6fe7ccc8 | 70 | m_okay &= buffer16.tryAppend(&u, 1); |
4e4e5a6f A |
71 | } |
72 | } | |
73 | ||
6fe7ccc8 A |
74 | void append(const LChar* str, size_t len) |
75 | { | |
76 | if (m_is8Bit) { | |
77 | m_okay &= buffer8.tryAppend(str, len); | |
78 | return; | |
79 | } | |
80 | m_okay &= buffer8.tryReserveCapacity(buffer16.size() + len); | |
81 | for (size_t i = 0; i < len; i++) { | |
82 | UChar u = str[i]; | |
83 | m_okay &= buffer16.tryAppend(&u, 1); | |
84 | } | |
85 | } | |
86 | ||
4e4e5a6f A |
87 | void append(const UChar* str, size_t len) |
88 | { | |
6fe7ccc8 A |
89 | if (m_is8Bit) |
90 | upConvert(); // FIXME: We could check character by character its size. | |
91 | m_okay &= buffer16.tryAppend(str, len); | |
4e4e5a6f A |
92 | } |
93 | ||
93a37866 | 94 | void append(const String& str) |
4e4e5a6f | 95 | { |
6fe7ccc8 A |
96 | unsigned length = str.length(); |
97 | ||
98 | if (!length) | |
99 | return; | |
100 | ||
101 | if (m_is8Bit) { | |
102 | if (str.is8Bit()) { | |
103 | m_okay &= buffer8.tryAppend(str.characters8(), length); | |
104 | return; | |
105 | } | |
106 | upConvert(); | |
107 | } | |
108 | m_okay &= buffer16.tryAppend(str.characters(), length); | |
109 | } | |
110 | ||
111 | void upConvert() | |
112 | { | |
113 | ASSERT(m_is8Bit); | |
114 | size_t len = buffer8.size(); | |
115 | ||
116 | for (size_t i = 0; i < len; i++) | |
117 | buffer16.append(buffer8[i]); | |
118 | ||
119 | buffer8.clear(); | |
120 | m_is8Bit = false; | |
4e4e5a6f A |
121 | } |
122 | ||
123 | JSValue build(ExecState* exec) | |
124 | { | |
125 | if (!m_okay) | |
126 | return throwOutOfMemoryError(exec); | |
6fe7ccc8 A |
127 | if (m_is8Bit) { |
128 | buffer8.shrinkToFit(); | |
129 | if (!buffer8.data()) | |
130 | return throwOutOfMemoryError(exec); | |
93a37866 | 131 | return jsString(exec, String::adopt(buffer8)); |
6fe7ccc8 A |
132 | } |
133 | buffer16.shrinkToFit(); | |
134 | if (!buffer16.data()) | |
4e4e5a6f | 135 | return throwOutOfMemoryError(exec); |
93a37866 | 136 | return jsString(exec, String::adopt(buffer16)); |
4e4e5a6f A |
137 | } |
138 | ||
139 | protected: | |
93a37866 A |
140 | Vector<LChar, 64, UnsafeVectorOverflow> buffer8; |
141 | Vector<UChar, 64, UnsafeVectorOverflow> buffer16; | |
4e4e5a6f | 142 | bool m_okay; |
6fe7ccc8 | 143 | bool m_is8Bit; |
4e4e5a6f A |
144 | }; |
145 | ||
146 | template<typename StringType1, typename StringType2> | |
147 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2) | |
148 | { | |
14957cd0 | 149 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2); |
4e4e5a6f A |
150 | if (!result) |
151 | return throwOutOfMemoryError(exec); | |
152 | return jsNontrivialString(exec, result); | |
153 | } | |
154 | ||
155 | template<typename StringType1, typename StringType2, typename StringType3> | |
156 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3) | |
157 | { | |
14957cd0 | 158 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3); |
4e4e5a6f A |
159 | if (!result) |
160 | return throwOutOfMemoryError(exec); | |
161 | return jsNontrivialString(exec, result); | |
162 | } | |
163 | ||
164 | template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> | |
165 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) | |
166 | { | |
14957cd0 | 167 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4); |
4e4e5a6f A |
168 | if (!result) |
169 | return throwOutOfMemoryError(exec); | |
170 | return jsNontrivialString(exec, result); | |
171 | } | |
172 | ||
173 | template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> | |
174 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) | |
175 | { | |
14957cd0 | 176 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5); |
4e4e5a6f A |
177 | if (!result) |
178 | return throwOutOfMemoryError(exec); | |
179 | return jsNontrivialString(exec, result); | |
180 | } | |
181 | ||
182 | template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> | |
183 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) | |
184 | { | |
14957cd0 | 185 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5, string6); |
4e4e5a6f A |
186 | if (!result) |
187 | return throwOutOfMemoryError(exec); | |
188 | return jsNontrivialString(exec, result); | |
189 | } | |
190 | ||
191 | } | |
192 | ||
193 | #endif |