summaryrefslogtreecommitdiffstats
path: root/js/src/jsstr.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsstr.h')
-rw-r--r--js/src/jsstr.h495
1 files changed, 495 insertions, 0 deletions
diff --git a/js/src/jsstr.h b/js/src/jsstr.h
new file mode 100644
index 000000000..3b92aa21b
--- /dev/null
+++ b/js/src/jsstr.h
@@ -0,0 +1,495 @@
+/* -*- 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 <stdio.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);
+}
+
+extern int32_t
+js_fputs(const char16_t* s, FILE* f);
+
+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 UniqueChars
+DuplicateString(const char* s, size_t n);
+
+extern UniqueTwoByteChars
+DuplicateString(const char16_t* s);
+
+extern UniqueTwoByteChars
+DuplicateString(const char16_t* s, size_t n);
+
+/*
+ * 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 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);
+
+extern bool
+str_fromCharCode(JSContext* cx, unsigned argc, Value* vp);
+
+extern bool
+str_fromCharCode_one_arg(JSContext* cx, HandleValue code, MutableHandleValue rval);
+
+extern bool
+str_fromCodePoint(JSContext* cx, unsigned argc, Value* vp);
+
+extern bool
+str_fromCodePoint_one_arg(JSContext* cx, HandleValue code, MutableHandleValue rval);
+
+/* String methods exposed so they can be installed in the self-hosting global. */
+
+extern bool
+str_includes(JSContext* cx, unsigned argc, Value* vp);
+
+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);
+
+extern bool
+str_contains(JSContext *cx, unsigned argc, Value *vp);
+
+extern bool
+str_endsWith(JSContext* cx, unsigned argc, Value* vp);
+
+extern bool
+str_trim(JSContext* cx, unsigned argc, Value* vp);
+
+extern bool
+str_trimLeft(JSContext* cx, unsigned argc, Value* vp);
+
+extern bool
+str_trimRight(JSContext* cx, unsigned argc, Value* vp);
+
+extern bool
+str_toLocaleLowerCase(JSContext* cx, unsigned argc, Value* vp);
+
+extern bool
+str_toLocaleUpperCase(JSContext* cx, unsigned argc, Value* vp);
+
+#if !EXPOSE_INTL_API
+extern bool
+str_localeCompare(JSContext* cx, unsigned argc, Value* vp);
+#else
+extern bool
+str_normalize(JSContext* cx, unsigned argc, Value* vp);
+#endif
+
+extern bool
+str_concat(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;
+}
+
+JSObject*
+str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep,
+ uint32_t limit);
+
+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);
+
+extern bool
+FlatStringMatch(JSContext* cx, unsigned argc, Value* vp);
+
+extern bool
+FlatStringSearch(JSContext* cx, unsigned argc, Value* vp);
+
+} /* namespace js */
+
+#endif /* jsstr_h */