// This file is generated by Values_cpp.template.

// Copyright 2016 The Chromium 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 "Values.h"

#include "{{config.encoding_lib.header}}"

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}

namespace {

const char* const nullValueString = "null";
const char* const trueValueString = "true";
const char* const falseValueString = "false";

inline bool escapeChar(uint16_t c, StringBuilder* dst)
{
    switch (c) {
    case '\b': StringUtil::builderAppend(*dst, "\\b"); break;
    case '\f': StringUtil::builderAppend(*dst, "\\f"); break;
    case '\n': StringUtil::builderAppend(*dst, "\\n"); break;
    case '\r': StringUtil::builderAppend(*dst, "\\r"); break;
    case '\t': StringUtil::builderAppend(*dst, "\\t"); break;
    case '\\': StringUtil::builderAppend(*dst, "\\\\"); break;
    case '"': StringUtil::builderAppend(*dst, "\\\""); break;
    default:
        return false;
    }
    return true;
}

const char hexDigits[17] = "0123456789ABCDEF";

void appendUnsignedAsHex(uint16_t number, StringBuilder* dst)
{
    StringUtil::builderAppend(*dst, "\\u");
    for (size_t i = 0; i < 4; ++i) {
        uint16_t c = hexDigits[(number & 0xF000) >> 12];
        StringUtil::builderAppend(*dst, c);
        number <<= 4;
    }
}

template <typename Char>
void escapeStringForJSONInternal(const Char* str, unsigned len,
                                 StringBuilder* dst)
{
    for (unsigned i = 0; i < len; ++i) {
        Char c = str[i];
        if (escapeChar(c, dst))
            continue;
        if (c < 32 || c > 126) {
            appendUnsignedAsHex(c, dst);
        } else {
            StringUtil::builderAppend(*dst, c);
        }
    }
}

// When parsing CBOR, we limit recursion depth for objects and arrays
// to this constant.
static constexpr int kStackLimitValues = 1000;

using {{config.encoding_lib.namespace}}::Error;
using {{config.encoding_lib.namespace}}::Status;
using {{config.encoding_lib.namespace}}::span;
namespace cbor {
using {{config.encoding_lib.namespace}}::cbor::CBORTokenTag;
using {{config.encoding_lib.namespace}}::cbor::CBORTokenizer;
using {{config.encoding_lib.namespace}}::cbor::EncodeBinary;
using {{config.encoding_lib.namespace}}::cbor::EncodeDouble;
using {{config.encoding_lib.namespace}}::cbor::EncodeFalse;
using {{config.encoding_lib.namespace}}::cbor::EncodeFromLatin1;
using {{config.encoding_lib.namespace}}::cbor::EncodeFromUTF16;
using {{config.encoding_lib.namespace}}::cbor::EncodeIndefiniteLengthArrayStart;
using {{config.encoding_lib.namespace}}::cbor::EncodeIndefiniteLengthMapStart;
using {{config.encoding_lib.namespace}}::cbor::EncodeInt32;
using {{config.encoding_lib.namespace}}::cbor::EncodeNull;
using {{config.encoding_lib.namespace}}::cbor::EncodeStop;
using {{config.encoding_lib.namespace}}::cbor::EncodeString8;
using {{config.encoding_lib.namespace}}::cbor::EncodeTrue;
using {{config.encoding_lib.namespace}}::cbor::EnvelopeEncoder;
using {{config.encoding_lib.namespace}}::cbor::InitialByteForEnvelope;
}  // namespace cbor

// Below are three parsing routines for CBOR, which cover enough
// to roundtrip JSON messages.
std::unique_ptr<DictionaryValue> parseMap(int32_t stack_depth, cbor::CBORTokenizer* tokenizer);
std::unique_ptr<ListValue> parseArray(int32_t stack_depth, cbor::CBORTokenizer* tokenizer);
std::unique_ptr<Value> parseValue(int32_t stack_depth, cbor::CBORTokenizer* tokenizer);

// |bytes| must start with the indefinite length array byte, so basically,
// ParseArray may only be called after an indefinite length array has been
// detected.
std::unique_ptr<ListValue> parseArray(int32_t stack_depth, cbor::CBORTokenizer* tokenizer) {
  DCHECK(tokenizer->TokenTag() == cbor::CBORTokenTag::ARRAY_START);
  tokenizer->Next();
  auto list = ListValue::create();
  while (tokenizer->TokenTag() != cbor::CBORTokenTag::STOP) {
    // Error::CBOR_UNEXPECTED_EOF_IN_ARRAY
    if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE) return nullptr;
    if (tokenizer->TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr;
    // Parse value.
    auto value = parseValue(stack_depth, tokenizer);
    if (!value) return nullptr;
    list->pushValue(std::move(value));
  }
  tokenizer->Next();
  return list;
}

std::unique_ptr<Value> parseValue(
    int32_t stack_depth, cbor::CBORTokenizer* tokenizer) {
  // Error::CBOR_STACK_LIMIT_EXCEEDED
  if (stack_depth > kStackLimitValues) return nullptr;
  // Skip past the envelope to get to what's inside.
  if (tokenizer->TokenTag() == cbor::CBORTokenTag::ENVELOPE)
    tokenizer->EnterEnvelope();
  switch (tokenizer->TokenTag()) {
    case cbor::CBORTokenTag::ERROR_VALUE:
      return nullptr;
    case cbor::CBORTokenTag::DONE:
      // Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE
      return nullptr;
    case cbor::CBORTokenTag::TRUE_VALUE: {
      std::unique_ptr<Value> value = FundamentalValue::create(true);
      tokenizer->Next();
      return value;
    }
    case cbor::CBORTokenTag::FALSE_VALUE: {
      std::unique_ptr<Value> value = FundamentalValue::create(false);
      tokenizer->Next();
      return value;
    }
    case cbor::CBORTokenTag::NULL_VALUE: {
      std::unique_ptr<Value> value = FundamentalValue::null();
      tokenizer->Next();
      return value;
    }
    case cbor::CBORTokenTag::INT32: {
      std::unique_ptr<Value> value = FundamentalValue::create(tokenizer->GetInt32());
      tokenizer->Next();
      return value;
    }
    case cbor::CBORTokenTag::DOUBLE: {
      std::unique_ptr<Value> value = FundamentalValue::create(tokenizer->GetDouble());
      tokenizer->Next();
      return value;
    }
    case cbor::CBORTokenTag::STRING8: {
      span<uint8_t> str = tokenizer->GetString8();
      std::unique_ptr<Value> value =
          StringValue::create(StringUtil::fromUTF8(str.data(), str.size()));
      tokenizer->Next();
      return value;
    }
    case cbor::CBORTokenTag::STRING16: {
      span<uint8_t> wire = tokenizer->GetString16WireRep();
      DCHECK_EQ(wire.size() & 1, 0u);
      std::unique_ptr<Value> value = StringValue::create(StringUtil::fromUTF16LE(
          reinterpret_cast<const uint16_t*>(wire.data()), wire.size() / 2));
      tokenizer->Next();
      return value;
    }
    case cbor::CBORTokenTag::BINARY: {
      span<uint8_t> payload = tokenizer->GetBinary();
      tokenizer->Next();
      return BinaryValue::create(Binary::fromSpan(payload.data(), payload.size()));
    }
    case cbor::CBORTokenTag::MAP_START:
      return parseMap(stack_depth + 1, tokenizer);
    case cbor::CBORTokenTag::ARRAY_START:
      return parseArray(stack_depth + 1, tokenizer);
    default:
      // Error::CBOR_UNSUPPORTED_VALUE
      return nullptr;
  }
}

// |bytes| must start with the indefinite length array byte, so basically,
// ParseArray may only be called after an indefinite length array has been
// detected.
std::unique_ptr<DictionaryValue> parseMap(
    int32_t stack_depth, cbor::CBORTokenizer* tokenizer) {
  auto dict = DictionaryValue::create();
  tokenizer->Next();
  while (tokenizer->TokenTag() != cbor::CBORTokenTag::STOP) {
    if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE) {
      // Error::CBOR_UNEXPECTED_EOF_IN_MAP
      return nullptr;
    }
    if (tokenizer->TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr;
    // Parse key.
    String key;
    if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) {
      span<uint8_t> key_span = tokenizer->GetString8();
      key = StringUtil::fromUTF8(key_span.data(), key_span.size());
      tokenizer->Next();
    } else if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING16) {
      span<uint8_t> key_span = tokenizer->GetString16WireRep();
      if (key_span.size() & 1) return nullptr;  // UTF16 is 2 byte multiple.
      key = StringUtil::fromUTF16LE(
          reinterpret_cast<const uint16_t*>(key_span.data()),
          key_span.size() / 2);
      tokenizer->Next();
    } else {
      // Error::CBOR_INVALID_MAP_KEY
      return nullptr;
    }
    // Parse value.
    auto value = parseValue(stack_depth, tokenizer);
    if (!value) return nullptr;
    dict->setValue(key, std::move(value));
  }
  tokenizer->Next();
  return dict;
}

} // anonymous namespace

// static
std::unique_ptr<Value> Value::parseBinary(const uint8_t* data, size_t size) {
  span<uint8_t> bytes(data, size);

  // Error::CBOR_NO_INPUT
  if (bytes.empty()) return nullptr;

  // Error::CBOR_INVALID_START_BYTE
  if (bytes[0] != cbor::InitialByteForEnvelope()) return nullptr;

  cbor::CBORTokenizer tokenizer(bytes);
  if (tokenizer.TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr;

  // We checked for the envelope start byte above, so the tokenizer
  // must agree here, since it's not an error.
  DCHECK(tokenizer.TokenTag() == cbor::CBORTokenTag::ENVELOPE);
  tokenizer.EnterEnvelope();
  // Error::MAP_START_EXPECTED
  if (tokenizer.TokenTag() != cbor::CBORTokenTag::MAP_START) return nullptr;
  std::unique_ptr<Value> result = parseMap(/*stack_depth=*/1, &tokenizer);
  if (!result) return nullptr;
  if (tokenizer.TokenTag() == cbor::CBORTokenTag::DONE) return result;
  if (tokenizer.TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr;
  // Error::CBOR_TRAILING_JUNK
  return nullptr;
}

bool Value::asBoolean(bool*) const
{
    return false;
}

bool Value::asDouble(double*) const
{
    return false;
}

bool Value::asInteger(int*) const
{
    return false;
}

bool Value::asString(String*) const
{
    return false;
}

bool Value::asBinary(Binary*) const
{
    return false;
}

void Value::writeJSON(StringBuilder* output) const
{
    DCHECK(m_type == TypeNull);
    StringUtil::builderAppend(*output, nullValueString, 4);
}

void Value::writeBinary(std::vector<uint8_t>* bytes) const {
    DCHECK(m_type == TypeNull);
    bytes->push_back(cbor::EncodeNull());
}

std::unique_ptr<Value> Value::clone() const
{
    return Value::null();
}

String Value::toJSONString() const
{
    StringBuilder result;
    StringUtil::builderReserve(result, 512);
    writeJSON(&result);
    return StringUtil::builderToString(result);
}

String Value::serializeToJSON() {
    return toJSONString();
}

std::vector<uint8_t> Value::serializeToBinary() {
    std::vector<uint8_t> bytes;
    writeBinary(&bytes);
    return bytes;
}

bool FundamentalValue::asBoolean(bool* output) const
{
    if (type() != TypeBoolean)
        return false;
    *output = m_boolValue;
    return true;
}

bool FundamentalValue::asDouble(double* output) const
{
    if (type() == TypeDouble) {
        *output = m_doubleValue;
        return true;
    }
    if (type() == TypeInteger) {
        *output = m_integerValue;
        return true;
    }
    return false;
}

bool FundamentalValue::asInteger(int* output) const
{
    if (type() != TypeInteger)
        return false;
    *output = m_integerValue;
    return true;
}

void FundamentalValue::writeJSON(StringBuilder* output) const
{
    DCHECK(type() == TypeBoolean || type() == TypeInteger || type() == TypeDouble);
    if (type() == TypeBoolean) {
        if (m_boolValue)
            StringUtil::builderAppend(*output, trueValueString, 4);
        else
            StringUtil::builderAppend(*output, falseValueString, 5);
    } else if (type() == TypeDouble) {
        if (!std::isfinite(m_doubleValue)) {
            StringUtil::builderAppend(*output, nullValueString, 4);
            return;
        }
        StringUtil::builderAppend(*output, StringUtil::fromDouble(m_doubleValue));
    } else if (type() == TypeInteger) {
        StringUtil::builderAppend(*output, StringUtil::fromInteger(m_integerValue));
    }
}

void FundamentalValue::writeBinary(std::vector<uint8_t>* bytes) const {
    switch (type()) {
    case TypeDouble:
        cbor::EncodeDouble(m_doubleValue, bytes);
        return;
    case TypeInteger:
        cbor::EncodeInt32(m_integerValue, bytes);
        return;
    case TypeBoolean:
        bytes->push_back(m_boolValue ? cbor::EncodeTrue() : cbor::EncodeFalse());
        return;
    default:
        DCHECK(false);
    }
}

std::unique_ptr<Value> FundamentalValue::clone() const
{
    switch (type()) {
    case TypeDouble: return FundamentalValue::create(m_doubleValue);
    case TypeInteger: return FundamentalValue::create(m_integerValue);
    case TypeBoolean: return FundamentalValue::create(m_boolValue);
    default:
        DCHECK(false);
    }
    return nullptr;
}

bool StringValue::asString(String* output) const
{
    *output = m_stringValue;
    return true;
}

void StringValue::writeJSON(StringBuilder* output) const
{
    DCHECK(type() == TypeString);
    StringUtil::builderAppendQuotedString(*output, m_stringValue);
}

namespace {
// This routine distinguishes between the current encoding for a given
// string |s|, and calls encoding routines that will
// - Ensure that all ASCII strings end up being encoded as UTF8 in
//   the wire format - e.g., EncodeFromUTF16 will detect ASCII and
//   do the (trivial) transcode to STRING8 on the wire, but if it's
//   not ASCII it'll do STRING16.
// - Select a format that's cheap to convert to. E.g., we don't
//   have LATIN1 on the wire, so we call EncodeFromLatin1 which
//   transcodes to UTF8 if needed.
void EncodeString(const String& s, std::vector<uint8_t>* out) {
  if (StringUtil::CharacterCount(s) == 0) {
    cbor::EncodeString8(span<uint8_t>(nullptr, 0), out);  // Empty string.
  } else if (StringUtil::CharactersLatin1(s)) {
    cbor::EncodeFromLatin1(span<uint8_t>(StringUtil::CharactersLatin1(s),
		                         StringUtil::CharacterCount(s)),
                           out);
  } else if (StringUtil::CharactersUTF16(s)) {
    cbor::EncodeFromUTF16(span<uint16_t>(StringUtil::CharactersUTF16(s),
                                         StringUtil::CharacterCount(s)),
                          out);
  } else if (StringUtil::CharactersUTF8(s)) {
    cbor::EncodeString8(span<uint8_t>(StringUtil::CharactersUTF8(s),
                                      StringUtil::CharacterCount(s)),
                        out);
  }
}
}  // namespace

void StringValue::writeBinary(std::vector<uint8_t>* bytes) const {
  EncodeString(m_stringValue, bytes);
}

std::unique_ptr<Value> StringValue::clone() const
{
    return StringValue::create(m_stringValue);
}

bool BinaryValue::asBinary(Binary* output) const
{
    *output = m_binaryValue;
    return true;
}

void BinaryValue::writeJSON(StringBuilder* output) const
{
    DCHECK(type() == TypeBinary);
    StringUtil::builderAppendQuotedString(*output, m_binaryValue.toBase64());
}

void BinaryValue::writeBinary(std::vector<uint8_t>* bytes) const {
    cbor::EncodeBinary(span<uint8_t>(m_binaryValue.data(),
                                     m_binaryValue.size()), bytes);
}

std::unique_ptr<Value> BinaryValue::clone() const
{
    return BinaryValue::create(m_binaryValue);
}

void SerializedValue::writeJSON(StringBuilder* output) const
{
    DCHECK(type() == TypeSerialized);
    StringUtil::builderAppend(*output, m_serializedJSON);
}

void SerializedValue::writeBinary(std::vector<uint8_t>* output) const
{
    DCHECK(type() == TypeSerialized);
    output->insert(output->end(), m_serializedBinary.begin(), m_serializedBinary.end());
}

std::unique_ptr<Value> SerializedValue::clone() const
{
    return std::unique_ptr<SerializedValue>(new SerializedValue(m_serializedJSON, m_serializedBinary));
}

DictionaryValue::~DictionaryValue()
{
}

void DictionaryValue::setBoolean(const String& name, bool value)
{
    setValue(name, FundamentalValue::create(value));
}

void DictionaryValue::setInteger(const String& name, int value)
{
    setValue(name, FundamentalValue::create(value));
}

void DictionaryValue::setDouble(const String& name, double value)
{
    setValue(name, FundamentalValue::create(value));
}

void DictionaryValue::setString(const String& name, const String& value)
{
    setValue(name, StringValue::create(value));
}

void DictionaryValue::setValue(const String& name, std::unique_ptr<Value> value)
{
    set(name, value);
}

void DictionaryValue::setObject(const String& name, std::unique_ptr<DictionaryValue> value)
{
    set(name, value);
}

void DictionaryValue::setArray(const String& name, std::unique_ptr<ListValue> value)
{
    set(name, value);
}

bool DictionaryValue::getBoolean(const String& name, bool* output) const
{
    protocol::Value* value = get(name);
    if (!value)
        return false;
    return value->asBoolean(output);
}

bool DictionaryValue::getInteger(const String& name, int* output) const
{
    Value* value = get(name);
    if (!value)
        return false;
    return value->asInteger(output);
}

bool DictionaryValue::getDouble(const String& name, double* output) const
{
    Value* value = get(name);
    if (!value)
        return false;
    return value->asDouble(output);
}

bool DictionaryValue::getString(const String& name, String* output) const
{
    protocol::Value* value = get(name);
    if (!value)
        return false;
    return value->asString(output);
}

DictionaryValue* DictionaryValue::getObject(const String& name) const
{
    return DictionaryValue::cast(get(name));
}

protocol::ListValue* DictionaryValue::getArray(const String& name) const
{
    return ListValue::cast(get(name));
}

protocol::Value* DictionaryValue::get(const String& name) const
{
    Dictionary::const_iterator it = m_data.find(name);
    if (it == m_data.end())
        return nullptr;
    return it->second.get();
}

DictionaryValue::Entry DictionaryValue::at(size_t index) const
{
    const String key = m_order[index];
    return std::make_pair(key, m_data.find(key)->second.get());
}

bool DictionaryValue::booleanProperty(const String& name, bool defaultValue) const
{
    bool result = defaultValue;
    getBoolean(name, &result);
    return result;
}

int DictionaryValue::integerProperty(const String& name, int defaultValue) const
{
    int result = defaultValue;
    getInteger(name, &result);
    return result;
}

double DictionaryValue::doubleProperty(const String& name, double defaultValue) const
{
    double result = defaultValue;
    getDouble(name, &result);
    return result;
}

void DictionaryValue::remove(const String& name)
{
    m_data.erase(name);
    m_order.erase(std::remove(m_order.begin(), m_order.end(), name), m_order.end());
}

void DictionaryValue::writeJSON(StringBuilder* output) const
{
    StringUtil::builderAppend(*output, '{');
    for (size_t i = 0; i < m_order.size(); ++i) {
        Dictionary::const_iterator it = m_data.find(m_order[i]);
        CHECK(it != m_data.end());
        if (i)
            StringUtil::builderAppend(*output, ',');
        StringUtil::builderAppendQuotedString(*output, it->first);
        StringUtil::builderAppend(*output, ':');
        it->second->writeJSON(output);
    }
    StringUtil::builderAppend(*output, '}');
}

void DictionaryValue::writeBinary(std::vector<uint8_t>* bytes) const {
    cbor::EnvelopeEncoder encoder;
    encoder.EncodeStart(bytes);
    bytes->push_back(cbor::EncodeIndefiniteLengthMapStart());
    for (size_t i = 0; i < m_order.size(); ++i) {
        const String& key = m_order[i];
        Dictionary::const_iterator value = m_data.find(key);
        DCHECK(value != m_data.cend() && value->second);
        EncodeString(key, bytes);
        value->second->writeBinary(bytes);
    }
    bytes->push_back(cbor::EncodeStop());
    encoder.EncodeStop(bytes);
}

std::unique_ptr<Value> DictionaryValue::clone() const
{
    std::unique_ptr<DictionaryValue> result = DictionaryValue::create();
    for (size_t i = 0; i < m_order.size(); ++i) {
        String key = m_order[i];
        Dictionary::const_iterator value = m_data.find(key);
        DCHECK(value != m_data.cend() && value->second);
        result->setValue(key, value->second->clone());
    }
    return std::move(result);
}

DictionaryValue::DictionaryValue()
    : Value(TypeObject)
{
}

ListValue::~ListValue()
{
}

void ListValue::writeJSON(StringBuilder* output) const
{
    StringUtil::builderAppend(*output, '[');
    bool first = true;
    for (const std::unique_ptr<protocol::Value>& value : m_data) {
        if (!first)
            StringUtil::builderAppend(*output, ',');
        value->writeJSON(output);
        first = false;
    }
    StringUtil::builderAppend(*output, ']');
}

void ListValue::writeBinary(std::vector<uint8_t>* bytes) const {
    cbor::EnvelopeEncoder encoder;
    encoder.EncodeStart(bytes);
    bytes->push_back(cbor::EncodeIndefiniteLengthArrayStart());
    for (size_t i = 0; i < m_data.size(); ++i) {
        m_data[i]->writeBinary(bytes);
    }
    bytes->push_back(cbor::EncodeStop());
    encoder.EncodeStop(bytes);
}

std::unique_ptr<Value> ListValue::clone() const
{
    std::unique_ptr<ListValue> result = ListValue::create();
    for (const std::unique_ptr<protocol::Value>& value : m_data)
        result->pushValue(value->clone());
    return std::move(result);
}

ListValue::ListValue()
    : Value(TypeArray)
{
}

void ListValue::pushValue(std::unique_ptr<protocol::Value> value)
{
    DCHECK(value);
    m_data.push_back(std::move(value));
}

protocol::Value* ListValue::at(size_t index)
{
    DCHECK_LT(index, m_data.size());
    return m_data[index].get();
}

void escapeLatinStringForJSON(const uint8_t* str, unsigned len, StringBuilder* dst)
{
    escapeStringForJSONInternal<uint8_t>(str, len, dst);
}

void escapeWideStringForJSON(const uint16_t* str, unsigned len, StringBuilder* dst)
{
    escapeStringForJSONInternal<uint16_t>(str, len, dst);
}

{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
