<commit_before>//The MIT License (MIT)
//
//Copyright (c) 2015 Relja Ljubobratovic, ljubobratovic.relja@gmail.com
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
//
// Description:
// Testing program for libcv. Contains assertion checks for various algorithms, but also
// performs print-outs in which used can recognize if printed result is correct.
// Also shows images if libcv is compiled with gui support.
//
// Author:
// Relja Ljubobratovic, ljubobratovic.relja@gmail.com

#include <iostream>
#include <algorithm>

#include "../include/vector.hpp"
#include "../include/matrix.hpp"
#include "../include/image.hpp"
#include "../include/io.hpp"
#include "../include/improc.hpp"
#include "../include/gui.hpp"
#include "../include/kdtree.hpp"
#include "../include/draw.hpp"

/*
	data type test check module
*/

void cv_vector_test() {
	cv::vector<float> vec;
	ASSERT(vec.empty());

	unsigned vec_size = 6;

	vec.create(vec_size);
	ASSERT(vec.length() == vec_size);
	ASSERT(vec);

	vec[0] = 1;
	vec[1] = 3;
	vec[2] = 5;
	vec[3] = 7;
	vec[4] = 9;
	vec[5] = 11;

	auto m = vec.min();
	ASSERT(*m == 1);

	m = vec.max();
	ASSERT(*m == vec[vec_size - 1]);

	auto st_vec = vec(0, vec_size - 1, 2);
	ASSERT(st_vec[0] == vec[0] && st_vec[1] == vec[2] && st_vec[2] == vec[4]);
	ASSERT(&st_vec[0] == &vec[0] && &st_vec[1] == &vec[2] && &st_vec[2] == &vec[4]);

	const cv::vector<float> const_st_vec = vec(0, vec_size - 1, 2);
	ASSERT(const_st_vec[0] == vec[0] && const_st_vec[1] == vec[2] && const_st_vec[2] == vec[4]);

	cv::vector<int> init_vec = {1, 3, 4};
	ASSERT(init_vec.length() == 3 && init_vec[0] == 1 && init_vec[1] == 3 && init_vec[2] == 4);

	auto vec_cpy = st_vec.clone();
	ASSERT(std::equal(vec_cpy.begin(), vec_cpy.end(), st_vec.begin()));
	ASSERT(&vec_cpy[0] != &st_vec[0]);

	// distance ------------------------------

	cv::vector<int> a = {1, 2};
	cv::vector<int> b = {1, 3};

	ASSERT(a.distance(b) == 1.);

	cv::vector<float> a_f = a; // conversion to float.
	a_f.normalize();

	auto a_norm = a.norm(); // L2 by default

	for (unsigned i = 0; i < a.length(); ++i) {
		ASSERT(a_f[i] == static_cast<float>((a[i]) / a_norm));
	}
}

void cv_matrix_test() {

	cv::matrix<double> mat(3, 3);
	std::cout << "3x3 matrix:\n" << mat << std::endl;

	mat.fill(3);

	std::cout << "3x3 matrix filled with 3:\n" << mat << std::endl;

	mat.reshape(1, 9);

	std::cout << "1x9 reshaped matrix:\n" << mat << std::endl;

	mat.reshape(3, 3);

	std::cout << "3x3 reshaped to original:\n" << mat << std::endl;

	auto r = mat.row(1);
	r.fill(0);
	ASSERT(mat(1, 0) == 0 && mat(1, 1) == 0 && mat(1, 2) == 0);

	auto c = mat.col(1);
	c.fill(1);
	ASSERT(mat(0, 1) == 1 && mat(1, 1) == 1 && mat(2, 1) == 1);

	cv::matrix3f mat_3f(3, 3);
	mat_3f.fill({255, 15, 354});
	std::cout << mat_3f << std::endl;
}

void cv_image_array_test() {

	cv::image_array im = cv::imread("/home/relja/Lenna.png", cv::UINT8, 1);
	im.convert_to(cv::REAL);

	cv::matrixr im_r, f_x, f_y, blur, f_grad;

	im_r = im;

	cv::calc_derivatives(im_r, f_x, f_y);

	f_grad = cv::normalize(f_x + f_y);

	cv::imshow("im", im);
	cv::imshow("gradients", f_grad);

	cv::wait_key();

	return;
}

void cv_gradient_test() {

	cv::image_array im = cv::imread("/home/relja/Lenna.png", cv::UINT8, 1);
	im.convert_to(cv::REAL);

	cv::matrixr im_r, f_x, f_y, blur, f_grad, h, s, non_max;

	im_r = im;

	cv::calc_derivatives(im_r, f_x, f_y);

	f_grad = cv::normalize(f_x + f_y);

	h = cv::normalize(cv::harris(im_r, 3, 0.8, 1));
	s = cv::normalize(cv::good_features(im_r, 3, 1));

	non_max = s.clone();
	cv::filter_non_maximum(non_max, 5);

	cv::imshow("im", im);
	cv::imshow("gradients", f_grad);
	cv::imshow("harris corners", h);
	cv::imshow("shi-tomasi corners", s);
	cv::imshow("shi-tomasi corners non-max", non_max);

	cv::wait_key();

	return;
}

void cv_kd_tree_test() {

	srand(time(NULL));

	std::vector<cv::vec2i> result;

	std::vector<cv::vec2i> source, results;
	std::vector<unsigned> idResults;

	for (unsigned i = 0; i < 1000; i++) {
		cv::vec2i ptr = { rand() % 599, rand() % 599 };
		source.push_back(ptr);
	}

	double radius = 250.0;
	int nnCount = 6;

	cv::vec2i ptr_search = { rand() % 600, rand() % 600 };

	cv::kd_tree2i kd(source);

	while (true) {

		if (nnCount < 3) {
			nnCount = 3;
		}

		cv::matrix3b img = cv::matrix3b::zeros(600,600);

		for (unsigned i = 0; i < source.size(); i++) {
			cv::draw_circle(img, source[i], 5, cv::vec3b{0, 0, 255});
		}

		kd.knn_index(ptr_search, nnCount, idResults, radius);

		cv::draw_circle(img, ptr_search, 5, {255, 0, 0});
		cv::draw_circle(img, ptr_search, radius, {255, 255, 0});

		for (auto id : idResults) {
				cv::draw_circle(img, source[id], 5, {0, 255, 0});
		}

		cv::imshow("KD", img);
		char key = cv::wait_key();

		switch (key) {
		case 'q':
			return;
		case 'o':
			radius += 10.0;
			break;

		case 'p':
			radius -= 10.0;
			break;
		case 'k':
			nnCount += 1;
			break;
		case 'l':
			nnCount -= 1;
			break;
		default:
			ptr_search = { rand() % 600, rand() % 600 };
			break;
		}
	}
}

void cv_draw_test() {

	cv::matrix3b img = cv::matrix3b::zeros(512, 512);

	cv::polygoni poly;
	poly << cv::vec2i{100, 300} << cv::vec2i{150, 200} << cv::vec2i{200, 300};

	cv::draw_polygon(img, poly, {255, 0, 0}, 1, true);

	//cv::draw_point(img, {256, 256}, {255, 0, 0}, 1);
	//cv::draw_line(img, {200, 200}, {300, 250}, {0, 255, 0});
	//cv::draw_circle(img, {256, 256}, 15, {0, 0, 255});

	cv::imshow("draw image", img);
	cv::wait_key();

}

int main() {

	//cv_vector_test();
	//cv_matrix_test();
	//cv_image_array_test();
	//cv_gradient_test();
	//cv_draw_test();
	cv_kd_tree_test();

	std::cout << "libcv test passed!" << std::endl;

	return EXIT_SUCCESS;
}
<commit_msg>added linear algebra testing<commit_after>//The MIT License (MIT)
//
//Copyright (c) 2015 Relja Ljubobratovic, ljubobratovic.relja@gmail.com
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
//
// Description:
// Testing program for libcv. Contains assertion checks for various algorithms, but also
// performs print-outs in which used can recognize if printed result is correct.
// Also shows images if libcv is compiled with gui support.
//
// Author:
// Relja Ljubobratovic, ljubobratovic.relja@gmail.com

#include <iostream>
#include <algorithm>

#include "../include/vector.hpp"
#include "../include/matrix.hpp"
#include "../include/image.hpp"
#include "../include/io.hpp"
#include "../include/improc.hpp"
#include "../include/gui.hpp"
#include "../include/kdtree.hpp"
#include "../include/draw.hpp"
#include "../include/linalg.hpp"
#include "../include/math.hpp"

/*
	data type test check module
*/

void cv_vector_test() {
	cv::vector<float> vec;
	ASSERT(vec.empty());

	unsigned vec_size = 6;

	vec.create(vec_size);
	ASSERT(vec.length() == vec_size);
	ASSERT(vec);

	vec[0] = 1;
	vec[1] = 3;
	vec[2] = 5;
	vec[3] = 7;
	vec[4] = 9;
	vec[5] = 11;

	auto m = vec.min();
	ASSERT(*m == 1);

	m = vec.max();
	ASSERT(*m == vec[vec_size - 1]);

	auto st_vec = vec(0, vec_size - 1, 2);
	ASSERT(st_vec[0] == vec[0] && st_vec[1] == vec[2] && st_vec[2] == vec[4]);
	ASSERT(&st_vec[0] == &vec[0] && &st_vec[1] == &vec[2] && &st_vec[2] == &vec[4]);

	const cv::vector<float> const_st_vec = vec(0, vec_size - 1, 2);
	ASSERT(const_st_vec[0] == vec[0] && const_st_vec[1] == vec[2] && const_st_vec[2] == vec[4]);

	cv::vector<int> init_vec = {1, 3, 4};
	ASSERT(init_vec.length() == 3 && init_vec[0] == 1 && init_vec[1] == 3 && init_vec[2] == 4);

	auto vec_cpy = st_vec.clone();
	ASSERT(std::equal(vec_cpy.begin(), vec_cpy.end(), st_vec.begin()));
	ASSERT(&vec_cpy[0] != &st_vec[0]);

	// distance ------------------------------

	cv::vector<int> a = {1, 2};
	cv::vector<int> b = {1, 3};

	ASSERT(a.distance(b) == 1.);

	cv::vector<float> a_f = a; // conversion to float.
	a_f.normalize();

	auto a_norm = a.norm(); // L2 by default

	for (unsigned i = 0; i < a.length(); ++i) {
		ASSERT(a_f[i] == static_cast<float>((a[i]) / a_norm));
	}
}

void cv_matrix_test() {

	cv::matrix<double> mat(3, 3);
	std::cout << "3x3 matrix:\n" << mat << std::endl;

	mat.fill(3);

	std::cout << "3x3 matrix filled with 3:\n" << mat << std::endl;

	mat.reshape(1, 9);

	std::cout << "1x9 reshaped matrix:\n" << mat << std::endl;

	mat.reshape(3, 3);

	std::cout << "3x3 reshaped to original:\n" << mat << std::endl;

	auto r = mat.row(1);
	r.fill(0);
	ASSERT(mat(1, 0) == 0 && mat(1, 1) == 0 && mat(1, 2) == 0);

	auto c = mat.col(1);
	c.fill(1);
	ASSERT(mat(0, 1) == 1 && mat(1, 1) == 1 && mat(2, 1) == 1);

	cv::matrix3f mat_3f(3, 3);
	mat_3f.fill({255, 15, 354});
	std::cout << mat_3f << std::endl;
}

void cv_image_array_test() {

	cv::image_array im = cv::imread("/home/relja/Lenna.png", cv::UINT8, 1);
	im.convert_to(cv::REAL);

	cv::matrixr im_r, f_x, f_y, blur, f_grad;

	im_r = im;

	cv::calc_derivatives(im_r, f_x, f_y);

	f_grad = cv::normalize(f_x + f_y);

	cv::imshow("im", im);
	cv::imshow("gradients", f_grad);

	cv::wait_key();

	return;
}

void cv_gradient_test() {

	cv::image_array im = cv::imread("/home/relja/Lenna.png", cv::UINT8, 1);
	im.convert_to(cv::REAL);

	cv::matrixr im_r, f_x, f_y, blur, f_grad, h, s, non_max;

	im_r = im;

	cv::calc_derivatives(im_r, f_x, f_y);

	f_grad = cv::normalize(f_x + f_y);

	h = cv::normalize(cv::harris(im_r, 3, 0.8, 1));
	s = cv::normalize(cv::good_features(im_r, 3, 1));

	non_max = s.clone();
	cv::filter_non_maximum(non_max, 5);

	cv::imshow("im", im);
	cv::imshow("gradients", f_grad);
	cv::imshow("harris corners", h);
	cv::imshow("shi-tomasi corners", s);
	cv::imshow("shi-tomasi corners non-max", non_max);

	cv::wait_key();

	return;
}

void cv_kd_tree_test() {

	srand(time(NULL));

	std::vector<cv::vec2i> result;

	std::vector<cv::vec2i> source, results;
	std::vector<unsigned> idResults;

	for (unsigned i = 0; i < 1000; i++) {
		cv::vec2i ptr = { rand() % 599, rand() % 599 };
		source.push_back(ptr);
	}

	double radius = 250.0;
	int nnCount = 6;

	cv::vec2i ptr_search = { rand() % 600, rand() % 600 };

	cv::kd_tree2i kd(source);

	while (true) {

		if (nnCount < 3) {
			nnCount = 3;
		}

		cv::matrix3b img = cv::matrix3b::zeros(600,600);

		for (unsigned i = 0; i < source.size(); i++) {
			cv::draw_circle(img, source[i], 5, cv::vec3b {0, 0, 255});
		}

		kd.knn_index(ptr_search, nnCount, idResults, radius);

		cv::draw_circle(img, ptr_search, 5, {255, 0, 0});
		cv::draw_circle(img, ptr_search, radius, {255, 255, 0});

		for (auto id : idResults) {
			cv::draw_circle(img, source[id], 5, {0, 255, 0});
		}

		cv::imshow("KD", img);
		char key = cv::wait_key();

		switch (key) {
		case 'q':
			return;
		case 'o':
			radius += 10.0;
			break;

		case 'p':
			radius -= 10.0;
			break;
		case 'k':
			nnCount += 1;
			break;
		case 'l':
			nnCount -= 1;
			break;
		default:
			ptr_search = { rand() % 600, rand() % 600 };
			break;
		}
	}
}

void cv_draw_test() {

	cv::matrix3b img = cv::matrix3b::zeros(512, 512);

	cv::polygoni poly;
	poly << cv::vec2i {100, 300} << cv::vec2i {150, 200} << cv::vec2i {200, 300};

	cv::draw_polygon(img, poly, {255, 0, 0}, 1, true);
	cv::draw_point(img, {256, 256}, {255, 0, 0}, 1);
	cv::draw_line(img, {200, 200}, {300, 250}, {0, 255, 0});
	cv::draw_circle(img, {256, 256}, 15, {0, 0, 255});

	cv::imshow("draw image", img);
	cv::wait_key();

}

void cv_linalg_test() {

	// inverse test /////////////////////////////////////////////////////////////////////////////////
	cv::matrixr mat = {{32, 4, 5}, {1, 32, 4}, {31, 54, 54}};

	auto inv = mat.clone();

	cv::invert(inv);

	auto one_mat = mat * inv;

	// is identity ?
	ASSERT(cv::is_aproximation(one_mat(0, 0), static_cast<real_t>(1.0), static_cast<real_t>(10e-6)));
	ASSERT(cv::is_aproximation(one_mat(1, 1), static_cast<real_t>(1.0), static_cast<real_t>(10e-6)));
	ASSERT(cv::is_aproximation(one_mat(2, 2), static_cast<real_t>(1.0), static_cast<real_t>(10e-6)));

	ASSERT(cv::is_aproximation(one_mat(0, 1), static_cast<real_t>(.0), static_cast<real_t>(10e-6)));
	ASSERT(cv::is_aproximation(one_mat(0, 2), static_cast<real_t>(.0), static_cast<real_t>(10e-6)));
	ASSERT(cv::is_aproximation(one_mat(1, 0), static_cast<real_t>(.0), static_cast<real_t>(10e-6)));

	ASSERT(cv::is_aproximation(one_mat(1, 2), static_cast<real_t>(.0), static_cast<real_t>(10e-6)));
	ASSERT(cv::is_aproximation(one_mat(2, 0), static_cast<real_t>(.0), static_cast<real_t>(10e-6)));
	ASSERT(cv::is_aproximation(one_mat(2, 1), static_cast<real_t>(.0), static_cast<real_t>(10e-6)));

	// inverse test end /////////////////////////////////////////////////////////////////////////////

	// lu decomposition test ////////////////////////////////////////////////////////////////////////
	cv::matrixr L, U, P;

	mat = {{7, 3, -11}, {-6, 7, 10}, {-11, 2, -2}};

	cv::lu_decomp(mat, L, U, P);

	auto comp_res = (P*L*U);

	ASSERT(std::memcmp((void*)mat.data(), (void*)comp_res.data(), 9*sizeof(real_t)));

	// lu decomposition test end ////////////////////////////////////////////////////////////////////

	// svd decomposition test ///////////////////////////////////////////////////////////////////////

	cv::matrixr S, Vt;

	cv::svd_decomp(mat, U, S, Vt);

	comp_res = (U*S*Vt);
	ASSERT(std::memcmp((void*)mat.data(), (void*)comp_res.data(), 9*sizeof(real_t)));

	// svd decomposition test end ///////////////////////////////////////////////////////////////////

	// system solving : LU

	cv::matrixr a = {
		{6.80 , -6.05 , -0.45 ,  8.32 , -9.67},
		{-2.11,  -3.30,   2.58,   2.71,  -5.14},
		{5.66 ,  5.36 , -2.70 ,  4.35 , -7.26},
		{5.97 , -4.44 ,  0.27 , -7.17 ,  6.08},
		{8.23 ,  1.08 ,  9.04 ,  2.14 , -6.87}
	};

	cv::matrixr b = {
		{4.02 , -1.56 ,  9.81},
		{6.19 ,  4.00 , -4.09},
		{-8.22,  -8.67,  -4.57},
		{-7.57,   1.75,  -8.61},
		{-3.03,   2.86,   8.99}
	};

	cv::matrixr correct_solution = {
		{-0.800714, -0.389621, 0.955465 },
		{-0.695243, -0.554427, 0.22066 },
		{0.593915 ,0.842227, 1.90064 },
		{1.32173 ,-0.103802 ,5.35766 },
		{0.565756 ,0.105711 ,4.0406 }
	};

	cv::matrixr x;

	cv::lu_solve(a, b, x);

	std::cout << correct_solution << std::endl;
	std::cout << x << std::endl;

	for(unsigned i = 0; i < correct_solution.rows(); ++i) {
		for(unsigned j = 0; j < correct_solution.cols(); ++j) {
			ASSERT(cv::cmp_real(correct_solution(i, j), x(i, j)));
		}
	}
}

int main() {

	//cv_vector_test();
	//cv_matrix_test();
	//cv_image_array_test();
	//cv_gradient_test();
	//cv_draw_test();
	//cv_kd_tree_test();
	cv_linalg_test();

	std::cout << "libcv test passed!" << std::endl;

	return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#define CATCH_CONFIG_RUNNER
#include "catch.hpp"

#include <logger.h>

int main(int argc, char *argv[])
{
	setlocale(LC_CTYPE, "");
	newsbeuter::logger::getInstance().set_logfile("testlog.txt");
	newsbeuter::logger::getInstance().set_loglevel(newsbeuter::level::DEBUG);

	return Catch::Session().run(argc, argv);
}

<commit_msg>Disable logging in tests<commit_after>#define CATCH_CONFIG_RUNNER
#include "catch.hpp"

#include <logger.h>

int main(int argc, char *argv[])
{
	setlocale(LC_CTYPE, "");

	return Catch::Session().run(argc, argv);
}

<|endoftext|>


<commit_before>#include "cpx/PluginFactory.hpp"

#include "TestPluginInterface.hpp"

#include "minitest.h"

#include <iostream>
#include <string>

/*
If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname.
Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for further details)
*/

void test_loading_default()
{
    cpx::PluginFactory pluginFactory;
    pluginFactory.loadLibrary("./test-plugin.cpx");
    ASSERT_EQ(pluginFactory.getRegisteredPluginNames().size(),1);
    pluginFactory.loadLibrary("./test-plugin-other.cpx");
    ASSERT_EQ(pluginFactory.getRegisteredPluginNames().size(),2);
}

void test_loading_nosingleton()
{
    cpx::PluginFactory pluginFactory;
    cpx::PluginFactory pluginFactory2;
    pluginFactory.loadLibrary("./test-plugin.cpx");
    ASSERT_EQ(pluginFactory.getRegisteredPluginNames().size(),1);
    ASSERT_EQ(pluginFactory2.getRegisteredPluginNames().size(),0);
    pluginFactory2.loadLibrary("./test-plugin-copy.cpx");
    pluginFactory2.loadLibrary("./test-plugin-other.cpx");
    ASSERT_EQ(pluginFactory.getRegisteredPluginNames().size(),1);
    ASSERT_EQ(pluginFactory2.getRegisteredPluginNames().size(),2);
}

void test_loading_error()
{
    cpx::PluginFactory pluginFactory;
    ASSERT_RAISE(pluginFactory.loadLibrary("./test-plugin.cp"));
}

void test_loading_twice()
{
    cpx::PluginFactory pluginFactory;
    pluginFactory.loadLibrary("./test-plugin.cpx");
    ASSERT_RAISE(pluginFactory.loadLibrary("./test-plugin.cpx"));
}

void test_loading_copy()
{
    cpx::PluginFactory pluginFactory;
    pluginFactory.loadLibrary("./test-plugin.cpx");
    ASSERT_RAISE(pluginFactory.loadLibrary("./test/test-plugin-copy.cpx"));
}

int main()
{

    RUN_TEST(test_loading_default);
    RUN_TEST(test_loading_nosingleton);
    RUN_TEST(test_loading_error);
    RUN_TEST(test_loading_twice);
    RUN_TEST(test_loading_copy);

    /*
    catch (const std::runtime_error& e)
    {
        std::cerr << e.what() <<std::endl;
        return 1;
    }

    if (pluginFactory.getRegisteredPluginNames().size()!=1)
    {
        std::cerr << "Error: plugin not registered" <<std::endl;
        return 1;
    }

    std::cout << pluginFactory.toString();

    TestPluginProducer* pluginProducer = pluginFactory.getProducer<TestPluginProducer>("TestPlugin");

    //std::cout<<pluginProducer->toString()<<std::endl;
    std::string s("Test Plugin Argument");
    TestPluginInterface* t = pluginProducer->create(s);
    (void)t;
    */
    return 0;
}

<commit_msg>add dlopen help in test<commit_after>#include "cpx/PluginFactory.hpp"

#include "TestPluginInterface.hpp"

#include "minitest.h"

#include <iostream>
#include <string>

/*
dlopen:
If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname.
Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for further details)
  o   (ELF only) If the executable file for the calling program
       contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag,
       then the directories listed in the DT_RPATH tag are searched.

   o   If, at the time that the program was started, the environment
       variable LD_LIBRARY_PATH was defined to contain a colon-separated
       list of directories, then these are searched.  (As a security
       measure this variable is ignored for set-user-ID and set-group-ID
       programs.)

   o   (ELF only) If the executable file for the calling program
       contains a DT_RUNPATH tag, then the directories listed in that
       tag are searched.

   o   The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is
       checked to see whether it contains an entry for filename.

   o   The directories /lib and /usr/lib are searched (in that order).
*/

void test_loading_default()
{
    cpx::PluginFactory pluginFactory;
    pluginFactory.loadLibrary("./test-plugin.cpx");
    ASSERT_EQ(pluginFactory.getRegisteredPluginNames().size(),1);
    pluginFactory.loadLibrary("./test-plugin-other.cpx");
    ASSERT_EQ(pluginFactory.getRegisteredPluginNames().size(),2);
}

void test_loading_nosingleton()
{
    cpx::PluginFactory pluginFactory;
    cpx::PluginFactory pluginFactory2;
    pluginFactory.loadLibrary("./test-plugin.cpx");
    ASSERT_EQ(pluginFactory.getRegisteredPluginNames().size(),1);
    ASSERT_EQ(pluginFactory2.getRegisteredPluginNames().size(),0);
    pluginFactory2.loadLibrary("./test-plugin-copy.cpx");
    pluginFactory2.loadLibrary("./test-plugin-other.cpx");
    ASSERT_EQ(pluginFactory.getRegisteredPluginNames().size(),1);
    ASSERT_EQ(pluginFactory2.getRegisteredPluginNames().size(),2);
}

void test_loading_error()
{
    cpx::PluginFactory pluginFactory;
    ASSERT_RAISE(pluginFactory.loadLibrary("./test-plugin.cp"));
}

void test_loading_twice()
{
    cpx::PluginFactory pluginFactory;
    pluginFactory.loadLibrary("./test-plugin.cpx");
    ASSERT_RAISE(pluginFactory.loadLibrary("./test-plugin.cpx"));
}

void test_loading_copy()
{
    cpx::PluginFactory pluginFactory;
    pluginFactory.loadLibrary("./test-plugin.cpx");
    ASSERT_RAISE(pluginFactory.loadLibrary("./test/test-plugin-copy.cpx"));
}

int main()
{

    RUN_TEST(test_loading_default);
    RUN_TEST(test_loading_nosingleton);
    RUN_TEST(test_loading_error);
    RUN_TEST(test_loading_twice);
    RUN_TEST(test_loading_copy);

    /*
    catch (const std::runtime_error& e)
    {
        std::cerr << e.what() <<std::endl;
        return 1;
    }

    if (pluginFactory.getRegisteredPluginNames().size()!=1)
    {
        std::cerr << "Error: plugin not registered" <<std::endl;
        return 1;
    }

    std::cout << pluginFactory.toString();

    TestPluginProducer* pluginProducer = pluginFactory.getProducer<TestPluginProducer>("TestPlugin");

    //std::cout<<pluginProducer->toString()<<std::endl;
    std::string s("Test Plugin Argument");
    TestPluginInterface* t = pluginProducer->create(s);
    (void)t;
    */
    return 0;
}

<|endoftext|>


<commit_before>
#include "catch.hpp"

#include <raspberry/raspberry.hpp>

#include <string>

RASPBERRY_DECL_METHOD(FuncConcept, func);
RASPBERRY_DECL_METHOD(SquareConcept, square);

using AnyFunc = raspberry::Any<FuncConcept<int()const>,SquareConcept<float(float)>>;

struct SomeFunc {
    int func() const {
        return 42;
    }

    float square(float x) {
        return x*x;
    }
};

TEST_CASE("Objects can be stored in Any", "[raspberry]") {
    AnyFunc f = SomeFunc{};

    REQUIRE(f.func() == 42);
    REQUIRE(f.square(12) == 144);
}

struct negative_test_assign {
    template <typename AF>
    static decltype( AF(std::declval<const AF&>()), bool{} ) test(int) { return false; }

    template <typename AF>
    static bool test(long) { return true; }
};

TEST_CASE("Any cannot be stored in Any or copied", "[raspberry]") {
    REQUIRE(negative_test_assign::test<AnyFunc>(int{}));
}

RASPBERRY_DECL_METHOD(RefDetectConcept, ref_detect);

using AnyRefDetector = raspberry::Any<RefDetectConcept<void(int)>>;

struct RefDetector {
    int value = 0;

    void ref_detect(int x) {
        value = x;
    }
};

TEST_CASE("Objects are copied by default", "[raspberry]") {
    RefDetector rd;
    REQUIRE(rd.value == 0);

    AnyRefDetector ard = rd;
    REQUIRE(rd.value == 0);

    ard.ref_detect(42);
    REQUIRE(rd.value == 0);
}

TEST_CASE("std::reference_wrapper is used to capture by reference", "[raspberry]") {
    RefDetector rd;
    REQUIRE(rd.value == 0);

    AnyRefDetector ard = std::ref(rd);
    REQUIRE(rd.value == 0);

    ard.ref_detect(42);
    REQUIRE(rd.value == 42);
}

RASPBERRY_DECL_METHOD(SetStringConcept, set_string);

using AnySetString = raspberry::Any<
        SetStringConcept< void(const std::string&) >,
        SetStringConcept< void(const char*) >
>;

struct StringSetter {
    std::string value;

    void set_string(const std::string& s) {
        value = s;
    }

    void set_string(const char* s) {
        value = s;
    }
};

TEST_CASE("Methods can be overloaded", "[raspberry]") {
    StringSetter s;
    AnySetString a = std::ref(s);

    a.set_string("char[]");
    REQUIRE(s.value == "char[]");

    a.set_string(std::string("std::string"));
    REQUIRE(s.value == "std::string");

}

RASPBERRY_DECL_METHOD(MaybeConstGetter, get);

using AnyMaybeConstGetter = raspberry::Any<
        MaybeConstGetter< int&() >,
        MaybeConstGetter< const int&() const >
>;

struct SomeMaybeConstGetter {
    int value;
    int& get() { return value; }
    const int& get() const { return value; }
};

TEST_CASE("Const and non-const overloads can coexist", "[raspberry]") {
    SomeMaybeConstGetter s;
    AnyMaybeConstGetter a = std::ref(s);

    s.value = 7;
    REQUIRE(s.value == 7);

    a.get() = 42;
    REQUIRE(s.value == 42);

    const auto& ac = a;
    REQUIRE(ac.get() == 42);
    REQUIRE(std::is_const<std::remove_reference_t<decltype(ac.get())>>::value);
}

using AnyMaybeConstGetterReversed = raspberry::Any<
        MaybeConstGetter< const int&() const >,
        MaybeConstGetter< int&() >
>;

TEST_CASE("Const and non-const overloads can come in any order", "[raspberry]") {
    SomeMaybeConstGetter s;
    AnyMaybeConstGetterReversed a = std::ref(s);

    s.value = 7;
    REQUIRE(s.value == 7);

    a.get() = 42;
    REQUIRE(s.value == 42);

    const auto& ac = a;
    REQUIRE(ac.get() == 42);
    REQUIRE(std::is_const<std::remove_reference_t<decltype(ac.get())>>::value);
}

RASPBERRY_DECL_METHOD(ConstTester, c_func);

using AnyConstTester = raspberry::Any< ConstTester< void() > >;

struct SomeConstTester {
    void c_func() const {}
};

TEST_CASE("Const methods can be called from non-const concepts", "[raspberry]") {
    AnyConstTester ac = SomeConstTester{};
    ac.c_func();
    REQUIRE(true);
}

RASPBERRY_DECL_METHOD(ConversionTester, test);

using AnyConversionTester = raspberry::Any< ConversionTester< int(double) > >;

struct SomeConversionTester {
    double test(double d) const { return d; }
};

TEST_CASE("Method return values follow implicit conversion through concepts", "[raspberry]") {
    SomeConversionTester s;
    double d = 7.42;
    REQUIRE(s.test(d) == 7.42);

    AnyConversionTester a = s;
    REQUIRE(a.test(d) == 7);
}

<commit_msg>Added tests for RecAny<commit_after>
#include "catch.hpp"

#include <raspberry/raspberry.hpp>

#include <string>

RASPBERRY_DECL_METHOD(FuncConcept, func);
RASPBERRY_DECL_METHOD(SquareConcept, square);

using AnyFunc = raspberry::Any<FuncConcept<int()const>,SquareConcept<float(float)>>;

struct SomeFunc {
    int func() const {
        return 42;
    }

    float square(float x) {
        return x*x;
    }
};

TEST_CASE("Objects can be stored in Any", "[raspberry]") {
    AnyFunc f = SomeFunc{};

    REQUIRE(f.func() == 42);
    REQUIRE(f.square(12) == 144);
}

struct negative_test_assign {
    template <typename AF>
    static decltype( AF(std::declval<const AF&>()), bool{} ) test(int) { return false; }

    template <typename AF>
    static bool test(long) { return true; }
};

TEST_CASE("Any cannot be stored in Any or copied", "[raspberry]") {
    REQUIRE(negative_test_assign::test<AnyFunc>(int{}));
}

RASPBERRY_DECL_METHOD(RefDetectConcept, ref_detect);

using AnyRefDetector = raspberry::Any<RefDetectConcept<void(int)>>;

struct RefDetector {
    int value = 0;

    void ref_detect(int x) {
        value = x;
    }
};

TEST_CASE("Objects are copied by default", "[raspberry]") {
    RefDetector rd;
    REQUIRE(rd.value == 0);

    AnyRefDetector ard = rd;
    REQUIRE(rd.value == 0);

    ard.ref_detect(42);
    REQUIRE(rd.value == 0);
}

TEST_CASE("std::reference_wrapper is used to capture by reference", "[raspberry]") {
    RefDetector rd;
    REQUIRE(rd.value == 0);

    AnyRefDetector ard = std::ref(rd);
    REQUIRE(rd.value == 0);

    ard.ref_detect(42);
    REQUIRE(rd.value == 42);
}

RASPBERRY_DECL_METHOD(SetStringConcept, set_string);

using AnySetString = raspberry::Any<
        SetStringConcept< void(const std::string&) >,
        SetStringConcept< void(const char*) >
>;

struct StringSetter {
    std::string value;

    void set_string(const std::string& s) {
        value = s;
    }

    void set_string(const char* s) {
        value = s;
    }
};

TEST_CASE("Methods can be overloaded", "[raspberry]") {
    StringSetter s;
    AnySetString a = std::ref(s);

    a.set_string("char[]");
    REQUIRE(s.value == "char[]");

    a.set_string(std::string("std::string"));
    REQUIRE(s.value == "std::string");

}

RASPBERRY_DECL_METHOD(MaybeConstGetter, get);

using AnyMaybeConstGetter = raspberry::Any<
        MaybeConstGetter< int&() >,
        MaybeConstGetter< const int&() const >
>;

struct SomeMaybeConstGetter {
    int value;
    int& get() { return value; }
    const int& get() const { return value; }
};

TEST_CASE("Const and non-const overloads can coexist", "[raspberry]") {
    SomeMaybeConstGetter s;
    AnyMaybeConstGetter a = std::ref(s);

    s.value = 7;
    REQUIRE(s.value == 7);

    a.get() = 42;
    REQUIRE(s.value == 42);

    const auto& ac = a;
    REQUIRE(ac.get() == 42);
    REQUIRE(std::is_const<std::remove_reference_t<decltype(ac.get())>>::value);
}

using AnyMaybeConstGetterReversed = raspberry::Any<
        MaybeConstGetter< const int&() const >,
        MaybeConstGetter< int&() >
>;

TEST_CASE("Const and non-const overloads can come in any order", "[raspberry]") {
    SomeMaybeConstGetter s;
    AnyMaybeConstGetterReversed a = std::ref(s);

    s.value = 7;
    REQUIRE(s.value == 7);

    a.get() = 42;
    REQUIRE(s.value == 42);

    const auto& ac = a;
    REQUIRE(ac.get() == 42);
    REQUIRE(std::is_const<std::remove_reference_t<decltype(ac.get())>>::value);
}

RASPBERRY_DECL_METHOD(ConstTester, c_func);

using AnyConstTester = raspberry::Any< ConstTester< void() > >;

struct SomeConstTester {
    void c_func() const {}
};

TEST_CASE("Const methods can be called from non-const concepts", "[raspberry]") {
    AnyConstTester ac = SomeConstTester{};
    ac.c_func();
    REQUIRE(true);
}

RASPBERRY_DECL_METHOD(ConversionTester, test);

using AnyConversionTester = raspberry::Any< ConversionTester< int(double) > >;

struct SomeConversionTester {
    double test(double d) const { return d; }
};

TEST_CASE("Method return values follow implicit conversion through concepts", "[raspberry]") {
    SomeConversionTester s;
    double d = 7.42;
    REQUIRE(s.test(d) == 7.42);

    AnyConversionTester a = s;
    REQUIRE(a.test(d) == 7);
}

struct RecAnyFunc final : raspberry::RecAny<
    FuncConcept<int(RecAnyFunc&)>
> { using RecAny::RecAny; };

struct RecAnyTester {
    int x;
    int func(RecAnyFunc&) { return x; }
};

TEST_CASE("RecAny can be used for recursive CRTP", "[raspberry]") {
    RecAnyFunc rat = RecAnyTester{7};
    REQUIRE(rat.func(rat) == 7);

    rat = RecAnyTester{42};
    REQUIRE(rat.func(rat) == 42);

    RecAnyFunc rat2 = std::move(rat);
    rat = RecAnyTester{13};
    REQUIRE(rat.func(rat) == 13);
    REQUIRE(rat2.func(rat2) == 42);
};

struct RecAnyFuncValue final : raspberry::RecAny<
    FuncConcept<int(RecAnyFuncValue)>
> { using RecAny::RecAny; };

struct RecAnyValueTester {
    int x;
    int func(RecAnyFuncValue) { return x; }
};

TEST_CASE("RecAny concepts can accept RecAny value types", "[raspberry]") {
    RecAnyFuncValue rat1 = RecAnyValueTester{7};
    RecAnyFuncValue rat2 = RecAnyValueTester{42};
    REQUIRE(rat1.func(std::move(rat2)) == 7);
};
<|endoftext|>


<commit_before>#include <iostream>
#include "../Jzon.h"

int main(int argc, char **argv)
{
	if (argc != 2) {
		std::cerr << "Expecting 1 argument - a file name" << std::endl;
		return 1;
	}
	std::string fname(argv[1]);
	Jzon::FileReader readr(fname);
	std::string const err = readr.GetError();
	if (!err.empty()) {
		std::cerr << err << std::endl;
		return 1;
	}
	Jzon::Node *node;
	switch (readr.DetermineType())
	{
	case Jzon::Node::Type::T_ARRAY:
		node = new Jzon::Array;
		// std::cout << "It's an array!" << std::endl;
		break;
	case Jzon::Node::Type::T_OBJECT:
		node = new Jzon::Object;
		// std::cout << "It's an object!" << std::endl;
		break;
	case Jzon::Node::Type::T_VALUE:
		node = new Jzon::Value;
		// std::cout << "It's a value!" << std::endl;
		break;
	default:
		std::cerr << "Sanity check fail" << std::endl;
		return 1;
	}
	bool res = readr.Read(*node);
	if (!res) {
		std::cerr << readr.GetError() << std::endl;
		return 1;
	}
	// std::cout << "It worked!" << std::endl;
	return 0;
}<commit_msg>Remove c++11 enum<commit_after>#include <iostream>
#include "../Jzon.h"

int main(int argc, char **argv)
{
	if (argc != 2) {
		std::cerr << "Expecting 1 argument - a file name" << std::endl;
		return 1;
	}
	std::string fname(argv[1]);
	Jzon::FileReader readr(fname);
	std::string const err = readr.GetError();
	if (!err.empty()) {
		std::cerr << err << std::endl;
		return 1;
	}
	Jzon::Node *node;
	switch (readr.DetermineType())
	{
	case Jzon::Node::T_ARRAY:
		node = new Jzon::Array;
		// std::cout << "It's an array!" << std::endl;
		break;
	case Jzon::Node::T_OBJECT:
		node = new Jzon::Object;
		// std::cout << "It's an object!" << std::endl;
		break;
	case Jzon::Node::T_VALUE:
		node = new Jzon::Value;
		// std::cout << "It's a value!" << std::endl;
		break;
	default:
		std::cerr << "Sanity check fail" << std::endl;
		return 1;
	}
	bool res = readr.Read(*node);
	if (!res) {
		std::cerr << readr.GetError() << std::endl;
		return 1;
	}
	// std::cout << "It worked!" << std::endl;
	return 0;
}
<|endoftext|>


<commit_before>#include <sx/ResFileHelper.h>
#include <ns/NodeFactory.h>
#include <node0/SceneNode.h>
#include <node0/CompComplex.h>
#include <unirender/Factory.h>
#include <ns/RegistCallback.h>
#include <facade/Facade.h>
#include <shadergraph/Evaluator.h>
#include <shadergraph/Block.h>
#include <shadergraph/ShaderGraph.h>
#include <shadergraph/block/FragmentShader.h>
#include <js/RapidJsonHelper.h>
#include <dag/Node.h>
#include <unirender/typedef.h>
#include <unirender/Device.h>
#include <unirender/ShaderProgram.h>
#include <unirender/TextureDescription.h>
#include <unirender/Framebuffer.h>
#include <unirender/Context.h>
#include <unirender/DrawState.h>
#include <unirender/ClearState.h>
#include <gimg_export.h>
#include <gimg_typedef.h>

#include <blueprint/Node.h>
#include <blueprint/Pin.h>
#include <blueprint/Connecting.h>
#include <blueprint/Blueprint.h>
#include <blueprint/CompNode.h>
#include <blueprint/NSCompNode.h>
#include <shaderlab/ShaderLab.h>
#include <shaderlab/ShaderAdapter.h>
#include <shaderlab/Evaluator.h>
#include <shaderlab/Node.h>
#include <shaderlab/node/Texture2DAsset.h>

#include <gl/glew.h>
#include <glfw3.h>

#include <boost/filesystem.hpp>

#include <stdio.h>
#include <stdlib.h>

namespace
{

const char* vs = R"(
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main()
{
	gl_Position = vec4(aPos, 0.0, 1.0);
	TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
)";

const int TEX_SIZE = 512;

uint8_t* BUFFER = nullptr;

}

void error_callback(int error, const char* description)
{
    fputs(description, stderr);
}

bool init_gl()
{
	glfwSetErrorCallback(error_callback);
	if (!glfwInit()) {
		exit(EXIT_FAILURE);
		return false;
	}

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
	GLFWwindow* window = glfwCreateWindow(100, 100, "rotate-crop", nullptr, nullptr);
	if (!window)
	{
		glfwTerminate();
		return false;
	}
	glfwMakeContextCurrent(window);

	// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
	glewExperimental = GL_TRUE;
	//// Initialize GLEW to setup the OpenGL Function pointers
	//if (glewInit() != GLEW_OK) {
	//	return -1;
	//}

	return true;
}

void setup_nodes(const ur::Device& dev, const std::string& dir,
                 const std::vector<n0::SceneNodePtr>& nodes, std::vector<bp::NodePtr>& front_nodes,
                 std::vector<std::shared_ptr<dag::Node<shadergraph::Variant>>>& back_nodes)
{
    for (int i = 0, n = nodes.size(); i < n; ++i)
    {
        if (!nodes[i]->HasUniqueComp<bp::CompNode>()) {
            continue;
        }

        auto front = nodes[i]->GetUniqueComp<bp::CompNode>().GetNode();
        front_nodes[i] = front;
        if (!front) {
            continue;
        }

        auto type = front->get_type();
        if (!type.is_derived_from<shaderlab::Node>()) {
            continue;
        }

        // create back node

        auto src_type = type.get_name().to_string();
        auto dst_type = "shadergraph::" + src_type.substr(src_type.find("shaderlab::") + std::string("shaderlab::").size());

        rttr::type t = rttr::type::get_by_name(dst_type);
        assert(t.is_valid());

        rttr::variant var = t.create();
        assert(var.is_valid());

        auto back = var.get_value<std::shared_ptr<dag::Node<shadergraph::Variant>>>();
        assert(back);

        // update back props
        auto f_type = front->get_type();
        auto b_type = back->get_type();
        if (f_type.is_derived_from<shaderlab::Node>() &&
            b_type.is_derived_from<dag::Node<shadergraph::Variant>>())
        {
            for (auto& dst_prop : b_type.get_properties())
            {
                auto src_prop = f_type.get_property(dst_prop.get_name());
                assert(src_prop.is_valid());
                dst_prop.set_value(back, src_prop.get_value(front));
            }
        }

        shaderlab::ShaderAdapter::Front2Back(*front, *back, dir, dev);

        back_nodes[i] = back;
    }
}

void setup_connections(const std::string& filepath, const std::vector<n0::SceneNodePtr>& nodes,
                       std::vector<bp::NodePtr>& front_nodes, std::vector<std::shared_ptr<dag::Node<shadergraph::Variant>>>& back_nodes)
{
    std::unordered_map<const bp::Node*, std::shared_ptr<dag::Node<shadergraph::Variant>>> front2back;
    assert(front_nodes.size() == back_nodes.size() && nodes.size() == front_nodes.size());
    for (int i = 0, n = nodes.size(); i < n; ++i)
    {
        if (front_nodes[i]) {
            assert(back_nodes[i]);
            front2back.insert({ front_nodes[i].get(), back_nodes[i] });
        }
    }

    rapidjson::Document doc;
    js::RapidJsonHelper::ReadFromFile(filepath.c_str(), doc);
    bp::NSCompNode::LoadConnection(nodes, doc["nodes"]);
    for (int i = 0, n = nodes.size(); i < n; ++i)
    {
        auto& front = front_nodes[i];
        auto& back = back_nodes[i];
        if (!front) {
            continue;
        }

        assert(back);
        for (auto& in : front->GetAllInput())
        {
            for (auto& conn : in->GetConnecting())
            {
                auto f_pin = conn->GetFrom();
                auto t_pin = conn->GetTo();

                auto f_itr = front2back.find(&f_pin->GetParent());
                auto t_itr = front2back.find(&t_pin->GetParent());
                if (f_itr == front2back.end() || t_itr == front2back.end()) {
                    continue;
                }

                dag::make_connecting<shadergraph::Variant>(
                    { f_itr->second, f_pin->GetPosIdx() },
                    { t_itr->second, t_pin->GetPosIdx() }
                );
            }
        }
    }
}

std::shared_ptr<ur::ShaderProgram>
build_shader(const ur::Device& dev, const std::vector<bp::NodePtr>& front_nodes,
             const std::vector<std::shared_ptr<dag::Node<shadergraph::Variant>>>& back_nodes,
             std::vector<std::pair<size_t, ur::TexturePtr>>& textures)
{
    shadergraph::Evaluator eval;

    std::string fs;

    // build frag m_shader
    for (auto& back : back_nodes)
    {
        if (!back) {
            continue;
        }
        auto block = std::static_pointer_cast<shadergraph::Block>(back);
        if (block->get_type() == rttr::type::get<shadergraph::block::FragmentShader>())
        {
            eval.Rebuild(block);
            fs = eval.GenShaderCode();
            break;
        }
    }

    if (fs.empty()) {
        return nullptr;
    }

    auto shader = dev.CreateShaderProgram(vs, fs);
    if (!shader->CheckStatus()) {
        return nullptr;
    }

    // textures
    assert(front_nodes.size() == back_nodes.size());
    for (int i = 0, n = front_nodes.size(); i < n; ++i)
    {
        auto& front = front_nodes[i];
        auto& back = back_nodes[i];
        if (front->get_type() != rttr::type::get<shaderlab::node::Texture2DAsset>()) {
            continue;
        }

        auto tex = std::static_pointer_cast<shaderlab::node::Texture2DAsset>(front)->GetTexture();
        if (!tex) {
            continue;
        }

        assert(back);
        auto block = std::static_pointer_cast<shadergraph::Block>(back);
        auto name = eval.QueryRealName(&block->GetExports()[0].var.type);

        auto slot = shader->QueryTexSlot(name);
        if (slot >= 0) {
            textures.push_back({ slot, tex });
        }
    }

    // update uniforms
    shaderlab::Evaluator::UpdateUniforms(eval, shader);

    return shader;
}

void test_file(const ur::Device& dev, ur::Context& ctx,
               const std::shared_ptr<ur::Framebuffer>& rt,
               const std::string& filepath)
{
    auto dir = boost::filesystem::path(filepath).parent_path().string();

    auto root = ns::NodeFactory::Create(dev, filepath);

    auto& ccomplex = root->GetSharedComp<n0::CompComplex>();
    auto& children = ccomplex.GetAllChildren();

    std::vector<bp::NodePtr> front_nodes(children.size(), nullptr);
    std::vector<std::shared_ptr<dag::Node<shadergraph::Variant>>> back_nodes(children.size(), nullptr);
    setup_nodes(dev, dir, children, front_nodes, back_nodes);
    setup_connections(filepath, children, front_nodes, back_nodes);

    std::vector<std::pair<size_t, ur::TexturePtr>> textures;
    auto shader = build_shader(dev, front_nodes, back_nodes, textures);

    ctx.SetFramebuffer(rt);
    ctx.SetViewport(0, 0, TEX_SIZE, TEX_SIZE);

    ur::ClearState clear;
    clear.buffers = ur::ClearBuffers::ColorAndDepthBuffer;
    clear.color.FromRGBA(0x88888888);
    ctx.Clear(clear);

    ur::DrawState ds;
    ds.program      = shader;
    ds.render_state = ur::DefaultRenderState2D();
    ds.vertex_array = dev.GetVertexArray(ur::Device::PrimitiveType::Quad, ur::VertexLayoutType::PosTex);

    for (auto& t : textures) {
        ctx.SetTexture(t.first, t.second);
    }

    ctx.Draw(ur::PrimitiveType::TriangleStrip, ds, nullptr);

    dev.ReadPixels(BUFFER, ur::TextureFormat::RGB, 0, 0, TEX_SIZE, TEX_SIZE);

    auto out_filepath = filepath.substr(0, filepath.find_last_of('.')) + ".jpg";
    gimg_export(out_filepath.c_str(), BUFFER, TEX_SIZE, TEX_SIZE, GPF_RGB, false);

    ctx.SetFramebuffer(nullptr);
}

void test_folder(const ur::Device& dev, ur::Context& ctx,
                 const std::string& dir)
{
    ur::TextureDescription desc;
    desc.target = ur::TextureTarget::Texture2D;
    desc.width  = TEX_SIZE;
    desc.height = TEX_SIZE;
    desc.format = ur::TextureFormat::RGB;
    auto tex = dev.CreateTexture(desc);

    auto fbo = dev.CreateFramebuffer();
    fbo->SetAttachment(ur::AttachmentType::Color0, ur::TextureTarget::Texture2D, tex, nullptr);

    boost::filesystem::recursive_directory_iterator itr(dir), end;
    while (itr != end)
    {
        if (boost::filesystem::is_regular(itr->path()))
        {
            auto path = itr->path().string();
            if (sx::ResFileHelper::Type(path) == sx::ResFileType::RES_FILE_JSON) {
                test_file(dev, ctx, fbo, path);
            }
        }
        ++itr;
    }
}

int main()
{
    init_gl();

    auto dev = ur::CreateDeviceGL();
    auto ctx = ur::CreateContextGL(*dev);

    ns::RegistCallback::Init();
    facade::Facade::Instance()->Init(*dev);
    bp::Blueprint::Instance();
    shadergraph::ShaderGraph::Instance();
    shaderlab::ShaderLab::Instance();

    BUFFER = new uint8_t[TEX_SIZE * TEX_SIZE * 4];

    // fixme: id
    auto node = std::make_shared<n0::SceneNode>();
    node->AddSharedComp<n0::CompComplex>();

    test_folder(*dev, *ctx, "../../../test/cases");

    return 0;
}<commit_msg>[CHANGED] move some funcs to bp<commit_after>#include <sx/ResFileHelper.h>
#include <ns/NodeFactory.h>
#include <node0/SceneNode.h>
#include <node0/CompComplex.h>
#include <unirender/Factory.h>
#include <ns/RegistCallback.h>
#include <facade/Facade.h>
#include <shadergraph/Evaluator.h>
#include <shadergraph/Block.h>
#include <shadergraph/ShaderGraph.h>
#include <shadergraph/block/FragmentShader.h>
#include <js/RapidJsonHelper.h>
#include <dag/Node.h>
#include <unirender/typedef.h>
#include <unirender/Device.h>
#include <unirender/ShaderProgram.h>
#include <unirender/TextureDescription.h>
#include <unirender/Framebuffer.h>
#include <unirender/Context.h>
#include <unirender/DrawState.h>
#include <unirender/ClearState.h>
#include <gimg_export.h>
#include <gimg_typedef.h>

#include <blueprint/Node.h>
#include <blueprint/Pin.h>
#include <blueprint/Connecting.h>
#include <blueprint/Blueprint.h>
#include <blueprint/CompNode.h>
#include <blueprint/NSCompNode.h>
#include <blueprint/SerializeHelper.h>
#include <shaderlab/ShaderLab.h>
#include <shaderlab/ShaderAdapter.h>
#include <shaderlab/Evaluator.h>
#include <shaderlab/Node.h>
#include <shaderlab/node/Texture2DAsset.h>

#include <gl/glew.h>
#include <glfw3.h>

#include <boost/filesystem.hpp>

#include <stdio.h>
#include <stdlib.h>

namespace
{

const char* vs = R"(
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main()
{
	gl_Position = vec4(aPos, 0.0, 1.0);
	TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
)";

const int TEX_SIZE = 512;

uint8_t* BUFFER = nullptr;

}

void error_callback(int error, const char* description)
{
    fputs(description, stderr);
}

bool init_gl()
{
	glfwSetErrorCallback(error_callback);
	if (!glfwInit()) {
		exit(EXIT_FAILURE);
		return false;
	}

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
	GLFWwindow* window = glfwCreateWindow(100, 100, "rotate-crop", nullptr, nullptr);
	if (!window)
	{
		glfwTerminate();
		return false;
	}
	glfwMakeContextCurrent(window);

	// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
	glewExperimental = GL_TRUE;
	//// Initialize GLEW to setup the OpenGL Function pointers
	//if (glewInit() != GLEW_OK) {
	//	return -1;
	//}

	return true;
}

std::shared_ptr<ur::ShaderProgram>
build_shader(const ur::Device& dev, const std::vector<bp::NodePtr>& front_nodes,
             const std::vector<std::shared_ptr<dag::Node<shadergraph::Variant>>>& back_nodes,
             std::vector<std::pair<size_t, ur::TexturePtr>>& textures)
{
    shadergraph::Evaluator eval;

    std::string fs;

    // build frag m_shader
    for (auto& back : back_nodes)
    {
        if (!back) {
            continue;
        }
        auto block = std::static_pointer_cast<shadergraph::Block>(back);
        if (block->get_type() == rttr::type::get<shadergraph::block::FragmentShader>())
        {
            eval.Rebuild(block);
            fs = eval.GenShaderCode();
            break;
        }
    }

    if (fs.empty()) {
        return nullptr;
    }

    auto shader = dev.CreateShaderProgram(vs, fs);
    if (!shader->CheckStatus()) {
        return nullptr;
    }

    // textures
    assert(front_nodes.size() == back_nodes.size());
    for (int i = 0, n = front_nodes.size(); i < n; ++i)
    {
        auto& front = front_nodes[i];
        auto& back = back_nodes[i];
        if (front->get_type() != rttr::type::get<shaderlab::node::Texture2DAsset>()) {
            continue;
        }

        auto tex = std::static_pointer_cast<shaderlab::node::Texture2DAsset>(front)->GetTexture();
        if (!tex) {
            continue;
        }

        assert(back);
        auto block = std::static_pointer_cast<shadergraph::Block>(back);
        auto name = eval.QueryRealName(&block->GetExports()[0].var.type);

        auto slot = shader->QueryTexSlot(name);
        if (slot >= 0) {
            textures.push_back({ slot, tex });
        }
    }

    // update uniforms
    shaderlab::Evaluator::UpdateUniforms(eval, shader);

    return shader;
}

void test_file(const ur::Device& dev, ur::Context& ctx,
               const std::shared_ptr<ur::Framebuffer>& rt,
               const std::string& filepath)
{
    auto dir = boost::filesystem::path(filepath).parent_path().string();

    auto root = ns::NodeFactory::Create(dev, filepath);

    auto& ccomplex = root->GetSharedComp<n0::CompComplex>();
    auto& children = ccomplex.GetAllChildren();

    std::vector<bp::NodePtr> front_nodes(children.size(), nullptr);
    std::vector<std::shared_ptr<dag::Node<shadergraph::Variant>>> back_nodes(children.size(), nullptr);

    bp::SerializeHelper::SetupNodes(children, front_nodes, back_nodes);
    assert(front_nodes.size() == back_nodes.size());
    for (int i = 0, n = front_nodes.size(); i < n; ++i) {
        shaderlab::ShaderAdapter::Front2Back(*front_nodes[i], *back_nodes[i], dir, dev);
    }
    bp::SerializeHelper::SetupConnections(filepath, children, front_nodes, back_nodes);

    std::vector<std::pair<size_t, ur::TexturePtr>> textures;
    auto shader = build_shader(dev, front_nodes, back_nodes, textures);

    ctx.SetFramebuffer(rt);
    ctx.SetViewport(0, 0, TEX_SIZE, TEX_SIZE);

    ur::ClearState clear;
    clear.buffers = ur::ClearBuffers::ColorAndDepthBuffer;
    clear.color.FromRGBA(0x88888888);
    ctx.Clear(clear);

    ur::DrawState ds;
    ds.program      = shader;
    ds.render_state = ur::DefaultRenderState2D();
    ds.vertex_array = dev.GetVertexArray(ur::Device::PrimitiveType::Quad, ur::VertexLayoutType::PosTex);

    for (auto& t : textures) {
        ctx.SetTexture(t.first, t.second);
    }

    ctx.Draw(ur::PrimitiveType::TriangleStrip, ds, nullptr);

    dev.ReadPixels(BUFFER, ur::TextureFormat::RGB, 0, 0, TEX_SIZE, TEX_SIZE);

    auto out_filepath = filepath.substr(0, filepath.find_last_of('.')) + ".jpg";
    gimg_export(out_filepath.c_str(), BUFFER, TEX_SIZE, TEX_SIZE, GPF_RGB, false);

    ctx.SetFramebuffer(nullptr);
}

void test_folder(const ur::Device& dev, ur::Context& ctx,
                 const std::string& dir)
{
    ur::TextureDescription desc;
    desc.target = ur::TextureTarget::Texture2D;
    desc.width  = TEX_SIZE;
    desc.height = TEX_SIZE;
    desc.format = ur::TextureFormat::RGB;
    auto tex = dev.CreateTexture(desc);

    auto fbo = dev.CreateFramebuffer();
    fbo->SetAttachment(ur::AttachmentType::Color0, ur::TextureTarget::Texture2D, tex, nullptr);

    boost::filesystem::recursive_directory_iterator itr(dir), end;
    while (itr != end)
    {
        if (boost::filesystem::is_regular(itr->path()))
        {
            auto path = itr->path().string();
            if (sx::ResFileHelper::Type(path) == sx::ResFileType::RES_FILE_JSON) {
                test_file(dev, ctx, fbo, path);
            }
        }
        ++itr;
    }
}

int main()
{
    init_gl();

    auto dev = ur::CreateDeviceGL();
    auto ctx = ur::CreateContextGL(*dev);

    ns::RegistCallback::Init();
    facade::Facade::Instance()->Init(*dev);
    bp::Blueprint::Instance();
    shadergraph::ShaderGraph::Instance();
    shaderlab::ShaderLab::Instance();

    BUFFER = new uint8_t[TEX_SIZE * TEX_SIZE * 4];

    // fixme: id
    auto node = std::make_shared<n0::SceneNode>();
    node->AddSharedComp<n0::CompComplex>();

    test_folder(*dev, *ctx, "../../../test/cases");

    return 0;
}<|endoftext|>


<commit_before>#include "dynet/nodes.h"
#include "dynet/exec.h"
#include "dynet/dynet.h"
#include "dynet/training.h"
#include "dynet/timing.h"
#include "dynet/rnn.h"
#include "dynet/gru.h"
#include "dynet/lstm.h"
#include "dynet/fast-lstm.h"
#include "dynet/dict.h"
#include "dynet/expr.h"

#include <iostream>
#include <fstream>
#include <sstream>
#include <type_traits>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/program_options.hpp>

#include "s2s/encdec.hpp"
#include "s2s/define.hpp"
#include "s2s/comp.hpp"
#include "s2s/metrics.hpp"

namespace s2s {

    void greedy_decode(const batch& one_batch, std::vector<std::vector<unsigned int > >& osent, encoder_decoder *encdec, dicts &d, const s2s_options &opts){
        //unsigned slen = sents.size();
        dynet::ComputationGraph cg;
        osent.push_back(std::vector<unsigned int>(one_batch.src.at(0).at(0).size(), d.target_start_id));
        std::vector<dynet::expr::Expression> i_enc = encdec->encoder(one_batch, cg);
        std::vector<dynet::expr::Expression> i_feed = encdec->init_feed(one_batch, cg);
        for (int t = 0; t < opts.max_length; ++t) {
            dynet::expr::Expression i_att_t = encdec->decoder_attention(cg, osent[t], i_feed[t], i_enc[0]);
            std::vector<dynet::expr::Expression> i_out_t = encdec->decoder_output(cg, i_att_t, i_enc[1]);
            i_feed.push_back(i_out_t[1]);
            Expression predict = softmax(i_out_t[0]);
            std::vector<dynet::Tensor> results = cg.incremental_forward(predict).batch_elems();
            std::vector<unsigned int> osent_col;
            for(unsigned int i = 0; i < results.size(); i++){
                auto output = as_vector(results.at(i));
                int w_id = 0;
                double w_prob = output[w_id];
                for(unsigned int j=0; j<output.size(); j++){
                    if(output[j] > w_prob){
                        w_id = j;
                        w_prob = output[j];
                    }
                }
                osent_col.push_back(w_id);
            }
            osent.push_back(osent_col);
            // end check
            unsigned int num_end = 0;
            for(const unsigned int w_id : osent_col){
                if(w_id == d.target_end_id){
                    num_end++;
                }
            }
            if(num_end == osent_col.size()){
                break;
            }
        }
    }

    void greedy_decode_vinyals(const batch& one_batch, std::vector<std::vector<unsigned int > >& osent, encoder_decoder *encdec, dicts &d, const s2s_options &opts){
        //unsigned slen = sents.size();
        dynet::ComputationGraph cg;
        std::vector XX_count = one_batch.len_src;
        osent.push_back(std::vector<unsigned int>(one_batch.src.at(0).at(0).size(), d.target_start_id));
        std::vector<dynet::expr::Expression> i_enc = encdec->encoder(one_batch, cg);
        std::vector<dynet::expr::Expression> i_feed = encdec->init_feed(one_batch, cg);
        // skip start and end symbols from count
        for(auto& elem : one_batch.len_src){
            elem =- 2;
        }
        for (int t = 0; t < opts.max_length; ++t) {
            dynet::expr::Expression i_att_t = encdec->decoder_attention(cg, osent[t], i_feed[t], i_enc[0]);
            std::vector<dynet::expr::Expression> i_out_t = encdec->decoder_output(cg, i_att_t, i_enc[1]);
            i_feed.push_back(i_out_t[1]);
            Expression predict = softmax(i_out_t[0]);
            std::vector<dynet::Tensor> results = cg.incremental_forward(predict).batch_elems();
            std::vector<unsigned int> osent_col;
            for(unsigned int i = 0; i < results.size(); i++){
                auto output = as_vector(results.at(i));
                int w_id = 0;
                double w_prob = output[w_id];
                for(unsigned int j=0; j<output.size(); j++){
                    if(output[j] > w_prob){
                        if(XX_count.at(j) > 0){
                            if(j != d.target_end_id){
                                w_id = j;
                                w_prob = output[j];
                            }
                        }else{
                            std::string w_str = d.d_trg.convert(w_id);
                            if(j != d.d_trg[0].convert("XX") || w_str[0] != '('){
                                w_id = j;
                                w_prob = output[j];
                            }
                        }
                    }
                }
                osent_col.push_back(w_id);
                if(w_id == d.d_trg[0].convert("XX")){
                    XX_count[i]--;
                }
            }
            osent.push_back(osent_col);
            // end check
            unsigned int num_end = 0;
            for(const unsigned int w_id : osent_col){
                if(w_id == d.target_end_id){
                    num_end++;
                }
            }
            if(num_end == osent_col.size()){
                break;
            }
        }
    }

    void beam_decode(){
    }

    std::string print_sents(std::vector<std::vector<unsigned int > >& osent, dicts& d){
        std::string sents = "";
        std::vector<std::vector<unsigned int> > sents_conved;
        sents_conved.resize(osent.at(0).size());
        for(unsigned int col_id = 0; col_id < osent.size(); col_id++){
            for(unsigned int sid = 0; sid < osent.at(col_id).size(); sid++){
                sents_conved[sid].push_back(osent.at(col_id).at(sid));
            }
        }
        for(const auto sent : sents_conved){
            for(const auto wid : sent){
                std::string word = d.d_trg.convert(wid);
                sents += word;
                if(wid == d.target_end_id){
                    break;
                }
                sents += " ";
            }
            sents += "\n";
        }
        return sents;
    }

};
<commit_msg>Vinyals decoder fixed.<commit_after>#include "dynet/nodes.h"
#include "dynet/exec.h"
#include "dynet/dynet.h"
#include "dynet/training.h"
#include "dynet/timing.h"
#include "dynet/rnn.h"
#include "dynet/gru.h"
#include "dynet/lstm.h"
#include "dynet/fast-lstm.h"
#include "dynet/dict.h"
#include "dynet/expr.h"

#include <iostream>
#include <fstream>
#include <sstream>
#include <type_traits>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/program_options.hpp>

#include "s2s/encdec.hpp"
#include "s2s/define.hpp"
#include "s2s/comp.hpp"
#include "s2s/metrics.hpp"

namespace s2s {

    void greedy_decode(const batch& one_batch, std::vector<std::vector<unsigned int > >& osent, encoder_decoder *encdec, dicts &d, const s2s_options &opts){
        //unsigned slen = sents.size();
        dynet::ComputationGraph cg;
        osent.push_back(std::vector<unsigned int>(one_batch.src.at(0).at(0).size(), d.target_start_id));
        std::vector<dynet::expr::Expression> i_enc = encdec->encoder(one_batch, cg);
        std::vector<dynet::expr::Expression> i_feed = encdec->init_feed(one_batch, cg);
        for (int t = 0; t < opts.max_length; ++t) {
            dynet::expr::Expression i_att_t = encdec->decoder_attention(cg, osent[t], i_feed[t], i_enc[0]);
            std::vector<dynet::expr::Expression> i_out_t = encdec->decoder_output(cg, i_att_t, i_enc[1]);
            i_feed.push_back(i_out_t[1]);
            Expression predict = softmax(i_out_t[0]);
            std::vector<dynet::Tensor> results = cg.incremental_forward(predict).batch_elems();
            std::vector<unsigned int> osent_col;
            for(unsigned int i = 0; i < results.size(); i++){
                auto output = as_vector(results.at(i));
                int w_id = 0;
                double w_prob = output[w_id];
                for(unsigned int j=0; j<output.size(); j++){
                    if(output[j] > w_prob){
                        w_id = j;
                        w_prob = output[j];
                    }
                }
                osent_col.push_back(w_id);
            }
            osent.push_back(osent_col);
            // end check
            unsigned int num_end = 0;
            for(const unsigned int w_id : osent_col){
                if(w_id == d.target_end_id){
                    num_end++;
                }
            }
            if(num_end == osent_col.size()){
                break;
            }
        }
    }

    void greedy_decode_vinyals(const batch& one_batch, std::vector<std::vector<unsigned int > >& osent, encoder_decoder *encdec, dicts &d, const s2s_options &opts){
        //unsigned slen = sents.size();
        dynet::ComputationGraph cg;
        std::vector<unsigned int> XX_count = one_batch.len_src;
        osent.push_back(std::vector<unsigned int>(one_batch.src.at(0).at(0).size(), d.target_start_id));
        std::vector<dynet::expr::Expression> i_enc = encdec->encoder(one_batch, cg);
        std::vector<dynet::expr::Expression> i_feed = encdec->init_feed(one_batch, cg);
        // skip start and end symbols from count
        for(auto& elem : XX_count){
            elem =- 2;
        }
        for (int t = 0; t < opts.max_length; ++t) {
            dynet::expr::Expression i_att_t = encdec->decoder_attention(cg, osent[t], i_feed[t], i_enc[0]);
            std::vector<dynet::expr::Expression> i_out_t = encdec->decoder_output(cg, i_att_t, i_enc[1]);
            i_feed.push_back(i_out_t[1]);
            Expression predict = softmax(i_out_t[0]);
            std::vector<dynet::Tensor> results = cg.incremental_forward(predict).batch_elems();
            std::vector<unsigned int> osent_col;
            for(unsigned int i = 0; i < results.size(); i++){
                auto output = as_vector(results.at(i));
                int w_id = 0;
                double w_prob = output[w_id];
                for(unsigned int j=0; j<output.size(); j++){
                    if(output[j] > w_prob){
                        if(XX_count.at(j) > 0){
                            if(j != d.target_end_id){
                                w_id = j;
                                w_prob = output[j];
                            }
                        }else{
                            std::string w_str = d.d_trg.convert(w_id);
                            if(j != d.d_trg.convert("XX") || w_str[0] != '('){
                                w_id = j;
                                w_prob = output[j];
                            }
                        }
                    }
                }
                osent_col.push_back(w_id);
                if(w_id == d.d_trg.convert("XX")){
                    XX_count[i]--;
                }
            }
            osent.push_back(osent_col);
            // end check
            unsigned int num_end = 0;
            for(const unsigned int w_id : osent_col){
                if(w_id == d.target_end_id){
                    num_end++;
                }
            }
            if(num_end == osent_col.size()){
                break;
            }
        }
    }

    void beam_decode(){
    }

    std::string print_sents(std::vector<std::vector<unsigned int > >& osent, dicts& d){
        std::string sents = "";
        std::vector<std::vector<unsigned int> > sents_conved;
        sents_conved.resize(osent.at(0).size());
        for(unsigned int col_id = 0; col_id < osent.size(); col_id++){
            for(unsigned int sid = 0; sid < osent.at(col_id).size(); sid++){
                sents_conved[sid].push_back(osent.at(col_id).at(sid));
            }
        }
        for(const auto sent : sents_conved){
            for(const auto wid : sent){
                std::string word = d.d_trg.convert(wid);
                sents += word;
                if(wid == d.target_end_id){
                    break;
                }
                sents += " ";
            }
            sents += "\n";
        }
        return sents;
    }

};
<|endoftext|>


<commit_before>#pragma once

#define xgetter(ACCESSOR, MEMBER) \
	auto const& ACCESSOR() const noexcept { return MEMBER; }

#define xsetter(ACCESSOR, MEMBER)                \
	auto& ACCESSOR(decltype(MEMBER) const & m) { \
		MEMBER = m;                              \
		return *this;                            \
	}                                            \
                                                 \
	auto& ACCESSOR(decltype(MEMBER)&& m) {       \
		MEMBER = std::move(m);                   \
		return *this;                            \
	}

#define xaccess(ACCESSOR, MEMBER) \
	xgetter(ACCESSOR, MEMBER) xsetter(ACCESSOR, MEMBER)

// Virtual setter
#define xsetterv(ACCESSOR, MEMBER)                \
	virtual auto& ACCESSOR(decltype(MEMBER) const & m) { \
		MEMBER = m;                              \
		return *this;                            \
	}

#define xaccessv(ACCESSOR, MEMBER) \
	xgetter(ACCESSOR, MEMBER) xsetterv(ACCESSOR, MEMBER)

#define xproperty_r(TYPE, NAME) TYPE NAME();
#define xproperty_w(TYPE, NAME) void NAME(TYPE const&);
#define xproperty(TYPE, NAME) xproperty_r(TYPE, NAME); xproperty_w(TYPE, NAME)
<commit_msg>Fixed xaccessv<commit_after>#pragma once

#define xgetter(ACCESSOR, MEMBER) \
	auto const& ACCESSOR() const noexcept { return MEMBER; }

#define xsetter(ACCESSOR, MEMBER)                \
	auto& ACCESSOR(decltype(MEMBER) const & m) { \
		MEMBER = m;                              \
		return *this;                            \
	}                                            \
                                                 \
	auto& ACCESSOR(decltype(MEMBER)&& m) {       \
		MEMBER = std::move(m);                   \
		return *this;                            \
	}

#define xaccess(ACCESSOR, MEMBER) \
	xgetter(ACCESSOR, MEMBER) xsetter(ACCESSOR, MEMBER)

// Virtual setter
#define xsetterv(ACCESSOR, MEMBER)                \
	virtual void ACCESSOR(decltype(MEMBER) const & m) { \
		MEMBER = m;                              \
	}

#define xaccessv(ACCESSOR, MEMBER) \
	xgetter(ACCESSOR, MEMBER) xsetterv(ACCESSOR, MEMBER)

#define xproperty_r(TYPE, NAME) TYPE NAME();
#define xproperty_w(TYPE, NAME) void NAME(TYPE const&);
#define xproperty(TYPE, NAME) xproperty_r(TYPE, NAME); xproperty_w(TYPE, NAME)
<|endoftext|>


<commit_before>#include <agency/new_executor_traits.hpp>
#include <cassert>
#include <iostream>

#include "test_executors.hpp"

template<class Executor>
void test()
{
  using executor_type = Executor;

  {
    // returning void
    executor_type exec;

    int set_me_to_thirteen = 0;

    agency::new_executor_traits<executor_type>::execute(exec, [&]
    {
      set_me_to_thirteen = 13;
    });

    assert(set_me_to_thirteen == 13);
    assert(exec.valid());
  }

  {
    // returning int
    executor_type exec;

    auto result = agency::new_executor_traits<executor_type>::execute(exec, []
    {
      return 13;
    });

    assert(result == 13);
    assert(exec.valid());
  }
}

int main()
{
  using namespace test_executors;

  test<empty_executor>();
  test<single_agent_when_all_execute_and_select_executor>();
  test<multi_agent_when_all_execute_and_select_executor>();
  test<single_agent_then_execute_executor>();

  test<multi_agent_execute_returning_user_defined_container_executor>();
  test<multi_agent_execute_returning_default_container_executor>();
  test<multi_agent_execute_returning_void_executor>();

  test<multi_agent_async_execute_returning_user_defined_container_executor>();

  std::cout << "OK" << std::endl;

  return 0;
}

<commit_msg>Test multi_agent_async_execute_returning_default_container with test_single_agent_executor.cpp.<commit_after>#include <agency/new_executor_traits.hpp>
#include <cassert>
#include <iostream>

#include "test_executors.hpp"

template<class Executor>
void test()
{
  using executor_type = Executor;

  {
    // returning void
    executor_type exec;

    int set_me_to_thirteen = 0;

    agency::new_executor_traits<executor_type>::execute(exec, [&]
    {
      set_me_to_thirteen = 13;
    });

    assert(set_me_to_thirteen == 13);
    assert(exec.valid());
  }

  {
    // returning int
    executor_type exec;

    auto result = agency::new_executor_traits<executor_type>::execute(exec, []
    {
      return 13;
    });

    assert(result == 13);
    assert(exec.valid());
  }
}

int main()
{
  using namespace test_executors;

  test<empty_executor>();
  test<single_agent_when_all_execute_and_select_executor>();
  test<multi_agent_when_all_execute_and_select_executor>();
  test<single_agent_then_execute_executor>();

  test<multi_agent_execute_returning_user_defined_container_executor>();
  test<multi_agent_execute_returning_default_container_executor>();
  test<multi_agent_execute_returning_void_executor>();

  test<multi_agent_async_execute_returning_user_defined_container_executor>();
  test<multi_agent_async_execute_returning_default_container_executor>();

  std::cout << "OK" << std::endl;

  return 0;
}

<|endoftext|>


<commit_before>#include <agency/new_executor_traits.hpp>
#include <cassert>
#include <iostream>

#include "test_executors.hpp"

template<class Executor>
void test()
{
  using executor_type = Executor;

  {
    // returning void
    executor_type exec;

    int set_me_to_thirteen = 0;

    agency::new_executor_traits<executor_type>::execute(exec, [&]
    {
      set_me_to_thirteen = 13;
    });

    assert(set_me_to_thirteen == 13);
    assert(exec.valid());
  }

  {
    // returning int
    executor_type exec;

    auto result = agency::new_executor_traits<executor_type>::execute(exec, []
    {
      return 13;
    });

    assert(result == 13);
    assert(exec.valid());
  }
}

int main()
{
  using namespace test_executors;

  test<empty_executor>();
  test<single_agent_when_all_execute_and_select_executor>();
  test<multi_agent_when_all_execute_and_select_executor>();
  test<single_agent_then_execute_executor>();

  test<multi_agent_execute_returning_user_defined_container_executor>();
  test<multi_agent_execute_returning_default_container_executor>();
  test<multi_agent_execute_returning_void_executor>();

  test<multi_agent_async_execute_returning_user_defined_container_executor>();
  test<multi_agent_async_execute_returning_default_container_executor>();
  test<multi_agent_async_execute_returning_void_executor>();

  test<multi_agent_execute_with_shared_inits_returning_user_defined_container_executor>();
  test<multi_agent_execute_with_shared_inits_returning_default_container_executor>();
  test<multi_agent_execute_with_shared_inits_returning_void_executor>();

  std::cout << "OK" << std::endl;

  return 0;
}

<commit_msg>Test all executors in test_single_agent_execute.cpp<commit_after>#include <agency/new_executor_traits.hpp>
#include <cassert>
#include <iostream>

#include "test_executors.hpp"

template<class Executor>
void test()
{
  using executor_type = Executor;

  {
    // returning void
    executor_type exec;

    int set_me_to_thirteen = 0;

    agency::new_executor_traits<executor_type>::execute(exec, [&]
    {
      set_me_to_thirteen = 13;
    });

    assert(set_me_to_thirteen == 13);
    assert(exec.valid());
  }

  {
    // returning int
    executor_type exec;

    auto result = agency::new_executor_traits<executor_type>::execute(exec, []
    {
      return 13;
    });

    assert(result == 13);
    assert(exec.valid());
  }
}

int main()
{
  using namespace test_executors;

  // a completely empty executor
  test<empty_executor>();

  // single-agent executors
  test<single_agent_execute_executor>();
  test<single_agent_async_execute_executor>();
  test<single_agent_then_execute_executor>();
  test<single_agent_when_all_execute_and_select_executor>();

  // multi-agent when_all_execute_and_select()
  test<multi_agent_when_all_execute_and_select_executor>();
  test<multi_agent_when_all_execute_and_select_with_shared_inits_executor>();

  // multi-agent execute()
  test<multi_agent_execute_with_shared_inits_returning_user_defined_container_executor>();
  test<multi_agent_execute_with_shared_inits_returning_default_container_executor>();
  test<multi_agent_execute_with_shared_inits_returning_void_executor>();

  test<multi_agent_execute_returning_user_defined_container_executor>();
  test<multi_agent_execute_returning_default_container_executor>();
  test<multi_agent_execute_returning_void_executor>();

  // multi-agent async_execute()
  test<multi_agent_async_execute_with_shared_inits_returning_user_defined_container_executor>();
  test<multi_agent_async_execute_with_shared_inits_returning_default_container_executor>();
  test<multi_agent_async_execute_with_shared_inits_returning_void_executor>();

  test<multi_agent_async_execute_returning_user_defined_container_executor>();
  test<multi_agent_async_execute_returning_default_container_executor>();
  test<multi_agent_async_execute_returning_void_executor>();

  // multi-agent then_execute()
  test<multi_agent_then_execute_with_shared_inits_returning_user_defined_container_executor>();
  test<multi_agent_then_execute_with_shared_inits_returning_default_container_executor>();
  test<multi_agent_then_execute_with_shared_inits_returning_void_executor>();

  test<multi_agent_then_execute_returning_user_defined_container_executor>();
  test<multi_agent_then_execute_returning_default_container_executor>();
  test<multi_agent_then_execute_returning_void_executor>();

  std::cout << "OK" << std::endl;

  return 0;
}

<|endoftext|>


<commit_before>#ifndef VECTOR_HPP
#define VECTOR_HPP

#include <new>
#include "Data.hpp"

namespace var {

/*! \brief Vector Class
 * \details The Vector class
 * is similar to std::vector but is embedded friendly.
 *
 *
 */
template<typename T> class Vector : public Data {
public:

	/*! \details Constructs an empty object.
	  *
	  */
	Vector(){ m_count = 0; }

	/*! \details Constructs a vector with \a count uninitialized items. */
	Vector(int count){
		resize(count);
	}

	/*! \details Returns a referece to the element
	  * at the specified position.
	  *
	  * @param pos The position in the vector to access.
	  *
	  * If \a pos is not a valid value, reference to
	  * the first eleemnt will be returned.
	  *
	  * If there are zero elements in the vector and
	  * no memory has been allocated, this method will
	  * dereference a null-pointer and cause the application
	  * to crash.
	  *
	  * If there are no elements and the vector has been
	  * allocated memory, this method will return a value
	  * that is no longer valid.
	  *
	  */
	T & at(u32 pos){ return Data::at<T>(pos); }

	/*! \details Provides a read-only reference to an element in the Vector.
	  *
	  * The same limitations apply to this method as apply to the read-write version.
	  *
	  */
	const T & at(u32 pos) const { return Data::at<T>(pos); }

	/*! \details Provides un-bounded access to the specified element (read-only).
	  *
	  * If the Vector has no data, this method may dereference a null pointer
	  * and cause the program to crash.
	  */
	const T & operator[](u32 idx) const { return vector_data_const()[idx]; }

	/*! \details Provides un-bounded access to the specified element.
	  *
	  * If the Vector has no data, this method may dereference a null pointer
	  * and cause the program to crash.
	  *
	  */
	T & operator[](u32 idx) { return vector_data()[idx]; }

	/*! \details Finds an object in the array.
	  *
	  * @param a The equivalent object to find
	  * @return The index of the object or count() it if wasn't found
	  *
	  */
	u32 find(const T & a){
		for(u32 i=0; i < count(); i++){
			if( at(i) == a ){
				return i;
			}
		}
		return count();
	}

	u32 find(const T & a, bool (*compare)(const T & a, const T & b)){
		for(u32 i=0; i < count(); i++){
			if( compare(at(i), a) ){
				return i;
			}
		}
		return count();
	}

	T * search(const T & a){
		return (T*)bsearch(&a, to_void(), count(), sizeof(T), ascending);
	}

	T * search(const T & a, int (*compare)(const void *, const void *)){
		return (T*)bsearch(&a, to_void(), count(), sizeof(T), compare);
	}

	/*! \details Returns the number of elements that are
	  * able to fit in the memory that is already allocated.
	  *
	  */
	u32 capacity() const {
		//how many elements can fit in current space
		return Data::capacity() / sizeof(T);
	}

	/*! \details Adds an element to the end of the Vector.
	  *
	  * If the element won't fit, space will be added. If space
	  * cannot be added, nothing will happen.
	  *
	  */
	int push_back(const T & value){
		if( add_space() == 0 ){
			new((void*)(vector_data() + m_count++)) T(value);
			return 0;
		}
		return -1;
	}

	/*! \details Removes the last element of the vector.
	  *
	  * This makes the last element inaccessible. It does not affect
	  * the memory allocation of the vector. Once items are popped,
	  * the memory can be freed using the method shrink_to_fit().
	  *
	  */
	void pop_back(){
		if( m_count ){
			//call the destructor
			vector_data()[m_count-1].~T();
			m_count--;
		}
	}

	/*! \details Frees unused memory that is reserved for this Vector. */
	void shrink_to_fit(){
		Data::resize(m_count*sizeof(T));
	}

	/*! \details Resizes the vector.
	  *
	  * @param count The new number of element for the vector to have
	  *
	  * This method will increase/decrease the number of elements in
	  * the vector. If elements are added, they will not be initialized.
	  *
	  * The method shrink_to_fit() will free memory that is no longer needed. It doesn't affect
	  * the count() of the object.
	  *
	  * The method reserve() will increase the memory that is available but does
	  * not affect the count() of the object().
	  *
	  */
	int resize(u32 count){
		//this needs to destruct each item that will be lost
		if( count < this->count() ){
			//size reduction if count < this->count()
			while( count < this->count() ){
				pop_back();
			}
		} else {
			while( count > this->count() ){
				push_back(T());
			}
		}
		return 0;
	}

	/*!
	  * \details Fills the vector will the specified value.
	  * \param value The value to assign to each element of the vector
	  */
	virtual void fill(const T & value){
		u32 i;
		for(i=0; i < count(); i++){
			this->at(i) = value;
		}
	}

	/*! \details Reserves enough data for the specified number of
	  * elements.
	  *
	  * @param new_capacity The number of elements to make room for.
	  *
	  */
	void reserve(u32 new_capacity){
		if( Data::capacity() < new_capacity*sizeof(T) ){
			Data::resize(new_capacity*sizeof(T));
		}
	}

	/*! \details Removes all elements from the vector.
	  *
	  * This method sets the count() to zero. It doesn't
	  * free any memory associated with the object.
	  *
	  */
	void clear(){
		//call the destructor on each item
		while( count() ){
			pop_back();
		}
	}

	int free(){
		clear();
		return Data::free();
	}

	static int ascending(const void * a, const void * b){
		const T * object_a = (const T*)a;
		const T * object_b = (const T*)b;
		if( *object_a < *object_b ){ return -1; }
		if( *object_a > *object_b ){ return 1; }
		return 0;
	}

	static int descending(const void * a, const void * b){
		const T * object_a = (const T*)a;
		const T * object_b = (const T*)b;
		if( *object_a < *object_b ){ return 1; }
		if( *object_a > *object_b ){ return -1; }
		return 0;
	}

	typedef int (*sort_compartor_t)(const void*, const void *);

	void sort(sort_compartor_t compare_function){
		qsort(to_void(), count(), sizeof(T), compare_function);
	}

	/*! \details Inserts an element at the specified position.
	  *
	  * @param pos The position to insert the object.
	  * @param value The element to insert
	  *
	  * If \a pos is at or past the end, \a value
	  * will be push_back() is used to add the element.
	  *
	  */
	int insert(u32 pos, const T & value){
		//add space
		if( push_back(value) < 0 ){
			return -1;
		}

		if( pos >= count() ){
			//already inserted on the end
			return 0;
		} else if( add_space() == 0 ){
			//move elements from pos to end back one
			for(u32 i=count(); i > pos; i-- ){
				vector_data()[i] = vector_data()[i-1];
			}
			vector_data()[pos] = value;
			return 0;
		}
		return -1;
	}

	/*! \details Returns the number of elemens in the Vector.
	  *
	  * The count includes the number of elements added to the vector
	  * using push_back() or insert(). If the resize() method is called,
	  * it will directly set the count() and ensure there is enough
	  * memory available to hold count() items.
	  *
	  *
	  */
	u32 count() const { return m_count; }

	/*! \details Returns the number of bytes used by the Vector.
	  *
	  * This accounts only for valid objects. Reserved space is not
	  * counted. To return the total number of bytes including reserve,
	  * use capacity() * sizeof(T).
	  *
	  */
	u32 size() const { return count()*sizeof(T); }

	T * vector_data(){ return to<T>(); }
	const T * vector_data_const() const { return to<T>(); }

	Vector<T> operator + (const Vector<T> & a) const {
		return operate(a, add);
	}

	Vector<T> operator - (const Vector<T> & a) const {
		return operate(a, subtract);
	}

	Vector<T> operator * (const Vector<T> & a) const {
		return operate(a, multiply);
	}

	Vector<T> operator / (const Vector<T> & a) const {
		return operate(a, divide);
	}

	Vector<T> operator + (const T & a) const {
		return operate_single(a, add);
	}

	Vector<T> operator - (const T & a) const {
		return operate_single(a, subtract);
	}

	Vector<T> operator * (const T & a) const {
		return operate_single(a, multiply);
	}

	Vector<T> operator / (const T & a) const {
		return operate_single(a, divide);
	}

	Vector<T> operator << (u32 a) const {
		Vector<T> result;
		result.resize(count());
		result.fill(T());
		if( a < count() ){
			for(u32 i=0; i < count()-a; i++){
				result.at(i) = at(i+a);
			}
		}
		return result;
	}

	Vector<T> operator >> (u32 a) const {
		Vector<T> result;
		result.resize(count());
		result.fill(T());
		if( a < count() ){
			for(u32 i=0; i < count()-a; i++){
				result.at(i+a) = at(i);
			}
		}
		return result;
	}

protected:

	Vector<T> operate(const Vector<T> & a, T (*fn)(const T &, const T &)) const {
		Vector<T> result;
		u32 c = a.count() < count() ? a.count() : count();
		for(u32 i=0; i < c; i++){
			result.push_back(fn(at(i), a.at(i)));
		}
		return result;
	}

	Vector<T> operate_single(const T & a, T (*fn)(const T &, const T &)) const {
		Vector<T> result;
		u32 c = count();
		for(u32 i=0; i < c; i++){
			result.push_back(fn(at(i), a));
		}
		return result;
	}

	static T add(const T & a, const T & b){ return a+b; }
	static T subtract(const T & a, const T & b){ return a-b; }
	static T multiply(const T & a, const T & b){ return a*b; }
	static T divide(const T & a, const T & b){ return a/b; }

	static bool compare(const Vector<T> & a, const Vector<T> & b){
		u32 i;
		if( a.count() != b.count() ){
			return false;
		}
		for(i=0; i < a.count(); i++){
			if( a[i] != b[i] ){
				return false;
			}
		}
		return true;
	}

private:

	int add_space(){
		if( (capacity() == 0) || (count() >= capacity()-1) ){
			if( Data::resize((m_count + jump_size()) * sizeof(T)) < 0 ){
				return -1;
			}
		}
		return 0;
	}

	static u32 jump_size(){ return 16; }
	u32 m_count;

};

}

#endif // VECTOR_HPP
<commit_msg>fix vector constructor<commit_after>#ifndef VECTOR_HPP
#define VECTOR_HPP

#include <new>
#include "Data.hpp"

namespace var {

/*! \brief Vector Class
 * \details The Vector class
 * is similar to std::vector but is embedded friendly.
 *
 *
 */
template<typename T> class Vector : public Data {
public:

	/*! \details Constructs an empty object.
	  *
	  */
	Vector(){ m_count = 0; }

	/*! \details Constructs a vector with \a count uninitialized items. */
	Vector(int count){
		m_count = 0;
		resize(count);
	}

	/*! \details Returns a referece to the element
	  * at the specified position.
	  *
	  * @param pos The position in the vector to access.
	  *
	  * If \a pos is not a valid value, reference to
	  * the first eleemnt will be returned.
	  *
	  * If there are zero elements in the vector and
	  * no memory has been allocated, this method will
	  * dereference a null-pointer and cause the application
	  * to crash.
	  *
	  * If there are no elements and the vector has been
	  * allocated memory, this method will return a value
	  * that is no longer valid.
	  *
	  */
	T & at(u32 pos){ return Data::at<T>(pos); }

	/*! \details Provides a read-only reference to an element in the Vector.
	  *
	  * The same limitations apply to this method as apply to the read-write version.
	  *
	  */
	const T & at(u32 pos) const { return Data::at<T>(pos); }

	/*! \details Provides un-bounded access to the specified element (read-only).
	  *
	  * If the Vector has no data, this method may dereference a null pointer
	  * and cause the program to crash.
	  */
	const T & operator[](u32 idx) const { return vector_data_const()[idx]; }

	/*! \details Provides un-bounded access to the specified element.
	  *
	  * If the Vector has no data, this method may dereference a null pointer
	  * and cause the program to crash.
	  *
	  */
	T & operator[](u32 idx) { return vector_data()[idx]; }

	/*! \details Finds an object in the array.
	  *
	  * @param a The equivalent object to find
	  * @return The index of the object or count() it if wasn't found
	  *
	  */
	u32 find(const T & a){
		for(u32 i=0; i < count(); i++){
			if( at(i) == a ){
				return i;
			}
		}
		return count();
	}

	u32 find(const T & a, bool (*compare)(const T & a, const T & b)){
		for(u32 i=0; i < count(); i++){
			if( compare(at(i), a) ){
				return i;
			}
		}
		return count();
	}

	T * search(const T & a){
		return (T*)bsearch(&a, to_void(), count(), sizeof(T), ascending);
	}

	T * search(const T & a, int (*compare)(const void *, const void *)){
		return (T*)bsearch(&a, to_void(), count(), sizeof(T), compare);
	}

	/*! \details Returns the number of elements that are
	  * able to fit in the memory that is already allocated.
	  *
	  */
	u32 capacity() const {
		//how many elements can fit in current space
		return Data::capacity() / sizeof(T);
	}

	/*! \details Adds an element to the end of the Vector.
	  *
	  * If the element won't fit, space will be added. If space
	  * cannot be added, nothing will happen.
	  *
	  */
	int push_back(const T & value){
		if( add_space() == 0 ){
			new((void*)(vector_data() + m_count++)) T(value);
			return 0;
		}
		return -1;
	}

	/*! \details Removes the last element of the vector.
	  *
	  * This makes the last element inaccessible. It does not affect
	  * the memory allocation of the vector. Once items are popped,
	  * the memory can be freed using the method shrink_to_fit().
	  *
	  */
	void pop_back(){
		if( m_count ){
			//call the destructor
			vector_data()[m_count-1].~T();
			m_count--;
		}
	}

	/*! \details Frees unused memory that is reserved for this Vector. */
	void shrink_to_fit(){
		Data::resize(m_count*sizeof(T));
	}

	/*! \details Resizes the vector.
	  *
	  * @param count The new number of element for the vector to have
	  *
	  * This method will increase/decrease the number of elements in
	  * the vector. If elements are added, they will not be initialized.
	  *
	  * The method shrink_to_fit() will free memory that is no longer needed. It doesn't affect
	  * the count() of the object.
	  *
	  * The method reserve() will increase the memory that is available but does
	  * not affect the count() of the object().
	  *
	  */
	int resize(u32 count){
		//this needs to destruct each item that will be lost
		if( count < this->count() ){
			//size reduction if count < this->count()
			while( count < this->count() ){
				pop_back();
			}
		} else {
			while( count > this->count() ){
				push_back(T());
			}
		}
		return 0;
	}

	/*!
	  * \details Fills the vector will the specified value.
	  * \param value The value to assign to each element of the vector
	  */
	virtual void fill(const T & value){
		u32 i;
		for(i=0; i < count(); i++){
			this->at(i) = value;
		}
	}

	/*! \details Reserves enough data for the specified number of
	  * elements.
	  *
	  * @param new_capacity The number of elements to make room for.
	  *
	  */
	void reserve(u32 new_capacity){
		if( Data::capacity() < new_capacity*sizeof(T) ){
			Data::resize(new_capacity*sizeof(T));
		}
	}

	/*! \details Removes all elements from the vector.
	  *
	  * This method sets the count() to zero. It doesn't
	  * free any memory associated with the object.
	  *
	  */
	void clear(){
		//call the destructor on each item
		while( count() ){
			pop_back();
		}
	}

	int free(){
		clear();
		return Data::free();
	}

	static int ascending(const void * a, const void * b){
		const T * object_a = (const T*)a;
		const T * object_b = (const T*)b;
		if( *object_a < *object_b ){ return -1; }
		if( *object_a > *object_b ){ return 1; }
		return 0;
	}

	static int descending(const void * a, const void * b){
		const T * object_a = (const T*)a;
		const T * object_b = (const T*)b;
		if( *object_a < *object_b ){ return 1; }
		if( *object_a > *object_b ){ return -1; }
		return 0;
	}

	typedef int (*sort_compartor_t)(const void*, const void *);

	void sort(sort_compartor_t compare_function){
		qsort(to_void(), count(), sizeof(T), compare_function);
	}

	/*! \details Inserts an element at the specified position.
	  *
	  * @param pos The position to insert the object.
	  * @param value The element to insert
	  *
	  * If \a pos is at or past the end, \a value
	  * will be push_back() is used to add the element.
	  *
	  */
	int insert(u32 pos, const T & value){
		//add space
		if( push_back(value) < 0 ){
			return -1;
		}

		if( pos >= count() ){
			//already inserted on the end
			return 0;
		} else if( add_space() == 0 ){
			//move elements from pos to end back one
			for(u32 i=count(); i > pos; i-- ){
				vector_data()[i] = vector_data()[i-1];
			}
			vector_data()[pos] = value;
			return 0;
		}
		return -1;
	}

	/*! \details Returns the number of elemens in the Vector.
	  *
	  * The count includes the number of elements added to the vector
	  * using push_back() or insert(). If the resize() method is called,
	  * it will directly set the count() and ensure there is enough
	  * memory available to hold count() items.
	  *
	  *
	  */
	u32 count() const { return m_count; }

	/*! \details Returns the number of bytes used by the Vector.
	  *
	  * This accounts only for valid objects. Reserved space is not
	  * counted. To return the total number of bytes including reserve,
	  * use capacity() * sizeof(T).
	  *
	  */
	u32 size() const { return count()*sizeof(T); }

	T * vector_data(){ return to<T>(); }
	const T * vector_data_const() const { return to<T>(); }

	Vector<T> operator + (const Vector<T> & a) const {
		return operate(a, add);
	}

	Vector<T> operator - (const Vector<T> & a) const {
		return operate(a, subtract);
	}

	Vector<T> operator * (const Vector<T> & a) const {
		return operate(a, multiply);
	}

	Vector<T> operator / (const Vector<T> & a) const {
		return operate(a, divide);
	}

	Vector<T> operator + (const T & a) const {
		return operate_single(a, add);
	}

	Vector<T> operator - (const T & a) const {
		return operate_single(a, subtract);
	}

	Vector<T> operator * (const T & a) const {
		return operate_single(a, multiply);
	}

	Vector<T> operator / (const T & a) const {
		return operate_single(a, divide);
	}

	Vector<T> operator << (u32 a) const {
		Vector<T> result;
		result.resize(count());
		result.fill(T());
		if( a < count() ){
			for(u32 i=0; i < count()-a; i++){
				result.at(i) = at(i+a);
			}
		}
		return result;
	}

	Vector<T> operator >> (u32 a) const {
		Vector<T> result;
		result.resize(count());
		result.fill(T());
		if( a < count() ){
			for(u32 i=0; i < count()-a; i++){
				result.at(i+a) = at(i);
			}
		}
		return result;
	}

protected:

	Vector<T> operate(const Vector<T> & a, T (*fn)(const T &, const T &)) const {
		Vector<T> result;
		u32 c = a.count() < count() ? a.count() : count();
		for(u32 i=0; i < c; i++){
			result.push_back(fn(at(i), a.at(i)));
		}
		return result;
	}

	Vector<T> operate_single(const T & a, T (*fn)(const T &, const T &)) const {
		Vector<T> result;
		u32 c = count();
		for(u32 i=0; i < c; i++){
			result.push_back(fn(at(i), a));
		}
		return result;
	}

	static T add(const T & a, const T & b){ return a+b; }
	static T subtract(const T & a, const T & b){ return a-b; }
	static T multiply(const T & a, const T & b){ return a*b; }
	static T divide(const T & a, const T & b){ return a/b; }

	static bool compare(const Vector<T> & a, const Vector<T> & b){
		u32 i;
		if( a.count() != b.count() ){
			return false;
		}
		for(i=0; i < a.count(); i++){
			if( a[i] != b[i] ){
				return false;
			}
		}
		return true;
	}

private:

	int add_space(){
		if( (capacity() == 0) || (count() >= capacity()-1) ){
			if( Data::resize((m_count + jump_size()) * sizeof(T)) < 0 ){
				return -1;
			}
		}
		return 0;
	}

	static u32 jump_size(){ return 16; }
	u32 m_count;

};

}

#endif // VECTOR_HPP
<|endoftext|>


<commit_before><commit_msg>Add debugging output operator<< for FontMetric<commit_after><|endoftext|>