// 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.crdtp.dir}}/cbor.h"

{% 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.crdtp.namespace}}::Error;
using {{config.crdtp.namespace}}::Status;
using {{config.crdtp.namespace}}::span;
namespace cbor {
using {{config.crdtp.namespace}}::cbor::CBORTokenTag;
using {{config.crdtp.namespace}}::cbor::CBORTokenizer;
using {{config.crdtp.namespace}}::cbor::EncodeBinary;
using {{config.crdtp.namespace}}::cbor::EncodeDouble;
using {{config.crdtp.namespace}}::cbor::EncodeFalse;
using {{config.crdtp.namespace}}::cbor::EncodeFromLatin1;
using {{config.crdtp.namespace}}::cbor::EncodeFromUTF16;
using {{config.crdtp.namespace}}::cbor::EncodeIndefiniteLengthArrayStart;
using {{config.crdtp.namespace}}::cbor::EncodeIndefiniteLengthMapStart;
using {{config.crdtp.namespace}}::cbor::EncodeInt32;
using {{config.crdtp.namespace}}::cbor::EncodeNull;
using {{config.crdtp.namespace}}::cbor::EncodeStop;
using {{config.crdtp.namespace}}::cbor::EncodeString8;
using {{config.crdtp.namespace}}::cbor::EncodeTrue;
using {{config.crdtp.namespace}}::cbor::EnvelopeEncoder;
using {{config.crdtp.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::AppendSerialized(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);
}

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

std::vector<uint8_t> SerializedValue::TakeSerialized() && {
    return std::move(m_serializedBinary);
}

void SerializedValue::AppendSerialized(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::AppendSerialized(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->AppendSerialized(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::AppendSerialized(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]->AppendSerialized(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 %}
