<commit_before>#include "module_webcams.h"
#include <Module_Webcams/form_webcams.h>
#include <assert.h>

Module_Webcams::Module_Webcams( QString id ) :
        RobotModule_MT( id )
{
//    VI.setUseCallback( true );
//    leftConnected = false;
//    rightConnected = false;
//    bottomConnected = false;
    leftFramerate = 5;
    rightFramerate = 5;
    bottomFramerate = 5;

    leftCap = NULL;
    rightCap = NULL;
    bottomCap = NULL;

    nCams = this->numOfCams();

    leftID = 1;
    rightID = 0;
    bottomID = 2;

    settingsChanged();

    leftFrame = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
    rightFrame = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
    bottomFrame = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
}

Module_Webcams::~Module_Webcams()
{
    stopWebcams();
    cvReleaseImage( &leftFrame );
    cvReleaseImage( &rightFrame );
    cvReleaseImage( &bottomFrame );
}

void Module_Webcams::stopWebcams()
{
    if ( leftCap != NULL )
    {
        delete leftCap;
        leftCap = NULL;
    }
    if ( rightCap != NULL )
    {
        delete rightCap;
        rightCap = NULL;
    }
    if ( bottomCap != NULL  )
    {
        delete bottomCap;
        bottomCap = NULL;
    }

    //cvReleaseCapture(&bottomCam);//VI.stopDevice( bottomID );
}

//void Module_Webcams::grabLeft( IplImage *left )
//{
//    if ( leftConnected )//&& VI.isFrameNew(leftID) )
//    {
//        mutex.lock();
//        assert( left->width == WEBCAM_WIDTH && left->height == WEBCAM_HEIGHT );
//        if(leftCap.grab())
//        {
//            cv::Mat mat;
//            leftCap.retrieve(mat,0);
//            cv::imshow("blub",mat);
//            left = new IplImage(mat.clone());
//        }

////        cvGrabFrame(leftCam);
////        left = cvCloneImage(cvRetrieveFrame(leftCam));
////        VI.getPixels( leftID, (unsigned char *)left->imageData, false, true );
//        mutex.unlock();
//    }
//}

//void Module_Webcams::grabRight( IplImage *right )
//{
//    if ( rightConnected )//&& VI.isFrameNew(rightID))
//    {
//        mutex.lock();
//        assert( right->width == WEBCAM_WIDTH && right->height == WEBCAM_HEIGHT );
//        if(rightCap.grab())
//        {
//            cv::Mat mat;
//            rightCap.retrieve(mat);
//            right = new IplImage(mat);
//        }

////        cvGrabFrame(rightCam);
////        right = cvCloneImage(cvRetrieveFrame(rightCam));
////        VI.getPixels( rightID, (unsigned char *)right->imageData, false, true );
//        mutex.unlock();
//    }
//}

//void Module_Webcams::grabBottom( IplImage *bottom )
//{
//    if ( bottomConnected )//&& VI.isFrameNew(bottomID))
//    {
//        mutex.lock();
//        assert( bottom->width == WEBCAM_WIDTH && bottom->height == WEBCAM_HEIGHT );
//        if(bottomCap.grab())
//        {
//            cv::Mat mat;
//            bottomCap.retrieve(mat);
//            bottom = new IplImage(mat);
//        }
//        //        cvGrabFrame(bottomCam);
////        bottom = cvCloneImage(cvRetrieveFrame(bottomCam));
////        VI.getPixels( bottomID, (unsigned char *)bottom->imageData, false, true );
//        mutex.unlock();
//    }
//}

void Module_Webcams::grabLeft( cv::Mat &left )
{
    if ( leftCap != NULL )
    {
        mutex.lock();
        IplImage* img = cvQueryFrame(leftCap);
        if(img)
        {
        cv::Mat mtx(img);
        left = mtx.clone();
        }
//        *leftCap >> left;
        mutex.unlock();
    }
}

void Module_Webcams::grabRight( cv::Mat &right )
{
    if ( rightCap != NULL )
    {
        mutex.lock();
        IplImage* img = cvQueryFrame(rightCap);
        if(img)
        {
        cv::Mat mat(img);
        right = mat.clone();
    }
//        *rightCap >> right;
        mutex.unlock();
    }
}

void Module_Webcams::grabBottom( cv::Mat &bottom )
{
//    qDebug() << "cam thread id";
//    qDebug() << QThread::currentThreadId();
    if ( bottomCap != NULL )//&& VI.isFrameNew(bottomID))
    {
        mutex.lock();
        IplImage* img = cvQueryFrame(bottomCap);
        if(img)
        {
        cv::Mat mat(img);
        bottom = mat.clone();
        }
//        assert( bottom.cols == WEBCAM_WIDTH && bottom.rows == WEBCAM_HEIGHT );
//        if(bottomCap.grab())
//            *bottomCap >> bottom;
//            bottomCap.retrieve(bottom);

//        cvGrabFrame(bottomCam);
//        IplImage *img = (cvCloneImage(cvRetrieveFrame(bottomCam)));
//        cv::Mat mtx (img);
//        bottom = mtx.clone();
//        VI.getPixels( bottomID, (unsigned char *)bottom.data, true, true );
        mutex.unlock();
    }
}
//
//void Module_Webcams::grabBottom(QImage bottom1)
//{
//    cv::Mat bottom;
//    bottom.create( WEBCAM_HEIGHT, WEBCAM_WIDTH, CV_8UC3 );
//    qDebug() << "cam thread id";
//    qDebug() << QThread::currentThreadId();
//    if ( bottomConnected )//&& VI.isFrameNew(bottomID))
//    {
//        mutex.lock();
//        assert( bottom.cols == WEBCAM_WIDTH && bottom.rows == WEBCAM_HEIGHT );
//        VI.getPixels( bottomID, (unsigned char *)bottom.data, true, true );
//        mutex.unlock();
//    }
//     QImage image1((unsigned char*)bottom.data, bottom.cols, bottom.rows, QImage::Format_RGB888);
//     bottom1 = image1.copy();
//}

void Module_Webcams::reset()
{
    mutex.lock();
    stopWebcams();

    if ( this->isEnabled() )
    {
        if ( 0 <= bottomID && bottomID < nCams && bottomEnabled )
        {
            bottomCap = cvCaptureFromCAM(bottomID);
            if(bottomCap)
            {
                cvSetCaptureProperty(bottomCap,CV_CAP_PROP_FRAME_WIDTH,640);
                cvSetCaptureProperty(bottomCap,CV_CAP_PROP_FRAME_HEIGHT,480);
                qDebug() << QString::number(cvGetCaptureProperty(bottomCap,CV_CAP_PROP_FRAME_WIDTH));
                qDebug() << QString::number(cvGetCaptureProperty(bottomCap,CV_CAP_PROP_FRAME_HEIGHT));
            }
            else
            {
                delete bottomCap;
                bottomCap = NULL;
            }
//            bottomCam = cvCaptureFromCAM(bottomID);
//            bottomConnected = true;
//            VI.setIdealFramerate( bottomID, bottomFramerate );
//            bottomConnected = VI.setupDevice( bottomID, WEBCAM_WIDTH, WEBCAM_HEIGHT );
        }

        if ( 0 <= leftID && leftID < nCams && leftEnabled )
        {
            leftCap = cvCaptureFromCAM(leftID);
            if(leftCap)
            {
                cvSetCaptureProperty(leftCap,CV_CAP_PROP_FRAME_WIDTH,640);
                cvSetCaptureProperty(leftCap,CV_CAP_PROP_FRAME_HEIGHT,480);
//                qDebug() << QString::number(leftCap->get(CV_CAP_PROP_FRAME_HEIGHT));
//                qDebug() << QString::number(leftCap->get(CV_CAP_PROP_FRAME_WIDTH));

            }
            else
            {
                delete leftCap;
                leftCap = NULL;
            }

        }
        if ( 0 <= rightID && rightID < nCams && rightEnabled )
        {
//            rightCap = new cv::VideoCapture(3);
            rightCap = cvCaptureFromCAM(rightID);
            if(rightCap)
            {
                cvSetCaptureProperty(rightCap,CV_CAP_PROP_FRAME_WIDTH,640);
                cvSetCaptureProperty(rightCap,CV_CAP_PROP_FRAME_HEIGHT,480);

//                qDebug() << QString::number(rightCap->get(CV_CAP_PROP_FRAME_HEIGHT));
//                qDebug() << QString::number(rightCap->get(CV_CAP_PROP_FRAME_WIDTH));
            }
            else
            {
                delete rightCap;
                rightCap = NULL;
            }
//            VI.setIdealFramerate( rightID, rightFramerate );
//            rightConnected = VI.setupDevice( rightID, WEBCAM_WIDTH, WEBCAM_HEIGHT );
        }
    }
    mutex.unlock();
    qDebug() << "left" << leftConnected;
        qDebug() << "right" << rightConnected;
            qDebug() << "bottom" << bottomConnected;
}

int Module_Webcams::numOfCams()
{
    cv::VideoCapture cap;
    int finished = 0;
    int cams = 0;
    return 3;
//    while (!finished)
//    {
//        cap.open(cams);
//        if(!cap.isOpened())
//        {
//            finished = 1;
//        }
//        else
//        {
//            cams++;
//            cap.release();
//        }
//    }
//    return cams;
}

void Module_Webcams::terminate()
{
    stopWebcams();
    RobotModule_MT::terminate();
}

void Module_Webcams::statusChange( bool value )
{

}

void Module_Webcams::showSettings( int camNr )
{
//    VI.showSettingsWindow( camNr );
}

void Module_Webcams::settingsChanged()
{
//    nCams = VI.listDevices( true );
//    nCams = this->numOfCams();
//    logger->debug("Number of Cams "+QString::number(nCams));
    leftID = this->getSettingsValue("leftID",0).toInt();
    rightID = this->getSettingsValue("rightID",1).toInt();
    bottomID = this->getSettingsValue("bottomID",2).toInt();
    leftEnabled = this->getSettingsValue("leftEnabled",true).toBool();
    rightEnabled = this->getSettingsValue("rightEnabled",true).toBool();
    bottomEnabled = this->getSettingsValue("bottomEnabled",true).toBool();
    leftFramerate = this->getSettingsValue("leftFramerate",5).toInt();
    rightFramerate = this->getSettingsValue("rightFramerate",5).toInt();
    bottomFramerate = this->getSettingsValue("bottomFramerate",5).toInt();

    if ( isEnabled() )
    {
        reset();
    }
}

QWidget *Module_Webcams::createView( QWidget *parent )
{
    Form_Webcams *cams = new Form_Webcams( this, parent );
    return cams;
}

QList<RobotModule *> Module_Webcams::getDependencies()
{
    return QList<RobotModule *>();
}
<commit_msg><commit_after>#include "module_webcams.h"
#include <Module_Webcams/form_webcams.h>
#include <assert.h>

Module_Webcams::Module_Webcams( QString id ) :
        RobotModule_MT( id )
{
//    VI.setUseCallback( true );
//    leftConnected = false;
//    rightConnected = false;
//    bottomConnected = false;
    leftFramerate = 5;
    rightFramerate = 5;
    bottomFramerate = 5;

    leftCap = NULL;
    rightCap = NULL;
    bottomCap = NULL;

    nCams = this->numOfCams();

    leftID = 1;
    rightID = 0;
    bottomID = 2;

    settingsChanged();

    leftFrame = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
    rightFrame = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
    bottomFrame = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
}

Module_Webcams::~Module_Webcams()
{
    stopWebcams();
    cvReleaseImage( &leftFrame );
    cvReleaseImage( &rightFrame );
    cvReleaseImage( &bottomFrame );
}

void Module_Webcams::stopWebcams()
{
    if ( leftCap != NULL )
    {
        delete leftCap;
        leftCap = NULL;
    }
    if ( rightCap != NULL )
    {
        delete rightCap;
        rightCap = NULL;
    }
    if ( bottomCap != NULL  )
    {
        delete bottomCap;
        bottomCap = NULL;
    }

    //cvReleaseCapture(&bottomCam);//VI.stopDevice( bottomID );
}

//void Module_Webcams::grabLeft( IplImage *left )
//{
//    if ( leftConnected )//&& VI.isFrameNew(leftID) )
//    {
//        mutex.lock();
//        assert( left->width == WEBCAM_WIDTH && left->height == WEBCAM_HEIGHT );
//        if(leftCap.grab())
//        {
//            cv::Mat mat;
//            leftCap.retrieve(mat,0);
//            cv::imshow("blub",mat);
//            left = new IplImage(mat.clone());
//        }

////        cvGrabFrame(leftCam);
////        left = cvCloneImage(cvRetrieveFrame(leftCam));
////        VI.getPixels( leftID, (unsigned char *)left->imageData, false, true );
//        mutex.unlock();
//    }
//}

//void Module_Webcams::grabRight( IplImage *right )
//{
//    if ( rightConnected )//&& VI.isFrameNew(rightID))
//    {
//        mutex.lock();
//        assert( right->width == WEBCAM_WIDTH && right->height == WEBCAM_HEIGHT );
//        if(rightCap.grab())
//        {
//            cv::Mat mat;
//            rightCap.retrieve(mat);
//            right = new IplImage(mat);
//        }

////        cvGrabFrame(rightCam);
////        right = cvCloneImage(cvRetrieveFrame(rightCam));
////        VI.getPixels( rightID, (unsigned char *)right->imageData, false, true );
//        mutex.unlock();
//    }
//}

//void Module_Webcams::grabBottom( IplImage *bottom )
//{
//    if ( bottomConnected )//&& VI.isFrameNew(bottomID))
//    {
//        mutex.lock();
//        assert( bottom->width == WEBCAM_WIDTH && bottom->height == WEBCAM_HEIGHT );
//        if(bottomCap.grab())
//        {
//            cv::Mat mat;
//            bottomCap.retrieve(mat);
//            bottom = new IplImage(mat);
//        }
//        //        cvGrabFrame(bottomCam);
////        bottom = cvCloneImage(cvRetrieveFrame(bottomCam));
////        VI.getPixels( bottomID, (unsigned char *)bottom->imageData, false, true );
//        mutex.unlock();
//    }
//}

void Module_Webcams::grabLeft( cv::Mat &left )
{
    if ( leftCap != NULL )
    {
        mutex.lock();
        IplImage* img = cvQueryFrame(leftCap);
        if(img)
        {
        cv::Mat mtx(img);
        left = mtx.clone();
        }
//        *leftCap >> left;
        mutex.unlock();
    }
}

void Module_Webcams::grabRight( cv::Mat &right )
{
    if ( rightCap != NULL )
    {
        mutex.lock();
        IplImage* img = cvQueryFrame(rightCap);
        if(img)
        {
        cv::Mat mat(img);
        right = mat.clone();
    }
//        *rightCap >> right;
        mutex.unlock();
    }
}

void Module_Webcams::grabBottom( cv::Mat &bottom )
{
//    qDebug() << "cam thread id";
//    qDebug() << QThread::currentThreadId();
    if ( bottomCap != NULL )//&& VI.isFrameNew(bottomID))
    {
        mutex.lock();
        IplImage* img = cvQueryFrame(bottomCap);
        if(img)
        {
        cv::Mat mat(img);
        bottom = mat.clone();
        }
//        assert( bottom.cols == WEBCAM_WIDTH && bottom.rows == WEBCAM_HEIGHT );
//        if(bottomCap.grab())
//            *bottomCap >> bottom;
//            bottomCap.retrieve(bottom);

//        cvGrabFrame(bottomCam);
//        IplImage *img = (cvCloneImage(cvRetrieveFrame(bottomCam)));
//        cv::Mat mtx (img);
//        bottom = mtx.clone();
//        VI.getPixels( bottomID, (unsigned char *)bottom.data, true, true );
        mutex.unlock();
    }
}
//
//void Module_Webcams::grabBottom(QImage bottom1)
//{
//    cv::Mat bottom;
//    bottom.create( WEBCAM_HEIGHT, WEBCAM_WIDTH, CV_8UC3 );
//    qDebug() << "cam thread id";
//    qDebug() << QThread::currentThreadId();
//    if ( bottomConnected )//&& VI.isFrameNew(bottomID))
//    {
//        mutex.lock();
//        assert( bottom.cols == WEBCAM_WIDTH && bottom.rows == WEBCAM_HEIGHT );
//        VI.getPixels( bottomID, (unsigned char *)bottom.data, true, true );
//        mutex.unlock();
//    }
//     QImage image1((unsigned char*)bottom.data, bottom.cols, bottom.rows, QImage::Format_RGB888);
//     bottom1 = image1.copy();
//}

void Module_Webcams::reset()
{
    mutex.lock();
    stopWebcams();

    if ( this->isEnabled() )
    {
        if ( 0 <= bottomID && bottomID < nCams && bottomEnabled )
        {
            bottomCap = cvCaptureFromCAM(bottomID);
            if(bottomCap)
            {
                cvSetCaptureProperty(bottomCap,CV_CAP_PROP_FRAME_WIDTH,640);
                cvSetCaptureProperty(bottomCap,CV_CAP_PROP_FRAME_HEIGHT,480);
                cvSetCaptureProperty(bottomCap,CV_CAP_PROP_GAIN,0);
                qDebug() << QString::number(cvGetCaptureProperty(bottomCap,CV_CAP_PROP_FRAME_WIDTH));
                qDebug() << QString::number(cvGetCaptureProperty(bottomCap,CV_CAP_PROP_FRAME_HEIGHT));
            }
            else
            {
                delete bottomCap;
                bottomCap = NULL;
            }
//            bottomCam = cvCaptureFromCAM(bottomID);
//            bottomConnected = true;
//            VI.setIdealFramerate( bottomID, bottomFramerate );
//            bottomConnected = VI.setupDevice( bottomID, WEBCAM_WIDTH, WEBCAM_HEIGHT );
        }

        if ( 0 <= leftID && leftID < nCams && leftEnabled )
        {
            leftCap = cvCaptureFromCAM(leftID);
            if(leftCap)
            {
                cvSetCaptureProperty(leftCap,CV_CAP_PROP_FRAME_WIDTH,640);
                cvSetCaptureProperty(leftCap,CV_CAP_PROP_FRAME_HEIGHT,480);
                cvSetCaptureProperty(leftCap,CV_CAP_PROP_GAIN,0);
//                qDebug() << QString::number(leftCap->get(CV_CAP_PROP_FRAME_HEIGHT));
//                qDebug() << QString::number(leftCap->get(CV_CAP_PROP_FRAME_WIDTH));

            }
            else
            {
                delete leftCap;
                leftCap = NULL;
            }

        }
        if ( 0 <= rightID && rightID < nCams && rightEnabled )
        {
//            rightCap = new cv::VideoCapture(3);
            rightCap = cvCaptureFromCAM(rightID);
            if(rightCap)
            {
                cvSetCaptureProperty(rightCap,CV_CAP_PROP_FRAME_WIDTH,640);
                cvSetCaptureProperty(rightCap,CV_CAP_PROP_FRAME_HEIGHT,480);
                cvSetCaptureProperty(rightCap,CV_CAP_PROP_GAIN,0);

//                qDebug() << QString::number(rightCap->get(CV_CAP_PROP_FRAME_HEIGHT));
//                qDebug() << QString::number(rightCap->get(CV_CAP_PROP_FRAME_WIDTH));
            }
            else
            {
                delete rightCap;
                rightCap = NULL;
            }
//            VI.setIdealFramerate( rightID, rightFramerate );
//            rightConnected = VI.setupDevice( rightID, WEBCAM_WIDTH, WEBCAM_HEIGHT );
        }
    }
    mutex.unlock();
    qDebug() << "left" << leftConnected;
        qDebug() << "right" << rightConnected;
            qDebug() << "bottom" << bottomConnected;
}

int Module_Webcams::numOfCams()
{
    cv::VideoCapture cap;
    int finished = 0;
    int cams = 0;
    return 3;
//    while (!finished)
//    {
//        cap.open(cams);
//        if(!cap.isOpened())
//        {
//            finished = 1;
//        }
//        else
//        {
//            cams++;
//            cap.release();
//        }
//    }
//    return cams;
}

void Module_Webcams::terminate()
{
    stopWebcams();
    RobotModule_MT::terminate();
}

void Module_Webcams::statusChange( bool value )
{

}

void Module_Webcams::showSettings( int camNr )
{
//    VI.showSettingsWindow( camNr );
}

void Module_Webcams::settingsChanged()
{
//    nCams = VI.listDevices( true );
//    nCams = this->numOfCams();
//    logger->debug("Number of Cams "+QString::number(nCams));
    leftID = this->getSettingsValue("leftID",0).toInt();
    rightID = this->getSettingsValue("rightID",1).toInt();
    bottomID = this->getSettingsValue("bottomID",2).toInt();
    leftEnabled = this->getSettingsValue("leftEnabled",true).toBool();
    rightEnabled = this->getSettingsValue("rightEnabled",true).toBool();
    bottomEnabled = this->getSettingsValue("bottomEnabled",true).toBool();
    leftFramerate = this->getSettingsValue("leftFramerate",5).toInt();
    rightFramerate = this->getSettingsValue("rightFramerate",5).toInt();
    bottomFramerate = this->getSettingsValue("bottomFramerate",5).toInt();

    if ( isEnabled() )
    {
        reset();
    }
}

QWidget *Module_Webcams::createView( QWidget *parent )
{
    Form_Webcams *cams = new Form_Webcams( this, parent );
    return cams;
}

QList<RobotModule *> Module_Webcams::getDependencies()
{
    return QList<RobotModule *>();
}
<|endoftext|>


<commit_before>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "SocketDescriptor.hxx"
#include "SocketAddress.hxx"
#include "StaticSocketAddress.hxx"
#include "util/Error.hxx"

#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/tcp.h>

SocketDescriptor::~SocketDescriptor()
{
    if (IsDefined())
        Close();
}

void
SocketDescriptor::Close()
{
    assert(IsDefined());

    close(fd);
    fd = -1;
}

bool
SocketDescriptor::Create(int domain, int type, int protocol)
{
    assert(!IsDefined());

    type |= SOCK_CLOEXEC|SOCK_NONBLOCK;
    fd = socket(domain, type, protocol);
    return fd >= 0;
}

bool
SocketDescriptor::Create(int domain, int type, int protocol, Error &error)
{
    assert(!IsDefined());

    type |= SOCK_CLOEXEC|SOCK_NONBLOCK;
    fd = socket(domain, type, protocol);
    if (fd < 0) {
        error.SetErrno("Failed to create socket");
        return false;
    }

    return true;
}

bool
SocketDescriptor::CreateListen(int family, int socktype, int protocol,
                               const SocketAddress &address, Error &error)
{
    if (!Create(family, socktype, protocol, error))
        return false;

    const int reuse = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                   (const char *)&reuse, sizeof(reuse)) < 0) {
        error.SetErrno("Failed to set SO_REUSEADDR");
        Close();
        return false;
    }

    if (!Bind(address)) {
        error.SetErrno("Failed to bind");
        Close();
        return false;
    }

#ifdef __linux
    /* enable TCP Fast Open (requires Linux 3.7) */

#ifndef TCP_FASTOPEN
#define TCP_FASTOPEN 23
#endif

    if ((family == AF_INET || family == AF_INET6) &&
        socktype == SOCK_STREAM) {
        int qlen = 16;
        setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
    }
#endif

    if (listen(fd, 64) < 0) {
        error.SetErrno("Failed to listen");
        Close();
        return false;
    }

    setsockopt(fd, SOL_SOCKET, SO_PASSCRED,
               (const char *)&reuse, sizeof(reuse));

    return true;
}

bool
SocketDescriptor::Bind(SocketAddress address)
{
    assert(IsDefined());

    return bind(fd, address, address.GetSize()) == 0;
}

SocketDescriptor
SocketDescriptor::Accept(StaticSocketAddress &address, Error &error) const
{
    assert(IsDefined());

    address.size = address.GetCapacity();
    int result = accept4(fd, address, &address.size,
                         SOCK_CLOEXEC|SOCK_NONBLOCK);
    if (result < 0) {
        error.SetErrno("Failed to accept connection");
        return SocketDescriptor();
    }

    return SocketDescriptor(result);
}

bool
SocketDescriptor::Connect(const SocketAddress address)
{
    assert(IsDefined());

    return connect(fd, address, address.GetSize());
}

int
SocketDescriptor::GetError()
{
    assert(IsDefined());

    int s_err = 0;
    socklen_t s_err_size = sizeof(s_err);
    return getsockopt(fd, SOL_SOCKET, SO_ERROR,
                      (char *)&s_err, &s_err_size) == 0
        ? s_err
        : errno;
}

StaticSocketAddress
SocketDescriptor::GetLocalAddress() const
{
    assert(IsDefined());

    StaticSocketAddress result;
    result.size = result.GetCapacity();
    if (getsockname(fd, result, &result.size) < 0)
        result.Clear();

    return result;
}

<commit_msg>net/SocketDescriptor: fix Connect() return value<commit_after>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "SocketDescriptor.hxx"
#include "SocketAddress.hxx"
#include "StaticSocketAddress.hxx"
#include "util/Error.hxx"

#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/tcp.h>

SocketDescriptor::~SocketDescriptor()
{
    if (IsDefined())
        Close();
}

void
SocketDescriptor::Close()
{
    assert(IsDefined());

    close(fd);
    fd = -1;
}

bool
SocketDescriptor::Create(int domain, int type, int protocol)
{
    assert(!IsDefined());

    type |= SOCK_CLOEXEC|SOCK_NONBLOCK;
    fd = socket(domain, type, protocol);
    return fd >= 0;
}

bool
SocketDescriptor::Create(int domain, int type, int protocol, Error &error)
{
    assert(!IsDefined());

    type |= SOCK_CLOEXEC|SOCK_NONBLOCK;
    fd = socket(domain, type, protocol);
    if (fd < 0) {
        error.SetErrno("Failed to create socket");
        return false;
    }

    return true;
}

bool
SocketDescriptor::CreateListen(int family, int socktype, int protocol,
                               const SocketAddress &address, Error &error)
{
    if (!Create(family, socktype, protocol, error))
        return false;

    const int reuse = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                   (const char *)&reuse, sizeof(reuse)) < 0) {
        error.SetErrno("Failed to set SO_REUSEADDR");
        Close();
        return false;
    }

    if (!Bind(address)) {
        error.SetErrno("Failed to bind");
        Close();
        return false;
    }

#ifdef __linux
    /* enable TCP Fast Open (requires Linux 3.7) */

#ifndef TCP_FASTOPEN
#define TCP_FASTOPEN 23
#endif

    if ((family == AF_INET || family == AF_INET6) &&
        socktype == SOCK_STREAM) {
        int qlen = 16;
        setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
    }
#endif

    if (listen(fd, 64) < 0) {
        error.SetErrno("Failed to listen");
        Close();
        return false;
    }

    setsockopt(fd, SOL_SOCKET, SO_PASSCRED,
               (const char *)&reuse, sizeof(reuse));

    return true;
}

bool
SocketDescriptor::Bind(SocketAddress address)
{
    assert(IsDefined());

    return bind(fd, address, address.GetSize()) == 0;
}

SocketDescriptor
SocketDescriptor::Accept(StaticSocketAddress &address, Error &error) const
{
    assert(IsDefined());

    address.size = address.GetCapacity();
    int result = accept4(fd, address, &address.size,
                         SOCK_CLOEXEC|SOCK_NONBLOCK);
    if (result < 0) {
        error.SetErrno("Failed to accept connection");
        return SocketDescriptor();
    }

    return SocketDescriptor(result);
}

bool
SocketDescriptor::Connect(const SocketAddress address)
{
    assert(IsDefined());

    return connect(fd, address, address.GetSize()) == 0;
}

int
SocketDescriptor::GetError()
{
    assert(IsDefined());

    int s_err = 0;
    socklen_t s_err_size = sizeof(s_err);
    return getsockopt(fd, SOL_SOCKET, SO_ERROR,
                      (char *)&s_err, &s_err_size) == 0
        ? s_err
        : errno;
}

StaticSocketAddress
SocketDescriptor::GetLocalAddress() const
{
    assert(IsDefined());

    StaticSocketAddress result;
    result.size = result.GetCapacity();
    if (getsockname(fd, result, &result.size) < 0)
        result.Clear();

    return result;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) The Shogun Machine Learning Toolbox
 * Written (W) 2015 Wu Lin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Shogun Development Team.
 *
 */

#include <shogun/machine/gp/SingleSparseInferenceBase.h>
#ifdef USE_GPL_SHOGUN
#ifdef HAVE_NLOPT
#include <shogun/optimization/NLOPTMinimizer.h>
#include <shogun/features/DenseFeatures.h>
#endif //HAVE_NLOPT
#endif //USE_GPL_SHOGUN

#include <shogun/mathematics/Math.h>
#include <shogun/mathematics/eigen3.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/optimization/FirstOrderBoundConstraintsCostFunction.h>

using namespace shogun;
using namespace Eigen;

namespace shogun
{

#ifndef DOXYGEN_SHOULD_SKIP_THIS
/** Wrapper cost function used for the NLOPT minimizer */
class CSingleSparseInferenceCostFunction: public FirstOrderBoundConstraintsCostFunction
{
public:
        CSingleSparseInferenceCostFunction():FirstOrderBoundConstraintsCostFunction() {  init(); }
        virtual ~CSingleSparseInferenceCostFunction() { SG_UNREF(m_obj); }
        void set_target(CSingleSparseInferenceBase *obj)
	{
		if(obj!=m_obj)
		{
			SG_REF(obj);
			SG_UNREF(m_obj);
			m_obj=obj;
			REQUIRE(m_obj,"Object not set\n");
			m_obj->check_fully_sparse();
			REQUIRE(m_obj->m_fully_sparse,"Can not compute gradient\n");
		}
	}
        virtual float64_t get_cost()
	{
		REQUIRE(m_obj,"Object not set\n");
		double nlz=m_obj->get_negative_log_marginal_likelihood();
		return nlz;
	}
        virtual SGVector<float64_t> obtain_variable_reference()
	{
		REQUIRE(m_obj,"Object not set\n");
		SGMatrix<float64_t>& lat_m=m_obj->m_inducing_features;
		SGVector<double> x(lat_m.matrix,lat_m.num_rows*lat_m.num_cols,false);
		return x;
	}
        virtual SGVector<float64_t> get_gradient()
	{
		REQUIRE(m_obj,"Object not set\n");
		m_obj->compute_gradient();
		TParameter* param=m_obj->m_gradient_parameters->get_parameter("inducing_features");
		SGVector<float64_t> derivatives=m_obj->get_derivative_wrt_inducing_features(param);
		return derivatives;
	}
        virtual SGVector<float64_t> get_lower_bound()
	{
		REQUIRE(m_obj,"Object not set\n");
		return m_obj->m_lower_bound;
	}
        virtual SGVector<float64_t> get_upper_bound()
	{
		REQUIRE(m_obj,"Object not set\n");
		return m_obj->m_upper_bound;
	}
private:
        void init() { m_obj=NULL; }
        CSingleSparseInferenceBase *m_obj;
};
#endif //DOXYGEN_SHOULD_SKIP_THIS

CSingleSparseInferenceBase::CSingleSparseInferenceBase() : CSparseInferenceBase()
{
	init();
}

CSingleSparseInferenceBase::CSingleSparseInferenceBase(CKernel* kern, CFeatures* feat,
		CMeanFunction* m, CLabels* lab, CLikelihoodModel* mod, CFeatures* lat)
		: CSparseInferenceBase(kern, feat, m, lab, mod, lat)
{
	init();
	check_fully_sparse();
}

void CSingleSparseInferenceBase::init()
{
	m_fully_sparse=false;
	SG_ADD(&m_fully_sparse, "fully_Sparse",
		"whether the kernel support sparse inference", MS_NOT_AVAILABLE);
	m_lock=new CLock();

	SG_ADD(&m_upper_bound, "upper_bound",
		"upper bound of inducing features", MS_NOT_AVAILABLE);
	SG_ADD(&m_lower_bound, "lower_bound",
		"lower bound of inducing features", MS_NOT_AVAILABLE);
	SG_ADD(&m_max_ind_iterations, "max_ind_iterations",
		"max number of iterations used in inducing features optimization", MS_NOT_AVAILABLE);
	SG_ADD(&m_ind_tolerance, "ind_tolerance",
		"tolearance used in inducing features optimization", MS_NOT_AVAILABLE);
	SG_ADD(&m_opt_inducing_features,
		"opt_inducing_features", "whether optimize inducing features", MS_NOT_AVAILABLE);
	m_max_ind_iterations=50;
	m_ind_tolerance=1e-3;
	m_opt_inducing_features=false;
	m_lower_bound=SGVector<float64_t>();
	m_upper_bound=SGVector<float64_t>();
}

void CSingleSparseInferenceBase::set_kernel(CKernel* kern)
{
	CInferenceMethod::set_kernel(kern);
	check_fully_sparse();
}

CSingleSparseInferenceBase::~CSingleSparseInferenceBase()
{
	delete m_lock;
}

void CSingleSparseInferenceBase::check_fully_sparse()
{
	REQUIRE(m_kernel, "Kernel must be set first\n")
	if (strstr(m_kernel->get_name(), "SparseKernel")!=NULL)
		m_fully_sparse=true;
	else
	{
		SG_WARNING( "The provided kernel does not support to optimize inducing features\n");
		m_fully_sparse=false;
	}
}

SGVector<float64_t> CSingleSparseInferenceBase::get_derivative_wrt_inference_method(
		const TParameter* param)
{
	// the time complexity O(m^2*n) if the TO DO is done
	REQUIRE(param, "Param not set\n");
	REQUIRE(!(strcmp(param->m_name, "log_scale")
			&& strcmp(param->m_name, "log_inducing_noise")
			&& strcmp(param->m_name, "inducing_features")),
		    "Can't compute derivative of"
			" the nagative log marginal likelihood wrt %s.%s parameter\n",
			get_name(), param->m_name)

	if (!strcmp(param->m_name, "log_inducing_noise"))
		// wrt inducing_noise
		// compute derivative wrt inducing noise
		return get_derivative_wrt_inducing_noise(param);
	else if (!strcmp(param->m_name, "inducing_features"))
	{
		SGVector<float64_t> res;
		if (!m_fully_sparse)
		{
			int32_t dim=m_inducing_features.num_rows;
			int32_t num_samples=m_inducing_features.num_cols;
			res=SGVector<float64_t>(dim*num_samples);
			SG_WARNING("Derivative wrt %s cannot be computed since the kernel does not support fully sparse inference\n",
				param->m_name);
			res.zero();
			return res;
		}
		res=get_derivative_wrt_inducing_features(param);
		return res;
	}

	// wrt scale
	// clone kernel matrices
	SGVector<float64_t> deriv_trtr=m_ktrtr_diag.clone();
	SGMatrix<float64_t> deriv_uu=m_kuu.clone();
	SGMatrix<float64_t> deriv_tru=m_ktru.clone();

	// create eigen representation of kernel matrices
	Map<VectorXd> ddiagKi(deriv_trtr.vector, deriv_trtr.vlen);
	Map<MatrixXd> dKuui(deriv_uu.matrix, deriv_uu.num_rows, deriv_uu.num_cols);
	Map<MatrixXd> dKui(deriv_tru.matrix, deriv_tru.num_rows, deriv_tru.num_cols);

	// compute derivatives wrt scale for each kernel matrix
	SGVector<float64_t> result(1);

	result[0]=get_derivative_related_cov(deriv_trtr, deriv_uu, deriv_tru);
	result[0]*=CMath::exp(m_log_scale*2.0)*2.0;
	return result;
}

SGVector<float64_t> CSingleSparseInferenceBase::get_derivative_wrt_kernel(
	const TParameter* param)
{
	REQUIRE(param, "Param not set\n");
	SGVector<float64_t> result;
	int64_t len=const_cast<TParameter *>(param)->m_datatype.get_num_elements();
	result=SGVector<float64_t>(len);

	CFeatures *inducing_features=get_inducing_features();
	for (index_t i=0; i<result.vlen; i++)
	{
		SGVector<float64_t> deriv_trtr;
		SGMatrix<float64_t> deriv_uu;
		SGMatrix<float64_t> deriv_tru;

		m_lock->lock();
		m_kernel->init(m_features, m_features);
		//to reduce the time complexity
		//the kernel object only computes diagonal elements of gradients wrt hyper-parameter
		deriv_trtr=m_kernel->get_parameter_gradient_diagonal(param, i);

		m_kernel->init(inducing_features, inducing_features);
		deriv_uu=m_kernel->get_parameter_gradient(param, i);

		m_kernel->init(inducing_features, m_features);
		deriv_tru=m_kernel->get_parameter_gradient(param, i);
		m_lock->unlock();

		// create eigen representation of derivatives
		Map<VectorXd> ddiagKi(deriv_trtr.vector, deriv_trtr.vlen);
		Map<MatrixXd> dKuui(deriv_uu.matrix, deriv_uu.num_rows,
				deriv_uu.num_cols);
		Map<MatrixXd> dKui(deriv_tru.matrix, deriv_tru.num_rows,
				deriv_tru.num_cols);

		result[i]=get_derivative_related_cov(deriv_trtr, deriv_uu, deriv_tru);
		result[i]*=CMath::exp(m_log_scale*2.0);
	}
	SG_UNREF(inducing_features);
	return result;
}

void CSingleSparseInferenceBase::check_bound(SGVector<float64_t> bound, const char* name)
{
	if (bound.vlen>1)
	{
		REQUIRE(m_inducing_features.num_rows>0, "Inducing features must set before this method is called\n");
		REQUIRE(m_inducing_features.num_rows*m_inducing_features.num_cols==bound.vlen,
			"The length of inducing features (%dx%d)",
			" and the length of bound constraints (%d) are different\n",
			m_inducing_features.num_rows,m_inducing_features.num_cols,bound.vlen);
	}
	else if(bound.vlen==1)
	{
		SG_WARNING("All inducing_features (%dx%d) are constrainted by the single value (%f) in the %s bound\n",
			m_inducing_features.num_rows,m_inducing_features.num_cols,bound[0],name);
	}
}

void CSingleSparseInferenceBase::set_lower_bound_of_inducing_features(SGVector<float64_t> bound)
{
	check_bound(bound,"lower");
	m_lower_bound=bound;
}
void CSingleSparseInferenceBase::set_upper_bound_of_inducing_features(SGVector<float64_t> bound)
{
	check_bound(bound, "upper");
	m_upper_bound=bound;
}

void CSingleSparseInferenceBase::set_max_iterations_for_inducing_features(int32_t it)
{
	REQUIRE(it>0, "Iteration (%d) must be positive\n",it);
	m_max_ind_iterations=it;
}
void CSingleSparseInferenceBase::set_tolearance_for_inducing_features(float64_t tol)
{

	REQUIRE(tol>0, "Tolearance (%f) must be positive\n",tol);
	m_ind_tolerance=tol;
}
double CSingleSparseInferenceBase::nlopt_function(unsigned n, const double* x, double* grad, void* func_data)
{
	CSingleSparseInferenceBase* object=static_cast<CSingleSparseInferenceBase *>(func_data);
	REQUIRE(object,"func_data must be SingleSparseInferenceBase pointer\n");

	double nlz=object->get_negative_log_marginal_likelihood();
	object->compute_gradient();

	TParameter* param=object->m_gradient_parameters->get_parameter("inducing_features");
	SGVector<float64_t> derivatives=object->get_derivative_wrt_inducing_features(param);

	std::copy(derivatives.vector,derivatives.vector+n,grad);

	return nlz;
}

void CSingleSparseInferenceBase::enable_optimizing_inducing_features(bool is_optmization)
{
	m_opt_inducing_features=is_optmization;
}

void CSingleSparseInferenceBase::optimize_inducing_features()
{
#ifdef USE_GPL_SHOGUN
#ifdef HAVE_NLOPT
	if (!m_opt_inducing_features)
		return;

	check_fully_sparse();
	REQUIRE(m_fully_sparse,"Please use a kernel which supports to optimize inducing features\n");

	CSingleSparseInferenceCostFunction *cost_fun=new CSingleSparseInferenceCostFunction();
	SG_REF(this);
	cost_fun->set_target(this);

	NLOPTMinimizer* opt=new NLOPTMinimizer(cost_fun);
	opt->set_nlopt_parameters(NLOPT_LD_LBFGS, m_max_ind_iterations, m_ind_tolerance, m_ind_tolerance);
	opt->minimize();

	delete cost_fun;
	delete opt;
#else
	SG_PRINT("For this functionality we require NLOPT library\n");
#endif //HAVE_NLOPT
#else
	SG_PRINT("For this functionality we require NLOPT (GPL License) library\n");
#endif //USE_GPL_SHOGUN
}

}
<commit_msg>added some comments<commit_after>/*
 * Copyright (c) The Shogun Machine Learning Toolbox
 * Written (W) 2015 Wu Lin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Shogun Development Team.
 *
 */

#include <shogun/machine/gp/SingleSparseInferenceBase.h>
#ifdef USE_GPL_SHOGUN
#ifdef HAVE_NLOPT
#include <shogun/optimization/NLOPTMinimizer.h>
#include <shogun/features/DenseFeatures.h>
#endif //HAVE_NLOPT
#endif //USE_GPL_SHOGUN

#include <shogun/mathematics/Math.h>
#include <shogun/mathematics/eigen3.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/optimization/FirstOrderBoundConstraintsCostFunction.h>

using namespace shogun;
using namespace Eigen;

namespace shogun
{

#ifndef DOXYGEN_SHOULD_SKIP_THIS
/** Wrapper cost function used for the NLOPT minimizer */
class CSingleSparseInferenceCostFunction: public FirstOrderBoundConstraintsCostFunction
{
public:
        CSingleSparseInferenceCostFunction():FirstOrderBoundConstraintsCostFunction() {  init(); }
        virtual ~CSingleSparseInferenceCostFunction() { SG_UNREF(m_obj); }
        void set_target(CSingleSparseInferenceBase *obj)
	{
		if(obj!=m_obj)
		{
			SG_REF(obj);
			SG_UNREF(m_obj);
			m_obj=obj;
			REQUIRE(m_obj,"Object not set\n");
			m_obj->check_fully_sparse();
			REQUIRE(m_obj->m_fully_sparse,"Can not compute gradient\n");
		}
	}
        virtual float64_t get_cost()
	{
		REQUIRE(m_obj,"Object not set\n");
		double nlz=m_obj->get_negative_log_marginal_likelihood();
		return nlz;
	}
        virtual SGVector<float64_t> obtain_variable_reference()
	{
		REQUIRE(m_obj,"Object not set\n");
		SGMatrix<float64_t>& lat_m=m_obj->m_inducing_features;
		SGVector<double> x(lat_m.matrix,lat_m.num_rows*lat_m.num_cols,false);
		return x;
	}
        virtual SGVector<float64_t> get_gradient()
	{
		REQUIRE(m_obj,"Object not set\n");
		m_obj->compute_gradient();
		TParameter* param=m_obj->m_gradient_parameters->get_parameter("inducing_features");
		SGVector<float64_t> derivatives=m_obj->get_derivative_wrt_inducing_features(param);
		return derivatives;
	}
        virtual SGVector<float64_t> get_lower_bound()
	{
		REQUIRE(m_obj,"Object not set\n");
		return m_obj->m_lower_bound;
	}
        virtual SGVector<float64_t> get_upper_bound()
	{
		REQUIRE(m_obj,"Object not set\n");
		return m_obj->m_upper_bound;
	}
private:
        void init() { m_obj=NULL; }
        CSingleSparseInferenceBase *m_obj;
};
#endif //DOXYGEN_SHOULD_SKIP_THIS

CSingleSparseInferenceBase::CSingleSparseInferenceBase() : CSparseInferenceBase()
{
	init();
}

CSingleSparseInferenceBase::CSingleSparseInferenceBase(CKernel* kern, CFeatures* feat,
		CMeanFunction* m, CLabels* lab, CLikelihoodModel* mod, CFeatures* lat)
		: CSparseInferenceBase(kern, feat, m, lab, mod, lat)
{
	init();
	check_fully_sparse();
}

void CSingleSparseInferenceBase::init()
{
	m_fully_sparse=false;
	SG_ADD(&m_fully_sparse, "fully_Sparse",
		"whether the kernel support sparse inference", MS_NOT_AVAILABLE);
	m_lock=new CLock();

	SG_ADD(&m_upper_bound, "upper_bound",
		"upper bound of inducing features", MS_NOT_AVAILABLE);
	SG_ADD(&m_lower_bound, "lower_bound",
		"lower bound of inducing features", MS_NOT_AVAILABLE);
	SG_ADD(&m_max_ind_iterations, "max_ind_iterations",
		"max number of iterations used in inducing features optimization", MS_NOT_AVAILABLE);
	SG_ADD(&m_ind_tolerance, "ind_tolerance",
		"tolearance used in inducing features optimization", MS_NOT_AVAILABLE);
	SG_ADD(&m_opt_inducing_features,
		"opt_inducing_features", "whether optimize inducing features", MS_NOT_AVAILABLE);
	m_max_ind_iterations=50;
	m_ind_tolerance=1e-3;
	m_opt_inducing_features=false;
	m_lower_bound=SGVector<float64_t>();
	m_upper_bound=SGVector<float64_t>();
}

void CSingleSparseInferenceBase::set_kernel(CKernel* kern)
{
	CInferenceMethod::set_kernel(kern);
	check_fully_sparse();
}

CSingleSparseInferenceBase::~CSingleSparseInferenceBase()
{
	delete m_lock;
}

void CSingleSparseInferenceBase::check_fully_sparse()
{
	REQUIRE(m_kernel, "Kernel must be set first\n")
	if (strstr(m_kernel->get_name(), "SparseKernel")!=NULL)
		m_fully_sparse=true;
	else
	{
		SG_WARNING( "The provided kernel does not support to optimize inducing features\n");
		m_fully_sparse=false;
	}
}

SGVector<float64_t> CSingleSparseInferenceBase::get_derivative_wrt_inference_method(
		const TParameter* param)
{
	// the time complexity O(m^2*n) if the TO DO is done
	REQUIRE(param, "Param not set\n");
	REQUIRE(!(strcmp(param->m_name, "log_scale")
			&& strcmp(param->m_name, "log_inducing_noise")
			&& strcmp(param->m_name, "inducing_features")),
		    "Can't compute derivative of"
			" the nagative log marginal likelihood wrt %s.%s parameter\n",
			get_name(), param->m_name)

	if (!strcmp(param->m_name, "log_inducing_noise"))
		// wrt inducing_noise
		// compute derivative wrt inducing noise
		return get_derivative_wrt_inducing_noise(param);
	else if (!strcmp(param->m_name, "inducing_features"))
	{
		SGVector<float64_t> res;
		if (!m_fully_sparse)
		{
			int32_t dim=m_inducing_features.num_rows;
			int32_t num_samples=m_inducing_features.num_cols;
			res=SGVector<float64_t>(dim*num_samples);
			SG_WARNING("Derivative wrt %s cannot be computed since the kernel does not support fully sparse inference\n",
				param->m_name);
			res.zero();
			return res;
		}
		res=get_derivative_wrt_inducing_features(param);
		return res;
	}

	// wrt scale
	// clone kernel matrices
	SGVector<float64_t> deriv_trtr=m_ktrtr_diag.clone();
	SGMatrix<float64_t> deriv_uu=m_kuu.clone();
	SGMatrix<float64_t> deriv_tru=m_ktru.clone();

	// create eigen representation of kernel matrices
	Map<VectorXd> ddiagKi(deriv_trtr.vector, deriv_trtr.vlen);
	Map<MatrixXd> dKuui(deriv_uu.matrix, deriv_uu.num_rows, deriv_uu.num_cols);
	Map<MatrixXd> dKui(deriv_tru.matrix, deriv_tru.num_rows, deriv_tru.num_cols);

	// compute derivatives wrt scale for each kernel matrix
	SGVector<float64_t> result(1);

	result[0]=get_derivative_related_cov(deriv_trtr, deriv_uu, deriv_tru);
	result[0]*=CMath::exp(m_log_scale*2.0)*2.0;
	return result;
}

SGVector<float64_t> CSingleSparseInferenceBase::get_derivative_wrt_kernel(
	const TParameter* param)
{
	REQUIRE(param, "Param not set\n");
	SGVector<float64_t> result;
	int64_t len=const_cast<TParameter *>(param)->m_datatype.get_num_elements();
	result=SGVector<float64_t>(len);

	CFeatures *inducing_features=get_inducing_features();
	for (index_t i=0; i<result.vlen; i++)
	{
		SGVector<float64_t> deriv_trtr;
		SGMatrix<float64_t> deriv_uu;
		SGMatrix<float64_t> deriv_tru;

		m_lock->lock();
		m_kernel->init(m_features, m_features);
		//to reduce the time complexity
		//the kernel object only computes diagonal elements of gradients wrt hyper-parameter
		deriv_trtr=m_kernel->get_parameter_gradient_diagonal(param, i);

		m_kernel->init(inducing_features, inducing_features);
		deriv_uu=m_kernel->get_parameter_gradient(param, i);

		m_kernel->init(inducing_features, m_features);
		deriv_tru=m_kernel->get_parameter_gradient(param, i);
		m_lock->unlock();

		// create eigen representation of derivatives
		Map<VectorXd> ddiagKi(deriv_trtr.vector, deriv_trtr.vlen);
		Map<MatrixXd> dKuui(deriv_uu.matrix, deriv_uu.num_rows,
				deriv_uu.num_cols);
		Map<MatrixXd> dKui(deriv_tru.matrix, deriv_tru.num_rows,
				deriv_tru.num_cols);

		result[i]=get_derivative_related_cov(deriv_trtr, deriv_uu, deriv_tru);
		result[i]*=CMath::exp(m_log_scale*2.0);
	}
	SG_UNREF(inducing_features);
	return result;
}

void CSingleSparseInferenceBase::check_bound(SGVector<float64_t> bound, const char* name)
{
	if (bound.vlen>1)
	{
		REQUIRE(m_inducing_features.num_rows>0, "Inducing features must set before this method is called\n");
		REQUIRE(m_inducing_features.num_rows*m_inducing_features.num_cols==bound.vlen,
			"The length of inducing features (%dx%d)",
			" and the length of bound constraints (%d) are different\n",
			m_inducing_features.num_rows,m_inducing_features.num_cols,bound.vlen);
	}
	else if(bound.vlen==1)
	{
		SG_WARNING("All inducing_features (%dx%d) are constrainted by the single value (%f) in the %s bound\n",
			m_inducing_features.num_rows,m_inducing_features.num_cols,bound[0],name);
	}
}

void CSingleSparseInferenceBase::set_lower_bound_of_inducing_features(SGVector<float64_t> bound)
{
	check_bound(bound,"lower");
	m_lower_bound=bound;
}
void CSingleSparseInferenceBase::set_upper_bound_of_inducing_features(SGVector<float64_t> bound)
{
	check_bound(bound, "upper");
	m_upper_bound=bound;
}

void CSingleSparseInferenceBase::set_max_iterations_for_inducing_features(int32_t it)
{
	REQUIRE(it>0, "Iteration (%d) must be positive\n",it);
	m_max_ind_iterations=it;
}
void CSingleSparseInferenceBase::set_tolearance_for_inducing_features(float64_t tol)
{

	REQUIRE(tol>0, "Tolearance (%f) must be positive\n",tol);
	m_ind_tolerance=tol;
}
double CSingleSparseInferenceBase::nlopt_function(unsigned n, const double* x, double* grad, void* func_data)
{
	CSingleSparseInferenceBase* object=static_cast<CSingleSparseInferenceBase *>(func_data);
	REQUIRE(object,"func_data must be SingleSparseInferenceBase pointer\n");

	double nlz=object->get_negative_log_marginal_likelihood();
	object->compute_gradient();

	TParameter* param=object->m_gradient_parameters->get_parameter("inducing_features");
	SGVector<float64_t> derivatives=object->get_derivative_wrt_inducing_features(param);

	std::copy(derivatives.vector,derivatives.vector+n,grad);

	return nlz;
}

void CSingleSparseInferenceBase::enable_optimizing_inducing_features(bool is_optmization)
{
	m_opt_inducing_features=is_optmization;
#ifdef USE_GPL_SHOGUN
#ifdef HAVE_NLOPT
	if (m_opt_inducing_features)
	{
		check_fully_sparse();
		REQUIRE(m_fully_sparse,"Please use a kernel which has the functionality about optimizing inducing features\n");
	}
#else
	SG_WARNING("For this functionality we require NLOPT library\n");
#endif //HAVE_NLOPT
#else
	SG_WARNING("For this functionality we require NLOPT (GPL License) library\n");
#endif //USE_GPL_SHOGUN

}

void CSingleSparseInferenceBase::optimize_inducing_features()
{
#ifdef USE_GPL_SHOGUN
#ifdef HAVE_NLOPT
	if (!m_opt_inducing_features)
		return;

	CSingleSparseInferenceCostFunction *cost_fun=new CSingleSparseInferenceCostFunction();
	SG_REF(this);
	cost_fun->set_target(this);

	NLOPTMinimizer* opt=new NLOPTMinimizer(cost_fun);
	opt->set_nlopt_parameters(NLOPT_LD_LBFGS, m_max_ind_iterations, m_ind_tolerance, m_ind_tolerance);
	opt->minimize();

	delete cost_fun;
	delete opt;
#endif //HAVE_NLOPT
#endif //USE_GPL_SHOGUN
}

}
<|endoftext|>


<commit_before>#include "BoundaryConditions.h"

// to avoid compiler confusion, python.hpp must be include before Halide headers
#include <boost/python.hpp>

#include "../../src/BoundaryConditions.h"

#include <string>

void defineBoundaryConditions()
{

    return;
}

<commit_msg>Implemented BoundaryConditions<commit_after>#include "BoundaryConditions.h"

// to avoid compiler confusion, python.hpp must be include before Halide headers
#include <boost/python.hpp>

#include "../../src/Lambda.h" // needed by BoundaryConditions.h
#include "../../src/BoundaryConditions.h"
#include "../../src/Func.h"

#include <string>

namespace h = Halide;
namespace hb = Halide::BoundaryConditions;
namespace p = boost::python;

namespace {

template<typename T>
h::Func constant_exterior0(T func_like, h::Expr value)
{
    return hb::constant_exterior(func_like, value);
}

// C++ fun, variadic template recursive function !
template<typename T=void, typename ...Types>
void def_constant_exterior_for_image()
{
    p::def("constant_exterior", &constant_exterior0<h::Image<T>>, p::args("source", "value"));
    def_constant_exterior_for_image<Types...>(); // recursive call
    return;
}

template<>
void def_constant_exterior_for_image<void>()
{ // end of recursion
    return;
}

} // end of anonymous namespace

namespace {

template<typename T>
h::Func repeat_edge0(T func_like)
{
    return hb::repeat_edge(func_like);
}

// C++ fun, variadic template recursive function !
template<typename T=void, typename ...Types>
void def_repeat_edge_for_image()
{
    p::def("repeat_edge", &repeat_edge0<h::Image<T>>, p::args("source"));
    def_repeat_edge_for_image<Types...>(); // recursive call
    return;
}

template<>
void def_repeat_edge_for_image<void>()
{ // end of recursion
    return;
}

} // end of anonymous namespace

namespace {

template<typename T>
h::Func repeat_image0(T func_like)
{
    return hb::repeat_image(func_like);
}

// C++ fun, variadic template recursive function !
template<typename T=void, typename ...Types>
void def_repeat_image_for_image()
{
    p::def("repeat_image", &repeat_image0<h::Image<T>>, p::args("source"));
    def_repeat_image_for_image<Types...>(); // recursive call
    return;
}

template<>
void def_repeat_image_for_image<void>()
{ // end of recursion
    return;
}

} // end of anonymous namespace

namespace {

template<typename T>
h::Func mirror_image0(T func_like)
{
    return hb::mirror_image(func_like);
}

// C++ fun, variadic template recursive function !
template<typename T=void, typename ...Types>
void def_mirror_image_for_image()
{
    p::def("mirror_image", &mirror_image0<h::Image<T>>, p::args("source"));
    def_mirror_image_for_image<Types...>(); // recursive call
    return;
}

template<>
void def_mirror_image_for_image<void>()
{ // end of recursion
    return;
}

} // end of anonymous namespace

namespace {

template<typename T>
h::Func mirror_interior0(T func_like)
{
    return hb::mirror_interior(func_like);
}

// C++ fun, variadic template recursive function !
template<typename T=void, typename ...Types>
void def_mirror_interior_for_image()
{
    p::def("mirror_interior", &mirror_interior0<h::Image<T>>, p::args("source"));
    def_mirror_interior_for_image<Types...>(); // recursive call
    return;
}

template<>
void def_mirror_interior_for_image<void>()
{ // end of recursion
    return;
}

} // end of anonymous namespace

void defineBoundaryConditions()
{
    using p::self;

    // Other variants of constant_exterior exist, but not yet implemented

    p::def("constant_exterior", &constant_exterior0<h::ImageParam>, p::args("source", "value"),
           "Impose a boundary condition such that a given expression is returned "
           "everywhere outside the boundary. Generally the expression will be a "
           "constant, though the code currently allows accessing the arguments  "
           "of source.\n\n"
           "An ImageParam, Image<T>, or similar can be passed instead of a Func. If this  "
           "is done and no bounds are given, the boundaries will be taken from the  "
           "min and extent methods of the passed object.\n\n"
           "(This is similar to setting GL_TEXTURE_WRAP_* to GL_CLAMP_TO_BORDER  "
           " and putting value in the border of the texture.) ");

    def_constant_exterior_for_image<
            boost::uint8_t, boost::uint16_t, boost::uint32_t,
            boost::int8_t, boost::int16_t, boost::int32_t,
            float, double >();

    // The following variant is not yet implemented
    //    EXPORT Func constant_exterior(const Func &source, Expr value,
    //                                  const std::vector<std::pair<Expr, Expr>> &bounds);

    p::def("repeat_edge", &repeat_edge0<h::ImageParam>, p::args("source"),
           "Impose a boundary condition such that the nearest edge sample is returned "
           "everywhere outside the given region.\n\n"
           "An ImageParam, Image<T>, or similar can be passed instead of a Func. If this "
           "is done and no bounds are given, the boundaries will be taken from the "
           "min and extent methods of the passed object.\n\n"
           "(This is similar to setting GL_TEXTURE_WRAP_* to GL_CLAMP_TO_EDGE.)");

    def_repeat_edge_for_image<
            boost::uint8_t, boost::uint16_t, boost::uint32_t,
            boost::int8_t, boost::int16_t, boost::int32_t,
            float, double >();

    // The following variant is not yet implemented
    //    EXPORT Func repeat_edge(const Func &source,
    //                            const std::vector<std::pair<Expr, Expr>> &bounds);

    p::def("repeat_image", &repeat_image0<h::ImageParam>, p::args("source"),
           "Impose a boundary condition such that the entire coordinate space is "
           "tiled with copies of the image abutted against each other.\n\n"
           "An ImageParam, Image<T>, or similar can be passed instead of a Func. If this "
           "is done and no bounds are given, the boundaries will be taken from the "
           "min and extent methods of the passed object.\n\n"
           "(This is similar to setting GL_TEXTURE_WRAP_* to GL_REPEAT.)");

    def_repeat_image_for_image<
            boost::uint8_t, boost::uint16_t, boost::uint32_t,
            boost::int8_t, boost::int16_t, boost::int32_t,
            float, double >();

    //The following variant is not yet implemented
    //        EXPORT Func repeat_image(const Func &source,
    //                                 const std::vector<std::pair<Expr, Expr>> &bounds);

    p::def("mirror_image", &mirror_image0<h::ImageParam>, p::args("source"),
           "Impose a boundary condition such that the entire coordinate space is "
           "tiled with copies of the image abutted against each other, but mirror "
           "them such that adjacent edges are the same.\n\n"
           "An ImageParam, Image<T>, or similar can be passed instead of a Func. If this "
           "is done and no bounds are given, the boundaries will be taken from the "
           "min and extent methods of the passed object.\n\n"
           "(This is similar to setting GL_TEXTURE_WRAP_* to GL_MIRRORED_REPEAT.)");

    def_mirror_image_for_image<
            boost::uint8_t, boost::uint16_t, boost::uint32_t,
            boost::int8_t, boost::int16_t, boost::int32_t,
            float, double >();

    // The following variant is not yet implemented
    //        EXPORT Func mirror_image(const Func &source,
    //                                 const std::vector<std::pair<Expr, Expr>> &bounds);

    p::def("mirror_interior", &mirror_interior0<h::ImageParam>, p::args("source"),
           "Impose a boundary condition such that the entire coordinate space is "
           "tiled with copies of the image abutted against each other, but mirror "
           "them such that adjacent edges are the same and then overlap the edges.\n\n"
           "This produces an error if any extent is 1 or less. (TODO: check this.)\n\n"
           "An ImageParam, Image<T>, or similar can be passed instead of a Func. If this "
           "is done and no bounds are given, the boundaries will be taken from the "
           "min and extent methods of the passed object. "
           "(I do not believe there is a direct GL_TEXTURE_WRAP_* equivalent for this.)");

    def_mirror_interior_for_image<
            boost::uint8_t, boost::uint16_t, boost::uint32_t,
            boost::int8_t, boost::int16_t, boost::int32_t,
            float, double >();

    // The following variant is not yet implemented
    //    EXPORT Func mirror_interior(const Func &source,
    //                                const std::vector<std::pair<Expr, Expr>> &bounds);

    return;
}

<|endoftext|>


<commit_before>//Copyright (c) 2015 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "PolygonTest.h"

namespace cura
{
    CPPUNIT_TEST_SUITE_REGISTRATION(PolygonTest);

void PolygonTest::setUp()
{
    test_square.emplace_back(0, 0);
    test_square.emplace_back(100, 0);
    test_square.emplace_back(100, 100);
    test_square.emplace_back(0, 100);

    pointy_square.emplace_back(0, 0);
    pointy_square.emplace_back(47, 0);
    pointy_square.emplace_back(50, 80);
    pointy_square.emplace_back(53, 0);
    pointy_square.emplace_back(100, 0);
    pointy_square.emplace_back(100, 100);
    pointy_square.emplace_back(55, 100);
    pointy_square.emplace_back(50, 180);
    pointy_square.emplace_back(45, 100);
    pointy_square.emplace_back(0, 100);

    triangle.emplace_back(100, 0);
    triangle.emplace_back(300, 0);
    triangle.emplace_back(200, 100);
}

void PolygonTest::tearDown()
{
    //Do nothing.
}

void PolygonTest::polygonOffsetTest()
{
    Polygons test_squares;
    test_squares.add(test_square);
    Polygons expanded = test_squares.offset(25);
    int64_t expanded_length = expanded.polygonLength();

    Polygons square_hole;
    PolygonRef square_inverted = square_hole.newPoly();
    for (int i = test_square.size() - 1; i >= 0; i--)
    {
        square_inverted.add(test_square[i]);
    }
    Polygons contracted = square_hole.offset(25);
    int64_t contracted_length = contracted.polygonLength();

    CPPUNIT_ASSERT_MESSAGE("Offset on outside poly is different from offset on inverted poly!", std::abs(expanded_length - contracted_length) < 5);
}

void PolygonTest::isOutsideTest()
{
    Polygons test_triangle;
    test_triangle.add(triangle);

    CPPUNIT_ASSERT_MESSAGE("Point is calculated as inside while it's outside!", !test_triangle.inside(Point(0, 100)));
}

}<commit_msg>Remove whitespace at end of line<commit_after>//Copyright (c) 2015 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "PolygonTest.h"

namespace cura
{
    CPPUNIT_TEST_SUITE_REGISTRATION(PolygonTest);

void PolygonTest::setUp()
{
    test_square.emplace_back(0, 0);
    test_square.emplace_back(100, 0);
    test_square.emplace_back(100, 100);
    test_square.emplace_back(0, 100);

    pointy_square.emplace_back(0, 0);
    pointy_square.emplace_back(47, 0);
    pointy_square.emplace_back(50, 80);
    pointy_square.emplace_back(53, 0);
    pointy_square.emplace_back(100, 0);
    pointy_square.emplace_back(100, 100);
    pointy_square.emplace_back(55, 100);
    pointy_square.emplace_back(50, 180);
    pointy_square.emplace_back(45, 100);
    pointy_square.emplace_back(0, 100);

    triangle.emplace_back(100, 0);
    triangle.emplace_back(300, 0);
    triangle.emplace_back(200, 100);
}

void PolygonTest::tearDown()
{
    //Do nothing.
}

void PolygonTest::polygonOffsetTest()
{
    Polygons test_squares;
    test_squares.add(test_square);
    Polygons expanded = test_squares.offset(25);
    int64_t expanded_length = expanded.polygonLength();

    Polygons square_hole;
    PolygonRef square_inverted = square_hole.newPoly();
    for (int i = test_square.size() - 1; i >= 0; i--)
    {
        square_inverted.add(test_square[i]);
    }
    Polygons contracted = square_hole.offset(25);
    int64_t contracted_length = contracted.polygonLength();

    CPPUNIT_ASSERT_MESSAGE("Offset on outside poly is different from offset on inverted poly!", std::abs(expanded_length - contracted_length) < 5);
}

void PolygonTest::isOutsideTest()
{
    Polygons test_triangle;
    test_triangle.add(triangle);

    CPPUNIT_ASSERT_MESSAGE("Point is calculated as inside while it's outside!", !test_triangle.inside(Point(0, 100)));
}

}<|endoftext|>


<commit_before>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  @file JPetCommonToolsTest.cpp
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetCommonToolsTest
#include <boost/test/unit_test.hpp>
#include <map>
#include "JPetCommonTools.h"

BOOST_AUTO_TEST_SUITE(CommonToolsTestSuite)

BOOST_AUTO_TEST_CASE(findSubstringTest)
{
  std::string str("There are two needles in this haystack with needles.");
  std::string str2("needle");

  std::size_t found = JPetCommonTools::findSubstring(str, str2);
  BOOST_REQUIRE_EQUAL(found != std::string::npos, true);
}

BOOST_AUTO_TEST_CASE(ItoaTest)
{
  int testNumber = 64;

  std::string intAsASting = JPetCommonTools::Itoa(testNumber);
  BOOST_REQUIRE_EQUAL(intAsASting == "64", true);
}

BOOST_AUTO_TEST_CASE(intToStringTest)
{
  int testNumber = 64;

  std::string intAsASting = JPetCommonTools::intToString(testNumber);
  BOOST_REQUIRE_EQUAL(intAsASting == "64", true);
}

BOOST_AUTO_TEST_CASE(doubleToStringTest)
{
  double testNumber = 256.3264;

  std::string doubleAsASting = JPetCommonTools::doubleToString(testNumber);
  BOOST_REQUIRE_EQUAL(doubleAsASting == "256.326", true);
}

BOOST_AUTO_TEST_CASE(stringToIntTest)
{
  std::string testString = "1024";

  int stringAsAInt = JPetCommonTools::stringToInt(testString);
  BOOST_REQUIRE_EQUAL(stringAsAInt == 1024, true);
}

BOOST_AUTO_TEST_CASE(toBoolTest)
{
  std::string testString = "0";

  bool stringAsABool = JPetCommonTools::to_bool(testString);
  BOOST_REQUIRE_EQUAL(stringAsABool == false, true);
}

BOOST_AUTO_TEST_CASE(ifFileExistingTest)
{
  std::string fileTest = "run_tests.pl";

  bool ifFileExisting = JPetCommonTools::ifFileExisting(fileTest);
  BOOST_REQUIRE_EQUAL(ifFileExisting, true);
}

BOOST_AUTO_TEST_CASE(mapAreEqualTest)
{
  std::map<int, int> mapTestLeft, mapTestRight;
  bool areMapsEqual = JPetCommonTools::mapComparator(mapTestLeft, mapTestRight);
  BOOST_REQUIRE_EQUAL(areMapsEqual, true);
}

BOOST_AUTO_TEST_CASE(mapAreNotEqualTest)
{
  std::map<char, int> first;
  first['a'] = 10;
  first['b'] = 30;
  first['c'] = 50;
  first['d'] = 70;
  std::map<char, int> second;

  bool areMapsEqual = JPetCommonTools::mapComparator(first, second);
  BOOST_REQUIRE_EQUAL(areMapsEqual, false);
}

BOOST_AUTO_TEST_CASE(stripFileNameSuffixTest)
{
  std::string fileTest = "run_tests.pl";

  std::string stripFileNameSuffix = JPetCommonTools::stripFileNameSuffix(fileTest);
  BOOST_REQUIRE_EQUAL(stripFileNameSuffix == "run_tests", true);
}

BOOST_AUTO_TEST_CASE(extractFileNameSuffixTest)
{
  std::string fileTest = "run_tests.pl";

  std::string stripFileNameSuffix = JPetCommonTools::stripFileNameSuffix(fileTest);
  BOOST_REQUIRE_EQUAL(stripFileNameSuffix == ".pl", true);
}

BOOST_AUTO_TEST_CASE(currentFullPathTest)
{
  std::string currentFullPathTest = boost::filesystem::path(boost::filesystem::current_path()).string();

  std::string currentFullPath = JPetCommonTools::currentFullPath();
  BOOST_REQUIRE_EQUAL(currentFullPath == currentFullPathTest, true);
}

BOOST_AUTO_TEST_CASE(extractPathFromFileTest)
{
  std::string currentFullPathTest = boost::filesystem::path(boost::filesystem::current_path()).string();
  std::string currentFullPathTestWithFileName = currentFullPathTest + "/" + "run_tests.pl";

  std::string result = JPetCommonTools::extractPathFromFile(currentFullPathTestWithFileName);
  BOOST_REQUIRE_EQUAL(result.compare(currentFullPathTest), 0);
}

BOOST_AUTO_TEST_CASE(isDirectory)
{
  BOOST_REQUIRE(JPetCommonTools::isDirectory(boost::filesystem::initial_path().string()));
  BOOST_REQUIRE(!JPetCommonTools::isDirectory("fake/directory/baba"));
}

BOOST_AUTO_TEST_CASE(appendSlashToPathIfAbsent)
{
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent(""), "");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("./"), "./");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("/home/"), "/home/");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("/home"), "/home/");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("home/bbl/be"), "home/bbl/be/");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("test"), "test/");
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>Changed one line in suffixStrip function in CommonTools<commit_after>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  @file JPetCommonToolsTest.cpp
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetCommonToolsTest
#include <boost/test/unit_test.hpp>
#include <map>
#include "JPetCommonTools.h"

BOOST_AUTO_TEST_SUITE(CommonToolsTestSuite)

BOOST_AUTO_TEST_CASE(findSubstringTest)
{
  std::string str("There are two needles in this haystack with needles.");
  std::string str2("needle");

  std::size_t found = JPetCommonTools::findSubstring(str, str2);
  BOOST_REQUIRE_EQUAL(found != std::string::npos, true);
}

BOOST_AUTO_TEST_CASE(ItoaTest)
{
  int testNumber = 64;

  std::string intAsASting = JPetCommonTools::Itoa(testNumber);
  BOOST_REQUIRE_EQUAL(intAsASting == "64", true);
}

BOOST_AUTO_TEST_CASE(intToStringTest)
{
  int testNumber = 64;

  std::string intAsASting = JPetCommonTools::intToString(testNumber);
  BOOST_REQUIRE_EQUAL(intAsASting == "64", true);
}

BOOST_AUTO_TEST_CASE(doubleToStringTest)
{
  double testNumber = 256.3264;

  std::string doubleAsASting = JPetCommonTools::doubleToString(testNumber);
  BOOST_REQUIRE_EQUAL(doubleAsASting == "256.326", true);
}

BOOST_AUTO_TEST_CASE(stringToIntTest)
{
  std::string testString = "1024";

  int stringAsAInt = JPetCommonTools::stringToInt(testString);
  BOOST_REQUIRE_EQUAL(stringAsAInt == 1024, true);
}

BOOST_AUTO_TEST_CASE(toBoolTest)
{
  std::string testString = "0";

  bool stringAsABool = JPetCommonTools::to_bool(testString);
  BOOST_REQUIRE_EQUAL(stringAsABool == false, true);
}

BOOST_AUTO_TEST_CASE(ifFileExistingTest)
{
  std::string fileTest = "run_tests.pl";

  bool ifFileExisting = JPetCommonTools::ifFileExisting(fileTest);
  BOOST_REQUIRE_EQUAL(ifFileExisting, true);
}

BOOST_AUTO_TEST_CASE(mapAreEqualTest)
{
  std::map<int, int> mapTestLeft, mapTestRight;
  bool areMapsEqual = JPetCommonTools::mapComparator(mapTestLeft, mapTestRight);
  BOOST_REQUIRE_EQUAL(areMapsEqual, true);
}

BOOST_AUTO_TEST_CASE(mapAreNotEqualTest)
{
  std::map<char, int> first;
  first['a'] = 10;
  first['b'] = 30;
  first['c'] = 50;
  first['d'] = 70;
  std::map<char, int> second;

  bool areMapsEqual = JPetCommonTools::mapComparator(first, second);
  BOOST_REQUIRE_EQUAL(areMapsEqual, false);
}

BOOST_AUTO_TEST_CASE(stripFileNameSuffixTest)
{
  std::string fileTest = "run_tests.pl";

  std::string stripFileNameSuffix = JPetCommonTools::stripFileNameSuffix(fileTest);
  BOOST_REQUIRE_EQUAL(stripFileNameSuffix == "run_tests", true);
}

BOOST_AUTO_TEST_CASE(extractFileNameSuffixTest)
{
  std::string fileTest = "run_tests.pl";

  std::string stripFileNameSuffix = JPetCommonTools::stripFileNameSuffix(fileTest);
  BOOST_REQUIRE_EQUAL(stripFileNameSuffix, ".pl");
}

BOOST_AUTO_TEST_CASE(currentFullPathTest)
{
  std::string currentFullPathTest = boost::filesystem::path(boost::filesystem::current_path()).string();

  std::string currentFullPath = JPetCommonTools::currentFullPath();
  BOOST_REQUIRE_EQUAL(currentFullPath == currentFullPathTest, true);
}

BOOST_AUTO_TEST_CASE(extractPathFromFileTest)
{
  std::string currentFullPathTest = boost::filesystem::path(boost::filesystem::current_path()).string();
  std::string currentFullPathTestWithFileName = currentFullPathTest + "/" + "run_tests.pl";

  std::string result = JPetCommonTools::extractPathFromFile(currentFullPathTestWithFileName);
  BOOST_REQUIRE_EQUAL(result.compare(currentFullPathTest), 0);
}

BOOST_AUTO_TEST_CASE(isDirectory)
{
  BOOST_REQUIRE(JPetCommonTools::isDirectory(boost::filesystem::initial_path().string()));
  BOOST_REQUIRE(!JPetCommonTools::isDirectory("fake/directory/baba"));
}

BOOST_AUTO_TEST_CASE(appendSlashToPathIfAbsent)
{
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent(""), "");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("./"), "./");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("/home/"), "/home/");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("/home"), "/home/");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("home/bbl/be"), "home/bbl/be/");
  BOOST_REQUIRE_EQUAL(JPetCommonTools::appendSlashToPathIfAbsent("test"), "test/");
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>// $Id: linear_solver.C,v 1.4 2005-06-12 18:36:41 jwpeterson Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local Includes
#include "linear_solver.h"
#include "laspack_linear_solver.h"
#include "petsc_linear_solver.h"

//------------------------------------------------------------------
// LinearSolver members
template <typename T>
AutoPtr<LinearSolver<T> >
LinearSolver<T>::build(const SolverPackage solver_package)
{
  // Build the appropriate solver
  switch (solver_package)
    {

#ifdef HAVE_LASPACK
    case LASPACK_SOLVERS:
      {
	AutoPtr<LinearSolver<T> > ap(new LaspackLinearSolver<T>);
	return ap;
      }
#endif

#ifdef HAVE_PETSC
    case PETSC_SOLVERS:
      {
	AutoPtr<LinearSolver<T> > ap(new PetscLinearSolver<T>);
	return ap;
      }
#endif

    default:
      std::cerr << "ERROR:  Unrecognized solver package: "
		<< solver_package
		<< std::endl;
      error();
    }

  AutoPtr<LinearSolver<T> > ap(NULL);
  return ap;
}

//------------------------------------------------------------------
// Explicit instantiations
template class LinearSolver<Number>;

<commit_msg>We use an AutoPtr outside of the #ifdefs, so we should include auto_ptr.h<commit_after>// $Id: linear_solver.C,v 1.5 2007-07-01 01:53:48 roystgnr Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local Includes
#include "auto_ptr.h"
#include "linear_solver.h"
#include "laspack_linear_solver.h"
#include "petsc_linear_solver.h"

//------------------------------------------------------------------
// LinearSolver members
template <typename T>
AutoPtr<LinearSolver<T> >
LinearSolver<T>::build(const SolverPackage solver_package)
{
  // Build the appropriate solver
  switch (solver_package)
    {

#ifdef HAVE_LASPACK
    case LASPACK_SOLVERS:
      {
	AutoPtr<LinearSolver<T> > ap(new LaspackLinearSolver<T>);
	return ap;
      }
#endif

#ifdef HAVE_PETSC
    case PETSC_SOLVERS:
      {
	AutoPtr<LinearSolver<T> > ap(new PetscLinearSolver<T>);
	return ap;
      }
#endif

    default:
      std::cerr << "ERROR:  Unrecognized solver package: "
		<< solver_package
		<< std::endl;
      error();
    }

  AutoPtr<LinearSolver<T> > ap(NULL);
  return ap;
}

//------------------------------------------------------------------
// Explicit instantiations
template class LinearSolver<Number>;

<|endoftext|>


<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;
    }

    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());
}

<commit_msg>js sandbox: changed extension (dll/so) blacklist to a whitelist<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_whitelist; //the search is system wide, so whitelist is best to not leak to 3rd party libs
    extension_whitelist << "qt.core" << "qt.gui" << "qt.xml" << "qt.xmlpatterns" << "qt.opengl" << "qt.phonon"; //webkit not allowed directly so scripts can't open hidden browsers to do malicious stuff. uitools to be investigated

    QStringList qtcore_blacklist; //the types in qt.core which are not safe. should probably be a whitelist too.
    qtcore_blacklist << "QDir" << "QFile" << "QFileSystemWatcher" << "QFileInfo" << "QLibrary" << "QPluginLoader";

    if (!trusted_ && !extension_whitelist.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|>