|
Packit |
f0b94e |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
Packit |
f0b94e |
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
|
Packit |
f0b94e |
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
f0b94e |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
f0b94e |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#ifndef util_Text_h
|
|
Packit |
f0b94e |
#define util_Text_h
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "mozilla/Assertions.h"
|
|
Packit |
f0b94e |
#include "mozilla/Attributes.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include <ctype.h>
|
|
Packit |
f0b94e |
#include <stddef.h>
|
|
Packit |
f0b94e |
#include <stdint.h>
|
|
Packit |
f0b94e |
#include <stdio.h>
|
|
Packit |
f0b94e |
#include <string>
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "jsutil.h"
|
|
Packit |
f0b94e |
#include "NamespaceImports.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "js/Utility.h"
|
|
Packit |
f0b94e |
#include "util/Unicode.h"
|
|
Packit |
f0b94e |
#include "vm/Printer.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class JSLinearString;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*
|
|
Packit |
f0b94e |
* Shorthands for ASCII (7-bit) decimal and hex conversion.
|
|
Packit |
f0b94e |
* Manually inline isdigit and isxdigit for performance; MSVC doesn't do this
|
|
Packit |
f0b94e |
* for us.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
#define JS7_ISDEC(c) ((((unsigned)(c)) - '0') <= 9)
|
|
Packit |
f0b94e |
#define JS7_ISA2F(c) \
|
|
Packit |
f0b94e |
((((((unsigned)(c)) - 'a') <= 5) || (((unsigned)(c)) - 'A') <= 5))
|
|
Packit |
f0b94e |
#define JS7_UNDEC(c) ((c) - '0')
|
|
Packit |
f0b94e |
#define JS7_ISOCT(c) ((((unsigned)(c)) - '0') <= 7)
|
|
Packit |
f0b94e |
#define JS7_UNOCT(c) (JS7_UNDEC(c))
|
|
Packit |
f0b94e |
#define JS7_ISHEX(c) ((c) < 128 && (JS7_ISDEC(c) || JS7_ISA2F(c)))
|
|
Packit |
f0b94e |
#define JS7_UNHEX(c) \
|
|
Packit |
f0b94e |
(unsigned)(JS7_ISDEC(c) ? (c) - '0' : 10 + tolower(c) - 'a')
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
static MOZ_ALWAYS_INLINE size_t js_strlen(const char16_t* s) {
|
|
Packit |
f0b94e |
return std::char_traits<char16_t>::length(s);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <typename CharT>
|
|
Packit |
f0b94e |
extern const CharT* js_strchr_limit(const CharT* s, char16_t c,
|
|
Packit |
f0b94e |
const CharT* limit);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
extern int32_t js_fputs(const char16_t* s, FILE* f);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace js {
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class StringBuffer;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <typename Char1, typename Char2>
|
|
Packit |
f0b94e |
inline bool EqualChars(const Char1* s1, const Char2* s2, size_t len);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <typename Char1>
|
|
Packit |
f0b94e |
inline bool EqualChars(const Char1* s1, const Char1* s2, size_t len) {
|
|
Packit |
f0b94e |
return mozilla::PodEqual(s1, s2, len);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <typename Char1, typename Char2>
|
|
Packit |
f0b94e |
inline bool EqualChars(const Char1* s1, const Char2* s2, size_t len) {
|
|
Packit |
f0b94e |
for (const Char1 *s1end = s1 + len; s1 < s1end; s1++, s2++) {
|
|
Packit |
f0b94e |
if (*s1 != *s2) return false;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Return less than, equal to, or greater than zero depending on whether
|
|
Packit |
f0b94e |
// s1 is less than, equal to, or greater than s2.
|
|
Packit |
f0b94e |
template <typename Char1, typename Char2>
|
|
Packit |
f0b94e |
inline int32_t CompareChars(const Char1* s1, size_t len1, const Char2* s2,
|
|
Packit |
f0b94e |
size_t len2) {
|
|
Packit |
f0b94e |
size_t n = Min(len1, len2);
|
|
Packit |
f0b94e |
for (size_t i = 0; i < n; i++) {
|
|
Packit |
f0b94e |
if (int32_t cmp = s1[i] - s2[i]) return cmp;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return int32_t(len1 - len2);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Return s advanced past any Unicode white space characters.
|
|
Packit |
f0b94e |
template <typename CharT>
|
|
Packit |
f0b94e |
static inline const CharT* SkipSpace(const CharT* s, const CharT* end) {
|
|
Packit |
f0b94e |
MOZ_ASSERT(s <= end);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
while (s < end && unicode::IsSpace(*s)) s++;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return s;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
extern UniqueChars DuplicateString(JSContext* cx, const char* s);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
extern UniqueTwoByteChars DuplicateString(JSContext* cx, const char16_t* s);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*
|
|
Packit |
f0b94e |
* These variants do not report OOMs, you must arrange for OOMs to be reported
|
|
Packit |
f0b94e |
* yourself.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
extern UniqueChars DuplicateString(const char* s);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
extern UniqueChars DuplicateString(const char* s, size_t n);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
extern UniqueTwoByteChars DuplicateString(const char16_t* s);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
extern UniqueTwoByteChars DuplicateString(const char16_t* s, size_t n);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*
|
|
Packit |
f0b94e |
* Inflate bytes in ASCII encoding to char16_t code units. Return null on error,
|
|
Packit |
f0b94e |
* otherwise return the char16_t buffer that was malloc'ed. A null char is
|
|
Packit |
f0b94e |
* appended.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
extern char16_t* InflateString(JSContext* cx, const char* bytes, size_t length);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*
|
|
Packit |
f0b94e |
* Inflate bytes to JS chars in an existing buffer. 'dst' must be large
|
|
Packit |
f0b94e |
* enough for 'srclen' char16_t code units. The buffer is NOT null-terminated.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
inline void CopyAndInflateChars(char16_t* dst, const char* src, size_t srclen) {
|
|
Packit |
f0b94e |
for (size_t i = 0; i < srclen; i++) dst[i] = (unsigned char)src[i];
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
inline void CopyAndInflateChars(char16_t* dst, const JS::Latin1Char* src,
|
|
Packit |
f0b94e |
size_t srclen) {
|
|
Packit |
f0b94e |
for (size_t i = 0; i < srclen; i++) dst[i] = src[i];
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*
|
|
Packit |
f0b94e |
* Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
|
|
Packit |
f0b94e |
* 'length chars. The buffer is NOT null-terminated. The destination length
|
|
Packit |
f0b94e |
* must to be initialized with the buffer size and will contain on return the
|
|
Packit |
f0b94e |
* number of copied bytes.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
template <typename CharT>
|
|
Packit |
f0b94e |
extern bool DeflateStringToBuffer(JSContext* maybecx, const CharT* chars,
|
|
Packit |
f0b94e |
size_t charsLength, char* bytes,
|
|
Packit |
f0b94e |
size_t* length);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*
|
|
Packit |
f0b94e |
* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
|
|
Packit |
f0b94e |
* least 4 bytes long. Return the number of UTF-8 bytes of data written.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
extern uint32_t OneUcs4ToUtf8Char(uint8_t* utf8Buffer, uint32_t ucs4Char);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
extern size_t PutEscapedStringImpl(char* buffer, size_t size,
|
|
Packit |
f0b94e |
GenericPrinter* out, JSLinearString* str,
|
|
Packit |
f0b94e |
uint32_t quote);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <typename CharT>
|
|
Packit |
f0b94e |
extern size_t PutEscapedStringImpl(char* buffer, size_t bufferSize,
|
|
Packit |
f0b94e |
GenericPrinter* out, const CharT* chars,
|
|
Packit |
f0b94e |
size_t length, uint32_t quote);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*
|
|
Packit |
f0b94e |
* Write str into buffer escaping any non-printable or non-ASCII character
|
|
Packit |
f0b94e |
* using \escapes for JS string literals.
|
|
Packit |
f0b94e |
* Guarantees that a NUL is at the end of the buffer unless size is 0. Returns
|
|
Packit |
f0b94e |
* the length of the written output, NOT including the NUL. Thus, a return
|
|
Packit |
f0b94e |
* value of size or more means that the output was truncated. If buffer
|
|
Packit |
f0b94e |
* is null, just returns the length of the output. If quote is not 0, it must
|
|
Packit |
f0b94e |
* be a single or double quote character that will quote the output.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
inline size_t PutEscapedString(char* buffer, size_t size, JSLinearString* str,
|
|
Packit |
f0b94e |
uint32_t quote) {
|
|
Packit |
f0b94e |
size_t n = PutEscapedStringImpl(buffer, size, nullptr, str, quote);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* PutEscapedStringImpl can only fail with a file. */
|
|
Packit |
f0b94e |
MOZ_ASSERT(n != size_t(-1));
|
|
Packit |
f0b94e |
return n;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <typename CharT>
|
|
Packit |
f0b94e |
inline size_t PutEscapedString(char* buffer, size_t bufferSize,
|
|
Packit |
f0b94e |
const CharT* chars, size_t length,
|
|
Packit |
f0b94e |
uint32_t quote) {
|
|
Packit |
f0b94e |
size_t n =
|
|
Packit |
f0b94e |
PutEscapedStringImpl(buffer, bufferSize, nullptr, chars, length, quote);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* PutEscapedStringImpl can only fail with a file. */
|
|
Packit |
f0b94e |
MOZ_ASSERT(n != size_t(-1));
|
|
Packit |
f0b94e |
return n;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
inline bool EscapedStringPrinter(GenericPrinter& out, JSLinearString* str,
|
|
Packit |
f0b94e |
uint32_t quote) {
|
|
Packit |
f0b94e |
return PutEscapedStringImpl(nullptr, 0, &out, str, quote) != size_t(-1);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
inline bool EscapedStringPrinter(GenericPrinter& out, const char* chars,
|
|
Packit |
f0b94e |
size_t length, uint32_t quote) {
|
|
Packit |
f0b94e |
return PutEscapedStringImpl(nullptr, 0, &out, chars, length, quote) !=
|
|
Packit |
f0b94e |
size_t(-1);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*
|
|
Packit |
f0b94e |
* Write str into file escaping any non-printable or non-ASCII character.
|
|
Packit |
f0b94e |
* If quote is not 0, it must be a single or double quote character that
|
|
Packit |
f0b94e |
* will quote the output.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
inline bool FileEscapedString(FILE* fp, JSLinearString* str, uint32_t quote) {
|
|
Packit |
f0b94e |
Fprinter out(fp);
|
|
Packit |
f0b94e |
bool res = EscapedStringPrinter(out, str, quote);
|
|
Packit |
f0b94e |
out.finish();
|
|
Packit |
f0b94e |
return res;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
inline bool FileEscapedString(FILE* fp, const char* chars, size_t length,
|
|
Packit |
f0b94e |
uint32_t quote) {
|
|
Packit |
f0b94e |
Fprinter out(fp);
|
|
Packit |
f0b94e |
bool res = EscapedStringPrinter(out, chars, length, quote);
|
|
Packit |
f0b94e |
out.finish();
|
|
Packit |
f0b94e |
return res;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
bool EncodeURI(JSContext* cx, StringBuffer& sb, const char* chars,
|
|
Packit |
f0b94e |
size_t length);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
} // namespace js
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#endif // util_Text_h
|