// 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-util.h"

#include "src/base/platform/platform.h"
#include "src/conversions.h"
#include "src/inspector/protocol/Protocol.h"
#include "src/unicode-cache.h"

namespace v8_inspector {

v8::Local<v8::String> toV8String(v8::Isolate* isolate, const String16& string) {
  if (string.isEmpty()) return v8::String::Empty(isolate);
  DCHECK_GT(v8::String::kMaxLength, string.length());
  return v8::String::NewFromTwoByte(
             isolate, reinterpret_cast<const uint16_t*>(string.characters16()),
             v8::NewStringType::kNormal, static_cast<int>(string.length()))
      .ToLocalChecked();
}

v8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate,
                                             const String16& string) {
  if (string.isEmpty()) return v8::String::Empty(isolate);
  DCHECK_GT(v8::String::kMaxLength, string.length());
  return v8::String::NewFromTwoByte(
             isolate, reinterpret_cast<const uint16_t*>(string.characters16()),
             v8::NewStringType::kInternalized,
             static_cast<int>(string.length()))
      .ToLocalChecked();
}

v8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate,
                                             const char* str) {
  return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kInternalized)
      .ToLocalChecked();
}

v8::Local<v8::String> toV8String(v8::Isolate* isolate,
                                 const StringView& string) {
  if (!string.length()) return v8::String::Empty(isolate);
  DCHECK_GT(v8::String::kMaxLength, string.length());
  if (string.is8Bit())
    return v8::String::NewFromOneByte(
               isolate, reinterpret_cast<const uint8_t*>(string.characters8()),
               v8::NewStringType::kNormal, static_cast<int>(string.length()))
        .ToLocalChecked();
  return v8::String::NewFromTwoByte(
             isolate, reinterpret_cast<const uint16_t*>(string.characters16()),
             v8::NewStringType::kNormal, static_cast<int>(string.length()))
      .ToLocalChecked();
}

String16 toProtocolString(v8::Local<v8::String> value) {
  if (value.IsEmpty() || value->IsNullOrUndefined()) return String16();
  std::unique_ptr<UChar[]> buffer(new UChar[value->Length()]);
  value->Write(reinterpret_cast<uint16_t*>(buffer.get()), 0, value->Length());
  return String16(buffer.get(), value->Length());
}

String16 toProtocolStringWithTypeCheck(v8::Local<v8::Value> value) {
  if (value.IsEmpty() || !value->IsString()) return String16();
  return toProtocolString(value.As<v8::String>());
}

String16 toString16(const StringView& string) {
  if (!string.length()) return String16();
  if (string.is8Bit())
    return String16(reinterpret_cast<const char*>(string.characters8()),
                    string.length());
  return String16(reinterpret_cast<const UChar*>(string.characters16()),
                  string.length());
}

StringView toStringView(const String16& string) {
  if (string.isEmpty()) return StringView();
  return StringView(reinterpret_cast<const uint16_t*>(string.characters16()),
                    string.length());
}

bool stringViewStartsWith(const StringView& string, const char* prefix) {
  if (!string.length()) return !(*prefix);
  if (string.is8Bit()) {
    for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) {
      if (string.characters8()[i] != prefix[j]) return false;
    }
  } else {
    for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) {
      if (string.characters16()[i] != prefix[j]) return false;
    }
  }
  return true;
}

namespace protocol {

// static
double StringUtil::toDouble(const char* s, size_t len, bool* isOk) {
  v8::internal::UnicodeCache unicode_cache;
  int flags = v8::internal::ALLOW_HEX | v8::internal::ALLOW_OCTAL |
              v8::internal::ALLOW_BINARY;
  double result = StringToDouble(&unicode_cache, s, flags);
  *isOk = !std::isnan(result);
  return result;
}

std::unique_ptr<protocol::Value> StringUtil::parseJSON(
    const StringView& string) {
  if (!string.length()) return nullptr;
  if (string.is8Bit()) {
    return parseJSONCharacters(string.characters8(),
                               static_cast<int>(string.length()));
  }
  return parseJSONCharacters(string.characters16(),
                             static_cast<int>(string.length()));
}

std::unique_ptr<protocol::Value> StringUtil::parseJSON(const String16& string) {
  if (!string.length()) return nullptr;
  return parseJSONCharacters(string.characters16(),
                             static_cast<int>(string.length()));
}

// static
void StringUtil::builderAppendQuotedString(StringBuilder& builder,
                                           const String& str) {
  builder.append('"');
  if (!str.isEmpty()) {
    escapeWideStringForJSON(
        reinterpret_cast<const uint16_t*>(str.characters16()),
        static_cast<int>(str.length()), &builder);
  }
  builder.append('"');
}

}  // namespace protocol

// static
std::unique_ptr<StringBuffer> StringBuffer::create(const StringView& string) {
  String16 owner = toString16(string);
  return StringBufferImpl::adopt(owner);
}

// static
std::unique_ptr<StringBufferImpl> StringBufferImpl::adopt(String16& string) {
  return std::unique_ptr<StringBufferImpl>(new StringBufferImpl(string));
}

StringBufferImpl::StringBufferImpl(String16& string) {
  m_owner.swap(string);
  m_string = toStringView(m_owner);
}

String16 debuggerIdToString(const std::pair<int64_t, int64_t>& debuggerId) {
  const size_t kBufferSize = 35;

  char buffer[kBufferSize];
  v8::base::OS::SNPrintF(buffer, kBufferSize, "(%08" PRIX64 "%08" PRIX64 ")",
                         debuggerId.first, debuggerId.second);
  return String16(buffer);
}

String16 stackTraceIdToString(uintptr_t id) {
  String16Builder builder;
  builder.appendNumber(static_cast<size_t>(id));
  return builder.toString();
}

}  // namespace v8_inspector
