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/. */
10 #include "mozilla/HashFunctions.h"
11 #include "mozilla/PodOperations.h"
12 #include "mozilla/UniquePtr.h"
15 #include "NamespaceImports.h"
17 #include "gc/Rooting.h"
18 #include "js/RootingAPI.h"
19 #include "vm/Unicode.h"
21 class JSAutoByteString
;
29 class MutatingRopeSegmentRange
;
31 template <AllowGC allowGC
>
33 ConcatStrings(ThreadSafeContext
* cx
,
34 typename MaybeRooted
<JSString
*, allowGC
>::HandleType left
,
35 typename MaybeRooted
<JSString
*, allowGC
>::HandleType right
);
37 // Return s advanced past any Unicode white space characters.
38 template <typename CharT
>
39 static inline const CharT
*
40 SkipSpace(const CharT
* s
, const CharT
* end
)
44 while (s
< end
&& unicode::IsSpace(*s
))
50 // Return less than, equal to, or greater than zero depending on whether
51 // s1 is less than, equal to, or greater than s2.
52 template <typename Char1
, typename Char2
>
54 CompareChars(const Char1
* s1
, size_t len1
, const Char2
* s2
, size_t len2
)
56 size_t n
= Min(len1
, len2
);
57 for (size_t i
= 0; i
< n
; i
++) {
58 if (int32_t cmp
= s1
[i
] - s2
[i
])
62 return int32_t(len1
- len2
);
66 CompareChars(const jschar
* s1
, size_t len1
, JSLinearString
* s2
);
75 JSSubString() { mozilla::PodZero(this); }
77 void initEmpty(JSLinearString
* base
) {
81 void init(JSLinearString
* base
, size_t offset
, size_t length
) {
83 this->offset
= offset
;
84 this->length
= length
;
89 * Shorthands for ASCII (7-bit) decimal and hex conversion.
90 * Manually inline isdigit for performance; MSVC doesn't do this for us.
92 #define JS7_ISDEC(c) ((((unsigned)(c)) - '0') <= 9)
93 #define JS7_UNDEC(c) ((c) - '0')
94 #define JS7_ISHEX(c) ((c) < 128 && isxdigit(c))
95 #define JS7_UNHEX(c) (unsigned)(JS7_ISDEC(c) ? (c) - '0' : 10 + tolower(c) - 'a')
96 #define JS7_ISLET(c) ((c) < 128 && isalpha(c))
98 /* Initialize the String class, returning its prototype object. */
100 js_InitStringClass(JSContext
* cx
, js::HandleObject obj
);
103 * Convert a value to a printable C string.
106 js_ValueToPrintable(JSContext
* cx
, const js::Value
&,
107 JSAutoByteString
* bytes
, bool asSource
= false);
110 js_strlen(const jschar
* s
);
113 js_strcmp(const jschar
* lhs
, const jschar
* rhs
);
115 template <typename CharT
>
117 js_strchr_limit(const CharT
* s
, jschar c
, const CharT
* limit
);
119 static MOZ_ALWAYS_INLINE
void
120 js_strncpy(jschar
* dst
, const jschar
* src
, size_t nelem
)
122 return mozilla::PodCopy(dst
, src
, nelem
);
127 extern mozilla::UniquePtr
<char[], JS::FreePolicy
>
128 DuplicateString(ThreadSafeContext
* cx
, const char* s
);
130 extern mozilla::UniquePtr
<jschar
[], JS::FreePolicy
>
131 DuplicateString(ThreadSafeContext
* cx
, const jschar
* s
);
134 * Convert a non-string value to a string, returning null after reporting an
135 * error, otherwise returning a new string reference.
137 template <AllowGC allowGC
>
139 ToStringSlow(ExclusiveContext
* cx
, typename MaybeRooted
<Value
, allowGC
>::HandleType arg
);
142 * Convert the given value to a string. This method includes an inline
143 * fast-path for the case where the value is already a string; if the value is
144 * known not to be a string, use ToStringSlow instead.
146 template <AllowGC allowGC
>
147 static MOZ_ALWAYS_INLINE JSString
*
148 ToString(JSContext
* cx
, JS::HandleValue v
)
152 return ToStringSlow
<allowGC
>(cx
, v
);
156 * This function implements E-262-3 section 9.8, toString. Convert the given
157 * value to a string of jschars appended to the given buffer. On error, the
158 * passed buffer may have partial results appended.
161 ValueToStringBuffer(JSContext
* cx
, const Value
& v
, StringBuffer
& sb
);
164 * Convert a value to its source expression, returning null after reporting
165 * an error, otherwise returning a new string reference.
168 ValueToSource(JSContext
* cx
, HandleValue v
);
171 * Convert a JSString to its source expression; returns null after reporting an
172 * error, otherwise returns a new string reference. No Handle needed since the
173 * input is dead after the GC.
176 StringToSource(JSContext
* cx
, JSString
* str
);
179 * Test if strings are equal. The caller can call the function even if str1
180 * or str2 are not GC-allocated things.
183 EqualStrings(JSContext
* cx
, JSString
* str1
, JSString
* str2
, bool* result
);
185 /* Use the infallible method instead! */
187 EqualStrings(JSContext
* cx
, JSLinearString
* str1
, JSLinearString
* str2
, bool* result
) MOZ_DELETE
;
189 /* EqualStrings is infallible on linear strings. */
191 EqualStrings(JSLinearString
* str1
, JSLinearString
* str2
);
194 EqualChars(JSLinearString
* str1
, JSLinearString
* str2
);
197 * Return less than, equal to, or greater than zero depending on whether
198 * str1 is less than, equal to, or greater than str2.
201 CompareStrings(JSContext
* cx
, JSString
* str1
, JSString
* str2
, int32_t* result
);
204 * Same as CompareStrings but for atoms. Don't use this to just test
205 * for equality; use this when you need an ordering on atoms.
208 CompareAtoms(JSAtom
* atom1
, JSAtom
* atom2
);
211 * Return true if the string matches the given sequence of ASCII bytes.
214 StringEqualsAscii(JSLinearString
* str
, const char* asciiBytes
);
216 /* Return true if the string contains a pattern anywhere inside it. */
218 StringHasPattern(JSLinearString
* text
, const jschar
* pat
, uint32_t patlen
);
221 StringFindPattern(JSLinearString
* text
, JSLinearString
* pat
, size_t start
);
223 // Whether the string contains any RegExp meta characters (., *, and so forth).
224 // Searches the range [beginOffset, length - endOffset>.
226 StringHasRegExpMetaChars(JSLinearString
* str
, size_t beginOffset
= 0, size_t endOffset
= 0);
228 template <typename Char1
, typename Char2
>
230 EqualChars(const Char1
* s1
, const Char2
* s2
, size_t len
);
232 template <typename Char1
>
234 EqualChars(const Char1
* s1
, const Char1
* s2
, size_t len
)
236 return mozilla::PodEqual(s1
, s2
, len
);
239 template <typename Char1
, typename Char2
>
241 EqualChars(const Char1
* s1
, const Char2
* s2
, size_t len
)
243 for (const Char1
* s1end
= s1
+ len
; s1
< s1end
; s1
++, s2
++) {
251 * Inflate bytes in ASCII encoding to jschars. Return null on error, otherwise
252 * return the jschar that was malloc'ed. length is updated to the length of the
253 * new string (in jschars). A null char is appended, but it is not included in
257 InflateString(ThreadSafeContext
* cx
, const char* bytes
, size_t* length
);
260 * Inflate bytes to JS chars in an existing buffer. 'dst' must be large
261 * enough for 'srclen' jschars. The buffer is NOT null-terminated.
264 CopyAndInflateChars(jschar
* dst
, const char* src
, size_t srclen
)
266 for (size_t i
= 0; i
< srclen
; i
++)
267 dst
[i
] = (unsigned char) src
[i
];
271 CopyAndInflateChars(jschar
* dst
, const JS::Latin1Char
* src
, size_t srclen
)
273 for (size_t i
= 0; i
< srclen
; i
++)
278 * Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
279 * 'length chars. The buffer is NOT null-terminated. The destination length
280 * must to be initialized with the buffer size and will contain on return the
281 * number of copied bytes.
283 template <typename CharT
>
285 DeflateStringToBuffer(JSContext
* maybecx
, const CharT
* chars
,
286 size_t charsLength
, char* bytes
, size_t* length
);
289 * The String.prototype.replace fast-native entry point is exported for joined
290 * function optimization in js{interp,tracer}.cpp.
293 str_replace(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
296 str_fromCharCode(JSContext
* cx
, unsigned argc
, Value
* vp
);
299 str_fromCharCode_one_arg(JSContext
* cx
, HandleValue code
, MutableHandleValue rval
);
304 js_str_toString(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
307 js_str_charAt(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
312 str_charCodeAt_impl(JSContext
* cx
, HandleString string
, HandleValue index
, MutableHandleValue res
);
317 js_str_charCodeAt(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
319 * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
320 * least 6 bytes long. Return the number of UTF-8 bytes of data written.
323 js_OneUcs4ToUtf8Char(uint8_t* utf8Buffer
, uint32_t ucs4Char
);
328 PutEscapedStringImpl(char* buffer
, size_t size
, FILE* fp
, JSLinearString
* str
, uint32_t quote
);
330 template <typename CharT
>
332 PutEscapedStringImpl(char* buffer
, size_t bufferSize
, FILE* fp
, const CharT
* chars
,
333 size_t length
, uint32_t quote
);
336 * Write str into buffer escaping any non-printable or non-ASCII character
337 * using \escapes for JS string literals.
338 * Guarantees that a NUL is at the end of the buffer unless size is 0. Returns
339 * the length of the written output, NOT including the NUL. Thus, a return
340 * value of size or more means that the output was truncated. If buffer
341 * is null, just returns the length of the output. If quote is not 0, it must
342 * be a single or double quote character that will quote the output.
345 PutEscapedString(char* buffer
, size_t size
, JSLinearString
* str
, uint32_t quote
)
347 size_t n
= PutEscapedStringImpl(buffer
, size
, nullptr, str
, quote
);
349 /* PutEscapedStringImpl can only fail with a file. */
350 JS_ASSERT(n
!= size_t(-1));
354 template <typename CharT
>
356 PutEscapedString(char* buffer
, size_t bufferSize
, const CharT
* chars
, size_t length
, uint32_t quote
)
358 size_t n
= PutEscapedStringImpl(buffer
, bufferSize
, nullptr, chars
, length
, quote
);
360 /* PutEscapedStringImpl can only fail with a file. */
361 JS_ASSERT(n
!= size_t(-1));
366 * Write str into file escaping any non-printable or non-ASCII character.
367 * If quote is not 0, it must be a single or double quote character that
368 * will quote the output.
371 FileEscapedString(FILE* fp
, JSLinearString
* str
, uint32_t quote
)
373 return PutEscapedStringImpl(nullptr, 0, fp
, str
, quote
) != size_t(-1);
377 str_match(JSContext
* cx
, unsigned argc
, Value
* vp
);
380 str_search(JSContext
* cx
, unsigned argc
, Value
* vp
);
383 str_split(JSContext
* cx
, unsigned argc
, Value
* vp
);
386 str_split_string(JSContext
* cx
, HandleTypeObject type
, HandleString str
, HandleString sep
);
389 str_resolve(JSContext
* cx
, HandleObject obj
, HandleId id
, MutableHandleObject objp
);
392 str_replace_regexp_raw(JSContext
* cx
, HandleString string
, HandleObject regexp
,
393 HandleString replacement
, MutableHandleValue rval
);
396 str_replace_string_raw(JSContext
* cx
, HandleString string
, HandleString pattern
,
397 HandleString replacement
, MutableHandleValue rval
);
402 js_String(JSContext
* cx
, unsigned argc
, js::Value
* vp
);