blob: 45da6d3d2600a9c07f0820e6795e2aec08d2ce9e [file] [log] [blame]
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/inspector/string-16.h"
#if defined(STARBOARD)
#include "starboard/client_porting/poem/stdlib_poem.h"
#endif
#include <algorithm>
#include <cctype>
#include <cinttypes>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <string>
#include "src/base/platform/platform.h"
#include "src/inspector/v8-string-conversions.h"
#include "src/numbers/conversions.h"
namespace v8_inspector {
namespace {
bool isASCII(UChar c) { return !(c & ~0x7F); }
bool isSpaceOrNewLine(UChar c) {
return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9));
}
int64_t charactersToInteger(const UChar* characters, size_t length,
bool* ok = nullptr) {
std::vector<char> buffer;
buffer.reserve(length + 1);
for (size_t i = 0; i < length; ++i) {
if (!isASCII(characters[i])) {
if (ok) *ok = false;
return 0;
}
buffer.push_back(static_cast<char>(characters[i]));
}
buffer.push_back('\0');
char* endptr;
int64_t result = static_cast<int64_t>(strtoll(buffer.data(), &endptr, 10));
if (ok) *ok = !(*endptr);
return result;
}
} // namespace
String16::String16(const UChar* characters, size_t size)
: m_impl(characters, size) {}
String16::String16(const UChar* characters) : m_impl(characters) {}
String16::String16(const char* characters)
: String16(characters, std::strlen(characters)) {}
String16::String16(const char* characters, size_t size) {
m_impl.resize(size);
for (size_t i = 0; i < size; ++i) m_impl[i] = characters[i];
}
String16::String16(const std::basic_string<UChar>& impl) : m_impl(impl) {}
String16::String16(std::basic_string<UChar>&& impl) : m_impl(impl) {}
// static
String16 String16::fromInteger(int number) {
char arr[50];
v8::internal::Vector<char> buffer(arr, arraysize(arr));
return String16(IntToCString(number, buffer));
}
// static
String16 String16::fromInteger(size_t number) {
const size_t kBufferSize = 50;
char buffer[kBufferSize];
#if !defined(_WIN32) && !defined(_WIN64)
v8::base::OS::SNPrintF(buffer, kBufferSize, "%zu", number);
#else
v8::base::OS::SNPrintF(buffer, kBufferSize, "%Iu", number);
#endif
return String16(buffer);
}
// static
String16 String16::fromDouble(double number) {
char arr[50];
v8::internal::Vector<char> buffer(arr, arraysize(arr));
return String16(DoubleToCString(number, buffer));
}
// static
String16 String16::fromDouble(double number, int precision) {
std::unique_ptr<char[]> str(
v8::internal::DoubleToPrecisionCString(number, precision));
return String16(str.get());
}
int64_t String16::toInteger64(bool* ok) const {
return charactersToInteger(characters16(), length(), ok);
}
int String16::toInteger(bool* ok) const {
int64_t result = toInteger64(ok);
if (ok && *ok) {
*ok = result <= std::numeric_limits<int>::max() &&
result >= std::numeric_limits<int>::min();
}
return static_cast<int>(result);
}
String16 String16::stripWhiteSpace() const {
if (!length()) return String16();
size_t start = 0;
size_t end = length() - 1;
// skip white space from start
while (start <= end && isSpaceOrNewLine(characters16()[start])) ++start;
// only white space
if (start > end) return String16();
// skip white space from end
while (end && isSpaceOrNewLine(characters16()[end])) --end;
if (!start && end == length() - 1) return *this;
return String16(characters16() + start, end + 1 - start);
}
String16Builder::String16Builder() = default;
void String16Builder::append(const String16& s) {
m_buffer.insert(m_buffer.end(), s.characters16(),
s.characters16() + s.length());
}
void String16Builder::append(UChar c) { m_buffer.push_back(c); }
void String16Builder::append(char c) {
UChar u = c;
m_buffer.push_back(u);
}
void String16Builder::append(const UChar* characters, size_t length) {
m_buffer.insert(m_buffer.end(), characters, characters + length);
}
void String16Builder::append(const char* characters, size_t length) {
m_buffer.insert(m_buffer.end(), characters, characters + length);
}
void String16Builder::appendNumber(int number) {
constexpr int kBufferSize = 11;
char buffer[kBufferSize];
int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%d", number);
DCHECK_LE(0, chars);
m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
}
void String16Builder::appendNumber(size_t number) {
constexpr int kBufferSize = 20;
char buffer[kBufferSize];
#if !defined(_WIN32) && !defined(_WIN64)
int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%zu", number);
#else
int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%Iu", number);
#endif
DCHECK_LE(0, chars);
m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
}
void String16Builder::appendUnsignedAsHex(uint64_t number) {
constexpr int kBufferSize = 17;
char buffer[kBufferSize];
int chars =
v8::base::OS::SNPrintF(buffer, kBufferSize, "%016" PRIx64, number);
DCHECK_LE(0, chars);
m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
}
void String16Builder::appendUnsignedAsHex(uint32_t number) {
constexpr int kBufferSize = 9;
char buffer[kBufferSize];
int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%08" PRIx32, number);
DCHECK_LE(0, chars);
m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
}
String16 String16Builder::toString() {
return String16(m_buffer.data(), m_buffer.size());
}
void String16Builder::reserveCapacity(size_t capacity) {
m_buffer.reserve(capacity);
}
String16 String16::fromUTF8(const char* stringStart, size_t length) {
return String16(UTF8ToUTF16(stringStart, length));
}
String16 String16::fromUTF16LE(const UChar* stringStart, size_t length) {
#ifdef V8_TARGET_BIG_ENDIAN
// Need to flip the byte order on big endian machines.
String16Builder builder;
builder.reserveCapacity(length);
for (size_t i = 0; i < length; i++) {
const UChar utf16be_char =
stringStart[i] << 8 | (stringStart[i] >> 8 & 0x00FF);
builder.append(utf16be_char);
}
return builder.toString();
#else
// No need to do anything on little endian machines.
return String16(stringStart, length);
#endif // V8_TARGET_BIG_ENDIAN
}
std::string String16::utf8() const {
return UTF16ToUTF8(m_impl.data(), m_impl.size());
}
} // namespace v8_inspector