<commit_before>/* ------------------------------------------------------------------------*/
/* Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs     */
/*                                                                         */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at                                                */
/*                                                                         */
/* http://www.apache.org/licenses/LICENSE-2.0                              */
/*                                                                         */
/* Unless required by applicable law or agreed to in writing, software     */
/* distributed under the License is distributed on an "AS IS" BASIS,       */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*/
/* See the License for the specific language governing permissions and     */
/* limitations under the License.                                          */
/* ------------------------------------------------------------------------*/

#include <limits.h>

#include <iostream>
#include <sstream>
#include <algorithm>

#include "HostShare.h"

using namespace std;

/* ************************************************************************ */
/* HostSharePCI                                                             */
/* ************************************************************************ */

int HostSharePCI::from_xml_node(const xmlNodePtr node)
{
    int rc = Template::from_xml_node(node);

    if (rc != 0)
    {
        return -1;
    }

    return init();
}

int HostSharePCI::init()
{
    vector<Attribute *> devices;

    int num_devs = get("PCI", devices);

    for (int i=0; i < num_devs; i++)
    {
        VectorAttribute * pci = dynamic_cast<VectorAttribute *>(devices[i]);

        if (pci == 0)
        {
            return -1;
        }

        PCIDevice * pcidev = new PCIDevice(pci);

        pci_devices.insert(make_pair(pcidev->address, pcidev));
    }

    return 0;
}

/* ------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------*/

bool HostSharePCI::test_set(unsigned int vendor_id, unsigned int device_id,
        unsigned int class_id, VectorAttribute * devreq, int vmid,
        std::set<string>& assigned)
{
    map<string, PCIDevice *>::iterator it;

    for (it=pci_devices.begin(); it!=pci_devices.end(); it++)
    {
        PCIDevice * dev = it->second;

        if (dev->class_id  == class_id  &&
            dev->vendor_id == vendor_id &&
            dev->device_id == device_id &&
            dev->vmid      == -1 &&
            assigned.find(dev->address) == assigned.end())
        {
            assigned.insert(dev->address);

            if (vmid != -1)
            {
                dev->vmid = vmid;
                dev->attrs->replace("VMID", vmid);

                devreq->replace("DOMAIN",dev->attrs->vector_value("DOMAIN"));
                devreq->replace("BUS",dev->attrs->vector_value("BUS"));
                devreq->replace("SLOT",dev->attrs->vector_value("SLOT"));
                devreq->replace("FUNCTION",dev->attrs->vector_value("FUNCTION"));

                devreq->replace("ADDRESS",dev->attrs->vector_value("ADDRESS"));
            }

            return true;
        }
    }

    return false;
}

/* ------------------------------------------------------------------------*/

bool HostSharePCI::test_set(vector<Attribute *> &devs, int vmid)
{
    vector<Attribute *>::iterator it;
    std::set<string> assigned;

    unsigned int vendor_id, device_id, class_id;

    for ( it=devs.begin(); it!= devs.end(); it++)
    {
        VectorAttribute * pci = dynamic_cast<VectorAttribute *>(*it);

        if ( pci == 0 )
        {
            return false;
        }

        vendor_id = get_pci_value("VENDOR", pci);
        device_id = get_pci_value("DEVICE", pci);
        class_id  = get_pci_value("CLASS", pci);

        if (!test_set(vendor_id, device_id, class_id, pci, vmid, assigned))
        {
            return false;
        }
    }

    return true;
}

/* ------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------*/

void HostSharePCI::del(const vector<Attribute *> &devs)
{
    vector<Attribute *>::const_iterator it;
    map<string, PCIDevice *>::iterator pci_it;

    for ( it=devs.begin(); it!= devs.end(); it++)
    {
        const VectorAttribute * pci = dynamic_cast<const VectorAttribute *>(*it);

        if ( pci == 0 )
        {
            continue;
        }

        pci_it = pci_devices.find(pci->vector_value("ADDRESS"));

        if (pci_it != pci_devices.end())
        {
            pci_it->second->vmid = -1;
            pci_it->second->attrs->replace("VMID",-1);
        }
    }
};

/* ------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------*/

void HostSharePCI::set_monitorization(vector<Attribute*> &pci_att)
{
    vector<Attribute*>::iterator it;
    map<string, PCIDevice*>::iterator pci_it;

    string address;

    for (it = pci_att.begin(); it != pci_att.end(); it++)
    {
        VectorAttribute * pci = dynamic_cast<VectorAttribute *>(*it);

        if ( pci == 0 )
        {
            continue;
        }

        address = pci->vector_value("ADDRESS");

        if (address.empty())
        {
            delete pci;
            continue;
        }

        pci_it = pci_devices.find(address);

        if (pci_it != pci_devices.end())
        {
            delete pci;
            continue;
        }

        PCIDevice * dev = new PCIDevice(pci);

        pci_devices.insert(make_pair(address, dev));

        set(pci);
    }
};

/* ------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------*/

unsigned int HostSharePCI::get_pci_value(const char * name,
    const VectorAttribute * pci_device)
{
    string temp;

    temp = pci_device->vector_value(name);

    if (temp.empty())
    {
        return 0;
    }

    unsigned int  pci_value;
    istringstream iss(temp);

    iss >> hex >> pci_value;

    if (iss.fail() || !iss.eof())
    {
        return 0;
    }

    return pci_value;
}

HostSharePCI::PCIDevice::PCIDevice(VectorAttribute * _attrs)
    : vmid(-1), attrs(_attrs)
{
    vendor_id = get_pci_value("VENDOR", attrs);
    device_id = get_pci_value("DEVICE", attrs);
    class_id  = get_pci_value("CLASS", attrs);

    attrs->vector_value("VMID", vmid);
    attrs->vector_value("ADDRESS", address);
};

/* ************************************************************************ */
/* HostShare :: Constructor/Destructor                                      */
/* ************************************************************************ */

HostShare::HostShare(long long _max_disk,long long _max_mem,long long _max_cpu):
        ObjectXML(),
        disk_usage(0),
        mem_usage(0),
        cpu_usage(0),
        max_disk(_max_disk),
        max_mem(_max_mem),
        max_cpu(_max_cpu),
        free_disk(0),
        free_mem(0),
        free_cpu(0),
        used_disk(0),
        used_mem(0),
        used_cpu(0),
        running_vms(0),
        ds(),
        pci(){};

ostream& operator<<(ostream& os, HostShare& hs)
{
    string str;

    os << hs.to_xml(str);

    return os;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& HostShare::to_xml(string& xml) const
{
    string ds_xml, pci_xml;
    ostringstream   oss;

    oss << "<HOST_SHARE>"
          << "<DISK_USAGE>" << disk_usage << "</DISK_USAGE>"
          << "<MEM_USAGE>"  << mem_usage  << "</MEM_USAGE>"
          << "<CPU_USAGE>"  << cpu_usage  << "</CPU_USAGE>"
          << "<MAX_DISK>"   << max_disk   << "</MAX_DISK>"
          << "<MAX_MEM>"    << max_mem    << "</MAX_MEM>"
          << "<MAX_CPU>"    << max_cpu    << "</MAX_CPU>"
          << "<FREE_DISK>"  << free_disk  << "</FREE_DISK>"
          << "<FREE_MEM>"   << free_mem   << "</FREE_MEM>"
          << "<FREE_CPU>"   << free_cpu   << "</FREE_CPU>"
          << "<USED_DISK>"  << used_disk  << "</USED_DISK>"
          << "<USED_MEM>"   << used_mem   << "</USED_MEM>"
          << "<USED_CPU>"   << used_cpu   << "</USED_CPU>"
          << "<RUNNING_VMS>"<<running_vms <<"</RUNNING_VMS>"
          << ds.to_xml(ds_xml)
          << pci.to_xml(pci_xml)
        << "</HOST_SHARE>";

    xml = oss.str();

    return xml;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int HostShare::from_xml_node(const xmlNodePtr node)
{
    vector<xmlNodePtr> content;
    int rc = 0;

    // Initialize the internal XML object
    ObjectXML::update_from_node(node);

    rc += xpath(disk_usage, "/HOST_SHARE/DISK_USAGE", -1);
    rc += xpath(mem_usage,  "/HOST_SHARE/MEM_USAGE",  -1);
    rc += xpath(cpu_usage,  "/HOST_SHARE/CPU_USAGE",  -1);

    rc += xpath(max_disk,   "/HOST_SHARE/MAX_DISK",   -1);
    rc += xpath(max_mem ,   "/HOST_SHARE/MAX_MEM",    -1);
    rc += xpath(max_cpu ,   "/HOST_SHARE/MAX_CPU",    -1);

    rc += xpath(free_disk,  "/HOST_SHARE/FREE_DISK",  -1);
    rc += xpath(free_mem ,  "/HOST_SHARE/FREE_MEM",   -1);
    rc += xpath(free_cpu ,  "/HOST_SHARE/FREE_CPU",   -1);

    rc += xpath(used_disk,  "/HOST_SHARE/USED_DISK",  -1);
    rc += xpath(used_mem ,  "/HOST_SHARE/USED_MEM",   -1);
    rc += xpath(used_cpu ,  "/HOST_SHARE/USED_CPU",   -1);

    rc += xpath(running_vms,"/HOST_SHARE/RUNNING_VMS",-1);

    // ------------ DS Template ---------------

    ObjectXML::get_nodes("/HOST_SHARE/DATASTORES", content);

    if( content.empty())
    {
        return -1;
    }

    rc += ds.from_xml_node( content[0] );

    ObjectXML::free_nodes(content);

    content.clear();

    if (rc != 0)
    {
        return -1;
    }

    // ------------ DS Template ---------------

    ObjectXML::get_nodes("/HOST_SHARE/PCI_DEVICES", content);

    if( content.empty())
    {
        return -1;
    }

    rc += pci.from_xml_node( content[0] );

    ObjectXML::free_nodes(content);

    content.clear();

    if (rc != 0)
    {
        return -1;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

void HostShare::set_ds_monitorization(const vector<Attribute*> &ds_att)
{
    vector<Attribute*>::const_iterator it;

    ds.erase("DS");

    for (it = ds_att.begin(); it != ds_att.end(); it++)
    {
        ds.set(*it);
    }
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

<commit_msg>feature #3028: Fix PCI device assignment<commit_after>/* ------------------------------------------------------------------------*/
/* Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs     */
/*                                                                         */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at                                                */
/*                                                                         */
/* http://www.apache.org/licenses/LICENSE-2.0                              */
/*                                                                         */
/* Unless required by applicable law or agreed to in writing, software     */
/* distributed under the License is distributed on an "AS IS" BASIS,       */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*/
/* See the License for the specific language governing permissions and     */
/* limitations under the License.                                          */
/* ------------------------------------------------------------------------*/

#include <limits.h>

#include <iostream>
#include <sstream>
#include <algorithm>

#include "HostShare.h"

using namespace std;

/* ************************************************************************ */
/* HostSharePCI                                                             */
/* ************************************************************************ */

int HostSharePCI::from_xml_node(const xmlNodePtr node)
{
    int rc = Template::from_xml_node(node);

    if (rc != 0)
    {
        return -1;
    }

    return init();
}

int HostSharePCI::init()
{
    vector<Attribute *> devices;

    int num_devs = get("PCI", devices);

    for (int i=0; i < num_devs; i++)
    {
        VectorAttribute * pci = dynamic_cast<VectorAttribute *>(devices[i]);

        if (pci == 0)
        {
            return -1;
        }

        PCIDevice * pcidev = new PCIDevice(pci);

        pci_devices.insert(make_pair(pcidev->address, pcidev));
    }

    return 0;
}

/* ------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------*/

bool HostSharePCI::test_set(unsigned int vendor_id, unsigned int device_id,
        unsigned int class_id, VectorAttribute * devreq, int vmid,
        std::set<string>& assigned)
{
    map<string, PCIDevice *>::iterator it;

    for (it=pci_devices.begin(); it!=pci_devices.end(); it++)
    {
        PCIDevice * dev = it->second;

        if ((class_id  == 0 || dev->class_id  == class_id)  &&
		    (vendor_id == 0 || dev->vendor_id == vendor_id) &&
            (device_id == 0 || dev->device_id == device_id) &&
            dev->vmid  == -1 &&
            assigned.find(dev->address) == assigned.end())
        {
            assigned.insert(dev->address);

            if (vmid != -1)
            {
                dev->vmid = vmid;
                dev->attrs->replace("VMID", vmid);

                devreq->replace("DOMAIN",dev->attrs->vector_value("DOMAIN"));
                devreq->replace("BUS",dev->attrs->vector_value("BUS"));
                devreq->replace("SLOT",dev->attrs->vector_value("SLOT"));
                devreq->replace("FUNCTION",dev->attrs->vector_value("FUNCTION"));

                devreq->replace("ADDRESS",dev->attrs->vector_value("ADDRESS"));
            }

            return true;
        }
    }

    return false;
}

/* ------------------------------------------------------------------------*/

bool HostSharePCI::test_set(vector<Attribute *> &devs, int vmid)
{
    vector<Attribute *>::iterator it;
    std::set<string> assigned;

    unsigned int vendor_id, device_id, class_id;

    for ( it=devs.begin(); it!= devs.end(); it++)
    {
        VectorAttribute * pci = dynamic_cast<VectorAttribute *>(*it);

        if ( pci == 0 )
        {
            return false;
        }

        vendor_id = get_pci_value("VENDOR", pci);
        device_id = get_pci_value("DEVICE", pci);
        class_id  = get_pci_value("CLASS", pci);

        if (!test_set(vendor_id, device_id, class_id, pci, vmid, assigned))
        {
            return false;
        }
    }

    return true;
}

/* ------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------*/

void HostSharePCI::del(const vector<Attribute *> &devs)
{
    vector<Attribute *>::const_iterator it;
    map<string, PCIDevice *>::iterator pci_it;

    for ( it=devs.begin(); it!= devs.end(); it++)
    {
        const VectorAttribute * pci = dynamic_cast<const VectorAttribute *>(*it);

        if ( pci == 0 )
        {
            continue;
        }

        pci_it = pci_devices.find(pci->vector_value("ADDRESS"));

        if (pci_it != pci_devices.end())
        {
            pci_it->second->vmid = -1;
            pci_it->second->attrs->replace("VMID",-1);
        }
    }
};

/* ------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------*/

void HostSharePCI::set_monitorization(vector<Attribute*> &pci_att)
{
    vector<Attribute*>::iterator it;
    map<string, PCIDevice*>::iterator pci_it;

    string address;

    for (it = pci_att.begin(); it != pci_att.end(); it++)
    {
        VectorAttribute * pci = dynamic_cast<VectorAttribute *>(*it);

        if ( pci == 0 )
        {
            continue;
        }

        address = pci->vector_value("ADDRESS");

        if (address.empty())
        {
            delete pci;
            continue;
        }

        pci_it = pci_devices.find(address);

        if (pci_it != pci_devices.end())
        {
            delete pci;
            continue;
        }

        PCIDevice * dev = new PCIDevice(pci);

        pci_devices.insert(make_pair(address, dev));

        set(pci);
    }
};

/* ------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------*/

unsigned int HostSharePCI::get_pci_value(const char * name,
    const VectorAttribute * pci_device)
{
    string temp;

    temp = pci_device->vector_value(name);

    if (temp.empty())
    {
        return 0;
    }

    unsigned int  pci_value;
    istringstream iss(temp);

    iss >> hex >> pci_value;

    if (iss.fail() || !iss.eof())
    {
        return 0;
    }

    return pci_value;
}

HostSharePCI::PCIDevice::PCIDevice(VectorAttribute * _attrs)
    : vmid(-1), attrs(_attrs)
{
    vendor_id = get_pci_value("VENDOR", attrs);
    device_id = get_pci_value("DEVICE", attrs);
    class_id  = get_pci_value("CLASS", attrs);

    attrs->vector_value("VMID", vmid);
    attrs->vector_value("ADDRESS", address);
};

/* ************************************************************************ */
/* HostShare :: Constructor/Destructor                                      */
/* ************************************************************************ */

HostShare::HostShare(long long _max_disk,long long _max_mem,long long _max_cpu):
        ObjectXML(),
        disk_usage(0),
        mem_usage(0),
        cpu_usage(0),
        max_disk(_max_disk),
        max_mem(_max_mem),
        max_cpu(_max_cpu),
        free_disk(0),
        free_mem(0),
        free_cpu(0),
        used_disk(0),
        used_mem(0),
        used_cpu(0),
        running_vms(0),
        ds(),
        pci(){};

ostream& operator<<(ostream& os, HostShare& hs)
{
    string str;

    os << hs.to_xml(str);

    return os;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& HostShare::to_xml(string& xml) const
{
    string ds_xml, pci_xml;
    ostringstream   oss;

    oss << "<HOST_SHARE>"
          << "<DISK_USAGE>" << disk_usage << "</DISK_USAGE>"
          << "<MEM_USAGE>"  << mem_usage  << "</MEM_USAGE>"
          << "<CPU_USAGE>"  << cpu_usage  << "</CPU_USAGE>"
          << "<MAX_DISK>"   << max_disk   << "</MAX_DISK>"
          << "<MAX_MEM>"    << max_mem    << "</MAX_MEM>"
          << "<MAX_CPU>"    << max_cpu    << "</MAX_CPU>"
          << "<FREE_DISK>"  << free_disk  << "</FREE_DISK>"
          << "<FREE_MEM>"   << free_mem   << "</FREE_MEM>"
          << "<FREE_CPU>"   << free_cpu   << "</FREE_CPU>"
          << "<USED_DISK>"  << used_disk  << "</USED_DISK>"
          << "<USED_MEM>"   << used_mem   << "</USED_MEM>"
          << "<USED_CPU>"   << used_cpu   << "</USED_CPU>"
          << "<RUNNING_VMS>"<<running_vms <<"</RUNNING_VMS>"
          << ds.to_xml(ds_xml)
          << pci.to_xml(pci_xml)
        << "</HOST_SHARE>";

    xml = oss.str();

    return xml;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int HostShare::from_xml_node(const xmlNodePtr node)
{
    vector<xmlNodePtr> content;
    int rc = 0;

    // Initialize the internal XML object
    ObjectXML::update_from_node(node);

    rc += xpath(disk_usage, "/HOST_SHARE/DISK_USAGE", -1);
    rc += xpath(mem_usage,  "/HOST_SHARE/MEM_USAGE",  -1);
    rc += xpath(cpu_usage,  "/HOST_SHARE/CPU_USAGE",  -1);

    rc += xpath(max_disk,   "/HOST_SHARE/MAX_DISK",   -1);
    rc += xpath(max_mem ,   "/HOST_SHARE/MAX_MEM",    -1);
    rc += xpath(max_cpu ,   "/HOST_SHARE/MAX_CPU",    -1);

    rc += xpath(free_disk,  "/HOST_SHARE/FREE_DISK",  -1);
    rc += xpath(free_mem ,  "/HOST_SHARE/FREE_MEM",   -1);
    rc += xpath(free_cpu ,  "/HOST_SHARE/FREE_CPU",   -1);

    rc += xpath(used_disk,  "/HOST_SHARE/USED_DISK",  -1);
    rc += xpath(used_mem ,  "/HOST_SHARE/USED_MEM",   -1);
    rc += xpath(used_cpu ,  "/HOST_SHARE/USED_CPU",   -1);

    rc += xpath(running_vms,"/HOST_SHARE/RUNNING_VMS",-1);

    // ------------ DS Template ---------------

    ObjectXML::get_nodes("/HOST_SHARE/DATASTORES", content);

    if( content.empty())
    {
        return -1;
    }

    rc += ds.from_xml_node( content[0] );

    ObjectXML::free_nodes(content);

    content.clear();

    if (rc != 0)
    {
        return -1;
    }

    // ------------ DS Template ---------------

    ObjectXML::get_nodes("/HOST_SHARE/PCI_DEVICES", content);

    if( content.empty())
    {
        return -1;
    }

    rc += pci.from_xml_node( content[0] );

    ObjectXML::free_nodes(content);

    content.clear();

    if (rc != 0)
    {
        return -1;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

void HostShare::set_ds_monitorization(const vector<Attribute*> &ds_att)
{
    vector<Attribute*>::const_iterator it;

    ds.erase("DS");

    for (it = ds_att.begin(); it != ds_att.end(); it++)
    {
        ds.set(*it);
    }
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

<|endoftext|>


<commit_before>/* Given a funnel and a description of obstacles (in terms of vertices), check if the funnel is collision free when executed beginning at state x.

Inputs:
x: state from which funnel is executed (only the cyclic dimensions matter, really)

forest: cell array containing vertices of obstacles

funnelLibrary: struct containing funnel library
	funnelLibrary(*).xyz: xyz positions at time points (double 3 X N)
	funnelLibrary(*).cS: cholesky factorization of projection of S matrix (cell array)

funnelIdx: index of funnel to be checked

Output: Whether funnel is collision free (boolean)

Author: Anirudha Majumdar
Date: Nov 12 2013
*/

// Mex stuff
#include <mex.h>
#include <math.h>
#include <matrix.h>

// Timer functions
// #include <chrono>
// #include <ctime>
// #include <time.h>

// Internal access to bullet
#include "LinearMath/btTransform.h"

#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
// #include <iostream>

#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "LinearMath/btTransformUtil.h"

using namespace std;

// Set solvers for bullet
static btVoronoiSimplexSolver sGjkSimplexSolver;
static btGjkEpaPenetrationDepthSolver epaSolver;

/*Sphere of radius r representing the point.
We could probably make the radius 0 and be ok, but I'm not sure if bullet expects things to be non-degenrate.
*/
static const double g_radius = 1.0; // Don't change: leave at 1.0
static btSphereShape* g_point = new btSphereShape(g_radius);

double ptToPolyBullet(double *vertsPr, size_t nRows, size_t nCols){

	// Initialize polytope object with single point
	btConvexHullShape polytope(btVector3(vertsPr[0],vertsPr[1],vertsPr[2]), 1);

	// Add rest of the points (note the indexing starts from 1 on the loop)
	for(int i=1;i<nCols;i++){
			polytope.addPoint(btVector3(vertsPr[i*nRows],vertsPr[i*nRows+1],vertsPr[i*nRows+2]));

	}

	 // Assign elements of verts (input) to polytope
	btTransform tr;
	btGjkPairDetector::ClosestPointInput input;
	tr.setIdentity();
	input.m_transformA = tr;
	input.m_transformB = tr;

	btGjkPairDetector convexConvex(g_point,&polytope,&sGjkSimplexSolver,&epaSolver);

	// Output
	btPointCollector gjkOutput;

	convexConvex.getClosestPoints(input, gjkOutput, 0);

    return gjkOutput.m_distance + g_radius + CONVEX_DISTANCE_MARGIN;

}

/* Shift and transform vertices
 */
double *shiftAndTransform(double *verts, double *vertsT, const mxArray *x, mxArray *x0, int k, mxArray *cSk, size_t nRows, size_t nCols)
{
    /* This can and maybe should be sped up. For example, we know that cSk is upper triangular.*/
    double *dcSk = mxGetPr(cSk);
    double *dx0 = mxGetPr(x0);
    double *dx = mxGetPr(x);

    for(int i=0;i<nRows;i++){
        for(int j=0;j<nCols;j++){
            vertsT[j*nRows+i] = dcSk[i]*(verts[j*nRows+0]-dx0[k*nRows+0]-dx[0]) + dcSk[nRows+i]*(verts[j*nRows+1]-dx0[k*nRows+1]-dx[1]) + dcSk[2*nRows+i]*(verts[j*nRows+2]-dx0[k*nRows+2]-dx[2]);
            // mexPrintf("i: %d, j: %d, val: %f\n", i, j, vertsT[j*nRows+i]);
        }
    }

    return vertsT;

}

/* Checks if a given funnel number funnelIdx is collision free if executed beginning at state x. Returns a boolean (true if collision free, false if not).
*/
bool isCollisionFree(int funnelIdx, const mxArray *x, const mxArray *funnelLibrary, const mxArray *forest, mwSize numObs, double *min_dist)
{

// Initialize some variables
double *verts; // cell element (i.e. vertices)
mxArray *x0 = mxGetField(funnelLibrary, funnelIdx, "xyz"); // all points on trajectory
mxArray *obstacle;
mxArray *cS = mxGetField(funnelLibrary, funnelIdx, "cS");
mxArray *cSk;
size_t nCols;
size_t nRows;
double distance;

// Get number of time samples
mwSize N = mxGetNumberOfElements(mxGetField(funnelLibrary, funnelIdx, "cS"));

// Initialize collFree to true
bool collFree = true;

// For each time sample, we need to check if we are collision free
// mxArray *collisions = mxCreateLogicalMatrix(numObs,N);

for(int k=0;k<N;k++)
{

    // Get pointer to cholesky factorization of S at this time
    cSk = mxGetCell(cS,k);

    for(mwIndex jForest=0;jForest<numObs;jForest++)
    {

    // Get vertices of this obstacle
    obstacle = mxGetCell(forest, jForest);
    verts = mxGetPr(mxGetCell(forest, jForest)); // Get vertices
    nCols = mxGetN(obstacle);
    nRows = mxGetM(obstacle);

    double *vertsT = mxGetPr(mxCreateDoubleMatrix(nRows, nCols, mxREAL));

    // Shift vertices so that point on trajectory is at origin and transform by cholesky of S
    vertsT = shiftAndTransform(verts, vertsT, x, x0, k, cSk, nRows, nCols);

    // Call bullet to do point to polytope distance computation
    distance = ptToPolyBullet(vertsT, nRows, nCols);

    // Update min_dist
    if(distance < *min_dist){
        *min_dist = distance;
    }

    // mexPrintf("distance: %f\n", distance);

    // Check if distance is less than 1 (i.e. not collision free). If so, return
     //if(distance < 1){
       //collFree = false;
      // return collFree;
    //}

    }
}

if(*min_dist < 1){
    collFree = false;
}

return collFree;

}

/* Main mex funtion*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

// Get x (state) from which funnel is to be executed
const mxArray *x;
x = prhs[0];
// x = mxGetPr(prhs[0]);

// Deal with forest cell (second input)
const mxArray *forest; // Cell array containing forest (pointer)

forest = prhs[1]; // Get forest cell (second input)
mwSize numObs = mxGetNumberOfElements(forest); // Number of obstacles

// Now deal with funnel library object (third input)
const mxArray *funnelLibrary; // Funnel library (pointer)

funnelLibrary = prhs[2]; // Get funnel library (third input)

// Get funnelIdx (subtract 1 since index is coming from matlab)
int funnelIdx;
funnelIdx = (int )mxGetScalar(prhs[3]);
funnelIdx = funnelIdx-1;

// Initialize min_dist
// double min_dist_init = 1000000.0;
double min_dist = 1000000.0;
/*// Return min_dist if asked for
if (nlhs > 1){
        plhs[1] = mxCreateDoubleMatrix(1,1,mxREAL);
        min_dist = mxGetPr(plhs[1]);
}*/
// &min_dist = &min_dist_init;

// mexPrintf("min_dist: %f", min_dist);

// Initialize next funnel (output of this function)
bool collFree = isCollisionFree(funnelIdx, x, funnelLibrary, forest, numObs, &min_dist);

// Return collFree
plhs[0] = mxCreateLogicalScalar(collFree);

// mexPrintf("min_dist: %f", min_dist);

// Return min_dist if asked for
if (nlhs > 1){
        plhs[1] = mxCreateDoubleScalar(min_dist);
}

return;
}

<commit_msg>cleaned up comments in isCollisionFree_mex<commit_after>/* Given a funnel and a description of obstacles (in terms of vertices), check if the funnel is collision free when executed beginning at state x.

Inputs:
x: state from which funnel is executed (only the cyclic dimensions matter, really)

forest: cell array containing vertices of obstacles

funnelLibrary: struct containing funnel library
	funnelLibrary(*).xyz: xyz positions at time points (double 3 X N)
	funnelLibrary(*).cS: cholesky factorization of projection of S matrix (cell array)

funnelIdx: index of funnel to be checked

Output: Whether funnel is collision free (boolean)

Author: Anirudha Majumdar
Date: Nov 12 2013
*/

// Mex stuff
#include <mex.h>
#include <math.h>
#include <matrix.h>

// Internal access to bullet
#include "LinearMath/btTransform.h"

#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
// #include <iostream>

#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "LinearMath/btTransformUtil.h"

using namespace std;

// Set solvers for bullet
static btVoronoiSimplexSolver sGjkSimplexSolver;
static btGjkEpaPenetrationDepthSolver epaSolver;

/*Sphere of radius r representing the point.
We could probably make the radius 0 and be ok, but I'm not sure if bullet expects things to be non-degenrate.
*/
static const double g_radius = 1.0; // Don't change: leave at 1.0
static btSphereShape* g_point = new btSphereShape(g_radius);

double ptToPolyBullet(double *vertsPr, size_t nRows, size_t nCols){

	// Initialize polytope object with single point
	btConvexHullShape polytope(btVector3(vertsPr[0],vertsPr[1],vertsPr[2]), 1);

	// Add rest of the points (note the indexing starts from 1 on the loop)
	for(int i=1;i<nCols;i++){
			polytope.addPoint(btVector3(vertsPr[i*nRows],vertsPr[i*nRows+1],vertsPr[i*nRows+2]));

	}

	 // Assign elements of verts (input) to polytope
	btTransform tr;
	btGjkPairDetector::ClosestPointInput input;
	tr.setIdentity();
	input.m_transformA = tr;
	input.m_transformB = tr;

	btGjkPairDetector convexConvex(g_point,&polytope,&sGjkSimplexSolver,&epaSolver);

	// Output
	btPointCollector gjkOutput;

	convexConvex.getClosestPoints(input, gjkOutput, 0);

    return gjkOutput.m_distance + g_radius + CONVEX_DISTANCE_MARGIN;

}

/* Shift and transform vertices
 */
double *shiftAndTransform(double *verts, double *vertsT, const mxArray *x, mxArray *x0, int k, mxArray *cSk, size_t nRows, size_t nCols)
{
    /* This can and maybe should be sped up. For example, we know that cSk is upper triangular.*/
    double *dcSk = mxGetPr(cSk);
    double *dx0 = mxGetPr(x0);
    double *dx = mxGetPr(x);

    for(int i=0;i<nRows;i++){
        for(int j=0;j<nCols;j++){
            vertsT[j*nRows+i] = dcSk[i]*(verts[j*nRows+0]-dx0[k*nRows+0]-dx[0]) + dcSk[nRows+i]*(verts[j*nRows+1]-dx0[k*nRows+1]-dx[1]) + dcSk[2*nRows+i]*(verts[j*nRows+2]-dx0[k*nRows+2]-dx[2]);
        }
    }

    return vertsT;

}

/* Checks if a given funnel number funnelIdx is collision free if executed beginning at state x. Returns a boolean (true if collision free, false if not).
*/
bool isCollisionFree(int funnelIdx, const mxArray *x, const mxArray *funnelLibrary, const mxArray *forest, mwSize numObs, double *min_dist)
{

    // Initialize some variables
    double *verts; // cell element (i.e. vertices)
    mxArray *x0 = mxGetField(funnelLibrary, funnelIdx, "xyz"); // all points on trajectory
    mxArray *obstacle;
    mxArray *cS = mxGetField(funnelLibrary, funnelIdx, "cS");
    mxArray *cSk;
    size_t nCols;
    size_t nRows;
    double distance;

    // Get number of time samples
    mwSize N = mxGetNumberOfElements(mxGetField(funnelLibrary, funnelIdx, "cS"));

    // Initialize collFree to true
    bool collFree = true;

    // For each time sample, we need to check if we are collision free
    for(int k=0;k<N;k++)
    {
        // Get pointer to cholesky factorization of S at this time
        cSk = mxGetCell(cS,k);
        for(mwIndex jForest=0;jForest<numObs;jForest++)
        {
            // Get vertices of this obstacle
            obstacle = mxGetCell(forest, jForest);
            verts = mxGetPr(mxGetCell(forest, jForest)); // Get vertices
            nCols = mxGetN(obstacle);
            nRows = mxGetM(obstacle);

            double *vertsT = mxGetPr(mxCreateDoubleMatrix(nRows, nCols, mxREAL));

            // Shift vertices so that point on trajectory is at origin and transform by cholesky of S
            vertsT = shiftAndTransform(verts, vertsT, x, x0, k, cSk, nRows, nCols);

            // Call bullet to do point to polytope distance computation
            distance = ptToPolyBullet(vertsT, nRows, nCols);

            // Update min_dist
            if(distance < *min_dist){
                *min_dist = distance;
            }
        }
    }

    if(*min_dist < 1){
        collFree = false;
    }

    return collFree;
}

/* Main mex funtion*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

    // Get x (state) from which funnel is to be executed
    const mxArray *x;
    x = prhs[0];

    // Deal with forest cell (second input)
    const mxArray *forest; // Cell array containing forest (pointer)

    forest = prhs[1]; // Get forest cell (second input)
    mwSize numObs = mxGetNumberOfElements(forest); // Number of obstacles

    // Now deal with funnel library object (third input)
    const mxArray *funnelLibrary; // Funnel library (pointer)

    funnelLibrary = prhs[2]; // Get funnel library (third input)

    // Get funnelIdx (subtract 1 since index is coming from matlab)
    int funnelIdx;
    funnelIdx = (int )mxGetScalar(prhs[3]);
    funnelIdx = funnelIdx-1;

    // Initialize min_dist
    double min_dist = 1000000.0;

    // Initialize next funnel (output of this function)
    bool collFree = isCollisionFree(funnelIdx, x, funnelLibrary, forest, numObs, &min_dist);

    plhs[0] = mxCreateLogicalScalar(collFree);

    // Return min_dist if asked for
    if (nlhs > 1) {
        plhs[1] = mxCreateDoubleScalar(min_dist);
    }

return;
}

<|endoftext|>


<commit_before>#include <algorithm>
#include <functional>
#include <utility>
#include "lhef.h"

namespace lhef {
Particles SelectParticlesBy(std::function<bool(const Particle&)> pred,
                            const LHEFEvent& lhe) {
    Particles ps;
    auto entry = lhe.particle_entries();
    std::for_each(entry.cbegin(), entry.cend(),
                  [&] (const std::pair<int, Particle>& pmap) {
                      Particle p = pmap.second;
                      if (pred(p)) {
                          ps.push_back(p);
                      }});
    return ps;
}

Particles InitialStates(const LHEFEvent& lhe) {
    auto pred = [] (const Particle& p) {
        return p.mothup.first == 1;
    };
    return SelectParticlesBy(pred, lhe);
}

Particles FinalStates(const LHEFEvent& lhe) {
    auto pred = [] (const Particle& p) {
        return p.istup == 1;
    };
    return SelectParticlesBy(pred, lhe);
}

bool ParticleExists(const ParticleID& pid, const Particle& p) {
    return std::any_of(pid.cbegin(), pid.cend(),
                       [&] (const int& id) {
                           return id == p.idup;
                       });
}

Particles ParticlesOf(const ParticleID& pid, const LHEFEvent& lhe) {
    auto pred = [&] (const Particle& p) {
        return ParticleExists(pid, p);
    };
    return SelectParticlesBy(pred, lhe);
}

ParticleLines ParticleLinesOf(const ParticleID& pid, const LHEFEvent& lhe) {
    ParticleLines line;
    auto entry = lhe.particle_entries();
    for (const auto& e : entry) {
        Particle p = e.second;
        if (ParticleExists(pid, p)) {
            line.push_back(e.first);
        }
    }
    return line;
}

Particle Mother(const Particle& p, const LHEFEvent& lhe) {
    int mo_line = p.mothup.first;
    auto entry = lhe.particle_entries();
    auto mo_pos = entry.find(mo_line);
    if (mo_pos == entry.end()) {  // mother particle not found
        return entry.at(1);
    } else {
        return entry.at(mo_line);
    }
}

Particle Ancestor(const Particle& p, const LHEFEvent& lhe) {
    Particle mother = Mother(p, lhe);
    return mother.mothup.first == 1? mother : Ancestor(mother, lhe);
}

Particles Daughters(int pline, const LHEFEvent& lhe) {
    auto pred = [&] (const Particle& p) {
        return p.mothup.first == pline;
    };
    return SelectParticlesBy(pred, lhe);
}

bool IsInMotherLine(int pline, const Particle& p, const LHEFEvent& lhe) {
    if (p.mothup.first == 1) {
        return false;
    } else if (p.mothup.first == pline) {
        return true;
    } else {
        Particle direct_mother = Mother(p, lhe);
        return IsInMotherLine(pline, direct_mother, lhe);
    }
}

Particles FinalDaughters(int pline, const LHEFEvent& lhe) {
    Particles finalstates = FinalStates(lhe);
    auto pos = std::remove_if(finalstates.begin(), finalstates.end(),
                              [&] (const Particle& p) {
                                  return !IsInMotherLine(pline, p, lhe);
                              });
    finalstates.erase(pos, finalstates.end());
    return finalstates;
}
}  // namespace lhef
<commit_msg>Modify SelectParticlesBy function, remove unnecessary header<commit_after>#include "lhef.h"
#include <algorithm>
#include <functional>

namespace lhef {
Particles SelectParticlesBy(std::function<bool(const Particle&)> pred,
                            const LHEFEvent& lhe) {
    Particles ps;
    auto entry = lhe.particle_entries();
    std::for_each(entry.cbegin(), entry.cend(),
                  [&] (const EventEntry::value_type& pmap) {
                      auto p = pmap.second;
                      if (pred(p)) {
                          ps.push_back(p);
                      }});
    return ps;
}

Particles InitialStates(const LHEFEvent& lhe) {
    auto pred = [] (const Particle& p) {
        return p.mothup.first == 1;
    };
    return SelectParticlesBy(pred, lhe);
}

Particles FinalStates(const LHEFEvent& lhe) {
    auto pred = [] (const Particle& p) {
        return p.istup == 1;
    };
    return SelectParticlesBy(pred, lhe);
}

bool ParticleExists(const ParticleID& pid, const Particle& p) {
    return std::any_of(pid.cbegin(), pid.cend(),
                       [&] (const int& id) {
                           return id == p.idup;
                       });
}

Particles ParticlesOf(const ParticleID& pid, const LHEFEvent& lhe) {
    auto pred = [&] (const Particle& p) {
        return ParticleExists(pid, p);
    };
    return SelectParticlesBy(pred, lhe);
}

ParticleLines ParticleLinesOf(const ParticleID& pid, const LHEFEvent& lhe) {
    ParticleLines line;
    auto entry = lhe.particle_entries();
    for (const auto& e : entry) {
        auto p = e.second;
        if (ParticleExists(pid, p)) {
            line.push_back(e.first);
        }
    }
    return line;
}

Particle Mother(const Particle& p, const LHEFEvent& lhe) {
    int mo_line = p.mothup.first;
    auto entry = lhe.particle_entries();
    auto mo_pos = entry.find(mo_line);
    if (mo_pos == entry.end()) {  // mother particle not found
        return entry.at(1);
    } else {
        return entry.at(mo_line);
    }
}

Particle Ancestor(const Particle& p, const LHEFEvent& lhe) {
    Particle mother = Mother(p, lhe);
    return mother.mothup.first == 1? mother : Ancestor(mother, lhe);
}

Particles Daughters(int pline, const LHEFEvent& lhe) {
    auto pred = [&] (const Particle& p) {
        return p.mothup.first == pline;
    };
    return SelectParticlesBy(pred, lhe);
}

bool IsInMotherLine(int pline, const Particle& p, const LHEFEvent& lhe) {
    if (p.mothup.first == 1) {
        return false;
    } else if (p.mothup.first == pline) {
        return true;
    } else {
        Particle direct_mother = Mother(p, lhe);
        return IsInMotherLine(pline, direct_mother, lhe);
    }
}

Particles FinalDaughters(int pline, const LHEFEvent& lhe) {
    Particles finalstates = FinalStates(lhe);
    auto pos = std::remove_if(finalstates.begin(), finalstates.end(),
                              [&] (const Particle& p) {
                                  return !IsInMotherLine(pline, p, lhe);
                              });
    finalstates.erase(pos, finalstates.end());
    return finalstates;
}
}  // namespace lhef
<|endoftext|>


<commit_before>#ifndef _ctoolhu_typesafe_id_included_
#define _ctoolhu_typesafe_id_included_

#include <iosfwd>

namespace Ctoolhu {

	namespace TypeSafe {

		//stores a value (id) and exposes some typical operations usually performed on ids
		template <typename IdType>
		class Storage {

			typedef Storage<IdType> self_type;

		  public:

			bool operator ==(const self_type &comp) const
			{
				return _id == comp._id;
			}

			bool operator !=(const self_type &comp) const
			{
				return _id != comp._id;
			}

			bool operator <(const self_type &comp) const
			{
				return _id < comp._id;
			}

			bool operator >(const self_type &comp) const
			{
				return _id > comp._id;
			}

			bool operator <=(const self_type &comp) const
			{
				return _id <= comp._id;
			}

			bool operator >=(const self_type &comp) const
			{
				return _id >= comp._id;
			}

			friend std::ostream &operator <<(std::ostream &out, const self_type &storage)
			{
				out << storage._id;
				return out;
			}

		  protected:

			Storage() = default;

			IdType _id;
		};

		//policy defining that the conversion to stored id type is implicit
		template <typename IdType>
		class ImplicitConversion : public Storage<IdType> {

		  public:

			operator IdType() const
			{
				return _id;
			}

		  protected:

			ImplicitConversion() = default;
		};

		//policy defining that the conversion to stored id type is explicit so that it cannot be mistakenly juxtaposed for the underlying type
		template <typename IdType>
		class ExplicitConversion : public Storage<IdType> {

		  public:

			explicit operator IdType() const
			{
				return _id;
			}

		  protected:

			ExplicitConversion() = default;
		};

		//Tool for preventing mix-up of ids of different objects by means of
		//distinguishing their id types and disallowing conversion between them.
		//The conversions to the underlying type are based on the chosen policy.
		//
		//e.g. for lesson ID use (inside class Lesson)
		//
		//	Id<Lesson> _id;
		//
		//instead of
		//
		//	int _id;
		//
		template <
			class RequestingObject,		//type of the object which will have this id
			typename IdType = int,		//type of the id that would normally be used
			template <typename> class ConversionPolicy = ImplicitConversion
		>
		class Id : public ConversionPolicy<IdType> {

		  public:

			typedef RequestingObject object_type;
			typedef IdType id_type;

			explicit Id(IdType id)
#ifdef _DEBUG
				: _val(_id)
#endif
			{
				_id = id;
			}

#ifdef _DEBUG
			Id(const Id &src)
				: _val(_id)
			{
				_id = src._id;
			}

			Id &operator =(const Id &src)
			{
				_id = src._id;
				return *this;
			}

		  private:

			const IdType &_val; //so that we can see the value readily in watch window of the debugger
#endif
		};

	} //ns TypeSafe

} //ns Ctoolhu

#endif //file guard
<commit_msg>simplified operator << (no change in semantics)<commit_after>#ifndef _ctoolhu_typesafe_id_included_
#define _ctoolhu_typesafe_id_included_

#include <iosfwd>

namespace Ctoolhu {

	namespace TypeSafe {

		//stores a value (id) and exposes some typical operations usually performed on ids
		template <typename IdType>
		class Storage {

			typedef Storage<IdType> self_type;

		  public:

			bool operator ==(const self_type &comp) const
			{
				return _id == comp._id;
			}

			bool operator !=(const self_type &comp) const
			{
				return _id != comp._id;
			}

			bool operator <(const self_type &comp) const
			{
				return _id < comp._id;
			}

			bool operator >(const self_type &comp) const
			{
				return _id > comp._id;
			}

			bool operator <=(const self_type &comp) const
			{
				return _id <= comp._id;
			}

			bool operator >=(const self_type &comp) const
			{
				return _id >= comp._id;
			}

			friend std::ostream &operator <<(std::ostream &out, const self_type &storage)
			{
				return out << storage._id;
			}

		  protected:

			Storage() = default;

			IdType _id;
		};

		//policy defining that the conversion to stored id type is implicit
		template <typename IdType>
		class ImplicitConversion : public Storage<IdType> {

		  public:

			operator IdType() const
			{
				return _id;
			}

		  protected:

			ImplicitConversion() = default;
		};

		//policy defining that the conversion to stored id type is explicit so that it cannot be mistakenly juxtaposed for the underlying type
		template <typename IdType>
		class ExplicitConversion : public Storage<IdType> {

		  public:

			explicit operator IdType() const
			{
				return _id;
			}

		  protected:

			ExplicitConversion() = default;
		};

		//Tool for preventing mix-up of ids of different objects by means of
		//distinguishing their id types and disallowing conversion between them.
		//The conversions to the underlying type are based on the chosen policy.
		//
		//e.g. for lesson ID use (inside class Lesson)
		//
		//	Id<Lesson> _id;
		//
		//instead of
		//
		//	int _id;
		//
		template <
			class RequestingObject,		//type of the object which will have this id
			typename IdType = int,		//type of the id that would normally be used
			template <typename> class ConversionPolicy = ImplicitConversion
		>
		class Id : public ConversionPolicy<IdType> {

		  public:

			typedef RequestingObject object_type;
			typedef IdType id_type;

			explicit Id(IdType id)
#ifdef _DEBUG
				: _val(_id)
#endif
			{
				_id = id;
			}

#ifdef _DEBUG
			Id(const Id &src)
				: _val(_id)
			{
				_id = src._id;
			}

			Id &operator =(const Id &src)
			{
				_id = src._id;
				return *this;
			}

		  private:

			const IdType &_val; //so that we can see the value readily in watch window of the debugger
#endif
		};

	} //ns TypeSafe

} //ns Ctoolhu

#endif //file guard
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/io/file_class.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/string_io.hpp"
#include "flusspferd/create.hpp"
#include <boost/scoped_array.hpp>
#include <fstream>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace flusspferd;
using namespace flusspferd::io;

class file_class::impl {
public:
  std::fstream stream;

  static void create(char const *name, boost::optional<int> mode);
};

file_class::file_class(object const &obj, call_context &x)
  : stream_base(obj, 0), p(new impl)
{
  set_streambuf(p->stream.rdbuf());
  if (!x.arg.empty()) {
    string name = x.arg[0].to_string();
    open(name.c_str());
  }

  register_native_method("open", &file_class::open);
  register_native_method("close", &file_class::close);
}

file_class::~file_class()
{}

void file_class::class_info::augment_constructor(object constructor) {
  create_native_function(constructor, "create", &impl::create);
}

object file_class::class_info::create_prototype() {
  local_root_scope scope;

  object proto = create_object(flusspferd::get_prototype<stream_base>());

  create_native_method(proto, "open", 1);
  create_native_method(proto, "close", 0);

  return proto;
}

void file_class::open(char const *name) {
  security &sec = security::get();

  if (!sec.check_path(name, security::READ_WRITE))
    throw exception("Could not open file (security)");

  p->stream.open(name);

  if (!p->stream)
    throw exception("Could not open file");
}

void file_class::close() {
  p->stream.close();
}

void file_class::impl::create(char const *name, boost::optional<int> mode) {
  security &sec = security::get();

  if (!sec.check_path(name, security::CREATE))
    throw exception("Could not create file (security)");

  if (creat(name, mode.get_value_or(0666)) < 0)
    throw exception("Could not create file");
}
<commit_msg>IO/File: Add exists constructor method<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld, Ash Berlin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/io/file_class.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/string_io.hpp"
#include "flusspferd/create.hpp"
#include <boost/scoped_array.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace flusspferd;
using namespace flusspferd::io;

class file_class::impl {
public:
  std::fstream stream;

  static void create(char const *name, boost::optional<int> mode);
  static bool exists(char const *name);
};

file_class::file_class(object const &obj, call_context &x)
  : stream_base(obj, 0), p(new impl)
{
  set_streambuf(p->stream.rdbuf());
  if (!x.arg.empty()) {
    string name = x.arg[0].to_string();
    open(name.c_str());
  }

  register_native_method("open", &file_class::open);
  register_native_method("close", &file_class::close);
}

file_class::~file_class()
{}

void file_class::class_info::augment_constructor(object constructor) {
  create_native_function(constructor, "create", &impl::create);
  create_native_function(constructor, "exists", &impl::exists);
}

object file_class::class_info::create_prototype() {
  local_root_scope scope;

  object proto = create_object(flusspferd::get_prototype<stream_base>());

  create_native_method(proto, "open", 1);
  create_native_method(proto, "close", 0);
  create_native_method(proto, "exists", 0);

  return proto;
}

void file_class::open(char const *name) {
  security &sec = security::get();

  if (!sec.check_path(name, security::READ_WRITE))
    throw exception("Could not open file (security)");

  p->stream.open(name);

  define_property("fileName", string(name),
                  permanent_property | read_only_property );

  if (!p->stream)
    // TODO: Include some sort of system error message here
    throw exception("Could not open file");
}

void file_class::close() {
  p->stream.close();
  delete_property("fileName");
}

void file_class::impl::create(char const *name, boost::optional<int> mode) {
  security &sec = security::get();

  if (!sec.check_path(name, security::CREATE))
    throw exception("Could not create file (security)");

  if (creat(name, mode.get_value_or(0666)) < 0)
    throw exception("Could not create file");
}

bool file_class::impl::exists(char const *name) {
  return boost::filesystem::exists(name);
}

<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <sstream>

#include "stream_iterator.hpp"
#include "templateio.hpp"
#include "profile.hpp"

using namespace std;

//============================================================================
// Logic Language Parser.

//----------------------------------------------------------------------------
// Syntactic Structure.

using name_t = set<string>::const_iterator;

struct type_expression {
    virtual ostream& operator<< (ostream& out) const = 0;
};

struct type_variable : public type_expression {
    name_t const name;

    type_variable(name_t n) : name(n) {}

    virtual ostream& operator<< (ostream& out) const override {
        out << *name;
        return out;
    }
};

struct type_struct : public type_expression {
    name_t const name;
    vector<type_expression*> const args;

    template <typename As>
    type_struct(name_t n, As&& as) : name(n), args(forward<As>(as)) {}

    ostream& operator<< (ostream& out) const override {
        out << *name << "(";
        for (auto i = args.cbegin(); i != args.cend(); ++i) {
            (*i)->operator<<(out);
            auto j = i;
            if (++j != args.end()) {
                out << ", ";
            }
        }
        out << ")";
        return out;
    }
};

ostream& operator<< (ostream& out, type_expression* exp) {
    exp->operator<<(out);
    return out;
}

struct clause {
    type_struct* const head;
    vector<type_struct*> const impl;
    set<type_variable*> const reps;

    template <typename Is, typename Rs>
    clause(type_struct* h, Is&& is, Rs&& rs) : head(h), impl(forward<Is>(is)),
        reps(forward<Rs>(rs)) {}
};

ostream& operator<< (ostream& out, clause* cls) {
    cls->head->operator<<(out);
    auto f = cls->impl.cbegin();
    auto const l = cls->impl.cend();
    if (f != l) {
        out << " :-" << endl;
        for (auto i = f; i != l; ++i) {
            out << "\t";
            (*i)->operator<<(out);
            auto j = i;
            if (++j != l) {
                out << "," << endl;
            }
        }
    }
    out << ".";

    auto g = cls->reps.cbegin();
    auto const m = cls->reps.cend();
    if (g != m) {
        out << " [";
        for (auto i = g; i != m; ++i) {
            (*i)->operator<<(out);
            auto j = i;
            if (++j != m) {
                out << ", ";
            }
        }
        out << "]";
    }
    out << endl;

    return out;
}

//----------------------------------------------------------------------------
// Parser State

using var_t = map<string const*, type_variable*>::const_iterator;

struct parser_state {
    set<string> names; // global name table
    map<string const*, type_variable*> variables;
    set<type_variable*> repeated;
    set<type_variable*> repeated_in_goal;

    parser_state() {};
    parser_state(parser_state const&) = delete;
    parser_state& operator= (parser_state const&) = delete;

    name_t get_name(string const& name) {
        name_t const n = names.find(name);
        if (n == names.end()) {
            return names.insert(name).first;
        } else {
            return n;
        }
    }
};

//----------------------------------------------------------------------------
// Grammar

class return_variable {
public:
    return_variable() {}

    void operator() (type_variable** res, string const& name, parser_state* st) const {
        name_t const n = st->get_name(name);
        var_t i = st->variables.find(&(*n));
        if (i == st->variables.end()) {
            type_variable* const var = new type_variable(n);
            st->variables.insert(make_pair(&(*n), var));
            *res = var;
        } else {
            st->repeated.insert(i->second);
            *res = i->second;
        }
    }
} const return_variable;

struct return_args {
    return_args() {}
    void operator() (vector<type_expression*>* res, int n, type_variable* var, type_struct* str, parser_state*) const {
        switch(n) {
            case 0:
                res->push_back(var);
                break;
            case 1:
                res->push_back(str);
                break;
        }
    }
} const return_args;

struct return_struct {
    return_struct() {}
    void operator() (type_struct** res, string const& name, vector<type_expression*>& args, parser_state* st) const {
        name_t n = st->get_name(name);
        *res = new type_struct(n, args);
    }
} const return_struct;

struct return_goal {
    return_goal() {}
    void operator() (type_struct** res, type_struct* str, parser_state* st) const {
        *res = str;
        st->repeated_in_goal = st->repeated;
    }
} const return_goal;

struct return_impl {
    return_impl() {}
    void operator() (vector<type_struct*>* res, type_struct* impl, parser_state*) const {
        res->push_back(impl);
    }
} const return_impl;

struct return_clause {
    return_clause() {}
    void operator() (vector<clause*>* res, type_struct* head, vector<type_struct*>& impl, parser_state* st) const {
        res->push_back(new clause(head, impl, st->repeated_in_goal));
        st->variables.clear();
        st->repeated.clear();
        st->repeated_in_goal.clear();
    }
} const return_clause;

struct return_clause2 {
    return_clause2() {}
    void operator() (vector<clause*>* res, vector<type_struct*>& impl, parser_state* st) const {
        vector<type_expression*> vars;
        for (auto v : st->variables) {
            vars.push_back(v.second);
        }
        res->push_back(new clause(
            new type_struct(st->get_name("goal"), vars), impl, set<type_variable*> {}
        ));

        st->variables.clear();
        st->repeated.clear();
        st->repeated_in_goal.clear();
    }
} const return_clause2;

//----------------------------------------------------------------------------
// Parser

using expression_handle = pstream_handle<string, parser_state>;

auto const atom_tok = tokenise(some(accept(is_lower)) && many(accept(is_alnum || is_char('_'))));
auto const var_tok = tokenise(some(accept(is_upper || is_char('_'))) && many(accept(is_alnum)));
auto const open_tok = tokenise(accept(is_char('(')));
auto const close_tok = tokenise(accept(is_char(')')));
auto const sep_tok = tokenise(accept(is_char(',')));
auto const impl_tok = tokenise(accept_str(":-"));
auto const end_tok = tokenise(accept(is_char('.')));
auto const comment_tok = tokenise(accept(is_char('#')) && many(accept(is_print)) && accept(is_char('\n')));

pstream_handle<type_struct*, parser_state> const structure(pstream_handle<type_struct*, parser_state> const s) {
    return all(return_struct, atom_tok,
        option(discard(open_tok)
        && sep_by(any(return_args, all(return_variable, var_tok), s), discard(sep_tok))
        && discard(close_tok)));
}

pstream_handle<type_struct*, parser_state> const goal = structure(reference("structure", goal));

auto const clause = all(return_clause, all(return_goal, goal),
    option(discard(impl_tok) && sep_by(all(return_impl, goal), discard(sep_tok))) && discard(end_tok))
    || discard(impl_tok) && all(return_clause2, sep_by(all(return_impl, goal), discard(sep_tok)) && discard(end_tok))
    || discard(comment_tok);

struct expression_parser;

template <typename Range>
int parse(Range const &r) {
    auto const parser = first_token && some(clause);
    decltype(parser)::result_type a {};
    typename Range::iterator i = r.first;
    parser_state st;

    profile<expression_parser> p;
    if (parser(i, r, &a, &st)) {
        cout << "OK" << endl;
    } else {
        cout << "FAIL" << endl;
    }

    cout << a << endl;

    return i - r.first;
}

//----------------------------------------------------------------------------

int main(int const argc, char const *argv[]) {
    if (argc < 1) {
        cerr << "no input files" << endl;
    } else {
        for (int i = 1; i < argc; ++i) {
            profile<expression_parser>::reset();
            stream_range in(argv[i]);
            cout << argv[i] << endl;
            int const chars_read = parse(in);
            double const mb_per_s = static_cast<double>(chars_read) / static_cast<double>(profile<expression_parser>::report());
            cout << "parsed: " << mb_per_s << "MB/s" << endl;
        }
    }
}
<commit_msg>tidy and rename some objects<commit_after>#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <sstream>

#include "stream_iterator.hpp"
#include "templateio.hpp"
#include "profile.hpp"

using namespace std;

//============================================================================
// Logic Language Parser.

//----------------------------------------------------------------------------
// Syntactic Structure.

using name_t = set<string>::const_iterator;

struct type_expression {
    virtual ostream& operator<< (ostream& out) const = 0;
};

struct type_variable : public type_expression {
    name_t const name;

    type_variable(name_t n) : name(n) {}

    virtual ostream& operator<< (ostream& out) const override {
        out << *name;
        return out;
    }
};

struct type_struct : public type_expression {
    name_t const name;
    vector<type_expression*> const args;

    template <typename As>
    type_struct(name_t n, As&& as) : name(n), args(forward<As>(as)) {}

    ostream& operator<< (ostream& out) const override {
        out << *name << "(";
        for (auto i = args.cbegin(); i != args.cend(); ++i) {
            (*i)->operator<<(out);
            auto j = i;
            if (++j != args.end()) {
                out << ", ";
            }
        }
        out << ")";
        return out;
    }
};

ostream& operator<< (ostream& out, type_expression* exp) {
    exp->operator<<(out);
    return out;
}

struct clause {
    type_struct* const head;
    vector<type_struct*> const impl;
    set<type_variable*> const reps;

    template <typename Is, typename Rs>
    clause(type_struct* h, Is&& is, Rs&& rs) : head(h), impl(forward<Is>(is)),
        reps(forward<Rs>(rs)) {}
};

ostream& operator<< (ostream& out, clause* cls) {
    cls->head->operator<<(out);
    auto f = cls->impl.cbegin();
    auto const l = cls->impl.cend();
    if (f != l) {
        out << " :-" << endl;
        for (auto i = f; i != l; ++i) {
            out << "\t";
            (*i)->operator<<(out);
            auto j = i;
            if (++j != l) {
                out << "," << endl;
            }
        }
    }
    out << ".";

    auto g = cls->reps.cbegin();
    auto const m = cls->reps.cend();
    if (g != m) {
        out << " [";
        for (auto i = g; i != m; ++i) {
            (*i)->operator<<(out);
            auto j = i;
            if (++j != m) {
                out << ", ";
            }
        }
        out << "]";
    }
    out << endl;

    return out;
}

//----------------------------------------------------------------------------
// Parser State

using var_t = map<string const*, type_variable*>::const_iterator;

struct parser_state {
    set<string> names; // global name table
    map<string const*, type_variable*> variables;
    set<type_variable*> repeated;
    set<type_variable*> repeated_in_goal;

    parser_state() {};
    parser_state(parser_state const&) = delete;
    parser_state& operator= (parser_state const&) = delete;

    name_t get_name(string const& name) {
        name_t const n = names.find(name);
        if (n == names.end()) {
            return names.insert(name).first;
        } else {
            return n;
        }
    }
};

//----------------------------------------------------------------------------
// Grammar

struct return_variable {
    return_variable() {}
    void operator() (type_variable** res, string const& name, parser_state* st) const {
        name_t const n = st->get_name(name);
        var_t i = st->variables.find(&(*n));
        if (i == st->variables.end()) {
            type_variable* const var = new type_variable(n);
            st->variables.insert(make_pair(&(*n), var));
            *res = var;
        } else {
            st->repeated.insert(i->second);
            *res = i->second;
        }
    }
} const return_variable;

struct return_args {
    return_args() {}
    void operator() (vector<type_expression*>* res, int n, type_variable* var, type_struct* str, parser_state*) const {
        switch(n) {
            case 0:
                res->push_back(var);
                break;
            case 1:
                res->push_back(str);
                break;
        }
    }
} const return_args;

struct return_struct {
    return_struct() {}
    void operator() (type_struct** res, string const& name, vector<type_expression*>& args, parser_state* st) const {
        name_t n = st->get_name(name);
        *res = new type_struct(n, args);
    }
} const return_struct;

struct return_head {
    return_head() {}
    void operator() (type_struct** res, type_struct* str, parser_state* st) const {
        *res = str;
        st->repeated_in_goal = st->repeated;
    }
} const return_head;

struct return_goal {
    return_goal() {}
    void operator() (vector<type_struct*>* res, type_struct* impl, parser_state*) const {
        res->push_back(impl);
    }
} const return_goal;

struct return_clause {
    return_clause() {}
    void operator() (vector<clause*>* res, type_struct* head, vector<type_struct*>& impl, parser_state* st) const {
        res->push_back(new clause(head, impl, st->repeated_in_goal));
        st->variables.clear();
        st->repeated.clear();
        st->repeated_in_goal.clear();
    }
} const return_clause;

struct return_goals {
    return_goals() {}
    void operator() (vector<clause*>* res, vector<type_struct*>& impl, parser_state* st) const {
        vector<type_expression*> vars;
        for (auto v : st->variables) {
            vars.push_back(v.second);
        }
        res->push_back(new clause(
            new type_struct(st->get_name("goal"), vars), impl, set<type_variable*> {}
        ));

        st->variables.clear();
        st->repeated.clear();
        st->repeated_in_goal.clear();
    }
} const return_goals;

//----------------------------------------------------------------------------
// Parser

using expression_handle = pstream_handle<string, parser_state>;

auto const atom_tok = tokenise(some(accept(is_lower)) && many(accept(is_alnum || is_char('_'))));
auto const var_tok = tokenise(some(accept(is_upper || is_char('_'))) && many(accept(is_alnum)));
auto const open_tok = tokenise(accept(is_char('(')));
auto const close_tok = tokenise(accept(is_char(')')));
auto const sep_tok = tokenise(accept(is_char(',')));
auto const impl_tok = tokenise(accept_str(":-"));
auto const end_tok = tokenise(accept(is_char('.')));
auto const comment_tok = tokenise(accept(is_char('#')) && many(accept(is_print)) && accept(is_char('\n')));

pstream_handle<type_struct*, parser_state> const structure(pstream_handle<type_struct*, parser_state> const s) {
    return all(return_struct, atom_tok,
        option(discard(open_tok)
        && sep_by(any(return_args, all(return_variable, var_tok), s), discard(sep_tok))
        && discard(close_tok)));
}

pstream_handle<type_struct*, parser_state> const goal = structure(reference("structure", goal));

auto const clause = all(return_clause, all(return_head, goal),
    option(discard(impl_tok) && sep_by(all(return_goal, goal), discard(sep_tok))) && discard(end_tok))
    || discard(impl_tok) && all(return_goals, sep_by(all(return_goal, goal), discard(sep_tok)) && discard(end_tok))
    || discard(comment_tok);

struct expression_parser;

template <typename Range>
int parse(Range const &r) {
    auto const parser = first_token && some(clause);
    decltype(parser)::result_type a {};
    typename Range::iterator i = r.first;
    parser_state st;

    profile<expression_parser> p;
    if (parser(i, r, &a, &st)) {
        cout << "OK" << endl;
    } else {
        cout << "FAIL" << endl;
    }

    cout << a << endl;

    return i - r.first;
}

//----------------------------------------------------------------------------

int main(int const argc, char const *argv[]) {
    if (argc < 1) {
        cerr << "no input files" << endl;
    } else {
        for (int i = 1; i < argc; ++i) {
            profile<expression_parser>::reset();
            stream_range in(argv[i]);
            cout << argv[i] << endl;
            int const chars_read = parse(in);
            double const mb_per_s = static_cast<double>(chars_read) / static_cast<double>(profile<expression_parser>::report());
            cout << "parsed: " << mb_per_s << "MB/s" << endl;
        }
    }
}
<|endoftext|>


<commit_before>#include <cerrno>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <uv.h>

#include "log.h"

using std::cerr;
using std::cout;
using std::dec;
using std::endl;
using std::ofstream;
using std::ostream;
using std::ostringstream;
using std::setw;
using std::strerror;
using std::string;
using std::to_string;
using std::chrono::steady_clock;

class NullLogger : public Logger
{
public:
  NullLogger() = default;

  Logger *prefix(const char * /*file*/, int /*line*/) override { return this; }

  ostream &stream() override { return unopened; }

private:
  ofstream unopened;
};

class FileLogger : public Logger
{
public:
  FileLogger(const char *filename) : log_stream{filename, std::ios::out | std::ios::app}
  {
    if (!log_stream) {
      int stream_errno = errno;

      ostringstream msg;
      msg << "Unable to log to " << filename << ": " << strerror(stream_errno);
      err = msg.str();
    }

    FileLogger::prefix(__FILE__, __LINE__);
    log_stream << "FileLogger opened." << endl;
  }

  Logger *prefix(const char *file, int line) override
  {
    log_stream << "[" << setw(15) << file << ":" << setw(3) << dec << line << "] ";
    return this;
  }

  ostream &stream() override { return log_stream; }

  string get_error() const override { return err; }

private:
  ofstream log_stream;
  string err;
};

class StderrLogger : public Logger
{
public:
  StderrLogger()
  {
    StderrLogger::prefix(__FILE__, __LINE__);
    cerr << "StderrLogger opened." << endl;
  }

  Logger *prefix(const char *file, int line) override
  {
    cerr << "[" << setw(15) << file << ":" << setw(3) << dec << line << "] ";
    return this;
  }

  ostream &stream() override { return cerr; }

  string get_error() const override
  {
    if (!cerr) {
      return "Unable to log to stderr";
    }

    return "";
  }
};

class StdoutLogger : public Logger
{
public:
  StdoutLogger()
  {
    StdoutLogger::prefix(__FILE__, __LINE__);
    cout << "StdoutLogger opened." << endl;
  }

  Logger *prefix(const char *file, int line) override
  {
    cout << "[" << setw(15) << file << ":" << setw(3) << dec << line << "] ";
    return this;
  }

  ostream &stream() override { return cout; }

  string get_error() const override
  {
    if (!cout) {
      return "Unable to log to stdout";
    }

    return "";
  }
};

static uv_key_t current_logger_key;
static NullLogger the_null_logger;
static uv_once_t make_key_once = UV_ONCE_INIT;

static void make_key()
{
  uv_key_create(&current_logger_key);
}

Logger *Logger::current()
{
  uv_once(&make_key_once, &make_key);

  auto *logger = static_cast<Logger *>(uv_key_get(&current_logger_key));

  if (logger == nullptr) {
    uv_key_set(&current_logger_key, static_cast<void *>(&the_null_logger));
    logger = &the_null_logger;
  }

  return logger;
}

string replace_logger(const Logger *new_logger)
{
  if (new_logger != &the_null_logger) {
    string r = new_logger->get_error();
    if (!r.empty()) {
      delete new_logger;
    }
    return r;
  }

  Logger *prior = Logger::current();
  if (prior != &the_null_logger) {
    delete prior;
  }

  uv_key_set(&current_logger_key, (void *) new_logger);
  return "";
}

string Logger::to_file(const char *filename)
{
  return replace_logger(new FileLogger(filename));
}

string Logger::to_stderr()
{
  return replace_logger(new StderrLogger());
}

string Logger::to_stdout()
{
  return replace_logger(new StdoutLogger());
}

string Logger::disable()
{
  return replace_logger(&the_null_logger);
}

string Logger::from_env(const char *varname)
{
  const char *value = std::getenv(varname);
  if (value == nullptr) {
    return replace_logger(&the_null_logger);
  }

  if (std::strcmp("stdout", value) == 0) {
    return to_stdout();
  }
  if (std::strcmp("stderr", value) == 0) {
    return to_stderr();
  }
  return to_file(value);
}

string plural(long quantity, const string &singular_form, const string &plural_form)
{
  string result;
  result += to_string(quantity);
  result += " ";

  if (quantity == 1) {
    result += singular_form;
  } else {
    result += plural_form;
  }

  return result;
}

string plural(long quantity, const string &singular_form)
{
  string plural_form(singular_form + "s");
  return plural(quantity, singular_form, plural_form);
}

Timer::Timer() : start{steady_clock::now()}, duration{0}
{
  //
}

void Timer::stop()
{
  duration = measure_duration();
}

string Timer::format_duration() const
{
  size_t total = duration;
  if (total == 0) {
    total = measure_duration();
  }

  size_t milliseconds = total;
  size_t seconds = milliseconds / 1000;
  milliseconds -= (seconds * 1000);

  size_t minutes = seconds / 60;
  seconds -= (minutes * 60);

  size_t hours = minutes / 60;
  minutes -= (hours * 60);

  ostringstream out;
  if (hours > 0) out << plural(hours, "hour") << ' ';
  if (minutes > 0) out << plural(minutes, "minute") << ' ';
  if (seconds > 0) out << plural(seconds, "second") << ' ';
  out << plural(milliseconds, "millisecond") << " (" << total << "ms)";
  return out.str();
}
<commit_msg>Shhhh, linter<commit_after>#include <cerrno>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <uv.h>

#include "log.h"

using std::cerr;
using std::cout;
using std::dec;
using std::endl;
using std::ofstream;
using std::ostream;
using std::ostringstream;
using std::setw;
using std::strerror;
using std::string;
using std::to_string;
using std::chrono::steady_clock;

class NullLogger : public Logger
{
public:
  NullLogger() = default;

  Logger *prefix(const char * /*file*/, int /*line*/) override { return this; }

  ostream &stream() override { return unopened; }

private:
  ofstream unopened;
};

class FileLogger : public Logger
{
public:
  FileLogger(const char *filename) : log_stream{filename, std::ios::out | std::ios::app}
  {
    if (!log_stream) {
      int stream_errno = errno;

      ostringstream msg;
      msg << "Unable to log to " << filename << ": " << strerror(stream_errno);
      err = msg.str();
    }

    FileLogger::prefix(__FILE__, __LINE__);
    log_stream << "FileLogger opened." << endl;
  }

  Logger *prefix(const char *file, int line) override
  {
    log_stream << "[" << setw(15) << file << ":" << setw(3) << dec << line << "] ";
    return this;
  }

  ostream &stream() override { return log_stream; }

  string get_error() const override { return err; }

private:
  ofstream log_stream;
  string err;
};

class StderrLogger : public Logger
{
public:
  StderrLogger()
  {
    StderrLogger::prefix(__FILE__, __LINE__);
    cerr << "StderrLogger opened." << endl;
  }

  Logger *prefix(const char *file, int line) override
  {
    cerr << "[" << setw(15) << file << ":" << setw(3) << dec << line << "] ";
    return this;
  }

  ostream &stream() override { return cerr; }

  string get_error() const override
  {
    if (!cerr) {
      return "Unable to log to stderr";
    }

    return "";
  }
};

class StdoutLogger : public Logger
{
public:
  StdoutLogger()
  {
    StdoutLogger::prefix(__FILE__, __LINE__);
    cout << "StdoutLogger opened." << endl;
  }

  Logger *prefix(const char *file, int line) override
  {
    cout << "[" << setw(15) << file << ":" << setw(3) << dec << line << "] ";
    return this;
  }

  ostream &stream() override { return cout; }

  string get_error() const override
  {
    if (!cout) {
      return "Unable to log to stdout";
    }

    return "";
  }
};

static uv_key_t current_logger_key;
static NullLogger the_null_logger;
static uv_once_t make_key_once = UV_ONCE_INIT;

static void make_key()
{
  uv_key_create(&current_logger_key);
}

Logger *Logger::current()
{
  uv_once(&make_key_once, &make_key);

  auto *logger = static_cast<Logger *>(uv_key_get(&current_logger_key));

  if (logger == nullptr) {
    uv_key_set(&current_logger_key, static_cast<void *>(&the_null_logger));
    logger = &the_null_logger;
  }

  return logger;
}

string replace_logger(const Logger *new_logger)
{
  if (new_logger != &the_null_logger) {
    string r = new_logger->get_error();
    if (!r.empty()) {
      delete new_logger;
    }
    return r;
  }

  Logger *prior = Logger::current();
  if (prior != &the_null_logger) {
    delete prior;
  }

  uv_key_set(&current_logger_key, (void *) new_logger);
  return "";
}

string Logger::to_file(const char *filename)
{
  return replace_logger(new FileLogger(filename)); // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
}

string Logger::to_stderr()
{
  return replace_logger(new StderrLogger()); // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
}

string Logger::to_stdout()
{
  return replace_logger(new StdoutLogger()); // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
}

string Logger::disable()
{
  return replace_logger(&the_null_logger);
}

string Logger::from_env(const char *varname)
{
  const char *value = std::getenv(varname);
  if (value == nullptr) {
    return replace_logger(&the_null_logger);
  }

  if (std::strcmp("stdout", value) == 0) {
    return to_stdout();
  }
  if (std::strcmp("stderr", value) == 0) {
    return to_stderr();
  }
  return to_file(value);
}

string plural(long quantity, const string &singular_form, const string &plural_form)
{
  string result;
  result += to_string(quantity);
  result += " ";

  if (quantity == 1) {
    result += singular_form;
  } else {
    result += plural_form;
  }

  return result;
}

string plural(long quantity, const string &singular_form)
{
  string plural_form(singular_form + "s");
  return plural(quantity, singular_form, plural_form);
}

Timer::Timer() : start{steady_clock::now()}, duration{0}
{
  //
}

void Timer::stop()
{
  duration = measure_duration();
}

string Timer::format_duration() const
{
  size_t total = duration;
  if (total == 0) {
    total = measure_duration();
  }

  size_t milliseconds = total;
  size_t seconds = milliseconds / 1000;
  milliseconds -= (seconds * 1000);

  size_t minutes = seconds / 60;
  seconds -= (minutes * 60);

  size_t hours = minutes / 60;
  minutes -= (hours * 60);

  ostringstream out;
  if (hours > 0) out << plural(hours, "hour") << ' ';
  if (minutes > 0) out << plural(minutes, "minute") << ' ';
  if (seconds > 0) out << plural(seconds, "second") << ' ';
  out << plural(milliseconds, "millisecond") << " (" << total << "ms)";
  return out.str();
}
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2016 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Modules/Python/PythonInterfaceParser.h>
#include <Modules/Python/InterfaceWithPython.h>
#include <Core/Logging/Log.h>
// ReSharper disable once CppUnusedIncludeDirective
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>

using namespace SCIRun::Modules::Python;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Algorithms::Python;

PythonInterfaceParser::PythonInterfaceParser(const std::string& moduleId,
  const ModuleStateHandle& state,
  const std::vector<std::string>& portIds)
  : moduleId_(moduleId), state_(state), portIds_(portIds)
{
}

std::string PythonInterfaceParser::convertOutputSyntax(const std::string& line) const
{
  auto outputVarsToCheck = InterfaceWithPython::outputNameParameters();

  for (const auto& var : outputVarsToCheck)
  {
    auto varName = state_->getValue(var).toString();

    auto regexString = "(\\h*)" + varName + " = (.+)";
    //std::cout << "REGEX STRING " << regexString << std::endl;
    boost::regex outputRegex(regexString);
    boost::smatch what;
    if (regex_match(line, what, outputRegex))
    {
      int rhsIndex = what.size() > 2 ? 2 : 1;
      auto whitespace = what.size() > 2 ? boost::lexical_cast<std::string>(what[1]) : "";
      auto rhs = boost::lexical_cast<std::string>(what[rhsIndex]);
      auto converted = whitespace + "scirun_set_module_transient_state(\"" +
        moduleId_ + "\",\"" + varName + "\"," + rhs + ")";
      //std::cout << "CONVERTED TO " << converted << std::endl;
      return converted;
    }
  }

  return line;
}

std::string PythonInterfaceParser::convertInputSyntax(const std::string& line) const
{
  for (const auto& portId : portIds_)
  {
    auto inputName = state_->getValue(Name(portId)).toString();
    //std::cout << "FOUND INPUT VARIABLE NAME: " << inputName << " for port " << portId << std::endl;
    //std::cout << "NEED TO REPLACE " << inputName << " with\n\t" << "scirun_get_module_input_value(\"" << moduleId_ << "\", \"" << portId << "\")" << std::endl;
    auto index = line.find(inputName);
    if (index != std::string::npos)
    {
      auto codeCopy = line;
      return codeCopy.replace(index, inputName.length(),
        "scirun_get_module_input_value(\"" + moduleId_ + "\", \"" + portId + "\")");
    }
  }
  return line;
}

std::string PythonInterfaceParser::convertStandardCodeBlock(const PythonCodeBlock& block) const
{
  if (block.isMatlab)
    throw std::invalid_argument("Cannot process matlab block");

  std::ostringstream convertedCode;
  std::vector<std::string> lines;
  boost::split(lines, block.code, boost::is_any_of("\n"));
  for (const auto& line : lines)
  {
    convertedCode << convertInputSyntax(convertOutputSyntax(line)) << "\n";
  }
  return convertedCode.str();
}

PythonCode PythonInterfaceParser::extractSpecialBlocks(const std::string& code) const
{
  PythonCode blocks;
  static boost::regex matlabBlock("(.*)%%\\n(.*)\\n%%(.*)");

  boost::smatch what;
  if (regex_match(code, what, matlabBlock))
  {
    auto firstPart = std::string(what[1]);
    boost::trim(firstPart);
    auto matlabPart = std::string(what[2]);
    boost::trim(matlabPart);
    auto secondPart = std::string(what[3]);
    boost::trim(secondPart);

    parsePart(blocks, firstPart);

    if (!matlabPart.empty())
      blocks.push_back({matlabPart, true});

    parsePart(blocks, secondPart);
  }
  else
  {
    return {{code, false}};
  }
  return blocks;
}

void PythonInterfaceParser::parsePart(PythonCode& blocks, const std::string& part) const
{
  if (!part.empty())
  {
    if (part.find("%%") != std::string::npos)
    {
      auto rec = extractSpecialBlocks(part);
      blocks.insert(blocks.begin(), rec.begin(), rec.end());
    }
    else
      blocks.push_back({part, false});
  }
}

PythonCodeBlock PythonInterfaceParser::concatenateNormalBlocks(const PythonCode& codeList) const
{
  std::ostringstream ostr;
  for (const auto& block : codeList)
  {
    if (!block.isMatlab)
    {
      ostr << block.code << '\n';
    }
  }
  return {ostr.str(), false };
}
<commit_msg>Refactor<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2016 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Modules/Python/PythonInterfaceParser.h>
#include <Modules/Python/InterfaceWithPython.h>
#include <Core/Logging/Log.h>
// ReSharper disable once CppUnusedIncludeDirective
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>

using namespace SCIRun::Modules::Python;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Algorithms::Python;

PythonInterfaceParser::PythonInterfaceParser(const std::string& moduleId,
  const ModuleStateHandle& state,
  const std::vector<std::string>& portIds)
  : moduleId_(moduleId), state_(state), portIds_(portIds)
{
}

std::string PythonInterfaceParser::convertOutputSyntax(const std::string& line) const
{
  auto outputVarsToCheck = InterfaceWithPython::outputNameParameters();

  for (const auto& var : outputVarsToCheck)
  {
    auto varName = state_->getValue(var).toString();

    auto regexString = "(\\h*)" + varName + " = (.+)";
    //std::cout << "REGEX STRING " << regexString << std::endl;
    boost::regex outputRegex(regexString);
    boost::smatch what;
    if (regex_match(line, what, outputRegex))
    {
      int rhsIndex = what.size() > 2 ? 2 : 1;
      auto whitespace = what.size() > 2 ? boost::lexical_cast<std::string>(what[1]) : "";
      auto rhs = boost::lexical_cast<std::string>(what[rhsIndex]);
      auto converted = whitespace + "scirun_set_module_transient_state(\"" +
        moduleId_ + "\",\"" + varName + "\"," + rhs + ")";
      //std::cout << "CONVERTED TO " << converted << std::endl;
      return converted;
    }
  }

  return line;
}

std::string PythonInterfaceParser::convertInputSyntax(const std::string& line) const
{
  for (const auto& portId : portIds_)
  {
    auto inputName = state_->getValue(Name(portId)).toString();
    //std::cout << "FOUND INPUT VARIABLE NAME: " << inputName << " for port " << portId << std::endl;
    //std::cout << "NEED TO REPLACE " << inputName << " with\n\t" << "scirun_get_module_input_value(\"" << moduleId_ << "\", \"" << portId << "\")" << std::endl;
    auto index = line.find(inputName);
    if (index != std::string::npos)
    {
      auto codeCopy = line;
      return codeCopy.replace(index, inputName.length(),
        "scirun_get_module_input_value(\"" + moduleId_ + "\", \"" + portId + "\")");
    }
  }
  return line;
}

std::string PythonInterfaceParser::convertStandardCodeBlock(const PythonCodeBlock& block) const
{
  if (block.isMatlab)
    throw std::invalid_argument("Cannot process matlab block");

  std::ostringstream convertedCode;
  std::vector<std::string> lines;
  boost::split(lines, block.code, boost::is_any_of("\n"));
  for (const auto& line : lines)
  {
    convertedCode << convertInputSyntax(convertOutputSyntax(line)) << "\n";
  }
  return convertedCode.str();
}

PythonCode PythonInterfaceParser::extractSpecialBlocks(const std::string& code) const
{
  PythonCode blocks;
  static std::string matlabBlockRegex = std::string("(.*)") + PythonCodeBlock::delimiter
    + "\\n(.*)\\n" + PythonCodeBlock::delimiter + "(.*)";
  static boost::regex matlabBlock(matlabBlockRegex);

  boost::smatch what;
  if (regex_match(code, what, matlabBlock))
  {
    auto firstPart = std::string(what[1]);
    boost::trim(firstPart);
    auto matlabPart = std::string(what[2]);
    boost::trim(matlabPart);
    auto secondPart = std::string(what[3]);
    boost::trim(secondPart);

    parsePart(blocks, firstPart);

    if (!matlabPart.empty())
      blocks.push_back({matlabPart, true});

    parsePart(blocks, secondPart);
  }
  else
  {
    return {{code, false}};
  }
  return blocks;
}

void PythonInterfaceParser::parsePart(PythonCode& blocks, const std::string& part) const
{
  if (!part.empty())
  {
    if (part.find(PythonCodeBlock::delimiter) != std::string::npos)
    {
      auto rec = extractSpecialBlocks(part);
      blocks.insert(blocks.begin(), rec.begin(), rec.end());
    }
    else
      blocks.push_back({part, false});
  }
}

PythonCodeBlock PythonInterfaceParser::concatenateNormalBlocks(const PythonCode& codeList) const
{
  std::ostringstream ostr;
  for (const auto& block : codeList)
  {
    if (!block.isMatlab)
    {
      ostr << block.code << '\n';
    }
  }
  return {ostr.str(), false };
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <unistd.h>

int main(){
  char HOSTNAME[128];
  gethostname(HOSTNAME, sizeof HOSTNAME);
  bool REPEAT = true;

  while (REPEAT){
    string input;
    cout << getlogin() << "@" << HOSTNAME << "$ ";
    getline(cin, input);

    cout << input << endl;
  }
}
<commit_msg>hello<commit_after>#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;

int main(){
  char HOSTNAME[128];
  gethostname(HOSTNAME, sizeof HOSTNAME);
  bool REPEAT = true;

  while (REPEAT){
    string input;
    cout << getlogin() << "@" << HOSTNAME << "$ ";
    getline(cin, input);

    if (input == "exit"){
		REPEAT = false;
	}
  }
}
<|endoftext|>