mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-02 15:15:23 +00:00
72ea23c63e
--HG-- extra : commitid : JegWAoGsuQ9 extra : rebase_source : 995c1b6ab8e4fd3b83c44741cd84a2d7b0d934d7
459 lines
13 KiB
C++
459 lines
13 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef jsstr_h
|
|
#define jsstr_h
|
|
|
|
#include "mozilla/HashFunctions.h"
|
|
#include "mozilla/PodOperations.h"
|
|
|
|
#include "jsutil.h"
|
|
#include "NamespaceImports.h"
|
|
|
|
#include "gc/Rooting.h"
|
|
#include "js/RootingAPI.h"
|
|
#include "js/UniquePtr.h"
|
|
#include "vm/Printer.h"
|
|
#include "vm/Unicode.h"
|
|
|
|
class JSAutoByteString;
|
|
class JSLinearString;
|
|
|
|
namespace js {
|
|
|
|
class StringBuffer;
|
|
|
|
template <AllowGC allowGC>
|
|
extern JSString*
|
|
ConcatStrings(ExclusiveContext* cx,
|
|
typename MaybeRooted<JSString*, allowGC>::HandleType left,
|
|
typename MaybeRooted<JSString*, allowGC>::HandleType right);
|
|
|
|
// Return s advanced past any Unicode white space characters.
|
|
template <typename CharT>
|
|
static inline const CharT*
|
|
SkipSpace(const CharT* s, const CharT* end)
|
|
{
|
|
MOZ_ASSERT(s <= end);
|
|
|
|
while (s < end && unicode::IsSpace(*s))
|
|
s++;
|
|
|
|
return s;
|
|
}
|
|
|
|
// Return less than, equal to, or greater than zero depending on whether
|
|
// s1 is less than, equal to, or greater than s2.
|
|
template <typename Char1, typename Char2>
|
|
inline int32_t
|
|
CompareChars(const Char1* s1, size_t len1, const Char2* s2, size_t len2)
|
|
{
|
|
size_t n = Min(len1, len2);
|
|
for (size_t i = 0; i < n; i++) {
|
|
if (int32_t cmp = s1[i] - s2[i])
|
|
return cmp;
|
|
}
|
|
|
|
return int32_t(len1 - len2);
|
|
}
|
|
|
|
extern int32_t
|
|
CompareChars(const char16_t* s1, size_t len1, JSLinearString* s2);
|
|
|
|
} /* namespace js */
|
|
|
|
struct JSSubString {
|
|
JSLinearString* base;
|
|
size_t offset;
|
|
size_t length;
|
|
|
|
JSSubString() { mozilla::PodZero(this); }
|
|
|
|
void initEmpty(JSLinearString* base) {
|
|
this->base = base;
|
|
offset = length = 0;
|
|
}
|
|
void init(JSLinearString* base, size_t offset, size_t length) {
|
|
this->base = base;
|
|
this->offset = offset;
|
|
this->length = length;
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Shorthands for ASCII (7-bit) decimal and hex conversion.
|
|
* Manually inline isdigit for performance; MSVC doesn't do this for us.
|
|
*/
|
|
#define JS7_ISDEC(c) ((((unsigned)(c)) - '0') <= 9)
|
|
#define JS7_UNDEC(c) ((c) - '0')
|
|
#define JS7_ISOCT(c) ((((unsigned)(c)) - '0') <= 7)
|
|
#define JS7_UNOCT(c) (JS7_UNDEC(c))
|
|
#define JS7_ISHEX(c) ((c) < 128 && isxdigit(c))
|
|
#define JS7_UNHEX(c) (unsigned)(JS7_ISDEC(c) ? (c) - '0' : 10 + tolower(c) - 'a')
|
|
#define JS7_ISLET(c) ((c) < 128 && isalpha(c))
|
|
|
|
extern size_t
|
|
js_strlen(const char16_t* s);
|
|
|
|
extern int32_t
|
|
js_strcmp(const char16_t* lhs, const char16_t* rhs);
|
|
|
|
template <typename CharT>
|
|
extern const CharT*
|
|
js_strchr_limit(const CharT* s, char16_t c, const CharT* limit);
|
|
|
|
static MOZ_ALWAYS_INLINE void
|
|
js_strncpy(char16_t* dst, const char16_t* src, size_t nelem)
|
|
{
|
|
return mozilla::PodCopy(dst, src, nelem);
|
|
}
|
|
|
|
namespace js {
|
|
|
|
/* Initialize the String class, returning its prototype object. */
|
|
extern JSObject*
|
|
InitStringClass(JSContext* cx, HandleObject obj);
|
|
|
|
/*
|
|
* Convert a value to a printable C string.
|
|
*/
|
|
extern const char*
|
|
ValueToPrintable(JSContext* cx, const Value&, JSAutoByteString* bytes, bool asSource = false);
|
|
|
|
extern UniqueChars
|
|
DuplicateString(ExclusiveContext* cx, const char* s);
|
|
|
|
extern UniqueTwoByteChars
|
|
DuplicateString(ExclusiveContext* cx, const char16_t* s);
|
|
|
|
/*
|
|
* These variants do not report OOMs, you must arrange for OOMs to be reported
|
|
* yourself.
|
|
*/
|
|
extern UniqueChars
|
|
DuplicateString(const char* s);
|
|
|
|
extern UniqueTwoByteChars
|
|
DuplicateString(const char16_t* s);
|
|
|
|
/*
|
|
* Convert a non-string value to a string, returning null after reporting an
|
|
* error, otherwise returning a new string reference.
|
|
*/
|
|
template <AllowGC allowGC>
|
|
extern JSString*
|
|
ToStringSlow(ExclusiveContext* cx, typename MaybeRooted<Value, allowGC>::HandleType arg);
|
|
|
|
/*
|
|
* Convert the given value to a string. This method includes an inline
|
|
* fast-path for the case where the value is already a string; if the value is
|
|
* known not to be a string, use ToStringSlow instead.
|
|
*/
|
|
template <AllowGC allowGC>
|
|
static MOZ_ALWAYS_INLINE JSString*
|
|
ToString(JSContext* cx, JS::HandleValue v)
|
|
{
|
|
if (v.isString())
|
|
return v.toString();
|
|
return ToStringSlow<allowGC>(cx, v);
|
|
}
|
|
|
|
/*
|
|
* This function implements E-262-3 section 9.8, toString. Convert the given
|
|
* value to a string of characters appended to the given buffer. On error, the
|
|
* passed buffer may have partial results appended.
|
|
*/
|
|
inline bool
|
|
ValueToStringBuffer(JSContext* cx, const Value& v, StringBuffer& sb);
|
|
|
|
/*
|
|
* Convert a value to its source expression, returning null after reporting
|
|
* an error, otherwise returning a new string reference.
|
|
*/
|
|
extern JSString*
|
|
ValueToSource(JSContext* cx, HandleValue v);
|
|
|
|
/*
|
|
* Convert a JSString to its source expression; returns null after reporting an
|
|
* error, otherwise returns a new string reference. No Handle needed since the
|
|
* input is dead after the GC.
|
|
*/
|
|
extern JSString*
|
|
StringToSource(JSContext* cx, JSString* str);
|
|
|
|
/*
|
|
* Test if strings are equal. The caller can call the function even if str1
|
|
* or str2 are not GC-allocated things.
|
|
*/
|
|
extern bool
|
|
EqualStrings(JSContext* cx, JSString* str1, JSString* str2, bool* result);
|
|
|
|
/* Use the infallible method instead! */
|
|
extern bool
|
|
EqualStrings(JSContext* cx, JSLinearString* str1, JSLinearString* str2, bool* result) = delete;
|
|
|
|
/* EqualStrings is infallible on linear strings. */
|
|
extern bool
|
|
EqualStrings(JSLinearString* str1, JSLinearString* str2);
|
|
|
|
extern bool
|
|
EqualChars(JSLinearString* str1, JSLinearString* str2);
|
|
|
|
/*
|
|
* Return less than, equal to, or greater than zero depending on whether
|
|
* str1 is less than, equal to, or greater than str2.
|
|
*/
|
|
extern bool
|
|
CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result);
|
|
|
|
/*
|
|
* Same as CompareStrings but for atoms. Don't use this to just test
|
|
* for equality; use this when you need an ordering on atoms.
|
|
*/
|
|
extern int32_t
|
|
CompareAtoms(JSAtom* atom1, JSAtom* atom2);
|
|
|
|
/*
|
|
* Return true if the string matches the given sequence of ASCII bytes.
|
|
*/
|
|
extern bool
|
|
StringEqualsAscii(JSLinearString* str, const char* asciiBytes);
|
|
|
|
/* Return true if the string contains a pattern anywhere inside it. */
|
|
extern bool
|
|
StringHasPattern(JSLinearString* text, const char16_t* pat, uint32_t patlen);
|
|
|
|
extern int
|
|
StringFindPattern(JSLinearString* text, JSLinearString* pat, size_t start);
|
|
|
|
/* Return true if the string contains a pattern at |start|. */
|
|
extern bool
|
|
HasSubstringAt(JSLinearString* text, JSLinearString* pat, size_t start);
|
|
|
|
template <typename CharT>
|
|
extern bool
|
|
HasRegExpMetaChars(const CharT* chars, size_t length);
|
|
|
|
extern bool
|
|
StringHasRegExpMetaChars(JSLinearString* str);
|
|
|
|
template <typename Char1, typename Char2>
|
|
inline bool
|
|
EqualChars(const Char1* s1, const Char2* s2, size_t len);
|
|
|
|
template <typename Char1>
|
|
inline bool
|
|
EqualChars(const Char1* s1, const Char1* s2, size_t len)
|
|
{
|
|
return mozilla::PodEqual(s1, s2, len);
|
|
}
|
|
|
|
template <typename Char1, typename Char2>
|
|
inline bool
|
|
EqualChars(const Char1* s1, const Char2* s2, size_t len)
|
|
{
|
|
for (const Char1* s1end = s1 + len; s1 < s1end; s1++, s2++) {
|
|
if (*s1 != *s2)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Computes |str|'s substring for the range [beginInt, beginInt + lengthInt).
|
|
* Negative, overlarge, swapped, etc. |beginInt| and |lengthInt| are forbidden
|
|
* and constitute API misuse.
|
|
*/
|
|
JSString*
|
|
SubstringKernel(JSContext* cx, HandleString str, int32_t beginInt, int32_t lengthInt);
|
|
|
|
/*
|
|
* Inflate bytes in ASCII encoding to char16_t code units. Return null on error,
|
|
* otherwise return the char16_t buffer that was malloc'ed. length is updated to
|
|
* the length of the new string (in char16_t code units). A null char is
|
|
* appended, but it is not included in the length.
|
|
*/
|
|
extern char16_t*
|
|
InflateString(ExclusiveContext* cx, const char* bytes, size_t* length);
|
|
|
|
/*
|
|
* Inflate bytes to JS chars in an existing buffer. 'dst' must be large
|
|
* enough for 'srclen' char16_t code units. The buffer is NOT null-terminated.
|
|
*/
|
|
inline void
|
|
CopyAndInflateChars(char16_t* dst, const char* src, size_t srclen)
|
|
{
|
|
for (size_t i = 0; i < srclen; i++)
|
|
dst[i] = (unsigned char) src[i];
|
|
}
|
|
|
|
inline void
|
|
CopyAndInflateChars(char16_t* dst, const JS::Latin1Char* src, size_t srclen)
|
|
{
|
|
for (size_t i = 0; i < srclen; i++)
|
|
dst[i] = src[i];
|
|
}
|
|
|
|
/*
|
|
* Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
|
|
* 'length chars. The buffer is NOT null-terminated. The destination length
|
|
* must to be initialized with the buffer size and will contain on return the
|
|
* number of copied bytes.
|
|
*/
|
|
template <typename CharT>
|
|
extern bool
|
|
DeflateStringToBuffer(JSContext* maybecx, const CharT* chars,
|
|
size_t charsLength, char* bytes, size_t* length);
|
|
|
|
/*
|
|
* The String.prototype.replace fast-native entry point is exported for joined
|
|
* function optimization in js{interp,tracer}.cpp.
|
|
*/
|
|
extern bool
|
|
str_replace(JSContext* cx, unsigned argc, js::Value* vp);
|
|
|
|
extern bool
|
|
str_fromCharCode(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
extern bool
|
|
str_fromCharCode_one_arg(JSContext* cx, HandleValue code, MutableHandleValue rval);
|
|
|
|
/* String methods exposed so they can be installed in the self-hosting global. */
|
|
|
|
extern bool
|
|
str_indexOf(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
extern bool
|
|
str_lastIndexOf(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
extern bool
|
|
str_startsWith(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
extern bool
|
|
str_toLowerCase(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
extern bool
|
|
str_toUpperCase(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
extern bool
|
|
str_toString(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
extern bool
|
|
str_charAt(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
extern bool
|
|
str_charCodeAt_impl(JSContext* cx, HandleString string, HandleValue index, MutableHandleValue res);
|
|
|
|
extern bool
|
|
str_charCodeAt(JSContext* cx, unsigned argc, Value* vp);
|
|
/*
|
|
* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
|
|
* least 4 bytes long. Return the number of UTF-8 bytes of data written.
|
|
*/
|
|
extern uint32_t
|
|
OneUcs4ToUtf8Char(uint8_t* utf8Buffer, uint32_t ucs4Char);
|
|
|
|
extern size_t
|
|
PutEscapedStringImpl(char* buffer, size_t size, GenericPrinter* out, JSLinearString* str,
|
|
uint32_t quote);
|
|
|
|
template <typename CharT>
|
|
extern size_t
|
|
PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, const CharT* chars,
|
|
size_t length, uint32_t quote);
|
|
|
|
/*
|
|
* Write str into buffer escaping any non-printable or non-ASCII character
|
|
* using \escapes for JS string literals.
|
|
* Guarantees that a NUL is at the end of the buffer unless size is 0. Returns
|
|
* the length of the written output, NOT including the NUL. Thus, a return
|
|
* value of size or more means that the output was truncated. If buffer
|
|
* is null, just returns the length of the output. If quote is not 0, it must
|
|
* be a single or double quote character that will quote the output.
|
|
*/
|
|
inline size_t
|
|
PutEscapedString(char* buffer, size_t size, JSLinearString* str, uint32_t quote)
|
|
{
|
|
size_t n = PutEscapedStringImpl(buffer, size, nullptr, str, quote);
|
|
|
|
/* PutEscapedStringImpl can only fail with a file. */
|
|
MOZ_ASSERT(n != size_t(-1));
|
|
return n;
|
|
}
|
|
|
|
template <typename CharT>
|
|
inline size_t
|
|
PutEscapedString(char* buffer, size_t bufferSize, const CharT* chars, size_t length, uint32_t quote)
|
|
{
|
|
size_t n = PutEscapedStringImpl(buffer, bufferSize, nullptr, chars, length, quote);
|
|
|
|
/* PutEscapedStringImpl can only fail with a file. */
|
|
MOZ_ASSERT(n != size_t(-1));
|
|
return n;
|
|
}
|
|
|
|
inline bool
|
|
EscapedStringPrinter(GenericPrinter& out, JSLinearString* str, uint32_t quote)
|
|
{
|
|
return PutEscapedStringImpl(nullptr, 0, &out, str, quote) != size_t(-1);
|
|
}
|
|
|
|
inline bool
|
|
EscapedStringPrinter(GenericPrinter& out, const char* chars, size_t length, uint32_t quote)
|
|
{
|
|
return PutEscapedStringImpl(nullptr, 0, &out, chars, length, quote) != size_t(-1);
|
|
}
|
|
|
|
/*
|
|
* Write str into file escaping any non-printable or non-ASCII character.
|
|
* If quote is not 0, it must be a single or double quote character that
|
|
* will quote the output.
|
|
*/
|
|
inline bool
|
|
FileEscapedString(FILE* fp, JSLinearString* str, uint32_t quote)
|
|
{
|
|
Fprinter out(fp);
|
|
bool res = EscapedStringPrinter(out, str, quote);
|
|
out.finish();
|
|
return res;
|
|
}
|
|
|
|
inline bool
|
|
FileEscapedString(FILE* fp, const char* chars, size_t length, uint32_t quote)
|
|
{
|
|
Fprinter out(fp);
|
|
bool res = EscapedStringPrinter(out, chars, length, quote);
|
|
out.finish();
|
|
return res;
|
|
}
|
|
|
|
bool
|
|
str_match(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
bool
|
|
str_search(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
bool
|
|
str_split(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
JSObject*
|
|
str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep);
|
|
|
|
JSString *
|
|
str_flat_replace_string(JSContext *cx, HandleString string, HandleString pattern,
|
|
HandleString replacement);
|
|
|
|
JSString*
|
|
str_replace_string_raw(JSContext* cx, HandleString string, HandleString pattern,
|
|
HandleString replacement);
|
|
|
|
extern bool
|
|
StringConstructor(JSContext* cx, unsigned argc, Value* vp);
|
|
|
|
} /* namespace js */
|
|
|
|
#endif /* jsstr_h */
|