// 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 {
using {{config.crdtp.namespace}}::Status;
using {{config.crdtp.namespace}}::ParserHandler;
using {{config.crdtp.namespace}}::span;
namespace cbor {
using {{config.crdtp.namespace}}::cbor::ParseCBOR;
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

// Uses the parsing events received from driver of |ParserHandler|
// (e.g. cbor::ParseCBOR) into a protocol::Value instance.
class ValueParserHandler : public ParserHandler {
 public:
   // Provides the parsed protocol::Value.
   std::unique_ptr<Value> ReleaseRoot() { return std::move(root_); }

   // The first parsing error encountered; |status().ok()| is the default.
   Status status() const { return status_; }

 private:
  //
  // Implementation of  ParserHandler.
  //
  void HandleMapBegin() override {
    if (!status_.ok()) return;
    std::unique_ptr<DictionaryValue> dict = DictionaryValue::create();
    DictionaryValue* dict_ptr = dict.get();
    AddValueToParent(std::move(dict));
    stack_.emplace_back(dict_ptr);
  }

  void HandleMapEnd() override {
    if (!status_.ok()) return;
    DCHECK(!stack_.empty());
    DCHECK(stack_.back().is_dict);
    stack_.pop_back();
  }

  void HandleArrayBegin() override {
    if (!status_.ok()) return;
    std::unique_ptr<ListValue> list = ListValue::create();
    ListValue* list_ptr = list.get();
    AddValueToParent(std::move(list));
    stack_.emplace_back(list_ptr);
  }

  void HandleArrayEnd() override {
    if (!status_.ok()) return;
    DCHECK(!stack_.empty());
    DCHECK(!stack_.back().is_dict);
    stack_.pop_back();
  }

  void HandleString8(span<uint8_t> chars) override {
    AddStringToParent(StringUtil::fromUTF8(chars.data(), chars.size()));
  }

  void HandleString16(span<uint16_t> chars) override {
    AddStringToParent(
        StringUtil::fromUTF16LE(chars.data(), chars.size()));
  }

  void HandleBinary(span<uint8_t> bytes) override {
    AddValueToParent(
        BinaryValue::create(Binary::fromSpan(bytes.data(), bytes.size())));
  }

  void HandleDouble(double value) override {
    AddValueToParent(FundamentalValue::create(value));
  }

  void HandleInt32(int32_t value) override {
    AddValueToParent(FundamentalValue::create(value));
  }

  void HandleBool(bool value) override {
    AddValueToParent(FundamentalValue::create(value));
  }

  void HandleNull() override {
    AddValueToParent(Value::null());
  }

  void HandleError(Status error) override {
    status_ = error;
  }

  //
  // Adding strings and values to the parent value.
  // Strings are handled separately because they can be keys for
  // dictionary values.
  //
  void AddStringToParent(String str) {
    if (!status_.ok()) return;
    if (!root_) {
      DCHECK(!key_is_pending_);
      root_ = StringValue::create(str);
    } else if (stack_.back().is_dict) {
      // If we already have a pending key, then this is the value of the
      // key/value pair. Otherwise, it's the new pending key.
      if (key_is_pending_) {
        stack_.back().dict->setString(pending_key_, str);
        key_is_pending_ = false;
      } else {
        pending_key_ = std::move(str);
        key_is_pending_ = true;
      }
    } else {  // Top of the stack is a list.
      DCHECK(!key_is_pending_);
      stack_.back().list->pushValue(StringValue::create(str));
    }
  }

  void AddValueToParent(std::unique_ptr<Value> value) {
    if (!status_.ok()) return;
    if (!root_) {
      DCHECK(!key_is_pending_);
      root_ = std::move(value);
    } else if (stack_.back().is_dict) {
      DCHECK(key_is_pending_);
      stack_.back().dict->setValue(pending_key_, std::move(value));
      key_is_pending_ = false;
    } else {  // Top of the stack is a list.
      DCHECK(!key_is_pending_);
      stack_.back().list->pushValue(std::move(value));
    }
  }

  // |status_.ok()| is the default; if we receive an error event
  // we keep the first one and stop modifying any other state.
  Status status_;

  // The root of the parsed protocol::Value tree.
  std::unique_ptr<Value> root_;

  // If root_ is a list or a dictionary, this stack keeps track of
  // the container we're currently parsing as well as its ancestors.
  struct ContainerState {
    ContainerState(DictionaryValue* dict) : is_dict(true), dict(dict) {}
    ContainerState(ListValue* list) : is_dict(false), list(list) {}

    bool is_dict;
    union {
      DictionaryValue* dict;
      ListValue* list;
    };
  };
  std::vector<ContainerState> stack_;

  // For maps, keys and values are alternating events, so we keep the
  // key around and process it when the value arrives.
  bool key_is_pending_ = false;
  String pending_key_;
};
} // anonymous namespace

// static
std::unique_ptr<Value> Value::parseBinary(const uint8_t* data, size_t size) {
  ValueParserHandler handler;
  cbor::ParseCBOR(span<uint8_t>(data, size), &handler);
  // TODO(johannes): We have decent error info in handler.status(); provide
  // a richer interface that makes this available to client code.
  if (handler.status().ok())
    return handler.ReleaseRoot();
  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::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();
}

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::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;
}

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


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::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::unique_ptr<Value>(result.release());
}

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

ListValue::~ListValue()
{
}

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::unique_ptr<Value>(result.release());
}

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

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