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

#include "test/test_pivx.h"

#include "util.h"
#include "validation.h"

#include <vector>

#include <boost/test/unit_test.hpp>

#define SKIPLIST_LENGTH 300000

BOOST_FIXTURE_TEST_SUITE(skiplist_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(skiplist_test)
{
    std::vector<CBlockIndex> vIndex(SKIPLIST_LENGTH);

    for (int i=0; i<SKIPLIST_LENGTH; i++) {
        vIndex[i].nHeight = i;
        vIndex[i].pprev = (i == 0) ? NULL : &vIndex[i - 1];
        vIndex[i].BuildSkip();
    }

    for (int i=0; i<SKIPLIST_LENGTH; i++) {
        if (i > 0) {
            BOOST_CHECK(vIndex[i].pskip == &vIndex[vIndex[i].pskip->nHeight]);
            BOOST_CHECK(vIndex[i].pskip->nHeight < i);
        } else {
            BOOST_CHECK(vIndex[i].pskip == NULL);
        }
    }

    for (int i=0; i < 1000; i++) {
        int from = InsecureRandRange(SKIPLIST_LENGTH - 1);
        int to = InsecureRandRange(from + 1);

        BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]);
        BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]);
        BOOST_CHECK(vIndex[from].GetAncestor(0) == &vIndex[0]);
    }
}

BOOST_AUTO_TEST_CASE(getlocator_test)
{
    // Build a main chain 100000 blocks long.
    std::vector<uint256> vHashMain(100000);
    std::vector<CBlockIndex> vBlocksMain(100000);
    for (unsigned int i=0; i<vBlocksMain.size(); i++) {
        vHashMain[i] = i; // Set the hash equal to the height, so we can quickly check the distances.
        vBlocksMain[i].nHeight = i;
        vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : NULL;
        vBlocksMain[i].phashBlock = &vHashMain[i];
        vBlocksMain[i].BuildSkip();
        BOOST_CHECK_EQUAL((int)vBlocksMain[i].GetBlockHash().GetLow64(), vBlocksMain[i].nHeight);
        BOOST_CHECK(vBlocksMain[i].pprev == NULL || vBlocksMain[i].nHeight == vBlocksMain[i].pprev->nHeight + 1);
    }

    // Build a branch that splits off at block 49999, 50000 blocks long.
    std::vector<uint256> vHashSide(50000);
    std::vector<CBlockIndex> vBlocksSide(50000);
    for (unsigned int i=0; i<vBlocksSide.size(); i++) {
        vHashSide[i] = i + 50000 + (uint256(1) << 128); // Add 1<<128 to the hashes, so GetLow64() still returns the height.
        vBlocksSide[i].nHeight = i + 50000;
        vBlocksSide[i].pprev = i ? &vBlocksSide[i - 1] : &vBlocksMain[49999];
        vBlocksSide[i].phashBlock = &vHashSide[i];
        vBlocksSide[i].BuildSkip();
        BOOST_CHECK_EQUAL((int)vBlocksSide[i].GetBlockHash().GetLow64(), vBlocksSide[i].nHeight);
        BOOST_CHECK(vBlocksSide[i].pprev == NULL || vBlocksSide[i].nHeight == vBlocksSide[i].pprev->nHeight + 1);
    }

    // Build a CChain for the main branch.
    CChain chain;
    chain.SetTip(&vBlocksMain.back());

    // Test 100 random starting points for locators.
    for (int n=0; n<100; n++) {
        int r = InsecureRandRange(150000);
        CBlockIndex* tip = (r < 100000) ? &vBlocksMain[r] : &vBlocksSide[r - 100000];
        CBlockLocator locator = chain.GetLocator(tip);

        // The first result must be the block itself, the last one must be genesis.
        BOOST_CHECK(locator.vHave.front() == tip->GetBlockHash());
        BOOST_CHECK(locator.vHave.back() == vBlocksMain[0].GetBlockHash());

        // Entries 1 through 11 (inclusive) go back one step each.
        for (unsigned int i = 1; i < 12 && i < locator.vHave.size() - 1; i++) {
            BOOST_CHECK_EQUAL(locator.vHave[i].GetLow64(), tip->nHeight - i);
        }

        // The further ones (excluding the last one) go back with exponential steps.
        unsigned int dist = 2;
        for (unsigned int i = 12; i < locator.vHave.size() - 1; i++) {
            BOOST_CHECK_EQUAL(locator.vHave[i - 1].GetLow64() - locator.vHave[i].GetLow64(), dist);
            dist *= 2;
        }
    }
}

BOOST_AUTO_TEST_CASE(findearliestatleast_test)
{
    std::vector<uint256> vHashMain(100000);
    std::vector<CBlockIndex> vBlocksMain(100000);
    for (unsigned int i=0; i<vBlocksMain.size(); i++) {
        vHashMain[i] = ArithToUint256(i); // Set the hash equal to the height
        vBlocksMain[i].nHeight = i;
        vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : NULL;
        vBlocksMain[i].phashBlock = &vHashMain[i];
        vBlocksMain[i].BuildSkip();
        if (i < 10) {
            vBlocksMain[i].nTime = i;
            vBlocksMain[i].nTimeMax = i;
        } else {
            // randomly choose something in the range [MTP, MTP*2]
            int64_t medianTimePast = vBlocksMain[i].GetMedianTimePast();
            int r = InsecureRandRange(medianTimePast);
            vBlocksMain[i].nTime = r + medianTimePast;
            vBlocksMain[i].nTimeMax = std::max(vBlocksMain[i].nTime, vBlocksMain[i-1].nTimeMax);
        }
    }
    // Check that we set nTimeMax up correctly.
    unsigned int curTimeMax = 0;
    for (unsigned int i=0; i<vBlocksMain.size(); ++i) {
        curTimeMax = std::max(curTimeMax, vBlocksMain[i].nTime);
        BOOST_CHECK(curTimeMax == vBlocksMain[i].nTimeMax);
    }

    // Build a CChain for the main branch.
    CChain chain;
    chain.SetTip(&vBlocksMain.back());

    // Verify that FindEarliestAtLeast is correct.
    for (unsigned int i=0; i<10000; ++i) {
        // Pick a random element in vBlocksMain.
        int r = InsecureRandRange(vBlocksMain.size());
        int64_t test_time = vBlocksMain[r].nTime;
        CBlockIndex *ret = chain.FindEarliestAtLeast(test_time);
        BOOST_CHECK(ret->nTimeMax >= test_time);
        BOOST_CHECK((ret->pprev==NULL) || ret->pprev->nTimeMax < test_time);
        BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret);
    }
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>[Trivial] NULL --> nullptr in skiplist_tests<commit_after>// Copyright (c) 2014 The Bitcoin Core developers
// Copyright (c) 2017-2019 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "test/test_pivx.h"

#include "util.h"
#include "validation.h"

#include <vector>

#include <boost/test/unit_test.hpp>

#define SKIPLIST_LENGTH 300000

BOOST_FIXTURE_TEST_SUITE(skiplist_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(skiplist_test)
{
    std::vector<CBlockIndex> vIndex(SKIPLIST_LENGTH);

    for (int i=0; i<SKIPLIST_LENGTH; i++) {
        vIndex[i].nHeight = i;
        vIndex[i].pprev = (i == 0) ? nullptr : &vIndex[i - 1];
        vIndex[i].BuildSkip();
    }

    for (int i=0; i<SKIPLIST_LENGTH; i++) {
        if (i > 0) {
            BOOST_CHECK(vIndex[i].pskip == &vIndex[vIndex[i].pskip->nHeight]);
            BOOST_CHECK(vIndex[i].pskip->nHeight < i);
        } else {
            BOOST_CHECK(vIndex[i].pskip == nullptr);
        }
    }

    for (int i=0; i < 1000; i++) {
        int from = InsecureRandRange(SKIPLIST_LENGTH - 1);
        int to = InsecureRandRange(from + 1);

        BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]);
        BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]);
        BOOST_CHECK(vIndex[from].GetAncestor(0) == &vIndex[0]);
    }
}

BOOST_AUTO_TEST_CASE(getlocator_test)
{
    // Build a main chain 100000 blocks long.
    std::vector<uint256> vHashMain(100000);
    std::vector<CBlockIndex> vBlocksMain(100000);
    for (unsigned int i=0; i<vBlocksMain.size(); i++) {
        vHashMain[i] = i; // Set the hash equal to the height, so we can quickly check the distances.
        vBlocksMain[i].nHeight = i;
        vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : nullptr;
        vBlocksMain[i].phashBlock = &vHashMain[i];
        vBlocksMain[i].BuildSkip();
        BOOST_CHECK_EQUAL((int)vBlocksMain[i].GetBlockHash().GetLow64(), vBlocksMain[i].nHeight);
        BOOST_CHECK(vBlocksMain[i].pprev == nullptr || vBlocksMain[i].nHeight == vBlocksMain[i].pprev->nHeight + 1);
    }

    // Build a branch that splits off at block 49999, 50000 blocks long.
    std::vector<uint256> vHashSide(50000);
    std::vector<CBlockIndex> vBlocksSide(50000);
    for (unsigned int i=0; i<vBlocksSide.size(); i++) {
        vHashSide[i] = i + 50000 + (uint256(1) << 128); // Add 1<<128 to the hashes, so GetLow64() still returns the height.
        vBlocksSide[i].nHeight = i + 50000;
        vBlocksSide[i].pprev = i ? &vBlocksSide[i - 1] : &vBlocksMain[49999];
        vBlocksSide[i].phashBlock = &vHashSide[i];
        vBlocksSide[i].BuildSkip();
        BOOST_CHECK_EQUAL((int)vBlocksSide[i].GetBlockHash().GetLow64(), vBlocksSide[i].nHeight);
        BOOST_CHECK(vBlocksSide[i].pprev == nullptr || vBlocksSide[i].nHeight == vBlocksSide[i].pprev->nHeight + 1);
    }

    // Build a CChain for the main branch.
    CChain chain;
    chain.SetTip(&vBlocksMain.back());

    // Test 100 random starting points for locators.
    for (int n=0; n<100; n++) {
        int r = InsecureRandRange(150000);
        CBlockIndex* tip = (r < 100000) ? &vBlocksMain[r] : &vBlocksSide[r - 100000];
        CBlockLocator locator = chain.GetLocator(tip);

        // The first result must be the block itself, the last one must be genesis.
        BOOST_CHECK(locator.vHave.front() == tip->GetBlockHash());
        BOOST_CHECK(locator.vHave.back() == vBlocksMain[0].GetBlockHash());

        // Entries 1 through 11 (inclusive) go back one step each.
        for (unsigned int i = 1; i < 12 && i < locator.vHave.size() - 1; i++) {
            BOOST_CHECK_EQUAL(locator.vHave[i].GetLow64(), tip->nHeight - i);
        }

        // The further ones (excluding the last one) go back with exponential steps.
        unsigned int dist = 2;
        for (unsigned int i = 12; i < locator.vHave.size() - 1; i++) {
            BOOST_CHECK_EQUAL(locator.vHave[i - 1].GetLow64() - locator.vHave[i].GetLow64(), dist);
            dist *= 2;
        }
    }
}

BOOST_AUTO_TEST_CASE(findearliestatleast_test)
{
    std::vector<uint256> vHashMain(100000);
    std::vector<CBlockIndex> vBlocksMain(100000);
    for (unsigned int i=0; i<vBlocksMain.size(); i++) {
        vHashMain[i] = ArithToUint256(i); // Set the hash equal to the height
        vBlocksMain[i].nHeight = i;
        vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : nullptr;
        vBlocksMain[i].phashBlock = &vHashMain[i];
        vBlocksMain[i].BuildSkip();
        if (i < 10) {
            vBlocksMain[i].nTime = i;
            vBlocksMain[i].nTimeMax = i;
        } else {
            // randomly choose something in the range [MTP, MTP*2]
            int64_t medianTimePast = vBlocksMain[i].GetMedianTimePast();
            int r = InsecureRandRange(medianTimePast);
            vBlocksMain[i].nTime = r + medianTimePast;
            vBlocksMain[i].nTimeMax = std::max(vBlocksMain[i].nTime, vBlocksMain[i-1].nTimeMax);
        }
    }
    // Check that we set nTimeMax up correctly.
    unsigned int curTimeMax = 0;
    for (unsigned int i=0; i<vBlocksMain.size(); ++i) {
        curTimeMax = std::max(curTimeMax, vBlocksMain[i].nTime);
        BOOST_CHECK(curTimeMax == vBlocksMain[i].nTimeMax);
    }

    // Build a CChain for the main branch.
    CChain chain;
    chain.SetTip(&vBlocksMain.back());

    // Verify that FindEarliestAtLeast is correct.
    for (unsigned int i=0; i<10000; ++i) {
        // Pick a random element in vBlocksMain.
        int r = InsecureRandRange(vBlocksMain.size());
        int64_t test_time = vBlocksMain[r].nTime;
        CBlockIndex *ret = chain.FindEarliestAtLeast(test_time);
        BOOST_CHECK(ret->nTimeMax >= test_time);
        BOOST_CHECK((ret->pprev==nullptr) || ret->pprev->nTimeMax < test_time);
        BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret);
    }
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include <QObject>
#include <QVector>
#include <QString>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlField>
#include <QSqlError>
#include <QUrlQuery>
#include "kernel.h"
#include "ilwisdata.h"
#include "symboltable.h"
#include "operationExpression.h"
#include "operationmetadata.h"
#include "operation.h"
#include "commandhandler.h"
#include "mastercatalog.h"

//----------------------------------
Ilwis::CommandHandler *Ilwis::CommandHandler::_commandHandler= 0;
using namespace Ilwis;

//-----------------------------------
void ExecutionContext::clear()
{
    _silent = false;
    _threaded = true;
    _results.clear();
}

ExecutionContext::ExecutionContext(bool threaded) : _silent(false), _threaded(threaded){
}

void ExecutionContext::addOutput(SymbolTable &tbl, const QVariant &var, const QString &nme, quint64 tp, const Resource& res)
{
    QString name =  nme == sUNDEF ? SymbolTable::newAnonym() : nme;
    tbl.addSymbol(name,_scope, tp, var);
    _results.push_back(name);
    if ( name.indexOf(INTERNAL_PREFIX) == -1 && res.isValid()) {
        mastercatalog()->addItems({res});
    }
}

Ilwis::CommandHandler* Ilwis::commandhandler() {
    if (Ilwis::CommandHandler::_commandHandler == 0) {
        Ilwis::CommandHandler::_commandHandler = new Ilwis::CommandHandler(kernel()->parent());
        //Ilwis::CommandHandler::_context->init();

    }
    return Ilwis::CommandHandler::_commandHandler;
}

//-------------------------------------------------------
CommandHandler::CommandHandler(QObject *parent) :
    QObject(parent)
{
}

CommandHandler::~CommandHandler(){
   _commands.clear();
}

bool CommandHandler::execute(const QString& command, ExecutionContext *ctx) {
    SymbolTable tbl;
    OperationExpression expr(command, tbl);
    quint64 id = findOperationId(expr);
    if ( id != i64UNDEF) {
        QScopedPointer<OperationImplementation> oper(create( expr));
        if ( !oper.isNull() && oper->isValid()) {
            return oper->execute(ctx, tbl);
        }
    }
    return false;
}

bool CommandHandler::execute(const QString &command, ExecutionContext *ctx, SymbolTable &symTable)
{
    OperationExpression expr(command, symTable);
    quint64 id = findOperationId(expr);
    if ( id != i64UNDEF) {
        QScopedPointer<OperationImplementation> oper(create( expr));
        if ( !oper.isNull() && oper->isValid()) {
            return oper->execute(ctx, symTable);
        }
    }
    return false;
}

OperationImplementation *CommandHandler::create(const OperationExpression &expr)  {
    quint64 id = findOperationId(expr);
    auto iter = _commands.find(id);
    if ( iter != _commands.end()) {
        OperationImplementation *oper = ((*iter).second(id, expr));
        return oper;
    }
    return 0;
}

void CommandHandler::addOperation(quint64 id, CreateOperation op)
{

    if ( id != i64UNDEF) {
        _commands[id] = op;
    }
}

quint64 CommandHandler::findOperationId(const OperationExpression& expr) const {

    QSqlQuery db(kernel()->database());
    QSqlQuery db2(kernel()->database());
    QString query = QString("select * from mastercatalog where resource like '%1%' ").arg(expr.metaUrl().toString());
    if (db.exec(query)) {
        while ( db.next()){
            quint64 itemid = db.value("itemid").toLongLong();
            query = QString("select * from catalogitemproperties where itemid=%1").arg(itemid);
            if (db2.exec(query)) {
                std::map<QString, QString> values;
                while ( db2.next()){
                    QSqlRecord rec = db2.record();
                    values[rec.value("propertyname").toString()] = rec.value("propertyvalue").toString();
                }
                QString parmcount = values["inparameters"];
                if ( !expr.matchesParameterCount(parmcount))
                    continue;
                bool found = true;
                for(int i=0; i < expr.parameterCount(); ++i) {
                    QString key = QString("pin_%1_type").arg(i+1);
                    IlwisTypes tpExpr = expr.parm(i).valuetype();
                    auto iter = values.find(key);
                    if ( iter == values.end()){
                        found = false;
                        break;
                    }
                    IlwisTypes tpMeta = (*iter).second.toULongLong();
                    if ( (tpMeta & tpExpr) == 0 && tpExpr != i64UNDEF) {
                        found = false;
                        break;
                    }

                }
                if ( found)
                    return itemid;
            }
        }
    }
    ERROR2(ERR_NO_INITIALIZED_2,"metadata",expr.name());
    return i64UNDEF;
}
<commit_msg>improved the handling for methods with unbounded number of parameters<commit_after>#include <QObject>
#include <QVector>
#include <QString>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlField>
#include <QSqlError>
#include <QUrlQuery>
#include "kernel.h"
#include "ilwisdata.h"
#include "symboltable.h"
#include "operationExpression.h"
#include "operationmetadata.h"
#include "operation.h"
#include "commandhandler.h"
#include "mastercatalog.h"

//----------------------------------
Ilwis::CommandHandler *Ilwis::CommandHandler::_commandHandler= 0;
using namespace Ilwis;

//-----------------------------------
void ExecutionContext::clear()
{
    _silent = false;
    _threaded = true;
    _results.clear();
}

ExecutionContext::ExecutionContext(bool threaded) : _silent(false), _threaded(threaded){
}

void ExecutionContext::addOutput(SymbolTable &tbl, const QVariant &var, const QString &nme, quint64 tp, const Resource& res)
{
    QString name =  nme == sUNDEF ? SymbolTable::newAnonym() : nme;
    tbl.addSymbol(name,_scope, tp, var);
    _results.push_back(name);
    if ( name.indexOf(INTERNAL_PREFIX) == -1 && res.isValid()) {
        mastercatalog()->addItems({res});
    }
}

Ilwis::CommandHandler* Ilwis::commandhandler() {
    if (Ilwis::CommandHandler::_commandHandler == 0) {
        Ilwis::CommandHandler::_commandHandler = new Ilwis::CommandHandler(kernel()->parent());
        //Ilwis::CommandHandler::_context->init();

    }
    return Ilwis::CommandHandler::_commandHandler;
}

//-------------------------------------------------------
CommandHandler::CommandHandler(QObject *parent) :
    QObject(parent)
{
}

CommandHandler::~CommandHandler(){
   _commands.clear();
}

bool CommandHandler::execute(const QString& command, ExecutionContext *ctx) {
    SymbolTable tbl;
    OperationExpression expr(command, tbl);
    quint64 id = findOperationId(expr);
    if ( id != i64UNDEF) {
        QScopedPointer<OperationImplementation> oper(create( expr));
        if ( !oper.isNull() && oper->isValid()) {
            return oper->execute(ctx, tbl);
        }
    }
    return false;
}

bool CommandHandler::execute(const QString &command, ExecutionContext *ctx, SymbolTable &symTable)
{
    OperationExpression expr(command, symTable);
    quint64 id = findOperationId(expr);
    if ( id != i64UNDEF) {
        QScopedPointer<OperationImplementation> oper(create( expr));
        if ( !oper.isNull() && oper->isValid()) {
            return oper->execute(ctx, symTable);
        }
    }
    return false;
}

OperationImplementation *CommandHandler::create(const OperationExpression &expr)  {
    quint64 id = findOperationId(expr);
    auto iter = _commands.find(id);
    if ( iter != _commands.end()) {
        OperationImplementation *oper = ((*iter).second(id, expr));
        return oper;
    }
    return 0;
}

void CommandHandler::addOperation(quint64 id, CreateOperation op)
{

    if ( id != i64UNDEF) {
        _commands[id] = op;
    }
}

quint64 CommandHandler::findOperationId(const OperationExpression& expr) const {

    QSqlQuery db(kernel()->database());
    QSqlQuery db2(kernel()->database());
    QString query = QString("select * from mastercatalog where resource like '%1%' ").arg(expr.metaUrl().toString());
    if (db.exec(query)) {
        while ( db.next()){
            quint64 itemid = db.value("itemid").toLongLong();
            query = QString("select * from catalogitemproperties where itemid=%1").arg(itemid);
            if (db2.exec(query)) {
                std::map<QString, QString> values;
                while ( db2.next()){
                    QSqlRecord rec = db2.record();
                    values[rec.value("propertyname").toString()] = rec.value("propertyvalue").toString();
                }
                QString parmcount = values["inparameters"];
                if ( !expr.matchesParameterCount(parmcount))
                    continue;
                bool found = true;
                long index;
                if ( (index = parmcount.indexOf('+')) != -1) {
                    index = parmcount.left(index).toUInt();
                } else
                    index = 10000;
                for(long i=0; i < expr.parameterCount(); ++i) {
                    int n = min(i+1, index);
                    QString key = QString("pin_%1_type").arg(n);
                    IlwisTypes tpExpr = expr.parm(i).valuetype();
                    auto iter = values.find(key);
                    if ( iter == values.end()){
                        found = false;
                        break;
                    }
                    IlwisTypes tpMeta = (*iter).second.toULongLong();
                    if ( (tpMeta & tpExpr) == 0 && tpExpr != i64UNDEF) {
                        found = false;
                        break;
                    }

                }
                if ( found)
                    return itemid;
            }
        }
    }
    ERROR2(ERR_NO_INITIALIZED_2,"metadata",expr.name());
    return i64UNDEF;
}
<|endoftext|>


<commit_before>/*	opendatacon
 *
 *	Copyright (c) 2014:
 *
 *		DCrip3fJguWgVCLrZFfA7sIGgvx1Ou3fHfCxnrz4svAi
 *		yxeOtDhDCXf1Z4ApgXvX5ahqQmzRfJ2DoX8S05SqHA==
 *
 *	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.
 */
//
//  MhdWrapper.cpp
//  opendatacon
//
//  Created by Alan Murray on 14/09/2014.
//
//

#include <iostream>
#include <opendatacon/util.h>

#include "MhdWrapper.h"

const int POSTBUFFERSIZE = 512;
const char EMPTY_PAGE[] = "<title>File not found</title>File not found";

const std::unordered_map<std::string, const std::string> MimeTypeMap {
	{ "json", "application/json" },
	{ "js", "text/javascript" },
	{ "html", "text/html"},
	{ "jpg", "image/jpeg"},
	{ "css", "text/css"},
	{ "txt", "text/plain"},
	{ "svg", "image/svg+xml"},
	{ "default", "application/octet-stream"}
};

const std::string& GetMimeType(const std::string& rUrl)
{
	auto last = rUrl.find_last_of("/\\.");
	if (last == std::string::npos) return MimeTypeMap.at("default");
	const std::string pExt = rUrl.substr(last+1);

	if(MimeTypeMap.count(pExt) != 0)
	{
		return MimeTypeMap.at(pExt);
	}
	return MimeTypeMap.at("default");
}

static ssize_t
file_reader(void *cls, uint64_t pos, char *buf, size_t max)
{
	FILE *file = (FILE *)cls;

	(void)fseek(file, pos, SEEK_SET);
	return fread(buf, 1, max, file);
}

static void
file_free_callback(void *cls)
{
	FILE *file = (FILE *)cls;
	fclose(file);
}

const std::string GetPath(const std::string& rUrl)
{
	auto last = rUrl.find_last_of("/\\");
	if (last == std::string::npos) return "";
	return rUrl.substr(0,last);
}

const std::string GetFile(const std::string& rUrl)
{
	auto last = rUrl.find_last_of("/\\");
	if (last == std::string::npos) return rUrl;
	return rUrl.substr(last+1);
}

int ReturnFile(struct MHD_Connection *connection, const std::string& url)
{
	struct stat buf;
	FILE *file;
	struct MHD_Response *response;
	int ret;

	if ((0 == stat(url.c_str(), &buf)) && (S_ISREG(buf.st_mode)))
		fopen_s(&file, url.c_str(), "rb");
	else
		file = nullptr;
	if (file == nullptr)
	{
		if (auto log = odc::spdlog_get("WebUI"))
			log->error("WebUI : Failed to open file {}", url);

		response = MHD_create_response_from_buffer(strlen(EMPTY_PAGE),
			(void *)EMPTY_PAGE,
			MHD_RESPMEM_PERSISTENT);
		ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
		MHD_destroy_response(response);
	}
	else
	{
		response = MHD_create_response_from_callback(buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
			&file_reader, file,
			&file_free_callback);
		if (response == nullptr)
		{
			fclose(file);
			return MHD_NO;
		}
		MHD_add_response_header(response, "Content-Type", GetMimeType(url).c_str());
		ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
		MHD_destroy_response(response);
	}
	return ret;
}

int ReturnJSON(struct MHD_Connection *connection, const std::string& json_str)
{
	struct MHD_Response *response;
	int ret;

	/*
	 MHD_RESPMEM_MUST_FREE
	 MHD_RESPMEM_MUST_COPY
	 */
	response = MHD_create_response_from_buffer(json_str.size(),
		(void *)json_str.c_str(),
		MHD_RESPMEM_MUST_COPY);
	MHD_add_response_header (response, "Content-Type", MimeTypeMap.at("json").c_str());
	ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
	MHD_destroy_response(response);

	return ret;
}

/*
 * adapted from MHD_http_unescape
 */
std::string post_unescape(const char *val)
{
	std::string result;
	const char *rpos = val;
	//char *wpos = val;
	char *end;
	char buf3[3];

	while ('\0' != *rpos)
	{
		switch (*rpos)
		{
			case '+':
			{
				result += ' ';
				//*wpos = ' ';
				//wpos++;
				rpos++;
				break;
			}
			case '%':
			{
				if ( ('\0' == rpos[1]) ||
				     ('\0' == rpos[2]) )
				{
					//*wpos = '\0';
					//return wpos - val;
					return result;
				}
				buf3[0] = rpos[1];
				buf3[1] = rpos[2];
				buf3[2] = '\0';
				auto num = strtoul (buf3, &end, 16);
				if ('\0' == *end)
				{
					//*wpos = (char)((unsigned char) num);
					//wpos++;
					result += (char)((unsigned char) num);
					rpos += 3;
					break;
				}
				/* intentional fall through! */
			}
			default:
			{
				//*wpos = *rpos;
				//wpos++;
				result += *rpos;
				rpos++;
			}
		}
	}
	//*wpos = '\0'; /* add 0-terminator */
	//return wpos - val; /* = strlen(val) */
	return result;
}

static int
iterate_post (void *coninfo_cls,
	enum MHD_ValueKind kind, //MHD_POSTDATA_KIND
	const char *key,         // POST KEY
	const char *filename,
	const char *content_type,
	const char *transfer_encoding,
	const char *data, // POST VALUE
	uint64_t off,
	size_t size // POST VALUE LENGTH
	)
{
	struct connection_info_struct* con_info = (connection_info_struct*) coninfo_cls;

	if (kind == MHD_POSTDATA_KIND)
	{
		con_info->PostValues[post_unescape(key)] = post_unescape(data);
		return MHD_YES;
	}
	return MHD_NO;
}

void request_completed(void *cls, struct MHD_Connection *connection,
	void **con_cls,
	enum MHD_RequestTerminationCode toe)
{
	struct connection_info_struct *con_info = (connection_info_struct*)*con_cls;

	if (nullptr == con_info) return;
	if (nullptr != con_info->postprocessor) MHD_destroy_post_processor(con_info->postprocessor);
	con_info->postprocessor = nullptr;
	free(con_info);
	*con_cls = nullptr;
}

int CreateNewRequest(void *cls,
	struct MHD_Connection *connection,
	const std::string& url,
	const std::string& method,
	const std::string& version,
	const std::string& upload_data,
	size_t& upload_data_size,
	void **con_cls)
{
	struct connection_info_struct *con_info;

	con_info = new connection_info_struct;
	if (nullptr == con_info) return MHD_NO;
	*con_cls = (void*)con_info;

	if (method == MHD_HTTP_METHOD_GET) return MHD_YES;
	if (method == "POST")
	{
		auto length = atoi(MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length"));
		if (length == 0) return MHD_YES;
		con_info->postprocessor = MHD_create_post_processor(connection, POSTBUFFERSIZE, iterate_post, (void*) con_info);
		if (nullptr != con_info->postprocessor) return MHD_YES;
	}

	// unexpected method or couldn't create post processor
	free(con_info);
	*con_cls = nullptr;
	return MHD_NO;
}
<commit_msg>match new with delete (not free)<commit_after>/*	opendatacon
 *
 *	Copyright (c) 2014:
 *
 *		DCrip3fJguWgVCLrZFfA7sIGgvx1Ou3fHfCxnrz4svAi
 *		yxeOtDhDCXf1Z4ApgXvX5ahqQmzRfJ2DoX8S05SqHA==
 *
 *	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.
 */
//
//  MhdWrapper.cpp
//  opendatacon
//
//  Created by Alan Murray on 14/09/2014.
//
//

#include <iostream>
#include <opendatacon/util.h>

#include "MhdWrapper.h"

const int POSTBUFFERSIZE = 512;
const char EMPTY_PAGE[] = "<title>File not found</title>File not found";

const std::unordered_map<std::string, const std::string> MimeTypeMap {
	{ "json", "application/json" },
	{ "js", "text/javascript" },
	{ "html", "text/html"},
	{ "jpg", "image/jpeg"},
	{ "css", "text/css"},
	{ "txt", "text/plain"},
	{ "svg", "image/svg+xml"},
	{ "default", "application/octet-stream"}
};

const std::string& GetMimeType(const std::string& rUrl)
{
	auto last = rUrl.find_last_of("/\\.");
	if (last == std::string::npos) return MimeTypeMap.at("default");
	const std::string pExt = rUrl.substr(last+1);

	if(MimeTypeMap.count(pExt) != 0)
	{
		return MimeTypeMap.at(pExt);
	}
	return MimeTypeMap.at("default");
}

static ssize_t
file_reader(void *cls, uint64_t pos, char *buf, size_t max)
{
	FILE *file = (FILE *)cls;

	(void)fseek(file, pos, SEEK_SET);
	return fread(buf, 1, max, file);
}

static void
file_free_callback(void *cls)
{
	FILE *file = (FILE *)cls;
	fclose(file);
}

const std::string GetPath(const std::string& rUrl)
{
	auto last = rUrl.find_last_of("/\\");
	if (last == std::string::npos) return "";
	return rUrl.substr(0,last);
}

const std::string GetFile(const std::string& rUrl)
{
	auto last = rUrl.find_last_of("/\\");
	if (last == std::string::npos) return rUrl;
	return rUrl.substr(last+1);
}

int ReturnFile(struct MHD_Connection *connection, const std::string& url)
{
	struct stat buf;
	FILE *file;
	struct MHD_Response *response;
	int ret;

	if ((0 == stat(url.c_str(), &buf)) && (S_ISREG(buf.st_mode)))
		fopen_s(&file, url.c_str(), "rb");
	else
		file = nullptr;
	if (file == nullptr)
	{
		if (auto log = odc::spdlog_get("WebUI"))
			log->error("WebUI : Failed to open file {}", url);

		response = MHD_create_response_from_buffer(strlen(EMPTY_PAGE),
			(void *)EMPTY_PAGE,
			MHD_RESPMEM_PERSISTENT);
		ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
		MHD_destroy_response(response);
	}
	else
	{
		response = MHD_create_response_from_callback(buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
			&file_reader, file,
			&file_free_callback);
		if (response == nullptr)
		{
			fclose(file);
			return MHD_NO;
		}
		MHD_add_response_header(response, "Content-Type", GetMimeType(url).c_str());
		ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
		MHD_destroy_response(response);
	}
	return ret;
}

int ReturnJSON(struct MHD_Connection *connection, const std::string& json_str)
{
	struct MHD_Response *response;
	int ret;

	/*
	 MHD_RESPMEM_MUST_FREE
	 MHD_RESPMEM_MUST_COPY
	 */
	response = MHD_create_response_from_buffer(json_str.size(),
		(void *)json_str.c_str(),
		MHD_RESPMEM_MUST_COPY);
	MHD_add_response_header (response, "Content-Type", MimeTypeMap.at("json").c_str());
	ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
	MHD_destroy_response(response);

	return ret;
}

/*
 * adapted from MHD_http_unescape
 */
std::string post_unescape(const char *val)
{
	std::string result;
	const char *rpos = val;
	//char *wpos = val;
	char *end;
	char buf3[3];

	while ('\0' != *rpos)
	{
		switch (*rpos)
		{
			case '+':
			{
				result += ' ';
				//*wpos = ' ';
				//wpos++;
				rpos++;
				break;
			}
			case '%':
			{
				if ( ('\0' == rpos[1]) ||
				     ('\0' == rpos[2]) )
				{
					//*wpos = '\0';
					//return wpos - val;
					return result;
				}
				buf3[0] = rpos[1];
				buf3[1] = rpos[2];
				buf3[2] = '\0';
				auto num = strtoul (buf3, &end, 16);
				if ('\0' == *end)
				{
					//*wpos = (char)((unsigned char) num);
					//wpos++;
					result += (char)((unsigned char) num);
					rpos += 3;
					break;
				}
				/* intentional fall through! */
			}
			default:
			{
				//*wpos = *rpos;
				//wpos++;
				result += *rpos;
				rpos++;
			}
		}
	}
	//*wpos = '\0'; /* add 0-terminator */
	//return wpos - val; /* = strlen(val) */
	return result;
}

static int
iterate_post (void *coninfo_cls,
	enum MHD_ValueKind kind, //MHD_POSTDATA_KIND
	const char *key,         // POST KEY
	const char *filename,
	const char *content_type,
	const char *transfer_encoding,
	const char *data, // POST VALUE
	uint64_t off,
	size_t size // POST VALUE LENGTH
	)
{
	struct connection_info_struct* con_info = (connection_info_struct*) coninfo_cls;

	if (kind == MHD_POSTDATA_KIND)
	{
		con_info->PostValues[post_unescape(key)] = post_unescape(data);
		return MHD_YES;
	}
	return MHD_NO;
}

void request_completed(void *cls, struct MHD_Connection *connection,
	void **con_cls,
	enum MHD_RequestTerminationCode toe)
{
	struct connection_info_struct *con_info = (connection_info_struct*)*con_cls;

	if (nullptr == con_info) return;
	if (nullptr != con_info->postprocessor) MHD_destroy_post_processor(con_info->postprocessor);
	con_info->postprocessor = nullptr;
	free(con_info);
	*con_cls = nullptr;
}

int CreateNewRequest(void *cls,
	struct MHD_Connection *connection,
	const std::string& url,
	const std::string& method,
	const std::string& version,
	const std::string& upload_data,
	size_t& upload_data_size,
	void **con_cls)
{
	struct connection_info_struct *con_info;

	con_info = new connection_info_struct;
	if (nullptr == con_info) return MHD_NO;
	*con_cls = (void*)con_info;

	if (method == MHD_HTTP_METHOD_GET) return MHD_YES;
	if (method == "POST")
	{
		auto length = atoi(MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length"));
		if (length == 0) return MHD_YES;
		con_info->postprocessor = MHD_create_post_processor(connection, POSTBUFFERSIZE, iterate_post, (void*) con_info);
		if (nullptr != con_info->postprocessor) return MHD_YES;
	}

	// unexpected method or couldn't create post processor
	delete con_info;
	*con_cls = nullptr;
	return MHD_NO;
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------
// Copyright 2011 Ciaran McHale.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions.
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//----------------------------------------------------------------------

//--------
// #include's
//--------
#include "RecipeFileParser.h"
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

//--------
// Forward declarations
//--------
static void
parseCmdLineArgs(
	int						argc,
	char **					argv,
	const char *&			recipeFilename,
	const char *&			scope);
static void usage();

int
main(int argc, char ** argv)
{
	RecipeFileParser *		parser;
	const char *			recipeFilename;
	const char *			scope;
	StringVector			recipeScopes;
	StringVector			steps;
	StringVector			ingredients;
	const char *			name;
	int						i;
	int						len;
	int						i2;
	int						len2;

	setlocale(LC_ALL, "");
	parseCmdLineArgs(argc, argv, recipeFilename, scope);

	//--------
	// Parse and error-check a file containing recipes.
	//--------
	try {
		parser = new RecipeFileParser();
		parser->parse(recipeFilename, scope);
	} catch(const RecipeFileParserException & ex) {
		fprintf(stderr, "%s\n", ex.c_str());
		delete parser;
		return 1;
	}

	//--------
	// Print information about the recipes.
	//--------
	parser->listRecipeScopes(recipeScopes);
	len = recipeScopes.length();
	printf("There are %d recipes\n", len);
	for (i = 0; i < len; i++) {
		name = parser->getRecipeName(recipeScopes[i]);
		parser->getRecipeIngredients(recipeScopes[i], ingredients);
		parser->getRecipeSteps(recipeScopes[i], steps);
		printf("\nRecipe \"%s\":\n", name);
		len2 = ingredients.length();
		printf("\tThis recipe has %d ingredients:\n", len2);
		for (i2 = 0; i2 < len2; i2++) {
			printf("\t\t\"%s\"\n", ingredients[i2]);
		}
		len2 = steps.length();
		printf("\tThis recipe has %d steps:\n", len2);
		for (i2 = 0; i2 < len2; i2++) {
			printf("\t\t\"%s\"\n", steps[i2]);
		}
	}

	delete parser;
	return 0;
}

static void
parseCmdLineArgs(
	int						argc,
	char **					argv,
	const char *&			recipeFilename,
	const char *&			scope)
{
	int				i;

	recipeFilename = "";
	scope = "";

	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-h") == 0) {
			usage();
		} else if (strcmp(argv[i], "-recipes") == 0) {
			if (i == argc-1) { usage(); }
			recipeFilename = argv[i+1];
			i++;
		} else if (strcmp(argv[i], "-scope") == 0) {
			if (i == argc-1) { usage(); }
			scope = argv[i+1];
			i++;
		} else {
			fprintf(stderr, "Unrecognised option '%s'\n\n",
				argv[i]);
			usage();
		}
	}
	if (strcmp(recipeFilename, "") == 0) {
		usage();
	}
}

static void
usage()
{
	fprintf(stderr,
		"\n"
		"usage: demo <options> -recipes <source>\n"
		"\n"
		"The <options> can be:\n"
		"  -h                Print this usage statement\n"
		"  -scope            scope within recipes file\n"
		"A <source> can be one of the following:\n"
		"  file.cfg          A file\n"
		"  file#file.cfg     A file\n"
		"  exec#<command>    Output from executing the specified command\n\n");
	exit(1);
}

<commit_msg>Initialize variable.<commit_after>//----------------------------------------------------------------------
// Copyright 2011 Ciaran McHale.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions.
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//----------------------------------------------------------------------

//--------
// #include's
//--------
#include "RecipeFileParser.h"
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

//--------
// Forward declarations
//--------
static void
parseCmdLineArgs(
	int						argc,
	char **					argv,
	const char *&			recipeFilename,
	const char *&			scope);
static void usage();

int
main(int argc, char ** argv)
{
	RecipeFileParser *		parser = nullptr;
	const char *			recipeFilename;
	const char *			scope;
	StringVector			recipeScopes;
	StringVector			steps;
	StringVector			ingredients;
	const char *			name;
	int						i;
	int						len;
	int						i2;
	int						len2;

	setlocale(LC_ALL, "");
	parseCmdLineArgs(argc, argv, recipeFilename, scope);

	//--------
	// Parse and error-check a file containing recipes.
	//--------
	try {
		parser = new RecipeFileParser();
		parser->parse(recipeFilename, scope);
	} catch(const RecipeFileParserException & ex) {
		fprintf(stderr, "%s\n", ex.c_str());
		delete parser;
		return 1;
	}

	//--------
	// Print information about the recipes.
	//--------
	parser->listRecipeScopes(recipeScopes);
	len = recipeScopes.length();
	printf("There are %d recipes\n", len);
	for (i = 0; i < len; i++) {
		name = parser->getRecipeName(recipeScopes[i]);
		parser->getRecipeIngredients(recipeScopes[i], ingredients);
		parser->getRecipeSteps(recipeScopes[i], steps);
		printf("\nRecipe \"%s\":\n", name);
		len2 = ingredients.length();
		printf("\tThis recipe has %d ingredients:\n", len2);
		for (i2 = 0; i2 < len2; i2++) {
			printf("\t\t\"%s\"\n", ingredients[i2]);
		}
		len2 = steps.length();
		printf("\tThis recipe has %d steps:\n", len2);
		for (i2 = 0; i2 < len2; i2++) {
			printf("\t\t\"%s\"\n", steps[i2]);
		}
	}

	delete parser;
	return 0;
}

static void
parseCmdLineArgs(
	int						argc,
	char **					argv,
	const char *&			recipeFilename,
	const char *&			scope)
{
	int				i;

	recipeFilename = "";
	scope = "";

	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-h") == 0) {
			usage();
		} else if (strcmp(argv[i], "-recipes") == 0) {
			if (i == argc-1) { usage(); }
			recipeFilename = argv[i+1];
			i++;
		} else if (strcmp(argv[i], "-scope") == 0) {
			if (i == argc-1) { usage(); }
			scope = argv[i+1];
			i++;
		} else {
			fprintf(stderr, "Unrecognised option '%s'\n\n",
				argv[i]);
			usage();
		}
	}
	if (strcmp(recipeFilename, "") == 0) {
		usage();
	}
}

static void
usage()
{
	fprintf(stderr,
		"\n"
		"usage: demo <options> -recipes <source>\n"
		"\n"
		"The <options> can be:\n"
		"  -h                Print this usage statement\n"
		"  -scope            scope within recipes file\n"
		"A <source> can be one of the following:\n"
		"  file.cfg          A file\n"
		"  file#file.cfg     A file\n"
		"  exec#<command>    Output from executing the specified command\n\n");
	exit(1);
}

<|endoftext|>


<commit_before>#include "..\include\SequentialGreedy.h"

#include <iostream>

// Greedily color one vertex
uint16_t SequentialGreedy::colorVertexGreedy(uint64_t vertex, std::vector<uint64_t> &neighbors, ColorMap &colors)
{
	uint16_t color = 0;
	bool lowest_found = false;

	while (!lowest_found)
	{
		lowest_found = true;

		for (uint64_t id : neighbors)
		{
			auto search = colors.find(id);

			if (search == colors.end())
				continue;

			if (color == search->second)
			{
				lowest_found = false;
				color++;
				break;
			};
		}
	}

	return color;
}

// Greedily color all vertices.
int SequentialGreedy::color(AdjacencyList adjacencyList, std::set<Vertex> sortedVertices, bool ascending)
{
	static std::unordered_map<uint64_t, uint16_t> colors = std::unordered_map<uint64_t, uint16_t>();
	uint16_t highestColor = 0;

	// Ascending order
	if (ascending)
	{
		for (auto vertex = sortedVertices.begin(); vertex != sortedVertices.end(); ++vertex)
		{
			uint16_t color = colorVertexGreedy(
				vertex->id,
				adjacencyList.getNeighbors(vertex->id),
				colors
			);

			colors.insert(std::make_pair(vertex->id, color));

			if (color > highestColor)
				highestColor = color;
		}
	}

	// Descending order
	else
	{
		for (auto vertex = sortedVertices.rbegin(); vertex != sortedVertices.rend(); ++vertex)
		{
			uint16_t color = colorVertexGreedy(
				vertex->id,
				adjacencyList.getNeighbors(vertex->id),
				colors
			);

			colors.insert(std::make_pair(vertex->id, color));

			if (color > highestColor)
				highestColor = color;
		}
	}

	return highestColor + 1;
}
<commit_msg>Speed coloring individual vertices<commit_after>#include "..\include\SequentialGreedy.h"

#include <iostream>

// Greedily color one vertex
uint16_t SequentialGreedy::colorVertexGreedy(uint64_t vertex, std::vector<uint64_t> &neighbors, ColorMap &colors)
{
	std::set<uint16_t> neighborColors = std::set<uint16_t>();
	for (uint64_t neighbor : neighbors)
	{
		auto search = colors.find(neighbor);
		if (search == colors.end())	continue;
		neighborColors.insert(search->second);
	}

	uint16_t last = 0;
	for (uint16_t color : neighborColors)
	{
		if (color == last) last += 1;
		else break;
	}

	return last;
}

// Greedily color all vertices.
int SequentialGreedy::color(AdjacencyList adjacencyList, std::set<Vertex> sortedVertices, bool ascending)
{
	static std::unordered_map<uint64_t, uint16_t> colors = std::unordered_map<uint64_t, uint16_t>();
	uint16_t highestColor = 0;

	// Ascending order
	if (ascending)
	{
		for (auto vertex = sortedVertices.begin(); vertex != sortedVertices.end(); ++vertex)
		{
			uint16_t color = colorVertexGreedy(
				vertex->id,
				adjacencyList.getNeighbors(vertex->id),
				colors
			);

			colors.insert(std::make_pair(vertex->id, color));

			if (color > highestColor)
				highestColor = color;
		}
	}

	// Descending order
	else
	{
		for (auto vertex = sortedVertices.rbegin(); vertex != sortedVertices.rend(); ++vertex)
		{
			uint16_t color = colorVertexGreedy(
				vertex->id,
				adjacencyList.getNeighbors(vertex->id),
				colors
			);

			colors.insert(std::make_pair(vertex->id, color));

			if (color > highestColor)
				highestColor = color;
		}
	}

	return highestColor + 1;
}
<|endoftext|>


<commit_before>/*
 * $Id: BitVector.cpp,v 1.3 2006/09/18 06:20:15 nathanst Exp $
 *
 * This file is part of HOG.
 *
 * HOG is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * HOG is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with HOG; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <cstdlib>
#include <cstdio>
#include "BitVector.h"
#include "MMapUtil.h"
#include <sys/mman.h>

BitVector::BitVector(uint64_t _size)
{
	true_size = _size;
	size = (_size>>storageBitsPower)+1;
	storage = new storageElement[size];
	for (int x = 0; x < size; x++)
		storage[x] = 0;
	memmap = false;
}

BitVector::BitVector(uint64_t entries, const char *file, bool zero)
{
	// make sure we allocate even space for 32 bit entries
	while (0 != entries%storageBits)
	{
		entries++;
	}
	uint8_t *mem = GetMMAP(file, entries/8, fd, zero); // number of bytes needed
	storage = (storageElement*)mem;
	size = (entries>>storageBitsPower)+1;
	true_size = entries;
	memmap = true;
}

BitVector::~BitVector()
{
	if (!memmap)
	{
		delete [] storage;
	}
	else {
		printf("Closing mmap\n");
		// close memmap
		CloseMMap((uint8_t*)storage, true_size/8, fd);
	}
}

void BitVector::Save(const char *file)
{
	FILE *f = fopen(file, "w+");
	if (f == 0)
	{
		printf("File write error\n");
		exit(0);
	}
	fwrite(&true_size, sizeof(true_size), 1, f);
	fwrite(storage, sizeof(storageElement), size, f);
	fclose(f);
}

void BitVector::Load(const char *file)
{
	if (memmap)
	{
		printf("BitVector is memmapped; not loading\n");
		return;
	}

	delete [] storage;
	FILE *f = fopen(file, "r");
	if (f == 0)
	{
		printf("File write error\n");
		exit(0);
	}
	//fread(&size, sizeof(size), 1, f);
	fread(&true_size, sizeof(true_size), 1, f);
	printf("Loading %llu entries\n", true_size);
	// allocate storage
	size = (true_size>>storageBitsPower)+1;

	storage = new storageElement[size];
	//	for (int x = 0; x < size; x++)
	//		storage[x] = 0;

	// TODO:
	fread(storage, sizeof(storageElement), size, f);
	fclose(f);
}

void BitVector::clear()
{
  for (int x = 0; x < size; x++)
	  storage[x] = 0;
}

//BitVector *BitVector::Clone()
//{
//  BitVector *bv = new BitVector(true_size);
//  bv->Merge(this);
//  return bv;
//}

void BitVector::Set(uint64_t index, bool value)
{
  if ((index>>storageBitsPower) > size) {
    printf("SET %llu OUT OF RANGE\n", index);
    exit(0);
  }
  if (value)
    storage[index>>storageBitsPower] = storage[index>>storageBitsPower]|(1<<(index&storageMask));
  else
    storage[index>>storageBitsPower] = storage[index>>storageBitsPower]&(~(1<<(index&storageMask)));
}

//void BitVector::Merge(BitVector *bv)
//{
//  if (bv == 0) return;
//  if (bv->size != size) {
//    printf("Error; can't merge vectors of different sizes (%d/%d)\n", bv->true_size, true_size);
//    return;
//  }
//  for (int x = 0; x < size; x++) storage[x] |= bv->storage[x];
//}

bool BitVector::Equals(BitVector *bv)
{
  if (bv->size != size) return false;
  for (int x = 0; x < size; x++)
    if (storage[x] != bv->storage[x])
      return false;
  return true;
}

int BitVector::GetNumSetBits()
{
  int sum = 0;
  for (int x = 0; x < size; x++) {
    storageElement iter = storage[x];
    while (iter) {
      if (iter&1) sum++;
      iter = iter>>1;
    }
  }
  return sum;
}
<commit_msg>better error messages<commit_after>/*
 * $Id: BitVector.cpp,v 1.3 2006/09/18 06:20:15 nathanst Exp $
 *
 * This file is part of HOG.
 *
 * HOG is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * HOG is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with HOG; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <cstdlib>
#include <cstdio>
#include "BitVector.h"
#include "MMapUtil.h"
#include <sys/mman.h>

BitVector::BitVector(uint64_t _size)
{
	true_size = _size;
	size = (_size>>storageBitsPower)+1;
	storage = new storageElement[size];
	for (int x = 0; x < size; x++)
		storage[x] = 0;
	memmap = false;
}

BitVector::BitVector(uint64_t entries, const char *file, bool zero)
{
	// make sure we allocate even space for 32 bit entries
	while (0 != entries%storageBits)
	{
		entries++;
	}
	uint8_t *mem = GetMMAP(file, entries/8, fd, zero); // number of bytes needed
	storage = (storageElement*)mem;
	size = (entries>>storageBitsPower)+1;
	true_size = entries;
	memmap = true;
}

BitVector::~BitVector()
{
	if (!memmap)
	{
		delete [] storage;
	}
	else {
		printf("Closing mmap\n");
		// close memmap
		CloseMMap((uint8_t*)storage, true_size/8, fd);
	}
}

void BitVector::Save(const char *file)
{
	FILE *f = fopen(file, "w+");
	if (f == 0)
	{
		printf("File write error (%s)\n", file);
		exit(0);
	}
	fwrite(&true_size, sizeof(true_size), 1, f);
	fwrite(storage, sizeof(storageElement), size, f);
	fclose(f);
}

void BitVector::Load(const char *file)
{
	if (memmap)
	{
		printf("BitVector is memmapped; not loading\n");
		return;
	}

	delete [] storage;
	FILE *f = fopen(file, "r");
	if (f == 0)
	{
		printf("File read error (%s)\n", file);
		exit(0);
	}
	//fread(&size, sizeof(size), 1, f);
	fread(&true_size, sizeof(true_size), 1, f);
	printf("Loading %llu entries\n", true_size);
	// allocate storage
	size = (true_size>>storageBitsPower)+1;

	storage = new storageElement[size];
	//	for (int x = 0; x < size; x++)
	//		storage[x] = 0;

	// TODO:
	fread(storage, sizeof(storageElement), size, f);
	fclose(f);
}

void BitVector::clear()
{
  for (int x = 0; x < size; x++)
	  storage[x] = 0;
}

//BitVector *BitVector::Clone()
//{
//  BitVector *bv = new BitVector(true_size);
//  bv->Merge(this);
//  return bv;
//}

void BitVector::Set(uint64_t index, bool value)
{
  if ((index>>storageBitsPower) > size) {
    printf("SET %llu OUT OF RANGE\n", index);
    exit(0);
  }
  if (value)
    storage[index>>storageBitsPower] = storage[index>>storageBitsPower]|(1<<(index&storageMask));
  else
    storage[index>>storageBitsPower] = storage[index>>storageBitsPower]&(~(1<<(index&storageMask)));
}

//void BitVector::Merge(BitVector *bv)
//{
//  if (bv == 0) return;
//  if (bv->size != size) {
//    printf("Error; can't merge vectors of different sizes (%d/%d)\n", bv->true_size, true_size);
//    return;
//  }
//  for (int x = 0; x < size; x++) storage[x] |= bv->storage[x];
//}

bool BitVector::Equals(BitVector *bv)
{
  if (bv->size != size) return false;
  for (int x = 0; x < size; x++)
    if (storage[x] != bv->storage[x])
      return false;
  return true;
}

int BitVector::GetNumSetBits()
{
  int sum = 0;
  for (int x = 0; x < size; x++) {
    storageElement iter = storage[x];
    while (iter) {
      if (iter&1) sum++;
      iter = iter>>1;
    }
  }
  return sum;
}
<|endoftext|>


<commit_before>/*
* Copyright 2016 Nu-book Inc.
* Copyright 2019 Axel Waggershauser
*/
// SPDX-License-Identifier: Apache-2.0

#include "ReadBarcode.h"
#include "TextUtfEncoding.h"
#include "GTIN.h"

#include <cctype>
#include <chrono>
#include <clocale>
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>

using namespace ZXing;
using namespace TextUtfEncoding;

static void PrintUsage(const char* exePath)
{
	std::cout << "Usage: " << exePath << " [-fast] [-norotate] [-format <FORMAT[,...]>] [-pngout <png out path>] [-ispure] [-1] <png image path>...\n"
			  << "    -fast      Skip some lines/pixels during detection (faster)\n"
			  << "    -norotate  Don't try rotated image during detection (faster)\n"
			  << "    -noscale   Don't try downscaled images during detection (faster)\n"
			  << "    -format    Only detect given format(s) (faster)\n"
			  << "    -ispure    Assume the image contains only a 'pure'/perfect code (faster)\n"
			  << "    -1         Print only file name, text and status on one line per file/barcode\n"
			  << "    -escape    Escape non-graphical characters in angle brackets (implicit for -1 option, which always escapes)\n"
			  << "    -binary    Write (only) the binary content of the symbol(s) to stdout\n"
			  << "    -pngout    Write a copy of the input image with barcodes outlined by a green line\n"
			  << "\n"
			  << "Supported formats are:\n";
	for (auto f : BarcodeFormats::all()) {
		std::cout << "    " << ToString(f) << "\n";
	}
	std::cout << "Formats can be lowercase, with or without '-', separated by ',' and/or '|'\n";
}

static bool ParseOptions(int argc, char* argv[], DecodeHints& hints, bool& oneLine, bool& angleEscape, bool& binaryOutput,
						 std::vector<std::string>& filePaths, std::string& outPath)
{
	for (int i = 1; i < argc; ++i) {
		if (strcmp(argv[i], "-fast") == 0) {
			hints.setTryHarder(false);
		} else if (strcmp(argv[i], "-norotate") == 0) {
			hints.setTryRotate(false);
		} else if (strcmp(argv[i], "-noscale") == 0) {
			hints.setDownscaleThreshold(0);
		} else if (strcmp(argv[i], "-ispure") == 0) {
			hints.setIsPure(true);
			hints.setBinarizer(Binarizer::FixedThreshold);
		} else if (strcmp(argv[i], "-format") == 0) {
			if (++i == argc)
				return false;
			try {
				hints.setFormats(BarcodeFormatsFromString(argv[i]));
			} catch (const std::exception& e) {
				std::cerr << e.what() << "\n";
				return false;
			}
		} else if (strcmp(argv[i], "-1") == 0) {
			oneLine = true;
		} else if (strcmp(argv[i], "-escape") == 0) {
			angleEscape = true;
		} else if (strcmp(argv[i], "-binary") == 0) {
			binaryOutput = true;
		} else if (strcmp(argv[i], "-pngout") == 0) {
			if (++i == argc)
				return false;
			outPath = argv[i];
		} else {
			filePaths.push_back(argv[i]);
		}
	}

	return !filePaths.empty();
}

std::ostream& operator<<(std::ostream& os, const Position& points)
{
	for (const auto& p : points)
		os << p.x << "x" << p.y << " ";
	return os;
}

void drawLine(const ImageView& iv, PointI a, PointI b)
{
	int steps = maxAbsComponent(b - a);
	PointF dir = bresenhamDirection(PointF(b - a));
	int R = RedIndex(iv.format()), G = GreenIndex(iv.format()), B = BlueIndex(iv.format());
	for (int i = 0; i < steps; ++i) {
		auto p = PointI(centered(a + i * dir));
		auto* dst = const_cast<uint8_t*>(iv.data(p.x, p.y));
		dst[R] = dst[B] = 0;
		dst[G] = 0xff;
	}
}

void drawRect(const ImageView& image, const Position& pos)
{
	for (int i = 0; i < 4; ++i)
		drawLine(image, pos[i], pos[(i + 1) % 4]);
}

int main(int argc, char* argv[])
{
	DecodeHints hints;
	std::vector<std::string> filePaths;
	std::string outPath;
	bool oneLine = false;
	bool angleEscape = false;
	bool binaryOutput = false;
	int ret = 0;

	if (!ParseOptions(argc, argv, hints, oneLine, angleEscape, binaryOutput, filePaths, outPath)) {
		PrintUsage(argv[0]);
		return -1;
	}

	hints.setEanAddOnSymbol(EanAddOnSymbol::Read);

	if (oneLine)
		angleEscape = true;

	if (angleEscape)
		std::setlocale(LC_CTYPE, "en_US.UTF-8"); // Needed so `std::iswgraph()` in `ToUtf8(angleEscape)` does not 'swallow' all printable non-ascii utf8 chars

	for (const auto& filePath : filePaths) {
		int width, height, channels;
		std::unique_ptr<stbi_uc, void(*)(void*)> buffer(stbi_load(filePath.c_str(), &width, &height, &channels, 3), stbi_image_free);
		if (buffer == nullptr) {
			std::cerr << "Failed to read image: " << filePath << "\n";
			return -1;
		}

		ImageView image{buffer.get(), width, height, ImageFormat::RGB};
		auto results = ReadBarcodes(image, hints);

		// if we did not find anything, insert a dummy to produce some output for each file
		if (results.empty())
			results.emplace_back(DecodeStatus::NotFound);

		for (auto&& result : results) {

			if (!outPath.empty())
				drawRect(image, result.position());

			ret |= static_cast<int>(result.status());

			if (binaryOutput) {
				std::cout.write(reinterpret_cast<const char*>(result.binary().data()), result.binary().size());
				continue;
			}

			if (oneLine) {
				std::cout << filePath << " " << ToString(result.format());
				if (result.isValid())
					std::cout << " \"" << ToUtf8(result.text(), angleEscape) << "\"";
				else if (result.format() != BarcodeFormat::None)
					std::cout << " " << ToString(result.status());
				std::cout << "\n";
				continue;
			}

			if (filePaths.size() > 1 || results.size() > 1) {
				static bool firstFile = true;
				if (!firstFile)
					std::cout << "\n";
				if (filePaths.size() > 1)
					std::cout << "File:       " << filePath << "\n";
				firstFile = false;
			}
			std::cout << "Text:       \"" << ToUtf8(result.text(), angleEscape) << "\"\n"
					  << "Binary:     \"" << ToHex(result.binary()) << "\"\n"
					  << "ECI-Proto:  \"" << result.utf8Protocol() << "\"\n"
					  << "Format:     " << ToString(result.format()) << "\n"
					  << "Identifier: " << result.symbologyIdentifier() << "\n"
					  << "Position:   " << result.position() << "\n"
					  << "Rotation:   " << result.orientation() << " deg\n"
					  << "IsMirrored: " << (result.isMirrored() ? "true" : "false") << "\n"
					  << "Error:      " << ToString(result.status()) << "\n";

			auto printOptional = [](const char* key, const std::string& v) {
				if (!v.empty())
					std::cout << key << v << "\n";
			};

			printOptional("EC Level:   ", ToUtf8(result.ecLevel()));
			printOptional("App-Ind.:   ", result.applicationIndicator());

			if (result.lineCount())
				std::cout << "Lines:      " << result.lineCount() << "\n";

			if ((BarcodeFormat::EAN13 | BarcodeFormat::EAN8 | BarcodeFormat::UPCA | BarcodeFormat::UPCE)
					.testFlag(result.format())) {
				printOptional("Country:    ", GTIN::LookupCountryIdentifier(ToUtf8(result.text()), result.format()));
				printOptional("Add-On:     ", GTIN::EanAddOn(result));
				printOptional("Price:      ", GTIN::Price(GTIN::EanAddOn(result)));
				printOptional("Issue #:    ", GTIN::IssueNr(GTIN::EanAddOn(result)));
			} else if (result.format() == BarcodeFormat::ITF && result.text().length() == 14) {
				printOptional("Country:    ", GTIN::LookupCountryIdentifier(ToUtf8(result.text()), result.format()));
			}

			if (result.isPartOfSequence())
				std::cout << "Structured Append: symbol " << result.sequenceIndex() + 1 << " of "
						  << result.sequenceSize() << " (parity/id: '" << result.sequenceId() << "')\n";

			if (result.readerInit())
				std::cout << "Reader Initialisation/Programming\n";
		}

		if (Size(filePaths) == 1 && !outPath.empty())
			stbi_write_png(outPath.c_str(), image.width(), image.height(), 3, image.data(0, 0), image.rowStride());

	}

	return ret;
}
<commit_msg>example: use std::ios::boolalpha<commit_after>/*
* Copyright 2016 Nu-book Inc.
* Copyright 2019 Axel Waggershauser
*/
// SPDX-License-Identifier: Apache-2.0

#include "ReadBarcode.h"
#include "TextUtfEncoding.h"
#include "GTIN.h"

#include <cctype>
#include <chrono>
#include <clocale>
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>

using namespace ZXing;
using namespace TextUtfEncoding;

static void PrintUsage(const char* exePath)
{
	std::cout << "Usage: " << exePath << " [-fast] [-norotate] [-format <FORMAT[,...]>] [-pngout <png out path>] [-ispure] [-1] <png image path>...\n"
			  << "    -fast      Skip some lines/pixels during detection (faster)\n"
			  << "    -norotate  Don't try rotated image during detection (faster)\n"
			  << "    -noscale   Don't try downscaled images during detection (faster)\n"
			  << "    -format    Only detect given format(s) (faster)\n"
			  << "    -ispure    Assume the image contains only a 'pure'/perfect code (faster)\n"
			  << "    -1         Print only file name, text and status on one line per file/barcode\n"
			  << "    -escape    Escape non-graphical characters in angle brackets (implicit for -1 option, which always escapes)\n"
			  << "    -binary    Write (only) the binary content of the symbol(s) to stdout\n"
			  << "    -pngout    Write a copy of the input image with barcodes outlined by a green line\n"
			  << "\n"
			  << "Supported formats are:\n";
	for (auto f : BarcodeFormats::all()) {
		std::cout << "    " << ToString(f) << "\n";
	}
	std::cout << "Formats can be lowercase, with or without '-', separated by ',' and/or '|'\n";
}

static bool ParseOptions(int argc, char* argv[], DecodeHints& hints, bool& oneLine, bool& angleEscape, bool& binaryOutput,
						 std::vector<std::string>& filePaths, std::string& outPath)
{
	for (int i = 1; i < argc; ++i) {
		if (strcmp(argv[i], "-fast") == 0) {
			hints.setTryHarder(false);
		} else if (strcmp(argv[i], "-norotate") == 0) {
			hints.setTryRotate(false);
		} else if (strcmp(argv[i], "-noscale") == 0) {
			hints.setDownscaleThreshold(0);
		} else if (strcmp(argv[i], "-ispure") == 0) {
			hints.setIsPure(true);
			hints.setBinarizer(Binarizer::FixedThreshold);
		} else if (strcmp(argv[i], "-format") == 0) {
			if (++i == argc)
				return false;
			try {
				hints.setFormats(BarcodeFormatsFromString(argv[i]));
			} catch (const std::exception& e) {
				std::cerr << e.what() << "\n";
				return false;
			}
		} else if (strcmp(argv[i], "-1") == 0) {
			oneLine = true;
		} else if (strcmp(argv[i], "-escape") == 0) {
			angleEscape = true;
		} else if (strcmp(argv[i], "-binary") == 0) {
			binaryOutput = true;
		} else if (strcmp(argv[i], "-pngout") == 0) {
			if (++i == argc)
				return false;
			outPath = argv[i];
		} else {
			filePaths.push_back(argv[i]);
		}
	}

	return !filePaths.empty();
}

std::ostream& operator<<(std::ostream& os, const Position& points)
{
	for (const auto& p : points)
		os << p.x << "x" << p.y << " ";
	return os;
}

void drawLine(const ImageView& iv, PointI a, PointI b)
{
	int steps = maxAbsComponent(b - a);
	PointF dir = bresenhamDirection(PointF(b - a));
	int R = RedIndex(iv.format()), G = GreenIndex(iv.format()), B = BlueIndex(iv.format());
	for (int i = 0; i < steps; ++i) {
		auto p = PointI(centered(a + i * dir));
		auto* dst = const_cast<uint8_t*>(iv.data(p.x, p.y));
		dst[R] = dst[B] = 0;
		dst[G] = 0xff;
	}
}

void drawRect(const ImageView& image, const Position& pos)
{
	for (int i = 0; i < 4; ++i)
		drawLine(image, pos[i], pos[(i + 1) % 4]);
}

int main(int argc, char* argv[])
{
	DecodeHints hints;
	std::vector<std::string> filePaths;
	std::string outPath;
	bool oneLine = false;
	bool angleEscape = false;
	bool binaryOutput = false;
	int ret = 0;

	if (!ParseOptions(argc, argv, hints, oneLine, angleEscape, binaryOutput, filePaths, outPath)) {
		PrintUsage(argv[0]);
		return -1;
	}

	hints.setEanAddOnSymbol(EanAddOnSymbol::Read);

	if (oneLine)
		angleEscape = true;

	if (angleEscape)
		std::setlocale(LC_CTYPE, "en_US.UTF-8"); // Needed so `std::iswgraph()` in `ToUtf8(angleEscape)` does not 'swallow' all printable non-ascii utf8 chars

	std::cout.setf(std::ios::boolalpha);

	for (const auto& filePath : filePaths) {
		int width, height, channels;
		std::unique_ptr<stbi_uc, void(*)(void*)> buffer(stbi_load(filePath.c_str(), &width, &height, &channels, 3), stbi_image_free);
		if (buffer == nullptr) {
			std::cerr << "Failed to read image: " << filePath << "\n";
			return -1;
		}

		ImageView image{buffer.get(), width, height, ImageFormat::RGB};
		auto results = ReadBarcodes(image, hints);

		// if we did not find anything, insert a dummy to produce some output for each file
		if (results.empty())
			results.emplace_back(DecodeStatus::NotFound);

		for (auto&& result : results) {

			if (!outPath.empty())
				drawRect(image, result.position());

			ret |= static_cast<int>(result.status());

			if (binaryOutput) {
				std::cout.write(reinterpret_cast<const char*>(result.binary().data()), result.binary().size());
				continue;
			}

			if (oneLine) {
				std::cout << filePath << " " << ToString(result.format());
				if (result.isValid())
					std::cout << " \"" << ToUtf8(result.text(), angleEscape) << "\"";
				else if (result.format() != BarcodeFormat::None)
					std::cout << " " << ToString(result.status());
				std::cout << "\n";
				continue;
			}

			if (filePaths.size() > 1 || results.size() > 1) {
				static bool firstFile = true;
				if (!firstFile)
					std::cout << "\n";
				if (filePaths.size() > 1)
					std::cout << "File:       " << filePath << "\n";
				firstFile = false;
			}
			std::cout << "Text:       \"" << ToUtf8(result.text(), angleEscape) << "\"\n"
					  << "Binary:     \"" << ToHex(result.binary()) << "\"\n"
					  << "ECI-Proto:  \"" << result.utf8Protocol() << "\"\n"
					  << "Format:     " << ToString(result.format()) << "\n"
					  << "Identifier: " << result.symbologyIdentifier() << "\n"
					  << "Position:   " << result.position() << "\n"
					  << "Rotation:   " << result.orientation() << " deg\n"
					  << "IsMirrored: " << result.isMirrored() << "\n"
					  << "Error:      " << ToString(result.status()) << "\n";

			auto printOptional = [](const char* key, const std::string& v) {
				if (!v.empty())
					std::cout << key << v << "\n";
			};

			printOptional("EC Level:   ", ToUtf8(result.ecLevel()));
			printOptional("App-Ind.:   ", result.applicationIndicator());

			if (result.lineCount())
				std::cout << "Lines:      " << result.lineCount() << "\n";

			if ((BarcodeFormat::EAN13 | BarcodeFormat::EAN8 | BarcodeFormat::UPCA | BarcodeFormat::UPCE)
					.testFlag(result.format())) {
				printOptional("Country:    ", GTIN::LookupCountryIdentifier(ToUtf8(result.text()), result.format()));
				printOptional("Add-On:     ", GTIN::EanAddOn(result));
				printOptional("Price:      ", GTIN::Price(GTIN::EanAddOn(result)));
				printOptional("Issue #:    ", GTIN::IssueNr(GTIN::EanAddOn(result)));
			} else if (result.format() == BarcodeFormat::ITF && result.text().length() == 14) {
				printOptional("Country:    ", GTIN::LookupCountryIdentifier(ToUtf8(result.text()), result.format()));
			}

			if (result.isPartOfSequence())
				std::cout << "Structured Append: symbol " << result.sequenceIndex() + 1 << " of "
						  << result.sequenceSize() << " (parity/id: '" << result.sequenceId() << "')\n";

			if (result.readerInit())
				std::cout << "Reader Initialisation/Programming\n";
		}

		if (Size(filePaths) == 1 && !outPath.empty())
			stbi_write_png(outPath.c_str(), image.width(), image.height(), 3, image.data(0, 0), image.rowStride());

	}

	return ret;
}
<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

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

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

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

#include <NdbOut.hpp>
#include <NdbApi.hpp>
#include <NdbSleep.h>
#include <NDBT.hpp>
#include <HugoTransactions.hpp>
#include <getarg.h>

int
main(int argc, const char** argv){
  ndb_init();

  int _help = 0;
  const char* db = 0;

  struct getargs args[] = {
    { "database", 'd', arg_string, &db, "Database", "" },
    { "usage", '?', arg_flag, &_help, "Print help", "" }
  };
  int num_args = sizeof(args) / sizeof(args[0]);
  int optind = 0, i;
  char desc[] =
    "<tabname>+ \nThis program listen to events on specified tables\n";

  if(getarg(args, num_args, argc, argv, &optind) ||
     argv[optind] == NULL || _help) {
    arg_printusage(args, num_args, argv[0], desc);
    return NDBT_ProgramExit(NDBT_WRONGARGS);
  }

  // Connect to Ndb
  Ndb_cluster_connection con;
  if(con.connect(12, 5, 1) != 0)
  {
    return NDBT_ProgramExit(NDBT_FAILED);
  }
  Ndb MyNdb( &con, db ? db : "TEST_DB" );

  if(MyNdb.init() != 0){
    ERR(MyNdb.getNdbError());
    return NDBT_ProgramExit(NDBT_FAILED);
  }

  // Connect to Ndb and wait for it to become ready
  while(MyNdb.waitUntilReady() != 0)
    ndbout << "Waiting for ndb to become ready..." << endl;

  int result = 0;
  Uint64 last_gci= 0, cnt= 0;

  NdbDictionary::Dictionary *myDict = MyNdb.getDictionary();
  Vector<NdbDictionary::Event*> events;
  Vector<NdbEventOperation*> event_ops;
  for(i= optind; i<argc; i++)
  {
    const NdbDictionary::Table* table= myDict->getTable(argv[i]);
    if(!table)
    {
      ndbout_c("Could not find table: %s, skipping", argv[i]);
      continue;
    }

    BaseString name;
    name.appfmt("EV-%s", argv[i]);
    NdbDictionary::Event *myEvent= new NdbDictionary::Event(name.c_str());
    myEvent->setTable(table->getName());
    myEvent->addTableEvent(NdbDictionary::Event::TE_ALL);
    for(int a = 0; a < table->getNoOfColumns(); a++){
      myEvent->addEventColumn(a);
    }

    if (myDict->createEvent(* myEvent))
    {
      if(myDict->getNdbError().classification == NdbError::SchemaObjectExists)
      {
	g_info << "Event creation failed event exists\n";
	if (myDict->dropEvent(name.c_str()))
	{
	  g_err << "Failed to drop event: " << myDict->getNdbError() << endl;
	  result = 1;
	  goto end;
	}
	// try again
	if (myDict->createEvent(* myEvent))
	{
	  g_err << "Failed to create event: " << myDict->getNdbError() << endl;
	  result = 1;
	  goto end;
	}
      }
      else
      {
	g_err << "Failed to create event: " << myDict->getNdbError() << endl;
	result = 1;
	goto end;
      }
    }

    events.push_back(myEvent);

    NdbEventOperation* pOp = MyNdb.createEventOperation(name.c_str());
    if ( pOp == NULL ) {
      g_err << "Event operation creation failed" << endl;
      result = 1;
      goto end;
    }

    for (int a = 0; a < table->getNoOfColumns(); a++)
    {
      pOp->getValue(table->getColumn(a)->getName());
      pOp->getPreValue(table->getColumn(a)->getName());
    }
    event_ops.push_back(pOp);
  }

  for(i= 0; i<(int)event_ops.size(); i++)
  {
    if (event_ops[i]->execute())
    {
      g_err << "operation execution failed: " << event_ops[i]->getNdbError()
	    << endl;
      result = 1;
      goto end;
    }
  }

  while(true)
  {
    while(MyNdb.pollEvents(100) == 0);

    NdbEventOperation* pOp;
    while((pOp= MyNdb.nextEvent()) != 0)
    {
      if(pOp->getGCI() != last_gci)
      {
	if(cnt) ndbout_c("GCI: %lld events: %lld", last_gci, cnt);
	cnt= 1;
	last_gci= pOp->getGCI();
      }
      else
      {
	cnt++;
      }
    }
  }
end:
  return NDBT_ProgramExit(NDBT_OK);
}

template class Vector<NdbDictionary::Event*>;
template class Vector<NdbEventOperation*>;
<commit_msg>updated ndb listen_event to print more info, and to give immediate respose<commit_after>/* Copyright (C) 2003 MySQL AB

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

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

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

#include <NdbOut.hpp>
#include <NdbApi.hpp>
#include <NdbSleep.h>
#include <NDBT.hpp>
#include <HugoTransactions.hpp>
#include <getarg.h>

int
main(int argc, const char** argv){
  ndb_init();

  int _help = 0;
  const char* db = 0;

  struct getargs args[] = {
    { "database", 'd', arg_string, &db, "Database", "" },
    { "usage", '?', arg_flag, &_help, "Print help", "" }
  };
  int num_args = sizeof(args) / sizeof(args[0]);
  int optind = 0, i;
  char desc[] =
    "<tabname>+ \nThis program listen to events on specified tables\n";

  if(getarg(args, num_args, argc, argv, &optind) ||
     argv[optind] == NULL || _help) {
    arg_printusage(args, num_args, argv[0], desc);
    return NDBT_ProgramExit(NDBT_WRONGARGS);
  }

  // Connect to Ndb
  Ndb_cluster_connection con;
  if(con.connect(12, 5, 1) != 0)
  {
    return NDBT_ProgramExit(NDBT_FAILED);
  }
  Ndb MyNdb( &con, db ? db : "TEST_DB" );

  if(MyNdb.init() != 0){
    ERR(MyNdb.getNdbError());
    return NDBT_ProgramExit(NDBT_FAILED);
  }

  // Connect to Ndb and wait for it to become ready
  while(MyNdb.waitUntilReady() != 0)
    ndbout << "Waiting for ndb to become ready..." << endl;

  int result = 0;

  NdbDictionary::Dictionary *myDict = MyNdb.getDictionary();
  Vector<NdbDictionary::Event*> events;
  Vector<NdbEventOperation*> event_ops;
  for(i= optind; i<argc; i++)
  {
    const NdbDictionary::Table* table= myDict->getTable(argv[i]);
    if(!table)
    {
      ndbout_c("Could not find table: %s, skipping", argv[i]);
      continue;
    }

    BaseString name;
    name.appfmt("EV-%s", argv[i]);
    NdbDictionary::Event *myEvent= new NdbDictionary::Event(name.c_str());
    myEvent->setTable(table->getName());
    myEvent->addTableEvent(NdbDictionary::Event::TE_ALL);
    for(int a = 0; a < table->getNoOfColumns(); a++){
      myEvent->addEventColumn(a);
    }

    if (myDict->createEvent(* myEvent))
    {
      if(myDict->getNdbError().classification == NdbError::SchemaObjectExists)
      {
	g_info << "Event creation failed event exists. Removing...\n";
	if (myDict->dropEvent(name.c_str()))
	{
	  g_err << "Failed to drop event: " << myDict->getNdbError() << endl;
	  result = 1;
	  goto end;
	}
	// try again
	if (myDict->createEvent(* myEvent))
	{
	  g_err << "Failed to create event: " << myDict->getNdbError() << endl;
	  result = 1;
	  goto end;
	}
      }
      else
      {
	g_err << "Failed to create event: " << myDict->getNdbError() << endl;
	result = 1;
	goto end;
      }
    }

    events.push_back(myEvent);

    NdbEventOperation* pOp = MyNdb.createEventOperation(name.c_str());
    if ( pOp == NULL ) {
      g_err << "Event operation creation failed" << endl;
      result = 1;
      goto end;
    }

    for (int a = 0; a < table->getNoOfColumns(); a++)
    {
      pOp->getValue(table->getColumn(a)->getName());
      pOp->getPreValue(table->getColumn(a)->getName());
    }
    event_ops.push_back(pOp);
  }

  for(i= 0; i<(int)event_ops.size(); i++)
  {
    if (event_ops[i]->execute())
    {
      g_err << "operation execution failed: " << event_ops[i]->getNdbError()
	    << endl;
      result = 1;
      goto end;
    }
  }

  while(true)
  {
    while(MyNdb.pollEvents(100) == 0);

    NdbEventOperation* pOp= MyNdb.nextEvent();
    while(pOp)
    {
      Uint64 gci= pOp->getGCI();
      Uint64 cnt_i= 0, cnt_u= 0, cnt_d= 0;
      do
      {
	switch(pOp->getEventType())
	{
	case NdbDictionary::Event::TE_INSERT:
	  cnt_i++;
	  break;
	case NdbDictionary::Event::TE_DELETE:
	  cnt_d++;
	  break;
	case NdbDictionary::Event::TE_UPDATE:
	  cnt_u++;
	  break;
	default:
	  /* We should REALLY never get here. */
	  ndbout_c("Error: unknown event type");
	  abort();
	}
      } while ((pOp= MyNdb.nextEvent()) && gci == pOp->getGCI());
      ndbout_c("GCI: %lld events: %lld(I) %lld(U) %lld(D)", gci, cnt_i, cnt_u, cnt_d);
    }
  }
end:
  return NDBT_ProgramExit(NDBT_OK);
}

template class Vector<NdbDictionary::Event*>;
template class Vector<NdbEventOperation*>;
<|endoftext|>


<commit_before>#include "ToCNFAIG.h"

namespace BEEV
{

// Can it only add in the new variables somehow??
void addVariables(BBNodeManagerAIG& mgr, Cnf_Dat_t*& cnfData , ToSATBase::ASTNodeToSATVar& nodeToVar)
{
	BBNodeManagerAIG::SymbolToBBNode::const_iterator it;
	// Each symbol maps to a vector of CNF variables.
	for (it = mgr.symbolToBBNode.begin(); it != mgr.symbolToBBNode.end(); it++) {
		const ASTNode& n = it->first;
		const vector<BBNodeAIG> &b = it->second;

		const int width = (n.GetType() == BOOLEAN_TYPE) ? 1 : n.GetValueWidth();

		// INT_MAX for parts of symbols that didn't get encoded.
		vector<unsigned> v(width, ~((unsigned) 0));

		for (unsigned i = 0; i < b.size(); i++) {
			if (!b[i].IsNull()) {
				Aig_Obj_t * pObj;
				pObj = (Aig_Obj_t*) Vec_PtrEntry(mgr.aigMgr->vPis,
						b[i].symbol_index);
				v[i] = cnfData->pVarNums[pObj->Id];
			}
		}
		nodeToVar.insert(make_pair(n, v));
	}

}

// When we need abstraction refinement.
void ToCNFAIG::toCNF_renter(const BBNodeAIG& top, Cnf_Dat_t*& cnfData,
		ToSATBase::ASTNodeToSATVar& nodeToVar, BBNodeManagerAIG& mgr) {
	assert(priorCnfData != NULL);
	Aig_ObjCreatePo(mgr.aigMgr, top.n); // A new PO.

	cnfData = Cnf_DeriveSimple_Additional(mgr.aigMgr, priorCnfData);
	Cnf_DataFree(priorCnfData);
	priorCnfData = cnfData;

	addVariables( mgr,  cnfData , nodeToVar);
}

void ToCNFAIG::toCNF(const BBNodeAIG& top, Cnf_Dat_t*& cnfData,
		ToSATBase::ASTNodeToSATVar& nodeToVar,
		bool needAbsRef, BBNodeManagerAIG& mgr) {
	assert(cnfData == NULL);

	Aig_ObjCreatePo(mgr.aigMgr, top.n);
	if (!needAbsRef) {
		Aig_ManCleanup( mgr.aigMgr); // remove nodes not connected to the PO.
	}
	Aig_ManCheck( mgr.aigMgr); // check that AIG looks ok.

	assert(Aig_ManPoNum(mgr.aigMgr) == 1);

	// UseZeroes gives assertion errors.
	// Rewriting is sometimes very slow. Can it be configured to be faster?
	// What about refactoring???

	int nodeCount = mgr.aigMgr->nObjs[AIG_OBJ_AND];
	if (uf.stats_flag)
		cerr << "Nodes before AIG rewrite:" << nodeCount << endl;

	if (!needAbsRef && uf.isSet("aig_rewrite","0")) {
		Dar_LibStart();
		Aig_Man_t * pTemp;
		Dar_RwrPar_t Pars, *pPars = &Pars;
		Dar_ManDefaultRwrParams(pPars);

		// Assertion errors occur with this enabled.
		// pPars->fUseZeros = 1;

		// For mul63bit.smt2 with iterations =3 & nCutsMax = 8
		// CNF generation was taking 139 seconds, solving 10 seconds.

		// With nCutsMax =2, CNF generation takes 16 seconds, solving 10 seconds.
		// The rewriting doesn't remove as many nodes of course..
		int iterations = 3;

		for (int i = 0; i < iterations; i++) {
			mgr.aigMgr = Aig_ManDup(pTemp = mgr.aigMgr, 0);
			Aig_ManStop(pTemp);
			Dar_ManRewrite(mgr.aigMgr, pPars);

			mgr.aigMgr = Aig_ManDup(pTemp = mgr.aigMgr, 0);
			Aig_ManStop(pTemp);

			if (uf.stats_flag)
				cerr << "After rewrite [" << i << "]  nodes:"
						<< mgr.aigMgr->nObjs[AIG_OBJ_AND] << endl;

			if (nodeCount == mgr.aigMgr->nObjs[AIG_OBJ_AND])
				break;
		}
	}
	if (!needAbsRef && mgr.aigMgr->nObjs[AIG_OBJ_AND] < 2000000 && !uf.isSet("simple-cnf","0")) {
		cnfData = Cnf_Derive(mgr.aigMgr, 0);
	} else {
		cnfData = Cnf_DeriveSimple(mgr.aigMgr, 0);
	}

	BBNodeManagerAIG::SymbolToBBNode::const_iterator it;

	assert(nodeToVar.size() == 0);

	//todo. cf. with addvariables above...
	// Each symbol maps to a vector of CNF variables.
	for (it = mgr.symbolToBBNode.begin(); it != mgr.symbolToBBNode.end(); it++) {
		const ASTNode& n = it->first;
		const vector<BBNodeAIG> &b = it->second;
		assert(nodeToVar.find(n) == nodeToVar.end());

		const int width = (n.GetType() == BOOLEAN_TYPE) ? 1 : n.GetValueWidth();

		// INT_MAX for parts of symbols that didn't get encoded.
		vector<unsigned> v(width, ~((unsigned) 0));

		for (unsigned i = 0; i < b.size(); i++) {
			if (!b[i].IsNull()) {
				Aig_Obj_t * pObj;
				pObj = (Aig_Obj_t*) Vec_PtrEntry(mgr.aigMgr->vPis,
						b[i].symbol_index);
				v[i] = cnfData->pVarNums[pObj->Id];
			}
		}

		nodeToVar.insert(make_pair(n, v));
	}
	assert(cnfData != NULL);
}
};
<commit_msg>No longer default to the simple CNF generator for big AIGs, i.e >=2Million nodes. We used to do this because of a bug(?) now fixed in ABC.<commit_after>#include "ToCNFAIG.h"

namespace BEEV
{

// Can it only add in the new variables somehow??
void addVariables(BBNodeManagerAIG& mgr, Cnf_Dat_t*& cnfData , ToSATBase::ASTNodeToSATVar& nodeToVar)
{
	BBNodeManagerAIG::SymbolToBBNode::const_iterator it;
	// Each symbol maps to a vector of CNF variables.
	for (it = mgr.symbolToBBNode.begin(); it != mgr.symbolToBBNode.end(); it++) {
		const ASTNode& n = it->first;
		const vector<BBNodeAIG> &b = it->second;

		const int width = (n.GetType() == BOOLEAN_TYPE) ? 1 : n.GetValueWidth();

		// INT_MAX for parts of symbols that didn't get encoded.
		vector<unsigned> v(width, ~((unsigned) 0));

		for (unsigned i = 0; i < b.size(); i++) {
			if (!b[i].IsNull()) {
				Aig_Obj_t * pObj;
				pObj = (Aig_Obj_t*) Vec_PtrEntry(mgr.aigMgr->vPis,
						b[i].symbol_index);
				v[i] = cnfData->pVarNums[pObj->Id];
			}
		}
		nodeToVar.insert(make_pair(n, v));
	}

}

// When we need abstraction refinement.
void ToCNFAIG::toCNF_renter(const BBNodeAIG& top, Cnf_Dat_t*& cnfData,
		ToSATBase::ASTNodeToSATVar& nodeToVar, BBNodeManagerAIG& mgr) {
	assert(priorCnfData != NULL);
	Aig_ObjCreatePo(mgr.aigMgr, top.n); // A new PO.

	cnfData = Cnf_DeriveSimple_Additional(mgr.aigMgr, priorCnfData);
	Cnf_DataFree(priorCnfData);
	priorCnfData = cnfData;

	addVariables( mgr,  cnfData , nodeToVar);
}

void ToCNFAIG::toCNF(const BBNodeAIG& top, Cnf_Dat_t*& cnfData,
		ToSATBase::ASTNodeToSATVar& nodeToVar,
		bool needAbsRef, BBNodeManagerAIG& mgr) {
	assert(cnfData == NULL);

	Aig_ObjCreatePo(mgr.aigMgr, top.n);
	if (!needAbsRef) {
		Aig_ManCleanup( mgr.aigMgr); // remove nodes not connected to the PO.
	}
	Aig_ManCheck( mgr.aigMgr); // check that AIG looks ok.

	assert(Aig_ManPoNum(mgr.aigMgr) == 1);

	// UseZeroes gives assertion errors.
	// Rewriting is sometimes very slow. Can it be configured to be faster?
	// What about refactoring???

	int nodeCount = mgr.aigMgr->nObjs[AIG_OBJ_AND];
	if (uf.stats_flag)
		cerr << "Nodes before AIG rewrite:" << nodeCount << endl;

	if (!needAbsRef && uf.isSet("aig_rewrite","0")) {
		Dar_LibStart();
		Aig_Man_t * pTemp;
		Dar_RwrPar_t Pars, *pPars = &Pars;
		Dar_ManDefaultRwrParams(pPars);

		// Assertion errors occur with this enabled.
		// pPars->fUseZeros = 1;

		// For mul63bit.smt2 with iterations =3 & nCutsMax = 8
		// CNF generation was taking 139 seconds, solving 10 seconds.

		// With nCutsMax =2, CNF generation takes 16 seconds, solving 10 seconds.
		// The rewriting doesn't remove as many nodes of course..
		int iterations = 3;

		for (int i = 0; i < iterations; i++) {
			mgr.aigMgr = Aig_ManDup(pTemp = mgr.aigMgr, 0);
			Aig_ManStop(pTemp);
			Dar_ManRewrite(mgr.aigMgr, pPars);

			mgr.aigMgr = Aig_ManDup(pTemp = mgr.aigMgr, 0);
			Aig_ManStop(pTemp);

			if (uf.stats_flag)
				cerr << "After rewrite [" << i << "]  nodes:"
						<< mgr.aigMgr->nObjs[AIG_OBJ_AND] << endl;

			if (nodeCount == mgr.aigMgr->nObjs[AIG_OBJ_AND])
				break;
		}
	}
	if (!needAbsRef &&  !uf.isSet("simple-cnf","0")) {
		cnfData = Cnf_Derive(mgr.aigMgr, 0);
		if (uf.stats_flag)
		  cerr << "advanced CNF" << endl;
	} else {
		cnfData = Cnf_DeriveSimple(mgr.aigMgr, 0);
                if (uf.stats_flag)
                  cerr << "simple CNF" << endl;

	}

	BBNodeManagerAIG::SymbolToBBNode::const_iterator it;

	assert(nodeToVar.size() == 0);

	//todo. cf. with addvariables above...
	// Each symbol maps to a vector of CNF variables.
	for (it = mgr.symbolToBBNode.begin(); it != mgr.symbolToBBNode.end(); it++) {
		const ASTNode& n = it->first;
		const vector<BBNodeAIG> &b = it->second;
		assert(nodeToVar.find(n) == nodeToVar.end());

		const int width = (n.GetType() == BOOLEAN_TYPE) ? 1 : n.GetValueWidth();

		// INT_MAX for parts of symbols that didn't get encoded.
		vector<unsigned> v(width, ~((unsigned) 0));

		for (unsigned i = 0; i < b.size(); i++) {
			if (!b[i].IsNull()) {
				Aig_Obj_t * pObj;
				pObj = (Aig_Obj_t*) Vec_PtrEntry(mgr.aigMgr->vPis,
						b[i].symbol_index);
				v[i] = cnfData->pVarNums[pObj->Id];
			}
		}

		nodeToVar.insert(make_pair(n, v));
	}
	assert(cnfData != NULL);
}
};
<|endoftext|>


<commit_before>/**
 * Copyright 2013 Da Zheng
 *
 * This file is part of SA-GraphLib.
 *
 * SA-GraphLib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SA-GraphLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SA-GraphLib.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <signal.h>
#include <google/profiler.h>

#include <vector>

#include "thread.h"
#include "io_interface.h"
#include "container.h"
#include "concurrency.h"

#include "vertex_index.h"
#include "graph_engine.h"
#include "graph_config.h"

class bfs_vertex: public compute_directed_vertex
{
	enum {
		VISITED,
	};

	atomic_flags<int> flags;
public:
	bfs_vertex() {
	}

	bfs_vertex(vertex_id_t id,
			const vertex_index *index): compute_directed_vertex(id, index) {
	}

	bool has_visited() const {
		return flags.test_flag(VISITED);
	}

	bool set_visited(bool visited) {
		if (visited)
			return flags.set_flag(VISITED);
		else
			return flags.clear_flag(VISITED);
	}

	void run(vertex_program &prog) {
		if (!has_visited()) {
			directed_vertex_request req(get_id(), edge_type::OUT_EDGE);
			request_partial_vertices(&req, 1);
		}
	}

	void run(vertex_program &prog, const page_vertex &vertex);

	void run_on_message(vertex_program &prog, const vertex_message &msg) {
	}
};

void bfs_vertex::run(vertex_program &prog, const page_vertex &vertex)
{
	assert(!has_visited());
	set_visited(true);

	int num_dests = vertex.get_num_edges(OUT_EDGE);
	if (num_dests == 0)
		return;

	// We need to add the neighbors of the vertex to the queue of
	// the next level.
#ifdef USE_ARRAY
	stack_array<vertex_id_t, 1024> neighs(num_dests);
	vertex.read_edges(OUT_EDGE, neighs.data(), num_dests);
	prog.activate_vertices(neighs.data(), num_dests);
#else
	edge_seq_iterator it = vertex.get_neigh_seq_it(OUT_EDGE, 0, num_dests);
	prog.activate_vertices(it);
#endif
}

void int_handler(int sig_num)
{
	if (!graph_conf.get_prof_file().empty())
		ProfilerStop();
	exit(0);
}

void print_usage()
{
	fprintf(stderr,
			"bfs [options] conf_file graph_file index_file start_vertex\n");
	fprintf(stderr, "-c confs: add more configurations to the system\n");
	fprintf(stderr, "-p: preload the graph\n");
	graph_conf.print_help();
	params.print_help();
}

int main(int argc, char *argv[])
{
	int opt;
	std::string confs;
	int num_opts = 0;
	bool preload = false;
	while ((opt = getopt(argc, argv, "c:p")) != -1) {
		num_opts++;
		switch (opt) {
			case 'c':
				confs = optarg;
				num_opts++;
				break;
			case 'p':
				preload = true;
				break;
			default:
				print_usage();
		}
	}
	argv += 1 + num_opts;
	argc -= 1 + num_opts;

	if (argc < 4) {
		print_usage();
		exit(-1);
	}

	std::string conf_file = argv[0];
	std::string graph_file = argv[1];
	std::string index_file = argv[2];
	vertex_id_t start_vertex = atoi(argv[3]);

	config_map configs(conf_file);
	configs.add_options(confs);
	graph_conf.init(configs);
	graph_conf.print();

	signal(SIGINT, int_handler);
	init_io_system(configs);

	graph_index *index = NUMA_graph_index<bfs_vertex>::create(index_file,
			graph_conf.get_num_threads(), params.get_num_nodes());

	graph_engine *graph = graph_engine::create(graph_conf.get_num_threads(),
			params.get_num_nodes(), graph_file, index);
	if (preload)
		graph->preload_graph();
	printf("BFS starts\n");
	printf("prof_file: %s\n", graph_conf.get_prof_file().c_str());
	if (!graph_conf.get_prof_file().empty())
		ProfilerStart(graph_conf.get_prof_file().c_str());

	struct timeval start, end;
	gettimeofday(&start, NULL);
	graph->start(&start_vertex, 1);
	graph->wait4complete();
	gettimeofday(&end, NULL);

	NUMA_graph_index<bfs_vertex>::const_iterator it
		= ((NUMA_graph_index<bfs_vertex> *) index)->begin();
	NUMA_graph_index<bfs_vertex>::const_iterator end_it
		= ((NUMA_graph_index<bfs_vertex> *) index)->end();
	int num_visited = 0;
	for (; it != end_it; ++it) {
		const bfs_vertex &v = (const bfs_vertex &) *it;
		if (v.has_visited())
			num_visited++;
	}

	if (!graph_conf.get_prof_file().empty())
		ProfilerStop();
	if (graph_conf.get_print_io_stat())
		print_io_thread_stat();
	graph_engine::destroy(graph);
	destroy_io_system();
	printf("BFS from vertex %ld visits %d vertices. It takes %f seconds\n",
			(unsigned long) start_vertex, num_visited, time_diff(start, end));
}
<commit_msg>[Graph]: allow to choose traversed edges in BFS.<commit_after>/**
 * Copyright 2013 Da Zheng
 *
 * This file is part of SA-GraphLib.
 *
 * SA-GraphLib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SA-GraphLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SA-GraphLib.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <signal.h>
#include <google/profiler.h>

#include <vector>

#include "thread.h"
#include "io_interface.h"
#include "container.h"
#include "concurrency.h"

#include "vertex_index.h"
#include "graph_engine.h"
#include "graph_config.h"

edge_type traverse_edge = edge_type::OUT_EDGE;

class bfs_vertex: public compute_directed_vertex
{
	enum {
		VISITED,
	};

	atomic_flags<int> flags;
public:
	bfs_vertex() {
	}

	bfs_vertex(vertex_id_t id,
			const vertex_index *index): compute_directed_vertex(id, index) {
	}

	bool has_visited() const {
		return flags.test_flag(VISITED);
	}

	bool set_visited(bool visited) {
		if (visited)
			return flags.set_flag(VISITED);
		else
			return flags.clear_flag(VISITED);
	}

	void run(vertex_program &prog) {
		if (!has_visited()) {
			directed_vertex_request req(get_id(), traverse_edge);
			request_partial_vertices(&req, 1);
		}
	}

	void run(vertex_program &prog, const page_vertex &vertex);

	void run_on_message(vertex_program &prog, const vertex_message &msg) {
	}
};

void bfs_vertex::run(vertex_program &prog, const page_vertex &vertex)
{
	assert(!has_visited());
	set_visited(true);

	int num_dests = vertex.get_num_edges(traverse_edge);
	if (num_dests == 0)
		return;

	// We need to add the neighbors of the vertex to the queue of
	// the next level.
#ifdef USE_ARRAY
	stack_array<vertex_id_t, 1024> neighs(num_dests);
	vertex.read_edges(traverse_edge, neighs.data(), num_dests);
	prog.activate_vertices(neighs.data(), num_dests);
#else
	edge_seq_iterator it = vertex.get_neigh_seq_it(traverse_edge, 0, num_dests);
	prog.activate_vertices(it);
#endif
}

void int_handler(int sig_num)
{
	if (!graph_conf.get_prof_file().empty())
		ProfilerStop();
	exit(0);
}

void print_usage()
{
	fprintf(stderr,
			"bfs [options] conf_file graph_file index_file start_vertex\n");
	fprintf(stderr, "-c confs: add more configurations to the system\n");
	fprintf(stderr, "-p: preload the graph\n");
	fprintf(stderr, "-b: traverse with both in-edges and out-edges\n");
	graph_conf.print_help();
	params.print_help();
}

int main(int argc, char *argv[])
{
	int opt;
	std::string confs;
	int num_opts = 0;
	bool preload = false;
	while ((opt = getopt(argc, argv, "c:pb")) != -1) {
		num_opts++;
		switch (opt) {
			case 'c':
				confs = optarg;
				num_opts++;
				break;
			case 'p':
				preload = true;
				break;
			case 'b':
				traverse_edge = edge_type::BOTH_EDGES;
				break;
			default:
				print_usage();
		}
	}
	argv += 1 + num_opts;
	argc -= 1 + num_opts;

	if (argc < 4) {
		print_usage();
		exit(-1);
	}

	std::string conf_file = argv[0];
	std::string graph_file = argv[1];
	std::string index_file = argv[2];
	vertex_id_t start_vertex = atoi(argv[3]);

	config_map configs(conf_file);
	configs.add_options(confs);
	graph_conf.init(configs);
	graph_conf.print();

	signal(SIGINT, int_handler);
	init_io_system(configs);

	graph_index *index = NUMA_graph_index<bfs_vertex>::create(index_file,
			graph_conf.get_num_threads(), params.get_num_nodes());

	graph_engine *graph = graph_engine::create(graph_conf.get_num_threads(),
			params.get_num_nodes(), graph_file, index);
	if (preload)
		graph->preload_graph();
	printf("BFS starts\n");
	printf("prof_file: %s\n", graph_conf.get_prof_file().c_str());
	if (!graph_conf.get_prof_file().empty())
		ProfilerStart(graph_conf.get_prof_file().c_str());

	struct timeval start, end;
	gettimeofday(&start, NULL);
	graph->start(&start_vertex, 1);
	graph->wait4complete();
	gettimeofday(&end, NULL);

	NUMA_graph_index<bfs_vertex>::const_iterator it
		= ((NUMA_graph_index<bfs_vertex> *) index)->begin();
	NUMA_graph_index<bfs_vertex>::const_iterator end_it
		= ((NUMA_graph_index<bfs_vertex> *) index)->end();
	int num_visited = 0;
	for (; it != end_it; ++it) {
		const bfs_vertex &v = (const bfs_vertex &) *it;
		if (v.has_visited())
			num_visited++;
	}

	if (!graph_conf.get_prof_file().empty())
		ProfilerStop();
	if (graph_conf.get_print_io_stat())
		print_io_thread_stat();
	graph_engine::destroy(graph);
	destroy_io_system();
	printf("BFS from vertex %ld visits %d vertices. It takes %f seconds\n",
			(unsigned long) start_vertex, num_visited, time_diff(start, end));
}
<|endoftext|>