|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef jsstr_h |
|
8 #define jsstr_h |
|
9 |
|
10 #include "mozilla/HashFunctions.h" |
|
11 #include "mozilla/PodOperations.h" |
|
12 |
|
13 #include "jsutil.h" |
|
14 #include "NamespaceImports.h" |
|
15 |
|
16 #include "gc/Rooting.h" |
|
17 #include "js/RootingAPI.h" |
|
18 #include "vm/Unicode.h" |
|
19 |
|
20 class JSAutoByteString; |
|
21 class JSFlatString; |
|
22 class JSLinearString; |
|
23 |
|
24 namespace js { |
|
25 |
|
26 class StringBuffer; |
|
27 |
|
28 class MutatingRopeSegmentRange; |
|
29 |
|
30 template <AllowGC allowGC> |
|
31 extern JSString * |
|
32 ConcatStrings(ThreadSafeContext *cx, |
|
33 typename MaybeRooted<JSString*, allowGC>::HandleType left, |
|
34 typename MaybeRooted<JSString*, allowGC>::HandleType right); |
|
35 |
|
36 // Return s advanced past any Unicode white space characters. |
|
37 static inline const jschar * |
|
38 SkipSpace(const jschar *s, const jschar *end) |
|
39 { |
|
40 JS_ASSERT(s <= end); |
|
41 |
|
42 while (s < end && unicode::IsSpace(*s)) |
|
43 s++; |
|
44 |
|
45 return s; |
|
46 } |
|
47 |
|
48 // Return less than, equal to, or greater than zero depending on whether |
|
49 // s1 is less than, equal to, or greater than s2. |
|
50 inline int32_t |
|
51 CompareChars(const jschar *s1, size_t l1, const jschar *s2, size_t l2) |
|
52 { |
|
53 size_t n = Min(l1, l2); |
|
54 for (size_t i = 0; i < n; i++) { |
|
55 if (int32_t cmp = s1[i] - s2[i]) |
|
56 return cmp; |
|
57 } |
|
58 |
|
59 return (int32_t)(l1 - l2); |
|
60 } |
|
61 |
|
62 } /* namespace js */ |
|
63 |
|
64 extern JSString * JS_FASTCALL |
|
65 js_toLowerCase(JSContext *cx, JSString *str); |
|
66 |
|
67 extern JSString * JS_FASTCALL |
|
68 js_toUpperCase(JSContext *cx, JSString *str); |
|
69 |
|
70 struct JSSubString { |
|
71 size_t length; |
|
72 const jschar *chars; |
|
73 }; |
|
74 |
|
75 extern const jschar js_empty_ucstr[]; |
|
76 extern const JSSubString js_EmptySubString; |
|
77 |
|
78 /* |
|
79 * Shorthands for ASCII (7-bit) decimal and hex conversion. |
|
80 * Manually inline isdigit for performance; MSVC doesn't do this for us. |
|
81 */ |
|
82 #define JS7_ISDEC(c) ((((unsigned)(c)) - '0') <= 9) |
|
83 #define JS7_UNDEC(c) ((c) - '0') |
|
84 #define JS7_ISHEX(c) ((c) < 128 && isxdigit(c)) |
|
85 #define JS7_UNHEX(c) (unsigned)(JS7_ISDEC(c) ? (c) - '0' : 10 + tolower(c) - 'a') |
|
86 #define JS7_ISLET(c) ((c) < 128 && isalpha(c)) |
|
87 |
|
88 /* Initialize the String class, returning its prototype object. */ |
|
89 extern JSObject * |
|
90 js_InitStringClass(JSContext *cx, js::HandleObject obj); |
|
91 |
|
92 extern const char js_escape_str[]; |
|
93 extern const char js_unescape_str[]; |
|
94 extern const char js_uneval_str[]; |
|
95 extern const char js_decodeURI_str[]; |
|
96 extern const char js_encodeURI_str[]; |
|
97 extern const char js_decodeURIComponent_str[]; |
|
98 extern const char js_encodeURIComponent_str[]; |
|
99 |
|
100 /* GC-allocate a string descriptor for the given malloc-allocated chars. */ |
|
101 template <js::AllowGC allowGC> |
|
102 extern JSFlatString * |
|
103 js_NewString(js::ThreadSafeContext *cx, jschar *chars, size_t length); |
|
104 |
|
105 extern JSLinearString * |
|
106 js_NewDependentString(JSContext *cx, JSString *base, size_t start, size_t length); |
|
107 |
|
108 /* Copy a counted string and GC-allocate a descriptor for it. */ |
|
109 template <js::AllowGC allowGC> |
|
110 extern JSFlatString * |
|
111 js_NewStringCopyN(js::ExclusiveContext *cx, const jschar *s, size_t n); |
|
112 |
|
113 template <js::AllowGC allowGC> |
|
114 extern JSFlatString * |
|
115 js_NewStringCopyN(js::ThreadSafeContext *cx, const char *s, size_t n); |
|
116 |
|
117 /* Copy a C string and GC-allocate a descriptor for it. */ |
|
118 template <js::AllowGC allowGC> |
|
119 extern JSFlatString * |
|
120 js_NewStringCopyZ(js::ExclusiveContext *cx, const jschar *s); |
|
121 |
|
122 template <js::AllowGC allowGC> |
|
123 extern JSFlatString * |
|
124 js_NewStringCopyZ(js::ThreadSafeContext *cx, const char *s); |
|
125 |
|
126 /* |
|
127 * Convert a value to a printable C string. |
|
128 */ |
|
129 extern const char * |
|
130 js_ValueToPrintable(JSContext *cx, const js::Value &, |
|
131 JSAutoByteString *bytes, bool asSource = false); |
|
132 |
|
133 namespace js { |
|
134 |
|
135 /* |
|
136 * Convert a non-string value to a string, returning null after reporting an |
|
137 * error, otherwise returning a new string reference. |
|
138 */ |
|
139 template <AllowGC allowGC> |
|
140 extern JSString * |
|
141 ToStringSlow(ExclusiveContext *cx, typename MaybeRooted<Value, allowGC>::HandleType arg); |
|
142 |
|
143 /* |
|
144 * Convert the given value to a string. This method includes an inline |
|
145 * fast-path for the case where the value is already a string; if the value is |
|
146 * known not to be a string, use ToStringSlow instead. |
|
147 */ |
|
148 template <AllowGC allowGC> |
|
149 static MOZ_ALWAYS_INLINE JSString * |
|
150 ToString(JSContext *cx, JS::HandleValue v) |
|
151 { |
|
152 if (v.isString()) |
|
153 return v.toString(); |
|
154 return ToStringSlow<allowGC>(cx, v); |
|
155 } |
|
156 |
|
157 /* |
|
158 * This function implements E-262-3 section 9.8, toString. Convert the given |
|
159 * value to a string of jschars appended to the given buffer. On error, the |
|
160 * passed buffer may have partial results appended. |
|
161 */ |
|
162 inline bool |
|
163 ValueToStringBuffer(JSContext *cx, const Value &v, StringBuffer &sb); |
|
164 |
|
165 /* |
|
166 * Convert a value to its source expression, returning null after reporting |
|
167 * an error, otherwise returning a new string reference. |
|
168 */ |
|
169 extern JSString * |
|
170 ValueToSource(JSContext *cx, HandleValue v); |
|
171 |
|
172 /* |
|
173 * Convert a JSString to its source expression; returns null after reporting an |
|
174 * error, otherwise returns a new string reference. No Handle needed since the |
|
175 * input is dead after the GC. |
|
176 */ |
|
177 extern JSString * |
|
178 StringToSource(JSContext *cx, JSString *str); |
|
179 |
|
180 /* |
|
181 * Test if strings are equal. The caller can call the function even if str1 |
|
182 * or str2 are not GC-allocated things. |
|
183 */ |
|
184 extern bool |
|
185 EqualStrings(JSContext *cx, JSString *str1, JSString *str2, bool *result); |
|
186 |
|
187 /* Use the infallible method instead! */ |
|
188 extern bool |
|
189 EqualStrings(JSContext *cx, JSLinearString *str1, JSLinearString *str2, bool *result) MOZ_DELETE; |
|
190 |
|
191 /* EqualStrings is infallible on linear strings. */ |
|
192 extern bool |
|
193 EqualStrings(JSLinearString *str1, JSLinearString *str2); |
|
194 |
|
195 /* |
|
196 * Return less than, equal to, or greater than zero depending on whether |
|
197 * str1 is less than, equal to, or greater than str2. |
|
198 */ |
|
199 extern bool |
|
200 CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *result); |
|
201 |
|
202 extern int32_t |
|
203 CompareAtoms(JSAtom *atom1, JSAtom *atom2); |
|
204 |
|
205 /* |
|
206 * Return true if the string matches the given sequence of ASCII bytes. |
|
207 */ |
|
208 extern bool |
|
209 StringEqualsAscii(JSLinearString *str, const char *asciiBytes); |
|
210 |
|
211 /* Return true if the string contains a pattern anywhere inside it. */ |
|
212 extern bool |
|
213 StringHasPattern(const jschar *text, uint32_t textlen, |
|
214 const jschar *pat, uint32_t patlen); |
|
215 |
|
216 } /* namespace js */ |
|
217 |
|
218 extern size_t |
|
219 js_strlen(const jschar *s); |
|
220 |
|
221 extern int32_t |
|
222 js_strcmp(const jschar *lhs, const jschar *rhs); |
|
223 |
|
224 extern jschar * |
|
225 js_strchr_limit(const jschar *s, jschar c, const jschar *limit); |
|
226 |
|
227 static MOZ_ALWAYS_INLINE void |
|
228 js_strncpy(jschar *dst, const jschar *src, size_t nelem) |
|
229 { |
|
230 return mozilla::PodCopy(dst, src, nelem); |
|
231 } |
|
232 |
|
233 extern jschar * |
|
234 js_strdup(js::ThreadSafeContext *cx, const jschar *s); |
|
235 |
|
236 namespace js { |
|
237 |
|
238 /* |
|
239 * Inflate bytes in ASCII encoding to jschars. Return null on error, otherwise |
|
240 * return the jschar that was malloc'ed. length is updated to the length of the |
|
241 * new string (in jschars). A null char is appended, but it is not included in |
|
242 * the length. |
|
243 */ |
|
244 extern jschar * |
|
245 InflateString(ThreadSafeContext *cx, const char *bytes, size_t *length); |
|
246 |
|
247 /* |
|
248 * Inflate bytes to JS chars in an existing buffer. 'dst' must be large |
|
249 * enough for 'srclen' jschars. The buffer is NOT null-terminated. |
|
250 */ |
|
251 inline void |
|
252 InflateStringToBuffer(const char *src, size_t srclen, jschar *dst) |
|
253 { |
|
254 for (size_t i = 0; i < srclen; i++) |
|
255 dst[i] = (unsigned char) src[i]; |
|
256 } |
|
257 |
|
258 /* |
|
259 * Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for |
|
260 * 'length chars. The buffer is NOT null-terminated. The destination length |
|
261 * must to be initialized with the buffer size and will contain on return the |
|
262 * number of copied bytes. |
|
263 */ |
|
264 extern bool |
|
265 DeflateStringToBuffer(JSContext *maybecx, const jschar *chars, |
|
266 size_t charsLength, char *bytes, size_t *length); |
|
267 |
|
268 /* |
|
269 * The String.prototype.replace fast-native entry point is exported for joined |
|
270 * function optimization in js{interp,tracer}.cpp. |
|
271 */ |
|
272 extern bool |
|
273 str_replace(JSContext *cx, unsigned argc, js::Value *vp); |
|
274 |
|
275 extern bool |
|
276 str_fromCharCode(JSContext *cx, unsigned argc, Value *vp); |
|
277 |
|
278 } /* namespace js */ |
|
279 |
|
280 extern bool |
|
281 js_str_toString(JSContext *cx, unsigned argc, js::Value *vp); |
|
282 |
|
283 extern bool |
|
284 js_str_charAt(JSContext *cx, unsigned argc, js::Value *vp); |
|
285 |
|
286 extern bool |
|
287 js_str_charCodeAt(JSContext *cx, unsigned argc, js::Value *vp); |
|
288 |
|
289 /* |
|
290 * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at |
|
291 * least 6 bytes long. Return the number of UTF-8 bytes of data written. |
|
292 */ |
|
293 extern int |
|
294 js_OneUcs4ToUtf8Char(uint8_t *utf8Buffer, uint32_t ucs4Char); |
|
295 |
|
296 namespace js { |
|
297 |
|
298 extern size_t |
|
299 PutEscapedStringImpl(char *buffer, size_t size, FILE *fp, JSLinearString *str, uint32_t quote); |
|
300 |
|
301 extern size_t |
|
302 PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp, const jschar *chars, |
|
303 size_t length, uint32_t quote); |
|
304 |
|
305 /* |
|
306 * Write str into buffer escaping any non-printable or non-ASCII character |
|
307 * using \escapes for JS string literals. |
|
308 * Guarantees that a NUL is at the end of the buffer unless size is 0. Returns |
|
309 * the length of the written output, NOT including the NUL. Thus, a return |
|
310 * value of size or more means that the output was truncated. If buffer |
|
311 * is null, just returns the length of the output. If quote is not 0, it must |
|
312 * be a single or double quote character that will quote the output. |
|
313 */ |
|
314 inline size_t |
|
315 PutEscapedString(char *buffer, size_t size, JSLinearString *str, uint32_t quote) |
|
316 { |
|
317 size_t n = PutEscapedStringImpl(buffer, size, nullptr, str, quote); |
|
318 |
|
319 /* PutEscapedStringImpl can only fail with a file. */ |
|
320 JS_ASSERT(n != size_t(-1)); |
|
321 return n; |
|
322 } |
|
323 |
|
324 inline size_t |
|
325 PutEscapedString(char *buffer, size_t bufferSize, const jschar *chars, size_t length, uint32_t quote) |
|
326 { |
|
327 size_t n = PutEscapedStringImpl(buffer, bufferSize, nullptr, chars, length, quote); |
|
328 |
|
329 /* PutEscapedStringImpl can only fail with a file. */ |
|
330 JS_ASSERT(n != size_t(-1)); |
|
331 return n; |
|
332 } |
|
333 |
|
334 /* |
|
335 * Write str into file escaping any non-printable or non-ASCII character. |
|
336 * If quote is not 0, it must be a single or double quote character that |
|
337 * will quote the output. |
|
338 */ |
|
339 inline bool |
|
340 FileEscapedString(FILE *fp, JSLinearString *str, uint32_t quote) |
|
341 { |
|
342 return PutEscapedStringImpl(nullptr, 0, fp, str, quote) != size_t(-1); |
|
343 } |
|
344 |
|
345 bool |
|
346 str_match(JSContext *cx, unsigned argc, Value *vp); |
|
347 |
|
348 bool |
|
349 str_search(JSContext *cx, unsigned argc, Value *vp); |
|
350 |
|
351 bool |
|
352 str_split(JSContext *cx, unsigned argc, Value *vp); |
|
353 |
|
354 JSObject * |
|
355 str_split_string(JSContext *cx, HandleTypeObject type, HandleString str, HandleString sep); |
|
356 |
|
357 bool |
|
358 str_resolve(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp); |
|
359 |
|
360 bool |
|
361 str_replace_regexp_raw(JSContext *cx, HandleString string, HandleObject regexp, |
|
362 HandleString replacement, MutableHandleValue rval); |
|
363 |
|
364 bool |
|
365 str_replace_string_raw(JSContext *cx, HandleString string, HandleString pattern, |
|
366 HandleString replacement, MutableHandleValue rval); |
|
367 |
|
368 } /* namespace js */ |
|
369 |
|
370 extern bool |
|
371 js_String(JSContext *cx, unsigned argc, js::Value *vp); |
|
372 |
|
373 #endif /* jsstr_h */ |