<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "SurgSim/Math/MeshShape.h"

#include "SurgSim/DataStructures/AabbTree.h"
#include "SurgSim/Framework/Log.h"
#include "SurgSim/Framework/ObjectFactory.h"

namespace
{
SURGSIM_REGISTER(SurgSim::Math::Shape, SurgSim::Math::MeshShape);
}

namespace SurgSim
{
namespace Math
{

MeshShape::MeshShape() : m_volume(0.0), m_fileName()
{
	SURGSIM_ADD_SERIALIZABLE_PROPERTY(MeshShape, std::string, FileName, getFileName, setFileName);
}

int MeshShape::getType()
{
	return SHAPE_TYPE_MESH;
}

void MeshShape::setFileName(const std::string& fileName)
{
	using SurgSim::DataStructures::TriangleMesh;
	m_fileName = fileName;
	m_initialMesh = std::make_shared<TriangleMesh>(*SurgSim::DataStructures::loadTriangleMesh(fileName));
	m_mesh = std::make_shared<TriangleMesh>(*m_initialMesh);
}

std::string MeshShape::getFileName() const
{
	return m_fileName;
}

std::shared_ptr<SurgSim::DataStructures::TriangleMesh> MeshShape::getMesh()
{
	return m_mesh;
}

double MeshShape::getVolume() const
{
	if (nullptr == m_mesh)
	{
		SURGSIM_LOG_CRITICAL(SurgSim::Framework::Logger::getDefaultLogger()) <<
			"No mesh set for MeshShape, so it cannot compute volume.";
	}
	return m_volume;
}

SurgSim::Math::Vector3d MeshShape::getCenter() const
{
	if (nullptr == m_mesh)
	{
		SURGSIM_LOG_CRITICAL(SurgSim::Framework::Logger::getDefaultLogger()) <<
			"No mesh set for MeshShape, so it cannot compute center.";
	}
	return m_center;
}

SurgSim::Math::Matrix33d MeshShape::getSecondMomentOfVolume() const
{
	if (nullptr == m_mesh)
	{
		SURGSIM_LOG_CRITICAL(SurgSim::Framework::Logger::getDefaultLogger()) <<
			"No mesh set for MeshShape, so it cannot compute SecondMomentOfVolume.";
	}
	return m_secondMomentOfVolume;
}

namespace
{
/// Compute various integral terms
/// \note Please refer to http://www.geometrictools.com/Documentation/PolyhedralMassProperties.pdf
/// \note for details about parameters
void computeIntegralTerms(const double w0, const double w1, const double w2,
									 double* f1, double* f2, double* f3, double* g0, double* g1, double* g2)
{
	double temp0 = w0 + w1;
	double temp1 = w0 * w0;
	double temp2 = temp1 + w1 * temp0;
	*f1 = temp0 + w2;
	*f2 = temp2 + w2 * (*f1);
	*f3 = w0 * temp1 + w1 * temp2 + w2 * (*f2);
	*g0 = (*f2) + w0 * ((*f1) + w0);
	*g1 = (*f2) + w1 * ((*f1) + w1);
	*g2 = (*f2) + w2 * ((*f1) + w2);
}
};

void MeshShape::computeVolumeIntegrals()
{
	Eigen::VectorXd multiplier(10);
	multiplier << 1.0 / 6.0, 1.0 / 24.0, 1.0 / 24.0, 1.0 / 24.0, 1.0 / 60.0, 1.0 / 60.0, 1.0 / 60.0,
		1.0 / 120.0, 1.0 / 120.0, 1.0 / 120.0;

	Eigen::VectorXd integral(10); // integral order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
	integral.setZero();

	for (size_t t = 0; t < m_mesh->getNumTriangles(); t++)
	{
		// get vertices of triangle t
		const Vector3d& v0 = m_mesh->getVertexPosition(m_mesh->getTriangle(t).verticesId[0]);
		const Vector3d& v1 = m_mesh->getVertexPosition(m_mesh->getTriangle(t).verticesId[1]);
		const Vector3d& v2 = m_mesh->getVertexPosition(m_mesh->getTriangle(t).verticesId[2]);

		// get edges and cross product of edges
		Vector3d normal = (v1 - v0).cross(v2 - v0);

		// compute integral terms
		double f1x, f1y, f1z, f2x, f2y, f2z, f3x, f3y, f3z;
		double g0x, g0y, g0z, g1x, g1y, g1z, g2x, g2y, g2z;
		computeIntegralTerms(v0.x(), v1.x(), v2.x(), &f1x, &f2x, &f3x, &g0x, &g1x, &g2x);
		computeIntegralTerms(v0.y(), v1.y(), v2.y(), &f1y, &f2y, &f3y, &g0y, &g1y, &g2y);
		computeIntegralTerms(v0.z(), v1.z(), v2.z(), &f1z, &f2z, &f3z, &g0z, &g1z, &g2z);

		// update integrals
		integral[0] += normal[0] * f1x;
		integral[1] += normal[0] * f2x;
		integral[2] += normal[1] * f2y;
		integral[3] += normal[2] * f2z;
		integral[4] += normal[0] * f3x;
		integral[5] += normal[1] * f3y;
		integral[6] += normal[2] * f3z;
		integral[7] += normal[0] * (v0.y() * g0x + v1.y() * g1x + v2.y() * g2x);
		integral[8] += normal[1] * (v0.z() * g0y + v1.z() * g1y + v2.z() * g2y);
		integral[9] += normal[2] * (v0.x() * g0z + v1.x() * g1z + v2.x() * g2z);
	}
	integral = integral.cwiseProduct(multiplier);

	// volume
	m_volume = integral[0];

	// center of mass
	if (m_volume != 0.0)
	{
		m_center = integral.segment(1, 3) / m_volume;
	}
	else
	{
		m_center.setZero();
	}

	// second moment of volume relative to center
	Vector3d centerSquared = m_center.cwiseProduct(m_center);
	m_secondMomentOfVolume(0, 0) = integral[5] + integral[6] - m_volume * (centerSquared.y() + centerSquared.z());
	m_secondMomentOfVolume(1, 1) = integral[4] + integral[6] - m_volume * (centerSquared.z() + centerSquared.x());
	m_secondMomentOfVolume(2, 2) = integral[4] + integral[5] - m_volume * (centerSquared.x() + centerSquared.y());
	m_secondMomentOfVolume(0, 1) = -(integral[7] - m_volume * m_center.x() * m_center.y());
	m_secondMomentOfVolume(1, 0) = m_secondMomentOfVolume(0, 1);
	m_secondMomentOfVolume(1, 2) = -(integral[8] - m_volume * m_center.y() * m_center.z());
	m_secondMomentOfVolume(2, 1) = m_secondMomentOfVolume(1, 2);
	m_secondMomentOfVolume(0, 2) = -(integral[9] - m_volume * m_center.z() * m_center.x());
	m_secondMomentOfVolume(2, 0) = m_secondMomentOfVolume(0, 2);
}

void MeshShape::setGlobalPose(const SurgSim::Math::RigidTransform3d &pose)
{
	m_mesh->copyWithTransform(pose, *m_initialMesh);
}

std::shared_ptr<SurgSim::DataStructures::AabbTree> MeshShape::getAabbTree()
{
	return m_aabbTree;
}

void MeshShape::updateAabbTree()
{
	m_aabbTree = std::make_shared<SurgSim::DataStructures::AabbTree>();

	auto const& vertices = m_mesh->getVertices();
	auto const& triangles = m_mesh->getTriangles();

	for (size_t i = 0; i < triangles.size(); i++)
	{
		auto ids = triangles[i].verticesId;
		m_aabbTree->add(
			SurgSim::Math::makeAabb(vertices[ids[0]].position, vertices[ids[1]].position, vertices[ids[2]].position),
			i);
	}
}
}; // namespace Math
}; // namespace SurgSim
<commit_msg>MeshShape, refactor updateAabbTree<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "SurgSim/Math/MeshShape.h"

#include "SurgSim/DataStructures/AabbTree.h"
#include "SurgSim/Framework/Log.h"
#include "SurgSim/Framework/ObjectFactory.h"

namespace
{
SURGSIM_REGISTER(SurgSim::Math::Shape, SurgSim::Math::MeshShape);
}

namespace SurgSim
{
namespace Math
{

MeshShape::MeshShape() : m_volume(0.0), m_fileName()
{
	SURGSIM_ADD_SERIALIZABLE_PROPERTY(MeshShape, std::string, FileName, getFileName, setFileName);
}

int MeshShape::getType()
{
	return SHAPE_TYPE_MESH;
}

void MeshShape::setFileName(const std::string& fileName)
{
	using SurgSim::DataStructures::TriangleMesh;
	m_fileName = fileName;
	m_initialMesh = std::make_shared<TriangleMesh>(*SurgSim::DataStructures::loadTriangleMesh(fileName));
	m_mesh = std::make_shared<TriangleMesh>(*m_initialMesh);
}

std::string MeshShape::getFileName() const
{
	return m_fileName;
}

std::shared_ptr<SurgSim::DataStructures::TriangleMesh> MeshShape::getMesh()
{
	return m_mesh;
}

double MeshShape::getVolume() const
{
	if (nullptr == m_mesh)
	{
		SURGSIM_LOG_CRITICAL(SurgSim::Framework::Logger::getDefaultLogger()) <<
			"No mesh set for MeshShape, so it cannot compute volume.";
	}
	return m_volume;
}

SurgSim::Math::Vector3d MeshShape::getCenter() const
{
	if (nullptr == m_mesh)
	{
		SURGSIM_LOG_CRITICAL(SurgSim::Framework::Logger::getDefaultLogger()) <<
			"No mesh set for MeshShape, so it cannot compute center.";
	}
	return m_center;
}

SurgSim::Math::Matrix33d MeshShape::getSecondMomentOfVolume() const
{
	if (nullptr == m_mesh)
	{
		SURGSIM_LOG_CRITICAL(SurgSim::Framework::Logger::getDefaultLogger()) <<
			"No mesh set for MeshShape, so it cannot compute SecondMomentOfVolume.";
	}
	return m_secondMomentOfVolume;
}

namespace
{
/// Compute various integral terms
/// \note Please refer to http://www.geometrictools.com/Documentation/PolyhedralMassProperties.pdf
/// \note for details about parameters
void computeIntegralTerms(const double w0, const double w1, const double w2,
									 double* f1, double* f2, double* f3, double* g0, double* g1, double* g2)
{
	double temp0 = w0 + w1;
	double temp1 = w0 * w0;
	double temp2 = temp1 + w1 * temp0;
	*f1 = temp0 + w2;
	*f2 = temp2 + w2 * (*f1);
	*f3 = w0 * temp1 + w1 * temp2 + w2 * (*f2);
	*g0 = (*f2) + w0 * ((*f1) + w0);
	*g1 = (*f2) + w1 * ((*f1) + w1);
	*g2 = (*f2) + w2 * ((*f1) + w2);
}
};

void MeshShape::computeVolumeIntegrals()
{
	Eigen::VectorXd multiplier(10);
	multiplier << 1.0 / 6.0, 1.0 / 24.0, 1.0 / 24.0, 1.0 / 24.0, 1.0 / 60.0, 1.0 / 60.0, 1.0 / 60.0,
		1.0 / 120.0, 1.0 / 120.0, 1.0 / 120.0;

	Eigen::VectorXd integral(10); // integral order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
	integral.setZero();

	for (size_t t = 0; t < m_mesh->getNumTriangles(); t++)
	{
		// get vertices of triangle t
		const Vector3d& v0 = m_mesh->getVertexPosition(m_mesh->getTriangle(t).verticesId[0]);
		const Vector3d& v1 = m_mesh->getVertexPosition(m_mesh->getTriangle(t).verticesId[1]);
		const Vector3d& v2 = m_mesh->getVertexPosition(m_mesh->getTriangle(t).verticesId[2]);

		// get edges and cross product of edges
		Vector3d normal = (v1 - v0).cross(v2 - v0);

		// compute integral terms
		double f1x, f1y, f1z, f2x, f2y, f2z, f3x, f3y, f3z;
		double g0x, g0y, g0z, g1x, g1y, g1z, g2x, g2y, g2z;
		computeIntegralTerms(v0.x(), v1.x(), v2.x(), &f1x, &f2x, &f3x, &g0x, &g1x, &g2x);
		computeIntegralTerms(v0.y(), v1.y(), v2.y(), &f1y, &f2y, &f3y, &g0y, &g1y, &g2y);
		computeIntegralTerms(v0.z(), v1.z(), v2.z(), &f1z, &f2z, &f3z, &g0z, &g1z, &g2z);

		// update integrals
		integral[0] += normal[0] * f1x;
		integral[1] += normal[0] * f2x;
		integral[2] += normal[1] * f2y;
		integral[3] += normal[2] * f2z;
		integral[4] += normal[0] * f3x;
		integral[5] += normal[1] * f3y;
		integral[6] += normal[2] * f3z;
		integral[7] += normal[0] * (v0.y() * g0x + v1.y() * g1x + v2.y() * g2x);
		integral[8] += normal[1] * (v0.z() * g0y + v1.z() * g1y + v2.z() * g2y);
		integral[9] += normal[2] * (v0.x() * g0z + v1.x() * g1z + v2.x() * g2z);
	}
	integral = integral.cwiseProduct(multiplier);

	// volume
	m_volume = integral[0];

	// center of mass
	if (m_volume != 0.0)
	{
		m_center = integral.segment(1, 3) / m_volume;
	}
	else
	{
		m_center.setZero();
	}

	// second moment of volume relative to center
	Vector3d centerSquared = m_center.cwiseProduct(m_center);
	m_secondMomentOfVolume(0, 0) = integral[5] + integral[6] - m_volume * (centerSquared.y() + centerSquared.z());
	m_secondMomentOfVolume(1, 1) = integral[4] + integral[6] - m_volume * (centerSquared.z() + centerSquared.x());
	m_secondMomentOfVolume(2, 2) = integral[4] + integral[5] - m_volume * (centerSquared.x() + centerSquared.y());
	m_secondMomentOfVolume(0, 1) = -(integral[7] - m_volume * m_center.x() * m_center.y());
	m_secondMomentOfVolume(1, 0) = m_secondMomentOfVolume(0, 1);
	m_secondMomentOfVolume(1, 2) = -(integral[8] - m_volume * m_center.y() * m_center.z());
	m_secondMomentOfVolume(2, 1) = m_secondMomentOfVolume(1, 2);
	m_secondMomentOfVolume(0, 2) = -(integral[9] - m_volume * m_center.z() * m_center.x());
	m_secondMomentOfVolume(2, 0) = m_secondMomentOfVolume(0, 2);
}

void MeshShape::setGlobalPose(const SurgSim::Math::RigidTransform3d &pose)
{
	m_mesh->copyWithTransform(pose, *m_initialMesh);
}

std::shared_ptr<SurgSim::DataStructures::AabbTree> MeshShape::getAabbTree()
{
	return m_aabbTree;
}

void MeshShape::updateAabbTree()
{
	using SurgSim::Math::makeAabb;

	m_aabbTree = std::make_shared<SurgSim::DataStructures::AabbTree>();

	auto const& vertices = m_mesh->getVertices();
	auto const& triangles = m_mesh->getTriangles();

	size_t i = 0;
	for (auto triangle = triangles.begin(); triangle != triangles.end(); ++triangle)
	{
		auto& ids = triangle->verticesId;
		m_aabbTree->add(makeAabb(vertices[ids[0]].position, vertices[ids[1]].position, vertices[ids[2]].position), i++);
	}
}
}; // namespace Math
}; // namespace SurgSim
<|endoftext|>


<commit_before>#include <catch.hpp>

//#define FEATURE_ESTD_EXPLICIT_OBSERVER

#include <platform/generic/datapump-messageobserver.hpp>
#include <embr/datapump.hpp>
#include "coap/decoder/subject.hpp"

#include "test-data.h"
#include "test-observer.h"

#include <estd/exp/observer.h>

using namespace moducom::coap;
using namespace embr;

typedef moducom::io::experimental::NetBufDynamicMemory<> netbuf_t;
typedef uint32_t addr_t;
typedef TransportDescriptor<netbuf_t, addr_t> transport_descriptor_t;
typedef DataPump<transport_descriptor_t> datapump_t;
typedef datapump_t::Item item_t;

struct DatapumpObserver
{
    // thought const& would be necessary because of lack of copy constructors, but nope
    static void on_notify(moducom::coap::experimental::event::ReceiveDequeued<item_t> e)
    {
        REQUIRE(e.item.addr() == 0);
    }
};

TEST_CASE("Data pump tests", "[datapump]")
{
    SECTION("Datapump")
    {
        //typedef moducom::io::experimental::layer2::NetBufMemory<512> netbuf_t;
        //typedef moducom::io::experimental::NetBufDynamicMemory<> netbuf_t;
        //typedef uint32_t addr_t;

        // will only work if I make it <const char, but then
        // s.copy won't work since it wants to output to value_type*
        // which will be const char*
        //const estd::layer2::basic_string<char, 4> s = "Hi2u";

        datapump_t datapump;
        addr_t addr;

        netbuf_t netbuf;

        moducom::io::experimental::NetBufWriter<netbuf_t&> writer(netbuf);

        //writer.write(s);

        writer.write("hi2u", 4);

#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
        datapump.enqueue_out(std::move(writer.netbuf()), addr);
#else
        datapump.enqueue_out(writer.netbuf(), addr);
#endif

        datapump_t::Item& item = datapump.transport_front();
        netbuf_t* to_transport = item.netbuf();
        addr = item.addr();

        REQUIRE(to_transport != NULLPTR);

        const uint8_t* p = to_transport->processed();

        REQUIRE(p[0] == 'h');

    }
    SECTION("full synthetic request")
    {
        // FIX: Need to resolve end() behavior.  It's more efficient for end() to represent
        // that we are *ON* the end marker, but it's smoother code to have end() represent
        // -just past- the end, ala std iterator behaviors

        // set up netbuf-writer, datapump
        //typedef moducom::io::experimental::NetBufDynamicMemory<> netbuf_t;
        //typedef uint32_t addr_t;

#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
        moducom::io::experimental::NetBufWriter<netbuf_t> writer;
#else
        // FIX: doing this because of floating 'delete' within process_messageobserver
        // clearly not ideal
        netbuf_t* netbuf = new netbuf_t;

        moducom::io::experimental::NetBufWriter<netbuf_t&> writer(*netbuf);
#endif
        datapump_t datapump;

        // push synthetic incoming coap request data into netbuf via writer
        writer.write(buffer_16bit_delta, sizeof(buffer_16bit_delta));

        // Now take that synthetic netbuf data and simulates a transport input
        // on datapump
#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
        netbuf_t netbuf_copy = writer.netbuf();
        datapump.transport_in(std::move(writer.netbuf()), 0);
#else
        datapump.transport_in(writer.netbuf(), 0);
#endif

        // set up message subject+observer
        IncomingContext<addr_t> test_ctx;
        DecoderSubjectBase<moducom::coap::experimental::ContextDispatcherHandler<IncomingContext<addr_t> > > test(test_ctx);

        REQUIRE(!test_ctx.have_header());

        // now service the datapump with the 'test' DecoderSubject pushing out
        // to the message observer
        process_messageobserver(datapump, test);

        // Assert that ContextDispatcherHandler indeed parsed the incoming message
        REQUIRE(test_ctx.have_header());
        REQUIRE(test_ctx.header().message_id() == 0x0123);

#ifdef FEATURE_CPP_DECLTYPE
        // Requeue same synthetic data again for another test
#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
        datapump.transport_in(std::move(netbuf_copy), 0);
#else
        datapump.transport_in(writer.netbuf(), 0);
#endif

        SECTION("Experimental datapump dequeuing test")
        {
            estd::experimental::internal::stateless_subject<DatapumpObserver> s;

            process_messageobserver2(datapump, s);
        }
#endif
    }
}
<commit_msg>API collision test<commit_after>#include <catch.hpp>

//#define FEATURE_ESTD_EXPLICIT_OBSERVER

#include <platform/generic/datapump-messageobserver.hpp>
#include <embr/datapump.hpp>
#include "coap/decoder/subject.hpp"

#include "test-data.h"
#include "test-observer.h"

#include <estd/exp/observer.h>

//#define putchar(c) put_value(c)

using namespace moducom::coap;
using namespace embr;

typedef moducom::io::experimental::NetBufDynamicMemory<> netbuf_t;
typedef uint32_t addr_t;
typedef TransportDescriptor<netbuf_t, addr_t> transport_descriptor_t;
typedef DataPump<transport_descriptor_t> datapump_t;
typedef datapump_t::Item item_t;

struct DatapumpObserver
{
    // thought const& would be necessary because of lack of copy constructors, but nope
    static void on_notify(moducom::coap::experimental::event::ReceiveDequeued<item_t> e)
    {
        REQUIRE(e.item.addr() == 0);
    }
};

TEST_CASE("Data pump tests", "[datapump]")
{
    SECTION("Datapump")
    {
        //typedef moducom::io::experimental::layer2::NetBufMemory<512> netbuf_t;
        //typedef moducom::io::experimental::NetBufDynamicMemory<> netbuf_t;
        //typedef uint32_t addr_t;

        // will only work if I make it <const char, but then
        // s.copy won't work since it wants to output to value_type*
        // which will be const char*
        //const estd::layer2::basic_string<char, 4> s = "Hi2u";

        datapump_t datapump;
        addr_t addr;

        netbuf_t netbuf;

        moducom::io::experimental::NetBufWriter<netbuf_t&> writer(netbuf);

        //writer.write(s);

        writer.write("hi2u", 4);

#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
        datapump.enqueue_out(std::move(writer.netbuf()), addr);
#else
        datapump.enqueue_out(writer.netbuf(), addr);
#endif

        datapump_t::Item& item = datapump.transport_front();
        netbuf_t* to_transport = item.netbuf();
        addr = item.addr();

        REQUIRE(to_transport != NULLPTR);

        const uint8_t* p = to_transport->processed();

        REQUIRE(p[0] == 'h');

    }
    SECTION("API collision test")
    {
        netbuf_t netbuf;

        moducom::io::experimental::NetBufWriter<netbuf_t&> writer(netbuf);

        writer.putchar(0x77);

        REQUIRE(netbuf.processed()[0] == 0x77);
    }
    SECTION("full synthetic request")
    {
        // FIX: Need to resolve end() behavior.  It's more efficient for end() to represent
        // that we are *ON* the end marker, but it's smoother code to have end() represent
        // -just past- the end, ala std iterator behaviors

        // set up netbuf-writer, datapump
        //typedef moducom::io::experimental::NetBufDynamicMemory<> netbuf_t;
        //typedef uint32_t addr_t;

#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
        moducom::io::experimental::NetBufWriter<netbuf_t> writer;
#else
        // FIX: doing this because of floating 'delete' within process_messageobserver
        // clearly not ideal
        netbuf_t* netbuf = new netbuf_t;

        moducom::io::experimental::NetBufWriter<netbuf_t&> writer(*netbuf);
#endif
        datapump_t datapump;

        // push synthetic incoming coap request data into netbuf via writer
        writer.write(buffer_16bit_delta, sizeof(buffer_16bit_delta));

        // Now take that synthetic netbuf data and simulates a transport input
        // on datapump
#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
        netbuf_t netbuf_copy = writer.netbuf();
        datapump.transport_in(std::move(writer.netbuf()), 0);
#else
        datapump.transport_in(writer.netbuf(), 0);
#endif

        // set up message subject+observer
        IncomingContext<addr_t> test_ctx;
        DecoderSubjectBase<moducom::coap::experimental::ContextDispatcherHandler<IncomingContext<addr_t> > > test(test_ctx);

        REQUIRE(!test_ctx.have_header());

        // now service the datapump with the 'test' DecoderSubject pushing out
        // to the message observer
        process_messageobserver(datapump, test);

        // Assert that ContextDispatcherHandler indeed parsed the incoming message
        REQUIRE(test_ctx.have_header());
        REQUIRE(test_ctx.header().message_id() == 0x0123);

#ifdef FEATURE_CPP_DECLTYPE
        // Requeue same synthetic data again for another test
#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
        datapump.transport_in(std::move(netbuf_copy), 0);
#else
        datapump.transport_in(writer.netbuf(), 0);
#endif

        SECTION("Experimental datapump dequeuing test")
        {
            estd::experimental::internal::stateless_subject<DatapumpObserver> s;

            process_messageobserver2(datapump, s);
        }
#endif
    }
}
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#ifndef LIBREALSENSE_RS2_EXPORT_HPP
#define LIBREALSENSE_RS2_EXPORT_HPP

#include <map>
#include <fstream>
#include <cmath>
#include <sstream>
#include <cassert>
#include "rs_processing.hpp"
#include "rs_internal.hpp"

namespace rs2
{
    class save_to_ply : public filter
    {
    public:
        save_to_ply(std::string filename = "RealSense Pointcloud ", pointcloud pc = pointcloud())
            : filter([this](frame f, frame_source& s) { func(f, s); }),
            _pc(std::move(pc)), fname(filename)
        {
            register_simple_option(OPTION_IGNORE_COLOR, option_range{ 0, 1, 0, 1 });
        }

        static const auto OPTION_IGNORE_COLOR = rs2_option(RS2_OPTION_COUNT + 1);
    private:
        void func(frame data, frame_source& source)
        {
            frame depth, color;
            if (auto fs = data.as<frameset>()) {
                for (auto f : fs) {
                    if (f.is<points>()) depth = f;
                    else if (!depth && f.is<depth_frame>()) depth = f;
                    else if (!color && f.is<video_frame>()) color = f;
                }
            } else if (data.is<depth_frame>() || data.is<points>()) {
                depth = data;
            }

            if (!depth) throw std::runtime_error("Need depth data to save PLY");
            if (!depth.is<points>()) {
                if (color) _pc.map_to(color);
                depth = _pc.calculate(depth);
            }

            export_to_ply(depth, color);
            source.frame_ready(data); // passthrough filter because processing_block::process doesn't support sinks
        }

        void export_to_ply(points p, video_frame color) {
            const bool use_texcoords = color && !get_option(OPTION_IGNORE_COLOR);
            const auto verts = p.get_vertices();
            const auto texcoords = p.get_texture_coordinates();
            std::vector<rs2::vertex> new_verts;
            std::vector<std::array<uint8_t, 3>> new_tex;
            std::map<int, int> idx_map;

            new_verts.reserve(p.size());
            if (use_texcoords) new_tex.reserve(p.size());

            static const auto min_distance = 1e-6;

            for (size_t i = 0; i < p.size(); ++i) {
                if (fabs(verts[i].x) >= min_distance || fabs(verts[i].y) >= min_distance ||
                    fabs(verts[i].z) >= min_distance)
                {
                    idx_map[i] = new_verts.size();
                    new_verts.push_back(verts[i]);
                    if (use_texcoords)
                    {
                        auto rgb = get_texcolor(color, texcoords[i].u, texcoords[i].v);
                        new_tex.push_back(rgb);
                    }
                }
            }

            auto profile = p.get_profile().as<video_stream_profile>();
            auto width = profile.width(), height = profile.height();
            static const auto threshold = 0.05f;
            std::vector<std::array<int, 3>> faces;
            for (int x = 0; x < width - 1; ++x) {
                for (int y = 0; y < height - 1; ++y) {
                    auto a = y * width + x, b = y * width + x + 1, c = (y + 1)*width + x, d = (y + 1)*width + x + 1;
                    if (verts[a].z && verts[b].z && verts[c].z && verts[d].z
                        && fabs(verts[a].z - verts[b].z) < threshold && fabs(verts[a].z - verts[c].z) < threshold
                        && fabs(verts[b].z - verts[d].z) < threshold && fabs(verts[c].z - verts[d].z) < threshold)
                    {
                        if (idx_map.count(a) == 0 || idx_map.count(b) == 0 || idx_map.count(c) == 0 ||
                            idx_map.count(d) == 0)
                            continue;
                        faces.push_back({ idx_map[a], idx_map[b], idx_map[d] });
                        faces.push_back({ idx_map[d], idx_map[c], idx_map[a] });
                    }
                }
            }

            std::stringstream name;
            name << fname << p.get_frame_number() << ".ply";
            std::ofstream out(name.str());
            out << "ply\n";
            out << "format binary_little_endian 1.0\n";
            out << "comment pointcloud saved from Realsense Viewer\n";
            out << "element vertex " << new_verts.size() << "\n";
            out << "property float" << sizeof(float) * 8 << " x\n";
            out << "property float" << sizeof(float) * 8 << " y\n";
            out << "property float" << sizeof(float) * 8 << " z\n";
            if (use_texcoords)
            {
                out << "property uchar red\n";
                out << "property uchar green\n";
                out << "property uchar blue\n";
            }
            out << "element face " << faces.size() << "\n";
            out << "property list uchar int vertex_indices\n";
            out << "end_header\n";
            out.close();

            out.open(name.str(), std::ios_base::app | std::ios_base::binary);
            for (int i = 0; i < new_verts.size(); ++i)
            {
                // we assume little endian architecture on your device
                out.write(reinterpret_cast<const char*>(&(new_verts[i].x)), sizeof(float));
                out.write(reinterpret_cast<const char*>(&(new_verts[i].y)), sizeof(float));
                out.write(reinterpret_cast<const char*>(&(new_verts[i].z)), sizeof(float));

                if (use_texcoords)
                {
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][0])), sizeof(uint8_t));
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][1])), sizeof(uint8_t));
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][2])), sizeof(uint8_t));
                }
            }
            auto size = faces.size();
            for (int i = 0; i < size; ++i) {
                static const int three = 3;
                out.write(reinterpret_cast<const char*>(&three), sizeof(uint8_t));
                out.write(reinterpret_cast<const char*>(&(faces[i][0])), sizeof(int));
                out.write(reinterpret_cast<const char*>(&(faces[i][1])), sizeof(int));
                out.write(reinterpret_cast<const char*>(&(faces[i][2])), sizeof(int));
            }
        }

        // TODO: get_texcolor, options API
        std::array<uint8_t, 3> get_texcolor(const video_frame& texture, float u, float v)
        {
            const int w = texture.get_width(), h = texture.get_height();
            int x = std::min(std::max(int(u*w + .5f), 0), w - 1);
            int y = std::min(std::max(int(v*h + .5f), 0), h - 1);
            int idx = x * texture.get_bytes_per_pixel() + y * texture.get_stride_in_bytes();
            const auto texture_data = reinterpret_cast<const uint8_t*>(texture.get_data());
            return { texture_data[idx], texture_data[idx + 1], texture_data[idx + 2] };
        }

        std::string fname;
        pointcloud _pc;
    };

    class save_single_frameset : public filter {
    public:
        save_single_frameset(std::string filename = "RealSense Frameset ")
            : filter([this](frame f, frame_source& s) { save(f, s); }), fname(filename)
        {}

    private:
        void save(frame data, frame_source& source, bool do_signal=true)
        {
            software_device dev;

            std::vector<std::tuple<software_sensor, stream_profile, int>> sensors;
            std::vector<std::tuple<stream_profile, stream_profile>> extrinsics;

            if (auto fs = data.as<frameset>()) {
                int uid = 0;
                for (int i = 0; i < fs.size(); ++i) {
                    frame f = fs[i];
                    auto profile = f.get_profile();
                    std::stringstream sname;
                    sname << "Sensor (" << uid << ")";
                    auto s = dev.add_sensor(sname.str());
                    stream_profile software_profile;

                    if (auto vf = f.as<video_frame>()) {
                        auto vp = profile.as<video_stream_profile>();
                        rs2_video_stream stream{ vp.stream_type(), vp.stream_index(), uid++, vp.width(), vp.height(), vp.fps(), vf.get_bytes_per_pixel(), vp.format(), vp.get_intrinsics() };
                        software_profile = s.add_video_stream(stream);
                        if (f.is<rs2::depth_frame>()) {
                            auto ds = sensor_from_frame(f)->as<rs2::depth_sensor>();
                            s.add_read_only_option(RS2_OPTION_DEPTH_UNITS, ds.get_option(RS2_OPTION_DEPTH_UNITS));
                        }
                    } else if (f.is<motion_frame>()) {
                        auto mp = profile.as<motion_stream_profile>();
                        rs2_motion_stream stream{ mp.stream_type(), mp.stream_index(), uid++, mp.fps(), mp.format(), mp.get_motion_intrinsics() };
                        software_profile = s.add_motion_stream(stream);
                    } else if (f.is<pose_frame>()) {
                        rs2_pose_stream stream{ profile.stream_type(), profile.stream_index(), uid++, profile.fps(), profile.format() };
                        software_profile = s.add_pose_stream(stream);
                    } else {
                        // TODO: How to handle other frame types? (e.g. points)
                        assert(false);
                    }
                    sensors.emplace_back(s, software_profile, i);

                    bool found_extrin = false;
                    for (auto& root : extrinsics) {
                        try {
                            std::get<0>(root).register_extrinsics_to(software_profile,
                                std::get<1>(root).get_extrinsics_to(profile)
                            );
                            found_extrin = true;
                            break;
                        } catch (...) {}
                    }
                    if (!found_extrin) {
                        extrinsics.emplace_back(software_profile, profile);
                    }
                }

                // Recorder needs sensors to already exist when its created
                std::stringstream name;
                name << fname << data.get_frame_number() << ".bag";
                recorder rec(name.str(), dev);

                for (auto group : sensors) {
                    auto s = std::get<0>(group);
                    auto profile = std::get<1>(group);
                    s.open(profile);
                    s.start([](frame) {});
                    frame f = fs[std::get<2>(group)];
                    if (auto vf = f.as<video_frame>()) {
                        s.on_video_frame({ const_cast<void*>(vf.get_data()), [](void*) {}, vf.get_stride_in_bytes(), vf.get_bytes_per_pixel(),
                                           vf.get_timestamp(), vf.get_frame_timestamp_domain(), static_cast<int>(vf.get_frame_number()), profile });
                    } else if (f.is<motion_frame>()) {
                        s.on_motion_frame({ const_cast<void*>(f.get_data()), [](void*) {}, f.get_timestamp(),
                                            f.get_frame_timestamp_domain(), static_cast<int>(f.get_frame_number()), profile });
                    } else if (f.is<pose_frame>()) {
                        s.on_pose_frame({ const_cast<void*>(f.get_data()), [](void*) {}, f.get_timestamp(),
                                          f.get_frame_timestamp_domain(), static_cast<int>(f.get_frame_number()), profile });
                    }
                }
            } else {
                // single frame
                auto set = source.allocate_composite_frame({ data });
                save(set, source, false);
            }

            if (do_signal)
                source.frame_ready(data);
        }

        std::string fname;
    };
}

#endif<commit_msg>Remove redundant variable from rs_export.hpp<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#ifndef LIBREALSENSE_RS2_EXPORT_HPP
#define LIBREALSENSE_RS2_EXPORT_HPP

#include <map>
#include <fstream>
#include <cmath>
#include <sstream>
#include <cassert>
#include "rs_processing.hpp"
#include "rs_internal.hpp"

namespace rs2
{
    class save_to_ply : public filter
    {
    public:
        save_to_ply(std::string filename = "RealSense Pointcloud ", pointcloud pc = pointcloud())
            : filter([this](frame f, frame_source& s) { func(f, s); }),
            _pc(std::move(pc)), fname(filename)
        {
            register_simple_option(OPTION_IGNORE_COLOR, option_range{ 0, 1, 0, 1 });
        }

        static const auto OPTION_IGNORE_COLOR = rs2_option(RS2_OPTION_COUNT + 1);
    private:
        void func(frame data, frame_source& source)
        {
            frame depth, color;
            if (auto fs = data.as<frameset>()) {
                for (auto f : fs) {
                    if (f.is<points>()) depth = f;
                    else if (!depth && f.is<depth_frame>()) depth = f;
                    else if (!color && f.is<video_frame>()) color = f;
                }
            } else if (data.is<depth_frame>() || data.is<points>()) {
                depth = data;
            }

            if (!depth) throw std::runtime_error("Need depth data to save PLY");
            if (!depth.is<points>()) {
                if (color) _pc.map_to(color);
                depth = _pc.calculate(depth);
            }

            export_to_ply(depth, color);
            source.frame_ready(data); // passthrough filter because processing_block::process doesn't support sinks
        }

        void export_to_ply(points p, video_frame color) {
            const bool use_texcoords = color && !get_option(OPTION_IGNORE_COLOR);
            const auto verts = p.get_vertices();
            const auto texcoords = p.get_texture_coordinates();
            std::vector<rs2::vertex> new_verts;
            std::vector<std::array<uint8_t, 3>> new_tex;
            std::map<int, int> idx_map;

            new_verts.reserve(p.size());
            if (use_texcoords) new_tex.reserve(p.size());

            static const auto min_distance = 1e-6;

            for (size_t i = 0; i < p.size(); ++i) {
                if (fabs(verts[i].x) >= min_distance || fabs(verts[i].y) >= min_distance ||
                    fabs(verts[i].z) >= min_distance)
                {
                    idx_map[i] = new_verts.size();
                    new_verts.push_back(verts[i]);
                    if (use_texcoords)
                    {
                        auto rgb = get_texcolor(color, texcoords[i].u, texcoords[i].v);
                        new_tex.push_back(rgb);
                    }
                }
            }

            auto profile = p.get_profile().as<video_stream_profile>();
            auto width = profile.width(), height = profile.height();
            static const auto threshold = 0.05f;
            std::vector<std::array<int, 3>> faces;
            for (int x = 0; x < width - 1; ++x) {
                for (int y = 0; y < height - 1; ++y) {
                    auto a = y * width + x, b = y * width + x + 1, c = (y + 1)*width + x, d = (y + 1)*width + x + 1;
                    if (verts[a].z && verts[b].z && verts[c].z && verts[d].z
                        && fabs(verts[a].z - verts[b].z) < threshold && fabs(verts[a].z - verts[c].z) < threshold
                        && fabs(verts[b].z - verts[d].z) < threshold && fabs(verts[c].z - verts[d].z) < threshold)
                    {
                        if (idx_map.count(a) == 0 || idx_map.count(b) == 0 || idx_map.count(c) == 0 ||
                            idx_map.count(d) == 0)
                            continue;
                        faces.push_back({ idx_map[a], idx_map[b], idx_map[d] });
                        faces.push_back({ idx_map[d], idx_map[c], idx_map[a] });
                    }
                }
            }

            std::stringstream name;
            name << fname << p.get_frame_number() << ".ply";
            std::ofstream out(name.str());
            out << "ply\n";
            out << "format binary_little_endian 1.0\n";
            out << "comment pointcloud saved from Realsense Viewer\n";
            out << "element vertex " << new_verts.size() << "\n";
            out << "property float" << sizeof(float) * 8 << " x\n";
            out << "property float" << sizeof(float) * 8 << " y\n";
            out << "property float" << sizeof(float) * 8 << " z\n";
            if (use_texcoords)
            {
                out << "property uchar red\n";
                out << "property uchar green\n";
                out << "property uchar blue\n";
            }
            out << "element face " << faces.size() << "\n";
            out << "property list uchar int vertex_indices\n";
            out << "end_header\n";
            out.close();

            out.open(name.str(), std::ios_base::app | std::ios_base::binary);
            for (int i = 0; i < new_verts.size(); ++i)
            {
                // we assume little endian architecture on your device
                out.write(reinterpret_cast<const char*>(&(new_verts[i].x)), sizeof(float));
                out.write(reinterpret_cast<const char*>(&(new_verts[i].y)), sizeof(float));
                out.write(reinterpret_cast<const char*>(&(new_verts[i].z)), sizeof(float));

                if (use_texcoords)
                {
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][0])), sizeof(uint8_t));
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][1])), sizeof(uint8_t));
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][2])), sizeof(uint8_t));
                }
            }
            auto size = faces.size();
            for (int i = 0; i < size; ++i) {
                static const int three = 3;
                out.write(reinterpret_cast<const char*>(&three), sizeof(uint8_t));
                out.write(reinterpret_cast<const char*>(&(faces[i][0])), sizeof(int));
                out.write(reinterpret_cast<const char*>(&(faces[i][1])), sizeof(int));
                out.write(reinterpret_cast<const char*>(&(faces[i][2])), sizeof(int));
            }
        }

        // TODO: get_texcolor, options API
        std::array<uint8_t, 3> get_texcolor(const video_frame& texture, float u, float v)
        {
            const int w = texture.get_width(), h = texture.get_height();
            int x = std::min(std::max(int(u*w + .5f), 0), w - 1);
            int y = std::min(std::max(int(v*h + .5f), 0), h - 1);
            int idx = x * texture.get_bytes_per_pixel() + y * texture.get_stride_in_bytes();
            const auto texture_data = reinterpret_cast<const uint8_t*>(texture.get_data());
            return { texture_data[idx], texture_data[idx + 1], texture_data[idx + 2] };
        }

        std::string fname;
        pointcloud _pc;
    };

    class save_single_frameset : public filter {
    public:
        save_single_frameset(std::string filename = "RealSense Frameset ")
            : filter([this](frame f, frame_source& s) { save(f, s); }), fname(filename)
        {}

    private:
        void save(frame data, frame_source& source, bool do_signal=true)
        {
            software_device dev;

            std::vector<std::tuple<software_sensor, stream_profile, int>> sensors;
            std::vector<std::tuple<stream_profile, stream_profile>> extrinsics;

            if (auto fs = data.as<frameset>()) {
                for (int i = 0; i < fs.size(); ++i) {
                    frame f = fs[i];
                    auto profile = f.get_profile();
                    std::stringstream sname;
                    sname << "Sensor (" << i << ")";
                    auto s = dev.add_sensor(sname.str());
                    stream_profile software_profile;

                    if (auto vf = f.as<video_frame>()) {
                        auto vp = profile.as<video_stream_profile>();
                        rs2_video_stream stream{ vp.stream_type(), vp.stream_index(), i, vp.width(), vp.height(), vp.fps(), vf.get_bytes_per_pixel(), vp.format(), vp.get_intrinsics() };
                        software_profile = s.add_video_stream(stream);
                        if (f.is<rs2::depth_frame>()) {
                            auto ds = sensor_from_frame(f)->as<rs2::depth_sensor>();
                            s.add_read_only_option(RS2_OPTION_DEPTH_UNITS, ds.get_option(RS2_OPTION_DEPTH_UNITS));
                        }
                    } else if (f.is<motion_frame>()) {
                        auto mp = profile.as<motion_stream_profile>();
                        rs2_motion_stream stream{ mp.stream_type(), mp.stream_index(), i, mp.fps(), mp.format(), mp.get_motion_intrinsics() };
                        software_profile = s.add_motion_stream(stream);
                    } else if (f.is<pose_frame>()) {
                        rs2_pose_stream stream{ profile.stream_type(), profile.stream_index(), i, profile.fps(), profile.format() };
                        software_profile = s.add_pose_stream(stream);
                    } else {
                        // TODO: How to handle other frame types? (e.g. points)
                        assert(false);
                    }
                    sensors.emplace_back(s, software_profile, i);

                    bool found_extrin = false;
                    for (auto& root : extrinsics) {
                        try {
                            std::get<0>(root).register_extrinsics_to(software_profile,
                                std::get<1>(root).get_extrinsics_to(profile)
                            );
                            found_extrin = true;
                            break;
                        } catch (...) {}
                    }
                    if (!found_extrin) {
                        extrinsics.emplace_back(software_profile, profile);
                    }
                }

                // Recorder needs sensors to already exist when its created
                std::stringstream name;
                name << fname << data.get_frame_number() << ".bag";
                recorder rec(name.str(), dev);

                for (auto group : sensors) {
                    auto s = std::get<0>(group);
                    auto profile = std::get<1>(group);
                    s.open(profile);
                    s.start([](frame) {});
                    frame f = fs[std::get<2>(group)];
                    if (auto vf = f.as<video_frame>()) {
                        s.on_video_frame({ const_cast<void*>(vf.get_data()), [](void*) {}, vf.get_stride_in_bytes(), vf.get_bytes_per_pixel(),
                                           vf.get_timestamp(), vf.get_frame_timestamp_domain(), static_cast<int>(vf.get_frame_number()), profile });
                    } else if (f.is<motion_frame>()) {
                        s.on_motion_frame({ const_cast<void*>(f.get_data()), [](void*) {}, f.get_timestamp(),
                                            f.get_frame_timestamp_domain(), static_cast<int>(f.get_frame_number()), profile });
                    } else if (f.is<pose_frame>()) {
                        s.on_pose_frame({ const_cast<void*>(f.get_data()), [](void*) {}, f.get_timestamp(),
                                          f.get_frame_timestamp_domain(), static_cast<int>(f.get_frame_number()), profile });
                    }
                    s.stop();
                    s.close();
                }
            } else {
                // single frame
                auto set = source.allocate_composite_frame({ data });
                save(set, source, false);
            }

            if (do_signal)
                source.frame_ready(data);
        }

        std::string fname;
    };
}

#endif<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef ATTRIBUTE_DESCRIPTOR
#define ATTRIBUTE_DESCRIPTOR

#include <string>

namespace mapnik {

enum eAttributeType {
    Integer=1,
    Float  =2,
    Double =3,
    String =4,
    Geometry=5,
    Object=6
};

class attribute_descriptor
{
public:
    attribute_descriptor(std::string const& name,unsigned type,
                         bool primary_key=false,
                         int size=-1,
                         int precision=-1)
        : name_(name),
          type_(type),
          primary_key_(primary_key),
          size_(size),
          precision_(precision) {}

    attribute_descriptor(attribute_descriptor const& other)
        : name_(other.name_),
          type_(other.type_),
          primary_key_(other.primary_key_),
          size_(other.size_),
          precision_(other.precision_) {}

    attribute_descriptor& operator=(attribute_descriptor const& other)
    {
        if (this == &other)
            return *this;
        name_=other.name_;
        type_=other.type_;
        primary_key_=other.primary_key_;
        size_=other.size_;
        precision_=other.precision_;
        return *this;
    }

    std::string const& get_name() const
    {
        return name_;
    }

    unsigned get_type() const
    {
        return type_;
    }

    bool is_primary_key() const
    {
        return primary_key_;
    }

    int get_size() const
    {
        return size_;
    }

    int get_precision() const
    {
        return precision_;
    }

private:
    std::string name_;
    int type_;
    bool primary_key_;
    int size_;
    int precision_;
};

template <typename charT,typename traits>
inline std::basic_ostream<charT,traits>&
operator << (std::basic_ostream<charT,traits>& out,
             attribute_descriptor const& ad)
{
    out << "name=" << ad.get_name() << "\n";
    out << "type=" << ad.get_type() << "\n";
    out << "size=" << ad.get_size() << "\n";
    return out;
}

}

#endif // ATTRIBUTE_DESCRIPTOR_HPP
<commit_msg>add mapnik::Boolean type so we can report attributes with boolean type - closes #795<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef ATTRIBUTE_DESCRIPTOR
#define ATTRIBUTE_DESCRIPTOR

#include <string>

namespace mapnik {

enum eAttributeType {
    Integer=1,
    Float  =2,
    Double =3,
    String =4,
    Boolean =5,
    Geometry=6,
    Object=7
};

class attribute_descriptor
{
public:
    attribute_descriptor(std::string const& name,unsigned type,
                         bool primary_key=false,
                         int size=-1,
                         int precision=-1)
        : name_(name),
          type_(type),
          primary_key_(primary_key),
          size_(size),
          precision_(precision) {}

    attribute_descriptor(attribute_descriptor const& other)
        : name_(other.name_),
          type_(other.type_),
          primary_key_(other.primary_key_),
          size_(other.size_),
          precision_(other.precision_) {}

    attribute_descriptor& operator=(attribute_descriptor const& other)
    {
        if (this == &other)
            return *this;
        name_=other.name_;
        type_=other.type_;
        primary_key_=other.primary_key_;
        size_=other.size_;
        precision_=other.precision_;
        return *this;
    }

    std::string const& get_name() const
    {
        return name_;
    }

    unsigned get_type() const
    {
        return type_;
    }

    bool is_primary_key() const
    {
        return primary_key_;
    }

    int get_size() const
    {
        return size_;
    }

    int get_precision() const
    {
        return precision_;
    }

private:
    std::string name_;
    int type_;
    bool primary_key_;
    int size_;
    int precision_;
};

template <typename charT,typename traits>
inline std::basic_ostream<charT,traits>&
operator << (std::basic_ostream<charT,traits>& out,
             attribute_descriptor const& ad)
{
    out << "name=" << ad.get_name() << "\n";
    out << "type=" << ad.get_type() << "\n";
    out << "size=" << ad.get_size() << "\n";
    return out;
}

}

#endif // ATTRIBUTE_DESCRIPTOR_HPP
<|endoftext|>


<commit_before>/*
 * Stateplex - A server-side actor model library.
 *
 * core/terminalreceiver.cpp
 *
 * (c) 2013 Henrik Hedberg <henrik.hedberg@innologies.fi>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * Authors: Henrik Hedberg
 */

#include "terminalreceiver.h"

#include <ostream>

namespace Stateplex {

void TerminalReceiver::receiveEnd()
{ }

void TerminalReceiver::receive(const String *string)
{
	std::cout << string->chars();
}
void TerminalReceiver::receive(Buffer<> *buffer)
{
	Size length;
	for (Buffer<>::Iterator iterator(buffer); iterator.hasCurrent(); iterator.advance(length)) {
		length = iterator.charBlockLength();
		std::cout << iterator.charBlock();
	}
}

}
<commit_msg>TerminalReceiver: fixed compilation issue<commit_after>/*
 * Stateplex - A server-side actor model library.
 *
 * core/terminalreceiver.cpp
 *
 * (c) 2013 Henrik Hedberg <henrik.hedberg@innologies.fi>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * Authors: Henrik Hedberg
 */

#include "terminalreceiver.h"

#include <iostream>

namespace Stateplex {

void TerminalReceiver::receiveEnd()
{ }

void TerminalReceiver::receive(const String *string)
{
	std::cout << string->chars();
}
void TerminalReceiver::receive(Buffer<> *buffer)
{
	Size length;
	for (Buffer<>::Iterator iterator(buffer); iterator.hasCurrent(); iterator.advance(length)) {
		length = iterator.charBlockLength();
		std::cout << iterator.charBlock();
	}
}

}
<|endoftext|>


<commit_before>/** \file include/pomerol/MatsubaraContainers.h
** \brief Templated container classes designed to store values of functions of Matsubara frequencies.
**
** \author Andrey Antipov (Andrey.E.Antipov@gmail.com)
** \author Igor Krivenko (Igor.S.Krivenko@gmail.com)
*/
#ifndef POMEROL_INCLUDE_POMEROL_MATSUBARACONTAINERS_H
#define POMEROL_INCLUDE_POMEROL_MATSUBARACONTAINERS_H

#include "Misc.hpp"

#include <cmath>
#include <vector>

namespace Pomerol {

// class MatsubaraContainer1
template<typename SourceObject>
class MatsubaraContainer1 {
    const SourceObject* pSource;
    ComplexVectorType Values;
    long NumberOfMatsubaras = 0;

public:

    MatsubaraContainer1(const SourceObject* pSource) : pSource(pSource) {}

    ComplexType operator()(long MatsubaraNumber) const
    {
        if(MatsubaraNumber < NumberOfMatsubaras && MatsubaraNumber >= -NumberOfMatsubaras)
            return Values(NumberOfMatsubaras+MatsubaraNumber);
        else {
            DEBUG("MatsubaraContainer1 at " << this << ": " <<
                  "cache miss for n = " << MatsubaraNumber <<
                  " (NumberOfMatsubaras = " << NumberOfMatsubaras <<
                  "), fetching a raw value from " << pSource
            );
            return pSource->value(MatsubaraNumber);
        }
    }

    void fill(long NumberOfMatsubaras)
    {
        this->NumberOfMatsubaras = NumberOfMatsubaras;
        Values.resize(2*NumberOfMatsubaras);
        for(long MatsubaraNum=-NumberOfMatsubaras; MatsubaraNum<NumberOfMatsubaras; MatsubaraNum++)
            Values[MatsubaraNum+NumberOfMatsubaras] = pSource->value(MatsubaraNum);
    }

    long getNumberOfMatsubaras() const { return NumberOfMatsubaras; }
};

// class MatsubaraContainer4
template<typename SourceObject>
class MatsubaraContainer4 {
    const SourceObject* pSource = nullptr;
    long NumberOfMatsubaras = 0;
    std::vector<ComplexMatrixType> Values;
    std::vector<long> FermionicIndexOffset;

public:

    MatsubaraContainer4() = default;

    ComplexType operator()(long MatsubaraNumber1, long MatsubaraNumber2, long MatsubaraNumber3) const;

    // calls pSource->value(MatsubaraNumber1,MatsubaraNumber2,MatsubaraNumber3)
    void fill(const SourceObject* pSource, long NumberOfMatsubaras);

    long getNumberOfMatsubaras() const { return NumberOfMatsubaras; }
};

template<typename SourceObject> inline
void MatsubaraContainer4<SourceObject>::fill(const SourceObject* pSource, long NumberOfMatsubaras)
{
    this->NumberOfMatsubaras = NumberOfMatsubaras;
    this->pSource = pSource;

    if(NumberOfMatsubaras == 0){
        Values.clear();
        FermionicIndexOffset.clear();
        return;
    }else{
        Values.resize(4*NumberOfMatsubaras-1);
        FermionicIndexOffset.resize(4*NumberOfMatsubaras-1);
    }

    // \omega_1 = \nu, \omega_3 = \nu', \omega_1+\omega_2 = \Omega
    for(long BosonicIndexV=0; BosonicIndexV<=4*NumberOfMatsubaras-2; ++BosonicIndexV){
        long BosonicIndex = BosonicIndexV - 2*NumberOfMatsubaras;
        long FermionicMatrixSize = 2*NumberOfMatsubaras - std::abs(BosonicIndex+1);
        Values[BosonicIndexV].resize(FermionicMatrixSize,FermionicMatrixSize);
        FermionicIndexOffset[BosonicIndexV] =
            (BosonicIndex < 0 ? 0 : BosonicIndex+1) -NumberOfMatsubaras;

        for(long NuIndexM=0; NuIndexM<FermionicMatrixSize; ++NuIndexM)
        for(long NupIndexM=0; NupIndexM<FermionicMatrixSize; ++NupIndexM) {
            long MatsubaraNumber1 = NuIndexM+FermionicIndexOffset[BosonicIndexV];
            long MatsubaraNumber2 = BosonicIndex - MatsubaraNumber1;
            long MatsubaraNumber3 = NupIndexM+FermionicIndexOffset[BosonicIndexV];
            Values[BosonicIndexV](NuIndexM,NupIndexM) =
                pSource->value(MatsubaraNumber1,MatsubaraNumber2,MatsubaraNumber3);
        }
    }
}

template<typename SourceObject> inline
ComplexType MatsubaraContainer4<SourceObject>::operator()(long MatsubaraNumber1, long MatsubaraNumber2, long MatsubaraNumber3) const
{
    long BosonicIndexV = MatsubaraNumber2 + MatsubaraNumber1 + 2*NumberOfMatsubaras;
    if(BosonicIndexV >=0 && BosonicIndexV <= 2*(2*NumberOfMatsubaras-1)){
        long NuIndexM = MatsubaraNumber1-FermionicIndexOffset[BosonicIndexV];
        long NupIndexM = MatsubaraNumber3-FermionicIndexOffset[BosonicIndexV];
        if(NuIndexM >= 0 && NuIndexM < Values[BosonicIndexV].rows() &&
           NupIndexM >= 0 && NupIndexM < Values[BosonicIndexV].cols())
            return Values[BosonicIndexV](NuIndexM,NupIndexM);
    }

    DEBUG("MatsubaraContainer4 at " << this << ": " <<
          "cache miss for n1 = " << MatsubaraNumber1 << ", " <<
          "n2 = " << MatsubaraNumber2 << ", " <<
          "n3 = " << MatsubaraNumber3 <<
          " (NumberOfMatsubaras = " << NumberOfMatsubaras <<
          "), fetching a raw value from " << pSource
    );

    return pSource->value(MatsubaraNumber1,MatsubaraNumber2,MatsubaraNumber3);
}

} // namespace Pomerol

#endif // #ifndef POMEROL_INCLUDE_POMEROL_MATSUBARACONTAINERS_H
<commit_msg>Remove unused class `MatsubaraContainer1`<commit_after>/** \file include/pomerol/MatsubaraContainers.h
** \brief Templated container classes designed to store values of functions of Matsubara frequencies.
**
** \author Andrey Antipov (Andrey.E.Antipov@gmail.com)
** \author Igor Krivenko (Igor.S.Krivenko@gmail.com)
*/
#ifndef POMEROL_INCLUDE_POMEROL_MATSUBARACONTAINERS_H
#define POMEROL_INCLUDE_POMEROL_MATSUBARACONTAINERS_H

#include "Misc.hpp"

#include <cmath>
#include <vector>

namespace Pomerol {

// class MatsubaraContainer4
template<typename SourceObject>
class MatsubaraContainer4 {
    const SourceObject* pSource = nullptr;
    long NumberOfMatsubaras = 0;
    std::vector<ComplexMatrixType> Values;
    std::vector<long> FermionicIndexOffset;

public:

    MatsubaraContainer4() = default;

    ComplexType operator()(long MatsubaraNumber1, long MatsubaraNumber2, long MatsubaraNumber3) const;

    // calls pSource->value(MatsubaraNumber1,MatsubaraNumber2,MatsubaraNumber3)
    void fill(const SourceObject* pSource, long NumberOfMatsubaras);

    long getNumberOfMatsubaras() const { return NumberOfMatsubaras; }
};

template<typename SourceObject> inline
void MatsubaraContainer4<SourceObject>::fill(const SourceObject* pSource, long NumberOfMatsubaras)
{
    this->NumberOfMatsubaras = NumberOfMatsubaras;
    this->pSource = pSource;

    if(NumberOfMatsubaras == 0){
        Values.clear();
        FermionicIndexOffset.clear();
        return;
    }else{
        Values.resize(4*NumberOfMatsubaras-1);
        FermionicIndexOffset.resize(4*NumberOfMatsubaras-1);
    }

    // \omega_1 = \nu, \omega_3 = \nu', \omega_1+\omega_2 = \Omega
    for(long BosonicIndexV=0; BosonicIndexV<=4*NumberOfMatsubaras-2; ++BosonicIndexV){
        long BosonicIndex = BosonicIndexV - 2*NumberOfMatsubaras;
        long FermionicMatrixSize = 2*NumberOfMatsubaras - std::abs(BosonicIndex+1);
        Values[BosonicIndexV].resize(FermionicMatrixSize,FermionicMatrixSize);
        FermionicIndexOffset[BosonicIndexV] =
            (BosonicIndex < 0 ? 0 : BosonicIndex+1) -NumberOfMatsubaras;

        for(long NuIndexM=0; NuIndexM<FermionicMatrixSize; ++NuIndexM)
        for(long NupIndexM=0; NupIndexM<FermionicMatrixSize; ++NupIndexM) {
            long MatsubaraNumber1 = NuIndexM+FermionicIndexOffset[BosonicIndexV];
            long MatsubaraNumber2 = BosonicIndex - MatsubaraNumber1;
            long MatsubaraNumber3 = NupIndexM+FermionicIndexOffset[BosonicIndexV];
            Values[BosonicIndexV](NuIndexM,NupIndexM) =
                pSource->value(MatsubaraNumber1,MatsubaraNumber2,MatsubaraNumber3);
        }
    }
}

template<typename SourceObject> inline
ComplexType MatsubaraContainer4<SourceObject>::operator()(long MatsubaraNumber1, long MatsubaraNumber2, long MatsubaraNumber3) const
{
    long BosonicIndexV = MatsubaraNumber2 + MatsubaraNumber1 + 2*NumberOfMatsubaras;
    if(BosonicIndexV >=0 && BosonicIndexV <= 2*(2*NumberOfMatsubaras-1)){
        long NuIndexM = MatsubaraNumber1-FermionicIndexOffset[BosonicIndexV];
        long NupIndexM = MatsubaraNumber3-FermionicIndexOffset[BosonicIndexV];
        if(NuIndexM >= 0 && NuIndexM < Values[BosonicIndexV].rows() &&
           NupIndexM >= 0 && NupIndexM < Values[BosonicIndexV].cols())
            return Values[BosonicIndexV](NuIndexM,NupIndexM);
    }

    DEBUG("MatsubaraContainer4 at " << this << ": " <<
          "cache miss for n1 = " << MatsubaraNumber1 << ", " <<
          "n2 = " << MatsubaraNumber2 << ", " <<
          "n3 = " << MatsubaraNumber3 <<
          " (NumberOfMatsubaras = " << NumberOfMatsubaras <<
          "), fetching a raw value from " << pSource
    );

    return pSource->value(MatsubaraNumber1,MatsubaraNumber2,MatsubaraNumber3);
}

} // namespace Pomerol

#endif // #ifndef POMEROL_INCLUDE_POMEROL_MATSUBARACONTAINERS_H
<|endoftext|>


<commit_before>#include "util.h"
#include "asset_manager.h"

TC_NAMESPACE_BEGIN

AssetManager &AssetManager::get_instance() {
  static AssetManager manager;
  TC_P(&manager);
  return manager;
}

TC_NAMESPACE_END
<commit_msg>cleaned debug output<commit_after>#include "util.h"
#include "asset_manager.h"

TC_NAMESPACE_BEGIN

AssetManager &AssetManager::get_instance() {
  static AssetManager manager;
  return manager;
}

TC_NAMESPACE_END
<|endoftext|>


<commit_before>#ifndef ORG_EEROS_CORE_EXECUTORSERVICE_HPP_
#define ORG_EEROS_CORE_EXECUTORSERVICE_HPP_

#include <config.hpp>
#include <eeros/core/Executor.hpp>

#if defined(WINDOWS)
#include <windows.h>
#endif

#if defined(LINUX) || defined(PREEMPT_RT) || defined(FREEBSD)
#include <pthread.h>
#endif

#define RUNNING 1
#define MAX_NOF_THREADS 8

namespace eeros {

	class Executor;

	class ExecutorService {

	public:
		static int createNewThread(Executor* e);
		static void waitForSequenceEnd(Executor* waitExecutor);

	private:
		static int nofThreads;
	#if defined(WINDOWS)
		static HANDLE getHandle(int i);
		static DWORD WINAPI threadAction(LPVOID ptr);
		static DWORD dwThreads[];
		static HANDLE hThreads[];
	#endif
	#if defined(LINUX) || defined(PREEMPT_RT) || defined(FREEBSD)
		static void* threadAction(void*);
		static pthread_t threads[];
	#endif
	#if defined(XENOMAI)
		// TODO
	#endif

	#if defined(QNX)
		// TODO
	#endif
	};
};

#endif // ORG_EEROS_CORE_EXECUTORSERVICE_HPP_
<commit_msg>MAX_NOF_THREAD increased to 64<commit_after>#ifndef ORG_EEROS_CORE_EXECUTORSERVICE_HPP_
#define ORG_EEROS_CORE_EXECUTORSERVICE_HPP_

#include <config.hpp>
#include <eeros/core/Executor.hpp>

#if defined(WINDOWS)
#include <windows.h>
#endif

#if defined(LINUX) || defined(PREEMPT_RT) || defined(FREEBSD)
#include <pthread.h>
#endif

#define RUNNING 1
#define MAX_NOF_THREADS 64

namespace eeros {

	class Executor;

	class ExecutorService {

	public:
		static int createNewThread(Executor* e);
		static void waitForSequenceEnd(Executor* waitExecutor);

	private:
		static int nofThreads;
	#if defined(WINDOWS)
		static HANDLE getHandle(int i);
		static DWORD WINAPI threadAction(LPVOID ptr);
		static DWORD dwThreads[];
		static HANDLE hThreads[];
	#endif
	#if defined(LINUX) || defined(PREEMPT_RT) || defined(FREEBSD)
		static void* threadAction(void*);
		static pthread_t threads[];
	#endif
	#if defined(XENOMAI)
		// TODO
	#endif

	#if defined(QNX)
		// TODO
	#endif
	};
};

#endif // ORG_EEROS_CORE_EXECUTORSERVICE_HPP_
<|endoftext|>


<commit_before>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

 ======================================================================*/

/// @file
///     @brief Base class for all unit tests
///
///     @author Don Gagne <don@thegagnes.com>

#include "UnitTest.h"
#include "QGCApplication.h"

bool UnitTest::_messageBoxRespondedTo = false;
bool UnitTest::_badResponseButton = false;
QMessageBox::StandardButton UnitTest::_messageBoxResponseButton = QMessageBox::NoButton;
int UnitTest::_missedMessageBoxCount = 0;
UnitTest::UnitTestList_t UnitTest::_tests;

UnitTest::UnitTest(void) :
    _unitTestRun(false),
    _initTestCaseCalled(false),
    _cleanupTestCaseCalled(false),
    _initCalled(false),
    _cleanupCalled(false)
{

}

UnitTest::~UnitTest()
{
    if (_unitTestRun) {
        // Derived classes must call base class implementations
        Q_ASSERT(_initTestCaseCalled);
        Q_ASSERT(_cleanupTestCaseCalled);
        Q_ASSERT(_initCalled);
        Q_ASSERT(_cleanupCalled);
    }
}

void UnitTest::_addTest(QObject* test)
{
    Q_ASSERT(!_tests.contains(test));

    _tests.append(test);
}

void UnitTest::_unitTestCalled(void)
{
    _unitTestRun = true;
}

int UnitTest::run(int argc, char *argv[], QString& singleTest)
{
    int ret = 0;

    foreach (QObject* test, _tests) {
        if (singleTest.isEmpty() || singleTest == test->objectName()) {
            ret += QTest::qExec(test, argc, argv);
        }
    }

    return ret;
}

/// @brief Called at the initialization of the entire unit test.
///         Make sure to call first in your derived class
void UnitTest::initTestCase(void)
{
    _initTestCaseCalled = true;

    _activeUnitTest = this;
    _missedMessageBoxCount = 0;
    _badResponseButton = false;
}

/// @brief Called at the end of the entire unit test.
///         Make sure to call first in your derived class
void UnitTest::cleanupTestCase(void)
{
    _cleanupTestCaseCalled = true;

    Q_ASSERT(_activeUnitTest != NULL);
    _activeUnitTest = NULL;

    int missedMessageBoxCount = _missedMessageBoxCount;
    _missedMessageBoxCount = 0;

    // Make sure to reset any needed variables since this can fall and cause the rest of the method to be skipped
    QCOMPARE(missedMessageBoxCount, 0);
}

/// @brief Called before each test.
///         Make sure to call first in your derived class
void UnitTest::init(void)
{
    _initCalled = true;

    _messageBoxRespondedTo = false;
    _missedMessageBoxCount = 0;
    _badResponseButton = false;
    _messageBoxResponseButton = QMessageBox::NoButton;

    // Each test gets a clean global state
    qgcApp()->destroySingletonsForUnitTest();
    qgcApp()->createSingletonsForUnitTest();
}

/// @brief Called after each test.
///         Make sure to call first in your derived class
void UnitTest::cleanup(void)
{
    _cleanupCalled = true;

    int missedMessageBoxCount = _missedMessageBoxCount;
    _missedMessageBoxCount = 0;

    // Make sure to reset any needed variables since this can fall and cause the rest of the method to be skipped
    QCOMPARE(missedMessageBoxCount, 0);
}

void UnitTest::setExpectedMessageBox(QMessageBox::StandardButton response)
{
    Q_ASSERT(!_messageBoxRespondedTo);

    // We use an obsolete StandardButton value to signal that response button has not been set. So you can't use this.
    Q_ASSERT(response != QMessageBox::NoButton);
    Q_ASSERT(_messageBoxResponseButton == QMessageBox::NoButton);

    int missedMessageBoxCount = _missedMessageBoxCount;
    _missedMessageBoxCount = 0;

    QCOMPARE(missedMessageBoxCount, 0);

    _messageBoxResponseButton = response;
}

void UnitTest::checkExpectedMessageBox(int expectFailFlags)
{
    // Previous call to setExpectedMessageBox should have already checked this
    Q_ASSERT(_missedMessageBoxCount == 0);

    // Check for a valid response

    if (expectFailFlags & expectFailBadResponseButton) {
        QEXPECT_FAIL("", "Expecting failure due to bad button response", Continue);
    }
    QCOMPARE(_badResponseButton, false);

    if (expectFailFlags & expectFailNoMessageBox) {
        QEXPECT_FAIL("", "Expecting failure due to no message box", Continue);
    }
    QCOMPARE(_messageBoxRespondedTo, true);
}

QMessageBox::StandardButton UnitTest::_messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
{
    QMessageBox::StandardButton retButton;

    Q_UNUSED(icon);
    Q_UNUSED(title);
    Q_UNUSED(text);

    if (_messageBoxResponseButton == QMessageBox::NoButton) {
        // If no response button is set it means we were not expecting this message box. Response with default
        _missedMessageBoxCount++;
        retButton = defaultButton;
    } else {
        if (_messageBoxResponseButton & buttons) {
            // Everything is correct, use the specified response
            retButton = _messageBoxResponseButton;
        } else {
            // Trying to respond with a button not in the dialog. This is an error. Respond with default
            _badResponseButton = true;
            retButton = defaultButton;
        }
        _messageBoxRespondedTo = true;
    }

    // Clear response for next message box
    _messageBoxResponseButton = QMessageBox::NoButton;

    return retButton;
}
<commit_msg>Remove unused variable<commit_after>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

 ======================================================================*/

/// @file
///     @brief Base class for all unit tests
///
///     @author Don Gagne <don@thegagnes.com>

#include "UnitTest.h"
#include "QGCApplication.h"

bool UnitTest::_messageBoxRespondedTo = false;
bool UnitTest::_badResponseButton = false;
QMessageBox::StandardButton UnitTest::_messageBoxResponseButton = QMessageBox::NoButton;
int UnitTest::_missedMessageBoxCount = 0;
UnitTest::UnitTestList_t UnitTest::_tests;

UnitTest::UnitTest(void) :
    _unitTestRun(false),
    _initTestCaseCalled(false),
    _cleanupTestCaseCalled(false),
    _initCalled(false),
    _cleanupCalled(false)
{

}

UnitTest::~UnitTest()
{
    if (_unitTestRun) {
        // Derived classes must call base class implementations
        Q_ASSERT(_initTestCaseCalled);
        Q_ASSERT(_cleanupTestCaseCalled);
        Q_ASSERT(_initCalled);
        Q_ASSERT(_cleanupCalled);
    }
}

void UnitTest::_addTest(QObject* test)
{
    Q_ASSERT(!_tests.contains(test));

    _tests.append(test);
}

void UnitTest::_unitTestCalled(void)
{
    _unitTestRun = true;
}

int UnitTest::run(int argc, char *argv[], QString& singleTest)
{
    int ret = 0;

    foreach (QObject* test, _tests) {
        if (singleTest.isEmpty() || singleTest == test->objectName()) {
            ret += QTest::qExec(test, argc, argv);
        }
    }

    return ret;
}

/// @brief Called at the initialization of the entire unit test.
///         Make sure to call first in your derived class
void UnitTest::initTestCase(void)
{
    _initTestCaseCalled = true;

    _missedMessageBoxCount = 0;
    _badResponseButton = false;
}

/// @brief Called at the end of the entire unit test.
///         Make sure to call first in your derived class
void UnitTest::cleanupTestCase(void)
{
    _cleanupTestCaseCalled = true;

    int missedMessageBoxCount = _missedMessageBoxCount;
    _missedMessageBoxCount = 0;

    // Make sure to reset any needed variables since this can fall and cause the rest of the method to be skipped
    QCOMPARE(missedMessageBoxCount, 0);
}

/// @brief Called before each test.
///         Make sure to call first in your derived class
void UnitTest::init(void)
{
    _initCalled = true;

    _messageBoxRespondedTo = false;
    _missedMessageBoxCount = 0;
    _badResponseButton = false;
    _messageBoxResponseButton = QMessageBox::NoButton;

    // Each test gets a clean global state
    qgcApp()->destroySingletonsForUnitTest();
    qgcApp()->createSingletonsForUnitTest();
}

/// @brief Called after each test.
///         Make sure to call first in your derived class
void UnitTest::cleanup(void)
{
    _cleanupCalled = true;

    int missedMessageBoxCount = _missedMessageBoxCount;
    _missedMessageBoxCount = 0;

    // Make sure to reset any needed variables since this can fall and cause the rest of the method to be skipped
    QCOMPARE(missedMessageBoxCount, 0);
}

void UnitTest::setExpectedMessageBox(QMessageBox::StandardButton response)
{
    Q_ASSERT(!_messageBoxRespondedTo);

    // We use an obsolete StandardButton value to signal that response button has not been set. So you can't use this.
    Q_ASSERT(response != QMessageBox::NoButton);
    Q_ASSERT(_messageBoxResponseButton == QMessageBox::NoButton);

    int missedMessageBoxCount = _missedMessageBoxCount;
    _missedMessageBoxCount = 0;

    QCOMPARE(missedMessageBoxCount, 0);

    _messageBoxResponseButton = response;
}

void UnitTest::checkExpectedMessageBox(int expectFailFlags)
{
    // Previous call to setExpectedMessageBox should have already checked this
    Q_ASSERT(_missedMessageBoxCount == 0);

    // Check for a valid response

    if (expectFailFlags & expectFailBadResponseButton) {
        QEXPECT_FAIL("", "Expecting failure due to bad button response", Continue);
    }
    QCOMPARE(_badResponseButton, false);

    if (expectFailFlags & expectFailNoMessageBox) {
        QEXPECT_FAIL("", "Expecting failure due to no message box", Continue);
    }
    QCOMPARE(_messageBoxRespondedTo, true);
}

QMessageBox::StandardButton UnitTest::_messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
{
    QMessageBox::StandardButton retButton;

    Q_UNUSED(icon);
    Q_UNUSED(title);
    Q_UNUSED(text);

    if (_messageBoxResponseButton == QMessageBox::NoButton) {
        // If no response button is set it means we were not expecting this message box. Response with default
        _missedMessageBoxCount++;
        retButton = defaultButton;
    } else {
        if (_messageBoxResponseButton & buttons) {
            // Everything is correct, use the specified response
            retButton = _messageBoxResponseButton;
        } else {
            // Trying to respond with a button not in the dialog. This is an error. Respond with default
            _badResponseButton = true;
            retButton = defaultButton;
        }
        _messageBoxRespondedTo = true;
    }

    // Clear response for next message box
    _messageBoxResponseButton = QMessageBox::NoButton;

    return retButton;
}
<|endoftext|>