<commit_before>/*
 * smartBlockWorld.cpp
 *
 *  Created on: 12 avril 2013
 *      Author: ben
 */

#include <iostream>
#include <stdlib.h>
#include <string>

#include "smartBlocksWorld.h"
#include "smartBlocksBlock.h"
#include "scheduler.h"
#include "configExporter.h"

using namespace std;

namespace SmartBlocks {

SmartBlocksWorld::SmartBlocksWorld(const Cell3DPosition &gridSize, const Vector3D &gridScale,
                                   int argc, char *argv[]):World(argc, argv) {
    cout << "\033[1;31mSmartBlocksWorld constructor\033[0m" << endl;

    if (GlutContext::GUIisEnabled) {
        objBlock = new ObjLoader::ObjLoader("../../simulatorCore/resources/textures/smartBlocksTextures",
                                            "smartBlockSimple.obj");
        objBlockForPicking = new ObjLoader::ObjLoader("../../simulatorCore/resources/textures/smartBlocksTextures",
                                                      "smartBlockPicking.obj");
        objRepere = new ObjLoader::ObjLoader("../../simulatorCore/resources/textures/latticeTextures",
                                             "repere25.obj");
    }

    lattice = new SLattice(gridSize, gridScale.hasZero() ? defaultBlockSize : gridScale);
}

SmartBlocksWorld::~SmartBlocksWorld() {
    cout << "\033[1;31mSmartBlocksWorld destructor\033[0m" << endl;
}

void SmartBlocksWorld::deleteWorld() {
    delete((SmartBlocksWorld*)world);
    world=NULL;
}

void SmartBlocksWorld::addBlock(bID blockId, BlockCodeBuilder bcb,
                                const Cell3DPosition &pos, const Color &col,
                                short orientation, bool master) {
	if (blockId > maxBlockId)
		maxBlockId = blockId;
	else if (blockId == 0)
		blockId = incrementBlockId();

    SmartBlocksBlock *smartBlock = new SmartBlocksBlock(blockId, bcb);
    buildingBlocksMap.insert(std::pair<int,BaseSimulator::BuildingBlock*>
                             (smartBlock->blockId, (BaseSimulator::BuildingBlock*)smartBlock) );
    getScheduler()->schedule(new CodeStartEvent(getScheduler()->now(), smartBlock));

    SmartBlocksGlBlock *glBlock = new SmartBlocksGlBlock(blockId);
    tabGlBlocks.push_back(glBlock);
    smartBlock->setGlBlock(glBlock);
    smartBlock->setPosition(pos);
    smartBlock->setColor(col);

    if (lattice->isInGrid(pos)) {
        lattice->insert(smartBlock, pos);
    } else {
        cerr << "ERROR : BLOCK #" << blockId << " out of the grid !!!!!" << endl;
        exit(1);
    }
}

void SmartBlocksWorld::linkBlock(const Cell3DPosition &pos) {
    SmartBlocksBlock *ptrNeighbor;
    SmartBlocksBlock *ptrBlock = (SmartBlocksBlock*)lattice->getBlock(pos);
    vector<Cell3DPosition> nRelCells = lattice->getRelativeConnectivity(pos);
    Cell3DPosition nPos;

    // Check neighbors for each interface
    for (int i = 0; i < 4; i++) {
        nPos = pos + nRelCells[i];
        ptrNeighbor = (SmartBlocksBlock*)lattice->getBlock(nPos);
        if (ptrNeighbor) {
            (ptrBlock)->getInterface(SLattice::Direction(i))->
                connect(ptrNeighbor->getInterface(SLattice::Direction(
                                                      lattice->getOppositeDirection(i))));

            OUTPUT << "connection #" << (ptrBlock)->blockId <<
                " to #" << ptrNeighbor->blockId << endl;
        } else {
            (ptrBlock)->getInterface(SLattice::Direction(i))->connect(NULL);
        }
    }
}

void SmartBlocksWorld::glDraw() {
    static const GLfloat white[]={1.0,1.0,1.0,1.0},
        gray[]={0.2,0.2,0.2,1.0};

        glMaterialfv(GL_FRONT,GL_AMBIENT,gray);
        glMaterialfv(GL_FRONT,GL_DIFFUSE,white);
        glMaterialfv(GL_FRONT,GL_SPECULAR,gray);
        glMaterialf(GL_FRONT,GL_SHININESS,40.0);
        glPushMatrix();
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,idTextureFloor);
        glNormal3f(0,0,1.0f);
        glScalef(lattice->gridSize[0]*lattice->gridScale[0],
                 lattice->gridSize[1]*lattice->gridScale[1],1.0f);
        glBegin(GL_QUADS);
        glTexCoord2f(0,0);
        glVertex3f(0.0f,0.0f,0.0f);
        glTexCoord2f(lattice->gridSize[0],0);
        glVertex3f(1.0f,0.0f,0.0f);
        glTexCoord2f(lattice->gridSize[0],lattice->gridSize[1]);
        glVertex3f(1.0,1.0,0.0f);
        glTexCoord2f(0,lattice->gridSize[1]);
        glVertex3f(0.0,1.0,0.0f);
        glEnd();
        glPopMatrix();
        // draw the axes
        objRepere->glDraw();

        glPushMatrix();
        /*glTranslatef(-lattice->gridSize[0]/2.0f*lattice->gridScale[0],
          -lattice->gridSize[1]/2.0f*lattice->gridScale[1],0); */
        glDisable(GL_TEXTURE_2D);
        vector <GlBlock*>::iterator ic=tabGlBlocks.begin();
        lock();
        while (ic!=tabGlBlocks.end()) {
            ((SmartBlocksGlBlock*)(*ic))->glDraw(objBlock);
            ic++;
        }
        unlock();

        /*// drawing the mobiles
          Physics::glDraw();
        */
        glPopMatrix();
}

void SmartBlocksWorld::glDrawIdByMaterial() {
    glPushMatrix();
    glDisable(GL_TEXTURE_2D);

    vector <GlBlock*>::iterator ic=tabGlBlocks.begin();
    int n=1;
    lock();
    while (ic!=tabGlBlocks.end()) {
        ((SmartBlocksGlBlock*)(*ic))->glDrawIdByMaterial(objBlockForPicking, n);
        ic++;
    }
    unlock();
    glPopMatrix();
}

void SmartBlocksWorld::glDrawId() {
    glPushMatrix();
    glDisable(GL_TEXTURE_2D);

    vector <GlBlock*>::iterator ic=tabGlBlocks.begin();
    int n=1;
    lock();
    while (ic!=tabGlBlocks.end()) {
        ((SmartBlocksGlBlock*)(*ic))->glDrawId(objBlock,n);
        ic++;
    }
    unlock();
    glPopMatrix();
}

void SmartBlocksWorld::loadTextures(const string &str) {
    if (GlutContext::GUIisEnabled) {
        //string path = str+"/circuit.tga";
        string path = str+"/bois.tga";
        int lx,ly;
        idTextureFloor = GlutWindow::loadTexture(path.c_str(),lx,ly);

        path=str+"/../smartBlocksTextures/digits.tga";
        idTextureDigits = GlutWindow::loadTexture(path.c_str(),lx,ly);
    }
}

void SmartBlocksWorld::setSelectedFace(int n) {
    numSelectedGlBlock = n / 5;
    string name = objBlockForPicking->getObjMtlName(n % 5);

    if (name == "Material__72") numSelectedFace = SLattice::South;
    else if (name == "Material__66") numSelectedFace = SLattice::East;
    else if (name == "Material__71") numSelectedFace = SLattice::West;
    else if (name == "Material__68") numSelectedFace = SLattice::North;
    else {
		cerr << "warning: Unrecognized picking face" << endl;
		numSelectedFace = 4;	// UNDEFINED
    }

    cerr << "SET " << name << " = " << numSelectedFace << " = "
         << lattice->getDirectionString(numSelectedFace) << endl;
}

void SmartBlocksWorld::exportConfiguration() {
	SmartBlocksConfigExporter exporter = SmartBlocksConfigExporter(this);
	exporter.exportConfiguration();
}

} // SmartBlocks namespace
<commit_msg>Suppress unnecessary trace when picking, and fix potential invalid read<commit_after>/*
 * smartBlockWorld.cpp
 *
 *  Created on: 12 avril 2013
 *      Author: ben
 */

#include <iostream>
#include <stdlib.h>
#include <string>

#include "smartBlocksWorld.h"
#include "smartBlocksBlock.h"
#include "scheduler.h"
#include "configExporter.h"

using namespace std;

namespace SmartBlocks {

SmartBlocksWorld::SmartBlocksWorld(const Cell3DPosition &gridSize, const Vector3D &gridScale,
                                   int argc, char *argv[]):World(argc, argv) {
    cout << "\033[1;31mSmartBlocksWorld constructor\033[0m" << endl;

    if (GlutContext::GUIisEnabled) {
        objBlock = new ObjLoader::ObjLoader("../../simulatorCore/resources/textures/smartBlocksTextures",
                                            "smartBlockSimple.obj");
        objBlockForPicking = new ObjLoader::ObjLoader("../../simulatorCore/resources/textures/smartBlocksTextures",
                                                      "smartBlockPicking.obj");
        objRepere = new ObjLoader::ObjLoader("../../simulatorCore/resources/textures/latticeTextures",
                                             "repere25.obj");
    }

    lattice = new SLattice(gridSize, gridScale.hasZero() ? defaultBlockSize : gridScale);
}

SmartBlocksWorld::~SmartBlocksWorld() {
    cout << "\033[1;31mSmartBlocksWorld destructor\033[0m" << endl;
}

void SmartBlocksWorld::deleteWorld() {
    delete((SmartBlocksWorld*)world);
    world=NULL;
}

void SmartBlocksWorld::addBlock(bID blockId, BlockCodeBuilder bcb,
                                const Cell3DPosition &pos, const Color &col,
                                short orientation, bool master) {
	if (blockId > maxBlockId)
		maxBlockId = blockId;
	else if (blockId == 0)
		blockId = incrementBlockId();

    SmartBlocksBlock *smartBlock = new SmartBlocksBlock(blockId, bcb);
    buildingBlocksMap.insert(std::pair<int,BaseSimulator::BuildingBlock*>
                             (smartBlock->blockId, (BaseSimulator::BuildingBlock*)smartBlock) );
    getScheduler()->schedule(new CodeStartEvent(getScheduler()->now(), smartBlock));

    SmartBlocksGlBlock *glBlock = new SmartBlocksGlBlock(blockId);
    tabGlBlocks.push_back(glBlock);
    smartBlock->setGlBlock(glBlock);
    smartBlock->setPosition(pos);
    smartBlock->setColor(col);

    if (lattice->isInGrid(pos)) {
        lattice->insert(smartBlock, pos);
    } else {
        cerr << "ERROR : BLOCK #" << blockId << " out of the grid !!!!!" << endl;
        exit(1);
    }
}

void SmartBlocksWorld::linkBlock(const Cell3DPosition &pos) {
    SmartBlocksBlock *ptrNeighbor;
    SmartBlocksBlock *ptrBlock = (SmartBlocksBlock*)lattice->getBlock(pos);
    vector<Cell3DPosition> nRelCells = lattice->getRelativeConnectivity(pos);
    Cell3DPosition nPos;

    // Check neighbors for each interface
    for (int i = 0; i < 4; i++) {
        nPos = pos + nRelCells[i];
        ptrNeighbor = (SmartBlocksBlock*)lattice->getBlock(nPos);
        if (ptrNeighbor) {
            (ptrBlock)->getInterface(SLattice::Direction(i))->
                connect(ptrNeighbor->getInterface(SLattice::Direction(
                                                      lattice->getOppositeDirection(i))));

            OUTPUT << "connection #" << (ptrBlock)->blockId <<
                " to #" << ptrNeighbor->blockId << endl;
        } else {
            (ptrBlock)->getInterface(SLattice::Direction(i))->connect(NULL);
        }
    }
}

void SmartBlocksWorld::glDraw() {
    static const GLfloat white[]={1.0,1.0,1.0,1.0},
        gray[]={0.2,0.2,0.2,1.0};

        glMaterialfv(GL_FRONT,GL_AMBIENT,gray);
        glMaterialfv(GL_FRONT,GL_DIFFUSE,white);
        glMaterialfv(GL_FRONT,GL_SPECULAR,gray);
        glMaterialf(GL_FRONT,GL_SHININESS,40.0);
        glPushMatrix();
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,idTextureFloor);
        glNormal3f(0,0,1.0f);
        glScalef(lattice->gridSize[0]*lattice->gridScale[0],
                 lattice->gridSize[1]*lattice->gridScale[1],1.0f);
        glBegin(GL_QUADS);
        glTexCoord2f(0,0);
        glVertex3f(0.0f,0.0f,0.0f);
        glTexCoord2f(lattice->gridSize[0],0);
        glVertex3f(1.0f,0.0f,0.0f);
        glTexCoord2f(lattice->gridSize[0],lattice->gridSize[1]);
        glVertex3f(1.0,1.0,0.0f);
        glTexCoord2f(0,lattice->gridSize[1]);
        glVertex3f(0.0,1.0,0.0f);
        glEnd();
        glPopMatrix();
        // draw the axes
        objRepere->glDraw();

        glPushMatrix();
        /*glTranslatef(-lattice->gridSize[0]/2.0f*lattice->gridScale[0],
          -lattice->gridSize[1]/2.0f*lattice->gridScale[1],0); */
        glDisable(GL_TEXTURE_2D);
        vector <GlBlock*>::iterator ic=tabGlBlocks.begin();
        lock();
        while (ic!=tabGlBlocks.end()) {
            ((SmartBlocksGlBlock*)(*ic))->glDraw(objBlock);
            ic++;
        }
        unlock();

        /*// drawing the mobiles
          Physics::glDraw();
        */
        glPopMatrix();
}

void SmartBlocksWorld::glDrawIdByMaterial() {
    glPushMatrix();
    glDisable(GL_TEXTURE_2D);

    vector <GlBlock*>::iterator ic=tabGlBlocks.begin();
    int n=1;
    lock();
    while (ic!=tabGlBlocks.end()) {
        ((SmartBlocksGlBlock*)(*ic))->glDrawIdByMaterial(objBlockForPicking, n);
        ic++;
    }
    unlock();
    glPopMatrix();
}

void SmartBlocksWorld::glDrawId() {
    glPushMatrix();
    glDisable(GL_TEXTURE_2D);

    vector <GlBlock*>::iterator ic=tabGlBlocks.begin();
    int n=1;
    lock();
    while (ic!=tabGlBlocks.end()) {
        ((SmartBlocksGlBlock*)(*ic))->glDrawId(objBlock,n);
        ic++;
    }
    unlock();
    glPopMatrix();
}

void SmartBlocksWorld::loadTextures(const string &str) {
    if (GlutContext::GUIisEnabled) {
        //string path = str+"/circuit.tga";
        string path = str+"/bois.tga";
        int lx,ly;
        idTextureFloor = GlutWindow::loadTexture(path.c_str(),lx,ly);

        path=str+"/../smartBlocksTextures/digits.tga";
        idTextureDigits = GlutWindow::loadTexture(path.c_str(),lx,ly);
    }
}

void SmartBlocksWorld::setSelectedFace(int n) {
    numSelectedGlBlock = n / 5;
    string name = objBlockForPicking->getObjMtlName(n % 5);

    if (name == "Material__72") numSelectedFace = SLattice::South;
    else if (name == "Material__66") numSelectedFace = SLattice::East;
    else if (name == "Material__71") numSelectedFace = SLattice::West;
    else if (name == "Material__68") numSelectedFace = SLattice::North;
    else {
		numSelectedFace = 4;	// Top
        return;
    }

    // cerr << "SET " << name << " = " << numSelectedFace << " = "
    //      << lattice->getDirectionString(numSelectedFace) << endl;
}

void SmartBlocksWorld::exportConfiguration() {
	SmartBlocksConfigExporter exporter = SmartBlocksConfigExporter(this);
	exporter.exportConfiguration();
}

} // SmartBlocks namespace
<|endoftext|>


<commit_before>// Copyright (c) 2015 The Hivemind Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
extern "C" {
#include "linalg/src/tc_mat.h"
}
#include "resolvevotedialog.h"
#include "resolvevoteinputtablemodel.h"
#include <iostream>

ResolveVoteInputTableModel::ResolveVoteInputTableModel()
    : QAbstractTableModel(0),
    resolveVoteDialog(0),
    voteptr(0)
{

}

ResolveVoteInputTableModel::~ResolveVoteInputTableModel()
{

}

int ResolveVoteInputTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 3 + ((voteptr && *voteptr)? (*voteptr)->nr: 0);
}

int ResolveVoteInputTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 1 + ((voteptr && *voteptr)? (*voteptr)->nc: 0);
}

QVariant ResolveVoteInputTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    if (role == Qt::DisplayRole)
    {
        if (!voteptr || !*voteptr)
            return QVariant();

        uint32_t row = index.row();
        uint32_t col = index.column();
        if ((row < 3+(*voteptr)->nr)
            && (col < 1+(*voteptr)->nc))
        {

            double value = 0.0;

            if (col == 0) { /* Starting Reputations */
                if (row >= 3)
                    value = (*voteptr)->rvecs[TC_VOTE_OLD_REP]->a[row-3][0];
                else
                    return QVariant();
            }
            else
            if (row == 0) /* Binary/Scalar */
                value = (*voteptr)->cvecs[TC_VOTE_IS_BINARY]->a[0][col-1];
            else
            if (row == 1) /* Minimum */
                value = 0.0;
            else
            if (row == 2) /* Maximum */
                value = 1.0;
            else
                value = (*voteptr)->M->a[row-3][col-1];

            if (value != (*voteptr)->NA) {
                char tmp[32];
                snprintf(tmp, sizeof(tmp), "%.8f", value);
                return QVariant(QString(tmp));
            }
            return QVariant(QString("NA"));
        }
    }
    else
    if (role == Qt::TextAlignmentRole)
        return (int)(Qt::AlignRight|Qt::AlignVCenter);

    return QVariant();
}

QVariant ResolveVoteInputTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole)
        {
            char tmp[32];
            if (section == 0)
                snprintf(tmp, sizeof(tmp), "Old Rep");
            else
                snprintf(tmp, sizeof(tmp), "Decision %u", section+1);
            return QVariant(QString(tmp));
        }
        else
        if (role == Qt::TextAlignmentRole)
            return (int)(Qt::AlignLeft|Qt::AlignVCenter);
        else
        if (role == Qt::ToolTipRole)
        {
        }
    }

    if(orientation == Qt::Vertical)
    {
        if (role == Qt::DisplayRole) {
            if (section == 0) return QVariant(tr("Binary/Scalar"));
            if (section == 1) return QVariant(tr("Minumum"));
            if (section == 2) return QVariant(tr("Maximum"));
            char tmp[32];
            snprintf(tmp, sizeof(tmp), "Voter %u", section - 2);
            return QVariant(QString(tmp));
        }
        else
        if (role == Qt::TextAlignmentRole)
            return (int)(Qt::AlignLeft|Qt::AlignVCenter);
        else
        if (role == Qt::ToolTipRole)
        {
        }
    }

    return QVariant();
}

Qt::ItemFlags ResolveVoteInputTableModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::ItemIsEnabled;
    return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}

void ResolveVoteInputTableModel::onDataChange()
{
    uint32_t nr = 3 + ((voteptr && *voteptr)? (*voteptr)->nr: 0);
    uint32_t nc = (voteptr && *voteptr)? (*voteptr)->nc: 0;
    if (nc) {
        QModelIndex topLeft = index(0, 0, QModelIndex());
        QModelIndex bottomRight = index(nr-1, nc-1, QModelIndex());
        emit dataChanged(topLeft, bottomRight);
    }
}

bool ResolveVoteInputTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role != Qt::EditRole)
        return false;

    if (!index.isValid())
        return false;

    const char *str;

    if(value.isNull()) {
        std::cout << "FALSE\n\n";
        return false;
    } else {
        str = value.toString().toStdString().c_str();
    }

    bool isNA = (strstr(str, "NA"))? true: false;
    double dvalue = atof(str);

    int row = index.row();
    int col = index.column();
    if ((row < 3+(int)(*voteptr)->nr)
        && (col < 1 + (int)(*voteptr)->nc))
    {
        if (col == 0) {
           if (row >= 3)
              (*voteptr)->rvecs[TC_VOTE_OLD_REP]->a[row-3][0] = dvalue;
        }
        else
        if (row == 0)
           (*voteptr)->cvecs[TC_VOTE_IS_BINARY]->a[0][col-1] = (dvalue > 0.5)? 1.0: 0.0;
        else
        if (row == 1)
            ;
        else
        if (row == 2)
            ;
        else
           (*voteptr)->M->a[row-3][col-1] = (isNA)? (*voteptr)->NA:  dvalue;

        emit dataChanged(index, index);

        if (resolveVoteDialog)
            resolveVoteDialog->onInputChange();
    }
    return false;
}

<commit_msg>Revert "Fixed invalid read bug. Found while testing my code with valgrind to find my own bug"<commit_after>// Copyright (c) 2015 The Hivemind Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
extern "C" {
#include "linalg/src/tc_mat.h"
}
#include "resolvevotedialog.h"
#include "resolvevoteinputtablemodel.h"

ResolveVoteInputTableModel::ResolveVoteInputTableModel()
    : QAbstractTableModel(0),
    resolveVoteDialog(0),
    voteptr(0)
{

}

ResolveVoteInputTableModel::~ResolveVoteInputTableModel()
{

}

int ResolveVoteInputTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 3 + ((voteptr && *voteptr)? (*voteptr)->nr: 0);
}

int ResolveVoteInputTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 1 + ((voteptr && *voteptr)? (*voteptr)->nc: 0);
}

QVariant ResolveVoteInputTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    if (role == Qt::DisplayRole)
    {
        if (!voteptr || !*voteptr)
            return QVariant();

        uint32_t row = index.row();
        uint32_t col = index.column();
        if ((row < 3+(*voteptr)->nr)
            && (col < 1+(*voteptr)->nc))
        {

            double value = 0.0;

            if (col == 0) { /* Starting Reputations */
                if (row >= 3)
                    value = (*voteptr)->rvecs[TC_VOTE_OLD_REP]->a[row-3][0];
                else
                    return QVariant();
            }
            else
            if (row == 0) /* Binary/Scalar */
                value = (*voteptr)->cvecs[TC_VOTE_IS_BINARY]->a[0][col-1];
            else
            if (row == 1) /* Minimum */
                value = 0.0;
            else
            if (row == 2) /* Maximum */
                value = 1.0;
            else
                value = (*voteptr)->M->a[row-3][col-1];

            if (value != (*voteptr)->NA) {
                char tmp[32];
                snprintf(tmp, sizeof(tmp), "%.8f", value);
                return QVariant(QString(tmp));
            }
            return QVariant(QString("NA"));
        }
    }
    else
    if (role == Qt::TextAlignmentRole)
        return (int)(Qt::AlignRight|Qt::AlignVCenter);

    return QVariant();
}

QVariant ResolveVoteInputTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole)
        {
            char tmp[32];
            if (section == 0)
                snprintf(tmp, sizeof(tmp), "Old Rep");
            else
                snprintf(tmp, sizeof(tmp), "Decision %u", section+1);
            return QVariant(QString(tmp));
        }
        else
        if (role == Qt::TextAlignmentRole)
            return (int)(Qt::AlignLeft|Qt::AlignVCenter);
        else
        if (role == Qt::ToolTipRole)
        {
        }
    }

    if(orientation == Qt::Vertical)
    {
        if (role == Qt::DisplayRole) {
            if (section == 0) return QVariant(tr("Binary/Scalar"));
            if (section == 1) return QVariant(tr("Minumum"));
            if (section == 2) return QVariant(tr("Maximum"));
            char tmp[32];
            snprintf(tmp, sizeof(tmp), "Voter %u", section - 2);
            return QVariant(QString(tmp));
        }
        else
        if (role == Qt::TextAlignmentRole)
            return (int)(Qt::AlignLeft|Qt::AlignVCenter);
        else
        if (role == Qt::ToolTipRole)
        {
        }
    }

    return QVariant();
}

Qt::ItemFlags ResolveVoteInputTableModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::ItemIsEnabled;
    return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}

void ResolveVoteInputTableModel::onDataChange()
{
    uint32_t nr = 3 + ((voteptr && *voteptr)? (*voteptr)->nr: 0);
    uint32_t nc = (voteptr && *voteptr)? (*voteptr)->nc: 0;
    if (nc) {
        QModelIndex topLeft = index(0, 0, QModelIndex());
        QModelIndex bottomRight = index(nr-1, nc-1, QModelIndex());
        emit dataChanged(topLeft, bottomRight);
    }
}

bool ResolveVoteInputTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role != Qt::EditRole)
        return false;

    if (!index.isValid())
        return false;

    const char *str = value.toString().toStdString().c_str();
    if (!str)
        return false;

    bool isNA = (strstr(str, "NA"))? true: false;
    double dvalue = atof(str);

    int row = index.row();
    int col = index.column();
    if ((row < 3+(int)(*voteptr)->nr)
        && (col < 1 + (int)(*voteptr)->nc))
    {
        if (col == 0) {
           if (row >= 3)
              (*voteptr)->rvecs[TC_VOTE_OLD_REP]->a[row-3][0] = dvalue;
        }
        else
        if (row == 0)
           (*voteptr)->cvecs[TC_VOTE_IS_BINARY]->a[0][col-1] = (dvalue > 0.5)? 1.0: 0.0;
        else
        if (row == 1)
            ;
        else
        if (row == 2)
            ;
        else
           (*voteptr)->M->a[row-3][col-1] = (isNA)? (*voteptr)->NA:  dvalue;

        emit dataChanged(index, index);

        if (resolveVoteDialog)
            resolveVoteDialog->onInputChange();
    }
    return false;
}

<|endoftext|>


<commit_before>/*
Copyright 2016 Colin Girling

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.
*/

#ifndef OCL_GUARD_TEST_TDIOTESTLOG_HPP
#define OCL_GUARD_TEST_TDIOTESTLOG_HPP

#include "TestLog.hpp"
#include <iostream>

namespace ocl
{

class StdioTestLog : public TestLog
{
public:
    virtual void Write(TestString const& str)
    {
        std::cout << str.Ptr();
    }

    virtual void WriteEOL()
    {
        std::cout << std::endl;
    }
};

}

#endif // OCL_GUARD_TEST_TDIOTESTLOG_HPP
<commit_msg>Corrected #define guard for StdioTestLog class.<commit_after>/*
Copyright 2016 Colin Girling

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.
*/

#ifndef OCL_GUARD_TEST_STDIOTESTLOG_HPP
#define OCL_GUARD_TEST_STDIOTESTLOG_HPP

#include "TestLog.hpp"
#include <iostream>

namespace ocl
{

class StdioTestLog : public TestLog
{
public:
    virtual void Write(TestString const& str)
    {
        std::cout << str.Ptr();
    }

    virtual void WriteEOL()
    {
        std::cout << std::endl;
    }
};

}

#endif // OCL_GUARD_TEST_STDIOTESTLOG_HPP
<|endoftext|>


<commit_before>#include "Overlap.h"
#include "BaseVecVec.h"
#include "AnyStringGraph.h"
#include "util.h"

DEFINE_USAGE(
"Usage: map-contained-reads ORIG_READS_FILE ORIG_OVERLAPS_FILE\n"
"                           OLD_TO_NEW_INDICES_FILE GRAPH_FILE OUT_GRAPH_FILE\n"
"\n"
"Map contained reads back into a graph.\n"
"\n"
"Input:\n"
"      READS_FILE:     The set of reads from which the overlaps were found.\n"
"      OVERLAPS_FILE:  The set of overlaps, computed from the reads in\n"
"                       READS_FILE.\n"
"      OLD_TO_NEW_INDICES_FILE:   A map from the old read indices to the new\n"
"                                 read indices.\n"
"      GRAPH_FILE:     The graph to map the contained reads into.\n"
"\n"
"Output:\n"
"      OUT_GRAPH_FILE: The output graph into which the contained reads have.\n"
"                      been mapped.\n"
);

int main(int argc, char **argv)
{
	USAGE_IF(argc != 6);
	const char * const orig_reads_file         = argv[1];
	const char * const orig_overlaps_file      = argv[2];
	const char * const old_to_new_indices_file = argv[3];
	const char * const graph_file              = argv[4];
	const char * const out_graph_file          = argv[5];

	info("Loading original reads from \"%s\"", orig_reads_file);
	BaseVecVec orig_reads(orig_reads_file);

	info("Loading original overlaps from \"%s\"", orig_overlaps_file);
	OverlapVecVec orig_overlaps(orig_overlaps_file);

	info("Loading map from old to new read indices from \"%s\"", old_to_new_indices_file);
	std::vector<size_t> old_to_new_indices;
	{
		std::ifstream is(old_to_new_indices_file);
		boost::archive::binary_iarchive ar(is);
		ar >> old_to_new_indices;
	}

	size_t num_orig_reads = orig_reads.size();

	assert(old_to_new_indices.size() == num_orig_reads);
	assert(orig_overlaps.size() == num_orig_reads);

	// Count the number of contained reads.
	size_t num_contained_reads = 0;
	for (size_t i = 0; i < num_orig_reads; i++)
		if (old_to_new_indices[i] == ~size_t(0))
			num_contained_reads++;

	// The number of uncontained reads is the number of original reads minus
	// the number of contained reads.
	size_t num_uncontained_reads = num_orig_reads - num_contained_reads;

	info("%zu of %zu original reads were contained (%.2f%%)",
	     num_contained_reads, num_orig_reads,
	     TO_PERCENT(num_contained_reads, num_orig_reads));

	// Use the old to new indices map to build the reverse map from the new
	// to old read indices.  At the same time, construct a sequential
	// numbering of the contained reads, and build a map from the original
	// read indices to contained read indices and a reverse map from the
	// contained read indices to the original read indices.
	std::vector<size_t> contained_to_old_indices(num_contained_reads, ~size_t(0));
	std::vector<size_t> new_to_old_indices(num_uncontained_reads, ~size_t(0));
	std::vector<size_t> old_to_contained_indices(num_orig_reads, ~size_t(0));
	size_t j = 0;
	for (size_t i = 0; i < orig_reads.size(); i++) {
		if (old_to_new_indices[i] == ~size_t(0)) {
			// The read exists in the original reads but not in the
			// new reads, so it is a contained read.
			old_to_contained_indices[i] = j;
			contained_to_old_indices[j++] = i;
		} else {
			// The read exists in both the original and new reads,
			// so it is not a contained read.  It may have been
			// renumbered.
			assert(old_to_new_indices[i] < num_uncontained_reads);
			assert(new_to_old_indices[old_to_new_indices[i]] == ~size_t(0));
			new_to_old_indices[old_to_new_indices[i]] = i;
		}
	}
	assert(j == num_contained_reads);

	// Find the shortest overhanging overlap for each contained read
	info("Finding the shortest overhanging overlap for each contained read");

	std::vector<const Overlap *>
		shortest_overhang_overlaps(num_contained_reads, NULL);

	std::vector<Overlap::read_pos_t>
		shortest_overhang_lens(num_contained_reads,
				       std::numeric_limits<Overlap::read_pos_t>::max());

	foreach (const OverlapVecVec::OverlapSet & overlap_set, orig_overlaps) {
		foreach(const Overlap & o, overlap_set) {
			Overlap::read_idx_t f_idx;
			Overlap::read_pos_t f_beg;
			Overlap::read_pos_t f_end;
			Overlap::read_idx_t g_idx;
			Overlap::read_pos_t g_beg;
			Overlap::read_pos_t g_end;
			bool rc;

			Overlap::read_idx_t uncontained_read_orig_idx;
			Overlap::read_pos_t uncontained_read_overlap_beg;
			Overlap::read_pos_t uncontained_read_overlap_end;

			assert_overlap_valid(o, orig_reads, 1, 0);

			o.get(f_idx, f_beg, f_end, g_idx, g_beg, g_end, rc);
			const BaseVec & f = orig_reads[f_idx];
			const BaseVec & g = orig_reads[g_idx];
			const BaseVec * uncontained_read;

			assert(f_idx < num_orig_reads);
			assert(g_idx < num_orig_reads);

			size_t contained_read_orig_idx = ~size_t(0);
			if (f_beg == 0 && f_end == f.size() - 1) {
				// Read f is contained
				// ... but only count this overlap if g is NOT
				// contained
				if (old_to_new_indices[g_idx] != ~size_t(0)) {
					contained_read_orig_idx      = f_idx;
					uncontained_read             = &g;
					uncontained_read_orig_idx    = g_idx;
					uncontained_read_overlap_beg = g_beg;
					uncontained_read_overlap_end = g_end;
				}
			} else if (g_beg == 0 && g_end == g.size() - 1) {
				// Read g is contained
				// ... but only count this overlap is f is NOT
				// contained
				if (old_to_new_indices[f_idx] != ~size_t(0)) {
					contained_read_orig_idx      = g_idx;
					uncontained_read             = &f;
					uncontained_read_orig_idx    = f_idx;
					uncontained_read_overlap_beg = f_beg;
					uncontained_read_overlap_end = f_end;
				}
			}

			if (contained_read_orig_idx != ~size_t(0)) {
				assert(old_to_new_indices[contained_read_orig_idx] ==
				       ~size_t(0));
				assert(old_to_contained_indices[contained_read_orig_idx] !=
				       ~size_t(0));
				// This is a containing overlap, and the read
				// with original index @contained_read_orig_idx
				// is contained.  Compute the overhang length.
				Overlap::read_pos_t overhang_len;
				if (rc) {
					//
					//
					//      ---------->
					//  <------------------------
					//
					//                 |overhang|
					overhang_len = uncontained_read_overlap_beg;
				} else {
					//
					//
					//      ---------->
					//  ------------------------>
					//
					//                 |overhang|
					assert(uncontained_read->length() >=
					       uncontained_read_overlap_end + 1);
					overhang_len = uncontained_read->length() -
						       (uncontained_read_overlap_end + 1);
				}

				// Index of this contained read in the
				// sequential numbering of the contained reads
				size_t contained_idx =
					old_to_contained_indices[contained_read_orig_idx];

				// Update the shortest overhang if this overhang
				// is shorter than the previous shortest one.
				if (overhang_len < shortest_overhang_lens[contained_idx]) {
					shortest_overhang_overlaps[contained_idx] = &o;
					shortest_overhang_lens[contained_idx] = overhang_len;
				}
			}
		}
	}

	info("Reading string graph from \"%s\"", graph_file);
	AnyStringGraph graph(graph_file);

	info("Mapping %zu contained reads into the string graph", num_contained_reads);

	// Map the contained reads into the graph, given the overlap to use to
	// map each contained read.
	for (size_t i = 0; i < num_contained_reads; i++) {

		// Original index of this contained read
		size_t contained_read_orig_idx = contained_to_old_indices[i];

		// The overlap in which the overhang from the end of this
		// contained read to its containing read is the shortest
		const Overlap *o = shortest_overhang_overlaps[i];

		// Original read index must be valid, the read must be
		// contained, and it must have at least 1 overlap with an
		// uncontained read.
		assert(contained_read_orig_idx < num_orig_reads);
		assert(old_to_new_indices[contained_read_orig_idx] == ~size_t(0));
		assert(o != NULL);

		Overlap::read_idx_t f_idx, g_idx;
		Overlap::read_idx_t uncontained_read_dir;
		Overlap::read_idx_t uncontained_read_new_idx;

		o->get_indices(f_idx, g_idx);

		if (f_idx == contained_read_orig_idx) {
			uncontained_read_new_idx = old_to_new_indices[g_idx];
		} else {
			assert(g_idx == contained_read_orig_idx);
			uncontained_read_new_idx = old_to_new_indices[f_idx];
		}

		assert(uncontained_read_new_idx < num_uncontained_reads);

		uncontained_read_dir = (o->is_rc() ? 1 : 0);

		graph.map_contained_read(uncontained_read_new_idx,
					 uncontained_read_dir,
					 shortest_overhang_lens[i]);
	}

	info("Writing string graph to \"%s\"", out_graph_file);
	graph.write(out_graph_file);
	return 0;
}
<commit_msg>Map underhangs as well as overhangs<commit_after>#include "Overlap.h"
#include "BaseVecVec.h"
#include "AnyStringGraph.h"
#include "util.h"

DEFINE_USAGE(
"Usage: map-contained-reads ORIG_READS_FILE ORIG_OVERLAPS_FILE\n"
"                           OLD_TO_NEW_INDICES_FILE GRAPH_FILE OUT_GRAPH_FILE\n"
"\n"
"Map contained reads back into a graph.\n"
"\n"
"Input:\n"
"      READS_FILE:     The set of reads from which the overlaps were found.\n"
"      OVERLAPS_FILE:  The set of overlaps, computed from the reads in\n"
"                       READS_FILE.\n"
"      OLD_TO_NEW_INDICES_FILE:   A map from the old read indices to the new\n"
"                                 read indices.\n"
"      GRAPH_FILE:     The graph to map the contained reads into.\n"
"\n"
"Output:\n"
"      OUT_GRAPH_FILE: The output graph into which the contained reads have.\n"
"                      been mapped.\n"
);

int main(int argc, char **argv)
{
	USAGE_IF(argc != 6);
	const char * const orig_reads_file         = argv[1];
	const char * const orig_overlaps_file      = argv[2];
	const char * const old_to_new_indices_file = argv[3];
	const char * const graph_file              = argv[4];
	const char * const out_graph_file          = argv[5];

	info("Loading original reads from \"%s\"", orig_reads_file);
	BaseVecVec orig_reads(orig_reads_file);

	info("Loading original overlaps from \"%s\"", orig_overlaps_file);
	OverlapVecVec orig_overlaps(orig_overlaps_file);

	info("Loading map from old to new read indices from \"%s\"", old_to_new_indices_file);
	std::vector<size_t> old_to_new_indices;
	{
		std::ifstream is(old_to_new_indices_file);
		boost::archive::binary_iarchive ar(is);
		ar >> old_to_new_indices;
	}

	size_t num_orig_reads = orig_reads.size();

	assert(old_to_new_indices.size() == num_orig_reads);
	assert(orig_overlaps.size() == num_orig_reads);

	// Count the number of contained reads.
	size_t num_contained_reads = 0;
	for (size_t i = 0; i < num_orig_reads; i++)
		if (old_to_new_indices[i] == ~size_t(0))
			num_contained_reads++;

	// The number of uncontained reads is the number of original reads minus
	// the number of contained reads.
	size_t num_uncontained_reads = num_orig_reads - num_contained_reads;

	info("%zu of %zu original reads were contained (%.2f%%)",
	     num_contained_reads, num_orig_reads,
	     TO_PERCENT(num_contained_reads, num_orig_reads));

	// Use the old to new indices map to build the reverse map from the new
	// to old read indices.  At the same time, construct a sequential
	// numbering of the contained reads, and build a map from the original
	// read indices to contained read indices and a reverse map from the
	// contained read indices to the original read indices.
	std::vector<size_t> contained_to_old_indices(num_contained_reads, ~size_t(0));
	std::vector<size_t> new_to_old_indices(num_uncontained_reads, ~size_t(0));
	std::vector<size_t> old_to_contained_indices(num_orig_reads, ~size_t(0));
	size_t j = 0;
	for (size_t i = 0; i < orig_reads.size(); i++) {
		if (old_to_new_indices[i] == ~size_t(0)) {
			// The read exists in the original reads but not in the
			// new reads, so it is a contained read.
			old_to_contained_indices[i] = j;
			contained_to_old_indices[j++] = i;
		} else {
			// The read exists in both the original and new reads,
			// so it is not a contained read.  It may have been
			// renumbered.
			assert(old_to_new_indices[i] < num_uncontained_reads);
			assert(new_to_old_indices[old_to_new_indices[i]] == ~size_t(0));
			new_to_old_indices[old_to_new_indices[i]] = i;
		}
	}
	assert(j == num_contained_reads);

	// Find the shortest overhanging overlap for each contained read
	info("Finding the shortest overhanging overlap for each contained read");

	std::vector<const Overlap *>
		shortest_overhang_overlaps(num_contained_reads, NULL);

	std::vector<const Overlap *>
		shortest_underhang_overlaps(num_contained_reads, NULL);

	std::vector<Overlap::read_pos_t>
		shortest_overhang_lens(num_contained_reads,
				       std::numeric_limits<Overlap::read_pos_t>::max());

	std::vector<Overlap::read_pos_t>
		shortest_underhang_lens(num_contained_reads,
					std::numeric_limits<Overlap::read_pos_t>::max());

	foreach (const OverlapVecVec::OverlapSet & overlap_set, orig_overlaps) {
		foreach(const Overlap & o, overlap_set) {
			Overlap::read_idx_t f_idx;
			Overlap::read_pos_t f_beg;
			Overlap::read_pos_t f_end;
			Overlap::read_idx_t g_idx;
			Overlap::read_pos_t g_beg;
			Overlap::read_pos_t g_end;
			bool rc;

			Overlap::read_idx_t uncontained_read_orig_idx;
			Overlap::read_pos_t uncontained_read_overlap_beg;
			Overlap::read_pos_t uncontained_read_overlap_end;

			assert_overlap_valid(o, orig_reads, 1, 0);

			o.get(f_idx, f_beg, f_end, g_idx, g_beg, g_end, rc);
			const BaseVec & f = orig_reads[f_idx];
			const BaseVec & g = orig_reads[g_idx];
			const BaseVec * uncontained_read;

			assert(f_idx < num_orig_reads);
			assert(g_idx < num_orig_reads);

			size_t contained_read_orig_idx = ~size_t(0);
			if (f_beg == 0 && f_end == f.size() - 1) {
				// Read f is contained
				// ... but only count this overlap if g is NOT
				// contained
				if (old_to_new_indices[g_idx] != ~size_t(0)) {
					contained_read_orig_idx      = f_idx;
					uncontained_read             = &g;
					uncontained_read_orig_idx    = g_idx;
					uncontained_read_overlap_beg = g_beg;
					uncontained_read_overlap_end = g_end;
				}
			} else if (g_beg == 0 && g_end == g.size() - 1) {
				// Read g is contained
				// ... but only count this overlap is f is NOT
				// contained
				if (old_to_new_indices[f_idx] != ~size_t(0)) {
					contained_read_orig_idx      = g_idx;
					uncontained_read             = &f;
					uncontained_read_orig_idx    = f_idx;
					uncontained_read_overlap_beg = f_beg;
					uncontained_read_overlap_end = f_end;
				}
			}

			if (contained_read_orig_idx != ~size_t(0)) {
				assert(old_to_new_indices[contained_read_orig_idx] ==
				       ~size_t(0));
				assert(old_to_contained_indices[contained_read_orig_idx] !=
				       ~size_t(0));
				// This is a containing overlap, and the read
				// with original index @contained_read_orig_idx
				// is contained.  Compute the overhang length.
				Overlap::read_pos_t overhang_len;
				Overlap::read_pos_t underhang_len;
				if (rc) {
					//
					//
					//      ---------->
					//  <------------------------
					//
					//                 |overhang|
					overhang_len = uncontained_read_overlap_beg;
					underhang_len = uncontained_read->length() -
							(uncontained_read_overlap_end + 1);
				} else {
					//
					//
					//      ---------->
					//  ------------------------>
					//
					//                 |overhang|
					assert(uncontained_read->length() >=
					       uncontained_read_overlap_end + 1);
					overhang_len = uncontained_read->length() -
						       (uncontained_read_overlap_end + 1);
					underhang_len = uncontained_read_overlap_beg;
				}

				// Index of this contained read in the
				// sequential numbering of the contained reads
				size_t contained_idx =
					old_to_contained_indices[contained_read_orig_idx];

				// Update the shortest overhang if this overhang
				// is shorter than the previous shortest one.
				if (overhang_len < shortest_overhang_lens[contained_idx]) {
					shortest_overhang_overlaps[contained_idx] = &o;
					shortest_overhang_lens[contained_idx] = overhang_len;
				}

				if (underhang_len < shortest_underhang_lens[contained_idx]) {
					shortest_underhang_overlaps[contained_idx] = &o;
					shortest_underhang_lens[contained_idx] = underhang_len;
				}
			}
		}
	}

	info("Reading string graph from \"%s\"", graph_file);
	AnyStringGraph graph(graph_file);

	info("Mapping %zu contained reads into the string graph", num_contained_reads);

	// Map the contained reads into the graph, given the overlap to use to
	// map each contained read.
	for (size_t i = 0; i < num_contained_reads; i++) {

		// Original index of this contained read
		size_t contained_read_orig_idx;

		// The overlap in which the overhang from the end of this
		// contained read to its containing read is the shortest
		const Overlap *o;

		Overlap::read_idx_t f_idx, g_idx;
		Overlap::read_idx_t uncontained_read_dir;
		Overlap::read_idx_t uncontained_read_new_idx;

		// Map the overhang
		contained_read_orig_idx = contained_to_old_indices[i];
		o = shortest_overhang_overlaps[i];
		// Original read index must be valid, the read must be
		// contained, and it must have at least 1 overlap with an
		// uncontained read.
		assert(contained_read_orig_idx < num_orig_reads);
		assert(old_to_new_indices[contained_read_orig_idx] == ~size_t(0));
		assert(o != NULL);
		o->get_indices(f_idx, g_idx);
		if (f_idx == contained_read_orig_idx) {
			uncontained_read_new_idx = old_to_new_indices[g_idx];
		} else {
			assert(g_idx == contained_read_orig_idx);
			uncontained_read_new_idx = old_to_new_indices[f_idx];
		}
		assert(uncontained_read_new_idx < num_uncontained_reads);
		uncontained_read_dir = (o->is_rc() ? 1 : 0);
		graph.map_contained_read(uncontained_read_new_idx,
					 uncontained_read_dir,
					 shortest_overhang_lens[i]);

		// Map the underhang
		o = shortest_underhang_overlaps[i];
		assert(o != NULL);
		o->get_indices(f_idx, g_idx);
		if (f_idx == contained_read_orig_idx) {
			uncontained_read_new_idx = old_to_new_indices[g_idx];
		} else {
			assert(g_idx == contained_read_orig_idx);
			uncontained_read_new_idx = old_to_new_indices[f_idx];
		}
		assert(uncontained_read_new_idx < num_uncontained_reads);
		uncontained_read_dir = (o->is_rc() ? 0 : 1);
		graph.map_contained_read(uncontained_read_new_idx,
					 uncontained_read_dir,
					 shortest_overhang_lens[i]);
	}

	info("Writing string graph to \"%s\"", out_graph_file);
	graph.write(out_graph_file);
	return 0;
}
<|endoftext|>


<commit_before>#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/session.hpp"

#include <boost/utility.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/thread/mutex.hpp>

#include "test.hpp"

using namespace libtorrent;
using namespace boost::filesystem;

int test_main()
{
	const int piece_size = 16;
	const int half = piece_size / 2;
	torrent_info info;
	info.set_piece_size(piece_size);
	info.add_file("temp_storage/test1.tmp", 17);
	info.add_file("temp_storage/test2.tmp", 612);
	info.add_file("temp_storage/test3.tmp", 0);
	info.add_file("temp_storage/test4.tmp", 0);
	info.add_file("temp_storage/test5.tmp", 1);

	char piece0[piece_size] =
	{ 6, 6, 6, 6, 6, 6, 6, 6
	, 9, 9, 9, 9, 9, 9, 9, 9};

	char piece1[piece_size] =
	{ 0, 0, 0, 0, 0, 0, 0, 0
	, 1, 1, 1, 1, 1, 1, 1, 1};

	char piece2[piece_size] =
	{ 0, 0, 1, 0, 0, 0, 0, 0
	, 1, 1, 1, 1, 1, 1, 1, 1};

	info.set_hash(0, hasher(piece0, piece_size).final());
	info.set_hash(1, hasher(piece1, piece_size).final());
	info.set_hash(2, hasher(piece2, piece_size).final());

	info.create_torrent();

	create_directory(initial_path() / "temp_storage");

	int num_pieces = (1 + 612 + 17 + piece_size - 1) / piece_size;
	TEST_CHECK(info.num_pieces() == num_pieces);

	char piece[piece_size];

	{ // avoid having two storages use the same files
	storage s(info, initial_path());

	// write piece 1 (in slot 0)
	s.write(piece1, 0, 0, half);
	s.write(piece1 + half, 0, half, half);

	// verify piece 1
	s.read(piece, 0, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece1));

	// do the same with piece 0 and 2 (in slot 1 and 2)
	s.write(piece0, 1, 0, piece_size);
	s.write(piece2, 2, 0, piece_size);

	// verify piece 0 and 2
	s.read(piece, 1, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece0));

	s.read(piece, 2, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece2));

	// make sure the files have the correct size
	TEST_CHECK(file_size(initial_path() / "temp_storage" / "test1.tmp") == 17);
	TEST_CHECK(file_size(initial_path() / "temp_storage" / "test2.tmp") == 31);
	s.release_files();
	}

	// make sure the piece_manager can identify the pieces
	piece_manager pm(info, initial_path());
	boost::mutex lock;
	libtorrent::detail::piece_checker_data d;

	std::vector<bool> pieces;
	num_pieces = 0;
	TEST_CHECK(pm.check_fastresume(d, pieces, num_pieces, true) == false);
	bool finished = false;
	float progress;
	num_pieces = 0;
	while (!finished)
		boost::tie(finished, progress) = pm.check_files(pieces, num_pieces);

	TEST_CHECK(num_pieces == std::count(pieces.begin(), pieces.end()
		, true));

	pm.read(piece, 0, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece0));

	pm.read(piece, 1, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece1));

	pm.read(piece, 2, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece2));
	pm.release_files();

	remove_all(initial_path() / "temp_storage");

	return 0;
}

<commit_msg>updated storage test<commit_after>#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/session.hpp"

#include <boost/utility.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/thread/mutex.hpp>

#include "test.hpp"

using namespace libtorrent;
using namespace boost::filesystem;

int test_main()
{
	const int piece_size = 16;
	const int half = piece_size / 2;
	torrent_info info;
	info.set_piece_size(piece_size);
	info.add_file("temp_storage/test1.tmp", 17);
	info.add_file("temp_storage/test2.tmp", 612);
	info.add_file("temp_storage/test3.tmp", 0);
	info.add_file("temp_storage/test4.tmp", 0);
	info.add_file("temp_storage/test5.tmp", 1);

	char piece0[piece_size] =
	{ 6, 6, 6, 6, 6, 6, 6, 6
	, 9, 9, 9, 9, 9, 9, 9, 9};

	char piece1[piece_size] =
	{ 0, 0, 0, 0, 0, 0, 0, 0
	, 1, 1, 1, 1, 1, 1, 1, 1};

	char piece2[piece_size] =
	{ 0, 0, 1, 0, 0, 0, 0, 0
	, 1, 1, 1, 1, 1, 1, 1, 1};

	info.set_hash(0, hasher(piece0, piece_size).final());
	info.set_hash(1, hasher(piece1, piece_size).final());
	info.set_hash(2, hasher(piece2, piece_size).final());

	info.create_torrent();

	create_directory(initial_path() / "temp_storage");

	int num_pieces = (1 + 612 + 17 + piece_size - 1) / piece_size;
	TEST_CHECK(info.num_pieces() == num_pieces);

	char piece[piece_size];

	{ // avoid having two storages use the same files
	storage s(info, initial_path());

	// write piece 1 (in slot 0)
	s.write(piece1, 0, 0, half);
	s.write(piece1 + half, 0, half, half);

	// verify piece 1
	s.read(piece, 0, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece1));

	// do the same with piece 0 and 2 (in slot 1 and 2)
	s.write(piece0, 1, 0, piece_size);
	s.write(piece2, 2, 0, piece_size);

	// verify piece 0 and 2
	s.read(piece, 1, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece0));

	s.read(piece, 2, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece2));

	// make sure the files have the correct size
	TEST_CHECK(file_size(initial_path() / "temp_storage" / "test1.tmp") == 17);
	TEST_CHECK(file_size(initial_path() / "temp_storage" / "test2.tmp") == 31);
	s.release_files();
	}

	// make sure the piece_manager can identify the pieces
	piece_manager pm(info, initial_path());
	boost::mutex lock;
	libtorrent::detail::piece_checker_data d;

	std::vector<bool> pieces;
	num_pieces = 0;
	TEST_CHECK(pm.check_fastresume(d, pieces, num_pieces, true) == false);
	bool finished = false;
	float progress;
	num_pieces = 0;
	while (!finished)
		boost::tie(finished, progress) = pm.check_files(pieces, num_pieces);

	TEST_CHECK(num_pieces == std::count(pieces.begin(), pieces.end()
		, true));

	pm.read(piece, 0, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece0));

	pm.read(piece, 1, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece1));

	pm.read(piece, 2, 0, piece_size);
	TEST_CHECK(std::equal(piece, piece + piece_size, piece2));
	pm.release_files();

	TEST_CHECK(exists("temp_storage/test3.tmp"));
	TEST_CHECK(exists("temp_storage/test4.tmp"));

	remove_all(initial_path() / "temp_storage");

	return 0;
}

<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
#include <random>
#include "../includes/sdr.hpp"

std::chrono::system_clock::duration since_epoch()
{
    return std::chrono::system_clock::now().time_since_epoch();
}

int main()
{
    constexpr std::size_t Amount = 100000;
    constexpr std::size_t Width = 2048;
    constexpr std::size_t ParallelAmount = 100;
    constexpr float OnPercent = 0.02;

    sdr::bank<Width> memory;
    std::vector<std::bitset<Width>> fields;

    std::array<double, Width> weights;
    weights.fill(1.1);

    std::cout << "bench" << std::endl;
    std::cout << "\tamount: " << Amount << std::endl;
    std::cout << "\twidth: " << Width << std::endl;
    std::cout << "\tpercent: " << OnPercent << std::endl;
    std::cout << std::endl;

    {
        auto start = since_epoch();

        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> wdis(0, Width-1);

        const std::size_t amount_set = static_cast<std::size_t>(Width * OnPercent);

        for(std::size_t i=0; i<Amount; ++i) {
            std::bitset<Width> data;

            for(std::size_t j=0; j<amount_set; ++j) {
                data.set(wdis(gen));
            }

            fields.push_back(data);
        }

        auto end = since_epoch();

        std::cout << "generation took: " <<  std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;
    }

    {
        auto start = since_epoch();

        for(auto & field : fields) {
            memory.insert(sdr::concept(field));
        }

        auto end = since_epoch();

        std::cout << "insertion took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;
    }

    {
        auto start = since_epoch();

        memory.save_to_file("test.sdr");

        auto end = since_epoch();

        std::cout << "save to file took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;
    }

    memory.clear();

    {
        auto start = since_epoch();

        const std::size_t storage_size { memory.load_from_file("test.sdr") };

        auto end = since_epoch();

        std::cout << "load from file (" << storage_size << " concepts) took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;
    }

    {
        auto start = since_epoch();

        std::vector<std::future<std::vector<std::pair<sdr::position_t, std::size_t>>>> futures;

        for(sdr::position_t i=0; i < ParallelAmount; ++i) {
            futures.push_back(memory.async_closest(i, 10));
        }

        std::vector<std::vector<std::pair<sdr::position_t, std::size_t>>> closests;
        for(sdr::position_t i=0; i < ParallelAmount; ++i) {
            closests.push_back(futures[i].get());
        }

        auto end = since_epoch();

        std::cout << "finding closest (parallel => " << ParallelAmount << ") took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;

        std::size_t counter = 0;
        for(auto & closest : closests) {
            std::cout << "\t#" << counter << std::endl;

            for(auto & it : closest) {
                std::cout << "\t\t" << it.first << "\t:: " << it.second << std::endl;
            }

            std::cout << std::endl;
            ++counter;
        }
    }

    {
        auto start = since_epoch();

        std::array<double, Width> weights;
        std::fill(weights.begin(), weights.end(), 1.1);
        auto closest = memory.weighted_closest(1, 10, weights);

        auto end = since_epoch();

        std::cout << "finding weighted closest took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;

        std::cout << "closest: " << std::endl;
        for(auto & it : closest) {
            std::cout << "\t" << it.first << "\t:: " << it.second << std::endl;
        }
    }

    {
        std::vector<std::size_t> simlist(10);
        std::iota(simlist.begin(), simlist.end(), 1);

        auto start = since_epoch();

        auto similarity = memory.union_similarity(0, simlist);

        auto end = since_epoch();

        std::cout << "finding union similarity took: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count() << "ns" << std::endl;

        std::cout << "similarity: " << similarity << std::endl;
    }

    {
        auto start = since_epoch();

        auto matching = memory.matching(sdr::concept({ 0, 10 }));

        auto end = since_epoch();

        std::cout << "finding matching took: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count() << "ns" << std::endl;
        std::cout << "matching.size() => " << matching.size() << std::endl;

        std::cout << "matching: " << std::endl;
        for(auto & it : matching) {
            std::cout << it << std::endl;
        }
    }

    return 0;
}
<commit_msg>fix bench for large dimensions<commit_after>#include <chrono>
#include <iostream>
#include <random>
#include "../includes/sdr.hpp"

std::chrono::system_clock::duration since_epoch()
{
    return std::chrono::system_clock::now().time_since_epoch();
}

int main()
{
    constexpr std::size_t Amount = 100000;
    constexpr sdr::width_t Width = 2048;
    constexpr std::size_t ParallelAmount = 100;
    constexpr double OnPercent = 0.02;

    sdr::bank<Width> memory;
    std::vector<std::vector<sdr::position_t>> fields;

    std::vector<double> weights(Width, 1.1);

    std::cout << "bench" << std::endl;
    std::cout << "\tamount: " << Amount << std::endl;
    std::cout << "\twidth: " << Width << std::endl;
    std::cout << "\tpercent: " << OnPercent << std::endl;
    std::cout << std::endl;

    {
        auto start = since_epoch();

        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> wdis(0, Width-1);

        const std::size_t amount_set = static_cast<std::size_t>(Width * OnPercent);

        for(std::size_t i=0; i<Amount; ++i) {
            std::vector<sdr::position_t> data;

            for(std::size_t j=0; j<amount_set; ++j) {
                data.push_back(wdis(gen));
            }

            fields.push_back(data);
        }

        auto end = since_epoch();

        std::cout << "generation took: " <<  std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;
    }

    {
        auto start = since_epoch();

        for(auto & field : fields) {
            memory.insert(sdr::concept(field));
        }

        auto end = since_epoch();

        std::cout << "insertion took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;
    }

    {
        auto start = since_epoch();

        memory.save_to_file("test.sdr");

        auto end = since_epoch();

        std::cout << "save to file took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;
    }

    memory.clear();

    {
        auto start = since_epoch();

        const std::size_t storage_size { memory.load_from_file("test.sdr") };

        auto end = since_epoch();

        std::cout << "load from file (" << storage_size << " concepts) took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;
    }

    {
        auto start = since_epoch();

        std::vector<std::future<std::vector<std::pair<sdr::position_t, std::size_t>>>> futures;

        for(sdr::position_t i=0; i < ParallelAmount; ++i) {
            futures.push_back(memory.async_closest(i, 2));
        }

        std::vector<std::vector<std::pair<sdr::position_t, std::size_t>>> closests;
        for(sdr::position_t i=0; i < ParallelAmount; ++i) {
            closests.push_back(futures[i].get());
        }

        auto end = since_epoch();

        std::cout << "finding closest (parallel => " << ParallelAmount << ") took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;

        std::size_t counter = 0;
        for(auto & closest : closests) {
            std::cout << "\t#" << counter << std::endl;

            for(auto & it : closest) {
                std::cout << "\t\t" << it.first << "\t:: " << it.second << std::endl;
            }

            std::cout << std::endl;
            ++counter;
        }
    }

    {
        auto start = since_epoch();

        auto closest = memory.weighted_closest(1, 10, weights);

        auto end = since_epoch();

        std::cout << "finding weighted closest took: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << "ms" << std::endl;

        std::cout << "closest: " << std::endl;
        for(auto & it : closest) {
            std::cout << "\t" << it.first << "\t:: " << it.second << std::endl;
        }
    }

    {
        std::vector<std::size_t> simlist(10);
        std::iota(simlist.begin(), simlist.end(), 1);

        auto start = since_epoch();

        auto similarity = memory.union_similarity(0, simlist);

        auto end = since_epoch();

        std::cout << "finding union similarity took: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count() << "ns" << std::endl;

        std::cout << "similarity: " << similarity << std::endl;
    }

    {
        auto start = since_epoch();

        auto matching = memory.matching(sdr::concept({ 0, 10 }));

        auto end = since_epoch();

        std::cout << "finding matching took: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count() << "ns" << std::endl;
        std::cout << "matching.size() => " << matching.size() << std::endl;

        std::cout << "matching: " << std::endl;
        for(auto & it : matching) {
            std::cout << it << std::endl;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h

#include "IrrCompileConfig.h"

#ifdef _IRR_COMPILE_WITH_STL_LOADER_

#include "CSTLMeshFileLoader.h"
#include "SMesh.h"

#include "IReadFile.h"
#include "coreutil.h"
#include "os.h"
#include "SVertexManipulator.h"

#include <vector>

namespace irr
{
namespace scene
{

asset::IAsset* CSTLMeshFileLoader::loadAsset(io::IReadFile* _file, const asset::IAssetLoader::SAssetLoadParams& _params, asset::IAssetLoader::IAssetLoaderOverride* _override, uint32_t _hierarchyLevel)
{
	const long filesize = _file->getSize();
	if (filesize < 6) // we need a header
		return nullptr;

    bool hasColor = false;

	SCPUMesh* mesh = new SCPUMesh();
	ICPUMeshDataFormatDesc* desc = new ICPUMeshDataFormatDesc();
    {
	ICPUMeshBuffer* meshbuffer = new ICPUMeshBuffer();
	meshbuffer->setMeshDataAndFormat(desc);
	desc->drop();

	mesh->addMeshBuffer(meshbuffer);
	meshbuffer->drop();
    }

	bool binary = false;
	core::stringc token;
	if (getNextToken(_file, token) != "solid")
		binary = hasColor = true;

    core::vector<core::vectorSIMDf> positions, normals;
    core::vector<uint32_t> colors;
	if (binary)
	{
        if (_file->getSize() < 80)
        {
            mesh->drop();
            return nullptr;
        }
		_file->seek(80); // skip header
        uint32_t vtxCnt = 0u;
		_file->read(&vtxCnt, 4);
        positions.reserve(3*vtxCnt);
        normals.reserve(vtxCnt);
        colors.reserve(vtxCnt);
	}
	else
		goNextLine(_file); // skip header

	uint16_t attrib=0u;
	token.reserve(32);
	while (_file->getPos() < filesize)
	{
		if (!binary)
		{
			if (getNextToken(_file, token) != "facet")
			{
				if (token=="endsolid")
					break;
				mesh->drop();
				return nullptr;
			}
			if (getNextToken(_file, token) != "normal")
			{
				mesh->drop();
				return nullptr;
			}
		}

        {
        core::vectorSIMDf n;
		getNextVector(_file, n, binary);
        normals.push_back(n);
        }

		if (!binary)
		{
			if (getNextToken(_file, token) != "outer")
			{
				mesh->drop();
				return nullptr;
			}
			if (getNextToken(_file, token) != "loop")
			{
				mesh->drop();
				return nullptr;
			}
		}

        {
        core::vectorSIMDf p[3];
		for (uint32_t i = 0u; i < 3u; ++i)
		{
			if (!binary)
			{
				if (getNextToken(_file, token) != "vertex")
				{
					mesh->drop();
					return nullptr;
				}
			}
			getNextVector(_file, p[i], binary);
		}
        for (uint32_t i = 0u; i < 3u; ++i) // seems like in STL format vertices are ordered in clockwise manner...
            positions.push_back(p[2u-i]);
        }

		if (!binary)
		{
			if (getNextToken(_file, token) != "endloop")
			{
				mesh->drop();
				return nullptr;
			}
			if (getNextToken(_file, token) != "endfacet")
			{
				mesh->drop();
				return nullptr;
			}
		}
		else
		{
			_file->read(&attrib, 2);
		}

        if (hasColor && (attrib & 0x8000)) // assuming VisCam/SolidView non-standard trick to store color in 2 bytes of extra attribute
        {
            colors.push_back(video::A1R5G5B5toA8R8G8B8(attrib));
        }
        else
        {
            hasColor = false;
            colors.clear();
        }

		if ((normals.back() == core::vectorSIMDf()).all())
        {
			normals.back().set(
                core::plane3df(
                    (positions.rbegin()+2)->getAsVector3df(),
                    (positions.rbegin()+1)->getAsVector3df(),
                    (positions.rbegin()+0)->getAsVector3df()).Normal
            );
        }
	} // end while (_file->getPos() < filesize)

    const size_t vtxSize = hasColor ? (3 * sizeof(float) + 4 + 4) : (3 * sizeof(float) + 4);
	core::ICPUBuffer* vertexBuf = new core::ICPUBuffer(vtxSize*positions.size());

    uint32_t normal{};
    for (size_t i = 0u; i < positions.size(); ++i)
    {
        if (i%3 == 0)
            normal = quantizeNormal2_10_10_10(normals[i/3]);
        uint8_t* ptr = ((uint8_t*)(vertexBuf->getPointer())) + i*vtxSize;
        memcpy(ptr, positions[i].pointer, 3*4);
        ((uint32_t*)(ptr+12))[0] = normal;
        if (hasColor)
            memcpy(ptr+16, colors.data()+i/3, 4);
    }

	desc->mapVertexAttrBuffer(vertexBuf, EVAI_ATTR0, ECPA_THREE, ECT_FLOAT, vtxSize, 0);
	desc->mapVertexAttrBuffer(vertexBuf, EVAI_ATTR3, ECPA_FOUR, ECT_INT_2_10_10_10_REV, vtxSize, 12);
    if (hasColor)
	    desc->mapVertexAttrBuffer(vertexBuf, EVAI_ATTR1, ECPA_REVERSED_OR_BGRA, ECT_NORMALIZED_UNSIGNED_BYTE, vtxSize, 16);
	vertexBuf->drop();

	mesh->getMeshBuffer(0)->setIndexCount(positions.size());
    //mesh->getMeshBuffer(0)->setPrimitiveType(EPT_POINTS);
	mesh->recalculateBoundingBox(true);

	return mesh;
}

bool CSTLMeshFileLoader::isALoadableFileFormat(io::IReadFile * _file) const
{
    if (_file->getSize() <= 6u)
        return false;

    char header[6];
    const size_t prevPos = _file->getPos();
    _file->seek(0u);
    _file->read(header, 6u);
    _file->seek(prevPos);

    if (strncmp(header, "solid ", 6u) == 0)
        return true;
    else
        return _file->getSize() > 80u; // some other validation also needed here...
}

//! Read 3d vector of floats
void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vectorSIMDf& vec, bool binary) const
{
	if (binary)
	{
		file->read(&vec.X, 4);
		file->read(&vec.Y, 4);
		file->read(&vec.Z, 4);
	}
	else
	{
		goNextWord(file);
		core::stringc tmp;

		getNextToken(file, tmp);
		sscanf(tmp.c_str(),"%f",&vec.X);
		getNextToken(file, tmp);
		sscanf(tmp.c_str(),"%f",&vec.Y);
		getNextToken(file, tmp);
		sscanf(tmp.c_str(),"%f",&vec.Z);
	}
	vec.X=-vec.X;
}

//! Read next word
const core::stringc& CSTLMeshFileLoader::getNextToken(io::IReadFile* file, core::stringc& token) const
{
	goNextWord(file);
	uint8_t c;
	token = "";
	while(file->getPos() != file->getSize())
	{
		file->read(&c, 1);
		// found it, so leave
		if (core::isspace(c))
			break;
		token.append(c);
	}
	return token;
}

//! skip to next word
void CSTLMeshFileLoader::goNextWord(io::IReadFile* file) const
{
	uint8_t c;
	while(file->getPos() != file->getSize())
	{
		file->read(&c, 1);
		// found it, so leave
		if (!core::isspace(c))
		{
			file->seek(-1, true);
			break;
		}
	}
}

//! Read until line break is reached and stop at the next non-space character
void CSTLMeshFileLoader::goNextLine(io::IReadFile* file) const
{
	uint8_t c;
	// look for newline characters
	while(file->getPos() != file->getSize())
	{
		file->read(&c, 1);
		// found it, so leave
		if (c=='\n' || c=='\r')
			break;
	}
}

} // end namespace scene
} // end namespace irr

#endif // _IRR_COMPILE_WITH_STL_LOADER_
<commit_msg>asset-pipeline: STL better validation<commit_after>// Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h

#include "IrrCompileConfig.h"

#ifdef _IRR_COMPILE_WITH_STL_LOADER_

#include "CSTLMeshFileLoader.h"
#include "SMesh.h"

#include "IReadFile.h"
#include "coreutil.h"
#include "os.h"
#include "SVertexManipulator.h"

#include <vector>

namespace irr
{
namespace scene
{

asset::IAsset* CSTLMeshFileLoader::loadAsset(io::IReadFile* _file, const asset::IAssetLoader::SAssetLoadParams& _params, asset::IAssetLoader::IAssetLoaderOverride* _override, uint32_t _hierarchyLevel)
{
	const long filesize = _file->getSize();
	if (filesize < 6) // we need a header
		return nullptr;

    bool hasColor = false;

	SCPUMesh* mesh = new SCPUMesh();
	ICPUMeshDataFormatDesc* desc = new ICPUMeshDataFormatDesc();
    {
	ICPUMeshBuffer* meshbuffer = new ICPUMeshBuffer();
	meshbuffer->setMeshDataAndFormat(desc);
	desc->drop();

	mesh->addMeshBuffer(meshbuffer);
	meshbuffer->drop();
    }

	bool binary = false;
	core::stringc token;
	if (getNextToken(_file, token) != "solid")
		binary = hasColor = true;

    core::vector<core::vectorSIMDf> positions, normals;
    core::vector<uint32_t> colors;
	if (binary)
	{
        if (_file->getSize() < 80)
        {
            mesh->drop();
            return nullptr;
        }
		_file->seek(80); // skip header
        uint32_t vtxCnt = 0u;
		_file->read(&vtxCnt, 4);
        positions.reserve(3*vtxCnt);
        normals.reserve(vtxCnt);
        colors.reserve(vtxCnt);
	}
	else
		goNextLine(_file); // skip header

	uint16_t attrib=0u;
	token.reserve(32);
	while (_file->getPos() < filesize)
	{
		if (!binary)
		{
			if (getNextToken(_file, token) != "facet")
			{
				if (token=="endsolid")
					break;
				mesh->drop();
				return nullptr;
			}
			if (getNextToken(_file, token) != "normal")
			{
				mesh->drop();
				return nullptr;
			}
		}

        {
        core::vectorSIMDf n;
		getNextVector(_file, n, binary);
        normals.push_back(n);
        }

		if (!binary)
		{
			if (getNextToken(_file, token) != "outer")
			{
				mesh->drop();
				return nullptr;
			}
			if (getNextToken(_file, token) != "loop")
			{
				mesh->drop();
				return nullptr;
			}
		}

        {
        core::vectorSIMDf p[3];
		for (uint32_t i = 0u; i < 3u; ++i)
		{
			if (!binary)
			{
				if (getNextToken(_file, token) != "vertex")
				{
					mesh->drop();
					return nullptr;
				}
			}
			getNextVector(_file, p[i], binary);
		}
        for (uint32_t i = 0u; i < 3u; ++i) // seems like in STL format vertices are ordered in clockwise manner...
            positions.push_back(p[2u-i]);
        }

		if (!binary)
		{
			if (getNextToken(_file, token) != "endloop")
			{
				mesh->drop();
				return nullptr;
			}
			if (getNextToken(_file, token) != "endfacet")
			{
				mesh->drop();
				return nullptr;
			}
		}
		else
		{
			_file->read(&attrib, 2);
		}

        if (hasColor && (attrib & 0x8000)) // assuming VisCam/SolidView non-standard trick to store color in 2 bytes of extra attribute
        {
            colors.push_back(video::A1R5G5B5toA8R8G8B8(attrib));
        }
        else
        {
            hasColor = false;
            colors.clear();
        }

		if ((normals.back() == core::vectorSIMDf()).all())
        {
			normals.back().set(
                core::plane3df(
                    (positions.rbegin()+2)->getAsVector3df(),
                    (positions.rbegin()+1)->getAsVector3df(),
                    (positions.rbegin()+0)->getAsVector3df()).Normal
            );
        }
	} // end while (_file->getPos() < filesize)

    const size_t vtxSize = hasColor ? (3 * sizeof(float) + 4 + 4) : (3 * sizeof(float) + 4);
	core::ICPUBuffer* vertexBuf = new core::ICPUBuffer(vtxSize*positions.size());

    uint32_t normal{};
    for (size_t i = 0u; i < positions.size(); ++i)
    {
        if (i%3 == 0)
            normal = quantizeNormal2_10_10_10(normals[i/3]);
        uint8_t* ptr = ((uint8_t*)(vertexBuf->getPointer())) + i*vtxSize;
        memcpy(ptr, positions[i].pointer, 3*4);
        ((uint32_t*)(ptr+12))[0] = normal;
        if (hasColor)
            memcpy(ptr+16, colors.data()+i/3, 4);
    }

	desc->mapVertexAttrBuffer(vertexBuf, EVAI_ATTR0, ECPA_THREE, ECT_FLOAT, vtxSize, 0);
	desc->mapVertexAttrBuffer(vertexBuf, EVAI_ATTR3, ECPA_FOUR, ECT_INT_2_10_10_10_REV, vtxSize, 12);
    if (hasColor)
	    desc->mapVertexAttrBuffer(vertexBuf, EVAI_ATTR1, ECPA_REVERSED_OR_BGRA, ECT_NORMALIZED_UNSIGNED_BYTE, vtxSize, 16);
	vertexBuf->drop();

	mesh->getMeshBuffer(0)->setIndexCount(positions.size());
    //mesh->getMeshBuffer(0)->setPrimitiveType(EPT_POINTS);
	mesh->recalculateBoundingBox(true);

	return mesh;
}

bool CSTLMeshFileLoader::isALoadableFileFormat(io::IReadFile* _file) const
{
    if (_file->getSize() <= 6u)
        return false;

    char header[6];
    const size_t prevPos = _file->getPos();
    _file->seek(0u);
    _file->read(header, 6u);
    _file->seek(prevPos);

    if (strncmp(header, "solid ", 6u) == 0)
        return true;
    else
    {
        if (_file->getSize() < 84u)
        {
            _file->seek(prevPos);
            return false;
        }
        _file->seek(80u);
        uint32_t triCnt;
        _file->read(&triCnt, 4u);
        _file->seek(prevPos);
        const size_t STL_TRI_SZ = 50u;
        return _file->getSize() == (STL_TRI_SZ*triCnt + 84u);
    }
}

//! Read 3d vector of floats
void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vectorSIMDf& vec, bool binary) const
{
	if (binary)
	{
		file->read(&vec.X, 4);
		file->read(&vec.Y, 4);
		file->read(&vec.Z, 4);
	}
	else
	{
		goNextWord(file);
		core::stringc tmp;

		getNextToken(file, tmp);
		sscanf(tmp.c_str(),"%f",&vec.X);
		getNextToken(file, tmp);
		sscanf(tmp.c_str(),"%f",&vec.Y);
		getNextToken(file, tmp);
		sscanf(tmp.c_str(),"%f",&vec.Z);
	}
	vec.X=-vec.X;
}

//! Read next word
const core::stringc& CSTLMeshFileLoader::getNextToken(io::IReadFile* file, core::stringc& token) const
{
	goNextWord(file);
	uint8_t c;
	token = "";
	while(file->getPos() != file->getSize())
	{
		file->read(&c, 1);
		// found it, so leave
		if (core::isspace(c))
			break;
		token.append(c);
	}
	return token;
}

//! skip to next word
void CSTLMeshFileLoader::goNextWord(io::IReadFile* file) const
{
	uint8_t c;
	while(file->getPos() != file->getSize())
	{
		file->read(&c, 1);
		// found it, so leave
		if (!core::isspace(c))
		{
			file->seek(-1, true);
			break;
		}
	}
}

//! Read until line break is reached and stop at the next non-space character
void CSTLMeshFileLoader::goNextLine(io::IReadFile* file) const
{
	uint8_t c;
	// look for newline characters
	while(file->getPos() != file->getSize())
	{
		file->read(&c, 1);
		// found it, so leave
		if (c=='\n' || c=='\r')
			break;
	}
}

} // end namespace scene
} // end namespace irr

#endif // _IRR_COMPILE_WITH_STL_LOADER_
<|endoftext|>


<commit_before>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "leveldb/c.h"

#include <stdlib.h>
#include <unistd.h>
#include "leveldb/cache.h"
#include "leveldb/comparator.h"
#include "leveldb/db.h"
#include "leveldb/env.h"
#include "leveldb/filter_policy.h"
#include "leveldb/iterator.h"
#include "leveldb/options.h"
#include "leveldb/status.h"
#include "leveldb/write_batch.h"

using leveldb::Cache;
using leveldb::Comparator;
using leveldb::CompressionType;
using leveldb::DB;
using leveldb::Env;
using leveldb::FileLock;
using leveldb::FilterPolicy;
using leveldb::Iterator;
using leveldb::kMajorVersion;
using leveldb::kMinorVersion;
using leveldb::Logger;
using leveldb::NewBloomFilterPolicy;
using leveldb::NewLRUCache;
using leveldb::Options;
using leveldb::RandomAccessFile;
using leveldb::Range;
using leveldb::ReadOptions;
using leveldb::SequentialFile;
using leveldb::Slice;
using leveldb::Snapshot;
using leveldb::Status;
using leveldb::WritableFile;
using leveldb::WriteBatch;
using leveldb::WriteOptions;

extern "C" {

struct leveldb_t              { DB*               rep; };
struct leveldb_iterator_t     { Iterator*         rep; };
struct leveldb_writebatch_t   { WriteBatch        rep; };
struct leveldb_snapshot_t     { const Snapshot*   rep; };
struct leveldb_readoptions_t  { ReadOptions       rep; };
struct leveldb_writeoptions_t { WriteOptions      rep; };
struct leveldb_options_t      { Options           rep; };
struct leveldb_cache_t        { Cache*            rep; };
struct leveldb_seqfile_t      { SequentialFile*   rep; };
struct leveldb_randomfile_t   { RandomAccessFile* rep; };
struct leveldb_writablefile_t { WritableFile*     rep; };
struct leveldb_logger_t       { Logger*           rep; };
struct leveldb_filelock_t     { FileLock*         rep; };

struct leveldb_comparator_t : public Comparator {
  void* state_;
  void (*destructor_)(void*);
  int (*compare_)(
      void*,
      const char* a, size_t alen,
      const char* b, size_t blen);
  const char* (*name_)(void*);

  virtual ~leveldb_comparator_t() {
    (*destructor_)(state_);
  }

  virtual int Compare(const Slice& a, const Slice& b) const {
    return (*compare_)(state_, a.data(), a.size(), b.data(), b.size());
  }

  virtual const char* Name() const {
    return (*name_)(state_);
  }

  // No-ops since the C binding does not support key shortening methods.
  virtual void FindShortestSeparator(std::string*, const Slice&) const { }
  virtual void FindShortSuccessor(std::string* key) const { }
};

struct leveldb_filterpolicy_t : public FilterPolicy {
  void* state_;
  void (*destructor_)(void*);
  const char* (*name_)(void*);
  char* (*create_)(
      void*,
      const char* const* key_array, const size_t* key_length_array,
      int num_keys,
      size_t* filter_length);
  unsigned char (*key_match_)(
      void*,
      const char* key, size_t length,
      const char* filter, size_t filter_length);

  virtual ~leveldb_filterpolicy_t() {
    (*destructor_)(state_);
  }

  virtual const char* Name() const {
    return (*name_)(state_);
  }

  virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
    std::vector<const char*> key_pointers(n);
    std::vector<size_t> key_sizes(n);
    for (int i = 0; i < n; i++) {
      key_pointers[i] = keys[i].data();
      key_sizes[i] = keys[i].size();
    }
    size_t len;
    char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len);
    dst->append(filter, len);
    free(filter);
  }

  virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
    return (*key_match_)(state_, key.data(), key.size(),
                         filter.data(), filter.size());
  }
};

struct leveldb_env_t {
  Env* rep;
  bool is_default;
};

static bool SaveError(char** errptr, const Status& s) {
  assert(errptr != NULL);
  if (s.ok()) {
    return false;
  } else if (*errptr == NULL) {
    *errptr = strdup(s.ToString().c_str());
  } else {
    // TODO(sanjay): Merge with existing error?
    free(*errptr);
    *errptr = strdup(s.ToString().c_str());
  }
  return true;
}

static char* CopyString(const std::string& str) {
  char* result = reinterpret_cast<char*>(malloc(sizeof(char) * str.size()));
  memcpy(result, str.data(), sizeof(char) * str.size());
  return result;
}

leveldb_t* leveldb_open(
    const leveldb_options_t* options,
    const char* name,
    char** errptr) {
  DB* db;
  if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) {
    return NULL;
  }
  leveldb_t* result = new leveldb_t;
  result->rep = db;
  return result;
}

void leveldb_close(leveldb_t* db) {
  delete db->rep;
  delete db;
}

void leveldb_put(
    leveldb_t* db,
    const leveldb_writeoptions_t* options,
    const char* key, size_t keylen,
    const char* val, size_t vallen,
    char** errptr) {
  SaveError(errptr,
            db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen)));
}

void leveldb_delete(
    leveldb_t* db,
    const leveldb_writeoptions_t* options,
    const char* key, size_t keylen,
    char** errptr) {
  SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen)));
}

void leveldb_write(
    leveldb_t* db,
    const leveldb_writeoptions_t* options,
    leveldb_writebatch_t* batch,
    char** errptr) {
  SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
}

char* leveldb_get(
    leveldb_t* db,
    const leveldb_readoptions_t* options,
    const char* key, size_t keylen,
    size_t* vallen,
    char** errptr) {
  char* result = NULL;
  std::string tmp;
  Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp);
  if (s.ok()) {
    *vallen = tmp.size();
    result = CopyString(tmp);
  } else {
    *vallen = 0;
    if (!s.IsNotFound()) {
      SaveError(errptr, s);
    }
  }
  return result;
}

leveldb_iterator_t* leveldb_create_iterator(
    leveldb_t* db,
    const leveldb_readoptions_t* options) {
  leveldb_iterator_t* result = new leveldb_iterator_t;
  result->rep = db->rep->NewIterator(options->rep);
  return result;
}

const leveldb_snapshot_t* leveldb_create_snapshot(
    leveldb_t* db) {
  leveldb_snapshot_t* result = new leveldb_snapshot_t;
  result->rep = db->rep->GetSnapshot();
  return result;
}

void leveldb_release_snapshot(
    leveldb_t* db,
    const leveldb_snapshot_t* snapshot) {
  db->rep->ReleaseSnapshot(snapshot->rep);
  delete snapshot;
}

char* leveldb_property_value(
    leveldb_t* db,
    const char* propname) {
  std::string tmp;
  if (db->rep->GetProperty(Slice(propname), &tmp)) {
    // We use strdup() since we expect human readable output.
    return strdup(tmp.c_str());
  } else {
    return NULL;
  }
}

void leveldb_approximate_sizes(
    leveldb_t* db,
    int num_ranges,
    const char* const* range_start_key, const size_t* range_start_key_len,
    const char* const* range_limit_key, const size_t* range_limit_key_len,
    uint64_t* sizes) {
  Range* ranges = new Range[num_ranges];
  for (int i = 0; i < num_ranges; i++) {
    ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]);
    ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]);
  }
  db->rep->GetApproximateSizes(ranges, num_ranges, sizes);
  delete[] ranges;
}

void leveldb_compact_range(
    leveldb_t* db,
    const char* start_key, size_t start_key_len,
    const char* limit_key, size_t limit_key_len) {
  Slice a, b;
  db->rep->CompactRange(
      // Pass NULL Slice if corresponding "const char*" is NULL
      (start_key ? (a = Slice(start_key, start_key_len), &a) : NULL),
      (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : NULL));
}

void leveldb_destroy_db(
    const leveldb_options_t* options,
    const char* name,
    char** errptr) {
  SaveError(errptr, DestroyDB(name, options->rep));
}

void leveldb_repair_db(
    const leveldb_options_t* options,
    const char* name,
    char** errptr) {
  SaveError(errptr, RepairDB(name, options->rep));
}

void leveldb_iter_destroy(leveldb_iterator_t* iter) {
  delete iter->rep;
  delete iter;
}

unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) {
  return iter->rep->Valid();
}

void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) {
  iter->rep->SeekToFirst();
}

void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) {
  iter->rep->SeekToLast();
}

void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) {
  iter->rep->Seek(Slice(k, klen));
}

void leveldb_iter_next(leveldb_iterator_t* iter) {
  iter->rep->Next();
}

void leveldb_iter_prev(leveldb_iterator_t* iter) {
  iter->rep->Prev();
}

const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) {
  Slice s = iter->rep->key();
  *klen = s.size();
  return s.data();
}

const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) {
  Slice s = iter->rep->value();
  *vlen = s.size();
  return s.data();
}

void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) {
  SaveError(errptr, iter->rep->status());
}

leveldb_writebatch_t* leveldb_writebatch_create() {
  return new leveldb_writebatch_t;
}

void leveldb_writebatch_destroy(leveldb_writebatch_t* b) {
  delete b;
}

void leveldb_writebatch_clear(leveldb_writebatch_t* b) {
  b->rep.Clear();
}

void leveldb_writebatch_put(
    leveldb_writebatch_t* b,
    const char* key, size_t klen,
    const char* val, size_t vlen) {
  b->rep.Put(Slice(key, klen), Slice(val, vlen));
}

void leveldb_writebatch_delete(
    leveldb_writebatch_t* b,
    const char* key, size_t klen) {
  b->rep.Delete(Slice(key, klen));
}

void leveldb_writebatch_iterate(
    leveldb_writebatch_t* b,
    void* state,
    void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
    void (*deleted)(void*, const char* k, size_t klen)) {
  class H : public WriteBatch::Handler {
   public:
    void* state_;
    void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
    void (*deleted_)(void*, const char* k, size_t klen);
    virtual void Put(const Slice& key, const Slice& value) {
      (*put_)(state_, key.data(), key.size(), value.data(), value.size());
    }
    virtual void Delete(const Slice& key) {
      (*deleted_)(state_, key.data(), key.size());
    }
  };
  H handler;
  handler.state_ = state;
  handler.put_ = put;
  handler.deleted_ = deleted;
  b->rep.Iterate(&handler);
}

leveldb_options_t* leveldb_options_create() {
  return new leveldb_options_t;
}

void leveldb_options_destroy(leveldb_options_t* options) {
  delete options;
}

void leveldb_options_set_comparator(
    leveldb_options_t* opt,
    leveldb_comparator_t* cmp) {
  opt->rep.comparator = cmp;
}

void leveldb_options_set_filter_policy(
    leveldb_options_t* opt,
    leveldb_filterpolicy_t* policy) {
  opt->rep.filter_policy = policy;
}

void leveldb_options_set_create_if_missing(
    leveldb_options_t* opt, unsigned char v) {
  opt->rep.create_if_missing = v;
}

void leveldb_options_set_error_if_exists(
    leveldb_options_t* opt, unsigned char v) {
  opt->rep.error_if_exists = v;
}

void leveldb_options_set_paranoid_checks(
    leveldb_options_t* opt, unsigned char v) {
  opt->rep.paranoid_checks = v;
}

void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) {
  opt->rep.env = (env ? env->rep : NULL);
}

void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) {
  opt->rep.info_log = (l ? l->rep : NULL);
}

void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) {
  opt->rep.write_buffer_size = s;
}

void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) {
  opt->rep.max_open_files = n;
}

void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) {
  opt->rep.block_cache = c->rep;
}

void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) {
  opt->rep.block_size = s;
}

void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) {
  opt->rep.block_restart_interval = n;
}

void leveldb_options_set_compression(leveldb_options_t* opt, int t) {
  opt->rep.compression = static_cast<CompressionType>(t);
}

leveldb_comparator_t* leveldb_comparator_create(
    void* state,
    void (*destructor)(void*),
    int (*compare)(
        void*,
        const char* a, size_t alen,
        const char* b, size_t blen),
    const char* (*name)(void*)) {
  leveldb_comparator_t* result = new leveldb_comparator_t;
  result->state_ = state;
  result->destructor_ = destructor;
  result->compare_ = compare;
  result->name_ = name;
  return result;
}

void leveldb_comparator_destroy(leveldb_comparator_t* cmp) {
  delete cmp;
}

leveldb_filterpolicy_t* leveldb_filterpolicy_create(
    void* state,
    void (*destructor)(void*),
    char* (*create_filter)(
        void*,
        const char* const* key_array, const size_t* key_length_array,
        int num_keys,
        size_t* filter_length),
    unsigned char (*key_may_match)(
        void*,
        const char* key, size_t length,
        const char* filter, size_t filter_length),
    const char* (*name)(void*)) {
  leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t;
  result->state_ = state;
  result->destructor_ = destructor;
  result->create_ = create_filter;
  result->key_match_ = key_may_match;
  result->name_ = name;
  return result;
}

void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) {
  delete filter;
}

leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) {
  // Make a leveldb_filterpolicy_t, but override all of its methods so
  // they delegate to a NewBloomFilterPolicy() instead of user
  // supplied C functions.
  struct Wrapper : public leveldb_filterpolicy_t {
    const FilterPolicy* rep_;
    ~Wrapper() { delete rep_; }
    const char* Name() const { return rep_->Name(); }
    void CreateFilter(const Slice* keys, int n, std::string* dst) const {
      return rep_->CreateFilter(keys, n, dst);
    }
    bool KeyMayMatch(const Slice& key, const Slice& filter) const {
      return rep_->KeyMayMatch(key, filter);
    }
    static void DoNothing(void*) { }
  };
  Wrapper* wrapper = new Wrapper;
  wrapper->rep_ = NewBloomFilterPolicy(bits_per_key);
  wrapper->state_ = NULL;
  wrapper->destructor_ = &Wrapper::DoNothing;
  return wrapper;
}

leveldb_readoptions_t* leveldb_readoptions_create() {
  return new leveldb_readoptions_t;
}

void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) {
  delete opt;
}

void leveldb_readoptions_set_verify_checksums(
    leveldb_readoptions_t* opt,
    unsigned char v) {
  opt->rep.verify_checksums = v;
}

void leveldb_readoptions_set_fill_cache(
    leveldb_readoptions_t* opt, unsigned char v) {
  opt->rep.fill_cache = v;
}

void leveldb_readoptions_set_snapshot(
    leveldb_readoptions_t* opt,
    const leveldb_snapshot_t* snap) {
  opt->rep.snapshot = (snap ? snap->rep : NULL);
}

leveldb_writeoptions_t* leveldb_writeoptions_create() {
  return new leveldb_writeoptions_t;
}

void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) {
  delete opt;
}

void leveldb_writeoptions_set_sync(
    leveldb_writeoptions_t* opt, unsigned char v) {
  opt->rep.sync = v;
}

leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) {
  leveldb_cache_t* c = new leveldb_cache_t;
  c->rep = NewLRUCache(capacity);
  return c;
}

void leveldb_cache_destroy(leveldb_cache_t* cache) {
  delete cache->rep;
  delete cache;
}

leveldb_env_t* leveldb_create_default_env() {
  leveldb_env_t* result = new leveldb_env_t;
  result->rep = Env::Default();
  result->is_default = true;
  return result;
}

void leveldb_env_destroy(leveldb_env_t* env) {
  if (!env->is_default) delete env->rep;
  delete env;
}

void leveldb_free(void* ptr) {
  free(ptr);
}

int leveldb_major_version() {
  return kMajorVersion;
}

int leveldb_minor_version() {
  return kMinorVersion;
}

}  // end extern "C"
<commit_msg>Delete c.cc<commit_after><|endoftext|>


<commit_before>#include <yamail/resource_pool/async/pool.hpp>

#include <benchmark/benchmark.h>

#include <boost/numeric/conversion/cast.hpp>

#include <condition_variable>
#include <iomanip>
#include <random>
#include <thread>

namespace {

using namespace yamail::resource_pool;

struct benchmark_args {
    std::size_t sequences;
    std::size_t threads;
    std::size_t resources;
    std::size_t queue_size;
};

struct resource {};

struct context {
    boost::asio::io_context io_context;
    boost::asio::io_context::work work {io_context};
    std::atomic_bool stop {false};
    time_traits::duration timeout {std::chrono::milliseconds(100)};
    double recycle_probability {0};
    std::vector<std::chrono::steady_clock::duration> durations;
    std::condition_variable get_next;
    std::mutex get_next_mutex;
    std::unique_lock<std::mutex> get_next_lock {get_next_mutex};

    void wait_next() {
        get_next.wait(get_next_lock);
    }

    void allow_next() {
        get_next.notify_one();
    }

    void finish() {
        stop = true;
        io_context.stop();
    }
};

struct callback {
    context& ctx;
    async::pool<resource>& pool;

    void operator ()(const boost::system::error_code& ec, async::pool<resource>::handle handle) {
        impl(ec, std::move(handle));
        if (!ctx.stop) {
            pool.get_auto_waste(ctx.io_context, *this, ctx.timeout);
        }
        ctx.allow_next();
    }

    void impl(const boost::system::error_code& ec, async::pool<resource>::handle handle) {
        static thread_local std::minstd_rand generator(std::hash<std::thread::id>()(std::this_thread::get_id()));
        static std::uniform_real_distribution<> distrubution(0, 1);
        static constexpr const double recycle_probability = 0.5;
        if (!ec) {
            if (handle.empty()) {
                handle.reset(resource {});
            }
            if (distrubution(generator) < recycle_probability) {
                handle.recycle();
            }
        }
    }
};

struct io_context_post_callback {
    context& ctx;

    void operator ()() {
        if (!ctx.stop) {
            ctx.io_context.post(*this);
        }
        ctx.allow_next();
    }
};

static const std::vector<benchmark_args> benchmarks({
    {1, 1, 1, 0}, // 0
    {2, 1, 1, 1}, // 1
    {2, 1, 2, 0}, // 2
    {10, 1, 10, 0}, // 3
    {10, 1, 1, 9}, // 4
    {10, 1, 5, 5}, // 5
    {10, 1, 9, 1}, // 6
    {10, 2, 5, 5}, // 7
    {100, 1, 100, 0}, // 8
    {100, 1, 10, 90}, // 9
    {100, 1, 50, 50}, // 10
    {100, 1, 90, 10}, // 11
    {100, 2, 50, 50}, // 12
    {1000, 1, 10, 990}, // 13
    {1000, 2, 10, 990}, // 14
    {10000, 1, 10, 9990}, // 15
    {10000, 2, 10, 9990}, // 16
});

void get_auto_waste(benchmark::State& state) {
    const auto& args = benchmarks[boost::numeric_cast<std::size_t>(state.range(0))];
    context ctx;
    std::vector<std::thread> workers;
    for (std::size_t i = 0; i < args.threads; ++i) {
        workers.emplace_back(std::thread([&] { return ctx.io_context.run(); }));
    }
    async::pool<resource> pool(args.resources, args.queue_size);
    callback cb {ctx, pool};
    for (std::size_t i = 0; i < args.sequences; ++i) {
        pool.get_auto_waste(ctx.io_context, cb, ctx.timeout);
    }
    while (state.KeepRunning()) {
        ctx.wait_next();
    }
    ctx.finish();
    std::for_each(workers.begin(), workers.end(), std::mem_fn(&std::thread::join));
}

void all_benchmarks(benchmark::internal::Benchmark* b) {
    for (std::size_t n = 0; n < benchmarks.size(); ++n) {
        b->Arg(int(n));
    }
}

}

BENCHMARK(get_auto_waste)->Apply(all_benchmarks);

BENCHMARK_MAIN();
<commit_msg>Fix benchmark for multiple threads<commit_after>#include <yamail/resource_pool/async/pool.hpp>

#include <benchmark/benchmark.h>

#include <boost/numeric/conversion/cast.hpp>

#include <atomic>
#include <condition_variable>
#include <iomanip>
#include <random>
#include <thread>

namespace {

using namespace yamail::resource_pool;

struct benchmark_args {
    std::size_t sequences;
    std::size_t threads;
    std::size_t resources;
    std::size_t queue_size;
};

struct resource {};

struct context {
    boost::asio::io_context io_context;
    boost::asio::io_context::work work {io_context};
    std::atomic_bool stop {false};
    time_traits::duration timeout {std::chrono::milliseconds(100)};
    double recycle_probability {0};
    std::vector<std::chrono::steady_clock::duration> durations;
    std::condition_variable get_next;
    std::mutex get_next_mutex;
    std::unique_lock<std::mutex> get_next_lock {get_next_mutex};
    std::atomic<std::int64_t> ready_count {0};

    void wait_next() {
        if (--ready_count < 0) {
            get_next.wait(get_next_lock);
        }
    }

    void allow_next() {
        ++ready_count;
        get_next.notify_one();
    }

    void finish() {
        stop = true;
        io_context.stop();
    }
};

struct callback {
    context& ctx;
    async::pool<resource>& pool;

    void operator ()(const boost::system::error_code& ec, async::pool<resource>::handle handle) {
        impl(ec, std::move(handle));
        if (!ctx.stop) {
            pool.get_auto_waste(ctx.io_context, *this, ctx.timeout);
        }
        ctx.allow_next();
    }

    void impl(const boost::system::error_code& ec, async::pool<resource>::handle handle) {
        static thread_local std::minstd_rand generator(std::hash<std::thread::id>()(std::this_thread::get_id()));
        static std::uniform_real_distribution<> distrubution(0, 1);
        static constexpr const double recycle_probability = 0.5;
        if (!ec) {
            if (handle.empty()) {
                handle.reset(resource {});
            }
            if (distrubution(generator) < recycle_probability) {
                handle.recycle();
            }
        }
    }
};

struct io_context_post_callback {
    context& ctx;

    void operator ()() {
        if (!ctx.stop) {
            ctx.io_context.post(*this);
        }
        ctx.allow_next();
    }
};

static const std::vector<benchmark_args> benchmarks({
    {1, 1, 1, 0}, // 0
    {2, 1, 1, 1}, // 1
    {2, 1, 2, 0}, // 2
    {10, 1, 10, 0}, // 3
    {10, 1, 1, 9}, // 4
    {10, 1, 5, 5}, // 5
    {10, 1, 9, 1}, // 6
    {10, 2, 5, 5}, // 7
    {100, 1, 100, 0}, // 8
    {100, 1, 10, 90}, // 9
    {100, 1, 50, 50}, // 10
    {100, 1, 90, 10}, // 11
    {100, 2, 50, 50}, // 12
    {1000, 1, 10, 990}, // 13
    {1000, 2, 10, 990}, // 14
    {10000, 1, 10, 9990}, // 15
    {10000, 2, 10, 9990}, // 16
});

void get_auto_waste(benchmark::State& state) {
    const auto& args = benchmarks[boost::numeric_cast<std::size_t>(state.range(0))];
    context ctx;
    std::vector<std::thread> workers;
    for (std::size_t i = 0; i < args.threads; ++i) {
        workers.emplace_back(std::thread([&] { return ctx.io_context.run(); }));
    }
    async::pool<resource> pool(args.resources, args.queue_size);
    callback cb {ctx, pool};
    for (std::size_t i = 0; i < args.sequences; ++i) {
        pool.get_auto_waste(ctx.io_context, cb, ctx.timeout);
    }
    while (state.KeepRunning()) {
        ctx.wait_next();
    }
    ctx.finish();
    std::for_each(workers.begin(), workers.end(), std::mem_fn(&std::thread::join));
}

void all_benchmarks(benchmark::internal::Benchmark* b) {
    for (std::size_t n = 0; n < benchmarks.size(); ++n) {
        b->Arg(int(n));
    }
}

}

BENCHMARK(get_auto_waste)->Apply(all_benchmarks);

BENCHMARK_MAIN();
<|endoftext|>