<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   JavascriptInstance.cpp
 *  @brief  Javascript script instance used wit EC_Script.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "JavascriptInstance.h"
#include "JavascriptModule.h"
#include "ScriptMetaTypeDefines.h"
#include "NaaliCoreTypeDefines.h"
#include "EC_Script.h"
#include "IModule.h"
#include "AssetAPI.h"
#include "IAssetProvider.h" //to check if the code was loaded from a local or remote storage

#include "LoggingFunctions.h"
DEFINE_POCO_LOGGING_FUNCTIONS("JavascriptInstance")

#include <QFile>

#include "MemoryLeakCheck.h"

JavascriptInstance::JavascriptInstance(const QString &fileName, JavascriptModule *module)
:engine_(0),
sourceFile(fileName),
module_(module),
evaluated(false)
{
    CreateEngine();
    Load();
}

JavascriptInstance::JavascriptInstance(ScriptAssetPtr scriptRef, JavascriptModule *module)
:engine_(0),
scriptRef_(scriptRef),
module_(module),
evaluated(false)
{
    CreateEngine();
    Load();
}

JavascriptInstance::~JavascriptInstance()
{
    DeleteEngine();
}

void JavascriptInstance::Load()
{
    if (!engine_)
        CreateEngine();

    // Can't specify both a file source and an Asset API source.
    assert(sourceFile.isEmpty() || scriptRef_.get() == 0);

    //determine based on code origin whether it can be trusted with system access or not
    if (scriptRef_.get())
    {
        AssetProviderPtr provider = scriptRef_.get()->GetAssetProvider();
        if (provider->Name() == "Local")
            trusted_ = true;
        else
            trusted_ = false;
    }

    if (sourceFile.length() > 0)
    {
        program_ = LoadScript(sourceFile);
        trusted_ = true; //this is a local file directly, right?
    }

    // Do we even have a script to execute?
    if (program_.isEmpty() && (!scriptRef_.get() || scriptRef_->scriptContent.isEmpty()))
    {
        LogError("JavascriptInstance::Load: No script content to load!");
        return;
    }

    QString scriptSourceFilename = (scriptRef_.get() ? scriptRef_->Name() : sourceFile);
    QString &scriptContent = (scriptRef_.get() ? scriptRef_->scriptContent : program_);

    QScriptSyntaxCheckResult syntaxResult = engine_->checkSyntax(scriptContent);
    if (syntaxResult.state() != QScriptSyntaxCheckResult::Valid)
    {
        LogError("Syntax error in script " + scriptSourceFilename.toStdString() + "," + QString::number(syntaxResult.errorLineNumber()).toStdString() +
            ": " + syntaxResult.errorMessage().toStdString());

        // Delete our loaded script content (if any exists).
        program_ == "";
    }
}

QString JavascriptInstance::LoadScript(const QString &fileName)
{
    QString filename = fileName.trimmed();

    // First check if the include was supposed to go through the Asset API.
    if (module_)
    {
        ScriptAssetPtr asset = boost::dynamic_pointer_cast<ScriptAsset>(module_->GetFramework()->Asset()->GetAsset(fileName));
        if (asset)
            return asset->scriptContent;
    }

    // Otherwise, treat fileName as a local file to load up.

    QFile scriptFile(filename);
    if (!scriptFile.open(QIODevice::ReadOnly))
    {
        LogError(("JavascriptInstance::LoadScript: Failed to load script from file " + filename + "!").toStdString());
        return "";
    }

    QString result = scriptFile.readAll();
    scriptFile.close();

    QString trimmedResult = result.trimmed();
    if (trimmedResult.isEmpty())
    {
        LogWarning(("JavascriptInstance::LoadScript: Warning Loaded script from file " + filename + ", but the content was empty.").toStdString());
        return "";
    }
    return result;
}

void JavascriptInstance::Unload()
{
    DeleteEngine();
}

void JavascriptInstance::Run()
{
    // Need to have either absolute file path source or an Asset API source.
    if (!scriptRef_.get() && program_.isEmpty())
    {
        LogError("JavascriptInstance::Run: Cannot run, no script reference loaded.");
        return;
    }

    // Can't specify both a file source and an Asset API source.
    assert(sourceFile.isEmpty() || scriptRef_.get() == 0);

    // If we've already evaluated this script once before, create a new script engine to run it again, or otherwise
    // the effects would stack (we'd possibly register into signals twice, or other odd side effects).
    // We never allow a script to be run twice in this kind of "stacking" manner.
    if (evaluated)
    {
        Unload();
        Load();
    }

    if (!engine_)
    {
        LogError("JavascriptInstance::Run: Cannot run, script engine not loaded.");
        return;
    }

    // If no script specified at all, we'll have to abort.
    if (!scriptRef_.get() && program_.isEmpty())
        return;

    QString scriptSourceFilename = (scriptRef_.get() ? scriptRef_->Name() : sourceFile);
    QString &scriptContent = (scriptRef_.get() ? scriptRef_->scriptContent : program_);

    included_files_.clear();
    QScriptValue result = engine_->evaluate(scriptContent, scriptSourceFilename);
    if (engine_->hasUncaughtException())
        LogError(result.toString().toStdString());

    evaluated = true;
}

void JavascriptInstance::RegisterService(QObject *serviceObject, const QString &name)
{
    if (!engine_)
    {
        LogError("JavascriptInstance::RegisterService: No Qt script engine created when trying to register service to js script instance.");
        return;
    }
    if (!serviceObject)
    {
        LogError("JavascriptInstance::RegisterService: Trying to pass a null service object pointer to RegisterService!");
        return;
    }

    QScriptValue scriptValue = engine_->newQObject(serviceObject);
    engine_->globalObject().setProperty(name, scriptValue);
}

void JavascriptInstance::IncludeFile(const QString &path)
{
    for (uint i = 0; i < included_files_.size(); ++i)
    {
        if (included_files_[i].toLower() == path.toLower())
        {
            LogDebug("JavascriptInstance::IncludeFile: Not including already included file " + path.toStdString());
            return;
        }
    }

    QString script = LoadScript(path);

    QScriptContext *context = engine_->currentContext();
    assert(context);
    if (!context)
    {
        LogError("JavascriptInstance::IncludeFile: QScriptEngine::currentContext() returned null!");
        return;
    }

    QScriptContext *parent = context->parentContext();
    if (!parent)
    {
        LogError("JavascriptInstance::IncludeFile: QScriptEngine::parentContext() returned null!");
        return;
    }

    context->setActivationObject(context->parentContext()->activationObject());
    context->setThisObject(context->parentContext()->thisObject());

    QScriptSyntaxCheckResult syntaxResult = engine_->checkSyntax(script);
    if(syntaxResult.state() != QScriptSyntaxCheckResult::Valid)
    {
        LogError("JavascriptInstance::IncludeFile: Syntax error in " + path.toStdString() + syntaxResult.errorMessage().toStdString()
            + " In line:" + QString::number(syntaxResult.errorLineNumber()).toStdString());
        return;
    }

    QScriptValue result = engine_->evaluate(script);

    included_files_.push_back(path);

    if (engine_->hasUncaughtException())
        LogError(result.toString().toStdString());
}

void JavascriptInstance::ImportExtension(const QString &scriptExtensionName)
{
    assert(engine_);
    if (!engine_)
    {
        LogWarning(("JavascriptInstance::ImportExtension(" + scriptExtensionName + ") failed, QScriptEngine==null!").toStdString());
        return;
    }

    QScriptValue success = engine_->importExtension(scriptExtensionName);
    if (!success.isUndefined()) // Yes, importExtension returns undefinedValue if the import succeeds. http://doc.qt.nokia.com/4.7/qscriptengine.html#importExtension
        LogWarning(std::string("JavascriptInstance::ImportExtension: Failed to load ") + scriptExtensionName.toStdString() + " plugin for QtScript!");

    if (!trusted_)
    {
        QScriptValue exposed;
        exposed = engine_->globalObject().property("QDir");
        if (exposed.isValid())
        {
          engine_->globalObject().setProperty("QDir", QScriptValue::QScriptValue()); //passing an invalid val removes the property, http://doc.qt.nokia.com/4.6/qscriptvalue.html#setProperty
          LogInfo("JavascriptInstance::ImportExtension: removed QDir from the untrusted context.");
        }
    }
}

void JavascriptInstance::CreateEngine()
{
    if (engine_)
        DeleteEngine();
    engine_ = new QScriptEngine;
    connect(engine_, SIGNAL(signalHandlerException(const QScriptValue &)), SLOT(OnSignalHandlerException(const QScriptValue &)));

    ExposeQtMetaTypes(engine_);
    ExposeNaaliCoreTypes(engine_);
    ExposeCoreApiMetaTypes(engine_);

    EC_Script *ec = dynamic_cast<EC_Script *>(owner_.lock().get());
    module_->PrepareScriptInstance(this, ec);
    evaluated = false;
}

void JavascriptInstance::DeleteEngine()
{
    if (!engine_)
        return;

    program_ = "";
    engine_->abortEvaluation();

    // As a convention, we call a function 'OnScriptDestroyed' for each JS script
    // so that they can clean up their data before the script is removed from the object,
    // or when the system is unloading.

    QScriptValue destructor = engine_->globalObject().property("OnScriptDestroyed");
    if (!destructor.isUndefined())
        destructor.call();
    SAFE_DELETE(engine_);
}

void JavascriptInstance::OnSignalHandlerException(const QScriptValue& exception)
{
    LogError(exception.toString().toStdString());
}

<commit_msg>two blacklists: 1) for qt extensions (dll/so) and 2) for system access types in qt.core<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   JavascriptInstance.cpp
 *  @brief  Javascript script instance used wit EC_Script.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "JavascriptInstance.h"
#include "JavascriptModule.h"
#include "ScriptMetaTypeDefines.h"
#include "NaaliCoreTypeDefines.h"
#include "EC_Script.h"
#include "IModule.h"
#include "AssetAPI.h"
#include "IAssetProvider.h" //to check if the code was loaded from a local or remote storage

#include "LoggingFunctions.h"
DEFINE_POCO_LOGGING_FUNCTIONS("JavascriptInstance")

#include <QFile>

#include "MemoryLeakCheck.h"

JavascriptInstance::JavascriptInstance(const QString &fileName, JavascriptModule *module)
:engine_(0),
sourceFile(fileName),
module_(module),
evaluated(false)
{
    CreateEngine();
    Load();
}

JavascriptInstance::JavascriptInstance(ScriptAssetPtr scriptRef, JavascriptModule *module)
:engine_(0),
scriptRef_(scriptRef),
module_(module),
evaluated(false)
{
    CreateEngine();
    Load();
}

JavascriptInstance::~JavascriptInstance()
{
    DeleteEngine();
}

void JavascriptInstance::Load()
{
    if (!engine_)
        CreateEngine();

    // Can't specify both a file source and an Asset API source.
    assert(sourceFile.isEmpty() || scriptRef_.get() == 0);

    //determine based on code origin whether it can be trusted with system access or not
    if (scriptRef_.get())
    {
        AssetProviderPtr provider = scriptRef_.get()->GetAssetProvider();
        if (provider->Name() == "Local")
            trusted_ = true;
        else
            trusted_ = false;
    }

    if (sourceFile.length() > 0)
    {
        program_ = LoadScript(sourceFile);
        trusted_ = true; //this is a local file directly, right?
    }

    // Do we even have a script to execute?
    if (program_.isEmpty() && (!scriptRef_.get() || scriptRef_->scriptContent.isEmpty()))
    {
        LogError("JavascriptInstance::Load: No script content to load!");
        return;
    }

    QString scriptSourceFilename = (scriptRef_.get() ? scriptRef_->Name() : sourceFile);
    QString &scriptContent = (scriptRef_.get() ? scriptRef_->scriptContent : program_);

    QScriptSyntaxCheckResult syntaxResult = engine_->checkSyntax(scriptContent);
    if (syntaxResult.state() != QScriptSyntaxCheckResult::Valid)
    {
        LogError("Syntax error in script " + scriptSourceFilename.toStdString() + "," + QString::number(syntaxResult.errorLineNumber()).toStdString() +
            ": " + syntaxResult.errorMessage().toStdString());

        // Delete our loaded script content (if any exists).
        program_ == "";
    }
}

QString JavascriptInstance::LoadScript(const QString &fileName)
{
    QString filename = fileName.trimmed();

    // First check if the include was supposed to go through the Asset API.
    if (module_)
    {
        ScriptAssetPtr asset = boost::dynamic_pointer_cast<ScriptAsset>(module_->GetFramework()->Asset()->GetAsset(fileName));
        if (asset)
            return asset->scriptContent;
    }

    // Otherwise, treat fileName as a local file to load up.

    QFile scriptFile(filename);
    if (!scriptFile.open(QIODevice::ReadOnly))
    {
        LogError(("JavascriptInstance::LoadScript: Failed to load script from file " + filename + "!").toStdString());
        return "";
    }

    QString result = scriptFile.readAll();
    scriptFile.close();

    QString trimmedResult = result.trimmed();
    if (trimmedResult.isEmpty())
    {
        LogWarning(("JavascriptInstance::LoadScript: Warning Loaded script from file " + filename + ", but the content was empty.").toStdString());
        return "";
    }
    return result;
}

void JavascriptInstance::Unload()
{
    DeleteEngine();
}

void JavascriptInstance::Run()
{
    // Need to have either absolute file path source or an Asset API source.
    if (!scriptRef_.get() && program_.isEmpty())
    {
        LogError("JavascriptInstance::Run: Cannot run, no script reference loaded.");
        return;
    }

    // Can't specify both a file source and an Asset API source.
    assert(sourceFile.isEmpty() || scriptRef_.get() == 0);

    // If we've already evaluated this script once before, create a new script engine to run it again, or otherwise
    // the effects would stack (we'd possibly register into signals twice, or other odd side effects).
    // We never allow a script to be run twice in this kind of "stacking" manner.
    if (evaluated)
    {
        Unload();
        Load();
    }

    if (!engine_)
    {
        LogError("JavascriptInstance::Run: Cannot run, script engine not loaded.");
        return;
    }

    // If no script specified at all, we'll have to abort.
    if (!scriptRef_.get() && program_.isEmpty())
        return;

    QString scriptSourceFilename = (scriptRef_.get() ? scriptRef_->Name() : sourceFile);
    QString &scriptContent = (scriptRef_.get() ? scriptRef_->scriptContent : program_);

    included_files_.clear();
    QScriptValue result = engine_->evaluate(scriptContent, scriptSourceFilename);
    if (engine_->hasUncaughtException())
        LogError(result.toString().toStdString());

    evaluated = true;
}

void JavascriptInstance::RegisterService(QObject *serviceObject, const QString &name)
{
    if (!engine_)
    {
        LogError("JavascriptInstance::RegisterService: No Qt script engine created when trying to register service to js script instance.");
        return;
    }
    if (!serviceObject)
    {
        LogError("JavascriptInstance::RegisterService: Trying to pass a null service object pointer to RegisterService!");
        return;
    }

    QScriptValue scriptValue = engine_->newQObject(serviceObject);
    engine_->globalObject().setProperty(name, scriptValue);
}

void JavascriptInstance::IncludeFile(const QString &path)
{
    for (uint i = 0; i < included_files_.size(); ++i)
    {
        if (included_files_[i].toLower() == path.toLower())
        {
            LogDebug("JavascriptInstance::IncludeFile: Not including already included file " + path.toStdString());
            return;
        }
    }

    QString script = LoadScript(path);

    QScriptContext *context = engine_->currentContext();
    assert(context);
    if (!context)
    {
        LogError("JavascriptInstance::IncludeFile: QScriptEngine::currentContext() returned null!");
        return;
    }

    QScriptContext *parent = context->parentContext();
    if (!parent)
    {
        LogError("JavascriptInstance::IncludeFile: QScriptEngine::parentContext() returned null!");
        return;
    }

    context->setActivationObject(context->parentContext()->activationObject());
    context->setThisObject(context->parentContext()->thisObject());

    QScriptSyntaxCheckResult syntaxResult = engine_->checkSyntax(script);
    if(syntaxResult.state() != QScriptSyntaxCheckResult::Valid)
    {
        LogError("JavascriptInstance::IncludeFile: Syntax error in " + path.toStdString() + syntaxResult.errorMessage().toStdString()
            + " In line:" + QString::number(syntaxResult.errorLineNumber()).toStdString());
        return;
    }

    QScriptValue result = engine_->evaluate(script);

    included_files_.push_back(path);

    if (engine_->hasUncaughtException())
        LogError(result.toString().toStdString());
}

void JavascriptInstance::ImportExtension(const QString &scriptExtensionName)
{
    assert(engine_);
    if (!engine_)
    {
        LogWarning(("JavascriptInstance::ImportExtension(" + scriptExtensionName + ") failed, QScriptEngine==null!").toStdString());
        return;
    }

    QStringList extension_blacklist;
    extension_blacklist << "qt.network" << "qt.webkit"; //webkit to not allow scripts to open hidden browsers to do malicious stuff.

    QStringList qtcore_blacklist; //the types in qt.core which are not safe
    qtcore_blacklist << "QDir" << "QFile" << "QFileSystemWatcher" << "QFileInfo" << "QLibrary" << "QPluginLoader";

    if (!trusted_ && extension_blacklist.contains(scriptExtensionName, Qt::CaseInsensitive))
    {
        LogWarning("JavascriptInstance::ImportExtension: refusing to load a QtScript plugin for an untrusted instance: " + scriptExtensionName.toStdString());
        return;
    }

    QScriptValue success = engine_->importExtension(scriptExtensionName);
    if (!success.isUndefined()) // Yes, importExtension returns undefinedValue if the import succeeds. http://doc.qt.nokia.com/4.7/qscriptengine.html#importExtension
        LogWarning(std::string("JavascriptInstance::ImportExtension: Failed to load ") + scriptExtensionName.toStdString() + " plugin for QtScript!");

    if (!trusted_)
    {
        QScriptValue exposed;
        foreach (const QString &blacktype, qtcore_blacklist)
        {
            exposed = engine_->globalObject().property(blacktype);
            if (exposed.isValid())
            {
                engine_->globalObject().setProperty(blacktype, QScriptValue::QScriptValue()); //passing an invalid val removes the property, http://doc.qt.nokia.com/4.6/qscriptvalue.html#setProperty
                //LogInfo("JavascriptInstance::ImportExtension: removed a type from the untrusted context: " + blacktype.toStdString());
            }
        }
    }
}

void JavascriptInstance::CreateEngine()
{
    if (engine_)
        DeleteEngine();
    engine_ = new QScriptEngine;
    connect(engine_, SIGNAL(signalHandlerException(const QScriptValue &)), SLOT(OnSignalHandlerException(const QScriptValue &)));

    ExposeQtMetaTypes(engine_);
    ExposeNaaliCoreTypes(engine_);
    ExposeCoreApiMetaTypes(engine_);

    EC_Script *ec = dynamic_cast<EC_Script *>(owner_.lock().get());
    module_->PrepareScriptInstance(this, ec);
    evaluated = false;
}

void JavascriptInstance::DeleteEngine()
{
    if (!engine_)
        return;

    program_ = "";
    engine_->abortEvaluation();

    // As a convention, we call a function 'OnScriptDestroyed' for each JS script
    // so that they can clean up their data before the script is removed from the object,
    // or when the system is unloading.

    QScriptValue destructor = engine_->globalObject().property("OnScriptDestroyed");
    if (!destructor.isUndefined())
        destructor.call();
    SAFE_DELETE(engine_);
}

void JavascriptInstance::OnSignalHandlerException(const QScriptValue& exception)
{
    LogError(exception.toString().toStdString());
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
 */

#include <stdio.h>

// Qt stuff
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QGraphicsRectItem>
#include <QtGui/QPen>
#include <QtGui/QColor>

// OpenCV stuff
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/calib3d/calib3d.hpp> // for homography

// From this project (see src folder)
#include "ObjWidget.h"
#include "QtOpenCV.h"

void showUsage()
{
	printf("\n");
	printf("Usage :\n");
	printf("  ./example object.png scene.png\n");
	exit(1);
}

int main(int argc, char * argv[])
{
	if(argc<3)
	{
		showUsage();
	}
	QTime time;
	time.start();

	// GUI stuff
	QApplication app(argc, argv);
	ObjWidget objWidget;
	ObjWidget sceneWidget;

	//Load as grayscale
	cv::Mat objectImg = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
	cv::Mat sceneImg = cv::imread(argv[2], cv::IMREAD_GRAYSCALE);

	if(!objectImg.empty() && !sceneImg.empty())
	{
		std::vector<cv::KeyPoint> objectKeypoints;
		std::vector<cv::KeyPoint> sceneKeypoints;
		cv::Mat objectDescriptors;
		cv::Mat sceneDescriptors;

		////////////////////////////
		// EXTRACT KEYPOINTS
		////////////////////////////
		// The detector can be any of (see OpenCV features2d.hpp):
		// cv::FeatureDetector * detector = new cv::DenseFeatureDetector();
		// cv::FeatureDetector * detector = new cv::FastFeatureDetector();
		// cv::FeatureDetector * detector = new cv::GFTTDetector();
		// cv::FeatureDetector * detector = new cv::MSER();
		// cv::FeatureDetector * detector = new cv::ORB();
		// cv::FeatureDetector * detector = new cv::SIFT();
		// cv::FeatureDetector * detector = new cv::StarFeatureDetector();
		// cv::FeatureDetector * detector = new cv::SURF();
		cv::FeatureDetector * detector = new cv::SURF(600.0);
		detector->detect(objectImg, objectKeypoints);
		printf("Object: %d keypoints detected in %d ms\n", (int)objectKeypoints.size(), time.restart());
		detector->detect(sceneImg, sceneKeypoints);
		printf("Scene: %d keypoints detected in %d ms\n", (int)sceneKeypoints.size(), time.restart());

		////////////////////////////
		// EXTRACT DESCRIPTORS
		////////////////////////////
		// The extractor can be any of (see OpenCV features2d.hpp):
		// cv::DescriptorExtractor * extractor = new cv::BriefDescriptorExtractor();
		// cv::DescriptorExtractor * extractor = new cv::ORB();
		// cv::DescriptorExtractor * extractor = new cv::SIFT();
		// cv::DescriptorExtractor * extractor = new cv::SURF();
		cv::DescriptorExtractor * extractor = new cv::SURF(600.0);
		extractor->compute(objectImg, objectKeypoints, objectDescriptors);
		printf("Object: %d descriptors extracted in %d ms\n", objectDescriptors.rows, time.restart());
		extractor->compute(sceneImg, sceneKeypoints, sceneDescriptors);
		printf("Scene: %d descriptors extracted in %d ms\n", sceneDescriptors.rows, time.restart());

		////////////////////////////
		// NEAREST NEIGHBOR MATCHING USING FLANN LIBRARY (included in OpenCV)
		////////////////////////////
		// Format descriptors for Flann
		cv::Mat objectData;
		cv::Mat sceneData;
		if(objectDescriptors.type()!=CV_32F) {
			objectDescriptors.convertTo(objectData, CV_32F); // make sure it's CV_32F
		}
		else {
			objectData = objectDescriptors;
		}
		if(sceneDescriptors.type()!=CV_32F) {
			sceneDescriptors.convertTo(sceneData, CV_32F); // make sure it's CV_32F
		}
		else {
			sceneData = sceneDescriptors;
		}

		// Create Flann index
		cv::flann::Index treeFlannIndex(sceneData, cv::flann::KDTreeIndexParams());
		printf("Time creating FLANN index = %d ms\n", time.restart());

		// search (nearest neighbor)
		int k=2; // find the 2 nearest neighbors
		cv::Mat results(objectData.rows, k, CV_32SC1); // Results index
		cv::Mat dists(objectData.rows, k, CV_32FC1); // Distance results are CV_32FC1
		treeFlannIndex.knnSearch(objectData, results, dists, k, cv::flann::SearchParams() ); // maximum number of leafs checked
		printf("Time nearest neighbor search = %d ms\n", time.restart());

		////////////////////////////
		// PROCESS NEAREST NEIGHBOR RESULTS
		////////////////////////////
		// Set gui data
		objWidget.setData(objectKeypoints, objectDescriptors, objectImg, "SURF", "SURF");
		sceneWidget.setData(sceneKeypoints, sceneDescriptors, sceneImg, "SURF", "SURF");

		// Find correspondences by NNDR (Nearest Neighbor Distance Ratio)
		float nndrRatio = 0.6;
		std::vector<cv::Point2f> mpts_1, mpts_2; // Used for homography
		std::vector<int> indexes_1, indexes_2; // Used for homography
		std::vector<uchar> outlier_mask;  // Used for homography
		for(int i=0; i<objectData.rows; ++i)
		{
			// Check if this descriptor matches with those of the objects
			// Apply NNDR
			if(dists.at<float>(i,0) <= nndrRatio * dists.at<float>(i,1))
			{
				mpts_1.push_back(objectKeypoints.at(i).pt);
				indexes_1.push_back(i);

				mpts_2.push_back(sceneKeypoints.at(results.at<int>(i,0)).pt);
				indexes_2.push_back(results.at<int>(i,0));
			}
		}

		// FIND HOMOGRAPHY
		unsigned int minInliers = 8;
		if(mpts_1.size() >= minInliers)
		{
			time.start();
			cv::Mat H = findHomography(mpts_1,
					mpts_2,
					cv::RANSAC,
					1.0,
					outlier_mask);
			printf("Time finding homography = %d ms\n", time.restart());
			int inliers=0, outliers=0;
			for(unsigned int k=0; k<mpts_1.size();++k)
			{
				if(outlier_mask.at(k))
				{
					++inliers;
				}
				else
				{
					++outliers;
				}
			}
			QTransform hTransform(
			H.at<double>(0,0), H.at<double>(1,0), H.at<double>(2,0),
			H.at<double>(0,1), H.at<double>(1,1), H.at<double>(2,1),
			H.at<double>(0,2), H.at<double>(1,2), H.at<double>(2,2));

			// GUI : Change color and add homography rectangle
			QColor color(Qt::green);
			int alpha = 130;
			color.setAlpha(alpha);
			for(unsigned int k=0; k<mpts_1.size();++k)
			{
				if(outlier_mask.at(k))
				{
					objWidget.setKptColor(indexes_1.at(k), color);
					sceneWidget.setKptColor(indexes_2.at(k), color);
				}
				else
				{
					objWidget.setKptColor(indexes_1.at(k), QColor(255,0,0,alpha));
					sceneWidget.setKptColor(indexes_2.at(k), QColor(255,0,0,alpha));
				}
			}
			QPen rectPen(color);
			rectPen.setWidth(4);
			QGraphicsRectItem * rectItem = new QGraphicsRectItem(objWidget.pixmap().rect());
			rectItem->setPen(rectPen);
			rectItem->setTransform(hTransform);
			sceneWidget.addRect(rectItem);
			printf("Inliers=%d Outliers=%d\n", inliers, outliers);
		}
		else
		{
			printf("Not enough matches (%d) for homography...\n", (int)mpts_1.size());
		}

		// Wait for gui
		objWidget.setGraphicsViewMode(false);
		objWidget.setWindowTitle("Object");
		if(objWidget.pixmap().width() <= 800)
		{
			objWidget.setMinimumSize(objWidget.pixmap().width(), objWidget.pixmap().height());
		}
		else
		{
			objWidget.setMinimumSize(800, 600);
			objWidget.setAutoScale(false);
		}

		sceneWidget.setGraphicsViewMode(false);
		sceneWidget.setWindowTitle("Scene");
		if(sceneWidget.pixmap().width() <= 800)
		{
			sceneWidget.setMinimumSize(sceneWidget.pixmap().width(), sceneWidget.pixmap().height());
		}
		else
		{
			sceneWidget.setMinimumSize(800, 600);
			sceneWidget.setAutoScale(false);
		}

		sceneWidget.show();
		objWidget.show();

		int r = app.exec();
		printf("Closing...\n");

		////////////////////////////
		//Cleanup
		////////////////////////////
		delete detector;
		delete extractor;

		return r;
	}
	else
	{
		printf("Images are not valid!\n");
		showUsage();
	}

	return 1;
}
<commit_msg>Added loading images time in example<commit_after>/*
 * Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
 */

#include <stdio.h>

// Qt stuff
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QGraphicsRectItem>
#include <QtGui/QPen>
#include <QtGui/QColor>

// OpenCV stuff
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/calib3d/calib3d.hpp> // for homography

// From this project (see src folder)
#include "ObjWidget.h"
#include "QtOpenCV.h"

void showUsage()
{
	printf("\n");
	printf("Usage :\n");
	printf("  ./example object.png scene.png\n");
	exit(1);
}

int main(int argc, char * argv[])
{
	if(argc<3)
	{
		showUsage();
	}
	QTime time;

	// GUI stuff
	QApplication app(argc, argv);
	ObjWidget objWidget;
	ObjWidget sceneWidget;

	time.start();
	//Load as grayscale
	cv::Mat objectImg = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
	cv::Mat sceneImg = cv::imread(argv[2], cv::IMREAD_GRAYSCALE);

	if(!objectImg.empty() && !sceneImg.empty())
	{
		printf("Loading images: %d ms\n", time.restart());
		std::vector<cv::KeyPoint> objectKeypoints;
		std::vector<cv::KeyPoint> sceneKeypoints;
		cv::Mat objectDescriptors;
		cv::Mat sceneDescriptors;

		////////////////////////////
		// EXTRACT KEYPOINTS
		////////////////////////////
		// The detector can be any of (see OpenCV features2d.hpp):
		// cv::FeatureDetector * detector = new cv::DenseFeatureDetector();
		// cv::FeatureDetector * detector = new cv::FastFeatureDetector();
		// cv::FeatureDetector * detector = new cv::GFTTDetector();
		// cv::FeatureDetector * detector = new cv::MSER();
		// cv::FeatureDetector * detector = new cv::ORB();
		// cv::FeatureDetector * detector = new cv::SIFT();
		// cv::FeatureDetector * detector = new cv::StarFeatureDetector();
		// cv::FeatureDetector * detector = new cv::SURF();
		cv::FeatureDetector * detector = new cv::SURF(600.0);
		detector->detect(objectImg, objectKeypoints);
		printf("Object: %d keypoints detected in %d ms\n", (int)objectKeypoints.size(), time.restart());
		detector->detect(sceneImg, sceneKeypoints);
		printf("Scene: %d keypoints detected in %d ms\n", (int)sceneKeypoints.size(), time.restart());

		////////////////////////////
		// EXTRACT DESCRIPTORS
		////////////////////////////
		// The extractor can be any of (see OpenCV features2d.hpp):
		// cv::DescriptorExtractor * extractor = new cv::BriefDescriptorExtractor();
		// cv::DescriptorExtractor * extractor = new cv::ORB();
		// cv::DescriptorExtractor * extractor = new cv::SIFT();
		// cv::DescriptorExtractor * extractor = new cv::SURF();
		cv::DescriptorExtractor * extractor = new cv::SURF(600.0);
		extractor->compute(objectImg, objectKeypoints, objectDescriptors);
		printf("Object: %d descriptors extracted in %d ms\n", objectDescriptors.rows, time.restart());
		extractor->compute(sceneImg, sceneKeypoints, sceneDescriptors);
		printf("Scene: %d descriptors extracted in %d ms\n", sceneDescriptors.rows, time.restart());

		////////////////////////////
		// NEAREST NEIGHBOR MATCHING USING FLANN LIBRARY (included in OpenCV)
		////////////////////////////
		// Format descriptors for Flann
		cv::Mat objectData;
		cv::Mat sceneData;
		if(objectDescriptors.type()!=CV_32F) {
			objectDescriptors.convertTo(objectData, CV_32F); // make sure it's CV_32F
		}
		else {
			objectData = objectDescriptors;
		}
		if(sceneDescriptors.type()!=CV_32F) {
			sceneDescriptors.convertTo(sceneData, CV_32F); // make sure it's CV_32F
		}
		else {
			sceneData = sceneDescriptors;
		}

		// Create Flann index
		cv::flann::Index treeFlannIndex(sceneData, cv::flann::KDTreeIndexParams());
		printf("Time creating FLANN index = %d ms\n", time.restart());

		// search (nearest neighbor)
		int k=2; // find the 2 nearest neighbors
		cv::Mat results(objectData.rows, k, CV_32SC1); // Results index
		cv::Mat dists(objectData.rows, k, CV_32FC1); // Distance results are CV_32FC1
		treeFlannIndex.knnSearch(objectData, results, dists, k, cv::flann::SearchParams() ); // maximum number of leafs checked
		printf("Time nearest neighbor search = %d ms\n", time.restart());

		////////////////////////////
		// PROCESS NEAREST NEIGHBOR RESULTS
		////////////////////////////
		// Set gui data
		objWidget.setData(objectKeypoints, objectDescriptors, objectImg, "SURF", "SURF");
		sceneWidget.setData(sceneKeypoints, sceneDescriptors, sceneImg, "SURF", "SURF");

		// Find correspondences by NNDR (Nearest Neighbor Distance Ratio)
		float nndrRatio = 0.6;
		std::vector<cv::Point2f> mpts_1, mpts_2; // Used for homography
		std::vector<int> indexes_1, indexes_2; // Used for homography
		std::vector<uchar> outlier_mask;  // Used for homography
		for(int i=0; i<objectData.rows; ++i)
		{
			// Check if this descriptor matches with those of the objects
			// Apply NNDR
			if(dists.at<float>(i,0) <= nndrRatio * dists.at<float>(i,1))
			{
				mpts_1.push_back(objectKeypoints.at(i).pt);
				indexes_1.push_back(i);

				mpts_2.push_back(sceneKeypoints.at(results.at<int>(i,0)).pt);
				indexes_2.push_back(results.at<int>(i,0));
			}
		}

		// FIND HOMOGRAPHY
		unsigned int minInliers = 8;
		if(mpts_1.size() >= minInliers)
		{
			time.start();
			cv::Mat H = findHomography(mpts_1,
					mpts_2,
					cv::RANSAC,
					1.0,
					outlier_mask);
			printf("Time finding homography = %d ms\n", time.restart());
			int inliers=0, outliers=0;
			for(unsigned int k=0; k<mpts_1.size();++k)
			{
				if(outlier_mask.at(k))
				{
					++inliers;
				}
				else
				{
					++outliers;
				}
			}
			QTransform hTransform(
			H.at<double>(0,0), H.at<double>(1,0), H.at<double>(2,0),
			H.at<double>(0,1), H.at<double>(1,1), H.at<double>(2,1),
			H.at<double>(0,2), H.at<double>(1,2), H.at<double>(2,2));

			// GUI : Change color and add homography rectangle
			QColor color(Qt::green);
			int alpha = 130;
			color.setAlpha(alpha);
			for(unsigned int k=0; k<mpts_1.size();++k)
			{
				if(outlier_mask.at(k))
				{
					objWidget.setKptColor(indexes_1.at(k), color);
					sceneWidget.setKptColor(indexes_2.at(k), color);
				}
				else
				{
					objWidget.setKptColor(indexes_1.at(k), QColor(255,0,0,alpha));
					sceneWidget.setKptColor(indexes_2.at(k), QColor(255,0,0,alpha));
				}
			}
			QPen rectPen(color);
			rectPen.setWidth(4);
			QGraphicsRectItem * rectItem = new QGraphicsRectItem(objWidget.pixmap().rect());
			rectItem->setPen(rectPen);
			rectItem->setTransform(hTransform);
			sceneWidget.addRect(rectItem);
			printf("Inliers=%d Outliers=%d\n", inliers, outliers);
		}
		else
		{
			printf("Not enough matches (%d) for homography...\n", (int)mpts_1.size());
		}

		// Wait for gui
		objWidget.setGraphicsViewMode(false);
		objWidget.setWindowTitle("Object");
		if(objWidget.pixmap().width() <= 800)
		{
			objWidget.setMinimumSize(objWidget.pixmap().width(), objWidget.pixmap().height());
		}
		else
		{
			objWidget.setMinimumSize(800, 600);
			objWidget.setAutoScale(false);
		}

		sceneWidget.setGraphicsViewMode(false);
		sceneWidget.setWindowTitle("Scene");
		if(sceneWidget.pixmap().width() <= 800)
		{
			sceneWidget.setMinimumSize(sceneWidget.pixmap().width(), sceneWidget.pixmap().height());
		}
		else
		{
			sceneWidget.setMinimumSize(800, 600);
			sceneWidget.setAutoScale(false);
		}

		sceneWidget.show();
		objWidget.show();

		int r = app.exec();
		printf("Closing...\n");

		////////////////////////////
		//Cleanup
		////////////////////////////
		delete detector;
		delete extractor;

		return r;
	}
	else
	{
		printf("Images are not valid!\n");
		showUsage();
	}

	return 1;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef TOP_HPP_
#define TOP_HPP_

#if defined(ATI_ARCH_ARM)
# define __EXPORTED_HEADERS__ 1
#endif /*ATI_ARCH_ARM*/

#ifdef _WIN32
// Disable unneeded features of <windows.h> for efficiency.
# define NOGDICAPMASKS
# define NOVIRTUALKEYCODES
# define NOWINMESSAGES
# define NOWINSTYLES
# define NOSYSMETRICS
# define NOMENUS
# define NOICONS
# define NOKEYSTATES
# define NOSYSCOMMANDS
# define NORASTEROPS
# define NOSHOWWINDOW
# define OEMRESOURCE
# define NOATOM
# define NOCLIPBOARD
# define NOCOLOR
# define NOCTLMGR
# define NODRAWTEXT
# define NOGDI
# define NOKERNEL
# define NOMB
# define NOMEMMGR
# define NOMETAFILE
# define NOMINMAX
# define NOOPENFILE
# define NOSCROLL
# define NOSERVICE
# define NOSOUND
# define NOTEXTMETRIC
# define NOWH
# define NOWINOFFSETS
# define NOCOMM
# define NOKANJI
# define NOHELP
# define NOPROFILER
# define NODEFERWINDOWPOS
# define NOMCX
# ifndef NOCRYPT
#  define NOCRYPT
# endif
# define WIN32_LEAN_AND_MEAN 1
#endif /*_WIN32*/

#include "utils/macros.hpp"
#include "CL/opencl.h"

#if defined(CL_VERSION_2_0)
/* Deprecated in OpenCL 2.0 */
# define CL_DEVICE_QUEUE_PROPERTIES     0x102A
# define CL_DEVICE_HOST_UNIFIED_MEMORY  0x1035
#endif

#if !defined(ATI_ARCH_ARM)
#include <xmmintrin.h>
#endif /*!ATI_ARCH_ARM*/

#include <cstdint>
#include <cstddef>
#include <new>

typedef unsigned char* address;
typedef const unsigned char* const_address;
typedef void * pointer;
typedef const void * const_pointer;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef const char* cstring;

#if defined(_WIN32)
# if defined(_WIN64)
typedef __int64 ssize_t;
# else // !_WIN64
typedef __int32 ssize_t;
# endif // !_WIN64
#endif /*_WIN32*/

#ifdef _WIN32
# define SIZE_T_FMT "%Iu"
# define PTR_FMT    "0x%p"
# if _MSC_VER < 1900
#  define snprintf sprintf_s
# endif
#else /*!_WIN32*/
# define SIZE_T_FMT "%zu"
# define PTR_FMT    "%p"
#endif /*!_WIN32*/

typedef uint32_t cl_mem_fence_flags;

//! \cond ignore
#define _BAD_INT32  0xBAADBAAD
#define _BAD_INT64  0XBAADBAADBAADBAADLL
#define _BAD_INTPTR LP64_SWITCH(_BAD_INT32,_BAD_INT64)

const pointer badPointer = (pointer)(intptr_t) _BAD_INTPTR;
const address badAddress = (address)(intptr_t) _BAD_INTPTR;
//! \endcond

const size_t Ki = 1024;
const size_t Mi = Ki*Ki;
const size_t Gi = Ki*Ki*Ki;

const size_t K = 1000;
const size_t M = K*K;
const size_t G = K*K*K;

#include "utils/debug.hpp"

//! \addtogroup Utils

//! Namespace for AMD's OpenCL platform
namespace amd {/*@{*/

//! \brief The default Null object type (!= void*);
struct Null {};

//! \brief Return a const Null object (null)
inline const Null null() { return Null(); }

/*! \brief Equivalent to a namespace (All member functions are static).
 */
class AllStatic
{
WINDOWS_SWITCH(public,private):
    AllStatic() { ShouldNotCallThis(); }
    AllStatic(const AllStatic&) { ShouldNotCallThis(); }
    ~AllStatic() { ShouldNotCallThis(); }
};

/*! \brief For embedded objects.
 */
class EmbeddedObject
{
WINDOWS_SWITCH(public,private):
    void* operator new(size_t) { ShouldNotCallThis(); return badPointer;  }
    void operator delete(void *) { ShouldNotCallThis(); }
};

/*! \brief For stack allocated objects.
 */
class StackObject
{
WINDOWS_SWITCH(public,private):
    void* operator new(size_t) { ShouldNotCallThis(); return badPointer;  }
    void operator delete(void *) { ShouldNotCallThis(); }
};

/*! \brief for objects allocated in a dedicate memory pool.
  the standard 'new' should not be called,
  only the in place version 'new (allocation_pointer) <class>()'
  , delete should only invoke the destructors and not release memory
 */
class MemoryPoolObject
{
public:
	void* operator new(size_t) { ShouldNotCallThis(); return badPointer;  }
	void* operator new(size_t size,void * address) { return address; }
	void operator delete(void *) {  }
	void operator delete( void *,void * address) { }
};

/*! \brief For objects allocated on the C-heap.
 */
class HeapObject
{
public:
    void* operator new(size_t size);
    void operator delete(void* obj);
    void* operator new(size_t size, size_t extSize)
        { return HeapObject::operator new (size + extSize); };
    void operator delete(void* obj, size_t extSize)
        { HeapObject::operator delete (obj); }
};

/*! \brief For all reference counted objects.
 */
class ReferenceCountedObject
{
    volatile uint referenceCount_;

protected:
    virtual ~ReferenceCountedObject() { }
    virtual bool terminate() { return true; }

public:
    ReferenceCountedObject() : referenceCount_(1) { }

    void* operator new(size_t size) { return ::operator new(size); }
    void operator delete(void* p) { return ::operator delete(p); }
    void* operator new(size_t size, size_t extSize)
        { return ReferenceCountedObject::operator new (size + extSize); };
    void operator delete(void* obj, size_t extSize)
        { ReferenceCountedObject::operator delete (obj); }

    uint referenceCount() const { return referenceCount_; }

    uint retain();
    uint release();
};

/*@}*/} // namespace amd

#undef min // using std::min
#undef max // using std::max

#endif /*TOP_HPP_*/

<commit_msg>P4 to Git Change 1330418 by lmoriche@lmoriche_opencl_dev on 2016/10/24 01:43:34<commit_after>//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef TOP_HPP_
#define TOP_HPP_

#if defined(ATI_ARCH_ARM)
# define __EXPORTED_HEADERS__ 1
#endif /*ATI_ARCH_ARM*/

#ifdef _WIN32
// Disable unneeded features of <windows.h> for efficiency.
# define NODRAWTEXT 1
# define NOMINMAX 1
# define WIN32_LEAN_AND_MEAN 1
#endif /*_WIN32*/

#include "utils/macros.hpp"
#include "CL/opencl.h"

#if defined(CL_VERSION_2_0)
/* Deprecated in OpenCL 2.0 */
# define CL_DEVICE_QUEUE_PROPERTIES     0x102A
# define CL_DEVICE_HOST_UNIFIED_MEMORY  0x1035
#endif

#if !defined(ATI_ARCH_ARM)
#include <xmmintrin.h>
#endif /*!ATI_ARCH_ARM*/

#include <cstdint>
#include <cstddef>
#include <new>

typedef unsigned char* address;
typedef const unsigned char* const_address;
typedef void * pointer;
typedef const void * const_pointer;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef const char* cstring;

#if defined(_WIN32)
# if defined(_WIN64)
typedef __int64 ssize_t;
# else // !_WIN64
typedef __int32 ssize_t;
# endif // !_WIN64
#endif /*_WIN32*/

#ifdef _WIN32
# define SIZE_T_FMT "%Iu"
# define PTR_FMT    "0x%p"
# if _MSC_VER < 1900
#  define snprintf sprintf_s
# endif
#else /*!_WIN32*/
# define SIZE_T_FMT "%zu"
# define PTR_FMT    "%p"
#endif /*!_WIN32*/

typedef uint32_t cl_mem_fence_flags;

//! \cond ignore
#define _BAD_INT32  0xBAADBAAD
#define _BAD_INT64  0XBAADBAADBAADBAADLL
#define _BAD_INTPTR LP64_SWITCH(_BAD_INT32,_BAD_INT64)

const pointer badPointer = (pointer)(intptr_t) _BAD_INTPTR;
const address badAddress = (address)(intptr_t) _BAD_INTPTR;
//! \endcond

const size_t Ki = 1024;
const size_t Mi = Ki*Ki;
const size_t Gi = Ki*Ki*Ki;

const size_t K = 1000;
const size_t M = K*K;
const size_t G = K*K*K;

#include "utils/debug.hpp"

//! \addtogroup Utils

//! Namespace for AMD's OpenCL platform
namespace amd {/*@{*/

//! \brief The default Null object type (!= void*);
struct Null {};

//! \brief Return a const Null object (null)
inline const Null null() { return Null(); }

/*! \brief Equivalent to a namespace (All member functions are static).
 */
class AllStatic
{
WINDOWS_SWITCH(public,private):
    AllStatic() { ShouldNotCallThis(); }
    AllStatic(const AllStatic&) { ShouldNotCallThis(); }
    ~AllStatic() { ShouldNotCallThis(); }
};

/*! \brief For embedded objects.
 */
class EmbeddedObject
{
WINDOWS_SWITCH(public,private):
    void* operator new(size_t) { ShouldNotCallThis(); return badPointer;  }
    void operator delete(void *) { ShouldNotCallThis(); }
};

/*! \brief For stack allocated objects.
 */
class StackObject
{
WINDOWS_SWITCH(public,private):
    void* operator new(size_t) { ShouldNotCallThis(); return badPointer;  }
    void operator delete(void *) { ShouldNotCallThis(); }
};

/*! \brief for objects allocated in a dedicate memory pool.
  the standard 'new' should not be called,
  only the in place version 'new (allocation_pointer) <class>()'
  , delete should only invoke the destructors and not release memory
 */
class MemoryPoolObject
{
public:
	void* operator new(size_t) { ShouldNotCallThis(); return badPointer;  }
	void* operator new(size_t size,void * address) { return address; }
	void operator delete(void *) {  }
	void operator delete( void *,void * address) { }
};

/*! \brief For objects allocated on the C-heap.
 */
class HeapObject
{
public:
    void* operator new(size_t size);
    void operator delete(void* obj);
    void* operator new(size_t size, size_t extSize)
        { return HeapObject::operator new (size + extSize); };
    void operator delete(void* obj, size_t extSize)
        { HeapObject::operator delete (obj); }
};

/*! \brief For all reference counted objects.
 */
class ReferenceCountedObject
{
    volatile uint referenceCount_;

protected:
    virtual ~ReferenceCountedObject() { }
    virtual bool terminate() { return true; }

public:
    ReferenceCountedObject() : referenceCount_(1) { }

    void* operator new(size_t size) { return ::operator new(size); }
    void operator delete(void* p) { return ::operator delete(p); }
    void* operator new(size_t size, size_t extSize)
        { return ReferenceCountedObject::operator new (size + extSize); };
    void operator delete(void* obj, size_t extSize)
        { ReferenceCountedObject::operator delete (obj); }

    uint referenceCount() const { return referenceCount_; }

    uint retain();
    uint release();
};

/*@}*/} // namespace amd

#undef min // using std::min
#undef max // using std::max

#endif /*TOP_HPP_*/

<|endoftext|>


<commit_before>#include <benchmark/benchmark.h>
#include "generated.hpp"
#include <silicium/error_or.hpp>
#include <test/checkpoint.hpp>
#include <boost/asio/io_service.hpp>
#include <queue>

namespace
{
    struct in_process_pipe
    {
        boost::asio::io_service &dispatcher;
        boost::asio::const_buffer writing;
        boost::asio::mutable_buffer reading;
        std::function<void(boost::system::error_code, std::size_t)> write_callback;
        std::function<void(boost::system::error_code, std::size_t)> read_callback;

        explicit in_process_pipe(boost::asio::io_service &dispatcher)
            : dispatcher(dispatcher)
        {
        }

        template <class ConstBufferSequence, class CompletionToken>
        auto async_write_some(ConstBufferSequence const &buffers, CompletionToken &&token)
        {
            assert(!write_callback);
            assert(!boost::empty(buffers));
            using handler_type =
                typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::size_t)>::type;
            handler_type handler(std::forward<CompletionToken>(token));
            boost::asio::async_result<handler_type> result(handler);
            using boost::begin;
            writing = *begin(buffers);
            write_callback = std::move(handler);
            pump();
            return result.get();
        }

        template <class MutableBufferSequence, class CompletionToken>
        auto async_read_some(MutableBufferSequence const &buffers, CompletionToken &&token)
        {
            assert(!read_callback);
            assert(!boost::empty(buffers));
            using handler_type =
                typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::size_t)>::type;
            handler_type handler(std::forward<CompletionToken>(token));
            boost::asio::async_result<handler_type> result(handler);
            using boost::begin;
            reading = *begin(buffers);
            read_callback = std::move(handler);
            pump();
            return result.get();
        }

    private:
        void pump()
        {
            if (write_callback && read_callback)
            {
                std::size_t const copied = boost::asio::buffer_copy(reading, writing);
                dispatcher.post([
                    write_callback = Si::exchange(write_callback, nullptr),
                    read_callback = Si::exchange(read_callback, nullptr),
                    copied
                ]()
                                {
                                    write_callback({}, copied);
                                    read_callback({}, copied);
                                });
            }
        }
    };

    template <class AsyncStream>
    struct byte_counter
    {
        AsyncStream underlying;
        std::uint64_t written = 0;
        std::uint64_t read = 0;

        template <class... Args>
        explicit byte_counter(Args &&... args)
            : underlying(std::forward<Args>(args)...)
        {
        }

        template <class ConstBufferSequence, class CompletionToken>
        auto async_write_some(ConstBufferSequence const &buffers, CompletionToken &&token)
        {
            using handler_type =
                typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::size_t)>::type;
            handler_type handler(std::forward<CompletionToken>(token));
            boost::asio::async_result<handler_type> result(handler);
            underlying.async_write_some(buffers, warpcoil::cpp::wrap_handler(
                                                     [this](boost::system::error_code ec, std::size_t bytes_transferred,
                                                            decltype(handler) &handler)
                                                     {
                                                         written += bytes_transferred;
                                                         handler(ec, bytes_transferred);
                                                     },
                                                     std::move(handler)));
            return result.get();
        }

        template <class MutableBufferSequence, class CompletionToken>
        auto async_read_some(MutableBufferSequence const &buffers, CompletionToken &&token)
        {
            using handler_type =
                typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::size_t)>::type;
            handler_type handler(std::forward<CompletionToken>(token));
            boost::asio::async_result<handler_type> result(handler);
            underlying.async_read_some(buffers, warpcoil::cpp::wrap_handler(
                                                    [this](boost::system::error_code ec, std::size_t bytes_transferred,
                                                           decltype(handler) &handler)
                                                    {
                                                        read += bytes_transferred;
                                                        handler(ec, bytes_transferred);
                                                    },
                                                    std::move(handler)));
            return result.get();
        }
    };

    struct my_hello_service : async_binary_integer_function
    {
        void evaluate(std::tuple<std::uint64_t, std::uint64_t> argument,
                      std::function<void(boost::system::error_code, std::uint64_t)> on_result) override
        {
            on_result({}, std::get<0>(argument) * std::get<1>(argument));
        }
    };

    void RequestAndResponseOverInProcessPipe(benchmark::State &state)
    {
        boost::asio::io_service io;
        byte_counter<in_process_pipe> client_to_server(io);
        byte_counter<in_process_pipe> server_to_client(io);
        my_hello_service server_impl;
        warpcoil::cpp::message_splitter<decltype(client_to_server)> server_splitter(client_to_server);
        warpcoil::cpp::buffered_writer<decltype(server_to_client)> server_writer(server_to_client);
        async_binary_integer_function_server<decltype(server_impl), decltype(client_to_server),
                                             decltype(server_to_client)> server(server_impl, server_splitter,
                                                                                server_writer);

        warpcoil::cpp::message_splitter<decltype(server_to_client)> client_splitter(server_to_client);
        warpcoil::cpp::buffered_writer<decltype(client_to_server)> client_writer(client_to_server);
        async_binary_integer_function_client<decltype(server_to_client), decltype(client_to_server)> client(
            client_writer, client_splitter);

        while (state.KeepRunning())
        {
            warpcoil::checkpoint client_side;
            client.evaluate(std::make_tuple(34, 45), [&client_side](boost::system::error_code ec, std::uint64_t result)
                            {
                                client_side.enter();
                                Si::throw_if_error(ec);
                                if (result != (34u * 45u))
                                {
                                    boost::throw_exception(std::logic_error("wrong result"));
                                }
                            });
            warpcoil::checkpoint server_side;
            server.serve_one_request([&server_side](boost::system::error_code ec)
                                     {
                                         server_side.enter();
                                         Si::throw_if_error(ec);
                                     });
            server_side.enable();
            client_side.enable();
            io.reset();
            io.run();
        }

        std::uint64_t const total_transferred = client_to_server.read + client_to_server.written;
        if (total_transferred > (std::numeric_limits<std::size_t>::max)())
        {
            boost::throw_exception(std::logic_error("Transferred bytes overflowed"));
        }
        state.SetBytesProcessed(static_cast<size_t>(total_transferred));
    }
    BENCHMARK(RequestAndResponseOverInProcessPipe);
}
<commit_msg>prepare benchmark of different messages sizes<commit_after>#include <benchmark/benchmark.h>
#include "generated.hpp"
#include <silicium/error_or.hpp>
#include <test/checkpoint.hpp>
#include <boost/asio/io_service.hpp>
#include <queue>

namespace
{
    struct in_process_pipe
    {
        boost::asio::io_service &dispatcher;
        boost::asio::const_buffer writing;
        boost::asio::mutable_buffer reading;
        std::function<void(boost::system::error_code, std::size_t)> write_callback;
        std::function<void(boost::system::error_code, std::size_t)> read_callback;

        explicit in_process_pipe(boost::asio::io_service &dispatcher)
            : dispatcher(dispatcher)
        {
        }

        template <class ConstBufferSequence, class CompletionToken>
        auto async_write_some(ConstBufferSequence const &buffers, CompletionToken &&token)
        {
            assert(!write_callback);
            assert(!boost::empty(buffers));
            using handler_type =
                typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::size_t)>::type;
            handler_type handler(std::forward<CompletionToken>(token));
            boost::asio::async_result<handler_type> result(handler);
            using boost::begin;
            writing = *begin(buffers);
            write_callback = std::move(handler);
            pump();
            return result.get();
        }

        template <class MutableBufferSequence, class CompletionToken>
        auto async_read_some(MutableBufferSequence const &buffers, CompletionToken &&token)
        {
            assert(!read_callback);
            assert(!boost::empty(buffers));
            using handler_type =
                typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::size_t)>::type;
            handler_type handler(std::forward<CompletionToken>(token));
            boost::asio::async_result<handler_type> result(handler);
            using boost::begin;
            reading = *begin(buffers);
            read_callback = std::move(handler);
            pump();
            return result.get();
        }

    private:
        void pump()
        {
            if (write_callback && read_callback)
            {
                std::size_t const copied = boost::asio::buffer_copy(reading, writing);
                dispatcher.post([
                    write_callback = Si::exchange(write_callback, nullptr),
                    read_callback = Si::exchange(read_callback, nullptr),
                    copied
                ]()
                                {
                                    write_callback({}, copied);
                                    read_callback({}, copied);
                                });
            }
        }
    };

    template <class AsyncStream>
    struct byte_counter
    {
        AsyncStream underlying;
        std::uint64_t written = 0;
        std::uint64_t read = 0;

        template <class... Args>
        explicit byte_counter(Args &&... args)
            : underlying(std::forward<Args>(args)...)
        {
        }

        template <class ConstBufferSequence, class CompletionToken>
        auto async_write_some(ConstBufferSequence const &buffers, CompletionToken &&token)
        {
            using handler_type =
                typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::size_t)>::type;
            handler_type handler(std::forward<CompletionToken>(token));
            boost::asio::async_result<handler_type> result(handler);
            underlying.async_write_some(buffers, warpcoil::cpp::wrap_handler(
                                                     [this](boost::system::error_code ec, std::size_t bytes_transferred,
                                                            decltype(handler) &handler)
                                                     {
                                                         written += bytes_transferred;
                                                         handler(ec, bytes_transferred);
                                                     },
                                                     std::move(handler)));
            return result.get();
        }

        template <class MutableBufferSequence, class CompletionToken>
        auto async_read_some(MutableBufferSequence const &buffers, CompletionToken &&token)
        {
            using handler_type =
                typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::size_t)>::type;
            handler_type handler(std::forward<CompletionToken>(token));
            boost::asio::async_result<handler_type> result(handler);
            underlying.async_read_some(buffers, warpcoil::cpp::wrap_handler(
                                                    [this](boost::system::error_code ec, std::size_t bytes_transferred,
                                                           decltype(handler) &handler)
                                                    {
                                                        read += bytes_transferred;
                                                        handler(ec, bytes_transferred);
                                                    },
                                                    std::move(handler)));
            return result.get();
        }
    };

    struct my_hello_service : async_binary_integer_function
    {
        void evaluate(std::tuple<std::uint64_t, std::uint64_t> argument,
                      std::function<void(boost::system::error_code, std::uint64_t)> on_result) override
        {
            on_result({}, std::get<0>(argument) * std::get<1>(argument));
        }
    };

    template <class LoopBody>
    void BenchmarkWithInProcessPipe(benchmark::State &state, LoopBody const &body)
    {
        boost::asio::io_service io;
        byte_counter<in_process_pipe> client_to_server(io);
        byte_counter<in_process_pipe> server_to_client(io);
        my_hello_service server_impl;
        warpcoil::cpp::message_splitter<decltype(client_to_server)> server_splitter(client_to_server);
        warpcoil::cpp::buffered_writer<decltype(server_to_client)> server_writer(server_to_client);
        async_binary_integer_function_server<decltype(server_impl), decltype(client_to_server),
                                             decltype(server_to_client)> server(server_impl, server_splitter,
                                                                                server_writer);

        warpcoil::cpp::message_splitter<decltype(server_to_client)> client_splitter(server_to_client);
        warpcoil::cpp::buffered_writer<decltype(client_to_server)> client_writer(client_to_server);
        async_binary_integer_function_client<decltype(server_to_client), decltype(client_to_server)> client(
            client_writer, client_splitter);

        while (state.KeepRunning())
        {
            body(io, client, server);
        }

        std::uint64_t const total_transferred = client_to_server.read + client_to_server.written;
        if (total_transferred > (std::numeric_limits<std::size_t>::max)())
        {
            boost::throw_exception(std::logic_error("Transferred bytes overflowed"));
        }
        state.SetBytesProcessed(static_cast<size_t>(total_transferred));
    }

    void TinyRequestAndResponseOverInProcessPipe(benchmark::State &state)
    {
        BenchmarkWithInProcessPipe(state, [](boost::asio::io_service &io, auto &client, auto &server)
                                   {
                                       warpcoil::checkpoint client_side;
                                       client.evaluate(
                                           std::make_tuple(34, 45),
                                           [&client_side](boost::system::error_code ec, std::uint64_t result)
                                           {
                                               client_side.enter();
                                               Si::throw_if_error(ec);
                                               if (result != (34u * 45u))
                                               {
                                                   boost::throw_exception(std::logic_error("wrong result"));
                                               }
                                           });
                                       warpcoil::checkpoint server_side;
                                       server.serve_one_request([&server_side](boost::system::error_code ec)
                                                                {
                                                                    server_side.enter();
                                                                    Si::throw_if_error(ec);
                                                                });
                                       server_side.enable();
                                       client_side.enable();
                                       io.reset();
                                       io.run();
                                   });
    }
    BENCHMARK(TinyRequestAndResponseOverInProcessPipe);
}
<|endoftext|>


<commit_before>#include "DraggableView.h"

#include "cinder/app/App.h"
#include "poScene/ShapeView.h"

namespace po
{
	namespace scene
	{
		// Drag And Drop View
		DraggableViewRef DraggableView::create()
		{
			DraggableViewRef ref( new DraggableView() );
			ref->setup();
			return ref;
		}

		DraggableViewRef DraggableView::create( ci::vec2 snapBackPosition )
		{
			DraggableViewRef ref( new DraggableView( snapBackPosition ) );
			ref->setup();
			return ref;
		}

		void DraggableView::startHoverTimer( float seconds )
		{
			if( !mIsUsingTimer ) {
				mPreviousTime = ci::app::getElapsedSeconds();
				mIsUsingTimer = true;
			}

			mTimerDuration = seconds;

		}

		void DraggableView::stopHoverTimer()
		{
			if( mIsUsingTimer ) {
				mIsUsingTimer = false;
			}

			mHoverLastedTime = 0.f;
		}

		DraggableView::DraggableView()
			: mIsDragging( false )
			, mDraggingEventId( DraggableView::DRAGGING_EVENT_ID_NONE )
			, mSnapsBack( false )
			, mIsUsingTimer( false )
		{
		}

		DraggableView::DraggableView( ci::vec2 snapBackPosition )
			: mIsDragging( false )
			, mDraggingEventId( DraggableView::DRAGGING_EVENT_ID_NONE )
			, mSnapsBack( true )
			, mSnapPosition( snapBackPosition )
		{
			setPosition( snapBackPosition );

		}

		void DraggableView::setup()
		{
			connectEvents();
		}

		void DraggableView::update()
		{
			po::scene::View::update();

			if( !mIsUsingTimer ) {
				mPreviousTime = ci::app::getElapsedSeconds();
			}
			else {
				mHoverLastedTime = ci::app::getElapsedSeconds() - mPreviousTime;
			}

			if( mHoverLastedTime > 1.f ) {
				stopHoverTimer();
				DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
				mSignalDragHoverTimersUp.emit( ref );
				mIsDragging = false;
			}

			//ci::app::console() << mHoverLastedTime << std::endl;
		}

		void DraggableView::setSnapBackPosition( ci::vec2 snapBackPosition )
		{
			mSnapPosition = snapBackPosition;
			mSnapsBack = true;
		}

		void DraggableView::connectEvents()
		{
			// Attach drag events
			mConnections += getSignal( po::scene::MouseEvent::DOWN_INSIDE ).connect( std::bind( &DraggableView::mouseEventHandler, this, std::placeholders::_1 ) );
			mConnections += getSignal( po::scene::MouseEvent::DRAG ).connect( std::bind( &DraggableView::mouseEventHandler, this, std::placeholders::_1 ) );
			mConnections += getSignal( po::scene::MouseEvent::UP ).connect( std::bind( &DraggableView::mouseEventHandler, this, std::placeholders::_1 ) );
		}

		void DraggableView::setInteractionEnabled( bool enabled )
		{
			bool isEnabled = isInteractionEnabled();

			if( isEnabled == enabled ) {
				return;
			}

			po::scene::View::setInteractionEnabled( enabled );

			if( !enabled ) {
				bool isDragging = mIsDragging;
				mIsDragging = false;

				if( isDragging ) {
					DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
					mSignalDragCancelled.emit( ref );
				}
			}
		}

		void DraggableView::handleDragStartEvent( ci::vec2 localPos, ci::vec2 windowPos, int eventId )
		{
			ci::vec2 parentPos = getSuperview()->windowToLocal( windowPos );

			mPrevDragPosition = parentPos;
			mWindowDragPosition = windowPos;
			mDraggingEventId = eventId;

			DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
			mSignalDragBegan.emit( ref );

			mIsDragging = true;
		}

		void DraggableView::handleDragEvent( ci::vec2 localPos, ci::vec2 windowPos, int eventId )
		{
			if( mIsDragging && mDraggingEventId == eventId ) {
				ci::vec2 parentPos = getSuperview()->windowToLocal( windowPos );

				setPosition( getPosition() + ( parentPos - mPrevDragPosition ) );
				mPrevDragPosition = parentPos;
				mWindowDragPosition = windowPos;

				DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
				mSignalDragged.emit( ref );
			}
		}

		void DraggableView::handleDragEndEvent( ci::vec2 localPos, ci::vec2 windowPos, int eventId )
		{
			if( mIsDragging ) {
				mIsDragging = false;
				DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
				mSignalDragEnded.emit( ref );
			}
		}

		void DraggableView::mouseEventHandler( po::scene::MouseEvent& event )
		{
			switch( event.getType() ) {
				// Start Dragging
				case po::scene::MouseEvent::DOWN_INSIDE:
					handleDragStartEvent( event.getLocalPos(), event.getWindowPos(), 0 );
					break;

				// Move if we are dragging
				case po::scene::MouseEvent::DRAG:
					handleDragEvent( event.getLocalPos(), event.getWindowPos(), 0 );
					break;

				// Stop any dragging
				case po::scene::MouseEvent::UP:
					handleDragEndEvent( event.getLocalPos(), event.getWindowPos(), 0 );
					break;
			}
		}

		void DraggableView::touchEventHandler( po::scene::TouchEvent& event )
		{
			switch( event.getType() ) {
				// Start Dragging
				case po::scene::TouchEvent::BEGAN_INSIDE:
					handleDragStartEvent( event.getLocalPos(), event.getWindowPos(), event.getId() );
					break;

				// Move if we are dragging
				case po::scene::TouchEvent::MOVED:
					handleDragEvent( event.getLocalPos(), event.getWindowPos(), event.getId() );
					break;

				// Stop any dragging
				case po::scene::TouchEvent::ENDED:
					handleDragEndEvent( event.getLocalPos(), event.getWindowPos(), event.getId() );
					break;
			}
		}
	}
}
<commit_msg>fixed hover drag not ending bug<commit_after>#include "DraggableView.h"

#include "cinder/app/App.h"
#include "poScene/ShapeView.h"

namespace po
{
	namespace scene
	{
		// Drag And Drop View
		DraggableViewRef DraggableView::create()
		{
			DraggableViewRef ref( new DraggableView() );
			ref->setup();
			return ref;
		}

		DraggableViewRef DraggableView::create( ci::vec2 snapBackPosition )
		{
			DraggableViewRef ref( new DraggableView( snapBackPosition ) );
			ref->setup();
			return ref;
		}

		void DraggableView::startHoverTimer( float seconds )
		{
			if( !mIsUsingTimer ) {
				mPreviousTime = ci::app::getElapsedSeconds();
				mIsUsingTimer = true;
			}

			mTimerDuration = seconds;

		}

		void DraggableView::stopHoverTimer()
		{
			if( mIsUsingTimer ) {
				mIsUsingTimer = false;
			}

			mHoverLastedTime = 0.f;
		}

		DraggableView::DraggableView()
			: mIsDragging( false )
			, mDraggingEventId( DraggableView::DRAGGING_EVENT_ID_NONE )
			, mSnapsBack( false )
			, mIsUsingTimer( false )
		{
		}

		DraggableView::DraggableView( ci::vec2 snapBackPosition )
			: mIsDragging( false )
			, mDraggingEventId( DraggableView::DRAGGING_EVENT_ID_NONE )
			, mSnapsBack( true )
			, mSnapPosition( snapBackPosition )
		{
			setPosition( snapBackPosition );

		}

		void DraggableView::setup()
		{
			connectEvents();
		}

		void DraggableView::update()
		{
			po::scene::View::update();

			if( !mIsUsingTimer ) {
				mPreviousTime = ci::app::getElapsedSeconds();
			}
			else {
				mHoverLastedTime = ci::app::getElapsedSeconds() - mPreviousTime;
			}

			if( mHoverLastedTime > 1.f ) {
				stopHoverTimer();
				DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
				mSignalDragHoverTimersUp.emit( ref );
				mSignalDragEnded.emit( ref );
				mIsDragging = false;
			}

			//ci::app::console() << mHoverLastedTime << std::endl;
		}

		void DraggableView::setSnapBackPosition( ci::vec2 snapBackPosition )
		{
			mSnapPosition = snapBackPosition;
			mSnapsBack = true;
		}

		void DraggableView::connectEvents()
		{
			// Attach drag events
			mConnections += getSignal( po::scene::MouseEvent::DOWN_INSIDE ).connect( std::bind( &DraggableView::mouseEventHandler, this, std::placeholders::_1 ) );
			mConnections += getSignal( po::scene::MouseEvent::DRAG ).connect( std::bind( &DraggableView::mouseEventHandler, this, std::placeholders::_1 ) );
			mConnections += getSignal( po::scene::MouseEvent::UP ).connect( std::bind( &DraggableView::mouseEventHandler, this, std::placeholders::_1 ) );
		}

		void DraggableView::setInteractionEnabled( bool enabled )
		{
			bool isEnabled = isInteractionEnabled();

			if( isEnabled == enabled ) {
				return;
			}

			po::scene::View::setInteractionEnabled( enabled );

			if( !enabled ) {
				bool isDragging = mIsDragging;
				mIsDragging = false;

				if( isDragging ) {
					DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
					mSignalDragCancelled.emit( ref );
				}
			}
		}

		void DraggableView::handleDragStartEvent( ci::vec2 localPos, ci::vec2 windowPos, int eventId )
		{
			ci::vec2 parentPos = getSuperview()->windowToLocal( windowPos );

			mPrevDragPosition = parentPos;
			mWindowDragPosition = windowPos;
			mDraggingEventId = eventId;

			DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
			mSignalDragBegan.emit( ref );

			mIsDragging = true;
		}

		void DraggableView::handleDragEvent( ci::vec2 localPos, ci::vec2 windowPos, int eventId )
		{
			if( mIsDragging && mDraggingEventId == eventId ) {
				ci::vec2 parentPos = getSuperview()->windowToLocal( windowPos );

				setPosition( getPosition() + ( parentPos - mPrevDragPosition ) );
				mPrevDragPosition = parentPos;
				mWindowDragPosition = windowPos;

				DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
				mSignalDragged.emit( ref );
			}
		}

		void DraggableView::handleDragEndEvent( ci::vec2 localPos, ci::vec2 windowPos, int eventId )
		{
			if( mIsDragging ) {
				mIsDragging = false;
				DraggableViewRef ref = std::static_pointer_cast<DraggableView>( shared_from_this() );
				mSignalDragEnded.emit( ref );
			}
		}

		void DraggableView::mouseEventHandler( po::scene::MouseEvent& event )
		{
			switch( event.getType() ) {
				// Start Dragging
				case po::scene::MouseEvent::DOWN_INSIDE:
					handleDragStartEvent( event.getLocalPos(), event.getWindowPos(), 0 );
					break;

				// Move if we are dragging
				case po::scene::MouseEvent::DRAG:
					handleDragEvent( event.getLocalPos(), event.getWindowPos(), 0 );
					break;

				// Stop any dragging
				case po::scene::MouseEvent::UP:
					handleDragEndEvent( event.getLocalPos(), event.getWindowPos(), 0 );
					break;
			}
		}

		void DraggableView::touchEventHandler( po::scene::TouchEvent& event )
		{
			switch( event.getType() ) {
				// Start Dragging
				case po::scene::TouchEvent::BEGAN_INSIDE:
					handleDragStartEvent( event.getLocalPos(), event.getWindowPos(), event.getId() );
					break;

				// Move if we are dragging
				case po::scene::TouchEvent::MOVED:
					handleDragEvent( event.getLocalPos(), event.getWindowPos(), event.getId() );
					break;

				// Stop any dragging
				case po::scene::TouchEvent::ENDED:
					handleDragEndEvent( event.getLocalPos(), event.getWindowPos(), event.getId() );
					break;
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
 * bridge.cpp
 *
 *  Created on: Jun 11, 2015
 *      Author: parallels
 */

extern "C"{
#include "postgres.h"

#include "access/heapam.h"
#include "utils/rel.h"
#include "utils/ruleutils.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
}

class Bridge {

 public:

  /**
   * @brief Getting the relation name.
   * @param relation id relation id
   */
  static char* GetRelationName(Oid relation_id) {
      Relation relation;
      char *relation_name;

      relation = relation_open(relation_id, NoLock);

      // Get name for given relation
      relation_name = quote_qualified_identifier(get_namespace_name(RelationGetNamespace(relation)), RelationGetRelationName(relation));

      relation_close(relation, NoLock);

      return relation_name;
   }

};

<commit_msg>Minor fix<commit_after>/*
 * bridge.cpp
 *
 *  Created on: Jun 11, 2015
 *      Author: Jinwoong Kim
 */

extern "C"{
#include "postgres.h"

#include "access/heapam.h"
#include "utils/rel.h"
#include "utils/ruleutils.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
}

class Bridge {

 public:

  /**
   * @brief Getting the relation name.
   * @param relation id relation id
   */
  static char* GetRelationName(Oid relation_id) {
      Relation relation;
      char *relation_name;

      relation = relation_open(relation_id, NoLock);

      // Get name for given relation
      relation_name = quote_qualified_identifier(get_namespace_name(RelationGetNamespace(relation)), RelationGetRelationName(relation));

      relation_close(relation, NoLock);

      return relation_name;
   }

};

<|endoftext|>


<commit_before>#pragma once

#include <warpcoil/cpp/buffered_writer.hpp>
#include <map>

namespace warpcoil
{
    namespace cpp
    {
        enum class client_pipeline_request_status
        {
            ok,
            failure
        };

        template <class AsyncWriteStream, class AsyncReadStream>
        struct client_pipeline
        {
            explicit client_pipeline(AsyncWriteStream &requests, AsyncReadStream &responses)
                : writer(requests)
                , responses(responses)
                , response_buffer_used(0)
                , state(response_state::not_expecting_response)
            {
            }

            template <class ResultParser, class RequestBuilder, class ResultHandler>
            void request(RequestBuilder build_request, ResultHandler &handler)
            {
                if (!writer.is_running())
                {
                    writer.async_run([this](boost::system::error_code ec)
                                     {
                                         on_error(ec);
                                     });
                }
                auto sink = Si::Sink<std::uint8_t>::erase(writer.buffer_sink());
                request_id const current_id = next_request_id;
                ++next_request_id;
                write_integer(sink, current_id);
                switch (build_request(sink))
                {
                case client_pipeline_request_status::ok:
                    break;

                case client_pipeline_request_status::failure:
                    return;
                }
                writer.send_buffer();
                expected_responses.insert(std::make_pair(
                    current_id,
                    expected_response{[handler](boost::system::error_code const error) mutable
                                      {
                                          handler(error, typename ResultParser::result_type{});
                                      },
                                      [this, handler]() mutable
                                      {
                                          assert(state == response_state::parsing_result);
                                          begin_parse_value(
                                              responses, boost::asio::buffer(response_buffer), response_buffer_used,
                                              ResultParser(),
                                              parse_result_operation<ResultHandler, typename ResultParser::result_type>(
                                                  *this, std::move(handler)));
                                      }}));
                switch (state)
                {
                case response_state::not_expecting_response:
                    parse_header(handler);
                    break;

                case response_state::parsing_header:
                case response_state::parsing_result:
                    break;
                }
            }

        private:
            enum response_state
            {
                not_expecting_response,
                parsing_header,
                parsing_result
            };

            struct expected_response
            {
                std::function<void(boost::system::error_code)> on_error;
                std::function<void()> parse_result;
            };

            buffered_writer<AsyncWriteStream> writer;
            std::array<std::uint8_t, 512> response_buffer;
            AsyncReadStream &responses;
            std::size_t response_buffer_used;
            request_id next_request_id = 0;
            response_state state;
            std::map<request_id, expected_response> expected_responses;

            template <class DummyHandler>
            void parse_header(DummyHandler &handler)
            {
                begin_parse_value(responses, boost::asio::buffer(response_buffer), response_buffer_used,
                                  integer_parser<request_id>(), parse_header_operation<DummyHandler>(*this, handler));
                state = response_state::parsing_header;
            }

            void on_error(boost::system::error_code ec)
            {
                std::map<request_id, expected_response> local_expected_responses = std::move(expected_responses);
                assert(expected_responses.empty());
                state = response_state::not_expecting_response;
                for (auto const &entry : local_expected_responses)
                {
                    entry.second.on_error(ec);
                }
            }

            template <class DummyHandler>
            struct parse_header_operation
            {
                client_pipeline &pipeline;
                DummyHandler handler;

                explicit parse_header_operation(client_pipeline &pipeline, DummyHandler handler)
                    : pipeline(pipeline)
                    , handler(std::move(handler))
                {
                }

                void operator()(boost::system::error_code ec, request_id const id) const
                {
                    assert(pipeline.state == response_state::parsing_header);
                    if (!!ec)
                    {
                        pipeline.on_error(ec);
                        return;
                    }
                    auto const entry_found = pipeline.expected_responses.find(id);
                    if (entry_found == pipeline.expected_responses.end())
                    {
                        pipeline.state = response_state::not_expecting_response;
                        throw std::logic_error("TODO handle protocol violation");
                    }
                    std::function<void()> parse_result = std::move(entry_found->second.parse_result);
                    pipeline.expected_responses.erase(entry_found);
                    pipeline.state = response_state::parsing_result;
                    parse_result();
                }

                template <class Function>
                friend void asio_handler_invoke(Function &&f, parse_header_operation *operation)
                {
                    using boost::asio::asio_handler_invoke;
                    asio_handler_invoke(f, &operation->handler);
                }
            };

            template <class ResultHandler, class Result>
            struct parse_result_operation
            {
                client_pipeline &pipeline;
                ResultHandler handler;

                explicit parse_result_operation(client_pipeline &pipeline, ResultHandler handler)
                    : pipeline(pipeline)
                    , handler(std::move(handler))
                {
                }

                void operator()(boost::system::error_code ec, Result result)
                {
                    assert(pipeline.state == response_state::parsing_result);
                    if (!!ec)
                    {
                        pipeline.on_error(ec);
                        return;
                    }
                    if (pipeline.expected_responses.empty())
                    {
                        pipeline.state = response_state::not_expecting_response;
                    }
                    else
                    {
                        pipeline.parse_header(handler);
                        assert(pipeline.state == response_state::parsing_header);
                    }
                    handler(ec, std::move(result));
                }

                template <class Function>
                friend void asio_handler_invoke(Function &&f, parse_result_operation *operation)
                {
                    using boost::asio::asio_handler_invoke;
                    asio_handler_invoke(f, &operation->handler);
                }
            };
        };
    }
}
<commit_msg>try to support immediate completion of begin_parse_value in client_pipeline<commit_after>#pragma once

#include <warpcoil/cpp/buffered_writer.hpp>
#include <map>

namespace warpcoil
{
    namespace cpp
    {
        enum class client_pipeline_request_status
        {
            ok,
            failure
        };

        template <class AsyncWriteStream, class AsyncReadStream>
        struct client_pipeline
        {
            explicit client_pipeline(AsyncWriteStream &requests, AsyncReadStream &responses)
                : writer(requests)
                , responses(responses)
                , response_buffer_used(0)
                , state(response_state::not_expecting_response)
            {
            }

            template <class ResultParser, class RequestBuilder, class ResultHandler>
            void request(RequestBuilder build_request, ResultHandler &handler)
            {
                if (!writer.is_running())
                {
                    writer.async_run([this](boost::system::error_code ec)
                                     {
                                         on_error(ec);
                                     });
                }
                auto sink = Si::Sink<std::uint8_t>::erase(writer.buffer_sink());
                request_id const current_id = next_request_id;
                ++next_request_id;
                write_integer(sink, current_id);
                switch (build_request(sink))
                {
                case client_pipeline_request_status::ok:
                    break;

                case client_pipeline_request_status::failure:
                    return;
                }
                writer.send_buffer();
                expected_responses.insert(std::make_pair(
                    current_id,
                    expected_response{[handler](boost::system::error_code const error) mutable
                                      {
                                          handler(error, typename ResultParser::result_type{});
                                      },
                                      [this, handler]() mutable
                                      {
                                          assert(state == response_state::parsing_result);
                                          begin_parse_value(
                                              responses, boost::asio::buffer(response_buffer), response_buffer_used,
                                              ResultParser(),
                                              parse_result_operation<ResultHandler, typename ResultParser::result_type>(
                                                  *this, std::move(handler)));
                                      }}));
                switch (state)
                {
                case response_state::not_expecting_response:
                    parse_header(handler);
                    break;

                case response_state::parsing_header:
                case response_state::parsing_result:
                    break;
                }
            }

        private:
            enum response_state
            {
                not_expecting_response,
                parsing_header,
                parsing_result
            };

            struct expected_response
            {
                std::function<void(boost::system::error_code)> on_error;
                std::function<void()> parse_result;
            };

            buffered_writer<AsyncWriteStream> writer;
            std::array<std::uint8_t, 512> response_buffer;
            AsyncReadStream &responses;
            std::size_t response_buffer_used;
            request_id next_request_id = 0;
            response_state state;
            std::map<request_id, expected_response> expected_responses;

            template <class DummyHandler>
            void parse_header(DummyHandler &handler)
            {
                state = response_state::parsing_header;
                begin_parse_value(responses, boost::asio::buffer(response_buffer), response_buffer_used,
                                  integer_parser<request_id>(), parse_header_operation<DummyHandler>(*this, handler));
            }

            void on_error(boost::system::error_code ec)
            {
                std::map<request_id, expected_response> local_expected_responses = std::move(expected_responses);
                assert(expected_responses.empty());
                state = response_state::not_expecting_response;
                for (auto const &entry : local_expected_responses)
                {
                    entry.second.on_error(ec);
                }
            }

            template <class DummyHandler>
            struct parse_header_operation
            {
                client_pipeline &pipeline;
                DummyHandler handler;

                explicit parse_header_operation(client_pipeline &pipeline, DummyHandler handler)
                    : pipeline(pipeline)
                    , handler(std::move(handler))
                {
                }

                void operator()(boost::system::error_code ec, request_id const id) const
                {
                    assert(pipeline.state == response_state::parsing_header);
                    if (!!ec)
                    {
                        pipeline.on_error(ec);
                        return;
                    }
                    auto const entry_found = pipeline.expected_responses.find(id);
                    if (entry_found == pipeline.expected_responses.end())
                    {
                        pipeline.state = response_state::not_expecting_response;
                        throw std::logic_error("TODO handle protocol violation");
                    }
                    std::function<void()> parse_result = std::move(entry_found->second.parse_result);
                    pipeline.expected_responses.erase(entry_found);
                    pipeline.state = response_state::parsing_result;
                    parse_result();
                }

                template <class Function>
                friend void asio_handler_invoke(Function &&f, parse_header_operation *operation)
                {
                    using boost::asio::asio_handler_invoke;
                    asio_handler_invoke(f, &operation->handler);
                }
            };

            template <class ResultHandler, class Result>
            struct parse_result_operation
            {
                client_pipeline &pipeline;
                ResultHandler handler;

                explicit parse_result_operation(client_pipeline &pipeline, ResultHandler handler)
                    : pipeline(pipeline)
                    , handler(std::move(handler))
                {
                }

                void operator()(boost::system::error_code ec, Result result)
                {
                    assert(pipeline.state == response_state::parsing_result);
                    if (!!ec)
                    {
                        pipeline.on_error(ec);
                        return;
                    }
                    if (pipeline.expected_responses.empty())
                    {
                        pipeline.state = response_state::not_expecting_response;
                    }
                    else
                    {
                        pipeline.parse_header(handler);
                        assert(pipeline.state == response_state::parsing_header);
                    }
                    handler(ec, std::move(result));
                }

                template <class Function>
                friend void asio_handler_invoke(Function &&f, parse_result_operation *operation)
                {
                    using boost::asio::asio_handler_invoke;
                    asio_handler_invoke(f, &operation->handler);
                }
            };
        };
    }
}
<|endoftext|>


<commit_before>/*
* TLS v1.0 and v1.2 PRFs
* (C) 2004-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/prf_tls.h>
#include <botan/internal/xor_buf.h>
#include <botan/hmac.h>
#include <botan/md5.h>
#include <botan/sha160.h>

namespace Botan {

namespace {

/*
* TLS PRF P_hash function
*/
void P_hash(MemoryRegion<byte>& output,
            MessageAuthenticationCode* mac,
            const byte secret[], size_t secret_len,
            const byte seed[], size_t seed_len)
   {
   try
      {
      mac->set_key(secret, secret_len);
      }
   catch(Invalid_Key_Length)
      {
      throw Internal_Error("The premaster secret is too long for the PRF");
      }

   SecureVector<byte> A(seed, seed_len);

   size_t offset = 0;

   while(offset != output.size())
      {
      const size_t this_block_len =
         std::min<size_t>(mac->output_length(), output.size() - offset);

      A = mac->process(A);

      mac->update(A);
      mac->update(seed, seed_len);
      SecureVector<byte> block = mac->final();

      xor_buf(&output[offset], &block[0], this_block_len);
      offset += this_block_len;
      }
   }

}

/*
* TLS PRF Constructor and Destructor
*/
TLS_PRF::TLS_PRF()
   {
   hmac_md5 = new HMAC(new MD5);
   hmac_sha1 = new HMAC(new SHA_160);
   }

TLS_PRF::~TLS_PRF()
   {
   delete hmac_md5;
   delete hmac_sha1;
   }

/*
* TLS PRF
*/
SecureVector<byte> TLS_PRF::derive(size_t key_len,
                                   const byte secret[], size_t secret_len,
                                   const byte seed[], size_t seed_len) const
   {
   SecureVector<byte> output(key_len);

   size_t S1_len = (secret_len + 1) / 2,
          S2_len = (secret_len + 1) / 2;
   const byte* S1 = secret;
   const byte* S2 = secret + (secret_len - S2_len);

   P_hash(output, hmac_md5,  S1, S1_len, seed, seed_len);
   P_hash(output, hmac_sha1, S2, S2_len, seed, seed_len);

   return output;
   }

/*
* TLS v1.2 PRF Constructor and Destructor
*/
TLS_12_PRF::TLS_12_PRF(MessageAuthenticationCode* mac) : hmac(mac)
   {
   }

TLS_12_PRF::~TLS_12_PRF()
   {
   delete hmac;
   }

SecureVector<byte> TLS_12_PRF::derive(size_t key_len,
                                      const byte secret[], size_t secret_len,
                                      const byte seed[], size_t seed_len) const
   {
   SecureVector<byte> output(key_len);

   P_hash(output, hmac, secret, secret_len, seed, seed_len);

   return output;
   }

}
<commit_msg>Report the length of the pre master secret. Who knows if when this happens it'll be reproductible, etc, might as well have the information immediately.<commit_after>/*
* TLS v1.0 and v1.2 PRFs
* (C) 2004-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/prf_tls.h>
#include <botan/internal/xor_buf.h>
#include <botan/hmac.h>
#include <botan/md5.h>
#include <botan/sha160.h>

namespace Botan {

namespace {

/*
* TLS PRF P_hash function
*/
void P_hash(MemoryRegion<byte>& output,
            MessageAuthenticationCode* mac,
            const byte secret[], size_t secret_len,
            const byte seed[], size_t seed_len)
   {
   try
      {
      mac->set_key(secret, secret_len);
      }
   catch(Invalid_Key_Length)
      {
      throw Internal_Error("The premaster secret of " + to_string(secret_len) +
                           " bytes is too long for the PRF");
      }

   SecureVector<byte> A(seed, seed_len);

   size_t offset = 0;

   while(offset != output.size())
      {
      const size_t this_block_len =
         std::min<size_t>(mac->output_length(), output.size() - offset);

      A = mac->process(A);

      mac->update(A);
      mac->update(seed, seed_len);
      SecureVector<byte> block = mac->final();

      xor_buf(&output[offset], &block[0], this_block_len);
      offset += this_block_len;
      }
   }

}

/*
* TLS PRF Constructor and Destructor
*/
TLS_PRF::TLS_PRF()
   {
   hmac_md5 = new HMAC(new MD5);
   hmac_sha1 = new HMAC(new SHA_160);
   }

TLS_PRF::~TLS_PRF()
   {
   delete hmac_md5;
   delete hmac_sha1;
   }

/*
* TLS PRF
*/
SecureVector<byte> TLS_PRF::derive(size_t key_len,
                                   const byte secret[], size_t secret_len,
                                   const byte seed[], size_t seed_len) const
   {
   SecureVector<byte> output(key_len);

   size_t S1_len = (secret_len + 1) / 2,
          S2_len = (secret_len + 1) / 2;
   const byte* S1 = secret;
   const byte* S2 = secret + (secret_len - S2_len);

   P_hash(output, hmac_md5,  S1, S1_len, seed, seed_len);
   P_hash(output, hmac_sha1, S2, S2_len, seed, seed_len);

   return output;
   }

/*
* TLS v1.2 PRF Constructor and Destructor
*/
TLS_12_PRF::TLS_12_PRF(MessageAuthenticationCode* mac) : hmac(mac)
   {
   }

TLS_12_PRF::~TLS_12_PRF()
   {
   delete hmac;
   }

SecureVector<byte> TLS_12_PRF::derive(size_t key_len,
                                      const byte secret[], size_t secret_len,
                                      const byte seed[], size_t seed_len) const
   {
   SecureVector<byte> output(key_len);

   P_hash(output, hmac, secret, secret_len, seed, seed_len);

   return output;
   }

}
<|endoftext|>