<commit_before>#include <cassert>
#include <fstream>
#include <iostream>
#include <memory>
#include <set>
#include <string>

#include <gemmi/cif.hpp>
#include <gemmi/mmcif.hpp>

#define GEMMI_WRITE_IMPLEMENTATION
#include <gemmi/to_mmcif.hpp>
#undef GEMMI_WRITE_IMPLEMENTATION

#include "cif.hh"
#include "freesasa.h"

struct ModelDiscriminator {
    ModelDiscriminator(const std::string &model_name,
                       const int model_col = 11)
        : _model_name(model_name), _model_col(model_col)
    {
    }

    bool operator()(const gemmi::cif::Table::Row &site) const
    {
        return _model_name != site[_model_col];
    }

private:
    const std::string _model_name;
    int _model_col;
};

struct ModelSetDiscriminator {
    ModelSetDiscriminator(const std::set<int> models,
                          const int model_col = 11)
        : _models(models), _model_col(model_col)
    {
    }

    bool operator()(const gemmi::cif::Table::Row &site) const
    {
        return _models.count(std::stoi(site[_model_col])) == 0;
    }

private:
    const std::set<int> _models;
    int _model_col;
};

struct ChainDiscriminator {
    ChainDiscriminator(const std::string &model_name, const std::string &chain_name,
                       const int model_col = 11, const int chain_col = 1)
        : _model_name(model_name), _chain_name(chain_name),
          _model_col(model_col), _chain_col(chain_col)
    {
    }

    bool operator()(const gemmi::cif::Table::Row &site) const
    {
        return _model_name != site[_model_col] || _chain_name != site[_chain_col];
    }

private:
    const std::string _model_name, _chain_name;
    int _model_col, _chain_col;
};

static std::unique_ptr<std::set<int>>
get_models(const gemmi::cif::Document &doc)
{
    auto models = std::make_unique<std::set<int>>();
    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", {"pdbx_PDB_model_num"})) {
            models->insert(gemmi::cif::as_int(site[0]));
        }
    }
    return models;
}

static std::unique_ptr<std::set<std::string>>
get_chains(const gemmi::cif::Document &doc)
{
    auto chains = std::make_unique<std::set<std::string>>();
    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", {"auth_asym_id"})) {
            chains->insert(site[0]);
        }
    }
    return chains;
}

static std::unique_ptr<std::set<std::string>>
get_chains(const gemmi::Model &model)
{
    auto chains = std::make_unique<std::set<std::string>>();

    for (auto &chain : model.chains) {
        chains->insert(chain.name);
    }

    return chains;
}

static const auto atom_site_columns = std::vector<std::string>({
    "group_PDB",
    "auth_asym_id",
    "auth_seq_id",
    "pdbx_PDB_ins_code",
    "auth_comp_id",
    "auth_atom_id",
    "label_alt_id",
    "type_symbol",
    "Cartn_x",
    "Cartn_y",
    "Cartn_z",
    "pdbx_PDB_model_num",
});

static freesasa_cif_atom
freesasa_atom_from_site(const gemmi::cif::Table::Row &site)
{

    std::unique_ptr<std::string> auth_atom_id;
    // remove quotation marks if necessary
    if (site[5][0] == '"') {
        auth_atom_id = std::make_unique<std::string>(site[5].substr(1, site[5].size() - 2));
    }

    return {
        .group_PDB = site[0].c_str(),
        .auth_asym_id = site[1][0],
        .auth_seq_id = site[2].c_str(),
        .pdbx_PDB_ins_code = site[3].c_str(),
        .auth_comp_id = site[4].c_str(),
        .auth_atom_id = auth_atom_id ? std::move(*auth_atom_id).c_str() : site[5].c_str(),
        .label_alt_id = site[6].c_str(),
        .type_symbol = site[7].c_str(),
        .Cartn_x = atof(site[8].c_str()),
        .Cartn_y = atof(site[9].c_str()),
        .Cartn_z = atof(site[10].c_str())};
}

template <typename T>
static freesasa_structure *
freesasa_structure_from_pred(const gemmi::cif::Document &doc,
                             const T &discriminator,
                             const freesasa_classifier *classifier,
                             int structure_options)
{
    freesasa_structure *structure = freesasa_structure_new();
<<<<<<< HEAD
    std::string auth_atom_id;
    char prevAltId = '.';
=======
    // std::string auth_atom_id;  // Should be deleted due to refactoring.
>>>>>>> 59a514a... Successfully parsing tree structure and input cif file; matching tree atom to cif atom.

    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", atom_site_columns)) {
            if (site[0] != "ATOM" && !(structure_options & FREESASA_INCLUDE_HETATM)) {
                continue;
            }

            if (discriminator(site)) continue;

            freesasa_cif_atom atom = freesasa_atom_from_site(site);

            if (!(structure_options & FREESASA_INCLUDE_HYDROGEN) && std::string(atom.type_symbol) == "H") {
                continue;
            }

            // Pick the first alternative conformation for an atom
            auto currentAltId = site[6][0];
            if ((currentAltId != '.' && prevAltId == '.') || currentAltId == '.') {
                prevAltId = currentAltId;
            } else if (currentAltId != '.' && currentAltId != prevAltId) {
                continue;
            }

            freesasa_structure_add_cif_atom(structure, &atom, classifier, structure_options);
        }
    }
    return structure;
}

freesasa_structure *
freesasa_structure_from_cif(std::FILE *input,
                            const freesasa_classifier *classifier,
                            int structure_options)
{
    const auto doc = gemmi::cif::read_cstream(input, 8192, "cif-input");
    const auto models = get_models(doc);

    std::unique_ptr<const ModelSetDiscriminator> discriminator;
    if (structure_options & FREESASA_JOIN_MODELS) {
        discriminator = std::make_unique<const ModelSetDiscriminator>(std::move(*models));
    } else {
        auto firstModel = models->begin();
        auto singleModel = std::set<int>{*firstModel};
        discriminator = std::make_unique<const ModelSetDiscriminator>(singleModel);
    }
    return freesasa_structure_from_pred(doc, *discriminator, classifier, structure_options);
}

freesasa_structure *
freesasa_structure_from_model(const gemmi::cif::Document &doc,
                              const std::string &model_name,
                              const freesasa_classifier *classifier,
                              int structure_options)
{
    const ModelDiscriminator discriminator(model_name);
    return freesasa_structure_from_pred(doc, discriminator, classifier, structure_options);
    freesasa_structure *structure = freesasa_structure_new();
}

freesasa_structure *
freesasa_structure_from_chain(const gemmi::cif::Document doc,
                              const std::string &model_name,
                              const std::string &chain_name,
                              const freesasa_classifier *classifier,
                              int structure_options)
{
    const ChainDiscriminator discriminator(model_name, chain_name);
    return freesasa_structure_from_pred(doc, discriminator, classifier, structure_options);
}

std::vector<freesasa_structure *>
freesasa_cif_structure_array(std::FILE *input,
                             int *n,
                             const freesasa_classifier *classifier,
                             int options)
{
    int n_models = 0, n_chains = 0;

    std::vector<freesasa_structure *> ss;

    const auto doc = gemmi::cif::read_cstream(input, 8192, "cif-input");

    gemmi::Structure gemmi_struct = gemmi::make_structure_from_block(doc.blocks[0]);

    const auto models = gemmi_struct.models;

    n_models = models.size();

    /* only keep first model if option not provided */
    if (!(options & FREESASA_SEPARATE_MODELS)) n_models = 1;

    /* for each model read chains if requested */
    if (options & FREESASA_SEPARATE_CHAINS) {
        for (int i = 0; i < n_models; ++i) {
            auto chain_names = get_chains(models[i]);
            int n_new_chains = chain_names->size();
            n_chains += n_new_chains;

            if (n_new_chains == 0) {
                freesasa_warn("in %s(): no chains found (in model %s)", __func__, models[i].name.c_str());
                continue;
            }

            ss.reserve(n_new_chains);
            for (auto &chain_name : *chain_names) {
                ss.emplace_back(
                    freesasa_structure_from_chain(doc, models[i].name, chain_name, classifier, options));
                freesasa_structure_set_model(ss.back(), i + 1);
            }
        }
        if (n_chains == 0) freesasa_fail("In %s(): No chains in any model in protein: %s.", __func__, gemmi_struct.name.c_str());
        *n = n_chains;
    } else {
        ss.reserve(n_models);
        for (int i = 0; i < n_models; ++i) {
            ss.emplace_back(
                freesasa_structure_from_model(doc, models[i].name, classifier, options));
            freesasa_structure_set_model(ss.back(), i + 1);
        }
        *n = n_models;
    }
    return ss;
}

struct freesasa_MCRA{

    freesasa_MCRA(const int model, const std::string &chain, const std::string &residue, const std::string &res_num, const std::string &atom)
    : _model(model), _chain(chain), _residue(residue), _res_num(res_num), _atom(atom)
    {}

    int find_row(gemmi::cif::Table &table) const {
        unsigned idx = 0;
        for (auto site : table) {
            if ((*this)(site)) {
                return idx;
            }
            ++idx;
        }
        return -1;
    }

    friend std::ostream& operator << (std::ostream& os, const freesasa_MCRA& mcra){
        os << "Atom(" << mcra._model << " " << mcra._chain << " "  << mcra._residue << " [" << mcra._res_num << "] " << mcra._atom << ")";
        return os;
    }

private:
    bool operator () (const gemmi::cif::Table::Row &site) const {

        int model                  = std::stoul(site[11]);
        const std::string &chain   = site[1];
        const std::string &residue = site[4];
        const std::string &res_num = site[2];
        const std::string &atom    = site[5][0] != '"' ? site[5] : site[5].substr(1, site[5].size() - 2);

        if (_model == model){
            if (_chain == chain){
                if (_res_num == res_num && _residue == residue){
                    if (_atom == atom) {
                        return true;
                    }
                }
            }
        }
        return false;

    }

    const int _model;
    const std::string &_chain, &_residue, &_res_num,&_atom;
};

int freesasa_write_cif(std::FILE *output,
                       freesasa_node *root,
                       int options)
{
    freesasa_node *result{freesasa_node_children(root)};
    freesasa_node *structure;

    assert(output);
    assert(root);
    assert(freesasa_node_type(root) == FREESASA_NODE_ROOT);

    std::string inp_file{freesasa_node_name(result)};
    std::string out_file = inp_file.substr(0, inp_file.find_last_of(".")) + ".sasa.cif";

    std::cout << "Input file: " << inp_file << std::endl << "Output File: " << out_file << std::endl;

    const auto doc = gemmi::cif::read_file(inp_file);

    auto block = doc.sole_block();

    auto table = block.find("_atom_site.", atom_site_columns);

    while (result) {
        structure = freesasa_node_children(result);
        while (structure) {
            auto model = freesasa_node_structure_model(structure);
            auto chain = freesasa_node_children(structure);
            while (chain) {
                auto cName = freesasa_node_name(chain);
                auto residue = freesasa_node_children(chain);
                while (residue) {
                    auto rName = freesasa_node_name(residue);
                    auto rNum  = freesasa_node_residue_number(residue);
                    auto atom = freesasa_node_children(residue);
                    while (atom) {
                        auto aName   = freesasa_node_name(atom);
                        auto area    = freesasa_node_area(atom);
                        auto radius  = freesasa_node_atom_radius(atom);

                        int  rowNum = freesasa_MCRA{model, cName, rName, rNum, aName}.find_row(table);
                        // if (rowNum != -1) std::cout << "Found row: " << rowNum << std::endl;
                        // else {
                        //     std::cout << "Did not find row for " << freesasa_MCRA{model, cName, rName, rNum, aName} << std::endl;
                        //     exit(1);
                        // }
                        atom = freesasa_node_next(atom);
                    }
                    auto last_res_name = freesasa_node_name(residue);
                    auto last_res_number = freesasa_node_residue_number(residue);
                    residue = freesasa_node_next(residue);
                }
                auto last_chain = freesasa_node_name(chain);
                chain = freesasa_node_next(chain);
                std::cout << "Finished chain: " << cName << std::endl;
            }
            structure = freesasa_node_next(structure);
        }
        result = freesasa_node_next(result);
    }
    return FREESASA_SUCCESS;
}
<commit_msg>Sped up CIF atom search by not searching all rows for every freesasa tree node.<commit_after>#include <cassert>
#include <fstream>
#include <iostream>
#include <memory>
#include <set>
#include <string>

#include <gemmi/cif.hpp>
#include <gemmi/mmcif.hpp>

#define GEMMI_WRITE_IMPLEMENTATION
#include <gemmi/to_mmcif.hpp>
#undef GEMMI_WRITE_IMPLEMENTATION

#include "cif.hh"
#include "freesasa.h"

struct ModelDiscriminator {
    ModelDiscriminator(const std::string &model_name,
                       const int model_col = 11)
        : _model_name(model_name), _model_col(model_col)
    {
    }

    bool operator()(const gemmi::cif::Table::Row &site) const
    {
        return _model_name != site[_model_col];
    }

private:
    const std::string _model_name;
    int _model_col;
};

struct ModelSetDiscriminator {
    ModelSetDiscriminator(const std::set<int> models,
                          const int model_col = 11)
        : _models(models), _model_col(model_col)
    {
    }

    bool operator()(const gemmi::cif::Table::Row &site) const
    {
        return _models.count(std::stoi(site[_model_col])) == 0;
    }

private:
    const std::set<int> _models;
    int _model_col;
};

struct ChainDiscriminator {
    ChainDiscriminator(const std::string &model_name, const std::string &chain_name,
                       const int model_col = 11, const int chain_col = 1)
        : _model_name(model_name), _chain_name(chain_name),
          _model_col(model_col), _chain_col(chain_col)
    {
    }

    bool operator()(const gemmi::cif::Table::Row &site) const
    {
        return _model_name != site[_model_col] || _chain_name != site[_chain_col];
    }

private:
    const std::string _model_name, _chain_name;
    int _model_col, _chain_col;
};

static std::unique_ptr<std::set<int>>
get_models(const gemmi::cif::Document &doc)
{
    auto models = std::make_unique<std::set<int>>();
    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", {"pdbx_PDB_model_num"})) {
            models->insert(gemmi::cif::as_int(site[0]));
        }
    }
    return models;
}

static std::unique_ptr<std::set<std::string>>
get_chains(const gemmi::cif::Document &doc)
{
    auto chains = std::make_unique<std::set<std::string>>();
    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", {"auth_asym_id"})) {
            chains->insert(site[0]);
        }
    }
    return chains;
}

static std::unique_ptr<std::set<std::string>>
get_chains(const gemmi::Model &model)
{
    auto chains = std::make_unique<std::set<std::string>>();

    for (auto &chain : model.chains) {
        chains->insert(chain.name);
    }

    return chains;
}

static const auto atom_site_columns = std::vector<std::string>({
    "group_PDB",
    "auth_asym_id",
    "auth_seq_id",
    "pdbx_PDB_ins_code",
    "auth_comp_id",
    "auth_atom_id",
    "label_alt_id",
    "type_symbol",
    "Cartn_x",
    "Cartn_y",
    "Cartn_z",
    "pdbx_PDB_model_num",
});

static freesasa_cif_atom
freesasa_atom_from_site(const gemmi::cif::Table::Row &site)
{

    std::unique_ptr<std::string> auth_atom_id;
    // remove quotation marks if necessary
    if (site[5][0] == '"') {
        auth_atom_id = std::make_unique<std::string>(site[5].substr(1, site[5].size() - 2));
    }

    return {
        .group_PDB = site[0].c_str(),
        .auth_asym_id = site[1][0],
        .auth_seq_id = site[2].c_str(),
        .pdbx_PDB_ins_code = site[3].c_str(),
        .auth_comp_id = site[4].c_str(),
        .auth_atom_id = auth_atom_id ? std::move(*auth_atom_id).c_str() : site[5].c_str(),
        .label_alt_id = site[6].c_str(),
        .type_symbol = site[7].c_str(),
        .Cartn_x = atof(site[8].c_str()),
        .Cartn_y = atof(site[9].c_str()),
        .Cartn_z = atof(site[10].c_str())};
}

template <typename T>
static freesasa_structure *
freesasa_structure_from_pred(const gemmi::cif::Document &doc,
                             const T &discriminator,
                             const freesasa_classifier *classifier,
                             int structure_options)
{
    freesasa_structure *structure = freesasa_structure_new();
<<<<<<< HEAD
    std::string auth_atom_id;
    char prevAltId = '.';
=======
    // std::string auth_atom_id;  // Should be deleted due to refactoring.
>>>>>>> 59a514a... Successfully parsing tree structure and input cif file; matching tree atom to cif atom.

    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", atom_site_columns)) {
            if (site[0] != "ATOM" && !(structure_options & FREESASA_INCLUDE_HETATM)) {
                continue;
            }

            if (discriminator(site)) continue;

            freesasa_cif_atom atom = freesasa_atom_from_site(site);

            if (!(structure_options & FREESASA_INCLUDE_HYDROGEN) && std::string(atom.type_symbol) == "H") {
                continue;
            }

            // Pick the first alternative conformation for an atom
            auto currentAltId = site[6][0];
            if ((currentAltId != '.' && prevAltId == '.') || currentAltId == '.') {
                prevAltId = currentAltId;
            } else if (currentAltId != '.' && currentAltId != prevAltId) {
                continue;
            }

            freesasa_structure_add_cif_atom(structure, &atom, classifier, structure_options);
        }
    }
    return structure;
}

freesasa_structure *
freesasa_structure_from_cif(std::FILE *input,
                            const freesasa_classifier *classifier,
                            int structure_options)
{
    const auto doc = gemmi::cif::read_cstream(input, 8192, "cif-input");
    const auto models = get_models(doc);

    std::unique_ptr<const ModelSetDiscriminator> discriminator;
    if (structure_options & FREESASA_JOIN_MODELS) {
        discriminator = std::make_unique<const ModelSetDiscriminator>(std::move(*models));
    } else {
        auto firstModel = models->begin();
        auto singleModel = std::set<int>{*firstModel};
        discriminator = std::make_unique<const ModelSetDiscriminator>(singleModel);
    }
    return freesasa_structure_from_pred(doc, *discriminator, classifier, structure_options);
}

freesasa_structure *
freesasa_structure_from_model(const gemmi::cif::Document &doc,
                              const std::string &model_name,
                              const freesasa_classifier *classifier,
                              int structure_options)
{
    const ModelDiscriminator discriminator(model_name);
    return freesasa_structure_from_pred(doc, discriminator, classifier, structure_options);
    freesasa_structure *structure = freesasa_structure_new();
}

freesasa_structure *
freesasa_structure_from_chain(const gemmi::cif::Document doc,
                              const std::string &model_name,
                              const std::string &chain_name,
                              const freesasa_classifier *classifier,
                              int structure_options)
{
    const ChainDiscriminator discriminator(model_name, chain_name);
    return freesasa_structure_from_pred(doc, discriminator, classifier, structure_options);
}

std::vector<freesasa_structure *>
freesasa_cif_structure_array(std::FILE *input,
                             int *n,
                             const freesasa_classifier *classifier,
                             int options)
{
    int n_models = 0, n_chains = 0;

    std::vector<freesasa_structure *> ss;

    const auto doc = gemmi::cif::read_cstream(input, 8192, "cif-input");

    gemmi::Structure gemmi_struct = gemmi::make_structure_from_block(doc.blocks[0]);

    const auto models = gemmi_struct.models;

    n_models = models.size();

    /* only keep first model if option not provided */
    if (!(options & FREESASA_SEPARATE_MODELS)) n_models = 1;

    /* for each model read chains if requested */
    if (options & FREESASA_SEPARATE_CHAINS) {
        for (int i = 0; i < n_models; ++i) {
            auto chain_names = get_chains(models[i]);
            int n_new_chains = chain_names->size();
            n_chains += n_new_chains;

            if (n_new_chains == 0) {
                freesasa_warn("in %s(): no chains found (in model %s)", __func__, models[i].name.c_str());
                continue;
            }

            ss.reserve(n_new_chains);
            for (auto &chain_name : *chain_names) {
                ss.emplace_back(
                    freesasa_structure_from_chain(doc, models[i].name, chain_name, classifier, options));
                freesasa_structure_set_model(ss.back(), i + 1);
            }
        }
        if (n_chains == 0) freesasa_fail("In %s(): No chains in any model in protein: %s.", __func__, gemmi_struct.name.c_str());
        *n = n_chains;
    } else {
        ss.reserve(n_models);
        for (int i = 0; i < n_models; ++i) {
            ss.emplace_back(
                freesasa_structure_from_model(doc, models[i].name, classifier, options));
            freesasa_structure_set_model(ss.back(), i + 1);
        }
        *n = n_models;
    }
    return ss;
}

struct freesasa_MCRA{

    freesasa_MCRA(const int model, const std::string &chain, const std::string &residue, const std::string &res_num, const std::string &atom)
    : _model(model), _chain(chain), _residue(residue), _res_num(res_num), _atom(atom)
    {}

    int find_row(gemmi::cif::Table &table, int start_idx=0) const {
        int idx = start_idx, total_rows = table.length();

        assert(idx < total_rows);

        while (idx < total_rows - 1){
            if ((*this)(table[idx])) {
                return idx;
            }
            ++idx;
        }

        std::cout << "Did not find row for: " << *this << std::endl;
        std::cout << "Looping through entire table... " << std::endl;

        idx = 0;
        for (auto site : table) {
            if ((*this)(site)) {
                return idx;
            }
            ++idx;
        }
        std::cout << "Still couldnt find: " << *this << std::endl;
        return -1;
    }

    friend std::ostream& operator << (std::ostream& os, const freesasa_MCRA& mcra){
        os << "Atom(" << mcra._model << " " << mcra._chain << " "  << mcra._residue << " [" << mcra._res_num << "] " << mcra._atom << ")";
        return os;
    }

private:
    bool operator () (const gemmi::cif::Table::Row &site) const {

        int model                  = std::stoul(site[11]);
        const std::string &chain   = site[1];
        const std::string &residue = site[4];
        const std::string &res_num = site[2];
        const std::string &atom    = site[5][0] != '"' ? site[5] : site[5].substr(1, site[5].size() - 2);

        if (_model == model){
            if (_chain == chain){
                if (_res_num == res_num && _residue == residue){
                    if (_atom == atom) {
                        // std::cout << "Found! " << *this << std::endl;
                        return true;
                    }
                }
            }
        }
        return false;

    }

    const int _model;
    const std::string &_chain, &_residue, &_res_num,&_atom;
};

int freesasa_write_cif(std::FILE *output,
                       freesasa_node *root,
                       int options)
{
    freesasa_node *result{freesasa_node_children(root)};
    freesasa_node *structure;

    assert(output);
    assert(root);
    assert(freesasa_node_type(root) == FREESASA_NODE_ROOT);

    std::string inp_file{freesasa_node_name(result)};
    std::string out_file = inp_file.substr(0, inp_file.find_last_of(".")) + ".sasa.cif";
    std::cout << "Input file: " << inp_file << std::endl << "Output File: " << out_file << std::endl;

    const auto doc = gemmi::cif::read_file(inp_file);
    auto block     = doc.sole_block();
    auto table     = block.find("_atom_site.", atom_site_columns);
    std::cout << "Number of rows in the table: " << table.length() << std::endl;

    while (result) {
        structure = freesasa_node_children(result);
        std::cout << "New Result!" << std::endl;
        while (structure) {
            int rowNum = 0, idx = 0;
            auto model = freesasa_node_structure_model(structure);
            auto chain = freesasa_node_children(structure);
            std::cout << "New Structure!" << std::endl;
            while (chain) {
                auto cName = freesasa_node_name(chain);
                auto residue = freesasa_node_children(chain);
                while (residue) {
                    auto rName = freesasa_node_name(residue);
                    auto rNum  = freesasa_node_residue_number(residue);
                    auto atom = freesasa_node_children(residue);
                    while (atom) {
                        auto aName   = freesasa_node_name(atom);
                        auto area    = freesasa_node_area(atom);
                        auto radius  = freesasa_node_atom_radius(atom);

                        idx = freesasa_MCRA{model, cName, rName, rNum, aName}.find_row(table, rowNum);
                        rowNum = idx != -1 ? idx : rowNum;
                        if (idx == -1) exit(1);

                        atom = freesasa_node_next(atom);
                    }
                    auto last_res_name = freesasa_node_name(residue);
                    auto last_res_number = freesasa_node_residue_number(residue);
                    residue = freesasa_node_next(residue);
                }
                auto last_chain = freesasa_node_name(chain);
                chain = freesasa_node_next(chain);
                std::cout << "Finished chain: " << cName << std::endl;
            }
            structure = freesasa_node_next(structure);
        }
        result = freesasa_node_next(result);
    }
    return FREESASA_SUCCESS;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctime>
#include "Timer.h"

using namespace std;

int main( int argc, char *argv[] ){
	// if not enough arguments then exit
	if ( argc < 3 ) {
		cout << "Error! Not enough arguments." << endl;
		exit(1);
	}
	// if optional flag is passed in
	if ( argc == 4 ){

		Timer one;
		double oneusrTime;
		double onewallTime;
		double onesysTime;
		one.start();
		//=======================FIRST ONE=============================
		cout << "Using istream and ostream" << endl;
		//Open file
		ifstream fin(argv[1]);
		if(!fin.is_open()){
			cout << "Error opening source file" << endl;
			exit(1);
		}
		ifstream fcheck(argv[2]);
		if(fcheck.is_open()){
			cout << "Error! Dest file already exists!" << endl;
			exit(1);
		}
		ofstream fout(argv[2]);

		char c;
		while (fin.get(c)){
			fout.put(c);
		}
		fin.close();
		fout.close();
		one.elapsedTime(onewallTime, oneusrTime, onesysTime);
                cout << "First Method: " << endl;
                cout << "\tWall time: " << onewallTime << endl;
		cout << "\tUser time: " << oneusrTime << endl;
	        cout << "\tSystem time: " << onesysTime << endl << endl;

		//=========================SECOND ONE===========================
		cout << "Using read() and write()" << endl;
		Timer two;
		double twousr;
		double twowall;
		double twosys;
		two.start();
		int fdnew;
		int fdold;
		if(-1 == (fdnew = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)))
		{
			perror("Open");
			exit(1);
		}
		if(-1 == (fdold = open(argv[1], O_RDONLY)))
		{
			perror("Open");
			exit(1);
		}
		int size;
		char d;
		if(-1 == (size = read(fdold, &d, 1)))
		{
			perror("Write");
			exit(1);
		}
		while(size > 0)
		{
			if(-1 == write(fdnew,&d,size))
			{
				perror("write");
				exit(1);
			}
			if(-1 == (size = read(fdold,&d,1)))
			{
				perror("read");
				exit(1);
			}
		}
		if(-1 == close(fdnew))
		{
			perror("close");
			exit(1);
		}
		if(-1 == close(fdold))
		{
			perror("close");
			exit(1);
		}
		two.elapsedTime(twowall,twousr,twosys);
		cout << "Second Method: " << endl;
		cout << "\tWall time: " << twowall << endl;
		cout << "\tUser time: " << twousr << endl;
		cout << "\tSystem time: " << twosys << endl << endl;

		//==========================THIRD ONE==============================
		cout << "Using read() and write() W/ Buffer" << endl;
		//int fdnew;
		//int fdold;
		Timer three;
                double threeusr;
                double threewall;
                double threesys;
                three.start();

		if(-1 == (fdnew = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)))
		{
			perror("Open");
			exit(1);
		}
		if(-1 == (fdold = open(argv[1], O_RDONLY)))
		{
			perror("Open");
			exit(1);
		}
//		int size;
		char e[BUFSIZ];
		if(-1 == (size = read(fdold, e, sizeof(e))))
		{
			perror("Write");
			exit(1);
		}
		while(size > 0)
		{
			if(-1 == write(fdnew,e,size))
			{
				perror("write");
				exit(1);
			}
			if(-1 == (size = read(fdold,e,sizeof(e))))
			{
				perror("read");
				exit(1);
			}
		}
		if(-1 == close(fdnew))
		{
			perror("close");
			exit(1);
		}
		if(-1 == close(fdold))
		{
			perror("close");
			exit(1);
		}

		three.elapsedTime(threewall,threeusr,threesys);
                cout << "Third Method: " << endl;
                cout << "\tWall time: " << threewall << endl;
                cout << "\tUser time: " << threeusr << endl;
                cout << "\tSystem time: " << threesys << endl << endl;

	}
	// else run fastest one
	else{

		cout << "Using read() and write() W/ Buffer" << endl;
		int fdnew;
		int fdold;
		if(-1 == (fdnew = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)))
		{
			perror("Open");
			exit(1);
		}
		if(-1 == (fdold = open(argv[1], O_RDONLY)))
		{
			perror("Open");
			exit(1);
		}
		int size;
		char c[BUFSIZ];
		if(-1 == (size = read(fdold, c, sizeof(c))))
		{
			perror("Write");
			exit(1);
		}
		while(size > 0)
		{
			if(-1 == write(fdnew,c,size))
			{
				perror("write");
				exit(1);
			}
			if(-1 == (size = read(fdold,c,sizeof(c))))
			{
				perror("read");
				exit(1);
			}
		}
		if(-1 == close(fdnew))
		{
			perror("close");
			exit(1);
		}
		if(-1 == close(fdold))
		{
			perror("close");
			exit(1);
		}

	}
	return 0;
}
<commit_msg>fixed something<commit_after>#include <iostream>
#include <fstream>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctime>
#include "Timer.h"
using namespace std;

int main( int argc, char *argv[] ){
	// if not enough arguments then exit
	if ( argc < 3 ) {
		cout << "Error! Not enough arguments." << endl;
		exit(1);
	}
	// if optional flag is passed in
	if ( argc == 4 ){

		Timer one;
		double oneusrTime;
		double onewallTime;
		double onesysTime;
		one.start();
		//=======================FIRST ONE=============================
		cout << "Using istream and ostream" << endl;
		//Open file
		ifstream fin(argv[1]);
		if(!fin.is_open()){
			cout << "Error opening source file" << endl;
			exit(1);
		}
		ifstream fcheck(argv[2]);
		if(fcheck.is_open()){
			cout << "Error! Dest file already exists!" << endl;
			exit(1);
		}
		ofstream fout(argv[2]);

		char c;
		while (fin.get(c)){
			fout.put(c);
		}
		fin.close();
		fout.close();
		one.elapsedTime(onewallTime, oneusrTime, onesysTime);
                cout << "First Method: " << endl;
                cout << "\tWall time: " << onewallTime << endl;
		cout << "\tUser time: " << oneusrTime << endl;
	        cout << "\tSystem time: " << onesysTime << endl << endl;

		//=========================SECOND ONE===========================
		cout << "Using read() and write()" << endl;
		Timer two;
		double twousr;
		double twowall;
		double twosys;
		two.start();
		int fdnew;
		int fdold;
		if(-1 == (fdnew = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)))
		{
			perror("Open");
			exit(1);
		}
		if(-1 == (fdold = open(argv[1], O_RDONLY)))
		{
			perror("Open");
			exit(1);
		}
		int size;
		char d;
		if(-1 == (size = read(fdold, &d, 1)))
		{
			perror("Write");
			exit(1);
		}
		while(size > 0)
		{
			if(-1 == write(fdnew,&d,size))
			{
				perror("write");
				exit(1);
			}
			if(-1 == (size = read(fdold,&d,1)))
			{
				perror("read");
				exit(1);
			}
		}
		if(-1 == close(fdnew))
		{
			perror("close");
			exit(1);
		}
		if(-1 == close(fdold))
		{
			perror("close");
			exit(1);
		}
		two.elapsedTime(twowall,twousr,twosys);
		cout << "Second Method: " << endl;
		cout << "\tWall time: " << twowall << endl;
		cout << "\tUser time: " << twousr << endl;
		cout << "\tSystem time: " << twosys << endl << endl;

		//==========================THIRD ONE==============================
		cout << "Using read() and write() W/ Buffer" << endl;
		//int fdnew;
		//int fdold;
		Timer three;
                double threeusr;
                double threewall;
                double threesys;
                three.start();

		if(-1 == (fdnew = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)))
		{
			perror("Open");
			exit(1);
		}
		if(-1 == (fdold = open(argv[1], O_RDONLY)))
		{
			perror("Open");
			exit(1);
		}
//		int size;
		char e[BUFSIZ];
		if(-1 == (size = read(fdold, e, sizeof(e))))
		{
			perror("Write");
			exit(1);
		}
		while(size > 0)
		{
			if(-1 == write(fdnew,e,size))
			{
				perror("write");
				exit(1);
			}
			if(-1 == (size = read(fdold,e,sizeof(e))))
			{
				perror("read");
				exit(1);
			}
		}
		if(-1 == close(fdnew))
		{
			perror("close");
			exit(1);
		}
		if(-1 == close(fdold))
		{
			perror("close");
			exit(1);
		}

		three.elapsedTime(threewall,threeusr,threesys);
                cout << "Third Method: " << endl;
                cout << "\tWall time: " << threewall << endl;
                cout << "\tUser time: " << threeusr << endl;
                cout << "\tSystem time: " << threesys << endl << endl;

	}
	// else run fastest one
	else{

		cout << "Using read() and write() W/ Buffer" << endl;
		int fdnew;
		int fdold;
		if(-1 == (fdnew = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)))
		{
			perror("Open");
			exit(1);
		}
		if(-1 == (fdold = open(argv[1], O_RDONLY)))
		{
			perror("Open");
			exit(1);
		}
		int size;
		char c[BUFSIZ];
		if(-1 == (size = read(fdold, c, sizeof(c))))
		{
			perror("Write");
			exit(1);
		}
		while(size > 0)
		{
			if(-1 == write(fdnew,c,size))
			{
				perror("write");
				exit(1);
			}
			if(-1 == (size = read(fdold,c,sizeof(c))))
			{
				perror("read");
				exit(1);
			}
		}
		if(-1 == close(fdnew))
		{
			perror("close");
			exit(1);
		}
		if(-1 == close(fdold))
		{
			perror("close");
			exit(1);
		}

	}
	return 0;
}
<|endoftext|>


<commit_before>#include <QTest>
#include <QtCore>
#include <QHostInfo>
#include <tglobal.h>
#include <stdio.h>

static QByteArray randomString()
{
    QByteArray data;
    data.reserve(128);

#if QT_VERSION >= 0x040700
    data.append(QByteArray::number(QDateTime::currentMSecsSinceEpoch()));
#else
    QDateTime now = QDateTime::currentDateTime();
    data.append(QByteArray::number(now.toTime_t()));
    data.append(QByteArray::number(now.time().msec()));
#endif
    data.append(QHostInfo::localHostName());
    data.append(QByteArray::number(QCoreApplication::applicationPid()));
    data.append(QByteArray::number((qulonglong)QThread::currentThread()));
    data.append(QByteArray::number((qulonglong)qApp));
    data.append(QByteArray::number(Tf::randXor128()));
    return QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();
}

static QByteArray randomString(int length)
{
    static char ch[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const int num = strlen(ch) - 1;
    QByteArray ret;
    ret.reserve(length);

    for (int i = 0; i < length; ++i) {
        ret += ch[Tf::random(num)];
    }
    return ret;
}

class Thread : public QThread
{
    void run()
    {
        for (;;) {
            for (int i = 0; i < 20; ++i) {
                Tf::randXor128();
            }
            QThread::yieldCurrentThread();
        }
    }
};

class TestRand : public QObject
{
    Q_OBJECT
private slots:
    void random_data();
    void random();
    void bench_data();
    void bench();
    void randomstring1();
    void randomstring2();
};

void TestRand::random_data()
{
    QTest::addColumn<int>("seed");
    QTest::newRow("1") << 1;
    QTest::newRow("2") << 10;
    QTest::newRow("3") << 100;
}

void TestRand::random()
{
    QFETCH(int, seed);
    Tf::srandXor128(seed);
    for (int i = 0; i < 10; ++i)
        printf("rand: %u\n", Tf::randXor128());
}

void TestRand::bench_data()
{
    Tf::srandXor128(1222);

    for (int i = 0; i < 400; ++i) {
        (new Thread)->start();
    }
    Tf::msleep(100);
}

void TestRand::bench()
{
    QBENCHMARK {
        Tf::randXor128();
     }
}

void TestRand::randomstring1()
{
    QBENCHMARK {
        randomString();
    }
}

void TestRand::randomstring2()
{
    QBENCHMARK {
        randomString(20);
    }
}

QTEST_APPLESS_MAIN(TestRand)
#include "main.moc"

/*
rand: 3656013425
rand: 503675675
rand: 4013738704
rand: 4013743934
rand: 1693336950
rand: 1359361875
rand: 1483021801
rand: 1370094836
rand: 1199228482
rand: 665247057
rand: 3656013434
rand: 503675664
rand: 4013738715
rand: 4013721446
rand: 1693336957
rand: 1359376139
rand: 1483021794
rand: 1399432767
rand: 1169867906
rand: 665224457
rand: 3656013332
rand: 503675774
rand: 4013738677
rand: 4013945878
rand: 1693336851
rand: 1359289467
rand: 1483021708
rand: 1223347666
rand: 1580916481
rand: 665187961
*/
<commit_msg>update<commit_after>#include <QTest>
#include <QtCore>
#include <QHostInfo>
#include <tglobal.h>
#include <stdio.h>

static QByteArray randomString()
{
    QByteArray data;
    data.reserve(128);

#if QT_VERSION >= 0x040700
    data.append(QByteArray::number(QDateTime::currentMSecsSinceEpoch()));
#else
    QDateTime now = QDateTime::currentDateTime();
    data.append(QByteArray::number(now.toTime_t()));
    data.append(QByteArray::number(now.time().msec()));
#endif
    data.append(QHostInfo::localHostName());
    data.append(QByteArray::number(QCoreApplication::applicationPid()));
    data.append(QByteArray::number((qulonglong)QThread::currentThread()));
    data.append(QByteArray::number((qulonglong)qApp));
    data.append(QByteArray::number(Tf::randXor128()));
    return QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();
}

static QByteArray randomString(int length)
{
    static char ch[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const int num = strlen(ch) - 1;
    QByteArray ret;
    ret.reserve(length);

    for (int i = 0; i < length; ++i) {
        ret += ch[Tf::random(num)];
    }
    return ret;
}

class Thread : public QThread
{
    void run()
    {
        for (;;) {
            for (int i = 0; i < 20; ++i) {
                Tf::randXor128();
            }
            QThread::yieldCurrentThread();
        }
    }
};

class TestRand : public QObject
{
    Q_OBJECT
private slots:
    void initTestCase();
    void cleanupTestCase();
    void random_data();
    void random();
    void bench_data();
    void bench();
    void randomstring1();
    void randomstring2();

private:
    enum {
        THREADS_NUM = 256,
    };

    Thread *thread[THREADS_NUM];
};

void TestRand::initTestCase()
{
    // put load for benchmarks
    for (int i = 0; i < THREADS_NUM; ++i) {
        thread[i] = new Thread;
        thread[i]->start();
    }
    Tf::msleep(100);
}

void TestRand::cleanupTestCase()
{
    for (int i = 0; i < THREADS_NUM; ++i) {
        thread[i]->terminate();
    }
}

void TestRand::random_data()
{
    QTest::addColumn<int>("seed");
    QTest::newRow("1") << 1;
    QTest::newRow("2") << 10;
    QTest::newRow("3") << 100;
}

void TestRand::random()
{
    QFETCH(int, seed);
    Tf::srandXor128(seed);
    for (int i = 0; i < 10; ++i)
        printf("rand: %u\n", Tf::randXor128());
}

void TestRand::bench_data()
{
    Tf::srandXor128(1222);
}

void TestRand::bench()
{
    QBENCHMARK {
        Tf::randXor128();
     }
}

void TestRand::randomstring1()
{
    QBENCHMARK {
        randomString();
    }
}

void TestRand::randomstring2()
{
    QBENCHMARK {
        randomString(20);
    }
}

QTEST_APPLESS_MAIN(TestRand)
#include "main.moc"

/*
rand: 3656013425
rand: 503675675
rand: 4013738704
rand: 4013743934
rand: 1693336950
rand: 1359361875
rand: 1483021801
rand: 1370094836
rand: 1199228482
rand: 665247057
rand: 3656013434
rand: 503675664
rand: 4013738715
rand: 4013721446
rand: 1693336957
rand: 1359376139
rand: 1483021794
rand: 1399432767
rand: 1169867906
rand: 665224457
rand: 3656013332
rand: 503675774
rand: 4013738677
rand: 4013945878
rand: 1693336851
rand: 1359289467
rand: 1483021708
rand: 1223347666
rand: 1580916481
rand: 665187961
*/
<|endoftext|>


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

#include "rpcserver.h"
#include "rpcclient.h"

#include "base58.h"
#include "netbase.h"

#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>

using namespace std;
using namespace json_spirit;

Array
createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL)
{
    Array result;
    result.push_back(nRequired);
    Array addresses;
    if (address1) addresses.push_back(address1);
    if (address2) addresses.push_back(address2);
    result.push_back(addresses);
    return result;
}

Value CallRPC(string args)
{
    vector<string> vArgs;
    boost::split(vArgs, args, boost::is_any_of(" \t"));
    string strMethod = vArgs[0];
    vArgs.erase(vArgs.begin());
    Array params = RPCConvertValues(strMethod, vArgs);

    rpcfn_type method = tableRPC[strMethod]->actor;
    try {
        Value result = (*method)(params, false);
        return result;
    }
    catch (Object& objError)
    {
        throw runtime_error(find_value(objError, "message").get_str());
    }
}

BOOST_AUTO_TEST_SUITE(rpc_tests)

BOOST_AUTO_TEST_CASE(rpc_rawparams)
{
    // Test raw transaction API argument handling
    Value r;

    BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), runtime_error);

    BOOST_CHECK_THROW(CallRPC("createrawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("createrawtransaction [] []"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [] {}"));
    BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"), runtime_error);

    BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), runtime_error);
    string rawtx = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
    BOOST_CHECK_NO_THROW(r = CallRPC(string("decoderawtransaction ")+rawtx));
    BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1);
    BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0);
    BOOST_CHECK_THROW(r = CallRPC(string("decoderawtransaction ")+rawtx+" extra"), runtime_error);

    BOOST_CHECK_THROW(CallRPC("signrawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("signrawtransaction ff00"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx));
    BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null NONE|ANYONECANPAY"));
    BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" [] [] NONE|ANYONECANPAY"));
    BOOST_CHECK_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null badenum"), runtime_error);

    // Only check failure cases for sendrawtransaction, there's no network to send to...
    BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), runtime_error);
    BOOST_CHECK_THROW(CallRPC(string("sendrawtransaction ")+rawtx+" extra"), runtime_error);
}

BOOST_AUTO_TEST_CASE(rpc_rawsign)
{
    Value r;
    // input is a 1-of-2 multisig (so is output):
    string prevout =
      "[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\","
      "\"vout\":1,\"scriptPubKey\":\"a914b10c9df5f7edf436c697f02f1efdba4cf399615187\","
      "\"redeemScript\":\"512103debedc17b3df2badbcdd86d5feb4562b86fe182e5998abd8bcd4f122c6155b1b21027e940bb73ab8732bfdf7f9216ecefca5b94d6df834e77e108f68e66f126044c052ae\"}]";
    r = CallRPC(string("createrawtransaction ")+prevout+" "+
      "{\"3HqAe9LtNBjnsfM4CyYaWTnvCaUYT7v4oZ\":11}");
    string notsigned = r.get_str();
    string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
    string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
    r = CallRPC(string("signrawtransaction ")+notsigned+" "+prevout+" "+"[]");
    BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
    r = CallRPC(string("signrawtransaction ")+notsigned+" "+prevout+" "+"["+privkey1+","+privkey2+"]");
    BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
}

BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
{
    BOOST_CHECK(write_string(ValueFromAmount(0LL), false) == "0.00000000");
    BOOST_CHECK(write_string(ValueFromAmount(1LL), false) == "0.00000001");
    BOOST_CHECK(write_string(ValueFromAmount(17622195LL), false) == "0.17622195");
    BOOST_CHECK(write_string(ValueFromAmount(50000000LL), false) == "0.50000000");
    BOOST_CHECK(write_string(ValueFromAmount(89898989LL), false) == "0.89898989");
    BOOST_CHECK(write_string(ValueFromAmount(100000000LL), false) == "1.00000000");
    BOOST_CHECK(write_string(ValueFromAmount(2099999999999990LL), false) == "20999999.99999990");
    BOOST_CHECK(write_string(ValueFromAmount(2099999999999999LL), false) == "20999999.99999999");
}

static Value ValueFromString(const std::string &str)
{
    Value value;
    BOOST_CHECK(read_string(str, value));
    return value;
}

BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
{
    BOOST_CHECK(AmountFromValue(ValueFromString("0.00000001")) == 1LL);
    BOOST_CHECK(AmountFromValue(ValueFromString("0.17622195")) == 17622195LL);
    BOOST_CHECK(AmountFromValue(ValueFromString("0.5")) == 50000000LL);
    BOOST_CHECK(AmountFromValue(ValueFromString("0.50000000")) == 50000000LL);
    BOOST_CHECK(AmountFromValue(ValueFromString("0.89898989")) == 89898989LL);
    BOOST_CHECK(AmountFromValue(ValueFromString("1.00000000")) == 100000000LL);
    BOOST_CHECK(AmountFromValue(ValueFromString("20999999.9999999")) == 2099999999999990LL);
    BOOST_CHECK(AmountFromValue(ValueFromString("20999999.99999999")) == 2099999999999999LL);
}

BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr)
{
    // Check IPv4 addresses
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("1.2.3.4")).ToString(), "1.2.3.4");
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("127.0.0.1")).ToString(), "127.0.0.1");
    // Check IPv6 addresses
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::1")).ToString(), "::1");
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("123:4567:89ab:cdef:123:4567:89ab:cdef")).ToString(),
                                         "123:4567:89ab:cdef:123:4567:89ab:cdef");
    // v4 compatible must be interpreted as IPv4
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::0:127.0.0.1")).ToString(), "127.0.0.1");
    // v4 mapped must be interpreted as IPv4
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::ffff:127.0.0.1")).ToString(), "127.0.0.1");
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>rpc_tests: use BOOST_CHECK_EQUAL<commit_after>// Copyright (c) 2012-2013 The Bitcoin Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "rpcserver.h"
#include "rpcclient.h"

#include "base58.h"
#include "netbase.h"

#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>

using namespace std;
using namespace json_spirit;

Array
createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL)
{
    Array result;
    result.push_back(nRequired);
    Array addresses;
    if (address1) addresses.push_back(address1);
    if (address2) addresses.push_back(address2);
    result.push_back(addresses);
    return result;
}

Value CallRPC(string args)
{
    vector<string> vArgs;
    boost::split(vArgs, args, boost::is_any_of(" \t"));
    string strMethod = vArgs[0];
    vArgs.erase(vArgs.begin());
    Array params = RPCConvertValues(strMethod, vArgs);

    rpcfn_type method = tableRPC[strMethod]->actor;
    try {
        Value result = (*method)(params, false);
        return result;
    }
    catch (Object& objError)
    {
        throw runtime_error(find_value(objError, "message").get_str());
    }
}

BOOST_AUTO_TEST_SUITE(rpc_tests)

BOOST_AUTO_TEST_CASE(rpc_rawparams)
{
    // Test raw transaction API argument handling
    Value r;

    BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), runtime_error);

    BOOST_CHECK_THROW(CallRPC("createrawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("createrawtransaction [] []"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [] {}"));
    BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"), runtime_error);

    BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), runtime_error);
    string rawtx = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
    BOOST_CHECK_NO_THROW(r = CallRPC(string("decoderawtransaction ")+rawtx));
    BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1);
    BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0);
    BOOST_CHECK_THROW(r = CallRPC(string("decoderawtransaction ")+rawtx+" extra"), runtime_error);

    BOOST_CHECK_THROW(CallRPC("signrawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("signrawtransaction ff00"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx));
    BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null NONE|ANYONECANPAY"));
    BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" [] [] NONE|ANYONECANPAY"));
    BOOST_CHECK_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null badenum"), runtime_error);

    // Only check failure cases for sendrawtransaction, there's no network to send to...
    BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), runtime_error);
    BOOST_CHECK_THROW(CallRPC(string("sendrawtransaction ")+rawtx+" extra"), runtime_error);
}

BOOST_AUTO_TEST_CASE(rpc_rawsign)
{
    Value r;
    // input is a 1-of-2 multisig (so is output):
    string prevout =
      "[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\","
      "\"vout\":1,\"scriptPubKey\":\"a914b10c9df5f7edf436c697f02f1efdba4cf399615187\","
      "\"redeemScript\":\"512103debedc17b3df2badbcdd86d5feb4562b86fe182e5998abd8bcd4f122c6155b1b21027e940bb73ab8732bfdf7f9216ecefca5b94d6df834e77e108f68e66f126044c052ae\"}]";
    r = CallRPC(string("createrawtransaction ")+prevout+" "+
      "{\"3HqAe9LtNBjnsfM4CyYaWTnvCaUYT7v4oZ\":11}");
    string notsigned = r.get_str();
    string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
    string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
    r = CallRPC(string("signrawtransaction ")+notsigned+" "+prevout+" "+"[]");
    BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
    r = CallRPC(string("signrawtransaction ")+notsigned+" "+prevout+" "+"["+privkey1+","+privkey2+"]");
    BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
}

BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
{
    BOOST_CHECK_EQUAL(write_string(ValueFromAmount(0LL), false), "0.00000000");
    BOOST_CHECK_EQUAL(write_string(ValueFromAmount(1LL), false), "0.00000001");
    BOOST_CHECK_EQUAL(write_string(ValueFromAmount(17622195LL), false), "0.17622195");
    BOOST_CHECK_EQUAL(write_string(ValueFromAmount(50000000LL), false), "0.50000000");
    BOOST_CHECK_EQUAL(write_string(ValueFromAmount(89898989LL), false), "0.89898989");
    BOOST_CHECK_EQUAL(write_string(ValueFromAmount(100000000LL), false), "1.00000000");
    BOOST_CHECK_EQUAL(write_string(ValueFromAmount(2099999999999990LL), false), "20999999.99999990");
    BOOST_CHECK_EQUAL(write_string(ValueFromAmount(2099999999999999LL), false), "20999999.99999999");
}

static Value ValueFromString(const std::string &str)
{
    Value value;
    BOOST_CHECK(read_string(str, value));
    return value;
}

BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
{
    BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001")), 1LL);
    BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.17622195")), 17622195LL);
    BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.5")), 50000000LL);
    BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.50000000")), 50000000LL);
    BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.89898989")), 89898989LL);
    BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1.00000000")), 100000000LL);
    BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.9999999")), 2099999999999990LL);
    BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.99999999")), 2099999999999999LL);
}

BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr)
{
    // Check IPv4 addresses
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("1.2.3.4")).ToString(), "1.2.3.4");
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("127.0.0.1")).ToString(), "127.0.0.1");
    // Check IPv6 addresses
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::1")).ToString(), "::1");
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("123:4567:89ab:cdef:123:4567:89ab:cdef")).ToString(),
                                         "123:4567:89ab:cdef:123:4567:89ab:cdef");
    // v4 compatible must be interpreted as IPv4
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::0:127.0.0.1")).ToString(), "127.0.0.1");
    // v4 mapped must be interpreted as IPv4
    BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::ffff:127.0.0.1")).ToString(), "127.0.0.1");
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef DBFFILE_HPP
#define DBFFILE_HPP

#include <mapnik/feature.hpp>
// boost
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
// stl
#include <vector>
#include <string>
#include <cassert>

using mapnik::transcoder;
using mapnik::Feature;
class mapnik::transcoder;

struct field_descriptor
{
    int index_;
    std::string name_;
    char type_;
    int length_;
    int dec_;
    int offset_;
};

using namespace boost::iostreams;

class dbf_file
{
   private:
      int num_records_;
      int num_fields_;
      int record_length_;
      std::vector<field_descriptor> fields_;
      stream<mapped_file_source> file_;
      char* record_;
public:
      dbf_file();
      dbf_file(const std::string& file_name);
      ~dbf_file();
      bool is_open();
      void close();
      int num_records() const;
      int num_fields() const;
      field_descriptor const& descriptor(int col) const;
      void move_to(int index);
      std::string string_value(int col) const;
      void add_attribute(int col, transcoder const& tr, Feature const& f) const throw();
   private:
      dbf_file(const dbf_file&);
      dbf_file& operator=(const dbf_file&);
      void read_header();
      int read_short();
      int read_int();
      void skip(int bytes);
};

#endif //DBFFILE_HPP
<commit_msg>Removed forward declaration of mapnik::transcoder as we have already included the definition and the duplicate causes a compiler warning.<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef DBFFILE_HPP
#define DBFFILE_HPP

#include <mapnik/feature.hpp>
// boost
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
// stl
#include <vector>
#include <string>
#include <cassert>

using mapnik::transcoder;
using mapnik::Feature;

struct field_descriptor
{
    int index_;
    std::string name_;
    char type_;
    int length_;
    int dec_;
    int offset_;
};

using namespace boost::iostreams;

class dbf_file
{
   private:
      int num_records_;
      int num_fields_;
      int record_length_;
      std::vector<field_descriptor> fields_;
      stream<mapped_file_source> file_;
      char* record_;
public:
      dbf_file();
      dbf_file(const std::string& file_name);
      ~dbf_file();
      bool is_open();
      void close();
      int num_records() const;
      int num_fields() const;
      field_descriptor const& descriptor(int col) const;
      void move_to(int index);
      std::string string_value(int col) const;
      void add_attribute(int col, transcoder const& tr, Feature const& f) const throw();
   private:
      dbf_file(const dbf_file&);
      dbf_file& operator=(const dbf_file&);
      void read_header();
      int read_short();
      int read_int();
      void skip(int bytes);
};

#endif //DBFFILE_HPP
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "carlsim_tests.h"

#include <carlsim.h>
#include <periodic_spikegen.h>
#include <spikegen_from_file.h>
#include <spikegen_from_vector.h>

#include <vector>

// tests whether the binary file created by setSpikeMonitor matches the specifications of PeriodicSpikeGenerator
TEST(SpikeGen, PeriodicSpikeGenerator) {
	int isi = 100; // ms
	double rate = 1000.0/isi;
	int nNeur = 5;
	CARLsim sim("PeriodicSpikeGenerator",CPU_MODE,SILENT,0,1,42);

	int g0 = sim.createSpikeGeneratorGroup("Input0",nNeur,EXCITATORY_NEURON);
	int g1 = sim.createSpikeGeneratorGroup("Input1",nNeur,EXCITATORY_NEURON);
	PeriodicSpikeGenerator spkGen0(rate,true);
	PeriodicSpikeGenerator spkGen1(rate,false);
	sim.setSpikeGenerator(g0, &spkGen0);
	sim.setSpikeGenerator(g1, &spkGen1);

	int g2 = sim.createGroup("g2", 1, EXCITATORY_NEURON);
	sim.setNeuronParameters(g2, 0.02, 0.2, -65.0, 8.0);
	sim.setConductances(true);

	// add some dummy connections so we can actually run the network
	sim.connect(g0,g2,"random", RangeWeight(0.01), 0.5f, RangeDelay(1), SYN_FIXED);

	sim.setupNetwork();
	sim.setSpikeMonitor(g0,"spkInputGrp0.dat"); // save spikes to file
	sim.setSpikeMonitor(g1,"spkInputGrp1.dat"); // save spikes to file
	sim.runNetwork(1,0);

	// explicitly read the spike file to make sure
	int *inputArray0 = NULL, *inputArray1 = NULL;
	long inputSize0, inputSize1;
	readAndReturnSpikeFile("spkInputGrp0.dat",inputArray0,inputSize0);
	readAndReturnSpikeFile("spkInputGrp1.dat",inputArray1,inputSize1);
	ASSERT_EQ(inputSize0/2, nNeur * (int)rate);
	ASSERT_EQ(inputSize1/2, nNeur * ((int)rate-1));

	for (int i=0; i<inputSize0; i+=2) {
		EXPECT_EQ(inputArray0[i]%isi, 0);
	}
	for (int i=0; i<inputSize1; i+=2) {
		EXPECT_EQ(inputArray1[i]%isi, 0);
	}

	if (inputArray0!=NULL) delete[] inputArray0;
	if (inputArray1!=NULL) delete[] inputArray1;
}

TEST(SpikeGen, PeriodicSpikeGeneratorDeath) {
	EXPECT_DEATH({PeriodicSpikeGenerator spkGen(0.0);},"");
	EXPECT_DEATH({PeriodicSpikeGenerator spkGen(-10.0);},"");
}

TEST(SpikeGen, SpikeGeneratorFromFile) {
	int isi = 100; // ms
	double rate = 1000.0/isi;
	int nNeur = 5;
	CARLsim sim("SpikeGeneratorFromFile",CPU_MODE,SILENT,0,1,42);

	int g0 = sim.createSpikeGeneratorGroup("Input0",nNeur,EXCITATORY_NEURON);
	PeriodicSpikeGenerator spkGen0(rate,true);
	sim.setSpikeGenerator(g0, &spkGen0);

	int g1 = sim.createGroup("g1", 1, EXCITATORY_NEURON);
	sim.setNeuronParameters(g1, 0.02, 0.2, -65.0, 8.0);
	sim.setConductances(true);

	// add some dummy connections so we can actually run the network
	sim.connect(g0,g1,"random", RangeWeight(0.01), 0.5f, RangeDelay(1), SYN_FIXED);

	sim.setupNetwork();
	sim.setSpikeMonitor(g0,"spkInputGrp0.dat"); // save spikes to file
	sim.runNetwork(1,0);

	// now that we have created the spike file, run a different network using the spike file from above
	CARLsim sim2("SpikeGeneratorFromVector2",CPU_MODE,SILENT,0,1,42);

	g0 = sim2.createSpikeGeneratorGroup("Input",nNeur,EXCITATORY_NEURON);
	SpikeGeneratorFromFile spkGen2("spkInputGrp0.dat");
	sim2.setSpikeGenerator(g0, &spkGen2);

	g1 = sim2.createGroup("g1", 1, EXCITATORY_NEURON);
	sim2.setNeuronParameters(g1, 0.02, 0.2, -65.0, 8.0);
	sim2.setConductances(true);

	// add some dummy connections so we can actually run the network
	sim2.connect(g0,g1,"random", RangeWeight(0.01), 0.5f, RangeDelay(1), SYN_FIXED);

	sim2.setupNetwork();
	sim2.setSpikeMonitor(g0,"spkInputFinal.dat"); // save spikes to file
	sim2.runNetwork(1,0);

	// explicitly read the spike file to make sure
	int *inputArray0 = NULL;
	long inputSize0;
	readAndReturnSpikeFile("spkInputFinal.dat",inputArray0,inputSize0);
	ASSERT_EQ(inputSize0/2, nNeur * (int)rate);

	int j=0;
	for (int i=0; i<inputSize0; i+=2)
		EXPECT_EQ(inputArray0[i]%isi, 0);

	if (inputArray0!=NULL) delete[] inputArray0;
}

TEST(SpikeGen, SpikeGeneratorFromFileDeath) {
	EXPECT_DEATH({SpikeGeneratorFromFile spkGen("");},"");
	EXPECT_DEATH({SpikeGeneratorFromFile spkGen("thisFile/doesNot/exist.dat");},"");
}

// tests whether the binary spike file created by setSpikeMonitor contains the same spike times as specified
// by a spike vector
TEST(SpikeGen, SpikeGeneratorFromVector) {
	int spkTimesArr[11] = {13, 42, 99, 102, 200, 523, 738, 820, 821, 912, 989};
	std::vector<int> spkTimes(&spkTimesArr[0], &spkTimesArr[0]+11);

	int nNeur = 5;
	CARLsim sim("SpikeGeneratorFromVector",CPU_MODE,SILENT,0,1,42);

	int g0 = sim.createSpikeGeneratorGroup("Input",nNeur,EXCITATORY_NEURON);
	SpikeGeneratorFromVector spkGen(spkTimes);
	sim.setSpikeGenerator(g0, &spkGen);

	int g1 = sim.createGroup("g1", 1, EXCITATORY_NEURON);
	sim.setNeuronParameters(g1, 0.02, 0.2, -65.0, 8.0);
	sim.setConductances(true);

	// add some dummy connections so we can actually run the network
	sim.connect(g0,g1,"random", RangeWeight(0.01), 0.5f, RangeDelay(1), SYN_FIXED);

	sim.setupNetwork();
	sim.setSpikeMonitor(g0,"spkInputGrp0.dat"); // save spikes to file
	sim.runNetwork(1,0);

	// explicitly read the spike file to make sure
	int *inputArray0 = NULL;
	long inputSize0;
	readAndReturnSpikeFile("spkInputGrp0.dat",inputArray0,inputSize0);
	ASSERT_EQ(inputSize0/2, spkTimes.size());

	for (int i=0; i<spkTimes.size(); i++) {
		EXPECT_EQ(inputArray0[i*2], spkTimes[i]);
	}

	if (inputArray0!=NULL) delete[] inputArray0;
}

TEST(SpikeGen, SpikeGeneratorFromVectorDeath) {
	std::vector<int> emptyVec, negativeVec;
	negativeVec.push_back(0);
	negativeVec.push_back(-1);

	EXPECT_DEATH({SpikeGeneratorFromVector spkGen(emptyVec);},"");
	EXPECT_DEATH({SpikeGeneratorFromVector spkGen(negativeVec);},"");
}<commit_msg>fixed connect call in SpikeGen test<commit_after>#include "gtest/gtest.h"
#include "carlsim_tests.h"

#include <carlsim.h>
#include <periodic_spikegen.h>
#include <spikegen_from_file.h>
#include <spikegen_from_vector.h>

#include <vector>

// tests whether the binary file created by setSpikeMonitor matches the specifications of PeriodicSpikeGenerator
TEST(SpikeGen, PeriodicSpikeGenerator) {
	int isi = 100; // ms
	double rate = 1000.0/isi;
	int nNeur = 5;
	CARLsim sim("PeriodicSpikeGenerator",CPU_MODE,SILENT,0,1,42);

	int g0 = sim.createSpikeGeneratorGroup("Input0",nNeur,EXCITATORY_NEURON);
	int g1 = sim.createSpikeGeneratorGroup("Input1",nNeur,EXCITATORY_NEURON);
	PeriodicSpikeGenerator spkGen0(rate,true);
	PeriodicSpikeGenerator spkGen1(rate,false);
	sim.setSpikeGenerator(g0, &spkGen0);
	sim.setSpikeGenerator(g1, &spkGen1);

	int g2 = sim.createGroup("g2", 1, EXCITATORY_NEURON);
	sim.setNeuronParameters(g2, 0.02, 0.2, -65.0, 8.0);
	sim.setConductances(true);

	// add some dummy connections so we can actually run the network
	sim.connect(g0,g2,"random", RangeWeight(0.01), 0.5f, RangeDelay(1), RadiusRF(-1), SYN_FIXED);

	sim.setupNetwork();
	sim.setSpikeMonitor(g0,"spkInputGrp0.dat"); // save spikes to file
	sim.setSpikeMonitor(g1,"spkInputGrp1.dat"); // save spikes to file
	sim.runNetwork(1,0);

	// explicitly read the spike file to make sure
	int *inputArray0 = NULL, *inputArray1 = NULL;
	long inputSize0, inputSize1;
	readAndReturnSpikeFile("spkInputGrp0.dat",inputArray0,inputSize0);
	readAndReturnSpikeFile("spkInputGrp1.dat",inputArray1,inputSize1);
	ASSERT_EQ(inputSize0/2, nNeur * (int)rate);
	ASSERT_EQ(inputSize1/2, nNeur * ((int)rate-1));

	for (int i=0; i<inputSize0; i+=2) {
		EXPECT_EQ(inputArray0[i]%isi, 0);
	}
	for (int i=0; i<inputSize1; i+=2) {
		EXPECT_EQ(inputArray1[i]%isi, 0);
	}

	if (inputArray0!=NULL) delete[] inputArray0;
	if (inputArray1!=NULL) delete[] inputArray1;
}

TEST(SpikeGen, PeriodicSpikeGeneratorDeath) {
	EXPECT_DEATH({PeriodicSpikeGenerator spkGen(0.0);},"");
	EXPECT_DEATH({PeriodicSpikeGenerator spkGen(-10.0);},"");
}

TEST(SpikeGen, SpikeGeneratorFromFile) {
	int isi = 100; // ms
	double rate = 1000.0/isi;
	int nNeur = 5;
	CARLsim sim("SpikeGeneratorFromFile",CPU_MODE,SILENT,0,1,42);

	int g0 = sim.createSpikeGeneratorGroup("Input0",nNeur,EXCITATORY_NEURON);
	PeriodicSpikeGenerator spkGen0(rate,true);
	sim.setSpikeGenerator(g0, &spkGen0);

	int g1 = sim.createGroup("g1", 1, EXCITATORY_NEURON);
	sim.setNeuronParameters(g1, 0.02, 0.2, -65.0, 8.0);
	sim.setConductances(true);

	// add some dummy connections so we can actually run the network
	sim.connect(g0,g1,"random", RangeWeight(0.01), 0.5f, RangeDelay(1), RadiusRF(-1), SYN_FIXED);

	sim.setupNetwork();
	sim.setSpikeMonitor(g0,"spkInputGrp0.dat"); // save spikes to file
	sim.runNetwork(1,0);

	// now that we have created the spike file, run a different network using the spike file from above
	CARLsim sim2("SpikeGeneratorFromVector2",CPU_MODE,SILENT,0,1,42);

	g0 = sim2.createSpikeGeneratorGroup("Input",nNeur,EXCITATORY_NEURON);
	SpikeGeneratorFromFile spkGen2("spkInputGrp0.dat");
	sim2.setSpikeGenerator(g0, &spkGen2);

	g1 = sim2.createGroup("g1", 1, EXCITATORY_NEURON);
	sim2.setNeuronParameters(g1, 0.02, 0.2, -65.0, 8.0);
	sim2.setConductances(true);

	// add some dummy connections so we can actually run the network
	sim2.connect(g0,g1,"random", RangeWeight(0.01), 0.5f, RangeDelay(1), RadiusRF(-1), SYN_FIXED);

	sim2.setupNetwork();
	sim2.setSpikeMonitor(g0,"spkInputFinal.dat"); // save spikes to file
	sim2.runNetwork(1,0);

	// explicitly read the spike file to make sure
	int *inputArray0 = NULL;
	long inputSize0;
	readAndReturnSpikeFile("spkInputFinal.dat",inputArray0,inputSize0);
	ASSERT_EQ(inputSize0/2, nNeur * (int)rate);

	int j=0;
	for (int i=0; i<inputSize0; i+=2)
		EXPECT_EQ(inputArray0[i]%isi, 0);

	if (inputArray0!=NULL) delete[] inputArray0;
}

TEST(SpikeGen, SpikeGeneratorFromFileDeath) {
	EXPECT_DEATH({SpikeGeneratorFromFile spkGen("");},"");
	EXPECT_DEATH({SpikeGeneratorFromFile spkGen("thisFile/doesNot/exist.dat");},"");
}

// tests whether the binary spike file created by setSpikeMonitor contains the same spike times as specified
// by a spike vector
TEST(SpikeGen, SpikeGeneratorFromVector) {
	int spkTimesArr[11] = {13, 42, 99, 102, 200, 523, 738, 820, 821, 912, 989};
	std::vector<int> spkTimes(&spkTimesArr[0], &spkTimesArr[0]+11);

	int nNeur = 5;
	CARLsim sim("SpikeGeneratorFromVector",CPU_MODE,SILENT,0,1,42);

	int g0 = sim.createSpikeGeneratorGroup("Input",nNeur,EXCITATORY_NEURON);
	SpikeGeneratorFromVector spkGen(spkTimes);
	sim.setSpikeGenerator(g0, &spkGen);

	int g1 = sim.createGroup("g1", 1, EXCITATORY_NEURON);
	sim.setNeuronParameters(g1, 0.02, 0.2, -65.0, 8.0);
	sim.setConductances(true);

	// add some dummy connections so we can actually run the network
	sim.connect(g0,g1,"random", RangeWeight(0.01), 0.5f, RangeDelay(1), RadiusRF(-1), SYN_FIXED);

	sim.setupNetwork();
	sim.setSpikeMonitor(g0,"spkInputGrp0.dat"); // save spikes to file
	sim.runNetwork(1,0);

	// explicitly read the spike file to make sure
	int *inputArray0 = NULL;
	long inputSize0;
	readAndReturnSpikeFile("spkInputGrp0.dat",inputArray0,inputSize0);
	ASSERT_EQ(inputSize0/2, spkTimes.size());

	for (int i=0; i<spkTimes.size(); i++) {
		EXPECT_EQ(inputArray0[i*2], spkTimes[i]);
	}

	if (inputArray0!=NULL) delete[] inputArray0;
}

TEST(SpikeGen, SpikeGeneratorFromVectorDeath) {
	std::vector<int> emptyVec, negativeVec;
	negativeVec.push_back(0);
	negativeVec.push_back(-1);

	EXPECT_DEATH({SpikeGeneratorFromVector spkGen(emptyVec);},"");
	EXPECT_DEATH({SpikeGeneratorFromVector spkGen(negativeVec);},"");
}<|endoftext|>


<commit_before>/*
 * Copyright 2010-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
 */

#include <bx/os.h>
#include <bx/uint32_t.h>
#include <bx/string.h>

#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
#	include <windows.h>
#	include <psapi.h>
#elif  BX_PLATFORM_ANDROID \
	|| BX_PLATFORM_EMSCRIPTEN \
	|| BX_PLATFORM_BSD \
	|| BX_PLATFORM_HURD \
	|| BX_PLATFORM_IOS \
	|| BX_PLATFORM_LINUX \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_OSX \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_RPI \
	|| BX_PLATFORM_STEAMLINK
#	include <sched.h> // sched_yield
#	if BX_PLATFORM_BSD \
	|| BX_PLATFORM_IOS \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_OSX \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_STEAMLINK
#		include <pthread.h> // mach_port_t
#	endif // BX_PLATFORM_*

#	include <time.h> // nanosleep
#	if !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL
#		include <dlfcn.h> // dlopen, dlclose, dlsym
#	endif // !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL

#	if BX_PLATFORM_ANDROID
#		include <malloc.h> // mallinfo
#	elif   BX_PLATFORM_LINUX \
		|| BX_PLATFORM_RPI \
		|| BX_PLATFORM_STEAMLINK
#		include <unistd.h> // syscall
#		include <sys/syscall.h>
#	elif BX_PLATFORM_OSX
#		include <mach/mach.h> // mach_task_basic_info
#	elif BX_PLATFORM_HURD
#		include <pthread/pthread.h> // pthread_self
#	elif BX_PLATFORM_ANDROID
#		include "debug.h" // getTid is not implemented...
#	endif // BX_PLATFORM_ANDROID
#endif // BX_PLATFORM_

#if BX_CRT_MSVC
#	include <direct.h> // _getcwd
#else
#	include <unistd.h> // getcwd
#endif // BX_CRT_MSVC

namespace bx
{

	void sleep(uint32_t _ms)
	{
#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360
		::Sleep(_ms);
#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT
		BX_UNUSED(_ms);
		debugOutput("sleep is not implemented"); debugBreak();
#else
		timespec req = {(time_t)_ms/1000, (long)((_ms%1000)*1000000)};
		timespec rem = {0, 0};
		::nanosleep(&req, &rem);
#endif // BX_PLATFORM_
	}

	void yield()
	{
#if BX_PLATFORM_WINDOWS
		::SwitchToThread();
#elif BX_PLATFORM_XBOX360
		::Sleep(0);
#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT
		debugOutput("yield is not implemented"); debugBreak();
#else
		::sched_yield();
#endif // BX_PLATFORM_
	}

	uint32_t getTid()
	{
#if BX_PLATFORM_WINDOWS
		return ::GetCurrentThreadId();
#elif BX_PLATFORM_LINUX || BX_PLATFORM_RPI || BX_PLATFORM_STEAMLINK
		return (pid_t)::syscall(SYS_gettid);
#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
		return (mach_port_t)::pthread_mach_thread_np(pthread_self() );
#elif BX_PLATFORM_BSD || BX_PLATFORM_NACL
		// Casting __nc_basic_thread_data*... need better way to do this.
		return *(uint32_t*)::pthread_self();
#elif BX_PLATFORM_HURD
		return (pthread_t)::pthread_self();
#else
//#	pragma message "not implemented."
		debugOutput("getTid is not implemented"); debugBreak();
		return 0;
#endif //
	}

	size_t getProcessMemoryUsed()
	{
#if BX_PLATFORM_ANDROID
		struct mallinfo mi = mallinfo();
		return mi.uordblks;
#elif BX_PLATFORM_LINUX || BX_PLATFORM_HURD
		FILE* file = fopen("/proc/self/statm", "r");
		if (NULL == file)
		{
			return 0;
		}

		long pages = 0;
		int items = fscanf(file, "%*s%ld", &pages);
		fclose(file);
		return 1 == items
			? pages * sysconf(_SC_PAGESIZE)
			: 0
			;
#elif BX_PLATFORM_OSX
#	if defined(MACH_TASK_BASIC_INFO)
		mach_task_basic_info info;
		mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;

		int const result = task_info(mach_task_self()
				, MACH_TASK_BASIC_INFO
				, (task_info_t)&info
				, &infoCount
				);
#	else // MACH_TASK_BASIC_INFO
		task_basic_info info;
		mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT;

		int const result = task_info(mach_task_self()
				, TASK_BASIC_INFO
				, (task_info_t)&info
				, &infoCount
				);
#	endif // MACH_TASK_BASIC_INFO
		if (KERN_SUCCESS != result)
		{
			return 0;
		}

		return info.resident_size;
#elif BX_PLATFORM_WINDOWS
		PROCESS_MEMORY_COUNTERS pmc;
		GetProcessMemoryInfo(GetCurrentProcess()
			, &pmc
			, sizeof(pmc)
			);
		return pmc.WorkingSetSize;
#else
		return 0;
#endif // BX_PLATFORM_*
	}

	void* dlopen(const char* _filePath)
	{
#if BX_PLATFORM_WINDOWS
		return (void*)::LoadLibraryA(_filePath);
#elif  BX_PLATFORM_EMSCRIPTEN \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_filePath);
		return NULL;
#else
		return ::dlopen(_filePath, RTLD_LOCAL|RTLD_LAZY);
#endif // BX_PLATFORM_
	}

	void dlclose(void* _handle)
	{
#if BX_PLATFORM_WINDOWS
		::FreeLibrary( (HMODULE)_handle);
#elif  BX_PLATFORM_EMSCRIPTEN \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_handle);
#else
		::dlclose(_handle);
#endif // BX_PLATFORM_
	}

	void* dlsym(void* _handle, const char* _symbol)
	{
#if BX_PLATFORM_WINDOWS
		return (void*)::GetProcAddress( (HMODULE)_handle, _symbol);
#elif  BX_PLATFORM_EMSCRIPTEN \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_handle, _symbol);
		return NULL;
#else
		return ::dlsym(_handle, _symbol);
#endif // BX_PLATFORM_
	}

	bool getenv(const char* _name, char* _out, uint32_t* _inOutSize)
	{
#if BX_PLATFORM_WINDOWS
		DWORD len = ::GetEnvironmentVariableA(_name, _out, *_inOutSize);
		bool result = len != 0 && len < *_inOutSize;
		*_inOutSize = len;
		return result;
#elif  BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_name, _out, _inOutSize);
		return false;
#else
		const char* ptr = ::getenv(_name);
		uint32_t len = 0;
		bool result = false;
		if (NULL != ptr)
		{
			len = (uint32_t)strlen(ptr);

			result = len != 0 && len < *_inOutSize;
			if (len < *_inOutSize)
			{
				strcpy(_out, ptr);
			}
		}

		*_inOutSize = len;
		return result;
#endif // BX_PLATFORM_
	}

	void setenv(const char* _name, const char* _value)
	{
#if BX_PLATFORM_WINDOWS
		::SetEnvironmentVariableA(_name, _value);
#elif  BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_name, _value);
#else
		::setenv(_name, _value, 1);
#endif // BX_PLATFORM_
	}

	void unsetenv(const char* _name)
	{
#if BX_PLATFORM_WINDOWS
		::SetEnvironmentVariableA(_name, NULL);
#elif  BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_name);
#else
		::unsetenv(_name);
#endif // BX_PLATFORM_
	}

	int chdir(const char* _path)
	{
#if BX_PLATFORM_PS4 \
 || BX_PLATFORM_XBOXONE \
 || BX_PLATFORM_WINRT
		BX_UNUSED(_path);
		return -1;
#elif BX_CRT_MSVC
		return ::_chdir(_path);
#else
		return ::chdir(_path);
#endif // BX_COMPILER_
	}

	char* pwd(char* _buffer, uint32_t _size)
	{
#if BX_PLATFORM_PS4 \
 || BX_PLATFORM_XBOXONE \
 || BX_PLATFORM_WINRT
		BX_UNUSED(_buffer, _size);
		return NULL;
#elif BX_CRT_MSVC
		return ::_getcwd(_buffer, (int)_size);
#else
		return ::getcwd(_buffer, _size);
#endif // BX_COMPILER_
	}

	bool getTempPath(char* _out, uint32_t* _inOutSize)
	{
#if BX_PLATFORM_WINDOWS
		uint32_t len = ::GetTempPathA(*_inOutSize, _out);
		bool result = len != 0 && len < *_inOutSize;
		*_inOutSize = len;
		return result;
#else
		static const char* s_tmp[] =
		{
			"TMPDIR",
			"TMP",
			"TEMP",
			"TEMPDIR",

			NULL
		};

		for (const char** tmp = s_tmp; *tmp != NULL; ++tmp)
		{
			uint32_t len = *_inOutSize;
			*_out = '\0';
			bool result = getenv(*tmp, _out, &len);

			if (result
			&&  len != 0
			&&  len < *_inOutSize)
			{
				*_inOutSize = len;
				return result;
			}
		}

		return false;
#endif // BX_PLATFORM_*
	}

	bool stat(const char* _filePath, FileInfo& _fileInfo)
	{
		_fileInfo.m_size = 0;
		_fileInfo.m_type = FileInfo::Count;

#if BX_COMPILER_MSVC
		struct ::_stat64 st;
		int32_t result = ::_stat64(_filePath, &st);

		if (0 != result)
		{
			return false;
		}

		if (0 != (st.st_mode & _S_IFREG) )
		{
			_fileInfo.m_type = FileInfo::Regular;
		}
		else if (0 != (st.st_mode & _S_IFDIR) )
		{
			_fileInfo.m_type = FileInfo::Directory;
		}
#else
		struct ::stat st;
		int32_t result = ::stat(_filePath, &st);
		if (0 != result)
		{
			return false;
		}

		if (0 != (st.st_mode & S_IFREG) )
		{
			_fileInfo.m_type = FileInfo::Regular;
		}
		else if (0 != (st.st_mode & S_IFDIR) )
		{
			_fileInfo.m_type = FileInfo::Directory;
		}
#endif // BX_COMPILER_MSVC

		_fileInfo.m_size = st.st_size;

		return true;
	}

	void* exec(const char* const* _argv)
	{
#if BX_PLATFORM_LINUX || BX_PLATFORM_HURD
		pid_t pid = fork();

		if (0 == pid)
		{
			int result = execvp(_argv[0], const_cast<char *const*>(&_argv[1]) );
			BX_UNUSED(result);
			return NULL;
		}

		return (void*)uintptr_t(pid);
#elif BX_PLATFORM_WINDOWS
		STARTUPINFO si;
		memset(&si, 0, sizeof(STARTUPINFO) );
		si.cb = sizeof(STARTUPINFO);

		PROCESS_INFORMATION pi;
		memset(&pi, 0, sizeof(PROCESS_INFORMATION) );

		int32_t total = 0;
		for (uint32_t ii = 0; NULL != _argv[ii]; ++ii)
		{
			total += (int32_t)strlen(_argv[ii]) + 1;
		}

		char* temp = (char*)alloca(total);
		int32_t len = 0;
		for(uint32_t ii = 0; NULL != _argv[ii]; ++ii)
		{
			len += snprintf(&temp[len], bx::uint32_imax(0, total-len)
						, "%s "
						, _argv[ii]
						);
		}

		bool ok = !!CreateProcessA(_argv[0]
					, temp
					, NULL
					, NULL
					, false
					, 0
					, NULL
					, NULL
					, &si
					, &pi
					);
		if (ok)
		{
			return pi.hProcess;
		}

		return NULL;
#else
		return NULL;
#endif // BX_PLATFORM_LINUX || BX_PLATFORM_HURD
	}

} // namespace bx
<commit_msg>Cleanup.<commit_after>/*
 * Copyright 2010-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
 */

#include <bx/os.h>
#include <bx/uint32_t.h>
#include <bx/string.h>

#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
#	include <windows.h>
#	include <psapi.h>
#elif  BX_PLATFORM_ANDROID \
	|| BX_PLATFORM_EMSCRIPTEN \
	|| BX_PLATFORM_BSD \
	|| BX_PLATFORM_HURD \
	|| BX_PLATFORM_IOS \
	|| BX_PLATFORM_LINUX \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_OSX \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_RPI \
	|| BX_PLATFORM_STEAMLINK
#	include <sched.h> // sched_yield
#	if BX_PLATFORM_BSD \
	|| BX_PLATFORM_IOS \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_OSX \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_STEAMLINK
#		include <pthread.h> // mach_port_t
#	endif // BX_PLATFORM_*

#	include <time.h> // nanosleep
#	if !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL
#		include <dlfcn.h> // dlopen, dlclose, dlsym
#	endif // !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL

#	if BX_PLATFORM_ANDROID
#		include <malloc.h> // mallinfo
#	elif   BX_PLATFORM_LINUX \
		|| BX_PLATFORM_RPI \
		|| BX_PLATFORM_STEAMLINK
#		include <unistd.h> // syscall
#		include <sys/syscall.h>
#	elif BX_PLATFORM_OSX
#		include <mach/mach.h> // mach_task_basic_info
#	elif BX_PLATFORM_HURD
#		include <pthread/pthread.h> // pthread_self
#	elif BX_PLATFORM_ANDROID
#		include "debug.h" // getTid is not implemented...
#	endif // BX_PLATFORM_ANDROID
#endif // BX_PLATFORM_

#if BX_CRT_MSVC
#	include <direct.h> // _getcwd
#else
#	include <unistd.h> // getcwd
#endif // BX_CRT_MSVC

namespace bx
{

	void sleep(uint32_t _ms)
	{
#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360
		::Sleep(_ms);
#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT
		BX_UNUSED(_ms);
		debugOutput("sleep is not implemented"); debugBreak();
#else
		timespec req = {(time_t)_ms/1000, (long)((_ms%1000)*1000000)};
		timespec rem = {0, 0};
		::nanosleep(&req, &rem);
#endif // BX_PLATFORM_
	}

	void yield()
	{
#if BX_PLATFORM_WINDOWS
		::SwitchToThread();
#elif BX_PLATFORM_XBOX360
		::Sleep(0);
#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT
		debugOutput("yield is not implemented"); debugBreak();
#else
		::sched_yield();
#endif // BX_PLATFORM_
	}

	uint32_t getTid()
	{
#if BX_PLATFORM_WINDOWS
		return ::GetCurrentThreadId();
#elif BX_PLATFORM_LINUX || BX_PLATFORM_RPI || BX_PLATFORM_STEAMLINK
		return (pid_t)::syscall(SYS_gettid);
#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
		return (mach_port_t)::pthread_mach_thread_np(pthread_self() );
#elif BX_PLATFORM_BSD || BX_PLATFORM_NACL
		// Casting __nc_basic_thread_data*... need better way to do this.
		return *(uint32_t*)::pthread_self();
#elif BX_PLATFORM_HURD
		return (pthread_t)::pthread_self();
#else
//#	pragma message "not implemented."
		debugOutput("getTid is not implemented"); debugBreak();
		return 0;
#endif //
	}

	size_t getProcessMemoryUsed()
	{
#if BX_PLATFORM_ANDROID
		struct mallinfo mi = mallinfo();
		return mi.uordblks;
#elif BX_PLATFORM_LINUX || BX_PLATFORM_HURD
		FILE* file = fopen("/proc/self/statm", "r");
		if (NULL == file)
		{
			return 0;
		}

		long pages = 0;
		int items = fscanf(file, "%*s%ld", &pages);
		fclose(file);
		return 1 == items
			? pages * sysconf(_SC_PAGESIZE)
			: 0
			;
#elif BX_PLATFORM_OSX
#	if defined(MACH_TASK_BASIC_INFO)
		mach_task_basic_info info;
		mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;

		int const result = task_info(mach_task_self()
				, MACH_TASK_BASIC_INFO
				, (task_info_t)&info
				, &infoCount
				);
#	else // MACH_TASK_BASIC_INFO
		task_basic_info info;
		mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT;

		int const result = task_info(mach_task_self()
				, TASK_BASIC_INFO
				, (task_info_t)&info
				, &infoCount
				);
#	endif // MACH_TASK_BASIC_INFO
		if (KERN_SUCCESS != result)
		{
			return 0;
		}

		return info.resident_size;
#elif BX_PLATFORM_WINDOWS
		PROCESS_MEMORY_COUNTERS pmc;
		GetProcessMemoryInfo(GetCurrentProcess()
			, &pmc
			, sizeof(pmc)
			);
		return pmc.WorkingSetSize;
#else
		return 0;
#endif // BX_PLATFORM_*
	}

	void* dlopen(const char* _filePath)
	{
#if BX_PLATFORM_WINDOWS
		return (void*)::LoadLibraryA(_filePath);
#elif  BX_PLATFORM_EMSCRIPTEN \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_filePath);
		return NULL;
#else
		return ::dlopen(_filePath, RTLD_LOCAL|RTLD_LAZY);
#endif // BX_PLATFORM_
	}

	void dlclose(void* _handle)
	{
#if BX_PLATFORM_WINDOWS
		::FreeLibrary( (HMODULE)_handle);
#elif  BX_PLATFORM_EMSCRIPTEN \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_handle);
#else
		::dlclose(_handle);
#endif // BX_PLATFORM_
	}

	void* dlsym(void* _handle, const char* _symbol)
	{
#if BX_PLATFORM_WINDOWS
		return (void*)::GetProcAddress( (HMODULE)_handle, _symbol);
#elif  BX_PLATFORM_EMSCRIPTEN \
	|| BX_PLATFORM_NACL \
	|| BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_handle, _symbol);
		return NULL;
#else
		return ::dlsym(_handle, _symbol);
#endif // BX_PLATFORM_
	}

	bool getenv(const char* _name, char* _out, uint32_t* _inOutSize)
	{
#if BX_PLATFORM_WINDOWS
		DWORD len = ::GetEnvironmentVariableA(_name, _out, *_inOutSize);
		bool result = len != 0 && len < *_inOutSize;
		*_inOutSize = len;
		return result;
#elif  BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_name, _out, _inOutSize);
		return false;
#else
		const char* ptr = ::getenv(_name);
		uint32_t len = 0;
		bool result = false;
		if (NULL != ptr)
		{
			len = (uint32_t)strlen(ptr);

			result = len != 0 && len < *_inOutSize;
			if (len < *_inOutSize)
			{
				strcpy(_out, ptr);
			}
		}

		*_inOutSize = len;
		return result;
#endif // BX_PLATFORM_
	}

	void setenv(const char* _name, const char* _value)
	{
#if BX_PLATFORM_WINDOWS
		::SetEnvironmentVariableA(_name, _value);
#elif  BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_name, _value);
#else
		::setenv(_name, _value, 1);
#endif // BX_PLATFORM_
	}

	void unsetenv(const char* _name)
	{
#if BX_PLATFORM_WINDOWS
		::SetEnvironmentVariableA(_name, NULL);
#elif  BX_PLATFORM_PS4 \
	|| BX_PLATFORM_XBOXONE \
	|| BX_PLATFORM_WINRT
		BX_UNUSED(_name);
#else
		::unsetenv(_name);
#endif // BX_PLATFORM_
	}

	int chdir(const char* _path)
	{
#if BX_PLATFORM_PS4 \
 || BX_PLATFORM_XBOXONE \
 || BX_PLATFORM_WINRT
		BX_UNUSED(_path);
		return -1;
#elif BX_CRT_MSVC
		return ::_chdir(_path);
#else
		return ::chdir(_path);
#endif // BX_COMPILER_
	}

	char* pwd(char* _buffer, uint32_t _size)
	{
#if BX_PLATFORM_PS4 \
 || BX_PLATFORM_XBOXONE \
 || BX_PLATFORM_WINRT
		BX_UNUSED(_buffer, _size);
		return NULL;
#elif BX_CRT_MSVC
		return ::_getcwd(_buffer, (int)_size);
#else
		return ::getcwd(_buffer, _size);
#endif // BX_COMPILER_
	}

	bool getTempPath(char* _out, uint32_t* _inOutSize)
	{
#if BX_PLATFORM_WINDOWS
		uint32_t len = ::GetTempPathA(*_inOutSize, _out);
		bool result = len != 0 && len < *_inOutSize;
		*_inOutSize = len;
		return result;
#else
		static const char* s_tmp[] =
		{
			"TMPDIR",
			"TMP",
			"TEMP",
			"TEMPDIR",

			NULL
		};

		for (const char** tmp = s_tmp; *tmp != NULL; ++tmp)
		{
			uint32_t len = *_inOutSize;
			*_out = '\0';
			bool result = getenv(*tmp, _out, &len);

			if (result
			&&  len != 0
			&&  len < *_inOutSize)
			{
				*_inOutSize = len;
				return result;
			}
		}

		return false;
#endif // BX_PLATFORM_*
	}

	bool stat(const char* _filePath, FileInfo& _fileInfo)
	{
		_fileInfo.m_size = 0;
		_fileInfo.m_type = FileInfo::Count;

#if BX_COMPILER_MSVC
		struct ::_stat64 st;
		int32_t result = ::_stat64(_filePath, &st);

		if (0 != result)
		{
			return false;
		}

		if (0 != (st.st_mode & _S_IFREG) )
		{
			_fileInfo.m_type = FileInfo::Regular;
		}
		else if (0 != (st.st_mode & _S_IFDIR) )
		{
			_fileInfo.m_type = FileInfo::Directory;
		}
#else
		struct ::stat st;
		int32_t result = ::stat(_filePath, &st);
		if (0 != result)
		{
			return false;
		}

		if (0 != (st.st_mode & S_IFREG) )
		{
			_fileInfo.m_type = FileInfo::Regular;
		}
		else if (0 != (st.st_mode & S_IFDIR) )
		{
			_fileInfo.m_type = FileInfo::Directory;
		}
#endif // BX_COMPILER_MSVC

		_fileInfo.m_size = st.st_size;

		return true;
	}

	void* exec(const char* const* _argv)
	{
#if BX_PLATFORM_LINUX || BX_PLATFORM_HURD
		pid_t pid = fork();

		if (0 == pid)
		{
			int result = execvp(_argv[0], const_cast<char *const*>(&_argv[1]) );
			BX_UNUSED(result);
			return NULL;
		}

		return (void*)uintptr_t(pid);
#elif BX_PLATFORM_WINDOWS
		STARTUPINFO si;
		memset(&si, 0, sizeof(STARTUPINFO) );
		si.cb = sizeof(STARTUPINFO);

		PROCESS_INFORMATION pi;
		memset(&pi, 0, sizeof(PROCESS_INFORMATION) );

		int32_t total = 0;
		for (uint32_t ii = 0; NULL != _argv[ii]; ++ii)
		{
			total += (int32_t)strlen(_argv[ii]) + 1;
		}

		char* temp = (char*)alloca(total);
		int32_t len = 0;
		for(uint32_t ii = 0; NULL != _argv[ii]; ++ii)
		{
			len += snprintf(&temp[len], bx::uint32_imax(0, total-len)
						, "%s "
						, _argv[ii]
						);
		}

		bool ok = !!CreateProcessA(_argv[0]
					, temp
					, NULL
					, NULL
					, false
					, 0
					, NULL
					, NULL
					, &si
					, &pi
					);
		if (ok)
		{
			return pi.hProcess;
		}

		return NULL;
#else
		BX_UNUSED(_argv);
		return NULL;
#endif // BX_PLATFORM_LINUX || BX_PLATFORM_HURD
	}

} // namespace bx
<|endoftext|>