<commit_before>#include "joystickDrive.hpp"

//static SDL_Joystick *joystick;
/*
//Main now in joystickmain
int main()
{
	joystickDrive jD;

	for(;;)
	{
		//jD.printLoop();
		jD.setMotor();
		jD.readJoystick();
		if(jD.shouldQuit())
		{
			return(0);
		}
		usleep(4e4);

	}
}
*/
joystickDrive::joystickDrive()
{
	//m_motorCtr = new OSMC_driver();
	m_motorCtr = new OSMC_4wd_driver();

	quit = false;
	leftAnalogX = 0;
	leftAnalogY = 0;
	rightAnalogX = 0;
	rightAnalogY = 0;
	dPadX = 0;
	dPadY = 0;
	joystickButtons = 0;

	joystick_open();

}

joystickDrive::joystickDrive(OSMC_4wd_driver* osmc)
{
	m_motorCtr = osmc;
	quit = false;
	leftAnalogX = 0;
	leftAnalogY = 0;
	rightAnalogX = 0;
	rightAnalogY = 0;
	dPadX = 0;
	dPadY = 0;
	joystickButtons = 0;

	joystick_open();
}

joystickDrive::~joystickDrive()
{
	joystick_close();
}

//return [0,2 PI], normal math def
inline double joystickDrive::getHeading()
{
	//double theta = atan2(-1*rightAnalogY, rightAnalogX);
	double theta = atan2(-1*leftAnalogY, leftAnalogX);

	return theta;
}

inline double scaleThrottle(double t)
{
	const double slope = (double)100/(double)255;
	std::cout << "t: " << t << "\tf(t):" << (t-50)*slope + 50 << std::endl;
	return( (t-50)*slope + 50 );
}
#if 0
void joystickDrive::setMotor()
{
	readJoystick();

	double mag = abs(leftAnalogY);

	double realmag = sqrt(leftAnalogX*leftAnalogX + leftAnalogY*leftAnalogY) / (double(32768)*sqrt(2)) * 225;

	if(realmag < 50)
	{
		m_motorCtr.setMotorPWM(MC_MOTOR_FORWARD, 0, MC_MOTOR_FORWARD, 0);
		return;
	}

	double vel = mag / (double(32768)*sqrt(2)) * 110;

	double side = leftAnalogX / (double(32768)*sqrt(2)) * double(120) / double(5);

	double rvel = -1, lvel = -1;

	rvel = vel + side;
	//lvel = vel - 1.5*side + 55;
	lvel = vel - side;

	//turbo
	if((joystickButtons & 32) == 32)
	{
		rvel += 20;
		lvel += 20;
	}
	//turbo
	if((joystickButtons & 128) == 128)
	{
		rvel += 40;
		lvel += 40;
	}

	//force tight turn
	if((joystickButtons & 1) == 1)
	{
		m_motorCtr.setMotorPWM(MC_MOTOR_FORWARD, 0, MC_MOTOR_FORWARD, rvel);
		std::cout << "btn:" << joystickButtons << "\tleft at ("<< leftAnalogX << "," << leftAnalogY << ")\twould have set left: " << 0 << " right: " << vel << std::endl;
		return;
	}
	else if((joystickButtons & 4) == 4)
	{
		m_motorCtr.setMotorPWM(MC_MOTOR_FORWARD, lvel, MC_MOTOR_FORWARD, 0);
		std::cout << "btn:" << joystickButtons << "\tleft at ("<< leftAnalogX << "," << leftAnalogY << ")\twould have set left: " << vel << " right: " << 0 << std::endl;
		return;
	}
	double r = -1,l=-1;
	#if 0
	if(!qD.getEncoderVel(r,l))
	{
		std::cout << "r: " << r << "l: " << l << std::endl;
	}
	#endif
	std::cout << "btn:" << joystickButtons << "\tleft at ("<< leftAnalogX << "," << leftAnalogY << ")\twould have set left: " << lvel << " right: " << rvel << " side: " << side <<std::endl;
	m_motorCtr.setMotorPWM(MC_MOTOR_FORWARD, rvel, MC_MOTOR_FORWARD, lvel);
}
#else
void joystickDrive::setMotor()
{
	readJoystick();
	char theta = -1*(getHeading() * 128/(M_PI) + 64 + 128);

	//double rmag = sqrt(rightAnalogX*rightAnalogX + rightAnalogY*rightAnalogY);
	//double lmag = sqrt(leftAnalogX*leftAnalogX + leftAnalogY*leftAnalogY);
	double rymag = -1*rightAnalogY;
	double lymag = -1*leftAnalogY;
	double norm_rymag = rymag / double(32768);
	double norm_lymag = lymag / double(32768);

	double mag = 120;
	int rvel = norm_rymag * double(mag);
	int lvel = norm_lymag * double(mag);

	if(abs(rvel) < 50 || isnan(rvel) || isinf(rvel) || rvel > 255)//dead zone
	{
		rvel = 0;
	}
	else
	{
		if(rvel > 0)
		{
			rvel = (rvel - 50) * 2;
		}
		else
		{
			rvel = (rvel + 50) * 2;
		}
	}
	if(abs(lvel) < 50 || isnan(lvel) || isinf(lvel) || lvel > 255)//dead zone
	{
		lvel = 0;
	}
	else
	{
		if(lvel > 0)
		{
			lvel = (lvel - 50) * 2;
		}
		else
		{
			lvel = (lvel + 50) * 2;
		}
	}
	//turbo
	if((joystickButtons & 32) == 32)
	{
		rvel += (rvel >= 0) ? 30 : -30;
		lvel += (lvel >= 0) ? 30 : -30;
	}
	//turbo
	if((joystickButtons & 128) == 128)
	{
		rvel += (rvel >= 0) ? 30 : -30;
		lvel += (lvel >= 0) ? 30 : -30;
	}
	//backward
	/*if((joystickButtons & ) == )
	{
		rvel -= (rvel >= 0) ? 30 : -30;
		lvel -= (lvel >= 0) ? 30 : -30;
	}
	if ((joystickButtons & ) == )
	{
		rvel -= (rvel >= 0) ? 30 : -30;
		lvel -= (lvel >= 0) ? 30 : -30;
	}
	*/
	//force tight turn
	if((joystickButtons & 1) == 1)
	{
		lvel = 0;
	}
	else if((joystickButtons & 4) == 4)
	{
		rvel = 0;
	}

	std::cout << "btn:" << joystickButtons << "\tleft at ("<< leftAnalogX << "," << leftAnalogY << ") right at (" << rightAnalogX << "," << rightAnalogY << ")\twould have set lvel: " << lvel << " rvel: " << rvel << std::endl;

	// Find button values
	printLoop();

	//if(m_motorCtr->setMotorPWM(lvel, rvel,lvel, rvel))
	if(m_motorCtr->setMotorPWM(rvel, lvel,rvel, lvel))
	{
		std::cerr << "set failed" << std::endl;
	}
}
#endif
void joystickDrive::joystick_close(void) {
	// Send an SDL_QUIT event to the joystick event loop
	SDL_QuitEvent quitEvent = { SDL_QUIT };
	SDL_PushEvent((SDL_Event*) &quitEvent);
}

/**
 * Opens the joystick.
 *
 * @return		NULL if success;
 * 				or a message if error.
 */
const char* joystickDrive::joystick_open(void) {
	int err;

	// Initialize SDL
	if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 ) {
		return SDL_GetError();
	}

	joystick = SDL_JoystickOpen(0);
	if (!SDL_JoystickOpened(0)) {
		// TODO: would it work to return SDL_GetError() here?
		return "SDL_JoystickOpen failed";
	}

	// Call joystick_run() in new thread
	//err = pthread_create(&joystick_thread, NULL, &joystick_run, NULL);
	switch (err) {
		case EAGAIN:
			return "insufficient thread resources";
		case EINVAL:
			return "invalid thread attributes";
		default:
			break;
	}

	return NULL;	// no error
}

void joystickDrive::readJoystick() {
	int i;
	int done;
	SDL_Event event;

	/*
	// Ignore initial events during startup
	for (i=0;i<20;i++) {
		SDL_PollEvent(&event);
	}
	*/
	// Poll the joystick for events, and update globals
	done = 0;
		while ( SDL_PollEvent(&event) ) {
			switch (event.type) {
				case SDL_JOYAXISMOTION:
					switch (event.jaxis.axis) {
						case 0:
							leftAnalogX = event.jaxis.value;
							break;
						case 1:
							leftAnalogY = event.jaxis.value;
							break;
						case 2:
							rightAnalogX = event.jaxis.value;
							break;
						case 3:
							rightAnalogY = event.jaxis.value;
							break;
						case 4:
							dPadX = event.jaxis.value;
							break;
						case 5:
							dPadY = event.jaxis.value;
							break;
						default:
							break;
					}
					break;
				case SDL_JOYBUTTONDOWN:
					joystickButtons |= (1 << event.jbutton.button);
					break;
				case SDL_JOYBUTTONUP:
					joystickButtons &= ~(1 << event.jbutton.button);
					break;
				/*
				case SDL_KEYDOWN:
					if ( event.key.keysym.sym != SDLK_ESCAPE ) {//this line doesnt work
						break;
					}
					// Fall through to signal quit
				*/
				case SDL_QUIT:
					//done = 1;
					//exit(-1);
					quit = true;
					break;
				default:
					break;
			}
		}
}

bool joystickDrive::shouldQuit()
{
	return(quit);
}

bool joystickDrive::manualOverride()
{
	return check_button(RT_TRIG);
	// Checks if the manual override button is pressed
}

void joystickDrive::printLoop()
// Helper method for figuring out buttons on joystick
{
	for(;;)
	{
		readJoystick();
		std::cout << "Button value: " << std::hex << joystickButtons << "\n";
		bool t = joystickButtons << 8;
		std::cout << t << "\n";
		usleep(1e5);bool check_button(BUTTON);
	}
}

bool joystickDrive::check_button(BUTTON b)
{
	readJoystick();
	return (bool)(joystickButtons & 1<<b);
}
<commit_msg>start working on backward joystick<commit_after>#include "joystickDrive.hpp"

//static SDL_Joystick *joystick;
/*
//Main now in joystickmain
int main()
{
	joystickDrive jD;

	for(;;)
	{
		//jD.printLoop();
		jD.setMotor();
		jD.readJoystick();
		if(jD.shouldQuit())
		{
			return(0);
		}
		usleep(4e4);

	}
}
*/
joystickDrive::joystickDrive()
{
	//m_motorCtr = new OSMC_driver();
	m_motorCtr = new OSMC_4wd_driver();

	quit = false;
	leftAnalogX = 0;
	leftAnalogY = 0;
	rightAnalogX = 0;
	rightAnalogY = 0;
	dPadX = 0;
	dPadY = 0;
	joystickButtons = 0;

	joystick_open();

}

joystickDrive::joystickDrive(OSMC_4wd_driver* osmc)
{
	m_motorCtr = osmc;
	quit = false;
	leftAnalogX = 0;
	leftAnalogY = 0;
	rightAnalogX = 0;
	rightAnalogY = 0;
	dPadX = 0;
	dPadY = 0;
	joystickButtons = 0;

	joystick_open();
}

joystickDrive::~joystickDrive()
{
	joystick_close();
}

//return [0,2 PI], normal math def
inline double joystickDrive::getHeading()
{
	//double theta = atan2(-1*rightAnalogY, rightAnalogX);
	double theta = atan2(-1*leftAnalogY, leftAnalogX);

	return theta;
}

inline double scaleThrottle(double t)
{
	const double slope = (double)100/(double)255;
	std::cout << "t: " << t << "\tf(t):" << (t-50)*slope + 50 << std::endl;
	return( (t-50)*slope + 50 );
}
#if 0
void joystickDrive::setMotor()
{
	readJoystick();

	double mag = abs(leftAnalogY);

	double realmag = sqrt(leftAnalogX*leftAnalogX + leftAnalogY*leftAnalogY) / (double(32768)*sqrt(2)) * 225;

	if(realmag < 50)
	{
		m_motorCtr.setMotorPWM(MC_MOTOR_FORWARD, 0, MC_MOTOR_FORWARD, 0);
		return;
	}

	double vel = mag / (double(32768)*sqrt(2)) * 110;

	double side = leftAnalogX / (double(32768)*sqrt(2)) * double(120) / double(5);

	double rvel = -1, lvel = -1;

	rvel = vel + side;
	//lvel = vel - 1.5*side + 55;
	lvel = vel - side;

	//turbo
	if((joystickButtons & 32) == 32)
	{
		rvel += 20;
		lvel += 20;
	}
	//turbo
	if((joystickButtons & 128) == 128)
	{
		rvel += 40;
		lvel += 40;
	}

	//force tight turn
	if((joystickButtons & 1) == 1)
	{
		m_motorCtr.setMotorPWM(MC_MOTOR_FORWARD, 0, MC_MOTOR_FORWARD, rvel);
		std::cout << "btn:" << joystickButtons << "\tleft at ("<< leftAnalogX << "," << leftAnalogY << ")\twould have set left: " << 0 << " right: " << vel << std::endl;
		return;
	}
	else if((joystickButtons & 4) == 4)
	{
		m_motorCtr.setMotorPWM(MC_MOTOR_FORWARD, lvel, MC_MOTOR_FORWARD, 0);
		std::cout << "btn:" << joystickButtons << "\tleft at ("<< leftAnalogX << "," << leftAnalogY << ")\twould have set left: " << vel << " right: " << 0 << std::endl;
		return;
	}
	double r = -1,l=-1;
	#if 0
	if(!qD.getEncoderVel(r,l))
	{
		std::cout << "r: " << r << "l: " << l << std::endl;
	}
	#endif
	std::cout << "btn:" << joystickButtons << "\tleft at ("<< leftAnalogX << "," << leftAnalogY << ")\twould have set left: " << lvel << " right: " << rvel << " side: " << side <<std::endl;
	m_motorCtr.setMotorPWM(MC_MOTOR_FORWARD, rvel, MC_MOTOR_FORWARD, lvel);
}
#else
void joystickDrive::setMotor()
{
	readJoystick();
	char theta = -1*(getHeading() * 128/(M_PI) + 64 + 128);

	//double rmag = sqrt(rightAnalogX*rightAnalogX + rightAnalogY*rightAnalogY);
	//double lmag = sqrt(leftAnalogX*leftAnalogX + leftAnalogY*leftAnalogY);
	double rymag = -1*rightAnalogY;
	double lymag = -1*leftAnalogY;
	double norm_rymag = rymag / double(32768);
	double norm_lymag = lymag / double(32768);

	double mag = 120;
	int rvel = norm_rymag * double(mag);
	int lvel = norm_lymag * double(mag);

	if(abs(rvel) < 50 || isnan(rvel) || isinf(rvel) || rvel > 255)//dead zone
	{
		rvel = 0;
	}
	else
	{
		if(rvel > 0)
		{
			rvel = (rvel - 50) * 2;
		}
		else
		{
			rvel = (rvel + 50) * 2;
		}
	}
	if(abs(lvel) < 50 || isnan(lvel) || isinf(lvel) || lvel > 255)//dead zone
	{
		lvel = 0;
	}
	else
	{
		if(lvel > 0)
		{
			lvel = (lvel - 50) * 2;
		}
		else
		{
			lvel = (lvel + 50) * 2;
		}
	}
	//turbo
	if((joystickButtons & 32) == 32)
	{
		rvel += (rvel >= 0) ? 30 : -30;
		lvel += (lvel >= 0) ? 30 : -30;
	}
	//turbo
	if((joystickButtons & 128) == 128)
	{
		rvel += (rvel >= 0) ? 30 : -30;
		lvel += (lvel >= 0) ? 30 : -30;
	}
	/*//backward
	if((joystickButtons & 10) == 10)
	{
		rvel -= (rvel >= 0) ? 30 : -30;
		lvel -= (lvel >= 0) ? 30 : -30;
	}
	if ((joystickButtons & 40) == 40)
	{
		rvel -= (rvel >= 0) ? 30 : -30;
		lvel -= (lvel >= 0) ? 30 : -30;
	}*/
	//force tight turn
	if((joystickButtons & 1) == 1)
	{
		lvel = 0;
	}
	else if((joystickButtons & 4) == 4)
	{
		rvel = 0;
	}

	std::cout << /*"btn:" << joystickButtons << */"\tleft at ("<< leftAnalogX << "," << leftAnalogY << ") right at (" << rightAnalogX << "," << rightAnalogY << ")\twould have set lvel: " << lvel << " rvel: " << rvel << std::endl;

	// Find button values
	//printLoop();

	//if(m_motorCtr->setMotorPWM(lvel, rvel,lvel, rvel))
	if(m_motorCtr->setMotorPWM(rvel, lvel,rvel, lvel))
	{
		std::cerr << "set failed" << std::endl;
	}
}
#endif
void joystickDrive::joystick_close(void) {
	// Send an SDL_QUIT event to the joystick event loop
	SDL_QuitEvent quitEvent = { SDL_QUIT };
	SDL_PushEvent((SDL_Event*) &quitEvent);
}

/**
 * Opens the joystick.
 *
 * @return		NULL if success;
 * 				or a message if error.
 */
const char* joystickDrive::joystick_open(void) {
	int err;

	// Initialize SDL
	if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 ) {
		return SDL_GetError();
	}

	joystick = SDL_JoystickOpen(0);
	if (!SDL_JoystickOpened(0)) {
		// TODO: would it work to return SDL_GetError() here?
		return "SDL_JoystickOpen failed";
	}

	// Call joystick_run() in new thread
	//err = pthread_create(&joystick_thread, NULL, &joystick_run, NULL);
	switch (err) {
		case EAGAIN:
			return "insufficient thread resources";
		case EINVAL:
			return "invalid thread attributes";
		default:
			break;
	}

	return NULL;	// no error
}

void joystickDrive::readJoystick() {
	int i;
	int done;
	SDL_Event event;

	/*
	// Ignore initial events during startup
	for (i=0;i<20;i++) {
		SDL_PollEvent(&event);
	}
	*/
	// Poll the joystick for events, and update globals
	done = 0;
		while ( SDL_PollEvent(&event) ) {
			switch (event.type) {
				case SDL_JOYAXISMOTION:
					switch (event.jaxis.axis) {
						case 0:
							leftAnalogX = event.jaxis.value;
							break;
						case 1:
							leftAnalogY = event.jaxis.value;
							break;
						case 2:
							rightAnalogX = event.jaxis.value;
							break;
						case 3:
							rightAnalogY = event.jaxis.value;
							break;
						case 4:
							dPadX = event.jaxis.value;
							break;
						case 5:
							dPadY = event.jaxis.value;
							break;
						default:
							break;
					}
					break;
				case SDL_JOYBUTTONDOWN:
					joystickButtons |= (1 << event.jbutton.button);
					break;
				case SDL_JOYBUTTONUP:
					joystickButtons &= ~(1 << event.jbutton.button);
					break;
				/*
				case SDL_KEYDOWN:
					if ( event.key.keysym.sym != SDLK_ESCAPE ) {//this line doesnt work
						break;
					}
					// Fall through to signal quit
				*/
				case SDL_QUIT:
					//done = 1;
					//exit(-1);
					quit = true;
					break;
				default:
					break;
			}
		}
}

bool joystickDrive::shouldQuit()
{
	return(quit);
}

bool joystickDrive::manualOverride()
{
	return check_button(RT_TRIG);
	// Checks if the manual override button is pressed
}

void joystickDrive::printLoop()
// Helper method for figuring out buttons on joystick
{
	for(;;)
	{
		readJoystick();
		std::cout << "Button value: " << std::hex << joystickButtons << "\n";
		bool t = joystickButtons << 8;
		std::cout << t << "\n";
		usleep(1e5);bool check_button(BUTTON);
	}
}

bool joystickDrive::check_button(BUTTON b)
{
	readJoystick();
	return (bool)(joystickButtons & 1<<b);
}
<|endoftext|>


<commit_before>
#include <stdexcept>

#include "modules/Network/NetworkManager.hpp"
#include "modules/FileReader/FileReaderManager.hpp"
#include "modules/ModError/ModErrorManager.hpp"
#include "modules/DirListing/DirListingManager.hpp"
#include "utils/macros.hpp"
#include "utils/Path.hpp"

#include "ModuleManagerFactory.hpp"

using namespace ZHTTPD;

ModuleManagerFactory::ModuleManagerFactory()
{
    this->_builders["mod_network"] = &ModuleManagerFactory::_createNetworkModuleManager;
    this->_available_modules[ZHTTPD::API::CATEGORY::INPUTOUTPUT].push_back("mod_network");
    this->_builders["mod_filereader"] = &ModuleManagerFactory::_createFileReaderModuleManager;
    this->_available_modules[ZHTTPD::API::CATEGORY::PROCESSING].push_back("mod_filereader");
    this->_builders["mod_error"] = &ModuleManagerFactory::_createModErrorModuleManager;
    this->_available_modules[ZHTTPD::API::CATEGORY::PROCESSING].push_back("mod_error");
    this->_builders["mod_dirlisting"] = &ModuleManagerFactory::_createDirListingModuleManager;
    this->_available_modules[ZHTTPD::API::CATEGORY::PROCESSING].push_back("mod_dirlisting");
}

ModuleManagerFactory::~ModuleManagerFactory()
{
    std::map<std::string, Library*>::iterator it = this->_libraries.begin(),
                                              end = this->_libraries.end();
    for (; it != end; ++it)
    {
        ZHTTPD_DELETE(it->second);
    }
}

void ModuleManagerFactory::findModules(std::string const& modules_directory)
{
    assert(modules_directory.size() > 0 && "modules_directory is not a valid path");
    Path dir(modules_directory);
    if (!dir.exists())
        throw std::runtime_error("The path '" + modules_directory +"' does not exist");
    if (!dir.isDirectory())
        throw std::runtime_error("The path '"+ modules_directory +"'is not a valid directory");
    std::list<std::string> files = dir.getDirectoryContent();
    for (std::list<std::string>::iterator it = files.begin(), end = files.end(); it != end; ++it)
    {
        if (this->_isDynamicLibrary(*it))
        {
            Library* lib = 0;
            try
            {
                lib = new Library(dir + *it);
                lib_handler_t getInstance = lib->resolve<lib_handler_t>("getInstance");
                ZHTTPD::API::IModuleManager* manager = getInstance();
                std::string const& name = manager->getName();
                // TODO rendre possible de remplacer les modules par défaut
                // comme mod_network, mod_error, etc...
                if (this->_builders.find(name) != this->_builders.end())
                {
                    throw std::runtime_error("Two modules with the name '" +
                                             name + "' have been found");
                }
                this->_libraries[name] = lib;
                this->_builders[name] = &ModuleManagerFactory::_createFromLibrary;
                this->_available_modules[manager->getCategory()].push_back(name);
                //ZHTTPD_DELETE(manager);
                delete manager;
            }
            catch (std::exception& err)
            {
                LOG_ERROR("Cannot load '" + std::string(dir + *it) + "': " + err.what());
                ZHTTPD_DELETE(lib);
            }
        }
    }
}

API::IModuleManager* ModuleManagerFactory::getModuleManager(std::string const& name) const
{
    std::map<std::string, creator_t>::const_iterator it = this->_builders.find(name);
    if (it != this->_builders.end())
    {
        return (this->*(it->second))(name);
    }
    LOG_WARN("Module '" + name + "' is not in the factory");
    return 0;
}

ModuleManagerFactory::available_modules_t const& ModuleManagerFactory::getAvailableModules() const
{
    return this->_available_modules;
}

API::IModuleManager* ModuleManagerFactory::_createNetworkModuleManager(std::string const&) const
{
    return new MOD::NetworkManager();
}

API::IModuleManager* ModuleManagerFactory::_createFileReaderModuleManager(std::string const&) const
{
    return new MOD::FileReaderManager();
}

API::IModuleManager* ModuleManagerFactory::_createModErrorModuleManager(std::string const&) const
{
    return new MOD::ModErrorManager();
}

API::IModuleManager* ModuleManagerFactory::_createDirListingModuleManager(std::string const&) const
{
    return new MOD::DirListingManager();
}

API::IModuleManager* ModuleManagerFactory::_createFromLibrary(std::string const& name) const
{
    std::map<std::string, Library*>::const_iterator it = this->_libraries.find(name);
    assert(it != this->_libraries.end());
    lib_handler_t getInstance = it->second->resolve<lib_handler_t>("getInstance");
    return getInstance();
}

#ifdef _WIN32
# define ZHTTPD_LIB_EXTENSION "dll"
#else
# define ZHTTPD_LIB_EXTENSION "so"
#endif

bool ModuleManagerFactory::_isDynamicLibrary(std::string const& filename) const
{
    std::size_t i_dot = filename.find_last_of(".");
    if (i_dot != std::string::npos && i_dot < filename.size() - 1)
        return (filename.substr(i_dot + 1) == ZHTTPD_LIB_EXTENSION);
    return false;
}

#undef ZHTTPD_LIB_EXTENSION

<commit_msg>Add security when findModules fails<commit_after>
#include <stdexcept>

#include "modules/Network/NetworkManager.hpp"
#include "modules/FileReader/FileReaderManager.hpp"
#include "modules/ModError/ModErrorManager.hpp"
#include "modules/DirListing/DirListingManager.hpp"
#include "utils/macros.hpp"
#include "utils/Path.hpp"

#include "ModuleManagerFactory.hpp"

using namespace ZHTTPD;

ModuleManagerFactory::ModuleManagerFactory()
{
    this->_builders["mod_network"] = &ModuleManagerFactory::_createNetworkModuleManager;
    this->_available_modules[ZHTTPD::API::CATEGORY::INPUTOUTPUT].push_back("mod_network");
    this->_builders["mod_filereader"] = &ModuleManagerFactory::_createFileReaderModuleManager;
    this->_available_modules[ZHTTPD::API::CATEGORY::PROCESSING].push_back("mod_filereader");
    this->_builders["mod_error"] = &ModuleManagerFactory::_createModErrorModuleManager;
    this->_available_modules[ZHTTPD::API::CATEGORY::PROCESSING].push_back("mod_error");
    this->_builders["mod_dirlisting"] = &ModuleManagerFactory::_createDirListingModuleManager;
    this->_available_modules[ZHTTPD::API::CATEGORY::PROCESSING].push_back("mod_dirlisting");
}

ModuleManagerFactory::~ModuleManagerFactory()
{
    std::map<std::string, Library*>::iterator it = this->_libraries.begin(),
                                              end = this->_libraries.end();
    for (; it != end; ++it)
    {
        ZHTTPD_DELETE(it->second);
    }
}

void ModuleManagerFactory::findModules(std::string const& modules_directory)
{
    assert(modules_directory.size() > 0 && "modules_directory is not a valid path");
    Path dir(modules_directory);
    if (!dir.exists())
        throw std::runtime_error("The path '" + modules_directory +"' does not exist");
    if (!dir.isDirectory())
        throw std::runtime_error("The path '"+ modules_directory +"'is not a valid directory");
    std::list<std::string> files = dir.getDirectoryContent();
    for (std::list<std::string>::iterator it = files.begin(), end = files.end(); it != end; ++it)
    {
        if (this->_isDynamicLibrary(*it))
        {
            Library* lib = 0;
            ZHTTPD::API::IModuleManager* manager = 0;
            try
            {
                lib = new Library(dir + *it);
                lib_handler_t getInstance = lib->resolve<lib_handler_t>("getInstance");
                manager = getInstance();
                std::string const& name = manager->getName();
                // TODO rendre possible de remplacer les modules par défaut
                // comme mod_network, mod_error, etc...
                if (this->_builders.find(name) != this->_builders.end())
                {
                    throw std::runtime_error("Two modules with the name '" +
                                             name + "' have been found");
                }
                this->_libraries[name] = lib;
                this->_builders[name] = &ModuleManagerFactory::_createFromLibrary;
                this->_available_modules[manager->getCategory()].push_back(name);
                ZHTTPD_DELETE(manager);
            }
            catch (std::exception& err)
            {
                LOG_ERROR("Cannot load '" + std::string(dir + *it) + "': " + err.what());
                ZHTTPD_DELETE(lib);
                ZHTTPD_DELETE(manager);
            }
        }
    }
}

API::IModuleManager* ModuleManagerFactory::getModuleManager(std::string const& name) const
{
    std::map<std::string, creator_t>::const_iterator it = this->_builders.find(name);
    if (it != this->_builders.end())
    {
        return (this->*(it->second))(name);
    }
    LOG_WARN("Module '" + name + "' is not in the factory");
    return 0;
}

ModuleManagerFactory::available_modules_t const& ModuleManagerFactory::getAvailableModules() const
{
    return this->_available_modules;
}

API::IModuleManager* ModuleManagerFactory::_createNetworkModuleManager(std::string const&) const
{
    return new MOD::NetworkManager();
}

API::IModuleManager* ModuleManagerFactory::_createFileReaderModuleManager(std::string const&) const
{
    return new MOD::FileReaderManager();
}

API::IModuleManager* ModuleManagerFactory::_createModErrorModuleManager(std::string const&) const
{
    return new MOD::ModErrorManager();
}

API::IModuleManager* ModuleManagerFactory::_createDirListingModuleManager(std::string const&) const
{
    return new MOD::DirListingManager();
}

API::IModuleManager* ModuleManagerFactory::_createFromLibrary(std::string const& name) const
{
    std::map<std::string, Library*>::const_iterator it = this->_libraries.find(name);
    assert(it != this->_libraries.end());
    lib_handler_t getInstance = it->second->resolve<lib_handler_t>("getInstance");
    return getInstance();
}

#ifdef _WIN32
# define ZHTTPD_LIB_EXTENSION "dll"
#else
# define ZHTTPD_LIB_EXTENSION "so"
#endif

bool ModuleManagerFactory::_isDynamicLibrary(std::string const& filename) const
{
    std::size_t i_dot = filename.find_last_of(".");
    if (i_dot != std::string::npos && i_dot < filename.size() - 1)
        return (filename.substr(i_dot + 1) == ZHTTPD_LIB_EXTENSION);
    return false;
}

#undef ZHTTPD_LIB_EXTENSION

<|endoftext|>


<commit_before>#include "APSEthernet.h"

APSEthernet::APSEthernet() : socket_(ios_) {
    //Setup the socket to the APS_PROTO port and enable broadcasting for enumerating
    std::error_code ec;
    socket_.open(udp::v4(), ec);
    if (ec) {FILE_LOG(logERROR) << "Failed to open socket.";}
    socket_.bind(udp::endpoint(asio::ip::address::from_string("192.168.5.1"), APS_PROTO), ec);
    if (ec) {FILE_LOG(logERROR) << "Failed to bind to socket.";}

    socket_.set_option(asio::socket_base::broadcast(true));

    //io_service will return immediately so post receive task before .run()
    setup_receive();

    //Setup the asio service to run on a background thread
    receiveThread_ = std::thread([&](){ ios_.run(); });

};

APSEthernet::~APSEthernet() {
    //Stop the receive thread
    ios_.stop();
    receiveThread_.join();
}

void APSEthernet::setup_receive(){
    socket_.async_receive_from(
        asio::buffer(receivedData_, 2048), senderEndpoint_,
        [this](std::error_code ec, std::size_t bytesReceived)
        {
            //If there is anything to look at hand it off to the sorter
            if (!ec && bytesReceived > 0)
            {
                vector<uint8_t> packetData(receivedData_, receivedData_ + bytesReceived);
                sort_packet(packetData, senderEndpoint_);
            }

            //Start the receiver again
            setup_receive();
    });
}

void APSEthernet::sort_packet(const vector<uint8_t> & packetData, const udp::endpoint & sender){
    //If we have the endpoint address then add it to the queue
    string senderIP = sender.address().to_string();
    if(msgQueues_.find(senderIP) == msgQueues_.end()){
        //If it isn't in our list of APSs then perhaps we are seeing an enumerate status response
        //If so add the device info to the set
        if (packetData.size() == 84) {
            devInfo_[senderIP].endpoint = sender;
            //Turn the byte array into a packet to extract the MAC address
            //Not strictly necessary as we could just use the broadcast MAC address
            APSEthernetPacket packet = APSEthernetPacket(packetData);
            devInfo_[senderIP].macAddr = packet.header.src;
            FILE_LOG(logDEBUG1) << "Added device with IP " << senderIP << " and MAC addresss " << devInfo_[senderIP].macAddr.to_string();
        }
    }
    else{
        //Turn the byte array into an APSEthernetPacket
        APSEthernetPacket packet = APSEthernetPacket(packetData);
        //Grab a lock and push the packet into the message queue
        mLock_.lock();
        msgQueues_[senderIP].emplace(packet);
        mLock_.unlock();
    }
}

/* PUBLIC methods */

APSEthernet::EthernetError APSEthernet::init(string nic) {
    /*
    --Nothing doing for now
    TODO: Should eventually bind to particular NIC here?
    */
    reset_maps();

    return SUCCESS;
}

set<string> APSEthernet::enumerate() {
	/*
	 * Look for all APS units that respond to the broadcast packet
	 */

	FILE_LOG(logDEBUG1) << "APSEthernet::enumerate";

    reset_maps();

    //Put together the broadcast status request
    APSEthernetPacket broadcastPacket = APSEthernetPacket::create_broadcast_packet();
    udp::endpoint broadCastEndPoint(asio::ip::address_v4::broadcast(), APS_PROTO);
    socket_.send_to(asio::buffer(broadcastPacket.serialize()), broadCastEndPoint);

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

    set<string> deviceSerials;
    for (auto kv : devInfo_) {
        FILE_LOG(logINFO) << "Found device: " << kv.first;
        deviceSerials.insert(kv.first);
    }
    return deviceSerials;
}

void APSEthernet::reset_maps() {
    devInfo_.clear();
    msgQueues_.clear();
}

APSEthernet::EthernetError APSEthernet::connect(string serial) {

    mLock_.lock();
	msgQueues_[serial] = queue<APSEthernetPacket>();
    mLock_.unlock();
	return SUCCESS;
}

APSEthernet::EthernetError APSEthernet::disconnect(string serial) {
    mLock_.lock();
	msgQueues_.erase(serial);
    mLock_.unlock();
	return SUCCESS;
}

APSEthernet::EthernetError APSEthernet::send(string serial, APSEthernetPacket msg){
    return send(serial, vector<APSEthernetPacket>(1, msg));
}

APSEthernet::EthernetError APSEthernet::send(string serial, vector<APSEthernetPacket> msg, unsigned ackEvery /* see header for default */) {
    //Fill out the destination  MAC address
    FILE_LOG(logDEBUG3) << "Sending " << msg.size() << " packets to " << serial;
    unsigned ackct, retryct = 0;
    auto iter = packet.begin();

    while (iter != msg.end()){
        auto packet = *iter;;

        // insert the target MAC address - not really necessary anymore because UDP does filtering
        packet.header.dest = devInfo_[serial].macAddr;
        packet.header.seqNum = ackct;

        ackct++;
        //Apply acknowledge flag if necessary
        bool ackFlag = (ackct % ackEvery == 0) || (std::next(iter) == msg.end());
        if( ackFlag ){
            packet.header.command.ack = 1;
        }
        FILE_LOG(logDEBUG4) << "Packet command: " << print_APSCommand(packet.header.command);
        socket_.send_to(asio::buffer(packet.serialize()), devInfo_[serial].endpoint);
        iter++;

        //Wait for acknowledge if we need to
        //TODO: how to check response mode/stat for success?
        if (ackFlag){
            try{
                auto response = receive(serial)[0];
            }
            catch (std::exception& e) {
               if (retryct++ < 3) {
                    FILE_LOG(logDEBUG) << "No acknowledge received, retrying ...";
                    //Reset the acknowledge count
                    ackct = 0;
                    //Go back to the last acknowledged packet
                    iter -= (ackct % ackEvery == 0) ? ackEvery : ackct % ackEvery ;
                }
                else {
                    return TIMEOUT;
                }
            }
        }
    }

    return SUCCESS;
}

vector<APSEthernetPacket> APSEthernet::receive(string serial, size_t numPackets, size_t timeoutMS) {
    //Read the packets coming back in up to the timeout
    //Defaults: receive(string serial, size_t numPackets = 1, size_t timeoutMS = 1000);
    std::chrono::time_point<std::chrono::steady_clock> start, end;

    start = std::chrono::steady_clock::now();
    size_t elapsedTime = 0;

    vector<APSEthernetPacket> outVec;

    while (elapsedTime < timeoutMS){
        if (!msgQueues_[serial].empty()){
            mLock_.lock();
            outVec.push_back(msgQueues_[serial].front());
            msgQueues_[serial].pop();
            mLock_.unlock();
            FILE_LOG(logDEBUG4) << "Received packet command: " << print_APSCommand(outVec.back().header.command);
            if (outVec.size() == numPackets){
                FILE_LOG(logDEBUG3) << "Received " << numPackets << " packets from " << serial;
                return outVec;
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        end = std::chrono::steady_clock::now();
        elapsedTime =  std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
    }

    throw runtime_error("Timed out on receive");
}

<commit_msg>Should actually have tried to compile previous commit.<commit_after>#include "APSEthernet.h"

APSEthernet::APSEthernet() : socket_(ios_) {
    //Setup the socket to the APS_PROTO port and enable broadcasting for enumerating
    std::error_code ec;
    socket_.open(udp::v4(), ec);
    if (ec) {FILE_LOG(logERROR) << "Failed to open socket.";}
    socket_.bind(udp::endpoint(asio::ip::address::from_string("192.168.5.1"), APS_PROTO), ec);
    if (ec) {FILE_LOG(logERROR) << "Failed to bind to socket.";}

    socket_.set_option(asio::socket_base::broadcast(true));

    //io_service will return immediately so post receive task before .run()
    setup_receive();

    //Setup the asio service to run on a background thread
    receiveThread_ = std::thread([&](){ ios_.run(); });

};

APSEthernet::~APSEthernet() {
    //Stop the receive thread
    ios_.stop();
    receiveThread_.join();
}

void APSEthernet::setup_receive(){
    socket_.async_receive_from(
        asio::buffer(receivedData_, 2048), senderEndpoint_,
        [this](std::error_code ec, std::size_t bytesReceived)
        {
            //If there is anything to look at hand it off to the sorter
            if (!ec && bytesReceived > 0)
            {
                vector<uint8_t> packetData(receivedData_, receivedData_ + bytesReceived);
                sort_packet(packetData, senderEndpoint_);
            }

            //Start the receiver again
            setup_receive();
    });
}

void APSEthernet::sort_packet(const vector<uint8_t> & packetData, const udp::endpoint & sender){
    //If we have the endpoint address then add it to the queue
    string senderIP = sender.address().to_string();
    if(msgQueues_.find(senderIP) == msgQueues_.end()){
        //If it isn't in our list of APSs then perhaps we are seeing an enumerate status response
        //If so add the device info to the set
        if (packetData.size() == 84) {
            devInfo_[senderIP].endpoint = sender;
            //Turn the byte array into a packet to extract the MAC address
            //Not strictly necessary as we could just use the broadcast MAC address
            APSEthernetPacket packet = APSEthernetPacket(packetData);
            devInfo_[senderIP].macAddr = packet.header.src;
            FILE_LOG(logDEBUG1) << "Added device with IP " << senderIP << " and MAC addresss " << devInfo_[senderIP].macAddr.to_string();
        }
    }
    else{
        //Turn the byte array into an APSEthernetPacket
        APSEthernetPacket packet = APSEthernetPacket(packetData);
        //Grab a lock and push the packet into the message queue
        mLock_.lock();
        msgQueues_[senderIP].emplace(packet);
        mLock_.unlock();
    }
}

/* PUBLIC methods */

APSEthernet::EthernetError APSEthernet::init(string nic) {
    /*
    --Nothing doing for now
    TODO: Should eventually bind to particular NIC here?
    */
    reset_maps();

    return SUCCESS;
}

set<string> APSEthernet::enumerate() {
	/*
	 * Look for all APS units that respond to the broadcast packet
	 */

	FILE_LOG(logDEBUG1) << "APSEthernet::enumerate";

    reset_maps();

    //Put together the broadcast status request
    APSEthernetPacket broadcastPacket = APSEthernetPacket::create_broadcast_packet();
    udp::endpoint broadCastEndPoint(asio::ip::address_v4::broadcast(), APS_PROTO);
    socket_.send_to(asio::buffer(broadcastPacket.serialize()), broadCastEndPoint);

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

    set<string> deviceSerials;
    for (auto kv : devInfo_) {
        FILE_LOG(logINFO) << "Found device: " << kv.first;
        deviceSerials.insert(kv.first);
    }
    return deviceSerials;
}

void APSEthernet::reset_maps() {
    devInfo_.clear();
    msgQueues_.clear();
}

APSEthernet::EthernetError APSEthernet::connect(string serial) {

    mLock_.lock();
	msgQueues_[serial] = queue<APSEthernetPacket>();
    mLock_.unlock();
	return SUCCESS;
}

APSEthernet::EthernetError APSEthernet::disconnect(string serial) {
    mLock_.lock();
	msgQueues_.erase(serial);
    mLock_.unlock();
	return SUCCESS;
}

APSEthernet::EthernetError APSEthernet::send(string serial, APSEthernetPacket msg){
    return send(serial, vector<APSEthernetPacket>(1, msg));
}

APSEthernet::EthernetError APSEthernet::send(string serial, vector<APSEthernetPacket> msg, unsigned ackEvery /* see header for default */) {
    //Fill out the destination  MAC address
    FILE_LOG(logDEBUG3) << "Sending " << msg.size() << " packets to " << serial;
    unsigned ackct, retryct = 0;
    auto iter = msg.begin();

    while (iter != msg.end()){
        auto packet = *iter;;

        // insert the target MAC address - not really necessary anymore because UDP does filtering
        packet.header.dest = devInfo_[serial].macAddr;
        packet.header.seqNum = ackct;

        ackct++;
        //Apply acknowledge flag if necessary
        bool ackFlag = (ackct % ackEvery == 0) || (std::next(iter) == msg.end());
        if( ackFlag ){
            packet.header.command.ack = 1;
        }
        FILE_LOG(logDEBUG4) << "Packet command: " << print_APSCommand(packet.header.command);
        socket_.send_to(asio::buffer(packet.serialize()), devInfo_[serial].endpoint);
        iter++;

        //Wait for acknowledge if we need to
        //TODO: how to check response mode/stat for success?
        if (ackFlag){
            try{
                auto response = receive(serial)[0];
            }
            catch (std::exception& e) {
               if (retryct++ < 3) {
                    FILE_LOG(logDEBUG) << "No acknowledge received, retrying ...";
                    //Reset the acknowledge count
                    ackct = 0;
                    //Go back to the last acknowledged packet
                    iter -= (ackct % ackEvery == 0) ? ackEvery : ackct % ackEvery ;
                }
                else {
                    return TIMEOUT;
                }
            }
        }
    }

    return SUCCESS;
}

vector<APSEthernetPacket> APSEthernet::receive(string serial, size_t numPackets, size_t timeoutMS) {
    //Read the packets coming back in up to the timeout
    //Defaults: receive(string serial, size_t numPackets = 1, size_t timeoutMS = 1000);
    std::chrono::time_point<std::chrono::steady_clock> start, end;

    start = std::chrono::steady_clock::now();
    size_t elapsedTime = 0;

    vector<APSEthernetPacket> outVec;

    while (elapsedTime < timeoutMS){
        if (!msgQueues_[serial].empty()){
            mLock_.lock();
            outVec.push_back(msgQueues_[serial].front());
            msgQueues_[serial].pop();
            mLock_.unlock();
            FILE_LOG(logDEBUG4) << "Received packet command: " << print_APSCommand(outVec.back().header.command);
            if (outVec.size() == numPackets){
                FILE_LOG(logDEBUG3) << "Received " << numPackets << " packets from " << serial;
                return outVec;
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        end = std::chrono::steady_clock::now();
        elapsedTime =  std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
    }

    throw runtime_error("Timed out on receive");
}

<|endoftext|>


<commit_before>#include "CppUTest/TestHarness.h"
#include "CppUTestExt/MockSupport.h"

#include "Environment.h"
#include "MockSensor.h"

static const char* dummy_name_01 = "dummy_01";
static const char* dummy_name_02 = "dummy_02";

TEST_GROUP(Environment)
{
    Environment* env;
    void setup()
    {
        env = new Environment();
    }
    void teardown()
    {
        mock().clear();
        delete env;
    }
};

TEST(Environment, AddSensor)
{
    MockSensor* sensor = new MockSensor(dummy_name_01);
    env->addSensor(dummy_name_01, sensor);
    LONGS_EQUAL(1, env->getNumSensor());
}

TEST(Environment, AddMultipleSensor)
{
    MockSensor* sensor_1 = new MockSensor(dummy_name_01);
    MockSensor* sensor_2 = new MockSensor(dummy_name_02);
    env->addSensor(dummy_name_01, sensor_1);
    env->addSensor(dummy_name_02, sensor_2);

    LONGS_EQUAL(2, env->getNumSensor());

    POINTERS_EQUAL(sensor_1, env->getSensorByName(dummy_name_01));
    POINTERS_EQUAL(sensor_2, env->getSensorByName(dummy_name_02));
}

TEST(Environment, SingleSensorControl)
{
    MockSensor* sensor = new MockSensor(dummy_name_01);
    env->addSensor(dummy_name_01, sensor);

    mock().expectOneCall("Sensor#init()").onObject(sensor);
    env->init();
    mock().expectOneCall("Sensor#start()").onObject(sensor);
    env->start();
    mock().expectOneCall("Sensor#stop()").onObject(sensor);
    env->stop();
    mock().checkExpectations();
}
<commit_msg>refactor Environment Test<commit_after>#include "CppUTest/TestHarness.h"
#include "CppUTestExt/MockSupport.h"

#include "Environment.h"
#include "MockSensor.h"

static const char* dummy_name_01 = "dummy_01";
static const char* dummy_name_02 = "dummy_02";

typedef std::vector<MockSensor *> MockSensorList;

TEST_GROUP(Environment)
{
    Environment* env;
    void setup()
    {
        env = new Environment();
    }
    void teardown()
    {
        mock().clear();
        delete env;
    }

    int createSensors(std::string names[], unsigned int size, MockSensorList* sensors)
    {
        if(names == NULL || size < 1)
            return -1;

        if(sensors == NULL)
            return -1;

        sensors->clear();
        for(unsigned int i = 0; i < size; i++)
            sensors->push_back( new MockSensor(names[i]) );
        return 0;
    }

    void addSensorsToEnv(MockSensorList* sensors)
    {
        for(unsigned int i = 0; i < sensors->size(); i++)
            env->addSensor(sensors->at(i)->getName(), sensors->at(i));
    }

    void checkSensorsInEnv(std::string names[], MockSensorList* sensors)
    {
        LONGS_EQUAL(sensors->size(), env->getNumSensor());

        for(unsigned int i = 0; i < sensors->size(); i++)
            POINTERS_EQUAL(sensors->at(i), env->getSensorByName(names[i]));
    }
};

TEST(Environment, AddSensor)
{
    MockSensor* sensor = new MockSensor(dummy_name_01);
    env->addSensor(dummy_name_01, sensor);
    LONGS_EQUAL(1, env->getNumSensor());
}

TEST(Environment, AddMultipleSensor)
{
    MockSensorList sensors;
    std::string names[] = {dummy_name_01, dummy_name_02};

    createSensors(names, 2, &sensors);

    addSensorsToEnv(&sensors);

    checkSensorsInEnv(names, &sensors);
}

TEST(Environment, SingleSensorControl)
{
    MockSensor* sensor = new MockSensor(dummy_name_01);
    env->addSensor(dummy_name_01, sensor);

    mock().expectOneCall("Sensor#init()").onObject(sensor);
    env->init();
    mock().expectOneCall("Sensor#start()").onObject(sensor);
    env->start();
    mock().expectOneCall("Sensor#stop()").onObject(sensor);
    env->stop();
    mock().checkExpectations();
}
<|endoftext|>


<commit_before><commit_msg>Quick fix for linux shared build.<commit_after><|endoftext|>


<commit_before>#include "FAST/Data/Image.hpp"
#include "FAST/Streamers/ImageFileStreamer.hpp"
#include "FAST/Algorithms/UltrasoundVesselDetection/UltrasoundVesselDetection.hpp"
#include "FAST/Algorithms/UltrasoundVesselDetection/VesselCrossSection.hpp"
#include "FAST/Exporters/ImageExporter.hpp"
#include "FAST/Algorithms/ImageCropper/ImageCropper.hpp"
#include "boost/filesystem.hpp"

using namespace fast;

inline std::string currentDateTime() {
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
    // for more information about date/time format
    strftime(buf, sizeof(buf), "%Y-%m-%d-%H%M%S", &tstruct);

    return buf;
}

int main() {
	std::string storageDir = "/home/smistad/vessel_validation_dataset/";
	boost::filesystem::create_directories(storageDir);
	// Set up stream
	std::vector<std::string> recordings = {
			/*
	"/home/smistad/AssistantTestData/1/US-Acq_03_20150608T103739/Acquisition/US-Acq_03_20150608T103739_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/1/US-Acq_04_20150608T103837/Acquisition/US-Acq_04_20150608T103837_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/1/US-Acq_07_20150608T104148/Acquisition/US-Acq_07_20150608T104148_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/1/US-Acq_08_20150608T104238/Acquisition/US-Acq_08_20150608T104238_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/0/US-Acq_03_20150608T102144/Acquisition/US-Acq_03_20150608T102144_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/0/US-Acq_04_20150608T102242/Acquisition/US-Acq_04_20150608T102242_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/0/US-Acq_07_20150608T102703/Acquisition/US-Acq_07_20150608T102703_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/0/US-Acq_08_20150608T102854/Acquisition/US-Acq_08_20150608T102854_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/2/US-Acq_03_20150608T104805/Acquisition/US-Acq_03_20150608T104805_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/2/US-Acq_04_20150608T104910/Acquisition/US-Acq_04_20150608T104910_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/2/US-Acq_07_20150608T105549/Acquisition/US-Acq_07_20150608T105549_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/2/US-Acq_08_20150608T105649/Acquisition/US-Acq_08_20150608T105649_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/3/US-Acq_03_20150608T113646/Acquisition/US-Acq_03_20150608T113646_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/3/US-Acq_04_20150608T113750/Acquisition/US-Acq_04_20150608T113750_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/3/US-Acq_07_20150608T114115/Acquisition/US-Acq_07_20150608T114115_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/3/US-Acq_08_20150608T114217/Acquisition/US-Acq_08_20150608T114217_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/4/US-Acq_03_20150608T112610/Acquisition/US-Acq_03_20150608T112610_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/4/US-Acq_04_20150608T112656/Acquisition/US-Acq_04_20150608T112656_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/4/US-Acq_08_20150608T113129/Acquisition/US-Acq_08_20150608T113129_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/4/US-Acq_09_20150608T113245/Acquisition/US-Acq_09_20150608T113245_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/5/US-Acq_03_20150608T111610/Acquisition/US-Acq_03_20150608T111610_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/5/US-Acq_04_20150608T111701/Acquisition/US-Acq_04_20150608T111701_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/5/US-Acq_07_20150608T111940/Acquisition/US-Acq_07_20150608T111940_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/6/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/6/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/6/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/6/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/6/4/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/7/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/7/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/7/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/7/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/8/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/8/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/8/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/8/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/9/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/9/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/9/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/9/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/10/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/10/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/10/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/10/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/11/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/11/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/11/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/11/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/12/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/12/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/12/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/12/3/US-2D_#.mhd",
	*/
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-105012/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-105257/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 6\ feb\ 2016/2016-02-06-094808/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 6\ feb\ 2016/2016-02-06-095237/US-2D_#.mhd",

	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-114458/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-120411/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-120648/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-120843/US-2D_#.mhd"
	};
	for(int i = 0; i < recordings.size(); ++i) {
		ImageFileStreamer::pointer streamer = ImageFileStreamer::New();
		streamer->setStreamingMode(STREAMING_MODE_PROCESS_ALL_FRAMES);
		streamer->setStepSize(10);
		streamer->setFilenameFormat(recordings[i]);
		streamer->update();
		DynamicData::pointer images = streamer->getOutputData<Image>();

		// Put in subfolders
		int j = i / 4; // Group 4 sequences into each folder
		std::string targetDir = storageDir + boost::lexical_cast<std::string>(j) + "/";
		boost::filesystem::create_directories(targetDir);

		UltrasoundVesselDetection::pointer dummy = UltrasoundVesselDetection::New();

		// Store ROIs as PNGs to disk
		int counter = 0;
		UltrasoundVesselDetection::pointer detector = UltrasoundVesselDetection::New();
		while(!images->hasReachedEnd()) {
			Image::pointer image = images->getNextFrame(dummy);
			Vector3ui imageSize = image->getSize();
			Vector3f spacing = image->getSpacing();

			detector->setInputData(image);
			detector->update();
			std::vector<VesselCrossSection::pointer> crossSections = detector->getCrossSections();
			std::cout << "Found " << crossSections.size() << " cross sections" << std::endl;

			// For each detected black ellipse
			for(VesselCrossSection::pointer crossSection : crossSections) {
				VesselCrossSectionAccess::pointer access = crossSection->getAccess(ACCESS_READ);
				Vector2f imageCenter = access->getImageCenterPosition();

				// Radius in pixels
				const float majorRadius = access->getMajorRadius();
				const float minorRadius = access->getMinorRadius();
				const int frameSize = std::max((int)round(majorRadius), 50); // Nr if pixels to include around vessel

				Vector2i offset(
						round(imageCenter.x() - majorRadius) - frameSize,
						round(imageCenter.y() - majorRadius) - frameSize
				);
				int size2 = 2*majorRadius + 2*frameSize;
				Vector2i size(
						size2,
						size2
				);

				ImageCropper::pointer cropper = ImageCropper::New();
				cropper->setInputData(image);
				cropper->allowOutOfBoundsCropping(true);
				cropper->setOffset(offset);
				cropper->setSize(size);

				ImageExporter::pointer exporter = ImageExporter::New();
				std::string filename = currentDateTime() + "-" + boost::lexical_cast<std::string>(counter) + ".png";
				exporter->setFilename(targetDir + filename);
				exporter->setInputConnection(cropper->getOutputPort());
				exporter->update();
				counter++;
			}
		}
		std::cout << "Finished recording " << (i+1) << " of " << recordings.size() << std::endl;
	}
}
<commit_msg>Carotid artery<commit_after>#include "FAST/Data/Image.hpp"
#include "FAST/Streamers/ImageFileStreamer.hpp"
#include "FAST/Algorithms/UltrasoundVesselDetection/UltrasoundVesselDetection.hpp"
#include "FAST/Algorithms/UltrasoundVesselDetection/VesselCrossSection.hpp"
#include "FAST/Exporters/ImageExporter.hpp"
#include "FAST/Algorithms/ImageCropper/ImageCropper.hpp"
#include "boost/filesystem.hpp"

using namespace fast;

inline std::string currentDateTime() {
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
    // for more information about date/time format
    strftime(buf, sizeof(buf), "%Y-%m-%d-%H%M%S", &tstruct);

    return buf;
}

int main() {
	std::string storageDir = "/home/smistad/carotis_validation_dataset/";
	boost::filesystem::create_directories(storageDir);
	// Set up stream
	std::vector<std::string> recordings = {
			/*
	"/home/smistad/AssistantTestData/1/US-Acq_03_20150608T103739/Acquisition/US-Acq_03_20150608T103739_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/1/US-Acq_04_20150608T103837/Acquisition/US-Acq_04_20150608T103837_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/1/US-Acq_07_20150608T104148/Acquisition/US-Acq_07_20150608T104148_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/1/US-Acq_08_20150608T104238/Acquisition/US-Acq_08_20150608T104238_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/0/US-Acq_03_20150608T102144/Acquisition/US-Acq_03_20150608T102144_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/0/US-Acq_04_20150608T102242/Acquisition/US-Acq_04_20150608T102242_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/0/US-Acq_07_20150608T102703/Acquisition/US-Acq_07_20150608T102703_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/0/US-Acq_08_20150608T102854/Acquisition/US-Acq_08_20150608T102854_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/2/US-Acq_03_20150608T104805/Acquisition/US-Acq_03_20150608T104805_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/2/US-Acq_04_20150608T104910/Acquisition/US-Acq_04_20150608T104910_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/2/US-Acq_07_20150608T105549/Acquisition/US-Acq_07_20150608T105549_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/2/US-Acq_08_20150608T105649/Acquisition/US-Acq_08_20150608T105649_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/3/US-Acq_03_20150608T113646/Acquisition/US-Acq_03_20150608T113646_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/3/US-Acq_04_20150608T113750/Acquisition/US-Acq_04_20150608T113750_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/3/US-Acq_07_20150608T114115/Acquisition/US-Acq_07_20150608T114115_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/3/US-Acq_08_20150608T114217/Acquisition/US-Acq_08_20150608T114217_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/4/US-Acq_03_20150608T112610/Acquisition/US-Acq_03_20150608T112610_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/4/US-Acq_04_20150608T112656/Acquisition/US-Acq_04_20150608T112656_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/4/US-Acq_08_20150608T113129/Acquisition/US-Acq_08_20150608T113129_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/4/US-Acq_09_20150608T113245/Acquisition/US-Acq_09_20150608T113245_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/5/US-Acq_03_20150608T111610/Acquisition/US-Acq_03_20150608T111610_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/5/US-Acq_04_20150608T111701/Acquisition/US-Acq_04_20150608T111701_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/5/US-Acq_07_20150608T111940/Acquisition/US-Acq_07_20150608T111940_Image_Transducer_#.mhd",
	"/home/smistad/AssistantTestData/6/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/6/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/6/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/6/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/6/4/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/7/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/7/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/7/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/7/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/8/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/8/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/8/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/8/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/9/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/9/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/9/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/9/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/10/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/10/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/10/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/10/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/11/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/11/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/11/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/11/3/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/12/0/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/12/1/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/12/2/US-2D_#.mhd",
	"/home/smistad/AssistantTestData/12/3/US-2D_#.mhd",
	*/
			/*
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-105012/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-105257/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 6\ feb\ 2016/2016-02-06-094808/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 6\ feb\ 2016/2016-02-06-095237/US-2D_#.mhd",

	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-114458/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-120411/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-120648/US-2D_#.mhd",
	"/media/smistad/New\ Volume/Assistant\ Recordings/Leuven\ 5\ feb\ 2016/2016-02-05-120843/US-2D_#.mhd"
	*/
			"/media/smistad/New Volume/Carotis/2016-06-02-140622/US-2D_#.mhd",
			"/media/smistad/New Volume/Carotis/2016-06-02-140721/US-2D_#.mhd",
			"/media/smistad/New Volume/Carotis/2016-06-02-140846/US-2D_#.mhd",
			"/media/smistad/New Volume/Carotis/2016-06-02-140923/US-2D_#.mhd"
	};
	for(int i = 0; i < recordings.size(); ++i) {
		ImageFileStreamer::pointer streamer = ImageFileStreamer::New();
		streamer->setStreamingMode(STREAMING_MODE_PROCESS_ALL_FRAMES);
		streamer->setStepSize(20);
		streamer->setFilenameFormat(recordings[i]);
		streamer->update();
		DynamicData::pointer images = streamer->getOutputData<Image>();

		// Put in subfolders
		int j = i / 4; // Group 4 sequences into each folder
		std::string targetDir = storageDir + boost::lexical_cast<std::string>(j) + "/";
		boost::filesystem::create_directories(targetDir);

		UltrasoundVesselDetection::pointer dummy = UltrasoundVesselDetection::New();

		// Store ROIs as PNGs to disk
		int counter = 0;
		UltrasoundVesselDetection::pointer detector = UltrasoundVesselDetection::New();
		while(!images->hasReachedEnd()) {
			Image::pointer image = images->getNextFrame(dummy);
			Vector3ui imageSize = image->getSize();
			Vector3f spacing = image->getSpacing();

			detector->setInputData(image);
			detector->update();
			std::vector<VesselCrossSection::pointer> crossSections = detector->getCrossSections();
			std::cout << "Found " << crossSections.size() << " cross sections" << std::endl;

			// For each detected black ellipse
			for(VesselCrossSection::pointer crossSection : crossSections) {
				VesselCrossSectionAccess::pointer access = crossSection->getAccess(ACCESS_READ);
				Vector2f imageCenter = access->getImageCenterPosition();

				// Radius in pixels
				const float majorRadius = access->getMajorRadius();
				const float minorRadius = access->getMinorRadius();
				const int frameSize = std::max((int)round(majorRadius), 50); // Nr if pixels to include around vessel

				Vector2i offset(
						round(imageCenter.x() - majorRadius) - frameSize,
						round(imageCenter.y() - majorRadius) - frameSize
				);
				int size2 = 2*majorRadius + 2*frameSize;
				Vector2i size(
						size2,
						size2
				);

				ImageCropper::pointer cropper = ImageCropper::New();
				cropper->setInputData(image);
				cropper->allowOutOfBoundsCropping(true);
				cropper->setOffset(offset);
				cropper->setSize(size);

				ImageExporter::pointer exporter = ImageExporter::New();
				std::string filename = currentDateTime() + "-" + boost::lexical_cast<std::string>(counter) + ".png";
				exporter->setFilename(targetDir + filename);
				exporter->setInputConnection(cropper->getOutputPort());
				exporter->update();
				counter++;
			}
		}
		std::cout << "Finished recording " << (i+1) << " of " << recordings.size() << std::endl;
	}
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013-2014, Filippo Basso <bassofil@dei.unipd.it>
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *     1. Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *     2. Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *     3. Neither the name of the copyright holder(s) nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <calibration_common/algorithms/automatic_checkerboard_finder.h>

namespace calibration
{

bool AutomaticCheckerboardFinder::find(const Checkerboard & checkerboard,
                                       std::vector<cv::Point2f> & corners) const
{
  cv::Size pattern_size(checkerboard.cols(), checkerboard.rows());
  corners.clear();

  bool pattern_found = cv::findChessboardCorners(gray_, pattern_size, corners);

  if (pattern_found)
    cv::cornerSubPix(gray_,
                     corners,
                     cv::Size(2, 2),
                     cv::Size(-1, -1),
                     cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 100, 0.01));

  return pattern_found;
}

} /* namespace calibration */
<commit_msg>Added cv::CALIB_CB_FAST_CHECK flag to pattern extraction function.<commit_after>/*
 *  Copyright (c) 2013-2014, Filippo Basso <bassofil@dei.unipd.it>
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *     1. Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *     2. Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *     3. Neither the name of the copyright holder(s) nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <calibration_common/algorithms/automatic_checkerboard_finder.h>

namespace calibration
{

bool AutomaticCheckerboardFinder::find(const Checkerboard & checkerboard,
                                       std::vector<cv::Point2f> & corners) const
{
  cv::Size pattern_size(checkerboard.cols(), checkerboard.rows());
  corners.clear();

  bool pattern_found = cv::findChessboardCorners(gray_, pattern_size, corners, cv::CALIB_CB_FAST_CHECK);

  if (pattern_found)
  {
    cv::cornerSubPix(gray_,
                     corners,
                     cv::Size(2, 2),
                     cv::Size(-1, -1),
                     cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 100, 0.01));
  }

  return pattern_found;
}

} /* namespace calibration */
<|endoftext|>


<commit_before>// Copyright (C) 2015 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include <math.h>
#include <string.h>
//#include <algorithm>

#include "copasi/utilities/CUnitDefinition.h"
//#include "copasi/utilities/CUnitParser.h"
#include "copasi/report/CKeyFactory.h"
#include "copasi/report/CCopasiRootContainer.h"
//#include "copasi/model/CModel.h"
#include "copasi/xml/CCopasiXMLInterface.h"

//#include "CCopasiException.h"

// SI Name, Symbol, Definition
struct SIUnit
{
  const char * name;
  const char * symbol;
  const char * expression;
};

SIUnit SIUnits[] =
{
  //SI base
  {"meter",      "m",        "m"},
  {"gram",       "g",        "g"},
  {"second",     "s",        "s"},
  {"ampere",     "A",        "A"},
  {"kelvin",     "K",        "K"},
  {"mole",      "mol",      "mol"},
  {"candela",   "cd",       "cd"},

  //SI derived
  {"becquerel",  "Bq",       "s^-1"},
  {"coulomb",    "C",        "s*A"},
  {"farad",      "F",        "m^-2*kg^-1*s^4*A^2"},
  {"gray",       "Gy",       "m^2*s^-2"},
  {"henry",      "H",        "m^2*kg*s^-2*A^-2"},
  {"hertz",      "Hz",       "s^-1"},
  {"joule",      "J",        "m^2*kg*s^-2"},
  {"katal",      "kat",      "s^-1*mol"},
  {"liter",      "l",        "0.001*m^3"},
  {"lumen",      "lm",       "cd"},
  {"lux",        "lx",       "m^-2*cd"},
  {"mole",       "mol",      "Avogadro*#"},
  {"newton",     "N",        "m*kg*s^-2"},
  {"ohm",        "\xCE\xA9", "m^2*kg*s^-3*A^-2"},
  {"pascal",     "Pa",       "m^-1*kg*s^-2"},
  {"siemens",    "S",        "m^-2*kg^-1*s^3*A^2"},
  {"sievert",    "Sv",       "m^2*s^-2"},
  {"tesla",      "T",        "kg*s^-2*A^-1"},
  {"volt",       "V",        "m^2*kg*s^-3*A^-1"},
  {"watt",       "W",        "m^2*kg*s^-3"},
  {"weber",      "Wb",       "m^2*kg*s^-2*A^-1"},

  {"dimensionless", "1",      "1"},
  {"item",       "#",        "#"},
  {"minute",     "min",      "60*s"},
  {"hour",       "h",        "3600*s"},
  {"day",        "d",        "86400*s"},

  // This must be the last element of the SI unit list! Do not delete!
  {NULL,         NULL,        NULL}
};

// static

CUnit CUnitDefinition::getSIUnit(const std::string & symbol,
                                 const C_FLOAT64 & avogadro)
{
  SIUnit * pSIUnit = SIUnits;

  while (pSIUnit->name && strcmp(pSIUnit->symbol, symbol.c_str()) != 0)
    ++pSIUnit;

  if (!pSIUnit->name)
    fatalError();

  std::ostringstream buffer;

  if (strcmp(pSIUnit->symbol, "mol"))
    {
      buffer << pSIUnit->expression;
    }
  else
    {
      buffer << CCopasiXMLInterface::DBL(avogadro) << "*#";
    }

  CUnit SIunit = CUnit();
  SIunit.setExpression(buffer.str(), avogadro);

  return SIunit;
}

// static
void CUnitDefinition::updateSIUnitDefinitions(CUnitDefinitionDB * Units,
    const C_FLOAT64 & avogadro)
{
  SIUnit * pSIUnit = SIUnits;

  while (pSIUnit->name)
    {
      CUnitDefinition * pUnitDef = NULL;
      size_t Index = Units->getIndex(pSIUnit->name);

      if (Index != C_INVALID_INDEX)
        {
          pUnitDef = Units->operator [](Index);
        }
      else
        {
          pUnitDef = new CUnitDefinition(pSIUnit->name, Units);
          pUnitDef->setSymbol(pSIUnit->symbol);
        }

      std::ostringstream buffer;

      if (strcmp(pSIUnit->symbol, "mol"))
        {
          buffer << pSIUnit->expression;
        }
      else
        {
          buffer << CCopasiXMLInterface::DBL(avogadro) << "*#";
        }

      pUnitDef->setExpression(buffer.str(), avogadro);

      pSIUnit++;
    }
}

// constructors
// default
CUnitDefinition::CUnitDefinition(const std::string & name,
                                 const CCopasiContainer * pParent):
  CCopasiContainer(name, pParent, "Unit"),
  CUnit(),
  CAnnotation(),
  mSymbol("symbol")
{
  setup();
}

// kind
CUnitDefinition::CUnitDefinition(const CBaseUnit::Kind & kind,
                                 const CCopasiContainer * pParent):
  CCopasiContainer(CBaseUnit::Name[kind], pParent, "Unit"),
  CUnit(kind),
  CAnnotation(),
  mSymbol(CBaseUnit::getSymbol(kind))
{
  setup();
}

// copy
CUnitDefinition::CUnitDefinition(const CUnitDefinition &src,
                                 const C_FLOAT64 & avogadro,
                                 const CCopasiContainer * pParent):
  CCopasiContainer(src, pParent),
  CUnit(src, avogadro),
  CAnnotation(src),
  mSymbol(src.mSymbol)
{
  setup();
}

CUnitDefinition::~CUnitDefinition()
{
  CCopasiRootContainer::getKeyFactory()->remove(mKey);

  CCopasiContainer * pParent = getObjectParent();

  if (pParent != NULL)
    {
      pParent->remove(this);
    }
}

void CUnitDefinition::setup()
{
  CCopasiContainer * pParent = getObjectParent();

  if (pParent != NULL)
    {
      pParent->add(this, true);
    }

  mKey = CCopasiRootContainer::getKeyFactory()->add("Unit", this);

  // The following ought to trigger the exception for
  // a symbol already in the CUnitDefinitionDB
  std::ostringstream Symbol;

  Symbol.str(mSymbol.c_str());
  int i = 1;

  while (!setSymbol(Symbol.str()))
    {
      Symbol.str("");
      Symbol << mSymbol << "_" << i++;
    }
}

// virtual
const std::string & CUnitDefinition::getKey() const
{
  return CAnnotation::getKey();
}

bool CUnitDefinition::setSymbol(const std::string & symbol)
{
  CUnitDefinitionDB * pUnitDefinitionDB = dynamic_cast < CUnitDefinitionDB * >(getObjectParent());

  if (pUnitDefinitionDB == NULL ||
      pUnitDefinitionDB->changeSymbol(this, symbol))
    {
      mSymbol = symbol;

      return true;
    }

  CCopasiMessage(CCopasiMessage::ERROR, MCUnitDefinition + 2, symbol.c_str());

  return false;
}

const std::string & CUnitDefinition::getSymbol() const
{
  return mSymbol;
}

CUnitDefinition & CUnitDefinition::operator=(const CUnitDefinition & src)
{
  // All CUnitDefinition symbols in a CUnitDefinitionDB should be unique
  // This should protect that for cases like this:
  // *aCunitDefDB[i] = someCunitDef;

  if ((dynamic_cast < CUnitDefinitionDB *>(getObjectParent()))->containsSymbol(src.getSymbol()))
    CCopasiMessage ex(CCopasiMessage::EXCEPTION, MCUnitDefinition + 2);

  *this = src;

  return *this;
}

//static
bool CUnitDefinition::isBuiltinUnitSymbol(std::string symbol)
{
  SIUnit * pSIUnit = SIUnits;

  while (pSIUnit->symbol && strcmp(pSIUnit->symbol, symbol.c_str()) != 0)
    ++pSIUnit;

  return (pSIUnit->symbol != NULL);
}

bool CUnitDefinition::isReadOnly() const
{
  SIUnit * pSIUnit = SIUnits;

  while (pSIUnit->name && getObjectName() != pSIUnit->name)
    ++pSIUnit;

  return (pSIUnit->name != NULL);
}
<commit_msg>Fixed CUnitDefinition::operator= to check if rhs is itself, and make sure BOTH the symbol and the name not already used.<commit_after>// Copyright (C) 2015 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include <math.h>
#include <string.h>
//#include <algorithm>

#include "copasi/utilities/CUnitDefinition.h"
//#include "copasi/utilities/CUnitParser.h"
#include "copasi/report/CKeyFactory.h"
#include "copasi/report/CCopasiRootContainer.h"
//#include "copasi/model/CModel.h"
#include "copasi/xml/CCopasiXMLInterface.h"

//#include "CCopasiException.h"

// SI Name, Symbol, Definition
struct SIUnit
{
  const char * name;
  const char * symbol;
  const char * expression;
};

SIUnit SIUnits[] =
{
  //SI base
  {"meter",      "m",        "m"},
  {"gram",       "g",        "g"},
  {"second",     "s",        "s"},
  {"ampere",     "A",        "A"},
  {"kelvin",     "K",        "K"},
  {"mole",      "mol",      "mol"},
  {"candela",   "cd",       "cd"},

  //SI derived
  {"becquerel",  "Bq",       "s^-1"},
  {"coulomb",    "C",        "s*A"},
  {"farad",      "F",        "m^-2*kg^-1*s^4*A^2"},
  {"gray",       "Gy",       "m^2*s^-2"},
  {"henry",      "H",        "m^2*kg*s^-2*A^-2"},
  {"hertz",      "Hz",       "s^-1"},
  {"joule",      "J",        "m^2*kg*s^-2"},
  {"katal",      "kat",      "s^-1*mol"},
  {"liter",      "l",        "0.001*m^3"},
  {"lumen",      "lm",       "cd"},
  {"lux",        "lx",       "m^-2*cd"},
  {"mole",       "mol",      "Avogadro*#"},
  {"newton",     "N",        "m*kg*s^-2"},
  {"ohm",        "\xCE\xA9", "m^2*kg*s^-3*A^-2"},
  {"pascal",     "Pa",       "m^-1*kg*s^-2"},
  {"siemens",    "S",        "m^-2*kg^-1*s^3*A^2"},
  {"sievert",    "Sv",       "m^2*s^-2"},
  {"tesla",      "T",        "kg*s^-2*A^-1"},
  {"volt",       "V",        "m^2*kg*s^-3*A^-1"},
  {"watt",       "W",        "m^2*kg*s^-3"},
  {"weber",      "Wb",       "m^2*kg*s^-2*A^-1"},

  {"dimensionless", "1",      "1"},
  {"item",       "#",        "#"},
  {"minute",     "min",      "60*s"},
  {"hour",       "h",        "3600*s"},
  {"day",        "d",        "86400*s"},

  // This must be the last element of the SI unit list! Do not delete!
  {NULL,         NULL,        NULL}
};

// static

CUnit CUnitDefinition::getSIUnit(const std::string & symbol,
                                 const C_FLOAT64 & avogadro)
{
  SIUnit * pSIUnit = SIUnits;

  while (pSIUnit->name && strcmp(pSIUnit->symbol, symbol.c_str()) != 0)
    ++pSIUnit;

  if (!pSIUnit->name)
    fatalError();

  std::ostringstream buffer;

  if (strcmp(pSIUnit->symbol, "mol"))
    {
      buffer << pSIUnit->expression;
    }
  else
    {
      buffer << CCopasiXMLInterface::DBL(avogadro) << "*#";
    }

  CUnit SIunit = CUnit();
  SIunit.setExpression(buffer.str(), avogadro);

  return SIunit;
}

// static
void CUnitDefinition::updateSIUnitDefinitions(CUnitDefinitionDB * Units,
    const C_FLOAT64 & avogadro)
{
  SIUnit * pSIUnit = SIUnits;

  while (pSIUnit->name)
    {
      CUnitDefinition * pUnitDef = NULL;
      size_t Index = Units->getIndex(pSIUnit->name);

      if (Index != C_INVALID_INDEX)
        {
          pUnitDef = Units->operator [](Index);
        }
      else
        {
          pUnitDef = new CUnitDefinition(pSIUnit->name, Units);
          pUnitDef->setSymbol(pSIUnit->symbol);
        }

      std::ostringstream buffer;

      if (strcmp(pSIUnit->symbol, "mol"))
        {
          buffer << pSIUnit->expression;
        }
      else
        {
          buffer << CCopasiXMLInterface::DBL(avogadro) << "*#";
        }

      pUnitDef->setExpression(buffer.str(), avogadro);

      pSIUnit++;
    }
}

// constructors
// default
CUnitDefinition::CUnitDefinition(const std::string & name,
                                 const CCopasiContainer * pParent):
  CCopasiContainer(name, pParent, "Unit"),
  CUnit(),
  CAnnotation(),
  mSymbol("symbol")
{
  setup();
}

// kind
CUnitDefinition::CUnitDefinition(const CBaseUnit::Kind & kind,
                                 const CCopasiContainer * pParent):
  CCopasiContainer(CBaseUnit::Name[kind], pParent, "Unit"),
  CUnit(kind),
  CAnnotation(),
  mSymbol(CBaseUnit::getSymbol(kind))
{
  setup();
}

// copy
CUnitDefinition::CUnitDefinition(const CUnitDefinition &src,
                                 const C_FLOAT64 & avogadro,
                                 const CCopasiContainer * pParent):
  CCopasiContainer(src, pParent),
  CUnit(src, avogadro),
  CAnnotation(src),
  mSymbol(src.mSymbol)
{
  setup();
}

CUnitDefinition::~CUnitDefinition()
{
  CCopasiRootContainer::getKeyFactory()->remove(mKey);

  CCopasiContainer * pParent = getObjectParent();

  if (pParent != NULL)
    {
      pParent->remove(this);
    }
}

void CUnitDefinition::setup()
{
  CCopasiContainer * pParent = getObjectParent();

  if (pParent != NULL)
    {
      pParent->add(this, true);
    }

  mKey = CCopasiRootContainer::getKeyFactory()->add("Unit", this);

  // The following ought to trigger the exception for
  // a symbol already in the CUnitDefinitionDB
  std::ostringstream Symbol;

  Symbol.str(mSymbol.c_str());
  int i = 1;

  while (!setSymbol(Symbol.str()))
    {
      Symbol.str("");
      Symbol << mSymbol << "_" << i++;
    }
}

// virtual
const std::string & CUnitDefinition::getKey() const
{
  return CAnnotation::getKey();
}

bool CUnitDefinition::setSymbol(const std::string & symbol)
{
  CUnitDefinitionDB * pUnitDefinitionDB = dynamic_cast < CUnitDefinitionDB * >(getObjectParent());

  if (pUnitDefinitionDB == NULL ||
      pUnitDefinitionDB->changeSymbol(this, symbol))
    {
      mSymbol = symbol;

      return true;
    }

  CCopasiMessage(CCopasiMessage::ERROR, MCUnitDefinition + 2, symbol.c_str());

  return false;
}

const std::string & CUnitDefinition::getSymbol() const
{
  return mSymbol;
}

CUnitDefinition & CUnitDefinition::operator=(const CUnitDefinition & src)
{
   if (this == &src) return *this;

  // All CUnitDefinition symbols in a CUnitDefinitionDB should be unique
  // This should protect that for cases like this:
  // *aCunitDefDB[i] = someCunitDef;

   CUnitDefinitionDB * pDB =
       dynamic_cast < CUnitDefinitionDB * >(getObjectParent());

     if (pDB != NULL &&
         pDB->containsSymbol(src.getSymbol()) &&
         pDB->getIndex(src.getObjectName()) != C_INVALID_INDEX)
       CCopasiMessage ex(CCopasiMessage::EXCEPTION, MCUnitDefinition + 2);

  *this = src;

  return *this;
}

//static
bool CUnitDefinition::isBuiltinUnitSymbol(std::string symbol)
{
  SIUnit * pSIUnit = SIUnits;

  while (pSIUnit->symbol && strcmp(pSIUnit->symbol, symbol.c_str()) != 0)
    ++pSIUnit;

  return (pSIUnit->symbol != NULL);
}

bool CUnitDefinition::isReadOnly() const
{
  SIUnit * pSIUnit = SIUnits;

  while (pSIUnit->name && getObjectName() != pSIUnit->name)
    ++pSIUnit;

  return (pSIUnit->name != NULL);
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <cstdarg>
#include <iostream>
#include <Common/Colorful.hh>
#include <Core/Chunk.hh>
#include <GC/GC.hh>
#include <Object/NativeObject.hh>
#include <Core/CallFrame.hh>
#include <Compiler/Compiler.hh>
#include <Builtin/Builtins.hh>
#include <Core/TadpoleVM.hh>

namespace Tadpole::Core {

TadpoleVM::TadpoleVM() noexcept {
  gcompiler_ = new Compiler::GlobalCompiler();
  stack_.reserve(kDefaultCap);

  Builtin::register_builtins(*this);
  GC::GC::get_instance().append_roots("TadpoleVM", this);
}

TadpoleVM::~TadpoleVM() {
  delete gcompiler_;
  globals_.clear();
}

void TadpoleVM::define_native(const str_t& name, Value::TadpoleCFun&& fn) {
  globals_[name] = Object::NativeObject::create(std::move(fn));
}

InterpretRet TadpoleVM::interpret(const str_t& source_bytes) {
  Object::FunctionObject* fn = gcompiler_->compile(*this, source_bytes);
  if (fn == nullptr)
    return InterpretRet::ECOMPILE;

  // TODO:
  return InterpretRet::OK;
}

void TadpoleVM::iter_objects(Object::ObjectVisitor&& visitor) {
  // TODO:
}

}
<commit_msg>:construction: chore(vm): updated the common functional for vm of tadpole<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <cstdarg>
#include <iostream>
#include <Common/Colorful.hh>
#include <Core/Chunk.hh>
#include <GC/GC.hh>
#include <Object/NativeObject.hh>
#include <Core/CallFrame.hh>
#include <Compiler/Compiler.hh>
#include <Builtin/Builtins.hh>
#include <Core/TadpoleVM.hh>

namespace Tadpole::Core {

TadpoleVM::TadpoleVM() noexcept {
  gcompiler_ = new Compiler::GlobalCompiler();
  stack_.reserve(kDefaultCap);

  Builtin::register_builtins(*this);
  GC::GC::get_instance().append_roots("TadpoleVM", this);
}

TadpoleVM::~TadpoleVM() {
  delete gcompiler_;
  globals_.clear();
}

void TadpoleVM::define_native(const str_t& name, Value::TadpoleCFun&& fn) {
  globals_[name] = Object::NativeObject::create(std::move(fn));
}

InterpretRet TadpoleVM::interpret(const str_t& source_bytes) {
  Object::FunctionObject* fn = gcompiler_->compile(*this, source_bytes);
  if (fn == nullptr)
    return InterpretRet::ECOMPILE;

  // TODO:
  return InterpretRet::OK;
}

void TadpoleVM::iter_objects(Object::ObjectVisitor&& visitor) {
  // iterate Tadpole objects roots
  gcompiler_->iter_objects(std::move(visitor));
  for (auto& v : stack_)
    visitor(v.as_object(safe_t()));
  for (auto& f : frames_)
    visitor(f.closure());
  for (auto& g : globals_)
    visitor(g.second.as_object(safe_t()));
  for (auto* u = open_upvalues_; u != nullptr; u = u->next())
    visitor(u);
}

void TadpoleVM::reset() {
  stack_.clear();
  frames_.clear();
  open_upvalues_ = nullptr;
}

void TadpoleVM::runtime_error(const char* format, ...) {
  std::cerr << Common::Colorful::fg::red << "Traceback (most recent call last):" << std::endl;
  for (auto it = frames_.rbegin(); it != frames_.rend(); ++it) {
    auto& frame = *it;

    sz_t i = frame.frame_chunk()->offset_with(frame.ip()) - 1;
    std::cerr
      << "  [LINE: " << frame.frame_chunk()->get_line(i) << "] in "
      << "`" << frame.frame_fn()->name_asstr() << "()`"
      << std::endl;
  }

  va_list ap;
  va_start(ap, format);
  std::vfprintf(stderr, format, ap);
  va_end(ap);
  std::cerr << Common::Colorful::reset << std::endl;

  reset();
}

void TadpoleVM::push(const Value::Value& value) noexcept {
  stack_.push_back(value);
}

Value::Value TadpoleVM::pop() noexcept {
  Value::Value value = stack_.back();
  stack_.pop_back();
  return value;
}

const Value::Value& TadpoleVM::peek(sz_t distance) const noexcept {
  return stack_[stack_.size() - 1 - distance];
}

}
<|endoftext|>