]>
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" | |
14957cd0 | 31 | #include "UStringConcatenate.h" |
6fe7ccc8 | 32 | #include <wtf/Vector.h> |
4e4e5a6f A |
33 | |
34 | namespace JSC { | |
35 | ||
36 | class JSStringBuilder { | |
37 | public: | |
38 | JSStringBuilder() | |
39 | : m_okay(true) | |
6fe7ccc8 | 40 | , m_is8Bit(true) |
4e4e5a6f A |
41 | { |
42 | } | |
43 | ||
44 | void append(const UChar u) | |
45 | { | |
6fe7ccc8 A |
46 | if (m_is8Bit) { |
47 | if (u < 0xff) { | |
48 | LChar c = u; | |
49 | m_okay &= buffer8.tryAppend(&c, 1); | |
50 | return; | |
51 | } | |
52 | upConvert(); | |
53 | } | |
54 | m_okay &= buffer16.tryAppend(&u, 1); | |
4e4e5a6f A |
55 | } |
56 | ||
57 | void append(const char* str) | |
58 | { | |
59 | append(str, strlen(str)); | |
60 | } | |
61 | ||
62 | void append(const char* str, size_t len) | |
63 | { | |
6fe7ccc8 A |
64 | if (m_is8Bit) { |
65 | m_okay &= buffer8.tryAppend(reinterpret_cast<const LChar*>(str), len); | |
66 | return; | |
67 | } | |
68 | m_okay &= buffer8.tryReserveCapacity(buffer16.size() + len); | |
4e4e5a6f A |
69 | for (size_t i = 0; i < len; i++) { |
70 | UChar u = static_cast<unsigned char>(str[i]); | |
6fe7ccc8 | 71 | m_okay &= buffer16.tryAppend(&u, 1); |
4e4e5a6f A |
72 | } |
73 | } | |
74 | ||
6fe7ccc8 A |
75 | void append(const LChar* str, size_t len) |
76 | { | |
77 | if (m_is8Bit) { | |
78 | m_okay &= buffer8.tryAppend(str, len); | |
79 | return; | |
80 | } | |
81 | m_okay &= buffer8.tryReserveCapacity(buffer16.size() + len); | |
82 | for (size_t i = 0; i < len; i++) { | |
83 | UChar u = str[i]; | |
84 | m_okay &= buffer16.tryAppend(&u, 1); | |
85 | } | |
86 | } | |
87 | ||
4e4e5a6f A |
88 | void append(const UChar* str, size_t len) |
89 | { | |
6fe7ccc8 A |
90 | if (m_is8Bit) |
91 | upConvert(); // FIXME: We could check character by character its size. | |
92 | m_okay &= buffer16.tryAppend(str, len); | |
4e4e5a6f A |
93 | } |
94 | ||
95 | void append(const UString& str) | |
96 | { | |
6fe7ccc8 A |
97 | unsigned length = str.length(); |
98 | ||
99 | if (!length) | |
100 | return; | |
101 | ||
102 | if (m_is8Bit) { | |
103 | if (str.is8Bit()) { | |
104 | m_okay &= buffer8.tryAppend(str.characters8(), length); | |
105 | return; | |
106 | } | |
107 | upConvert(); | |
108 | } | |
109 | m_okay &= buffer16.tryAppend(str.characters(), length); | |
110 | } | |
111 | ||
112 | void upConvert() | |
113 | { | |
114 | ASSERT(m_is8Bit); | |
115 | size_t len = buffer8.size(); | |
116 | ||
117 | for (size_t i = 0; i < len; i++) | |
118 | buffer16.append(buffer8[i]); | |
119 | ||
120 | buffer8.clear(); | |
121 | m_is8Bit = false; | |
4e4e5a6f A |
122 | } |
123 | ||
124 | JSValue build(ExecState* exec) | |
125 | { | |
126 | if (!m_okay) | |
127 | return throwOutOfMemoryError(exec); | |
6fe7ccc8 A |
128 | if (m_is8Bit) { |
129 | buffer8.shrinkToFit(); | |
130 | if (!buffer8.data()) | |
131 | return throwOutOfMemoryError(exec); | |
132 | return jsString(exec, UString::adopt(buffer8)); | |
133 | } | |
134 | buffer16.shrinkToFit(); | |
135 | if (!buffer16.data()) | |
4e4e5a6f | 136 | return throwOutOfMemoryError(exec); |
6fe7ccc8 | 137 | return jsString(exec, UString::adopt(buffer16)); |
4e4e5a6f A |
138 | } |
139 | ||
140 | protected: | |
6fe7ccc8 A |
141 | Vector<LChar, 64> buffer8; |
142 | Vector<UChar, 64> buffer16; | |
4e4e5a6f | 143 | bool m_okay; |
6fe7ccc8 | 144 | bool m_is8Bit; |
4e4e5a6f A |
145 | }; |
146 | ||
147 | template<typename StringType1, typename StringType2> | |
148 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2) | |
149 | { | |
14957cd0 | 150 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2); |
4e4e5a6f A |
151 | if (!result) |
152 | return throwOutOfMemoryError(exec); | |
153 | return jsNontrivialString(exec, result); | |
154 | } | |
155 | ||
156 | template<typename StringType1, typename StringType2, typename StringType3> | |
157 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3) | |
158 | { | |
14957cd0 | 159 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3); |
4e4e5a6f A |
160 | if (!result) |
161 | return throwOutOfMemoryError(exec); | |
162 | return jsNontrivialString(exec, result); | |
163 | } | |
164 | ||
165 | template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> | |
166 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) | |
167 | { | |
14957cd0 | 168 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4); |
4e4e5a6f A |
169 | if (!result) |
170 | return throwOutOfMemoryError(exec); | |
171 | return jsNontrivialString(exec, result); | |
172 | } | |
173 | ||
174 | template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> | |
175 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) | |
176 | { | |
14957cd0 | 177 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5); |
4e4e5a6f A |
178 | if (!result) |
179 | return throwOutOfMemoryError(exec); | |
180 | return jsNontrivialString(exec, result); | |
181 | } | |
182 | ||
183 | template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> | |
184 | inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) | |
185 | { | |
14957cd0 | 186 | PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5, string6); |
4e4e5a6f A |
187 | if (!result) |
188 | return throwOutOfMemoryError(exec); | |
189 | return jsNontrivialString(exec, result); | |
190 | } | |
191 | ||
192 | } | |
193 | ||
194 | #endif |