// 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"

#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
