<commit_before>#pragma once

//mandala
#include "types.hpp"
#include "vertex_buffer.hpp"
#include "index_buffer.hpp"
#include "gpu_program_mgr.hpp"
#include "basic_gpu_program.hpp"
#include "rectangle.hpp"
#include "line.hpp"

#include "gpu_buffer_mgr.hpp"

namespace mandala
{
    template<typename T>
    void render_rectangle(const mat4_t& world_matrix, const mat4_t& view_projection_matrix, const details::rectangle_t<T>& rectangle, bool is_filled = false)
    {
        typedef vertex_buffer_t<basic_gpu_vertex_t> vertex_buffer_type;
        typedef index_buffer_t<uint8_t> index_buffer_type;

        static boost::weak_ptr<vertex_buffer_type> vertex_buffer;
        static boost::weak_ptr<index_buffer_type> index_buffer;

        if (vertex_buffer.expired())
        {
            vertex_buffer = gpu_buffers.make<vertex_buffer_type>();
            auto vertices = {
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 0, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 0, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 1, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 1, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type())
            };
            vertex_buffer.lock()->data(vertices, gpu_t::buffer_usage_e::dynamic_draw);
        }

        if (index_buffer.expired())
        {
            index_buffer = gpu_buffers.make<index_buffer_type>();
            index_buffer.lock()->data({ 0, 1, 2, 3 }, gpu_t::buffer_usage_e::static_draw);
        }

        gpu.buffers.push(gpu_t::buffer_target_e::array, vertex_buffer.lock());
        gpu.buffers.push(gpu_t::buffer_target_e::element_array, index_buffer.lock());

        const auto gpu_program = gpu_programs.get<basic_gpu_program_t>();

        gpu.programs.push(gpu_program);

        gpu.set_uniform("world_matrix", world_matrix * glm::translate(rectangle.x, rectangle.y, T(0)) * glm::scale(rectangle.width, rectangle.height, T(0)));
        gpu.set_uniform("view_projection_matrix", view_projection_matrix);

        gpu.draw_elements(is_filled ? gpu_t::primitive_type_e::triangle_fan : gpu_t::primitive_type_e::line_loop, 4, index_buffer_type::data_type, 0);

        gpu.programs.pop();

        gpu.buffers.pop(gpu_t::buffer_target_e::element_array);
        gpu.buffers.pop(gpu_t::buffer_target_e::array);
    }

    template<typename T>
    void render_aabb(const mat4_t& world_matrix, const mat4_t& view_projection_matrix, const details::aabb3_t<T>& aabb)
    {
        typedef vertex_buffer_t<basic_gpu_vertex_t> vertex_buffer_type;
        typedef index_buffer_t<uint8_t> index_buffer_type;

        static boost::weak_ptr<vertex_buffer_type> vertex_buffer;
        static boost::weak_ptr<index_buffer_type> index_buffer;

        if (vertex_buffer.expired())
        {
            vertex_buffer = gpu_buffers.make<vertex_buffer_type>();
            auto vertices = {
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 0, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 0, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 1, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 1, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 0, 1), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 0, 1), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 1, 1), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 1, 1), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type())
            };
            vertex_buffer.lock()->data(vertices, gpu_t::buffer_usage_e::dynamic_draw);
        }

        if (index_buffer.expired())
        {
            index_buffer = gpu_buffers.make<index_buffer_type>();
            index_buffer.lock()->data({ 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 5, 2, 6, 3, 7, 4, 5, 5, 6, 6, 7, 7, 4 }, gpu_t::buffer_usage_e::static_draw);
        }

        gpu.buffers.push(gpu_t::buffer_target_e::array, vertex_buffer.lock());
        gpu.buffers.push(gpu_t::buffer_target_e::element_array, index_buffer.lock());

        const auto gpu_program = gpu_programs.get<basic_gpu_program_t>();

        gpu.programs.push(gpu_program);

        gpu.set_uniform("world_matrix", world_matrix * glm::translate(aabb.min) * glm::scale(aabb.size()));
        gpu.set_uniform("view_projection_matrix", view_projection_matrix);

        gpu.draw_elements(gpu_t::primitive_type_e::lines, 24, index_buffer_type::data_type, 0);

        gpu.programs.pop();

        gpu.buffers.pop(gpu_t::buffer_target_e::element_array);
        gpu.buffers.pop(gpu_t::buffer_target_e::array);
    }
}<commit_msg>quick and dirty sphere renderer<commit_after>#pragma once

//mandala
#include "types.hpp"
#include "vertex_buffer.hpp"
#include "index_buffer.hpp"
#include "gpu_program_mgr.hpp"
#include "basic_gpu_program.hpp"
#include "rectangle.hpp"
#include "line.hpp"
#include "sphere.hpp"

#include "gpu_buffer_mgr.hpp"

namespace mandala
{
    template<typename T>
    void render_rectangle(const mat4_t& world_matrix, const mat4_t& view_projection_matrix, const details::rectangle_t<T>& rectangle, bool is_filled = false)
    {
        typedef vertex_buffer_t<basic_gpu_vertex_t> vertex_buffer_type;
        typedef index_buffer_t<uint8_t> index_buffer_type;

        static boost::weak_ptr<vertex_buffer_type> vertex_buffer;
        static boost::weak_ptr<index_buffer_type> index_buffer;

        if (vertex_buffer.expired())
        {
            vertex_buffer = gpu_buffers.make<vertex_buffer_type>();
            auto vertices = {
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 0, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 0, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 1, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 1, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type())
            };
            vertex_buffer.lock()->data(vertices, gpu_t::buffer_usage_e::dynamic_draw);
        }

        if (index_buffer.expired())
        {
            index_buffer = gpu_buffers.make<index_buffer_type>();
            index_buffer.lock()->data({ 0, 1, 2, 3 }, gpu_t::buffer_usage_e::static_draw);
        }

        gpu.buffers.push(gpu_t::buffer_target_e::array, vertex_buffer.lock());
        gpu.buffers.push(gpu_t::buffer_target_e::element_array, index_buffer.lock());

        const auto gpu_program = gpu_programs.get<basic_gpu_program_t>();

        gpu.programs.push(gpu_program);

        gpu.set_uniform("world_matrix", world_matrix * glm::translate(rectangle.x, rectangle.y, T(0)) * glm::scale(rectangle.width, rectangle.height, T(0)));
        gpu.set_uniform("view_projection_matrix", view_projection_matrix);

        gpu.draw_elements(is_filled ? gpu_t::primitive_type_e::triangle_fan : gpu_t::primitive_type_e::line_loop, 4, index_buffer_type::data_type, 0);

        gpu.programs.pop();

        gpu.buffers.pop(gpu_t::buffer_target_e::element_array);
        gpu.buffers.pop(gpu_t::buffer_target_e::array);
    }

    template<typename T>
    void render_aabb(const mat4_t& world_matrix, const mat4_t& view_projection_matrix, const details::aabb3_t<T>& aabb)
    {
        typedef vertex_buffer_t<basic_gpu_vertex_t> vertex_buffer_type;
        typedef index_buffer_t<uint8_t> index_buffer_type;

        static boost::weak_ptr<vertex_buffer_type> vertex_buffer;
        static boost::weak_ptr<index_buffer_type> index_buffer;

        if (vertex_buffer.expired())
        {
            vertex_buffer = gpu_buffers.make<vertex_buffer_type>();
            auto vertices = {
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 0, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 0, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 1, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 1, 0), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 0, 1), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 0, 1), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(1, 1, 1), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type()),
                basic_gpu_vertex_t(basic_gpu_vertex_t::location_type(0, 1, 1), basic_gpu_vertex_t::color_type(1), basic_gpu_vertex_t::texcoord_type())
            };
            vertex_buffer.lock()->data(vertices, gpu_t::buffer_usage_e::dynamic_draw);
        }

        if (index_buffer.expired())
        {
            index_buffer = gpu_buffers.make<index_buffer_type>();
            index_buffer.lock()->data({ 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 5, 2, 6, 3, 7, 4, 5, 5, 6, 6, 7, 7, 4 }, gpu_t::buffer_usage_e::static_draw);
        }

        gpu.buffers.push(gpu_t::buffer_target_e::array, vertex_buffer.lock());
        gpu.buffers.push(gpu_t::buffer_target_e::element_array, index_buffer.lock());

        const auto gpu_program = gpu_programs.get<basic_gpu_program_t>();

        gpu.programs.push(gpu_program);

        gpu.set_uniform("world_matrix", world_matrix * glm::translate(aabb.min) * glm::scale(aabb.size()));
        gpu.set_uniform("view_projection_matrix", view_projection_matrix);

        gpu.draw_elements(gpu_t::primitive_type_e::lines, 24, index_buffer_type::data_type, 0);

        gpu.programs.pop();

        gpu.buffers.pop(gpu_t::buffer_target_e::element_array);
        gpu.buffers.pop(gpu_t::buffer_target_e::array);
    }

    template<typename T>
    void render_sphere(const mat4_t& world_matrix, const mat4_t& view_projection_matrix, const details::sphere_t<T>& sphere)
    {
        typedef vertex_buffer_t<basic_gpu_vertex_t> vertex_buffer_type;
        typedef index_buffer_t<uint8_t> index_buffer_type;

        static boost::weak_ptr<vertex_buffer_type> vertex_buffer;
        static boost::weak_ptr<index_buffer_type> index_buffer;

        const size_t SPHERE_SIDES = 32;

        if (vertex_buffer.expired())
        {
            vertex_buffer = gpu_buffers.make<vertex_buffer_type>();

            std::vector<basic_gpu_vertex_t> vertices;
            vertices.reserve(SPHERE_SIDES);

            for (auto i = 0; i < SPHERE_SIDES; ++i)
            {
                auto sigma = static_cast<float32_t>(i) / SPHERE_SIDES * glm::pi<float32_t>() * 2;

                vertices.emplace_back(basic_gpu_vertex_t::location_type(glm::sin(sigma), glm::cos(sigma), 0), basic_gpu_vertex_t::color_type(0, 0, 1, 1), basic_gpu_vertex_t::texcoord_type());
            }

            for (auto i = 0; i < SPHERE_SIDES; ++i)
            {
                auto sigma = static_cast<float32_t>(i) / SPHERE_SIDES * glm::pi<float32_t>() * 2;

                vertices.emplace_back(basic_gpu_vertex_t::location_type(0, glm::sin(sigma), glm::cos(sigma)), basic_gpu_vertex_t::color_type(1, 0, 0, 1), basic_gpu_vertex_t::texcoord_type());
            }

            for (auto i = 0; i < SPHERE_SIDES; ++i)
            {
                auto sigma = static_cast<float32_t>(i) / SPHERE_SIDES * glm::pi<float32_t>() * 2;

                vertices.emplace_back(basic_gpu_vertex_t::location_type(glm::cos(sigma), 0, glm::sin(sigma)), basic_gpu_vertex_t::color_type(0, 1, 0, 1), basic_gpu_vertex_t::texcoord_type());
            }

            vertex_buffer.lock()->data(vertices, gpu_t::buffer_usage_e::dynamic_draw);
        }

        if (index_buffer.expired())
        {
            index_buffer = gpu_buffers.make<index_buffer_type>();

            std::vector<uint8_t> indices;
            indices.reserve(SPHERE_SIDES * 3);

            for (auto i = 0; i < SPHERE_SIDES * 3; ++i)
            {
                indices.push_back(i);
            }

            index_buffer.lock()->data(indices, gpu_t::buffer_usage_e::static_draw);
        }

        gpu.buffers.push(gpu_t::buffer_target_e::array, vertex_buffer.lock());
        gpu.buffers.push(gpu_t::buffer_target_e::element_array, index_buffer.lock());

        const auto gpu_program = gpu_programs.get<basic_gpu_program_t>();

        gpu.programs.push(gpu_program);

        gpu.set_uniform("world_matrix", world_matrix * glm::translate(sphere.origin) * glm::scale(vec3_t(sphere.radius)));
        gpu.set_uniform("view_projection_matrix", view_projection_matrix);

        gpu.draw_elements(gpu_t::primitive_type_e::line_loop, SPHERE_SIDES, index_buffer_type::data_type, SPHERE_SIDES * 0);
        gpu.draw_elements(gpu_t::primitive_type_e::line_loop, SPHERE_SIDES, index_buffer_type::data_type, SPHERE_SIDES * 1);
        gpu.draw_elements(gpu_t::primitive_type_e::line_loop, SPHERE_SIDES, index_buffer_type::data_type, SPHERE_SIDES * 2);

        gpu.programs.pop();

        gpu.buffers.pop(gpu_t::buffer_target_e::element_array);
        gpu.buffers.pop(gpu_t::buffer_target_e::array);
    }
}<|endoftext|>


<commit_before>#include <plasp/sas/Variable.h>

#include <iostream>

#include <plasp/utils/Formatting.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>

namespace plasp
{
namespace sas
{

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////

Variable::Variable()
:	m_axiomLayer(-1)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

Variable Variable::fromSAS(utils::Parser<> &parser)
{
	Variable variable;

	parser.expect<std::string>("begin_variable");
	parser.expect<std::string>("var");

	variable.m_name = parser.parse<std::string>();
	variable.m_axiomLayer = parser.parse<int>();

	const auto numberOfValues = parser.parse<size_t>();
	variable.m_values.reserve(numberOfValues);

	for (size_t j = 0; j < numberOfValues; j++)
	{
		variable.m_values.emplace_back(Value::fromSAS(parser));

		// <none of those> values are only allowed at the end
		if (j < numberOfValues - 1 && variable.m_values[j] == Value::None)
			throw utils::ParserException(parser.coordinate(), "<none of those> value must be the last value of a variable");
	}

	parser.expect<std::string>("end_variable");

	return variable;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Variable::printNameAsASPPredicate(utils::LogStream &outputStream) const
{
	outputStream << utils::Keyword("variable") << "(" << utils::escapeASP(m_name) << ")";
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Variable &Variable::referenceFromSAS(utils::Parser<> &parser, const Variables &variables)
{
	const auto variableID = parser.parse<size_t>();

	if (variableID >= variables.size())
		throw utils::ParserException(parser.coordinate(), "variable index out of range (index " + std::to_string(variableID) + ")");

	return variables[variableID];
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const std::string &Variable::name() const
{
	return m_name;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int Variable::axiomLayer() const
{
	return m_axiomLayer;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Values &Variable::values() const
{
	return m_values;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

}
}
<commit_msg>Added highlighting of variable names.<commit_after>#include <plasp/sas/Variable.h>

#include <iostream>

#include <plasp/utils/Formatting.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>

namespace plasp
{
namespace sas
{

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////

Variable::Variable()
:	m_axiomLayer(-1)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

Variable Variable::fromSAS(utils::Parser<> &parser)
{
	Variable variable;

	parser.expect<std::string>("begin_variable");
	parser.expect<std::string>("var");

	variable.m_name = parser.parse<std::string>();
	variable.m_axiomLayer = parser.parse<int>();

	const auto numberOfValues = parser.parse<size_t>();
	variable.m_values.reserve(numberOfValues);

	for (size_t j = 0; j < numberOfValues; j++)
	{
		variable.m_values.emplace_back(Value::fromSAS(parser));

		// <none of those> values are only allowed at the end
		if (j < numberOfValues - 1 && variable.m_values[j] == Value::None)
			throw utils::ParserException(parser.coordinate(), "<none of those> value must be the last value of a variable");
	}

	parser.expect<std::string>("end_variable");

	return variable;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Variable::printNameAsASPPredicate(utils::LogStream &outputStream) const
{
	outputStream << utils::Keyword("variable") << "(" << utils::Number(utils::escapeASP(m_name)) << ")";
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Variable &Variable::referenceFromSAS(utils::Parser<> &parser, const Variables &variables)
{
	const auto variableID = parser.parse<size_t>();

	if (variableID >= variables.size())
		throw utils::ParserException(parser.coordinate(), "variable index out of range (index " + std::to_string(variableID) + ")");

	return variables[variableID];
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const std::string &Variable::name() const
{
	return m_name;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int Variable::axiomLayer() const
{
	return m_axiomLayer;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Values &Variable::values() const
{
	return m_values;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

}
}
<|endoftext|>


<commit_before>// Copyright (2015) Gustav

#include "ride/proto.h"

#include <google/protobuf/text_format.h>

#include <wx/utils.h>

#include <cassert>
#include <fstream>  // NOLINT this is how we use fstrean
#include <sstream>  // NOLINT this is how we use sstream
#include <string>

#include "tinyxml2.h"  // NOLINT this is how we use tinyxml2

#include "ride/stringutils.h"

bool LoadProto(google::protobuf::Message* t, const wxFileName& file_name) {
  assert(t);

  if (file_name.IsFileReadable() == false) {
    return true;
  }
  const wxString path = file_name.GetFullPath();

  std::ifstream output(path.char_str());
  if (!output) return false;
  std::string data((std::istreambuf_iterator<char>(output)),
                   std::istreambuf_iterator<char>());
  if (false == google::protobuf::TextFormat::ParseFromString(data, t))
    return false;
  return true;
}

bool VerifyFileForWriting(const wxFileName& file_name) {
  file_name.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
  if (file_name.FileExists() && file_name.IsFileWritable() == false) {
    // abort if the file exist and isn't writable
    return false;
  }
  return true;
}

bool SaveProto(const google::protobuf::Message& t,
               const wxFileName& file_name) {
  if (false == VerifyFileForWriting(file_name)) return false;
  const wxString path = file_name.GetFullPath();

  std::ofstream output(path.char_str());
  std::string data;
  if (false == google::protobuf::TextFormat::PrintToString(t, &data))
    return false;
  output << data;
  return true;
}

bool LoadProtoBinary(google::protobuf::Message* message,
                     const wxFileName& file_name) {
  const wxString path = file_name.GetFullPath();
  if (file_name.IsFileReadable()) {
    std::fstream input(path.c_str().AsChar(), std::ios::in | std::ios::binary);
    const bool parse_result = message->ParseFromIstream(&input);
    if (false == parse_result) {
      return false;
    }
  }

  return true;
}

bool SaveProtoBinary(const google::protobuf::Message& message,
                     const wxFileName& file_name) {
  if (false == VerifyFileForWriting(file_name)) return false;
  const wxString config_path = file_name.GetFullPath();

  std::fstream config_stream(
      config_path.c_str().AsChar(),
      std::ios::out | std::ios::trunc | std::ios::binary);
  return message.SerializeToOstream(&config_stream);
}

template <typename T>
wxString ToString(const T& t) {
  std::ostringstream ss;
  ss << t;
  return ss.str().c_str();
}

void AddItem(tinyxml2::XMLElement* el, tinyxml2::XMLDocument* doc,
             const wxString s) {
  auto x = doc->NewElement("x");
  x->SetText(s);
  el->InsertEndChild(x);
}

void FillElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* root,
                 const google::protobuf::Message& mess);

tinyxml2::XMLElement* CreateXmlNode(
    tinyxml2::XMLDocument* doc, const google::protobuf::FieldDescriptor* desc,
    const google::protobuf::Message& mess) {
  auto ref = mess.GetReflection();

  if (desc->is_repeated() == false) {
    if (ref->HasField(mess, desc) == false) {
      return nullptr;
    }
  }

  tinyxml2::XMLElement* el = doc->NewElement("f");
  el->SetAttribute("n", desc->name().c_str());
  el->SetAttribute("u", desc->number());

  // TODO(Gustav): cleanup code
  if (desc->is_repeated()) {
    const int count = ref->FieldSize(mess, desc);
    switch (desc->cpp_type()) {
      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedInt32(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedInt64(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedUInt32(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedUInt64(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedDouble(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedFloat(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedBool(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
        for (int i = 0; i < count; ++i) {
          auto e = ref->GetRepeatedEnum(mess, desc, i);
          auto x = doc->NewElement("x");
          x->SetAttribute("v", e->name().c_str());
          x->SetAttribute("e", e->number());
          el->InsertEndChild(x);
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
        for (int i = 0; i < count; ++i) {
          const auto str = ref->GetRepeatedString(mess, desc, i);
          auto t = doc->NewText(str.c_str());
          auto x = doc->NewElement("x");
          x->InsertEndChild(t);
          if (StartsWith(str, " ") || str.length() > 40) {
            // TODO(Gustav): change the logic here?
            t->SetCData(true);
          }
          el->InsertEndChild(x);
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
        for (int i = 0; i < count; ++i) {
          auto x = doc->NewElement("x");
          FillElement(doc, x, ref->GetRepeatedMessage(mess, desc, i));
          el->InsertEndChild(x);
        }
        break;
      default:
        assert(false && "Unhandled cpp type");
    }
  } else {
    switch (desc->cpp_type()) {
      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
        el->SetText(ToString(ref->GetInt32(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
        el->SetText(ToString(ref->GetInt64(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
        el->SetText(ToString(ref->GetUInt32(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
        el->SetText(ToString(ref->GetUInt64(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
        el->SetText(ToString(ref->GetDouble(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
        el->SetText(ToString(ref->GetFloat(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
        el->SetText(ToString(ref->GetBool(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
        auto e = ref->GetEnum(mess, desc);
        el->SetAttribute("value", e->name().c_str());
        el->SetAttribute("enum", e->number());
      } break;
      case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
        const auto str = ref->GetString(mess, desc);
        auto t = doc->NewText(str.c_str());
        el->InsertEndChild(t);
        if (StartsWith(str, " ") || str.length() > 40) {
          // TODO(Gustav): change the logic here?
          t->SetCData(true);
        }
      } break;
      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
        FillElement(doc, el, ref->GetMessage(mess, desc));
        break;
      default:
        assert(false && "Unhandled cpp type");
    }
  }
  return el;
}

void FillElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* root,
                 const google::protobuf::Message& mess) {
  auto desc = mess.GetDescriptor();
  for (int i = 0; i < desc->field_count(); ++i) {
    auto f = desc->field(i);
    tinyxml2::XMLElement* node = CreateXmlNode(doc, f, mess);
    if (node != nullptr) {
      root->InsertEndChild(node);
    }
  }
}

class CustomPrinter : public tinyxml2::XMLPrinter {
 public:
  void PrintSpace(int depth) override {
    for (int i = 0; i < depth; ++i) {
      Print("\t");
    }
  }
};

wxString SaveProtoXml(const google::protobuf::Message& mess,
                      const wxFileName& file_name) {
  if (false == VerifyFileForWriting(file_name)) {
    return "Unable to verify file";
  }

  tinyxml2::XMLDocument doc;

  auto desc = mess.GetDescriptor();
  tinyxml2::XMLElement* root = doc.NewElement("message");
  root->SetAttribute("name", desc->name().c_str());
  // node->SetAttribute("id", ToString(desc->index()));

  FillElement(&doc, root, mess);
  doc.InsertEndChild(root);
  wxString path = file_name.GetFullPath();

  CustomPrinter p;
  doc.Print(&p);

  wxFile f;
  if (false == f.Open(path, wxFile::write)) {
    return "Unable to open file";
  }
  f.Write(p.CStr());
  f.Close();

  return "";
}

<commit_msg>less cdata and less data in xml #114<commit_after>// Copyright (2015) Gustav

#include "ride/proto.h"

#include <google/protobuf/text_format.h>

#include <wx/utils.h>

#include <cassert>
#include <fstream>  // NOLINT this is how we use fstrean
#include <sstream>  // NOLINT this is how we use sstream
#include <string>

#include "tinyxml2.h"  // NOLINT this is how we use tinyxml2

#include "ride/stringutils.h"

bool LoadProto(google::protobuf::Message* t, const wxFileName& file_name) {
  assert(t);

  if (file_name.IsFileReadable() == false) {
    return true;
  }
  const wxString path = file_name.GetFullPath();

  std::ifstream output(path.char_str());
  if (!output) return false;
  std::string data((std::istreambuf_iterator<char>(output)),
                   std::istreambuf_iterator<char>());
  if (false == google::protobuf::TextFormat::ParseFromString(data, t))
    return false;
  return true;
}

bool VerifyFileForWriting(const wxFileName& file_name) {
  file_name.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
  if (file_name.FileExists() && file_name.IsFileWritable() == false) {
    // abort if the file exist and isn't writable
    return false;
  }
  return true;
}

bool SaveProto(const google::protobuf::Message& t,
               const wxFileName& file_name) {
  if (false == VerifyFileForWriting(file_name)) return false;
  const wxString path = file_name.GetFullPath();

  std::ofstream output(path.char_str());
  std::string data;
  if (false == google::protobuf::TextFormat::PrintToString(t, &data))
    return false;
  output << data;
  return true;
}

bool LoadProtoBinary(google::protobuf::Message* message,
                     const wxFileName& file_name) {
  const wxString path = file_name.GetFullPath();
  if (file_name.IsFileReadable()) {
    std::fstream input(path.c_str().AsChar(), std::ios::in | std::ios::binary);
    const bool parse_result = message->ParseFromIstream(&input);
    if (false == parse_result) {
      return false;
    }
  }

  return true;
}

bool SaveProtoBinary(const google::protobuf::Message& message,
                     const wxFileName& file_name) {
  if (false == VerifyFileForWriting(file_name)) return false;
  const wxString config_path = file_name.GetFullPath();

  std::fstream config_stream(
      config_path.c_str().AsChar(),
      std::ios::out | std::ios::trunc | std::ios::binary);
  return message.SerializeToOstream(&config_stream);
}

template <typename T>
wxString ToString(const T& t) {
  std::ostringstream ss;
  ss << t;
  return ss.str().c_str();
}

void AddItem(tinyxml2::XMLElement* el, tinyxml2::XMLDocument* doc,
             const wxString s) {
  auto x = doc->NewElement("x");
  x->SetText(s);
  el->InsertEndChild(x);
}

void FillElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* root,
                 const google::protobuf::Message& mess);

bool UseCdata(const std::string& str) {
  return str.find_first_of(" \n\t") != std::string::npos;
}

tinyxml2::XMLElement* CreateXmlNode(
    tinyxml2::XMLDocument* doc, const google::protobuf::FieldDescriptor* desc,
    const google::protobuf::Message& mess) {
  auto ref = mess.GetReflection();

  if (desc->is_repeated() == false) {
    if (ref->HasField(mess, desc) == false) {
      return nullptr;
    }
  }

  tinyxml2::XMLElement* el = doc->NewElement("f");
  el->SetAttribute("n", desc->name().c_str());

  // TODO(Gustav): cleanup code
  if (desc->is_repeated()) {
    const int count = ref->FieldSize(mess, desc);
    switch (desc->cpp_type()) {
      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedInt32(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedInt64(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedUInt32(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedUInt64(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedDouble(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedFloat(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
        for (int i = 0; i < count; ++i) {
          AddItem(el, doc, ToString(ref->GetRepeatedBool(mess, desc, i)));
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
        for (int i = 0; i < count; ++i) {
          auto e = ref->GetRepeatedEnum(mess, desc, i);
          auto x = doc->NewElement("x");
          x->SetAttribute("v", e->name().c_str());
          el->InsertEndChild(x);
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
        for (int i = 0; i < count; ++i) {
          const auto str = ref->GetRepeatedString(mess, desc, i);
          auto t = doc->NewText(str.c_str());
          auto x = doc->NewElement("x");
          x->InsertEndChild(t);
          if (UseCdata(str)) {
            // TODO(Gustav): change the logic here?
            t->SetCData(true);
          }
          el->InsertEndChild(x);
        }
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
        for (int i = 0; i < count; ++i) {
          auto x = doc->NewElement("x");
          FillElement(doc, x, ref->GetRepeatedMessage(mess, desc, i));
          el->InsertEndChild(x);
        }
        break;
      default:
        assert(false && "Unhandled cpp type");
    }
  } else {
    switch (desc->cpp_type()) {
      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
        el->SetText(ToString(ref->GetInt32(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
        el->SetText(ToString(ref->GetInt64(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
        el->SetText(ToString(ref->GetUInt32(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
        el->SetText(ToString(ref->GetUInt64(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
        el->SetText(ToString(ref->GetDouble(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
        el->SetText(ToString(ref->GetFloat(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
        el->SetText(ToString(ref->GetBool(mess, desc)));
        break;
      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
        auto e = ref->GetEnum(mess, desc);
        el->SetAttribute("v", e->name().c_str());
      } break;
      case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
        const auto str = ref->GetString(mess, desc);
        auto t = doc->NewText(str.c_str());
        el->InsertEndChild(t);
        if (UseCdata(str)) {
          // TODO(Gustav): change the logic here?
          t->SetCData(true);
        }
      } break;
      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
        FillElement(doc, el, ref->GetMessage(mess, desc));
        break;
      default:
        assert(false && "Unhandled cpp type");
    }
  }
  return el;
}

void FillElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* root,
                 const google::protobuf::Message& mess) {
  auto desc = mess.GetDescriptor();
  for (int i = 0; i < desc->field_count(); ++i) {
    auto f = desc->field(i);
    tinyxml2::XMLElement* node = CreateXmlNode(doc, f, mess);
    if (node != nullptr) {
      root->InsertEndChild(node);
    }
  }
}

class CustomPrinter : public tinyxml2::XMLPrinter {
 public:
  void PrintSpace(int depth) override {
    for (int i = 0; i < depth; ++i) {
      Print("\t");
    }
  }
};

wxString SaveProtoXml(const google::protobuf::Message& mess,
                      const wxFileName& file_name) {
  if (false == VerifyFileForWriting(file_name)) {
    return "Unable to verify file";
  }

  tinyxml2::XMLDocument doc;

  auto desc = mess.GetDescriptor();
  tinyxml2::XMLElement* root = doc.NewElement("message");
  root->SetAttribute("name", desc->name().c_str());
  // node->SetAttribute("id", ToString(desc->index()));

  FillElement(&doc, root, mess);
  doc.InsertEndChild(root);
  wxString path = file_name.GetFullPath();

  CustomPrinter p;
  doc.Print(&p);

  wxFile f;
  if (false == f.Open(path, wxFile::write)) {
    return "Unable to open file";
  }
  f.Write(p.CStr());
  f.Close();

  return "";
}
<|endoftext|>


<commit_before>#include "interface/usb.h"
#include "util/bytebuffer.h"
#include "util/log.h"
#include "gpio.h"

#ifdef CHIPKIT

#define USB_VBUS_ANALOG_INPUT A0

#endif

#define USB_HANDLE_MAX_WAIT_COUNT 35000

namespace gpio = openxc::gpio;

using openxc::interface::usb::UsbDevice;
using openxc::interface::usb::UsbEndpoint;
using openxc::interface::usb::UsbEndpointDirection;
using openxc::gpio::GPIO_DIRECTION_INPUT;
using openxc::util::bytebuffer::processQueue;

// This is a reference to the last packet read
extern volatile CTRL_TRF_SETUP SetupPkt;
extern UsbDevice USB_DEVICE;
extern bool handleControlRequest(uint8_t);

boolean usbCallback(USB_EVENT event, void *pdata, word size) {
    // initial connection up to configure will be handled by the default
    // callback routine.
    USB_DEVICE.device.DefaultCBEventHandler(event, pdata, size);

    // TODO why can't we use USB_EVENT as the type anymore? rejects
    // EVENT_EP0_REQUEST as a switch case
    switch((int)event) {
    case EVENT_CONFIGURED:
        debug("USB Configured");
        USB_DEVICE.configured = true;

        for(int i = 0; i < ENDPOINT_COUNT; i++) {
            UsbEndpoint* endpoint = &USB_DEVICE.endpoints[i];
            if(endpoint->direction == UsbEndpointDirection::USB_ENDPOINT_DIRECTION_OUT) {
                USB_DEVICE.device.EnableEndpoint(endpoint->address,
                        USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            } else {
                USB_DEVICE.device.EnableEndpoint(endpoint->address,
                        USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            }
        }
        break;

    case EVENT_EP0_REQUEST:
        handleControlRequest(SetupPkt.bRequest);
        break;

    default:
        break;
    }
    // TODO how'd we get away with not returning a value for so long?
    return true;
}

void openxc::interface::usb::sendControlMessage(uint8_t* data, uint8_t length) {
    USB_DEVICE.device.EP0SendRAMPtr(data, length, USB_EP0_INCLUDE_ZERO);
}

bool vbusEnabled() {
#ifdef USB_VBUS_ANALOG_INPUT
    return analogRead(USB_VBUS_ANALOG_INPUT) > 100;
#else
    return true;
#endif
}

bool waitForHandle(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    int i = 0;
    while(usbDevice->configured &&
            usbDevice->device.HandleBusy(endpoint->deviceToHostHandle)) {
        ++i;
        if(i > USB_HANDLE_MAX_WAIT_COUNT) {
            // The reason we want to exit this loop early is that if USB is
            // attached and configured, but the host isn't sending an IN
            // requests, we will block here forever. As it is, it still slows
            // down UART transfers quite a bit, so setting configured = false
            // ASAP is important.

            // This can get really noisy when running but I want to leave it in
            // because it' useful to enable when debugging.
            // debug("USB most likely not connected or at least not requesting "
                    // "IN transfers - bailing out of handle waiting");
            return false;
        }
    }
    return true;
}

void openxc::interface::usb::processSendQueue(UsbDevice* usbDevice) {
    if(usbDevice->configured && !vbusEnabled()) {
        debug("USB no longer detected - marking unconfigured");
        usbDevice->configured = false;
    }

    for(int i = 0; i < ENDPOINT_COUNT; i++) {
        UsbEndpoint* endpoint = &usbDevice->endpoints[i];

        // Don't touch usbDevice->sendBuffer if there's still a pending transfer
        if(!waitForHandle(usbDevice, endpoint)) {
            return;
        }

        while(usbDevice->configured &&
                !QUEUE_EMPTY(uint8_t, &endpoint->sendQueue)) {
            int byteCount = 0;
            while(!QUEUE_EMPTY(uint8_t, &endpoint->sendQueue) &&
                    byteCount < USB_SEND_BUFFER_SIZE) {
                endpoint->sendBuffer[byteCount++] = QUEUE_POP(uint8_t,
                        &endpoint->sendQueue);
            }

            int nextByteIndex = 0;
            while(nextByteIndex < byteCount) {
                // Make sure the USB write is 100% complete before messing with this
                // buffer after we copy the message into it - the Microchip library
                // doesn't copy the data to its own internal buffer. See #171 for
                // background on this issue.
                // TODO instead of dropping, replace POP above with a SNAPSHOT
                // and POP off only exactly how many bytes were sent after the
                // fact.
                // TODO in order for this not to fail too often I had to increase
                // the USB_HANDLE_MAX_WAIT_COUNT. that may be OK since now we have
                // VBUS detection.
                if(!waitForHandle(usbDevice, endpoint)) {
                    debug("USB not responding in a timely fashion, dropped data");
                    return;
                }

                int bytesToTransfer = min(MAX_USB_PACKET_SIZE_BYTES,
                        byteCount - nextByteIndex);
                endpoint->deviceToHostHandle = usbDevice->device.GenWrite(
                        endpoint->address,
                        &endpoint->sendBuffer[nextByteIndex], bytesToTransfer);
                nextByteIndex += bytesToTransfer;
            }
        }
    }
}

void openxc::interface::usb::initialize(UsbDevice* usbDevice) {
    usb::initializeCommon(usbDevice);
    usbDevice->device = USBDevice(usbCallback);
    usbDevice->device.InitializeSystem(false);
#ifdef USB_VBUS_ANALOG_INPUT
    gpio::setDirection(0, USB_VBUS_ANALOG_INPUT, GPIO_DIRECTION_INPUT);
#endif
    debug("Done.");
}

void openxc::interface::usb::deinitialize(UsbDevice* usbDevice) {
    // disable USB (notifies stack we are disabling)
    USBModuleDisable();

    // power off the USB peripheral
    // TODO could not find a ready-made function or macro
    // in the USB library to actually turn off the module.
    // USBModuleDisable() is close to what we want, but it
    // sets the ON bit to 1 for some reason.
    // so, easy solution is just go right to the control register, for now
    U1PWRCCLR = (1 << 0);
}

/* Private: Arm the given endpoint for a read from the device to host.
 *
 * This also puts a NUL char in the beginning of the buffer so you don't get
 * confused that it's still a valid message.
 *
 * device - the CAN USB device to arm the endpoint on
 * endpoint - the endpoint to arm.
 * buffer - the destination buffer for the next OUT transfer.
 */
void armForRead(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    endpoint->receiveBuffer[0] = 0;
    endpoint->hostToDeviceHandle = usbDevice->device.GenRead(
            endpoint->address, (uint8_t*)endpoint->receiveBuffer,
            endpoint->size);
}

void openxc::interface::usb::read(UsbDevice* device, UsbEndpoint* endpoint,
        bool (*callback)(uint8_t*)) {
    if(!device->device.HandleBusy(endpoint->hostToDeviceHandle)) {
        if(endpoint->receiveBuffer[0] != '\0') {
            for(int i = 0; i < endpoint->size; i++) {
                if(!QUEUE_PUSH(uint8_t, &endpoint->receiveQueue,
                            endpoint->receiveBuffer[i])) {
                    debug("Dropped write from host -- queue is full");
                }
            }
            processQueue(&endpoint->receiveQueue, callback);
        }
        armForRead(device, endpoint);
    }
}
<commit_msg>Don't flush send queue on PIC32 if unconfigured.<commit_after>#include "interface/usb.h"
#include "util/bytebuffer.h"
#include "util/log.h"
#include "gpio.h"

#ifdef CHIPKIT

#define USB_VBUS_ANALOG_INPUT A0

#endif

#define USB_HANDLE_MAX_WAIT_COUNT 35000

namespace gpio = openxc::gpio;

using openxc::interface::usb::UsbDevice;
using openxc::interface::usb::UsbEndpoint;
using openxc::interface::usb::UsbEndpointDirection;
using openxc::gpio::GPIO_DIRECTION_INPUT;
using openxc::util::bytebuffer::processQueue;

// This is a reference to the last packet read
extern volatile CTRL_TRF_SETUP SetupPkt;
extern UsbDevice USB_DEVICE;
extern bool handleControlRequest(uint8_t);

boolean usbCallback(USB_EVENT event, void *pdata, word size) {
    // initial connection up to configure will be handled by the default
    // callback routine.
    USB_DEVICE.device.DefaultCBEventHandler(event, pdata, size);

    // TODO why can't we use USB_EVENT as the type anymore? rejects
    // EVENT_EP0_REQUEST as a switch case
    switch((int)event) {
    case EVENT_CONFIGURED:
        debug("USB Configured");
        USB_DEVICE.configured = true;

        for(int i = 0; i < ENDPOINT_COUNT; i++) {
            UsbEndpoint* endpoint = &USB_DEVICE.endpoints[i];
            if(endpoint->direction == UsbEndpointDirection::USB_ENDPOINT_DIRECTION_OUT) {
                USB_DEVICE.device.EnableEndpoint(endpoint->address,
                        USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            } else {
                USB_DEVICE.device.EnableEndpoint(endpoint->address,
                        USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            }
        }
        break;

    case EVENT_EP0_REQUEST:
        handleControlRequest(SetupPkt.bRequest);
        break;

    default:
        break;
    }
    // TODO how'd we get away with not returning a value for so long?
    return true;
}

void openxc::interface::usb::sendControlMessage(uint8_t* data, uint8_t length) {
    USB_DEVICE.device.EP0SendRAMPtr(data, length, USB_EP0_INCLUDE_ZERO);
}

bool vbusEnabled() {
#ifdef USB_VBUS_ANALOG_INPUT
    return analogRead(USB_VBUS_ANALOG_INPUT) > 100;
#else
    return true;
#endif
}

bool waitForHandle(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    int i = 0;
    while(usbDevice->configured &&
            usbDevice->device.HandleBusy(endpoint->deviceToHostHandle)) {
        ++i;
        if(i > USB_HANDLE_MAX_WAIT_COUNT) {
            // The reason we want to exit this loop early is that if USB is
            // attached and configured, but the host isn't sending an IN
            // requests, we will block here forever. As it is, it still slows
            // down UART transfers quite a bit, so setting configured = false
            // ASAP is important.

            // This can get really noisy when running but I want to leave it in
            // because it' useful to enable when debugging.
            // debug("USB most likely not connected or at least not requesting "
                    // "IN transfers - bailing out of handle waiting");
            return false;
        }
    }
    return true;
}

void openxc::interface::usb::processSendQueue(UsbDevice* usbDevice) {
    if(usbDevice->configured && !vbusEnabled()) {
        debug("USB no longer detected - marking unconfigured");
        usbDevice->configured = false;
        return;
    }

    for(int i = 0; i < ENDPOINT_COUNT; i++) {
        UsbEndpoint* endpoint = &usbDevice->endpoints[i];

        // Don't touch usbDevice->sendBuffer if there's still a pending transfer
        if(!waitForHandle(usbDevice, endpoint)) {
            return;
        }

        while(usbDevice->configured &&
                !QUEUE_EMPTY(uint8_t, &endpoint->sendQueue)) {
            int byteCount = 0;
            while(!QUEUE_EMPTY(uint8_t, &endpoint->sendQueue) &&
                    byteCount < USB_SEND_BUFFER_SIZE) {
                endpoint->sendBuffer[byteCount++] = QUEUE_POP(uint8_t,
                        &endpoint->sendQueue);
            }

            int nextByteIndex = 0;
            while(nextByteIndex < byteCount) {
                // Make sure the USB write is 100% complete before messing with this
                // buffer after we copy the message into it - the Microchip library
                // doesn't copy the data to its own internal buffer. See #171 for
                // background on this issue.
                // TODO instead of dropping, replace POP above with a SNAPSHOT
                // and POP off only exactly how many bytes were sent after the
                // fact.
                // TODO in order for this not to fail too often I had to increase
                // the USB_HANDLE_MAX_WAIT_COUNT. that may be OK since now we have
                // VBUS detection.
                if(!waitForHandle(usbDevice, endpoint)) {
                    debug("USB not responding in a timely fashion, dropped data");
                    return;
                }

                int bytesToTransfer = min(MAX_USB_PACKET_SIZE_BYTES,
                        byteCount - nextByteIndex);
                endpoint->deviceToHostHandle = usbDevice->device.GenWrite(
                        endpoint->address,
                        &endpoint->sendBuffer[nextByteIndex], bytesToTransfer);
                nextByteIndex += bytesToTransfer;
            }
        }
    }
}

void openxc::interface::usb::initialize(UsbDevice* usbDevice) {
    usb::initializeCommon(usbDevice);
    usbDevice->device = USBDevice(usbCallback);
    usbDevice->device.InitializeSystem(false);
#ifdef USB_VBUS_ANALOG_INPUT
    gpio::setDirection(0, USB_VBUS_ANALOG_INPUT, GPIO_DIRECTION_INPUT);
#endif
    debug("Done.");
}

void openxc::interface::usb::deinitialize(UsbDevice* usbDevice) {
    // disable USB (notifies stack we are disabling)
    USBModuleDisable();

    // power off the USB peripheral
    // TODO could not find a ready-made function or macro
    // in the USB library to actually turn off the module.
    // USBModuleDisable() is close to what we want, but it
    // sets the ON bit to 1 for some reason.
    // so, easy solution is just go right to the control register, for now
    U1PWRCCLR = (1 << 0);
}

/* Private: Arm the given endpoint for a read from the device to host.
 *
 * This also puts a NUL char in the beginning of the buffer so you don't get
 * confused that it's still a valid message.
 *
 * device - the CAN USB device to arm the endpoint on
 * endpoint - the endpoint to arm.
 * buffer - the destination buffer for the next OUT transfer.
 */
void armForRead(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    endpoint->receiveBuffer[0] = 0;
    endpoint->hostToDeviceHandle = usbDevice->device.GenRead(
            endpoint->address, (uint8_t*)endpoint->receiveBuffer,
            endpoint->size);
}

void openxc::interface::usb::read(UsbDevice* device, UsbEndpoint* endpoint,
        bool (*callback)(uint8_t*)) {
    if(!device->device.HandleBusy(endpoint->hostToDeviceHandle)) {
        if(endpoint->receiveBuffer[0] != '\0') {
            for(int i = 0; i < endpoint->size; i++) {
                if(!QUEUE_PUSH(uint8_t, &endpoint->receiveQueue,
                            endpoint->receiveBuffer[i])) {
                    debug("Dropped write from host -- queue is full");
                }
            }
            processQueue(&endpoint->receiveQueue, callback);
        }
        armForRead(device, endpoint);
    }
}
<|endoftext|>


<commit_before>#pragma once
/* RLTK (RogueLike Tool Kit) 1.00
 * Copyright (c) 2016-Present, Bracket Productions.
 * Licensed under the LGPL - see LICENSE file.
 */

#include <string>
#include <functional>
#include <SFML/Graphics.hpp>
#include "texture_resources.hpp"
#include "virtual_terminal.hpp"
#include "colors.hpp"
#include "rng.hpp"
#include "geometry.hpp"
#include "astar.hpp"

namespace rltk {

/*
 * Bootstrap the system with a window size and title (all optional params; leave them out and get 1024x768)
 */
void init(const int window_width=1024, const int window_height=768, const std::string window_title="RLTK Roguelike");

/*
 * The main run loop. Calls on_tick each frame. Window can be initially defined with width/height/title, but these
 * have sane defaults to get you started.
 */
void run(std::function<void(double)> on_tick, const std::string root_console_font);

/*
 * For rendering to the console
 */
extern std::unique_ptr<virtual_terminal> console;

/*
 * In case you want to do some SFML stuff yourself, this provides a pointer to the render window.
 */
sf::RenderWindow * get_window();

}
<commit_msg>No need for astar in the global header; working on interface.<commit_after>#pragma once
/* RLTK (RogueLike Tool Kit) 1.00
 * Copyright (c) 2016-Present, Bracket Productions.
 * Licensed under the LGPL - see LICENSE file.
 */

#include <string>
#include <functional>
#include <SFML/Graphics.hpp>
#include "texture_resources.hpp"
#include "virtual_terminal.hpp"
#include "colors.hpp"
#include "rng.hpp"
#include "geometry.hpp"

namespace rltk {

/*
 * Bootstrap the system with a window size and title (all optional params; leave them out and get 1024x768)
 */
void init(const int window_width=1024, const int window_height=768, const std::string window_title="RLTK Roguelike");

/*
 * The main run loop. Calls on_tick each frame. Window can be initially defined with width/height/title, but these
 * have sane defaults to get you started.
 */
void run(std::function<void(double)> on_tick, const std::string root_console_font);

/*
 * For rendering to the console
 */
extern std::unique_ptr<virtual_terminal> console;

/*
 * In case you want to do some SFML stuff yourself, this provides a pointer to the render window.
 */
sf::RenderWindow * get_window();

}
<|endoftext|>


<commit_before>#pragma once

#include "path.hh"
#include "types.hh"
#include "hash.hh"
#include "content-address.hh"

#include <map>

namespace nix {

/* Abstract syntax of derivations. */

struct DerivationOutput
{
    StorePath path;
    std::optional<FixedOutputHash> hash; /* hash used for expected hash computation */
};

typedef std::map<string, DerivationOutput> DerivationOutputs;

/* For inputs that are sub-derivations, we specify exactly which
   output IDs we are interested in. */
typedef std::map<StorePath, StringSet> DerivationInputs;

typedef std::map<string, string> StringPairs;

struct BasicDerivation
{
    DerivationOutputs outputs; /* keyed on symbolic IDs */
    StorePathSet inputSrcs; /* inputs that are sources */
    string platform;
    Path builder;
    Strings args;
    StringPairs env;

    BasicDerivation() { }
    virtual ~BasicDerivation() { };

    /* Return the path corresponding to the output identifier `id' in
       the given derivation. */
    const StorePath & findOutput(const std::string & id) const;

    bool isBuiltin() const;

    /* Return true iff this is a fixed-output derivation. */
    bool isFixedOutput() const;

    /* Return the output paths of a derivation. */
    StorePathSet outputPaths() const;

    /* Return the output names of a derivation. */
    StringSet outputNames() const;
};

struct Derivation : BasicDerivation
{
    DerivationInputs inputDrvs; /* inputs that are sub-derivations */

    /* Print a derivation. */
    std::string unparse(const Store & store, bool maskOutputs,
        std::map<std::string, StringSet> * actualInputs = nullptr) const;

    Derivation() { }
};

class Store;

enum RepairFlag : bool { NoRepair = false, Repair = true };

/* Write a derivation to the Nix store, and return its path. */
StorePath writeDerivation(ref<Store> store,
    const Derivation & drv, std::string_view name, RepairFlag repair = NoRepair);

/* Read a derivation from a file. */
Derivation parseDerivation(const Store & store, string && s);

// FIXME: remove
bool isDerivation(const string & fileName);

Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutputs);

/* Memoisation of hashDerivationModulo(). */
typedef std::map<StorePath, Hash> DrvHashes;

extern DrvHashes drvHashes; // FIXME: global, not thread-safe

bool wantOutput(const string & output, const std::set<string> & wanted);

struct Source;
struct Sink;

Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv);
void writeDerivation(Sink & out, const Store & store, const BasicDerivation & drv);

std::string hashPlaceholder(const std::string & outputName);

}
<commit_msg>Small namespace fix<commit_after>#pragma once

#include "path.hh"
#include "types.hh"
#include "hash.hh"
#include "content-address.hh"

#include <map>

namespace nix {

/* Abstract syntax of derivations. */

struct DerivationOutput
{
    StorePath path;
    std::optional<FixedOutputHash> hash; /* hash used for expected hash computation */
};

typedef std::map<string, DerivationOutput> DerivationOutputs;

/* For inputs that are sub-derivations, we specify exactly which
   output IDs we are interested in. */
typedef std::map<StorePath, StringSet> DerivationInputs;

typedef std::map<string, string> StringPairs;

struct BasicDerivation
{
    DerivationOutputs outputs; /* keyed on symbolic IDs */
    StorePathSet inputSrcs; /* inputs that are sources */
    string platform;
    Path builder;
    Strings args;
    StringPairs env;

    BasicDerivation() { }
    virtual ~BasicDerivation() { };

    /* Return the path corresponding to the output identifier `id' in
       the given derivation. */
    const StorePath & findOutput(const std::string & id) const;

    bool isBuiltin() const;

    /* Return true iff this is a fixed-output derivation. */
    bool isFixedOutput() const;

    /* Return the output paths of a derivation. */
    StorePathSet outputPaths() const;

    /* Return the output names of a derivation. */
    StringSet outputNames() const;
};

struct Derivation : BasicDerivation
{
    DerivationInputs inputDrvs; /* inputs that are sub-derivations */

    /* Print a derivation. */
    std::string unparse(const Store & store, bool maskOutputs,
        std::map<std::string, StringSet> * actualInputs = nullptr) const;

    Derivation() { }
};

class Store;

enum RepairFlag : bool { NoRepair = false, Repair = true };

/* Write a derivation to the Nix store, and return its path. */
StorePath writeDerivation(ref<Store> store,
    const Derivation & drv, std::string_view name, RepairFlag repair = NoRepair);

/* Read a derivation from a file. */
Derivation parseDerivation(const Store & store, std::string && s);

// FIXME: remove
bool isDerivation(const string & fileName);

Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutputs);

/* Memoisation of hashDerivationModulo(). */
typedef std::map<StorePath, Hash> DrvHashes;

extern DrvHashes drvHashes; // FIXME: global, not thread-safe

bool wantOutput(const string & output, const std::set<string> & wanted);

struct Source;
struct Sink;

Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv);
void writeDerivation(Sink & out, const Store & store, const BasicDerivation & drv);

std::string hashPlaceholder(const std::string & outputName);

}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "documentmetastoreattribute.h"
#include <vespa/vespalib/util/exceptions.h>

namespace proton {

namespace {

const vespalib::string _G_documentMetaStoreName("[documentmetastore]");

}

const vespalib::string &
DocumentMetaStoreAttribute::getFixedName()
{
    return _G_documentMetaStoreName;
}

DocumentMetaStoreAttribute::DocumentMetaStoreAttribute(const vespalib::string &name)
    : NotImplementedAttribute(name, Config(BasicType::NONE))
{ }

DocumentMetaStoreAttribute::~DocumentMetaStoreAttribute() = default;

}
<commit_msg>GC unused include<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "documentmetastoreattribute.h"

namespace proton {

namespace {

const vespalib::string _G_documentMetaStoreName("[documentmetastore]");

}

const vespalib::string &
DocumentMetaStoreAttribute::getFixedName()
{
    return _G_documentMetaStoreName;
}

DocumentMetaStoreAttribute::DocumentMetaStoreAttribute(const vespalib::string &name)
    : NotImplementedAttribute(name, Config(BasicType::NONE))
{ }

DocumentMetaStoreAttribute::~DocumentMetaStoreAttribute() = default;

}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
// File contains modifications by: The Gulden developers
// All modifications:
// Copyright (c) 2016-2018 The Gulden developers
// Authored by: Malcolm MacLeod (mmacleod@gmx.com)
// Distributed under the GULDEN software license, see the accompanying
// file COPYING

#include "transactiondesc.h"

#include "units.h"
#include "guiutil.h"
#include "paymentserver.h"
#include "transactionrecord.h"

#include "base58.h"
#include "consensus/consensus.h"
#include "validation/validation.h"
#include "script/script.h"
#include "timedata.h"
#include "util.h"
#include "wallet/db.h"
#include "wallet/wallet.h"

#include <stdint.h>
#include <string>

QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{
    AssertLockHeld(cs_main);
    if (!CheckFinalTx(wtx, chainActive))
    {
        if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
            return tr("Open for %n more block(s)", "", wtx.tx->nLockTime - chainActive.Height());
        else
            return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.tx->nLockTime));
    }
    else
    {
        int nDepth = wtx.GetDepthInMainChain();
        if (nDepth < 0)
            return tr("conflicted with a transaction with %1 confirmations").arg(-nDepth);
        else if (nDepth == 0)
            return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : "");
        else if (nDepth < 6)
            return tr("%1/unconfirmed").arg(nDepth);
        else
            return tr("%1 confirmations").arg(nDepth);
    }
}

QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
{
    QString strHTML;

    LOCK2(cs_main, wallet->cs_wallet);
    strHTML.reserve(4000);
    strHTML += "";

    int64_t nTime = wtx.GetTxTime();
    CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
    CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
    CAmount nNet = nCredit - nDebit;

    strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx);
    strHTML += "
";
    strHTML += "" + tr("Date") + ": " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "
";

    //
    // From
    //
    if (wtx.IsCoinBase())
    {
        strHTML += "" + tr("Source") + ": " + tr("Generated") + "
";
    }
    else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
    {
        // Online transaction
        strHTML += "" + tr("From") + ": " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "
";
    }
    else
    {
        // Offline transaction
        if (nNet > 0)
        {
            // Credit
            if (CGuldenAddress(rec->address).IsValid())
            {
                CTxDestination address = CGuldenAddress(rec->address).Get();
                if (wallet->mapAddressBook.count(rec->address))
                {
                    strHTML += "" + tr("From") + ": " + tr("unknown") + "
";
                    strHTML += "" + tr("To") + ": ";
                    strHTML += GUIUtil::HtmlEscape(rec->address);
                    QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only");
                    if (!wallet->mapAddressBook[CGuldenAddress(address).ToString()].name.empty())
                        strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[CGuldenAddress(address).ToString()].name) + ")";
                    else
                        strHTML += " (" + addressOwned + ")";
                    strHTML += "
";
                }
            }
        }
    }

    //
    // To
    //
    if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
    {
        // Online transaction
        std::string strAddress = wtx.mapValue["to"];
        strHTML += "" + tr("To") + ": ";
        if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].name.empty())
            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[strAddress].name) + " ";
        strHTML += GUIUtil::HtmlEscape(strAddress) + "
";
    }

    //
    // Amount
    //
    if (wtx.IsCoinBase() && nCredit == 0)
    {
        //
        // Coinbase
        //
        CAmount nUnmatured = 0;
        for(const CTxOut& txout : wtx.tx->vout)
            nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
        strHTML += "" + tr("Credit") + ": ";
        if (wtx.IsInMainChain())
            strHTML += GuldenUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
        else
            strHTML += "(" + tr("not accepted") + ")";
        strHTML += "
";
    }
    else if (nNet > 0)
    {
        //
        // Credit
        //
        strHTML += "" + tr("Credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, nNet) + "
";
    }
    else
    {
        isminetype fAllFromMe = ISMINE_SPENDABLE;
        for(const CTxIn& txin : wtx.tx->vin)
        {
            isminetype mine = wallet->IsMine(txin);
            if(fAllFromMe > mine) fAllFromMe = mine;
        }

        isminetype fAllToMe = ISMINE_SPENDABLE;
        for(const CTxOut& txout : wtx.tx->vout)
        {
            isminetype mine = wallet->IsMine(txout);
            if(fAllToMe > mine) fAllToMe = mine;
        }

        if (fAllFromMe)
        {
            if(fAllFromMe & ISMINE_WATCH_ONLY)
                strHTML += "" + tr("From") + ": " + tr("watch-only") + "
";

            //
            // Debit
            //
            for(const CTxOut& txout : wtx.tx->vout)
            {
                // Ignore change
                isminetype toSelf = wallet->IsMine(txout);
                if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE))
                    continue;

                if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
                {
                    // Offline transaction
                    CTxDestination address;
                    if (ExtractDestination(txout, address))
                    {
                        strHTML += "" + tr("To") + ": ";
                        if (wallet->mapAddressBook.count(CGuldenAddress(address).ToString()) && !wallet->mapAddressBook[CGuldenAddress(address).ToString()].name.empty())
                            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[CGuldenAddress(address).ToString()].name) + " ";
                        strHTML += GUIUtil::HtmlEscape(CGuldenAddress(address).ToString());
                        if(toSelf == ISMINE_SPENDABLE)
                            strHTML += " (own address)";
                        else if(toSelf & ISMINE_WATCH_ONLY)
                            strHTML += " (watch-only)";
                        strHTML += "
";
                    }
                }

                strHTML += "" + tr("Debit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -txout.nValue) + "
";
                if(toSelf)
                    strHTML += "" + tr("Credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, txout.nValue) + "
";
            }

            if (fAllToMe)
            {
                // Payment to self
                CAmount nChange = wtx.GetChange();
                CAmount nValue = nCredit - nChange;
                if (nValue != 0)
                {
                    strHTML += "" + tr("Total debit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -nValue) + "
";
                    strHTML += "" + tr("Total credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, nValue) + "
";
                }
                else
                {
                    strHTML += "" + tr("Total moved") + ": " + GuldenUnits::formatHtmlWithUnit(unit, nCredit) + "
";
                }
            }

            CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
            if (nTxFee > 0)
                strHTML += "" + tr("Transaction fee") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -nTxFee) + "
";
        }
        else
        {
            //
            // Mixed debit transaction
            //
            for(const CTxIn& txin : wtx.tx->vin)
                if (wallet->IsMine(txin))
                    strHTML += "" + tr("Debit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
";
            for(const CTxOut& txout : wtx.tx->vout)
                if (wallet->IsMine(txout))
                    strHTML += "" + tr("Credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
";
        }
    }

    strHTML += "" + tr("Net amount") + ": " + GuldenUnits::formatHtmlWithUnit(unit, nNet, true) + "
";

    //
    // Message
    //
    if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
        strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "
";
    if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
        strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
";

    strHTML += "" + tr("Transaction ID") + ": " + rec->getTxID() + "
";
    strHTML += "" + tr("Transaction total size") + ": " + QString::number(wtx.tx->GetTotalSize()) + " bytes
";
    strHTML += "" + tr("Output index") + ": " + QString::number(rec->getOutputIndex()) + "
";

    // Message from normal Gulden:URI (Gulden:123...?message=example)
    for (const PAIRTYPE(std::string, std::string)& r : wtx.vOrderForm)
        if (r.first == "Message")
            strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(r.second, true) + "
";

    //
    // PaymentRequest info:
    //
    for (const PAIRTYPE(std::string, std::string)& r : wtx.vOrderForm)
    {
        if (r.first == "PaymentRequest")
        {
            PaymentRequestPlus req;
            req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
            QString merchant;
            if (req.getMerchant(PaymentServer::getCertStore(), merchant))
                strHTML += "" + tr("Merchant") + ": " + GUIUtil::HtmlEscape(merchant) + "
";
        }
    }

    if (wtx.IsCoinBase())
    {
        quint32 numBlocksToMaturity = COINBASE_MATURITY +  1;
        strHTML += "
" + tr("Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.").arg(QString::number(numBlocksToMaturity)) + "
";
    }

    //
    // Debug view
    //
    if (logCategories != BCLog::NONE)
    {
        strHTML += "

" + tr("Debug information") + "

";
        for(const CTxIn& txin : wtx.tx->vin)
            if(wallet->IsMine(txin))
                strHTML += "" + tr("Debit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
";
        for(const CTxOut& txout : wtx.tx->vout)
            if(wallet->IsMine(txout))
                strHTML += "" + tr("Credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
";

        strHTML += "
" + tr("Transaction") + ":
";
        strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true);

        strHTML += "
" + tr("Inputs") + ":";
        strHTML += "
";

        for(const CTxIn& txin : wtx.tx->vin)
        {
            COutPoint prevout = txin.prevout;

            Coin prev;
            if(pcoinsTip->GetCoin(prevout, prev))
            {
                {
                    strHTML += "
";
                    const CTxOut &vout = prev.out;
                    CTxDestination address;
                    if (ExtractDestination(vout, address))
                    {
                        if (wallet->mapAddressBook.count(CGuldenAddress(address).ToString()) && !wallet->mapAddressBook[CGuldenAddress(address).ToString()].name.empty())
                            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[CGuldenAddress(address).ToString()].name) + " ";
                        strHTML += QString::fromStdString(CGuldenAddress(address).ToString());
                    }
                    strHTML = strHTML + " " + tr("Amount") + "=" + GuldenUnits::formatHtmlWithUnit(unit, vout.nValue);
                    strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "
";
                    strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "
";
                }
            }
        }

        strHTML += "
";
    }

    strHTML += "";
    return strHTML;
}
<commit_msg>UI: Cosmetic improvement to mining/witnessing tx details<commit_after>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
// File contains modifications by: The Gulden developers
// All modifications:
// Copyright (c) 2016-2018 The Gulden developers
// Authored by: Malcolm MacLeod (mmacleod@gmx.com)
// Distributed under the GULDEN software license, see the accompanying
// file COPYING

#include "transactiondesc.h"

#include "units.h"
#include "guiutil.h"
#include "paymentserver.h"
#include "transactionrecord.h"

#include "base58.h"
#include "consensus/consensus.h"
#include "validation/validation.h"
#include "script/script.h"
#include "timedata.h"
#include "util.h"
#include "wallet/db.h"
#include "wallet/wallet.h"

#include <stdint.h>
#include <string>

QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{
    AssertLockHeld(cs_main);
    if (!CheckFinalTx(wtx, chainActive))
    {
        if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
            return tr("Open for %n more block(s)", "", wtx.tx->nLockTime - chainActive.Height());
        else
            return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.tx->nLockTime));
    }
    else
    {
        int nDepth = wtx.GetDepthInMainChain();
        if (nDepth < 0)
            return tr("conflicted with a transaction with %1 confirmations").arg(-nDepth);
        else if (nDepth == 0)
            return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : "");
        else if (nDepth < 6)
            return tr("%1/unconfirmed").arg(nDepth);
        else
            return tr("%1 confirmations").arg(nDepth);
    }
}

QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
{
    QString strHTML;

    LOCK2(cs_main, wallet->cs_wallet);
    strHTML.reserve(4000);
    strHTML += "";

    int64_t nTime = wtx.GetTxTime();
    CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
    CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
    CAmount nNet = nCredit - nDebit;

    strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx);
    strHTML += "
";
    strHTML += "" + tr("Date") + ": " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "
";

    //
    // From
    //
    if (wtx.IsCoinBase())
    {
        strHTML += "" + tr("Source") + ": " + tr("Generated") + "
";
    }
    else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
    {
        // Online transaction
        strHTML += "" + tr("From") + ": " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "
";
    }
    else
    {
        // Offline transaction
        if (nNet > 0)
        {
            // Credit
            if (CGuldenAddress(rec->address).IsValid())
            {
                CTxDestination address = CGuldenAddress(rec->address).Get();
                if (wallet->mapAddressBook.count(rec->address))
                {
                    strHTML += "" + tr("From") + ": " + tr("unknown") + "
";
                    strHTML += "" + tr("To") + ": ";
                    strHTML += GUIUtil::HtmlEscape(rec->address);
                    QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only");
                    if (!wallet->mapAddressBook[CGuldenAddress(address).ToString()].name.empty())
                        strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[CGuldenAddress(address).ToString()].name) + ")";
                    else
                        strHTML += " (" + addressOwned + ")";
                    strHTML += "
";
                }
            }
        }
    }

    //
    // To
    //
    if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
    {
        // Online transaction
        std::string strAddress = wtx.mapValue["to"];
        strHTML += "" + tr("To") + ": ";
        if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].name.empty())
            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[strAddress].name) + " ";
        strHTML += GUIUtil::HtmlEscape(strAddress) + "
";
    }

    //
    // Amount
    //
    if (wtx.IsCoinBase() && nCredit == 0)
    {
        //
        // Coinbase
        //
        CAmount nUnmatured = 0;
        for(const CTxOut& txout : wtx.tx->vout)
            nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
        strHTML += "" + tr("Credit") + ": ";
        if (wtx.IsInMainChain())
        {
            if (wtx.IsCoinBase())
            {
                strHTML += GuldenUnits::formatHtmlWithUnit(unit, nUnmatured - nDebit)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
            }
            else
            {
                strHTML += GuldenUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
            }
        }
        else
            strHTML += "(" + tr("not accepted") + ")";
        strHTML += "
";
    }
    else if (nNet > 0)
    {
        //
        // Credit
        //
        strHTML += "" + tr("Credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, nNet) + "
";
    }
    else
    {
        isminetype fAllFromMe = ISMINE_SPENDABLE;
        for(const CTxIn& txin : wtx.tx->vin)
        {
            isminetype mine = wallet->IsMine(txin);
            if(fAllFromMe > mine) fAllFromMe = mine;
        }

        isminetype fAllToMe = ISMINE_SPENDABLE;
        for(const CTxOut& txout : wtx.tx->vout)
        {
            isminetype mine = wallet->IsMine(txout);
            if(fAllToMe > mine) fAllToMe = mine;
        }

        if (fAllFromMe)
        {
            if(fAllFromMe & ISMINE_WATCH_ONLY)
                strHTML += "" + tr("From") + ": " + tr("watch-only") + "
";

            //
            // Debit
            //
            for(const CTxOut& txout : wtx.tx->vout)
            {
                // Ignore change
                isminetype toSelf = wallet->IsMine(txout);
                if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE))
                    continue;

                if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
                {
                    // Offline transaction
                    CTxDestination address;
                    if (ExtractDestination(txout, address))
                    {
                        strHTML += "" + tr("To") + ": ";
                        if (wallet->mapAddressBook.count(CGuldenAddress(address).ToString()) && !wallet->mapAddressBook[CGuldenAddress(address).ToString()].name.empty())
                            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[CGuldenAddress(address).ToString()].name) + " ";
                        strHTML += GUIUtil::HtmlEscape(CGuldenAddress(address).ToString());
                        if(toSelf == ISMINE_SPENDABLE)
                            strHTML += " (own address)";
                        else if(toSelf & ISMINE_WATCH_ONLY)
                            strHTML += " (watch-only)";
                        strHTML += "
";
                    }
                }

                strHTML += "" + tr("Debit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -txout.nValue) + "
";
                if(toSelf)
                    strHTML += "" + tr("Credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, txout.nValue) + "
";
            }

            if (fAllToMe)
            {
                // Payment to self
                CAmount nChange = wtx.GetChange();
                CAmount nValue = nCredit - nChange;
                if (nValue != 0)
                {
                    strHTML += "" + tr("Total debit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -nValue) + "
";
                    strHTML += "" + tr("Total credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, nValue) + "
";
                }
                else
                {
                    strHTML += "" + tr("Total moved") + ": " + GuldenUnits::formatHtmlWithUnit(unit, nCredit) + "
";
                }
            }

            CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
            if (nTxFee > 0)
                strHTML += "" + tr("Transaction fee") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -nTxFee) + "
";
        }
        else
        {
            //
            // Mixed debit transaction
            //
            for(const CTxIn& txin : wtx.tx->vin)
                if (wallet->IsMine(txin))
                    strHTML += "" + tr("Debit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
";
            for(const CTxOut& txout : wtx.tx->vout)
                if (wallet->IsMine(txout))
                    strHTML += "" + tr("Credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
";
        }
    }

    if (!wtx.IsCoinBase())
    {
        strHTML += "" + tr("Net amount") + ": " + GuldenUnits::formatHtmlWithUnit(unit, nNet, true) + "
";
    }

    //
    // Message
    //
    if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
        strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "
";
    if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
        strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
";

    strHTML += "" + tr("Transaction ID") + ": " + rec->getTxID() + "
";
    strHTML += "" + tr("Transaction total size") + ": " + QString::number(wtx.tx->GetTotalSize()) + " bytes
";
    strHTML += "" + tr("Output index") + ": " + QString::number(rec->getOutputIndex()) + "
";

    // Message from normal Gulden:URI (Gulden:123...?message=example)
    for (const PAIRTYPE(std::string, std::string)& r : wtx.vOrderForm)
        if (r.first == "Message")
            strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(r.second, true) + "
";

    //
    // PaymentRequest info:
    //
    for (const PAIRTYPE(std::string, std::string)& r : wtx.vOrderForm)
    {
        if (r.first == "PaymentRequest")
        {
            PaymentRequestPlus req;
            req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
            QString merchant;
            if (req.getMerchant(PaymentServer::getCertStore(), merchant))
                strHTML += "" + tr("Merchant") + ": " + GUIUtil::HtmlEscape(merchant) + "
";
        }
    }

    if (wtx.IsCoinBase())
    {
        quint32 numBlocksToMaturity = COINBASE_MATURITY +  1;
        strHTML += "
" + tr("Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.").arg(QString::number(numBlocksToMaturity)) + "
";
    }

    //
    // Debug view
    //
    if (logCategories != BCLog::NONE)
    {
        strHTML += "

" + tr("Debug information") + "

";
        for(const CTxIn& txin : wtx.tx->vin)
            if(wallet->IsMine(txin))
                strHTML += "" + tr("Debit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
";
        for(const CTxOut& txout : wtx.tx->vout)
            if(wallet->IsMine(txout))
                strHTML += "" + tr("Credit") + ": " + GuldenUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
";

        strHTML += "
" + tr("Transaction") + ":
";
        strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true);

        strHTML += "
" + tr("Inputs") + ":";
        strHTML += "
";

        for(const CTxIn& txin : wtx.tx->vin)
        {
            COutPoint prevout = txin.prevout;

            Coin prev;
            if(pcoinsTip->GetCoin(prevout, prev))
            {
                {
                    strHTML += "
";
                    const CTxOut &vout = prev.out;
                    CTxDestination address;
                    if (ExtractDestination(vout, address))
                    {
                        if (wallet->mapAddressBook.count(CGuldenAddress(address).ToString()) && !wallet->mapAddressBook[CGuldenAddress(address).ToString()].name.empty())
                            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[CGuldenAddress(address).ToString()].name) + " ";
                        strHTML += QString::fromStdString(CGuldenAddress(address).ToString());
                    }
                    strHTML = strHTML + " " + tr("Amount") + "=" + GuldenUnits::formatHtmlWithUnit(unit, vout.nValue);
                    strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "
";
                    strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "
";
                }
            }
        }

        strHTML += "
";
    }

    strHTML += "";
    return strHTML;
}
<|endoftext|>