<commit_before>#include "ImgProcSet.h"
#include <typeinfo>
#include <time.h>
using namespace std;

namespace cvImagePipeline {
	namespace Filter {
		///////////////////////////////////////////////////////////////////////////
		// class ImgProcSet

		IMPLEMENT_CVFILTER(ImgProcSet);

		ImgProcSet::ImgProcSet()
			: lastAutoProcessor(0)
		{
		}
		ImgProcSet::~ImgProcSet()
		{
			std::vector<ImageProcessor*>::iterator dyn_filter = dyn_filters.begin();
			while(dyn_filter != dyn_filters.end()) {
#ifdef _DEBUG
				std::cout << "delete filter "
					<< typeid(**dyn_filter).name() << std::endl;
#endif
				delete *dyn_filter;
				*dyn_filter = 0;
				dyn_filter++;
			}
		}

		ImageProcessor& ImgProcSet::add(
			std::string filter_class_name,
			std::string filter_instance_name,
			bool autoBind)
		{
			ImageProcessor* filter = ImageProcessor::createFilter(filter_class_name);
			if(filter != 0) {
				dyn_filters.push_back(filter);
				name_to_filter[filter_instance_name] = filter;
				filter->setName(getName() + "." + filter_instance_name);
				add(*filter, autoBind);
			} else {
				std::cerr << "ImageProcessor \"" << filter_class_name << "\" is not exist in "
					<< getName() << " instance of class " << std::string(typeid(*this).name()) << "."
					<< std::endl;
				throw new std::exception("ProcessorNotFound");
			}
			return *filter;
		}
		ImageProcessor& ImgProcSet::add(ImageProcessor& proc, bool autoBind)
		{
			if(autoBind) {
				std::list<ImageProcessor*>::reverse_iterator back = procs.rbegin();
				if(back != procs.rend()) {
					ImageProcessor* last = *back;
					*last >> proc;
				} else {
					proc.setInputMat(getInputMat());
				}
				refOutputMat() = proc.getOutputMat();
				lastAutoProcessor = &proc;
			}
			procs.push_back(&proc);
			return proc;
		}
		void ImgProcSet::setParam(
			std::string filter_instance_name,
			std::string parameter_name, int value)
		{
			(*this)[filter_instance_name].property(parameter_name, value);
		}
		ImageProcessor& ImgProcSet::operator[](
			std::string filter_instance_name)
		{
			ImageProcessor* filter = 0;
			if(name_to_filter.count(filter_instance_name) > 0) {
				filter = name_to_filter[filter_instance_name];
			} else {
				std::cerr << "ImageProcessor named \"" << filter_instance_name << "\" is not exist in "
					<< getName() << " instance of class " << std::string(typeid(*this).name()) << "."
					<< std::endl;
				throw new std::exception("ProcessorInstanceNotFound");
			}
			return *filter;
		}

		void ImgProcSet::execute()
		{
			if (isEnable()) {
				std::list<ImageProcessor*>::iterator proc = procs.begin();
				while (proc != procs.end()) {
					if ((*proc)->isEnable()) {
						(*proc)->execute();
					}
					proc++;
				}
				if (lastAutoProcessor != 0) {
					setOutputMat(lastAutoProcessor->getOutputMat());
				}
			}
		}
		void ImgProcSet::putMarkdown(std::ostream& stream) {
			ImageProcessor::putMarkdown(stream);
			stream << "----" << std::endl;
			stream << std::endl;
			std::list<ImageProcessor*>::iterator proc = procs.begin();
			for(; proc != procs.end(); proc++) {
				(*proc)->putMarkdown(stream);
			}
		}

		using namespace pugi;
		/**
		 * create procesor pipeline from xml file.
		 */
		bool ImgProcSet::loadXml(const std::string& filename) {
			xml_document document;
			xml_parse_result result = document.load_file(filename.c_str());
			if(result.status != status_ok) {
				return false;
			}
			xml_node root_node = document.document_element();
#ifdef _DEBUG
			cerr << "[ImgProcSet::loadXml]" << "root node name = " << root_node.name() << endl;
#endif
			pugi::xml_attribute root_name_attr = root_node.attribute("name");
			setName(root_name_attr.as_string());

			xpath_node_set processor_node_set = root_node.select_nodes("Processor");
			xpath_node_set::const_iterator processor = processor_node_set.begin();
			while(processor != processor_node_set.end()) {
				addProcessorByXmlNode(processor->node());
				processor++;
			}
			return true;
		}
		void ImgProcSet::addProcessorByXmlNode(pugi::xml_node processor)
		{
			// Attr processor class name
			xml_attribute attr_proc_class = processor.attribute("class");
			// Attr instance name
			xml_attribute attr_proc_name = processor.attribute("name");
#ifdef _DEBUG
			cerr << "[ImgProcSet::addProcessorByXmlNode]  " << "Processor "
				<< attr_proc_class.name() << " = " << attr_proc_class.as_string() << ", "
				<< attr_proc_name.name() << " = " << attr_proc_name.as_string() << endl;
#endif

			// Attr autoBind
			xml_attribute attr_bind = processor.attribute("autoBind");

			string autoBindAttrName = string(attr_bind.name());
			bool autoBind = true;
			if(autoBindAttrName == "") {
#ifdef _DEBUG
				cerr << "property autoBind not specified. default=true" << std::endl;
#endif
			} else {
				autoBind  = attr_bind.as_bool();
			}
#ifdef _DEBUG
			cerr << "property autoBind = \"" << autoBind << "\"" << std::endl;
#endif

			// create and add.
			ImageProcessor& proc = add(
					attr_proc_class.as_string(),
					attr_proc_name.as_string(),
					autoBind);

			//
			// Property
			//
			xpath_node_set property_node_set = processor.select_nodes("Property");
			xpath_node_set::const_iterator property = property_node_set.begin();
			while(property != property_node_set.end()) {
				proc.setPropertyByXmlNode(property->node());
				property++;
			}

			//
			// Input
			//
			xpath_node_set input_node_set = processor.select_nodes("Input");
			xpath_node_set::const_iterator input = input_node_set.begin();
			while(input != input_node_set.end()) {
				setInputMatByXmlNode(proc, input->node());
				input++;
			}

		}
		void ImgProcSet::setInputMatByXmlNode(ImageProcessor& imageProcessor, pugi::xml_node input) {
			string srcProcName = string(input.attribute("from").as_string());
			string dstInMatName = string(input.attribute("to").as_string());
#ifdef _DEBUG
			cerr << "[ImageProcessor::setInputMatByXmlNode]    " << "Input "
				<< "from \"" << srcProcName << "\", to " << dstInMatName << endl;
#endif
			(*this)[srcProcName] >> imageProcessor.input(dstInMatName);
		}

		void ImageProcessor::setPropertyByXmlNode(xml_node property) {
			xml_attribute attr_prop_name = property.attribute("name");
			xml_attribute attr_prop_value = property.attribute("value");
#ifdef _DEBUG
			cerr << "[ImageProcessor::setPropertyByXmlNode]    " << "Property "
				<< attr_prop_name.name() << " = " << attr_prop_name.as_string() << ", "
				<< attr_prop_value.name() << " = " << attr_prop_value.as_string() << endl;
#endif
			setPropertyAsString(attr_prop_name.as_string(), attr_prop_value.as_string());
		}
	}
}
<commit_msg>add try catch in execute().<commit_after>#include "ImgProcSet.h"
#include <typeinfo>
#include <time.h>
using namespace std;

namespace cvImagePipeline {
	namespace Filter {
		///////////////////////////////////////////////////////////////////////////
		// class ImgProcSet

		IMPLEMENT_CVFILTER(ImgProcSet);

		ImgProcSet::ImgProcSet()
			: lastAutoProcessor(0)
		{
		}
		ImgProcSet::~ImgProcSet()
		{
			std::vector<ImageProcessor*>::iterator dyn_filter = dyn_filters.begin();
			while(dyn_filter != dyn_filters.end()) {
#ifdef _DEBUG
				std::cout << "delete filter "
					<< typeid(**dyn_filter).name() << std::endl;
#endif
				delete *dyn_filter;
				*dyn_filter = 0;
				dyn_filter++;
			}
		}

		ImageProcessor& ImgProcSet::add(
			std::string filter_class_name,
			std::string filter_instance_name,
			bool autoBind)
		{
			ImageProcessor* filter = ImageProcessor::createFilter(filter_class_name);
			if(filter != 0) {
				dyn_filters.push_back(filter);
				name_to_filter[filter_instance_name] = filter;
				filter->setName(getName() + "." + filter_instance_name);
				add(*filter, autoBind);
			} else {
				std::cerr << "ImageProcessor \"" << filter_class_name << "\" is not exist in "
					<< getName() << " instance of class " << std::string(typeid(*this).name()) << "."
					<< std::endl;
				throw new std::exception("ProcessorNotFound");
			}
			return *filter;
		}
		ImageProcessor& ImgProcSet::add(ImageProcessor& proc, bool autoBind)
		{
			if(autoBind) {
				std::list<ImageProcessor*>::reverse_iterator back = procs.rbegin();
				if(back != procs.rend()) {
					ImageProcessor* last = *back;
					*last >> proc;
				} else {
					proc.setInputMat(getInputMat());
				}
				refOutputMat() = proc.getOutputMat();
				lastAutoProcessor = &proc;
			}
			procs.push_back(&proc);
			return proc;
		}
		void ImgProcSet::setParam(
			std::string filter_instance_name,
			std::string parameter_name, int value)
		{
			(*this)[filter_instance_name].property(parameter_name, value);
		}
		ImageProcessor& ImgProcSet::operator[](
			std::string filter_instance_name)
		{
			ImageProcessor* filter = 0;
			if(name_to_filter.count(filter_instance_name) > 0) {
				filter = name_to_filter[filter_instance_name];
			} else {
				std::cerr << "ImageProcessor named \"" << filter_instance_name << "\" is not exist in "
					<< getName() << " instance of class " << std::string(typeid(*this).name()) << "."
					<< std::endl;
				throw new std::exception("ProcessorInstanceNotFound");
			}
			return *filter;
		}

		void ImgProcSet::execute()
		{
			if (isEnable()) {
				std::list<ImageProcessor*>::iterator proc = procs.begin();
				while (proc != procs.end()) {
					if ((*proc)->isEnable()) {
						try {
							(*proc)->execute();
						}
						catch (...) {
							cerr
								<< "exception caught in " << getName()
								<< "from " << (*proc)->getName() << "."
								<< endl;
						}
					}
					proc++;
				}
				if (lastAutoProcessor != 0) {
					setOutputMat(lastAutoProcessor->getOutputMat());
				}
			}
		}
		void ImgProcSet::putMarkdown(std::ostream& stream) {
			ImageProcessor::putMarkdown(stream);
			stream << "----" << std::endl;
			stream << std::endl;
			std::list<ImageProcessor*>::iterator proc = procs.begin();
			for(; proc != procs.end(); proc++) {
				(*proc)->putMarkdown(stream);
			}
		}

		using namespace pugi;
		/**
		 * create procesor pipeline from xml file.
		 */
		bool ImgProcSet::loadXml(const std::string& filename) {
			xml_document document;
			xml_parse_result result = document.load_file(filename.c_str());
			if(result.status != status_ok) {
				return false;
			}
			xml_node root_node = document.document_element();
#ifdef _DEBUG
			cerr << "[ImgProcSet::loadXml]" << "root node name = " << root_node.name() << endl;
#endif
			pugi::xml_attribute root_name_attr = root_node.attribute("name");
			setName(root_name_attr.as_string());

			xpath_node_set processor_node_set = root_node.select_nodes("Processor");
			xpath_node_set::const_iterator processor = processor_node_set.begin();
			while(processor != processor_node_set.end()) {
				addProcessorByXmlNode(processor->node());
				processor++;
			}
			return true;
		}
		void ImgProcSet::addProcessorByXmlNode(pugi::xml_node processor)
		{
			// Attr processor class name
			xml_attribute attr_proc_class = processor.attribute("class");
			// Attr instance name
			xml_attribute attr_proc_name = processor.attribute("name");
#ifdef _DEBUG
			cerr << "[ImgProcSet::addProcessorByXmlNode]  " << "Processor "
				<< attr_proc_class.name() << " = " << attr_proc_class.as_string() << ", "
				<< attr_proc_name.name() << " = " << attr_proc_name.as_string() << endl;
#endif

			// Attr autoBind
			xml_attribute attr_bind = processor.attribute("autoBind");

			string autoBindAttrName = string(attr_bind.name());
			bool autoBind = true;
			if(autoBindAttrName == "") {
#ifdef _DEBUG
				cerr << "property autoBind not specified. default=true" << std::endl;
#endif
			} else {
				autoBind  = attr_bind.as_bool();
			}
#ifdef _DEBUG
			cerr << "property autoBind = \"" << autoBind << "\"" << std::endl;
#endif

			// create and add.
			ImageProcessor& proc = add(
					attr_proc_class.as_string(),
					attr_proc_name.as_string(),
					autoBind);

			//
			// Property
			//
			xpath_node_set property_node_set = processor.select_nodes("Property");
			xpath_node_set::const_iterator property = property_node_set.begin();
			while(property != property_node_set.end()) {
				proc.setPropertyByXmlNode(property->node());
				property++;
			}

			//
			// Input
			//
			xpath_node_set input_node_set = processor.select_nodes("Input");
			xpath_node_set::const_iterator input = input_node_set.begin();
			while(input != input_node_set.end()) {
				setInputMatByXmlNode(proc, input->node());
				input++;
			}

		}
		void ImgProcSet::setInputMatByXmlNode(ImageProcessor& imageProcessor, pugi::xml_node input) {
			string srcProcName = string(input.attribute("from").as_string());
			string dstInMatName = string(input.attribute("to").as_string());
#ifdef _DEBUG
			cerr << "[ImageProcessor::setInputMatByXmlNode]    " << "Input "
				<< "from \"" << srcProcName << "\", to " << dstInMatName << endl;
#endif
			(*this)[srcProcName] >> imageProcessor.input(dstInMatName);
		}

		void ImageProcessor::setPropertyByXmlNode(xml_node property) {
			xml_attribute attr_prop_name = property.attribute("name");
			xml_attribute attr_prop_value = property.attribute("value");
#ifdef _DEBUG
			cerr << "[ImageProcessor::setPropertyByXmlNode]    " << "Property "
				<< attr_prop_name.name() << " = " << attr_prop_name.as_string() << ", "
				<< attr_prop_value.name() << " = " << attr_prop_value.as_string() << endl;
#endif
			setPropertyAsString(attr_prop_name.as_string(), attr_prop_value.as_string());
		}
	}
}
<|endoftext|>


<commit_before>/***************************************************************************
*   Copyright (C) 2003 by                                                 *
*   Unai Garro (ugarro@users.sourceforge.net)                             *
*   Cyril Bosselut (bosselut@b1project.com)                               *
*   Jason Kivlighn (mizunoami44@users.sourceforge.net)                    *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
***************************************************************************/

#include "shoppinglistdialog.h"

#include <klocale.h>
#include <kconfig.h>
#include <kdialog.h>
#include <kglobal.h>

#include "DBBackend/recipedb.h"
#include "refineshoppinglistdialog.h"
#include "datablocks/recipelist.h"
#include "widgets/recipelistview.h"
#include "recipefilter.h"
#include "recipeactionshandler.h"

/** A simple listview to accept dropping a RecipeItemDrag */
class ShoppingListView : public KListView
{
public:
	ShoppingListView( QWidget *parent ) : KListView( parent )
	{}

protected:
	bool acceptDrag( QDropEvent *event ) const
	{
		return RecipeItemDrag::canDecode( event );
	}

	QDragObject *dragObject()
	{
		RecipeListItem * item = dynamic_cast<RecipeListItem*>( selectedItem() );
		if ( item != 0 ) {

			RecipeItemDrag * obj = new RecipeItemDrag( item, this, "Recipe drag item" );
			/*const QPixmap *pm = item->pixmap(0);
			if( pm )
				obj->setPixmap( *pm );*/
			return obj;
		}
		return 0;
	}
};

ShoppingListDialog::ShoppingListDialog( QWidget *parent, RecipeDB *db ) : QWidget( parent )
{
	// Store pointer to database
	database = db;

	// Design dialog
	layout = new QGridLayout( this, 2, 2, KDialog::marginHint(), KDialog::spacingHint() );

	recipeListView = new KreListView ( this, i18n( "Full recipe list" ), true, 1 );
	layout->addWidget( recipeListView, 0, 0 );
	RecipeListView *listview = new RecipeListView( recipeListView, database );
	listview->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::MinimumExpanding );
	listview->setDragEnabled( true );
	listview->setAcceptDrops( true );
	listview->setDropVisualizer( false );
	connect( listview, SIGNAL( dropped( KListView*, QDropEvent*, QListViewItem* ) ),
	         this, SLOT( slotDropped( KListView*, QDropEvent*, QListViewItem* ) ) );
	listview->reload();
	recipeListView->setListView( listview );
	recipeListView->setCustomFilter( new RecipeFilter( recipeListView->listView() ), SLOT( filter( const QString & ) ) );
	recipeListView->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::MinimumExpanding );

	QBoxLayout* vboxl = new QVBoxLayout( this, 0, KDialog::spacingHint() );
	KIconLoader il;
	addRecipeButton = new QPushButton( this );
	addRecipeButton->setIconSet( il.loadIconSet( "forward", KIcon::Small ) );
	addRecipeButton->setFixedSize( QSize( 32, 32 ) );
	addRecipeButton->setFlat( true );
	vboxl->addWidget( addRecipeButton );

	removeRecipeButton = new QPushButton( this );
	removeRecipeButton->setIconSet( il.loadIconSet( "back", KIcon::Small ) );
	removeRecipeButton->setFixedSize( QSize( 32, 32 ) );
	removeRecipeButton->setFlat( true );
	vboxl->addWidget( removeRecipeButton );
	vboxl->addStretch();

	layout->addItem( vboxl, 0, 1 );

	shopRecipeListView = new KreListView ( this, "Shopping list" );
	ShoppingListView *slistview = new ShoppingListView( shopRecipeListView );
	slistview->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::MinimumExpanding );
	slistview->setDragEnabled( true );
	slistview->setAcceptDrops( true );
	slistview->setDropVisualizer( false );
	connect( slistview, SIGNAL( dropped( KListView*, QDropEvent*, QListViewItem* ) ),
	         this, SLOT( slotDropped( KListView*, QDropEvent*, QListViewItem* ) ) );
	shopRecipeListView->setListView( slistview );
	layout->addWidget( shopRecipeListView, 0, 2 );

	shopRecipeListView->listView() ->addColumn( i18n( "Recipe Title" ) );

	KConfig *config = KGlobal::config();
	config->setGroup( "Advanced" );
	bool show_id = config->readBoolEntry( "ShowID", false );
	shopRecipeListView->listView() ->addColumn( i18n( "Id" ), show_id ? -1 : 0 );

	shopRecipeListView->listView() ->setSorting( -1 );
	shopRecipeListView->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::MinimumExpanding );
	shopRecipeListView->listView() ->setAllColumnsShowFocus( true );

	buttonBar = new QHBox( this, "buttonBar" );
	layout->addMultiCellWidget( buttonBar, 1, 1, 0, 2 );

	layout->setColStretch( 0, 1 );
	layout->setColStretch( 1, 0 );
	layout->setColStretch( 2, 1 );

	okButton = new QPushButton( buttonBar, "okButton" );
	okButton->setText( i18n( "&OK" ) );
	QPixmap pm = il.loadIcon( "ok", KIcon::NoGroup, 16 );
	okButton->setIconSet( pm );

	//buttonBar->layout()->addItem( new QSpacerItem( 10,10, QSizePolicy::MinimumExpanding, QSizePolicy::Fixed ) );

	clearButton = new QPushButton( buttonBar, "clearButton" );
	clearButton->setText( i18n( "Clear" ) );
	pm = il.loadIcon( "editclear", KIcon::NoGroup, 16 );
	clearButton->setIconSet( pm );

	//Takes care of all recipe actions and provides a popup menu to 'recipeListView'
	actionHandler = new RecipeActionsHandler( recipeListView->listView(), database, RecipeActionsHandler::ExpandAll | RecipeActionsHandler::CollapseAll );

	// Connect signals & slots
	connect( addRecipeButton, SIGNAL( clicked() ), this, SLOT( addRecipe() ) );
	connect( removeRecipeButton, SIGNAL( clicked() ), this, SLOT( removeRecipe() ) );
	connect( okButton, SIGNAL( clicked() ), this, SLOT( showShoppingList() ) );
	connect( clearButton, SIGNAL( clicked() ), this, SLOT( clear() ) );
}

ShoppingListDialog::~ShoppingListDialog()
{}

void ShoppingListDialog::createShopping( const RecipeList &rlist )
{
	clear();
	RecipeList::const_iterator it;
	for ( it = rlist.begin(); it != rlist.end(); it++ ) {
		new RecipeListItem( shopRecipeListView->listView(), shopRecipeListView->listView() ->lastItem(), *it );
	}
}

void ShoppingListDialog::reloadRecipeList( void )
{
	( ( RecipeListView* ) recipeListView->listView() ) ->reload();
}

void ShoppingListDialog::reload( void )
{
	reloadRecipeList (); // Missing: check if there's non-existing recipes in the list now, and if so, delete.
}

void ShoppingListDialog::addRecipe( void )
{
	QListViewItem * it = recipeListView->listView() ->selectedItem();
	addRecipe( it );
}

void ShoppingListDialog::addRecipe( QListViewItem *item )
{
	if ( item ) {
		if ( item->rtti() == 1000 ) {
			RecipeListItem * recipe_it = ( RecipeListItem* ) item;

			Recipe r;
			r.title = recipe_it->title();
			r.recipeID = recipe_it->recipeID();
			( void ) new RecipeListItem( shopRecipeListView->listView(), r );
		}
		else if ( item->rtti() == 1001 ) { //add everything in the category
			//do this to only iterate over children of 'item'
			QListViewItem * pEndItem = NULL;
			QListViewItem *pStartItem = item;
			do {
				if ( pStartItem->nextSibling() )
					pEndItem = pStartItem->nextSibling();
				else
					pStartItem = pStartItem->parent();
			}
			while ( pStartItem && !pEndItem );

			QListViewItemIterator list_it = QListViewItemIterator( item );
			while ( list_it.current() != pEndItem ) {
				if ( list_it.current() ->rtti() == 1000 && list_it.current() ->isVisible() ) {
					RecipeListItem * recipe_it = ( RecipeListItem* ) list_it.current();
					Recipe r;
					r.title = recipe_it->title();
					r.recipeID = recipe_it->recipeID();
					( void ) new RecipeListItem( shopRecipeListView->listView(), r );
				}
				list_it++;
			}
		}
	}
}

void ShoppingListDialog::removeRecipe( void )
{
	QListViewItem * it;
	it = shopRecipeListView->listView() ->selectedItem();
	if ( it )
		delete it;
}

void ShoppingListDialog::showShoppingList( void )
{
	// Store the recipe list in ElementList object first
	ElementList recipeList;
	RecipeListItem *it;
	for ( it = ( RecipeListItem* ) this->shopRecipeListView->listView() ->firstChild();it;it = ( RecipeListItem* ) it->nextSibling() ) {
		Element newEl;
		newEl.id = it->recipeID();
		newEl.name = it->title(); // Storing the title is not necessary, but do it just in case it's used later on
		recipeList.add( newEl ); // Note that the element is *copied*, it's not added as pointer, so it doesn't matter it's deleted
	}

	RefineShoppingListDialog refineDialog( this, database, recipeList );
	refineDialog.exec();
}

void ShoppingListDialog::addRecipeToShoppingList( int recipeID )
{
	Recipe r;
	r.title = database->recipeTitle( recipeID );
	r.recipeID = recipeID;

	new RecipeListItem( shopRecipeListView->listView(), r );
}

void ShoppingListDialog::clear()
{
	shopRecipeListView->listView() ->clear();
}

void ShoppingListDialog::slotDropped( KListView *list, QDropEvent *e, QListViewItem * /*after*/ )
{
	Recipe r;
	RecipeListItem *item = new RecipeListItem( recipeListView->listView(), r ); // needs parent, use this temporarily
	if ( !RecipeItemDrag::decode( e, *item ) ) {
		delete item;
		return ;
	}

	if ( list == shopRecipeListView->listView() ) {
		addRecipe( item );
	}
	//find and delete the item if we just dropped onto the recipe list from the shopping list
	else if ( list == recipeListView->listView() && e->source() == shopRecipeListView->listView() ) {
		QListViewItemIterator list_it = QListViewItemIterator( shopRecipeListView->listView() );
		while ( list_it.current() ) {
			if ( ( ( RecipeListItem* ) list_it.current() ) ->recipeID() == item->recipeID() ) {
				delete list_it.current();
				break;
			}
			list_it++;
		}
	}

	delete item;
	item = 0; // not needed anymore
}

#include "shoppinglistdialog.moc"
<commit_msg>Found a missing i18n().  Luckily it was an already translated phrase ;)<commit_after>/***************************************************************************
*   Copyright (C) 2003 by                                                 *
*   Unai Garro (ugarro@users.sourceforge.net)                             *
*   Cyril Bosselut (bosselut@b1project.com)                               *
*   Jason Kivlighn (mizunoami44@users.sourceforge.net)                    *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
***************************************************************************/

#include "shoppinglistdialog.h"

#include <klocale.h>
#include <kconfig.h>
#include <kdialog.h>
#include <kglobal.h>

#include "DBBackend/recipedb.h"
#include "refineshoppinglistdialog.h"
#include "datablocks/recipelist.h"
#include "widgets/recipelistview.h"
#include "recipefilter.h"
#include "recipeactionshandler.h"

/** A simple listview to accept dropping a RecipeItemDrag */
class ShoppingListView : public KListView
{
public:
	ShoppingListView( QWidget *parent ) : KListView( parent )
	{}

protected:
	bool acceptDrag( QDropEvent *event ) const
	{
		return RecipeItemDrag::canDecode( event );
	}

	QDragObject *dragObject()
	{
		RecipeListItem * item = dynamic_cast<RecipeListItem*>( selectedItem() );
		if ( item != 0 ) {

			RecipeItemDrag * obj = new RecipeItemDrag( item, this, "Recipe drag item" );
			/*const QPixmap *pm = item->pixmap(0);
			if( pm )
				obj->setPixmap( *pm );*/
			return obj;
		}
		return 0;
	}
};

ShoppingListDialog::ShoppingListDialog( QWidget *parent, RecipeDB *db ) : QWidget( parent )
{
	// Store pointer to database
	database = db;

	// Design dialog
	layout = new QGridLayout( this, 2, 2, KDialog::marginHint(), KDialog::spacingHint() );

	recipeListView = new KreListView ( this, i18n( "Full recipe list" ), true, 1 );
	layout->addWidget( recipeListView, 0, 0 );
	RecipeListView *listview = new RecipeListView( recipeListView, database );
	listview->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::MinimumExpanding );
	listview->setDragEnabled( true );
	listview->setAcceptDrops( true );
	listview->setDropVisualizer( false );
	connect( listview, SIGNAL( dropped( KListView*, QDropEvent*, QListViewItem* ) ),
	         this, SLOT( slotDropped( KListView*, QDropEvent*, QListViewItem* ) ) );
	listview->reload();
	recipeListView->setListView( listview );
	recipeListView->setCustomFilter( new RecipeFilter( recipeListView->listView() ), SLOT( filter( const QString & ) ) );
	recipeListView->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::MinimumExpanding );

	QBoxLayout* vboxl = new QVBoxLayout( this, 0, KDialog::spacingHint() );
	KIconLoader il;
	addRecipeButton = new QPushButton( this );
	addRecipeButton->setIconSet( il.loadIconSet( "forward", KIcon::Small ) );
	addRecipeButton->setFixedSize( QSize( 32, 32 ) );
	addRecipeButton->setFlat( true );
	vboxl->addWidget( addRecipeButton );

	removeRecipeButton = new QPushButton( this );
	removeRecipeButton->setIconSet( il.loadIconSet( "back", KIcon::Small ) );
	removeRecipeButton->setFixedSize( QSize( 32, 32 ) );
	removeRecipeButton->setFlat( true );
	vboxl->addWidget( removeRecipeButton );
	vboxl->addStretch();

	layout->addItem( vboxl, 0, 1 );

	shopRecipeListView = new KreListView ( this, i18n("Shopping List") );
	ShoppingListView *slistview = new ShoppingListView( shopRecipeListView );
	slistview->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::MinimumExpanding );
	slistview->setDragEnabled( true );
	slistview->setAcceptDrops( true );
	slistview->setDropVisualizer( false );
	connect( slistview, SIGNAL( dropped( KListView*, QDropEvent*, QListViewItem* ) ),
	         this, SLOT( slotDropped( KListView*, QDropEvent*, QListViewItem* ) ) );
	shopRecipeListView->setListView( slistview );
	layout->addWidget( shopRecipeListView, 0, 2 );

	shopRecipeListView->listView() ->addColumn( i18n( "Recipe Title" ) );

	KConfig *config = KGlobal::config();
	config->setGroup( "Advanced" );
	bool show_id = config->readBoolEntry( "ShowID", false );
	shopRecipeListView->listView() ->addColumn( i18n( "Id" ), show_id ? -1 : 0 );

	shopRecipeListView->listView() ->setSorting( -1 );
	shopRecipeListView->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::MinimumExpanding );
	shopRecipeListView->listView() ->setAllColumnsShowFocus( true );

	buttonBar = new QHBox( this, "buttonBar" );
	layout->addMultiCellWidget( buttonBar, 1, 1, 0, 2 );

	layout->setColStretch( 0, 1 );
	layout->setColStretch( 1, 0 );
	layout->setColStretch( 2, 1 );

	okButton = new QPushButton( buttonBar, "okButton" );
	okButton->setText( i18n( "&OK" ) );
	QPixmap pm = il.loadIcon( "ok", KIcon::NoGroup, 16 );
	okButton->setIconSet( pm );

	//buttonBar->layout()->addItem( new QSpacerItem( 10,10, QSizePolicy::MinimumExpanding, QSizePolicy::Fixed ) );

	clearButton = new QPushButton( buttonBar, "clearButton" );
	clearButton->setText( i18n( "Clear" ) );
	pm = il.loadIcon( "editclear", KIcon::NoGroup, 16 );
	clearButton->setIconSet( pm );

	//Takes care of all recipe actions and provides a popup menu to 'recipeListView'
	actionHandler = new RecipeActionsHandler( recipeListView->listView(), database, RecipeActionsHandler::ExpandAll | RecipeActionsHandler::CollapseAll );

	// Connect signals & slots
	connect( addRecipeButton, SIGNAL( clicked() ), this, SLOT( addRecipe() ) );
	connect( removeRecipeButton, SIGNAL( clicked() ), this, SLOT( removeRecipe() ) );
	connect( okButton, SIGNAL( clicked() ), this, SLOT( showShoppingList() ) );
	connect( clearButton, SIGNAL( clicked() ), this, SLOT( clear() ) );
}

ShoppingListDialog::~ShoppingListDialog()
{}

void ShoppingListDialog::createShopping( const RecipeList &rlist )
{
	clear();
	RecipeList::const_iterator it;
	for ( it = rlist.begin(); it != rlist.end(); it++ ) {
		new RecipeListItem( shopRecipeListView->listView(), shopRecipeListView->listView() ->lastItem(), *it );
	}
}

void ShoppingListDialog::reloadRecipeList( void )
{
	( ( RecipeListView* ) recipeListView->listView() ) ->reload();
}

void ShoppingListDialog::reload( void )
{
	reloadRecipeList (); // Missing: check if there's non-existing recipes in the list now, and if so, delete.
}

void ShoppingListDialog::addRecipe( void )
{
	QListViewItem * it = recipeListView->listView() ->selectedItem();
	addRecipe( it );
}

void ShoppingListDialog::addRecipe( QListViewItem *item )
{
	if ( item ) {
		if ( item->rtti() == 1000 ) {
			RecipeListItem * recipe_it = ( RecipeListItem* ) item;

			Recipe r;
			r.title = recipe_it->title();
			r.recipeID = recipe_it->recipeID();
			( void ) new RecipeListItem( shopRecipeListView->listView(), r );
		}
		else if ( item->rtti() == 1001 ) { //add everything in the category
			//do this to only iterate over children of 'item'
			QListViewItem * pEndItem = NULL;
			QListViewItem *pStartItem = item;
			do {
				if ( pStartItem->nextSibling() )
					pEndItem = pStartItem->nextSibling();
				else
					pStartItem = pStartItem->parent();
			}
			while ( pStartItem && !pEndItem );

			QListViewItemIterator list_it = QListViewItemIterator( item );
			while ( list_it.current() != pEndItem ) {
				if ( list_it.current() ->rtti() == 1000 && list_it.current() ->isVisible() ) {
					RecipeListItem * recipe_it = ( RecipeListItem* ) list_it.current();
					Recipe r;
					r.title = recipe_it->title();
					r.recipeID = recipe_it->recipeID();
					( void ) new RecipeListItem( shopRecipeListView->listView(), r );
				}
				list_it++;
			}
		}
	}
}

void ShoppingListDialog::removeRecipe( void )
{
	QListViewItem * it;
	it = shopRecipeListView->listView() ->selectedItem();
	if ( it )
		delete it;
}

void ShoppingListDialog::showShoppingList( void )
{
	// Store the recipe list in ElementList object first
	ElementList recipeList;
	RecipeListItem *it;
	for ( it = ( RecipeListItem* ) this->shopRecipeListView->listView() ->firstChild();it;it = ( RecipeListItem* ) it->nextSibling() ) {
		Element newEl;
		newEl.id = it->recipeID();
		newEl.name = it->title(); // Storing the title is not necessary, but do it just in case it's used later on
		recipeList.add( newEl ); // Note that the element is *copied*, it's not added as pointer, so it doesn't matter it's deleted
	}

	RefineShoppingListDialog refineDialog( this, database, recipeList );
	refineDialog.exec();
}

void ShoppingListDialog::addRecipeToShoppingList( int recipeID )
{
	Recipe r;
	r.title = database->recipeTitle( recipeID );
	r.recipeID = recipeID;

	new RecipeListItem( shopRecipeListView->listView(), r );
}

void ShoppingListDialog::clear()
{
	shopRecipeListView->listView() ->clear();
}

void ShoppingListDialog::slotDropped( KListView *list, QDropEvent *e, QListViewItem * /*after*/ )
{
	Recipe r;
	RecipeListItem *item = new RecipeListItem( recipeListView->listView(), r ); // needs parent, use this temporarily
	if ( !RecipeItemDrag::decode( e, *item ) ) {
		delete item;
		return ;
	}

	if ( list == shopRecipeListView->listView() ) {
		addRecipe( item );
	}
	//find and delete the item if we just dropped onto the recipe list from the shopping list
	else if ( list == recipeListView->listView() && e->source() == shopRecipeListView->listView() ) {
		QListViewItemIterator list_it = QListViewItemIterator( shopRecipeListView->listView() );
		while ( list_it.current() ) {
			if ( ( ( RecipeListItem* ) list_it.current() ) ->recipeID() == item->recipeID() ) {
				delete list_it.current();
				break;
			}
			list_it++;
		}
	}

	delete item;
	item = 0; // not needed anymore
}

#include "shoppinglistdialog.moc"
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! TODO: this is a messy set of unit tests. It maybe worth reinstating Google
//! mock in the library. We can compare easily vectors.

#include <set>

#include <gtest/gtest.h>

#include <DO/KDTree.hpp>

#include "../AssertHelpers.hpp"

using namespace DO;
using namespace std;

inline vector<int> range(int begin, int end)
{
  vector<int> _range(end-begin);
  for (int i = begin; i < end; ++i)
    _range[i-begin] = i;
  return _range;
}

inline vector<int> range(int end)
{
  return range(0, end);
}

class TestKDTree : public testing::Test
{
protected:
  MatrixXd data;
  size_t num_points;
  size_t num_points_in_circle;

  TestKDTree()
  {
    // We construct two sets in points. The first one lives in the
    // zero-centered unit circle and the second in the zero-centered
    // circle with radius 10.
    num_points_in_circle = 5;
    num_points = 2*num_points_in_circle;
    data.resize(2, num_points);

    const size_t& N = num_points_in_circle;
    for (size_t i = 0; i < N; ++i)
    {
      double theta = i / (2*N*M_PI);
      data.col(i) << cos(theta), sin(theta);
    }

    for (size_t i = N; i < 2*N; ++i)
    {
      double theta = i / (2*N*M_PI);
      data.col(i) << 10*cos(theta), 10*sin(theta);
    }
  }
};

TEST_F(TestKDTree, test_simple_radius_search)
{
  // Input data.
  KDTree tree(data);
  Vector2d query = Vector2d::Zero();
  size_t num_nearest_neighbors = num_points_in_circle;
  double squared_search_radius = 1.0001;

  // In-out data.
  vector<int> nn_indices;
  vector<double> nn_squared_distances;

  // Output data.
  int num_found_neighbors;

  // First use case: we want to examine the squared distances.
  num_found_neighbors = tree.radius_search(
    query,
    squared_search_radius,
    nn_indices,
    nn_squared_distances);

  EXPECT_EQ(nn_indices.size(), num_nearest_neighbors);
  EXPECT_EQ(num_found_neighbors, num_nearest_neighbors);
  EXPECT_ITEMS_EQ(nn_indices, range(num_points_in_circle));
  for (size_t j = 0; j < nn_indices.size(); ++j)
    EXPECT_NEAR(nn_squared_distances[j], 1., 1e-10);

  // Second use case: we want to limit the number of neighbors to return.
  size_t max_num_nearest_neighbors = 2;
  num_found_neighbors = tree.radius_search(query,
                                           squared_search_radius,
                                           nn_indices,
                                           nn_squared_distances,
                                           max_num_nearest_neighbors);
  EXPECT_EQ(nn_indices.size(), max_num_nearest_neighbors);
  EXPECT_EQ(num_found_neighbors, max_num_nearest_neighbors);
  EXPECT_ITEMS_EQ(nn_indices, range(num_points_in_circle));
  for (size_t j = 0; j < nn_indices.size(); ++j)
    EXPECT_NEAR(nn_squared_distances[j], 1., 1e-10);
}

TEST_F(TestKDTree, test_simple_radius_search_with_query_point_in_data)
{
  // Input data.
  KDTree tree(data);
  size_t query = 0;
  size_t num_nearest_neighbors = num_points_in_circle-1;
  double squared_search_radius = 2.0001;

  // In-out data.
  vector<int> nn_indices;
  vector<double> nn_squared_distances;

  // Output data.
  int num_found_neighbors;

  // First use case: we want to examine the squared distances.
  num_found_neighbors = tree.radius_search(
    query,
    squared_search_radius,
    nn_indices,
    nn_squared_distances);

  EXPECT_EQ(nn_indices.size(), num_nearest_neighbors);
  EXPECT_EQ(num_found_neighbors, num_nearest_neighbors);
  for (size_t j = 0; j < nn_indices.size(); ++j)
  {
    EXPECT_LE(nn_indices[j], num_nearest_neighbors);
    EXPECT_LE(nn_squared_distances[j], 2.);
  }

  // Second use case: we want to limit the number of neighbors to return.
  size_t max_num_nearest_neighbors = 2;
  num_found_neighbors = tree.radius_search(query,
                                           squared_search_radius,
                                           nn_indices,
                                           nn_squared_distances,
                                           max_num_nearest_neighbors);

  EXPECT_EQ(nn_indices.size(), max_num_nearest_neighbors);
  EXPECT_EQ(num_found_neighbors, max_num_nearest_neighbors);
  for (size_t j = 0; j < nn_indices.size(); ++j)
  {
    EXPECT_LE(nn_indices[j], num_nearest_neighbors);
    EXPECT_LE(nn_squared_distances[j], 2.);
  }
}

TEST_F(TestKDTree, test_batch_radius_search)
{
  // Input data.
  KDTree tree(data);
  const size_t& num_queries = num_points_in_circle;
  MatrixXd queries(data.leftCols(num_queries));
  double squared_search_radius = 2.0001;

  // In-out data.
  vector<vector<int> > nn_indices;
  vector<vector<double> > nn_squared_distances;

  // First use case: we want to examine the squared distances.
  tree.radius_search(
    queries,
    squared_search_radius,
    nn_indices,
    nn_squared_distances);

  EXPECT_EQ(nn_indices.size(), num_queries);
  for (size_t i = 0; i < num_queries; ++i)
  {
    EXPECT_EQ(nn_indices[i].size(), num_queries);
    for (size_t j = 0; j < nn_indices[i].size(); ++j)
    {
      EXPECT_LE(nn_indices[i][j], num_queries);
      EXPECT_LE(nn_squared_distances[i][j], 2.);
    }
  }

  // Second use case: we want to limit the number of neighbors to return.
  size_t max_num_nearest_neighbors = 2;
  tree.radius_search(queries, squared_search_radius, nn_indices,
                     nn_squared_distances, max_num_nearest_neighbors);

  EXPECT_EQ(nn_indices.size(), num_queries);
  for (size_t i = 0; i < num_queries; ++i)
  {
    EXPECT_EQ(nn_indices[i].size(), max_num_nearest_neighbors);
    for (size_t j = 0; j < nn_indices[i].size(); ++j)
    {
      EXPECT_LE(nn_indices[i][j], num_queries);
      EXPECT_LE(nn_squared_distances[i][j], 2.);
    }
  }
}

TEST_F(TestKDTree, test_batch_radius_search_with_query_point_in_data)
{
  // Input data.
  KDTree tree(data);
  const size_t& num_queries = num_points_in_circle;
  vector<size_t> queries;
  for (size_t i = 0; i < num_queries; ++i)
    queries.push_back(i);
  double squared_search_radius = 2.0001;

  // In-out data.
  vector<vector<int> > nn_indices;
  vector<vector<double> > nn_squared_distances;

  // First use case: we want to examine the squared distances.
  tree.radius_search(
    queries,
    squared_search_radius,
    nn_indices,
    nn_squared_distances);

  EXPECT_EQ(nn_indices.size(), num_queries);
  for (size_t i = 0; i < num_queries; ++i)
  {
    EXPECT_EQ(nn_indices[i].size(), num_queries-1);
    for (size_t j = 0; j < nn_indices[i].size(); ++j)
    {
      EXPECT_LE(nn_indices[i][j], num_queries);
      EXPECT_LE(nn_squared_distances[i][j], 2.);
    }
  }

  // Second use case: we want to limit the number of neighbors to return.
  size_t max_num_nearest_neighbors = 2;
  tree.radius_search(queries, squared_search_radius, nn_indices,
    nn_squared_distances, max_num_nearest_neighbors);

  EXPECT_EQ(nn_indices.size(), num_queries);
  for (size_t i = 0; i < num_queries; ++i)
  {
    EXPECT_EQ(nn_indices[i].size(), max_num_nearest_neighbors);
    for (size_t j = 0; j < nn_indices[i].size(); ++j)
    {
      EXPECT_LE(nn_indices[i][j], num_queries);
      EXPECT_LE(nn_squared_distances[i][j], 2.);
    }
  }
}

int main(int argc, char **argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Improved readability of tests on radius search.<commit_after>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! TODO: this is a messy set of unit tests. It maybe worth reinstating Google
//! mock in the library. We can compare easily vectors.

#include <set>

#include <gtest/gtest.h>

#include <DO/KDTree.hpp>

#include "../AssertHelpers.hpp"

using namespace DO;
using namespace std;

inline vector<int> range(int begin, int end)
{
  vector<int> _range(end-begin);
  for (int i = begin; i < end; ++i)
    _range[i-begin] = i;
  return _range;
}

inline vector<int> range(int end)
{
  return range(0, end);
}

class TestKDTree : public testing::Test
{
protected:
  MatrixXd data;
  size_t num_points;
  size_t num_points_in_each_circle;

  TestKDTree()
  {
    // We construct two sets in points. The first one lives in the
    // zero-centered unit circle and the second in the zero-centered
    // circle with radius 10.
    num_points_in_each_circle = 30;
    num_points = 2*num_points_in_each_circle;
    data.resize(2, num_points);

    const size_t& N = num_points_in_each_circle;
    for (size_t i = 0; i < N; ++i)
    {
      double theta = i / (2*N*M_PI);
      data.col(i) << 2*cos(theta), 2*sin(theta);
    }

    for (size_t i = N; i < 2*N; ++i)
    {
      double theta = i / (2*N*M_PI);
      data.col(i) << 10*cos(theta), 10*sin(theta);
    }
  }
};

TEST_F(TestKDTree, test_simple_radius_search_default_use)
{
  // Input data.
  KDTree tree(data, 1, flann::SearchParams());
  Vector2d query = Vector2d::Zero();
  cout << query << endl;

  // In-out data.
  vector<int> nn_indices;
  vector<double> nn_squared_distances;

  // Regular use case.
  size_t num_nearest_neighbors = num_points_in_each_circle;
  double squared_search_radius = 4.1;
  int num_found_neighbors = tree.radius_search(query,
                                               squared_search_radius,
                                               nn_indices,
                                               nn_squared_distances);

  // Check the number of neighbors.
  EXPECT_EQ(nn_indices.size(), num_nearest_neighbors);
  EXPECT_EQ(num_found_neighbors, num_nearest_neighbors);

  // Check the indices of the nearest neighbors.
  EXPECT_ITEMS_EQ(range(num_points_in_each_circle), nn_indices);

  // Check the squared distances.
  EXPECT_EQ(nn_squared_distances.size(), num_nearest_neighbors);
  for (size_t j = 0; j < nn_squared_distances.size(); ++j)
    EXPECT_NEAR(nn_squared_distances[j], 4., 1e-10);
}

TEST_F(TestKDTree, test_simple_radius_search_with_restricted_num_of_neighbors)
{
  // Input data.
  KDTree tree(data);
  Vector2d query = Vector2d::Zero();
  double squared_search_radius = pow(2.0001, 2);

  // In-out data.
  vector<int> nn_indices;
  vector<double> nn_squared_distances;

  // Second use case: we want to limit the number of neighbors to return.
  size_t max_num_nearest_neighbors = 2;
  int num_found_neighbors = tree.radius_search(query,
                                               squared_search_radius,
                                               nn_indices,
                                               nn_squared_distances,
                                               max_num_nearest_neighbors);

  // Check the number of nearest neighbors.
  EXPECT_EQ(nn_indices.size(), max_num_nearest_neighbors);
  EXPECT_EQ(num_found_neighbors, max_num_nearest_neighbors);

  // Check the contents of the containers.
  for (size_t j = 0; j < nn_indices.size(); ++j)
  {
    EXPECT_LT(nn_indices[j], num_points_in_each_circle);
    EXPECT_NEAR(nn_squared_distances[j], 4., 1e-10);
  }
}

TEST_F(TestKDTree,
       test_simple_radius_search_with_query_point_in_data_default)
{
  // Input data.
  KDTree tree(data);
  size_t query = 0;
  size_t num_nearest_neighbors = num_points_in_each_circle-1;
  // Squared diameter of the inner circle.
  double squared_search_radius = pow(2.0001, 2);

  // In-out data.
  vector<int> nn_indices;
  vector<double> nn_squared_distances;

  // Output data.
  int num_found_neighbors;

  // Default use case.
  num_found_neighbors = tree.radius_search(query,
                                           squared_search_radius,
                                           nn_indices,
                                           nn_squared_distances);

  // Check the number of neighbors.
  EXPECT_EQ(nn_indices.size(), num_nearest_neighbors);
  EXPECT_EQ(num_found_neighbors, num_nearest_neighbors);

  // Check the indices.
  EXPECT_ITEMS_EQ(nn_indices, range(1, num_points_in_each_circle));

  // Check the squared distances.
  for (size_t j = 0; j < nn_indices.size(); ++j)
    EXPECT_LE(nn_squared_distances[j], squared_search_radius);
}

TEST_F(TestKDTree,
       test_simple_radius_search_with_query_point_in_data_restricted)
{
  // Input data.
  KDTree tree(data);
  size_t query = 0;
  double squared_search_radius = pow(2.0001, 2);

  // In-out data.
  vector<int> nn_indices;
  vector<double> nn_squared_distances;

  // Output data.
  int num_found_neighbors;
  // Second use case: we want to limit the number of neighbors to return.
  size_t max_num_nearest_neighbors = 2;
  num_found_neighbors = tree.radius_search(query,
                                           squared_search_radius,
                                           nn_indices,
                                           nn_squared_distances,
                                           max_num_nearest_neighbors);

  // Check the number of indices.
  EXPECT_EQ(nn_indices.size(), max_num_nearest_neighbors);
  EXPECT_EQ(num_found_neighbors, max_num_nearest_neighbors);

  // Check the number of squared distances.
  EXPECT_EQ(nn_squared_distances.size(), max_num_nearest_neighbors);

  // Check the contents of the retrieval.
  for (size_t j = 0; j < nn_squared_distances.size(); ++j)
  {
    // Check the index value.
    EXPECT_NE(nn_indices[j], 0);
    EXPECT_LT(nn_indices[j], num_points_in_each_circle);

    // Check the squared distances.
    EXPECT_LE(nn_squared_distances[j], 2.);
  }
}

TEST_F(TestKDTree, test_batch_radius_search_default)
{
  // Input data.
  KDTree tree(data);
  const size_t& num_queries = num_points_in_each_circle;
  MatrixXd queries(data.leftCols(num_queries));
  double squared_search_radius = pow(1.0001, 2);

  // In-out data.
  vector<vector<int> > nn_indices;
  vector<vector<double> > nn_squared_distances;

  // Use case.
  tree.radius_search(
    queries,
    squared_search_radius,
    nn_indices,
    nn_squared_distances);

  // Check the number of queries.
  EXPECT_EQ(nn_indices.size(), num_queries);
  EXPECT_EQ(nn_squared_distances.size(), num_queries);

  // Check the content of the retrieval.
  for (size_t i = 0; i < num_queries; ++i)
  {
    EXPECT_EQ(nn_indices[i].size(), num_points_in_each_circle);
    EXPECT_ITEMS_EQ(nn_indices[i], range(num_points_in_each_circle));

    EXPECT_EQ(nn_squared_distances[i].size(), num_points_in_each_circle);
    for (size_t j = 0; j < nn_squared_distances[i].size(); ++j)
      EXPECT_LE(nn_squared_distances[i][j], squared_search_radius);
  }
}

TEST_F(TestKDTree, test_batch_radius_search_restricted)
{
  // Input data.
  KDTree tree(data);
  const size_t& num_queries = num_points_in_each_circle;
  MatrixXd queries(data.leftCols(num_queries));
  double squared_search_radius = pow(2.0001, 2);

  // In-out data.
  vector<vector<int> > nn_indices;
  vector<vector<double> > nn_squared_distances;

  // Use case.
  size_t max_num_nearest_neighbors = 2;
  tree.radius_search(queries, squared_search_radius, nn_indices,
                     nn_squared_distances, max_num_nearest_neighbors);

  // Check the number of queries.
  EXPECT_EQ(nn_indices.size(), num_queries);
  EXPECT_EQ(nn_squared_distances.size(), num_queries);

  for (size_t i = 0; i < num_queries; ++i)
  {
    EXPECT_EQ(nn_indices[i].size(), max_num_nearest_neighbors);
    EXPECT_EQ(nn_squared_distances[i].size(), max_num_nearest_neighbors);

    for (size_t j = 0; j < nn_indices[i].size(); ++j)
    {
      EXPECT_LT(nn_indices[i][j], num_points_in_each_circle);
      EXPECT_LE(nn_squared_distances[i][j], squared_search_radius);
    }
  }
}

TEST_F(TestKDTree, test_batch_radius_search_with_query_point_in_data_default)
{
  // Input data.
  KDTree tree(data);
  const size_t& num_queries = num_points_in_each_circle;
  vector<size_t> queries;
  for (size_t i = 0; i < num_queries; ++i)
    queries.push_back(i);
  double squared_search_radius = pow(2.0001, 2);

  // In-out data.
  vector<vector<int> > nn_indices;
  vector<vector<double> > nn_squared_distances;

  // Default use case.
  tree.radius_search(
    queries,
    squared_search_radius,
    nn_indices,
    nn_squared_distances);

  // Check the number of queries.
  EXPECT_EQ(nn_indices.size(), num_queries);
  EXPECT_EQ(nn_squared_distances.size(), num_queries);

  // Check the contents of the retrieval.
  for (size_t i = 0; i < num_queries; ++i)
  {
    vector<int> true_indices = range(num_points_in_each_circle);
    true_indices.erase(true_indices.begin() + i);

    // Check the indices.
    EXPECT_EQ(nn_indices[i].size(), num_points_in_each_circle-1);
    EXPECT_ITEMS_EQ(true_indices, nn_indices[i]);

    // Check the squared distances.
    for (size_t j = 0; j < nn_indices[i].size(); ++j)
      EXPECT_LE(nn_squared_distances[i][j], squared_search_radius);
  }
}

TEST_F(TestKDTree, test_batch_radius_search_with_query_point_in_data_restricted)
{
  // Input data.
  KDTree tree(data);
  const size_t& num_queries = num_points_in_each_circle;
  vector<size_t> queries;
  for (size_t i = 0; i < num_queries; ++i)
    queries.push_back(i);
  double squared_search_radius = pow(2.0001, 2);

  // In-out data.
  vector<vector<int> > nn_indices;
  vector<vector<double> > nn_squared_distances;

  // Second use case: we want to limit the number of neighbors to return.
  size_t max_num_nearest_neighbors = 2;
  tree.radius_search(queries, squared_search_radius, nn_indices,
    nn_squared_distances, max_num_nearest_neighbors);

  EXPECT_EQ(nn_indices.size(), num_queries);
  EXPECT_EQ(nn_squared_distances.size(), num_queries);
  for (size_t i = 0; i < num_queries; ++i)
  {
    EXPECT_EQ(nn_indices[i].size(), max_num_nearest_neighbors);
    EXPECT_EQ(nn_squared_distances[i].size(), max_num_nearest_neighbors);

    for (size_t j = 0; j < nn_indices[i].size(); ++j)
    {
      EXPECT_LT(nn_indices[i][j], num_points_in_each_circle);
      EXPECT_NE(nn_indices[i][j], i);
      EXPECT_LE(nn_squared_distances[i][j], squared_search_radius);
    }
  }
}

int main(int argc, char **argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling | FileCheck %s

// Checks for infinite recursion when we combine nested calls of process line
// with global initializers.

#include "cling/Interpreter/Interpreter.h"

class MyClass { public:  MyClass(){ gCling->process("gCling->getVersion()");} };

MyClass *My = new MyClass(); // CHECK: (const char *) "{{.*}}"

extern "C" int printf(const char*...);

struct S {
  S() {
    printf("Exec\n");
    gCling->process("printf(\"RecursiveExec\\n\");");
  }
} s;
// CHECK-NEXT:Exec
// CHECK-NEXT:RecursiveExec
gCling->process("int RecursiveInit = printf(\"A\\n\");");
int ForceInitSequence = 17;

// CHECK-NEXT:A

// CHECK-EMPTY:

.q
<commit_msg>Add forgotten comment as part of d7da914fa0<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling | FileCheck %s

// Checks for infinite recursion when we combine nested calls of process line
// with global initializers.

#include "cling/Interpreter/Interpreter.h"

class MyClass { public:  MyClass(){ gCling->process("gCling->getVersion()");} };

MyClass *My = new MyClass(); // CHECK: (const char *) "{{.*}}"

extern "C" int printf(const char*...);

// from https://sft.its.cern.ch/jira/browse/ROOT-5856?focusedCommentId=30869&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-30869
struct S {
  S() {
    printf("Exec\n");
    gCling->process("printf(\"RecursiveExec\\n\");");
  }
} s;
// CHECK-NEXT:Exec
// CHECK-NEXT:RecursiveExec
gCling->process("int RecursiveInit = printf(\"A\\n\");");
int ForceInitSequence = 17;

// CHECK-NEXT:A

// CHECK-EMPTY:

.q
<|endoftext|>


<commit_before>#include <string.h>
#include <stdlib.h>
#include "../xml.h"
#include "../multicron.h"
#include "../uevent.h"
#include "uevent.h"
#include "power.h"

static const char *status_text[] = {
	"Unknown", "Charging", "Discharging", "Not charging", "Full"
};
static const char *health_text[] = {
	"Unknown", "Good", "Overheat", "Dead", "Over voltage",
	"Unspecified failure", "Cold",
};
static const char *technology_text[] = {
	"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd",
	"LiMn"
};
static const char *type_text[] = { "Battery", "UPS", "Mains", "USB" };

UEvents::Power::Power() {
	name=NULL;
	//type= ?
	status=UNKNOWN_STATUS;
	technology=UNKNOWN_TECHNOLOGY;
	voltage_min_design=-1;
	voltage_now=-1;
	charge_full_design=-1;
	charge_full=-1;
	charge_now=-1;
	model_name=NULL;
	manufacturer=NULL;
	serialnum=NULL;

}

UEvents::Power::~Power() {
	Display();
	if(name)
		free(name);
	if(model_name)
		free(model_name);
	if(manufacturer)
		free(manufacturer);
	if(serialnum)
		free(serialnum);
}

void UEvents::Power::SetVar(const char *name, const char *value) {
	unsigned int i;
	if(strcmp(name, "POWER_SUPPLY_NAME")==0) {
		name=strdup(value);
	} else if(strcmp(name, "POWER_SUPPLY_TYPE")==0) {
		for(i=0;i<sizeof(type_text);i++)
			if(strcmp(type_text[i], value)==0)
				type=(UEvents::Power::power_type)i;
	} else if(strcmp(name, "POWER_SUPPLY_PRESENT")==0) {
		present=atoi(value)==1 ? true : false;
	} else if(strcmp(name, "POWER_SUPPLY_TECHNOLOGY")==0) {
		for(i=0;i<sizeof(technology_text);i++)
			if(strcmp(technology_text[i], value)==0)
				technology=(UEvents::Power::power_technology)i;
	} else if(strcmp(name, "POWER_SUPPLY_VOLTAGE_MIN_DESIGN")==0) {
		voltage_min_design=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_VOLTAGE_NOW")==0) {
		voltage_now=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_CURRENT_NOW")==0) {
		current_now=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_FULL_CHARGE_DESIGN")==0) {
		charge_full_design=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_CHARGE_FULL")==0) {
		charge_full=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_CHARGE_NOW")==0) {
		charge_now=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_MODEL_NAME")==0) {
		model_name=strdup(value);
	} else if(strcmp(name, "POWER_SUPPLY_MANUFACTURER")==0) {
		manufacturer=strdup(value);
	} else if(strcmp(name, "POWER_SUPPLY_SERIAL_NUMBER")==0) {
		serialnum=strdup(value);
	}
}

void UEvents::Power::Display() {
	printf("Battery at %f%%\n", (100.0*charge_now)/(1.0*charge_full));
}
<commit_msg>I hate merging<commit_after>#include <string.h>
#include <stdlib.h>
#include "../xml.h"
#include "../multicron.h"
#include "../uevent.h"
#include "uevent.h"
#include "power.h"

static const char *status_text[] = {
	"Unknown", "Charging", "Discharging", "Not charging", "Full"
};
static const char *health_text[] = {
	"Unknown", "Good", "Overheat", "Dead", "Over voltage",
	"Unspecified failure", "Cold",
};
static const char *technology_text[] = {
	"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd",
	"LiMn"
};
static const char *type_text[] = { "Battery", "UPS", "Mains", "USB" };

UEvents::Power::Power() {
	name=NULL;
	//type= ?
	status=UNKNOWN_STATUS;
	technology=UNKNOWN_TECHNOLOGY;
	voltage_min_design=-1;
	voltage_now=-1;
	charge_full_design=-1;
	charge_full=-1;
	charge_now=-1;
	model_name=NULL;
	manufacturer=NULL;
	serialnum=NULL;

}

UEvents::Power::~Power() {
	Display();
	if(name)
		free(name);
	if(model_name)
		free(model_name);
	if(manufacturer)
		free(manufacturer);
	if(serialnum)
		free(serialnum);
}

void UEvents::Power::SetVar(const char *name, const char *value) {
	unsigned int i;
	if(strcmp(name, "POWER_SUPPLY_NAME")==0) {
		name=strdup(value);
	} else if(strcmp(name, "POWER_SUPPLY_TYPE")==0) {
		for(i=0;i<(sizeof(type_text)/sizeof(*type_text));i++)
			if(strcmp(type_text[i], value)==0)
				type=(UEvents::Power::power_type)i;
	} else if(strcmp(name, "POWER_SUPPLY_PRESENT")==0) {
		present=atoi(value)==1 ? true : false;
	} else if(strcmp(name, "POWER_SUPPLY_TECHNOLOGY")==0) {
		for(i=0;i<(sizeof(technology_text)/sizeof(*technology_text));i++)
			if(strcmp(technology_text[i], value)==0)
				technology=(UEvents::Power::power_technology)i;
	} else if(strcmp(name, "POWER_SUPPLY_VOLTAGE_MIN_DESIGN")==0) {
		voltage_min_design=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_VOLTAGE_NOW")==0) {
		voltage_now=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_CURRENT_NOW")==0) {
		current_now=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_FULL_CHARGE_DESIGN")==0) {
		charge_full_design=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_CHARGE_FULL")==0) {
		charge_full=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_CHARGE_NOW")==0) {
		charge_now=atoi(value);
	} else if(strcmp(name, "POWER_SUPPLY_MODEL_NAME")==0) {
		model_name=strdup(value);
	} else if(strcmp(name, "POWER_SUPPLY_MANUFACTURER")==0) {
		manufacturer=strdup(value);
	} else if(strcmp(name, "POWER_SUPPLY_SERIAL_NUMBER")==0) {
		serialnum=strdup(value);
	}
}

void UEvents::Power::Display() {
	printf("Battery at %f%%\n", (100.0*charge_now)/(1.0*charge_full));
}
<|endoftext|>


<commit_before>/*
 * Copyright deipi.com LLC and contributors. All rights reserved.
 *
 * 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.
 */

#include "TypesFieldProcessor.h"
#include <xapian/query.h>

NumericFieldProcessor::NumericFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query
NumericFieldProcessor::operator()(const std::string &str)
{
	LOG(this, "Numeric FP %s!!\n", str.c_str());
	std::string serialise = serialise_numeric(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand numeric specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

LatLongFieldProcessor::LatLongFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query
LatLongFieldProcessor::operator()(const std::string &str)
{
	LOG(NULL, "LatLong FP!!\n");
	std::string serialise = serialise_geo(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand LatLongs specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

LatLongDistanceFieldProcessor::LatLongDistanceFieldProcessor(std::string prefix_, std::string field_): prefix(prefix_), field(field_) {}
Xapian::Query
LatLongDistanceFieldProcessor::operator()(const std::string &str)
{
	LOG(this,"Inside of LatLongDistanceFieldProcessor %s\n", str.c_str());
	Xapian::LatLongCoords coords;
	if (get_coords(str, coords_) == 0) {
		LOG(this,"longitud %f latitud %f max_range %f\n", coords_[0],coords_[1], coords_[2]);
		Xapian::LatLongCoord centre(coords_[0], coords_[1]);
		coords_[2] = Xapian::miles_to_metres(coords_[2]);
		Xapian::GreatCircleMetric metric;
		//Use get_slot in 0
		Xapian::LatLongDistancePostingSource ps(get_slot(field), centre, metric, coords_[2]);
		return Xapian::Query(&ps);
	}
	throw Xapian::QueryParserError("LatLongDistanceFieldProcessor Didn't understand %s",str.c_str());
}

BooleanFieldProcessor::BooleanFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query BooleanFieldProcessor::operator()(const std::string &str)
{
	LOG(NULL, "Boolean FP!!\n");
	std::string serialise = serialise_bool(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand bool specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

DateFieldProcessor::DateFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query DateFieldProcessor::operator()(const std::string &str)
{
	LOG(NULL, "Date FP!!\n");
	std::string serialise = serialise_date(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand date specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

DateTimeValueRangeProcessor::DateTimeValueRangeProcessor(Xapian::valueno slot_, std::string prefix_): valno(slot_), prefix(prefix_) {}
Xapian::valueno
DateTimeValueRangeProcessor::operator()(std::string &begin, std::string &end)
{
	std::string buf;
	LOG(this,"Inside of DateTimeValueRangeProcessor\n");

	if(begin.size() != 0) {
		buf = prefix + serialise_date(begin);
		if(buf != "") {
			begin.assign(buf.c_str(), buf.size());
			LOG(this,"serialise of begin %s\n",buf.c_str());
		}
		else return Xapian::BAD_VALUENO;
	}
	buf = "";

	if(end.size() != 0) {
		buf = prefix + serialise_date(end);
		if(buf != "") {
			end.assign(buf.c_str(), buf.size());
			LOG(this,"serialise of end %s\n",std::string(prefix + buf).c_str());
		}
		else return Xapian::BAD_VALUENO;
	}
	return valno;
}<commit_msg>Added include in fields.cc<commit_after>/*
 * Copyright deipi.com LLC and contributors. All rights reserved.
 *
 * 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.
 */

#include "fields.h"
#include <xapian/query.h>

NumericFieldProcessor::NumericFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query
NumericFieldProcessor::operator()(const std::string &str)
{
	LOG(this, "Numeric FP %s!!\n", str.c_str());
	std::string serialise = serialise_numeric(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand numeric specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

LatLongFieldProcessor::LatLongFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query
LatLongFieldProcessor::operator()(const std::string &str)
{
	LOG(NULL, "LatLong FP!!\n");
	std::string serialise = serialise_geo(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand LatLongs specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

LatLongDistanceFieldProcessor::LatLongDistanceFieldProcessor(std::string prefix_, std::string field_): prefix(prefix_), field(field_) {}
Xapian::Query
LatLongDistanceFieldProcessor::operator()(const std::string &str)
{
	LOG(this,"Inside of LatLongDistanceFieldProcessor %s\n", str.c_str());
	Xapian::LatLongCoords coords;
	if (get_coords(str, coords_) == 0) {
		LOG(this,"longitud %f latitud %f max_range %f\n", coords_[0],coords_[1], coords_[2]);
		Xapian::LatLongCoord centre(coords_[0], coords_[1]);
		coords_[2] = Xapian::miles_to_metres(coords_[2]);
		Xapian::GreatCircleMetric metric;
		//Use get_slot in 0
		Xapian::LatLongDistancePostingSource ps(get_slot(field), centre, metric, coords_[2]);
		return Xapian::Query(&ps);
	}
	throw Xapian::QueryParserError("LatLongDistanceFieldProcessor Didn't understand %s",str.c_str());
}

BooleanFieldProcessor::BooleanFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query BooleanFieldProcessor::operator()(const std::string &str)
{
	LOG(NULL, "Boolean FP!!\n");
	std::string serialise = serialise_bool(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand bool specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

DateFieldProcessor::DateFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query DateFieldProcessor::operator()(const std::string &str)
{
	LOG(NULL, "Date FP!!\n");
	std::string serialise = serialise_date(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand date specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

DateTimeValueRangeProcessor::DateTimeValueRangeProcessor(Xapian::valueno slot_, std::string prefix_): valno(slot_), prefix(prefix_) {}
Xapian::valueno
DateTimeValueRangeProcessor::operator()(std::string &begin, std::string &end)
{
	std::string buf;
	LOG(this,"Inside of DateTimeValueRangeProcessor\n");

	if(begin.size() != 0) {
		buf = prefix + serialise_date(begin);
		if(buf != "") {
			begin.assign(buf.c_str(), buf.size());
			LOG(this,"serialise of begin %s\n",buf.c_str());
		}
		else return Xapian::BAD_VALUENO;
	}
	buf = "";

	if(end.size() != 0) {
		buf = prefix + serialise_date(end);
		if(buf != "") {
			end.assign(buf.c_str(), buf.size());
			LOG(this,"serialise of end %s\n",std::string(prefix + buf).c_str());
		}
		else return Xapian::BAD_VALUENO;
	}
	return valno;
}<|endoftext|>


<commit_before>/* fs_utils.cc
   Wolfgang Sourdeau, February 2014
   Copyright (c) 2014 Datacratic.  All rights reserved.

   A set of file-system abstraction functions intended to support common
   operations among different fs types or alikes.
*/

#include <memory>
#include <map>

#include "fs_utils.h"

using namespace std;
using namespace Datacratic;

namespace {

/* registry */

map<string, UrlFsHandler *> registry;

/* LOCALURLFSHANDLER */

struct LocalUrlFsHandler : public UrlFsHandler {
    virtual UrlInfo getInfo(const Url & url)
    {
        UrlInfo urlInfo;
        struct stat stats;
        string path = url.path();
        int res = ::stat(path.c_str(), &stats);
        if (res == -1) {
            throw ML::Exception(errno, "stat");
        }

        urlInfo.exists = true;
        urlInfo.lastModified = Date::fromTimespec(stats.st_mtim);
        urlInfo.size = stats.st_size;

        return urlInfo;
    }

    virtual void makeDirectory(const Url & url)
    {
        string path = url.path();
        int res = ::mkdir(path.c_str(), 0777);
        if (res == -1) {
            throw ML::Exception(errno, "mkdir");
        }
    }

    virtual void erase(const Url & url)
    {
        string path = url.path();
        int res = ::unlink(path.c_str());
        if (res == -1) {
            throw ML::Exception(errno, "unlink");
        }
    }
};

UrlFsHandler * findFsHandler(const string & scheme)
{
    auto handler = registry.find(scheme);
    if (handler == registry.end()) {
        throw ML::Exception("no handler found for scheme: " + scheme);
    }
    return handler->second;
}

struct AtInit {
    AtInit() {
        registerUrlFsHandler("file", new LocalUrlFsHandler());
    }
} atInit;

/* ensures that local filenames are represented as urls */
Url makeUrl(const string & urlStr)
{
    if (urlStr[0] == '/') {
        return Url("file://" + urlStr);
    }
    else {
        return Url(urlStr);
    }
}

}

namespace Datacratic {

/* URLFSHANDLER */

size_t
UrlFsHandler::
getSize(const Url & url)
{
    return getInfo(url).size;
}

string
UrlFsHandler::
getEtag(const Url & url)
{
    return getInfo(url).etag;
}

/* registry */

void registerUrlFsHandler(const std::string & scheme,
                          UrlFsHandler * handler)
{
    if (registry.find(scheme) != registry.end()) {
        throw ML::Exception("fs handler already registered");
    }
    registry[scheme] = handler;
}

UrlInfo
getUriObjectInfo(const std::string & url)
{
    Url realUrl = makeUrl(url);
    return findFsHandler(realUrl.scheme())->getInfo(realUrl);
}

UrlInfo
tryGetUriObjectInfo(const std::string & url)
{
    try {
        return getUriObjectInfo(url);
    }
    catch (...) {
        return UrlInfo();
    }
}

size_t
getUriSize(const std::string & url)
{
    Url realUrl = makeUrl(url);
    return findFsHandler(realUrl.scheme())->getSize(realUrl);
}

std::string
getUriEtag(const std::string & url)
{
    Url realUrl = makeUrl(url);
    return findFsHandler(realUrl.scheme())->getEtag(realUrl);
}

void
makeUriDirectory(const std::string & url)
{
    Url realUrl = makeUrl(url);
    findFsHandler(realUrl.scheme())->makeDirectory(realUrl);
}

void
eraseUriObject(const std::string & url)
{
    Url realUrl = makeUrl(url);
    findFsHandler(realUrl.scheme())->erase(realUrl);
}

bool
tryEraseUriObject(const std::string & uri)
{
    bool result(true);

    try {
        eraseUriObject(uri);
    }
    catch (...) {
        result = false;
    }

    return result;
}

}
<commit_msg>local version of makeDirectory uses boost::fs::create_directories<commit_after>/* fs_utils.cc
   Wolfgang Sourdeau, February 2014
   Copyright (c) 2014 Datacratic.  All rights reserved.

   A set of file-system abstraction functions intended to support common
   operations among different fs types or alikes.
*/

#include <memory>
#include <map>

#include "boost/filesystem.hpp"

#include "fs_utils.h"

using namespace std;
using namespace Datacratic;
namespace fs = boost::filesystem;

namespace {

/* registry */

map<string, UrlFsHandler *> registry;

/* LOCALURLFSHANDLER */

struct LocalUrlFsHandler : public UrlFsHandler {
    virtual UrlInfo getInfo(const Url & url)
    {
        UrlInfo urlInfo;
        struct stat stats;
        string path = url.path();
        int res = ::stat(path.c_str(), &stats);
        if (res == -1) {
            throw ML::Exception(errno, "stat");
        }

        urlInfo.exists = true;
        urlInfo.lastModified = Date::fromTimespec(stats.st_mtim);
        urlInfo.size = stats.st_size;

        return urlInfo;
    }

    virtual void makeDirectory(const Url & url)
    {
        boost::system::error_code ec;
        string path = url.path();
        if (!fs::create_directories(path, ec)) {
            throw ML::Exception(ec.message());
        }
    }

    virtual void erase(const Url & url)
    {
        string path = url.path();
        int res = ::unlink(path.c_str());
        if (res == -1) {
            throw ML::Exception(errno, "unlink");
        }
    }
};

UrlFsHandler * findFsHandler(const string & scheme)
{
    auto handler = registry.find(scheme);
    if (handler == registry.end()) {
        throw ML::Exception("no handler found for scheme: " + scheme);
    }
    return handler->second;
}

struct AtInit {
    AtInit() {
        registerUrlFsHandler("file", new LocalUrlFsHandler());
    }
} atInit;

/* ensures that local filenames are represented as urls */
Url makeUrl(const string & urlStr)
{
    if (urlStr[0] == '/') {
        return Url("file://" + urlStr);
    }
    else {
        return Url(urlStr);
    }
}

}

namespace Datacratic {

/* URLFSHANDLER */

size_t
UrlFsHandler::
getSize(const Url & url)
{
    return getInfo(url).size;
}

string
UrlFsHandler::
getEtag(const Url & url)
{
    return getInfo(url).etag;
}

/* registry */

void registerUrlFsHandler(const std::string & scheme,
                          UrlFsHandler * handler)
{
    if (registry.find(scheme) != registry.end()) {
        throw ML::Exception("fs handler already registered");
    }
    registry[scheme] = handler;
}

UrlInfo
getUriObjectInfo(const std::string & url)
{
    Url realUrl = makeUrl(url);
    return findFsHandler(realUrl.scheme())->getInfo(realUrl);
}

UrlInfo
tryGetUriObjectInfo(const std::string & url)
{
    try {
        return getUriObjectInfo(url);
    }
    catch (...) {
        return UrlInfo();
    }
}

size_t
getUriSize(const std::string & url)
{
    Url realUrl = makeUrl(url);
    return findFsHandler(realUrl.scheme())->getSize(realUrl);
}

std::string
getUriEtag(const std::string & url)
{
    Url realUrl = makeUrl(url);
    return findFsHandler(realUrl.scheme())->getEtag(realUrl);
}

void
makeUriDirectory(const std::string & url)
{
    Url realUrl = makeUrl(url);
    findFsHandler(realUrl.scheme())->makeDirectory(realUrl);
}

void
eraseUriObject(const std::string & url)
{
    Url realUrl = makeUrl(url);
    findFsHandler(realUrl.scheme())->erase(realUrl);
}

bool
tryEraseUriObject(const std::string & uri)
{
    bool result(true);

    try {
        eraseUriObject(uri);
    }
    catch (...) {
        result = false;
    }

    return result;
}

}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

#include "grins_config.h"

// GRINS
#include "grins/mesh_builder.h"
#include "grins/simulation.h"
#include "grins/simulation_builder.h"
#include "grins/multiphysics_sys.h"

//libMesh
#include "libmesh/exact_solution.h"

void test_error_norm( libMesh::ExactSolution& exact_sol,
                      const std::string& system_name,
                      const std::string& var,
                      const std::string& norm,
                      const double tol,
                      int& return_flag );

int main(int argc, char* argv[])
{
  GetPot command_line(argc,argv);

  if( !command_line.have_variable("input") )
    {
      std::cerr << "ERROR: Must specify input file on command line with input=<file>." << std::endl;
      exit(1);
    }

  if( !command_line.have_variable("soln-data") )
    {
      std::cerr << "ERROR: Must specify solution data on command line with soln-data=<file>." << std::endl;
      exit(1);
    }

  if( !command_line.have_variable("vars") )
    {
      std::cerr << "ERROR: Must specify variables on command line with vars='var1 var2'" << std::endl;
      exit(1);
    }

  if( !command_line.have_variable("norms") )
    {
      std::cerr << "ERROR: Must specify variables on command line with norms='L2 H1'" << std::endl;
      exit(1);
    }

  // libMesh input file should be first argument
  std::string libMesh_input_filename = command_line("input", "DIE!");

  {
    std::ifstream i(libMesh_input_filename.c_str());
    if (!i)
      {
        std::cerr << "Error: Could not read from libMesh input file "
                << libMesh_input_filename << std::endl;
        exit(1);
      }
  }

  // Create our GetPot object.
  GetPot libMesh_inputfile( libMesh_input_filename );

  // Initialize libMesh library.
  libMesh::LibMeshInit libmesh_init(argc, argv);

  GRINS::SimulationBuilder sim_builder;

  GRINS::Simulation grins( libMesh_inputfile,
			   sim_builder,
                           libmesh_init.comm() );

  // Do solve here
  grins.run();

  // Get equation systems to create ExactSolution object
  std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system();

   // Create Exact solution object and attach exact solution quantities
  libMesh::ExactSolution exact_sol(*es);

  libMesh::EquationSystems es_ref( es->get_mesh() );

  // Filename of file where comparison solution is stashed
  std::string solution_file = command_line("soln-data", "DIE!");
  es_ref.read( solution_file );

  exact_sol.attach_reference_solution( &es_ref );

  // Now grab the variables for which we want to compare
  unsigned int n_vars = command_line.vector_variable_size("vars");
  std::vector<std::string> vars(n_vars);
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      vars[v] = command_line("vars", "DIE!", v);
    }

  // Now grab the norms to compute for each variable error
  unsigned int n_norms = command_line.vector_variable_size("norms");
  std::vector<std::string> norms(n_norms);
  for( unsigned int n = 0; n < n_norms; n++ )
    {
      norms[n] = command_line("norms", "DIE!", n);
      if( norms[n] != std::string("L2") &&
          norms[n] != std::string("H1") )
        {
          std::cerr << "ERROR: Invalid norm input " << norms[n] << std::endl
                    << "       Valid values are: L2" << std::endl
                    << "                         H1" << std::endl;
        }
    }

  const std::string& system_name = grins.get_multiphysics_system_name();

  // Now compute error for each variable
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      exact_sol.compute_error(system_name, vars[v]);
    }

  int return_flag = 0;

  double tol = 1.0e-10;

  // Now test error for each variable, for each norm
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      for( unsigned int n = 0; n < n_norms; n++ )
        {
          test_error_norm( exact_sol, system_name, vars[v], norms[n], tol, return_flag );
        }
    }

  return return_flag;
}

void test_error_norm( libMesh::ExactSolution& exact_sol,
                      const std::string& system_name,
                      const std::string& var,
                      const std::string& norm,
                      const double tol,
                      int& return_flag )
{
  // We don't set return_flag unless we are setting it 1
  // since this function gets called multiple times and we don't
  // want to overwrite a previous "fail" (return_flag = 1) with
  // a "pass" (return_flag = 0)

  double error = 0.0;

  if( norm == std::string("L2") )
    {
      error = exact_sol.l2_error(system_name, var);
    }
  else if( norm == std::string("H1") )
    {
      error = exact_sol.h1_error(system_name, var);
    }
  else
    {
      std::cerr << "ERROR: Invalid norm " << norm << std::endl;
      exit(1);
    }

  if( error > tol )
    {
      return_flag = 1;

      std::cerr << "Tolerance exceeded for generic regression test!" << std::endl
                << "tolerance     = " << tol << std::endl
                << "norm of error = " << error << std::endl
                << "norm type     = " << norm << std::endl
                << "var           = " << var << std::endl;
    }

  return;
}
<commit_msg>A little more verbose on the test<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

#include "grins_config.h"

// GRINS
#include "grins/mesh_builder.h"
#include "grins/simulation.h"
#include "grins/simulation_builder.h"
#include "grins/multiphysics_sys.h"

//libMesh
#include "libmesh/exact_solution.h"

void test_error_norm( libMesh::ExactSolution& exact_sol,
                      const std::string& system_name,
                      const std::string& var,
                      const std::string& norm,
                      const double tol,
                      int& return_flag );

int main(int argc, char* argv[])
{
  GetPot command_line(argc,argv);

  if( !command_line.have_variable("input") )
    {
      std::cerr << "ERROR: Must specify input file on command line with input=<file>." << std::endl;
      exit(1);
    }

  if( !command_line.have_variable("soln-data") )
    {
      std::cerr << "ERROR: Must specify solution data on command line with soln-data=<file>." << std::endl;
      exit(1);
    }

  if( !command_line.have_variable("vars") )
    {
      std::cerr << "ERROR: Must specify variables on command line with vars='var1 var2'" << std::endl;
      exit(1);
    }

  if( !command_line.have_variable("norms") )
    {
      std::cerr << "ERROR: Must specify variables on command line with norms='L2 H1'" << std::endl;
      exit(1);
    }

  // libMesh input file should be first argument
  std::string libMesh_input_filename = command_line("input", "DIE!");

  {
    std::ifstream i(libMesh_input_filename.c_str());
    if (!i)
      {
        std::cerr << "Error: Could not read from libMesh input file "
                << libMesh_input_filename << std::endl;
        exit(1);
      }
  }

  // Create our GetPot object.
  GetPot libMesh_inputfile( libMesh_input_filename );

  // Initialize libMesh library.
  libMesh::LibMeshInit libmesh_init(argc, argv);

  GRINS::SimulationBuilder sim_builder;

  GRINS::Simulation grins( libMesh_inputfile,
			   sim_builder,
                           libmesh_init.comm() );

  // Do solve here
  grins.run();

  // Get equation systems to create ExactSolution object
  std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system();

   // Create Exact solution object and attach exact solution quantities
  libMesh::ExactSolution exact_sol(*es);

  libMesh::EquationSystems es_ref( es->get_mesh() );

  // Filename of file where comparison solution is stashed
  std::string solution_file = command_line("soln-data", "DIE!");
  es_ref.read( solution_file );

  exact_sol.attach_reference_solution( &es_ref );

  // Now grab the variables for which we want to compare
  unsigned int n_vars = command_line.vector_variable_size("vars");
  std::vector<std::string> vars(n_vars);
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      vars[v] = command_line("vars", "DIE!", v);
    }

  // Now grab the norms to compute for each variable error
  unsigned int n_norms = command_line.vector_variable_size("norms");
  std::vector<std::string> norms(n_norms);
  for( unsigned int n = 0; n < n_norms; n++ )
    {
      norms[n] = command_line("norms", "DIE!", n);
      if( norms[n] != std::string("L2") &&
          norms[n] != std::string("H1") )
        {
          std::cerr << "ERROR: Invalid norm input " << norms[n] << std::endl
                    << "       Valid values are: L2" << std::endl
                    << "                         H1" << std::endl;
        }
    }

  const std::string& system_name = grins.get_multiphysics_system_name();

  // Now compute error for each variable
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      exact_sol.compute_error(system_name, vars[v]);
    }

  int return_flag = 0;

  double tol = 1.0e-10;

  // Now test error for each variable, for each norm
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      for( unsigned int n = 0; n < n_norms; n++ )
        {
          test_error_norm( exact_sol, system_name, vars[v], norms[n], tol, return_flag );
        }
    }

  return return_flag;
}

void test_error_norm( libMesh::ExactSolution& exact_sol,
                      const std::string& system_name,
                      const std::string& var,
                      const std::string& norm,
                      const double tol,
                      int& return_flag )
{
  // We don't set return_flag unless we are setting it 1
  // since this function gets called multiple times and we don't
  // want to overwrite a previous "fail" (return_flag = 1) with
  // a "pass" (return_flag = 0)

  double error = 0.0;

  std::cout << "==========================================================" << std::endl
            << "Checking variable " << var << " using error norm " << norm << " with tol " << tol << "...";

  if( norm == std::string("L2") )
    {
      error = exact_sol.l2_error(system_name, var);
    }
  else if( norm == std::string("H1") )
    {
      error = exact_sol.h1_error(system_name, var);
    }
  else
    {
      std::cerr << "ERROR: Invalid norm " << norm << std::endl;
      exit(1);
    }

  if( error > tol )
    {
      return_flag = 1;

      std::cerr << "Tolerance exceeded for generic regression test!" << std::endl
                << "tolerance     = " << tol << std::endl
                << "norm of error = " << error << std::endl
                << "norm type     = " << norm << std::endl
                << "var           = " << var << std::endl;
    }
  else
    {
      std::cout << "PASSED!" << std::endl
                << "==========================================================" << std::endl;
    }

  return;
}
<|endoftext|>


<commit_before>/*

   nsjail
   -----------------------------------------

   Copyright 2014 Google Inc. All Rights Reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*/

#include "nsjail.h"

#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>

#include "cmdline.h"
#include "logs.h"
#include "macros.h"
#include "net.h"
#include "sandbox.h"
#include "subproc.h"
#include "util.h"

namespace nsjail {

static __thread int sigFatal = 0;
static __thread bool showProc = false;

static void sigHandler(int sig) {
	if (sig == SIGALRM) {
		return;
	}
	if (sig == SIGCHLD) {
		return;
	}
	if (sig == SIGUSR1 || sig == SIGQUIT) {
		showProc = true;
		return;
	}
	sigFatal = sig;
}

static bool setSigHandler(int sig) {
	LOG_D("Setting sighandler for signal %s (%d)", util::sigName(sig).c_str(), sig);

	sigset_t smask;
	sigemptyset(&smask);

	struct sigaction sa;
	sa.sa_handler = sigHandler;
	sa.sa_mask = smask;
	sa.sa_flags = 0;
	sa.sa_restorer = NULL;

	if (sig == SIGTTIN || sig == SIGTTOU) {
		sa.sa_handler = SIG_IGN;
	};
	if (sigaction(sig, &sa, NULL) == -1) {
		PLOG_E("sigaction(%d)", sig);
		return false;
	}
	return true;
}

static bool setSigHandlers(void) {
	for (const auto& i : nssigs) {
		if (!setSigHandler(i)) {
			return false;
		}
	}
	return true;
}

static bool setTimer(nsjconf_t* nsjconf) {
	if (nsjconf->mode == MODE_STANDALONE_EXECVE) {
		return true;
	}

	struct itimerval it = {
	    .it_interval =
		{
		    .tv_sec = 1,
		    .tv_usec = 0,
		},
	    .it_value =
		{
		    .tv_sec = 1,
		    .tv_usec = 0,
		},
	};
	if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
		PLOG_E("setitimer(ITIMER_REAL)");
		return false;
	}
	return true;
}

static int listenMode(nsjconf_t* nsjconf) {
	int listenfd = net::getRecvSocket(nsjconf->bindhost.c_str(), nsjconf->port);
	if (listenfd == -1) {
		return EXIT_FAILURE;
	}
	for (;;) {
		if (sigFatal > 0) {
			subproc::killAll(nsjconf);
			logs::logStop(sigFatal);
			close(listenfd);
			return EXIT_SUCCESS;
		}
		if (showProc) {
			showProc = false;
			subproc::displayProc(nsjconf);
		}
		int connfd = net::acceptConn(listenfd);
		if (connfd >= 0) {
			subproc::runChild(nsjconf, connfd, connfd, connfd);
			close(connfd);
		}
		subproc::reapProc(nsjconf);
	}
}

static int standaloneMode(nsjconf_t* nsjconf) {
	subproc::runChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
	for (;;) {
		int child_status = subproc::reapProc(nsjconf);

		if (subproc::countProc(nsjconf) == 0) {
			if (nsjconf->mode == MODE_STANDALONE_ONCE) {
				return child_status;
			}
			subproc::runChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
			continue;
		}
		if (showProc) {
			showProc = false;
			subproc::displayProc(nsjconf);
		}
		if (sigFatal > 0) {
			subproc::killAll(nsjconf);
			logs::logStop(sigFatal);
			return (128 + sigFatal);
		}

		pause();
	}
	// not reached
}

std::unique_ptr<struct termios> getTC(int fd) {
	std::unique_ptr<struct termios> trm(new struct termios);

	if (ioctl(fd, TCGETS, trm.get()) == -1) {
		PLOG_D("ioctl(fd=%d, TCGETS) failed", fd);
		return nullptr;
	}
	LOG_D("Saved the current state of the TTY");
	return trm;
}

void setTC(int fd, const struct termios* trm) {
	if (!trm) {
		return;
	}
	if (ioctl(fd, TCSETS, trm) == -1) {
		PLOG_W("ioctl(fd=%d, TCSETS) failed", fd);
		return;
	}
	LOG_D("Restored the previous state of the TTY");
}

}  // namespace nsjail

int main(int argc, char* argv[]) {
	std::unique_ptr<nsjconf_t> nsjconf = cmdline::parseArgs(argc, argv);
	std::unique_ptr<struct termios> trm = nsjail::getTC(STDIN_FILENO);

	if (!nsjconf) {
		LOG_F("Couldn't parse cmdline options");
	}
	if (!nsjconf->clone_newuser && geteuid() != 0) {
		LOG_W("--disable_clone_newuser might require root() privs");
	}
	if (nsjconf->daemonize && (daemon(0, 0) == -1)) {
		PLOG_F("daemon");
	}
	cmdline::logParams(nsjconf.get());
	if (!nsjail::setSigHandlers()) {
		LOG_F("nsjail::setSigHandlers() failed");
	}
	if (!nsjail::setTimer(nsjconf.get())) {
		LOG_F("nsjail::setTimer() failed");
	}
	if (!sandbox::preparePolicy(nsjconf.get())) {
		LOG_F("Couldn't prepare sandboxing policy");
	}

	int ret = 0;
	if (nsjconf->mode == MODE_LISTEN_TCP) {
		ret = nsjail::listenMode(nsjconf.get());
	} else {
		ret = nsjail::standaloneMode(nsjconf.get());
	}

	sandbox::closePolicy(nsjconf.get());
	/* Try to restore the underlying console's params in case some program has changed it */
	nsjail::setTC(STDIN_FILENO, trm.get());

	return ret;
}
<commit_msg>nsjail: more debug messages<commit_after>/*

   nsjail
   -----------------------------------------

   Copyright 2014 Google Inc. All Rights Reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*/

#include "nsjail.h"

#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>

#include <memory>

#include "cmdline.h"
#include "logs.h"
#include "macros.h"
#include "net.h"
#include "sandbox.h"
#include "subproc.h"
#include "util.h"

namespace nsjail {

static __thread int sigFatal = 0;
static __thread bool showProc = false;

static void sigHandler(int sig) {
	if (sig == SIGALRM) {
		return;
	}
	if (sig == SIGCHLD) {
		return;
	}
	if (sig == SIGUSR1 || sig == SIGQUIT) {
		showProc = true;
		return;
	}
	sigFatal = sig;
}

static bool setSigHandler(int sig) {
	LOG_D("Setting sighandler for signal %s (%d)", util::sigName(sig).c_str(), sig);

	sigset_t smask;
	sigemptyset(&smask);

	struct sigaction sa;
	sa.sa_handler = sigHandler;
	sa.sa_mask = smask;
	sa.sa_flags = 0;
	sa.sa_restorer = NULL;

	if (sig == SIGTTIN || sig == SIGTTOU) {
		sa.sa_handler = SIG_IGN;
	};
	if (sigaction(sig, &sa, NULL) == -1) {
		PLOG_E("sigaction(%d)", sig);
		return false;
	}
	return true;
}

static bool setSigHandlers(void) {
	for (const auto& i : nssigs) {
		if (!setSigHandler(i)) {
			return false;
		}
	}
	return true;
}

static bool setTimer(nsjconf_t* nsjconf) {
	if (nsjconf->mode == MODE_STANDALONE_EXECVE) {
		return true;
	}

	struct itimerval it = {
	    .it_interval =
		{
		    .tv_sec = 1,
		    .tv_usec = 0,
		},
	    .it_value =
		{
		    .tv_sec = 1,
		    .tv_usec = 0,
		},
	};
	if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
		PLOG_E("setitimer(ITIMER_REAL)");
		return false;
	}
	return true;
}

static int listenMode(nsjconf_t* nsjconf) {
	int listenfd = net::getRecvSocket(nsjconf->bindhost.c_str(), nsjconf->port);
	if (listenfd == -1) {
		return EXIT_FAILURE;
	}
	for (;;) {
		if (sigFatal > 0) {
			subproc::killAll(nsjconf);
			logs::logStop(sigFatal);
			close(listenfd);
			return EXIT_SUCCESS;
		}
		if (showProc) {
			showProc = false;
			subproc::displayProc(nsjconf);
		}
		int connfd = net::acceptConn(listenfd);
		if (connfd >= 0) {
			subproc::runChild(nsjconf, connfd, connfd, connfd);
			close(connfd);
		}
		subproc::reapProc(nsjconf);
	}
}

static int standaloneMode(nsjconf_t* nsjconf) {
	subproc::runChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
	for (;;) {
		int child_status = subproc::reapProc(nsjconf);

		if (subproc::countProc(nsjconf) == 0) {
			if (nsjconf->mode == MODE_STANDALONE_ONCE) {
				return child_status;
			}
			subproc::runChild(nsjconf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
			continue;
		}
		if (showProc) {
			showProc = false;
			subproc::displayProc(nsjconf);
		}
		if (sigFatal > 0) {
			subproc::killAll(nsjconf);
			logs::logStop(sigFatal);
			return (128 + sigFatal);
		}

		pause();
	}
	// not reached
}

std::unique_ptr<struct termios> getTC(int fd) {
	std::unique_ptr<struct termios> trm(new struct termios);

	if (ioctl(fd, TCGETS, trm.get()) == -1) {
		PLOG_D("ioctl(fd=%d, TCGETS) failed", fd);
		return nullptr;
	}
	LOG_D("Saved the current state of the TTY");
	return trm;
}

void setTC(int fd, const struct termios* trm) {
	if (!trm) {
		return;
	}
	if (ioctl(fd, TCSETS, trm) == -1) {
		PLOG_W("ioctl(fd=%d, TCSETS) failed", fd);
		return;
	}
	LOG_D("Restored the previous state of the TTY");
}

}  // namespace nsjail

int main(int argc, char* argv[]) {
	std::unique_ptr<nsjconf_t> nsjconf = cmdline::parseArgs(argc, argv);
	std::unique_ptr<struct termios> trm = nsjail::getTC(STDIN_FILENO);

	if (!nsjconf) {
		LOG_F("Couldn't parse cmdline options");
	}
	if (!nsjconf->clone_newuser && geteuid() != 0) {
		LOG_W("--disable_clone_newuser might require root() privs");
	}
	if (nsjconf->daemonize && (daemon(0, 0) == -1)) {
		PLOG_F("daemon");
	}
	cmdline::logParams(nsjconf.get());
	if (!nsjail::setSigHandlers()) {
		LOG_F("nsjail::setSigHandlers() failed");
	}
	if (!nsjail::setTimer(nsjconf.get())) {
		LOG_F("nsjail::setTimer() failed");
	}
	if (!sandbox::preparePolicy(nsjconf.get())) {
		LOG_F("Couldn't prepare sandboxing policy");
	}

	int ret = 0;
	if (nsjconf->mode == MODE_LISTEN_TCP) {
		ret = nsjail::listenMode(nsjconf.get());
	} else {
		ret = nsjail::standaloneMode(nsjconf.get());
	}

	sandbox::closePolicy(nsjconf.get());
	/* Try to restore the underlying console's params in case some program has changed it */
	nsjail::setTC(STDIN_FILENO, trm.get());

	LOG_D("Returning with %d", ret);
	return ret;
}
<|endoftext|>