chromium/third_party/inspector_protocol/lib/Values_cpp.template

// This file is generated by Values_cpp.template.

// Copyright 2016 The Chromium Authors
// 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;
}  // 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 result;
}

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

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