// 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/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()));
}

}  // 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);
}

}  // namespace v8_inspector
