text:
// Copyright (c) 2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "allowed_args.h"
#include "arith_uint256.h"
#include "chainparamsbase.h"
#include "fs.h"
#include "hash.h"
#include "primitives/block.h"
#include "rpc/client.h"
#include "rpc/protocol.h"
#include "streams.h"
#include "sync.h"
#include "util.h"
#include "utilstrencodings.h"

#include <cstdlib>
#include <stdio.h>

#include <event2/buffer.h>
#include <event2/event.h>
#include <event2/http.h>
#include <event2/keyvalq_struct.h>

#include <univalue.h>

using namespace std;

#ifdef DEBUG_LOCKORDER
#include <boost/thread/tss.hpp>
// BU add lockstack stuff here for bitcoin-cli, because I need to carefully
// order it in globals.cpp for bitcoind and bitcoin-qt
boost::mutex dd_mutex;
std::map<std::pair<void *, void *>, LockStack> lockorders;
boost::thread_specific_ptr<LockStack> lockstack;
#endif

// Internal miner
//
// ScanHash scans nonces looking for a hash with at least some zero bits.
// The nonce is usually preserved between calls, but periodically or if the
// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
// zero.
bool static ScanHash(const CBlockHeader *pblock, uint32_t &nNonce, uint256 *phash)
{
    // Write the first 76 bytes of the block header to a double-SHA256 state.
    CHash256 hasher;
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << *pblock;
    assert(ss.size() == 80);
    hasher.Write((unsigned char *)&ss[0], 76);

    while (true)
    {
        nNonce++;

        // Write the last 4 bytes of the block header (the nonce) to a copy of
        // the double-SHA256 state, and compute the result.
        CHash256(hasher).Write((unsigned char *)&nNonce, 4).Finalize((unsigned char *)phash);

        // Return the nonce if the hash has at least some zero bits,
        // caller will check if it has enough to reach the target
        if (((uint16_t *)phash)[15] == 0)
            return true;

        // If nothing found after trying for a while, return -1
        if ((nNonce & 0xfff) == 0)
            return false;
    }
}

class BitcoinMinerArgs : public AllowedArgs::BitcoinCli
{
public:
    BitcoinMinerArgs(CTweakMap *pTweaks = nullptr)
    {
        addHeader(_("Mining options:"))
            .addArg("blockversion=<n>", ::AllowedArgs::requiredInt,
                _("Set the block version number. For testing only.  Value must be an integer"))
            .addArg("cpus=<n>", ::AllowedArgs::requiredInt,
                _("Number of cpus to use for mining (default: 1).  Value must be an integer"))
            .addArg("duration=<n>", ::AllowedArgs::requiredInt,
                _("Number of seconds to mine a particular block candidate (default: 30). Value must be an integer"))
            .addArg("nblocks=<n>", ::AllowedArgs::requiredInt,
                _("Number of blocks to mine (default: mine forever / -1). Value must be an integer"))
            .addArg("coinbasesize=<n>", ::AllowedArgs::requiredInt,
                _("Get a fixed size coinbase Tx (default: do not use / 0). Value must be an integer"));
    }
};

static CBlockHeader CpuMinerJsonToHeader(const UniValue &params)
{
    // Does not set hashMerkleRoot (Does not exist in Mining-Candidate params).
    CBlockHeader blockheader;

    // nVersion
    blockheader.nVersion = params["version"].get_int();

    // hashPrevBlock
    string tmpstr = params["prevhash"].get_str();
    std::vector<unsigned char> vec = ParseHex(tmpstr);
    std::reverse(vec.begin(), vec.end()); // sent reversed
    blockheader.hashPrevBlock = uint256(vec);

    // nTime:
    blockheader.nTime = params["time"].get_int();

    // nBits
    {
        std::stringstream ss;
        ss << std::hex << params["nBits"].get_str();
        ss >> blockheader.nBits;
    }

    return blockheader;
}

static void CalculateNextMerkleRoot(uint256 &merkle_root, const uint256 &merkle_branch)
{
    // Append a branch to the root. Double SHA256 the whole thing:
    uint256 hash;
    CHash256()
        .Write(merkle_root.begin(), merkle_root.size())
        .Write(merkle_branch.begin(), merkle_branch.size())
        .Finalize(hash.begin());
    merkle_root = hash;
}

static uint256 CalculateMerkleRoot(uint256 &coinbase_hash, const std::vector<uint256> &merkleproof)
{
    uint256 merkle_root = coinbase_hash;
    for (unsigned int i = 0; i < merkleproof.size(); i++)
    {
        CalculateNextMerkleRoot(merkle_root, merkleproof[i]);
    }
    return merkle_root;
}

static bool CpuMineBlockHasher(CBlockHeader *pblock,
    vector<unsigned char> &coinbaseBytes,
    const std::vector<uint256> &merkleproof)
{
    uint32_t nExtraNonce = std::rand();
    uint32_t nNonce = pblock->nNonce;
    arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
    bool found = false;
    int ntries = 10;
    unsigned char *pbytes = (unsigned char *)&coinbaseBytes[0];

    while (!found)
    {
        // hashMerkleRoot:
        {
            ++nExtraNonce;
            // 48 - next in arr after Height. (Height in coinbase required for block.version=2):
            *(unsigned int *)(pbytes + 48) = nExtraNonce;
            uint256 hash;
            CHash256().Write(pbytes, coinbaseBytes.size()).Finalize(hash.begin());

            pblock->hashMerkleRoot = CalculateMerkleRoot(hash, merkleproof);
        }

        //
        // Search
        //
        uint256 hash;
        while (!found)
        {
            // Check if something found
            if (ScanHash(pblock, nNonce, &hash))
            {
                if (UintToArith256(hash) <= hashTarget)
                {
                    // Found a solution
                    pblock->nNonce = nNonce;
                    found = true;
                    printf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", hash.GetHex().c_str(),
                        hashTarget.GetHex().c_str());
                    break;
                }
                else
                {
                    if (ntries-- < 1)
                    {
                        pblock->nNonce = nNonce; // report the last nonce checked for accounting
                        return false; // Give up leave
                    }
                }
            }
        }
    }

    return found;
}

static double GetDifficulty(uint64_t nBits)
{
    int nShift = (nBits >> 24) & 0xff;

    double dDiff = (double)0x0000ffff / (double)(nBits & 0x00ffffff);

    while (nShift < 29)
    {
        dDiff *= 256.0;
        nShift++;
    }
    while (nShift > 29)
    {
        dDiff /= 256.0;
        nShift--;
    }
    return dDiff;
}

static UniValue CpuMineBlock(unsigned int searchDuration, const UniValue &params, bool &found)
{
    UniValue tmp(UniValue::VOBJ);
    UniValue ret(UniValue::VARR);
    string tmpstr;
    std::vector<uint256> merkleproof;
    CBlockHeader header;
    vector<unsigned char> coinbaseBytes(ParseHex(params["coinbase"].get_str()));

    found = false;

    // re-create merkle branches:
    {
        UniValue uvMerkleproof = params["merkleProof"];
        for (unsigned int i = 0; i < uvMerkleproof.size(); i++)
        {
            tmpstr = uvMerkleproof[i].get_str();
            std::vector<unsigned char> mbr = ParseHex(tmpstr);
            std::reverse(mbr.begin(), mbr.end());
            merkleproof.push_back(uint256(mbr));
        }
    }

    header = CpuMinerJsonToHeader(params);

    // Set the version (only to test):
    {
        int blockversion = GetArg("-blockversion", header.nVersion);
        if (blockversion != header.nVersion)
            printf("Force header.nVersion to %d\n", blockversion);
        header.nVersion = blockversion;
    }

    uint32_t startNonce = header.nNonce = std::rand();

    printf("Mining: id: %x parent: %s bits: %x difficulty: %3.2f time: %d\n", (unsigned int)params["id"].get_int64(),
        header.hashPrevBlock.ToString().c_str(), header.nBits, GetDifficulty(header.nBits), header.nTime);

    int64_t start = GetTime();
    while ((GetTime() < start + searchDuration) && !found)
    {
        // When mining mainnet, you would normally want to advance the time to keep the block time as close to the
        // real time as possible.  However, this CPU miner is only useful on testnet and in testnet the block difficulty
        // resets to 1 after 20 minutes.  This will cause the block's difficulty to mismatch the expected difficulty
        // and the block will be rejected.  So do not advance time (let it be advanced by bitcoind every time we
        // request a new block).
        // header.nTime = (header.nTime < GetTime()) ? GetTime() : header.nTime;
        found = CpuMineBlockHasher(&header, coinbaseBytes, merkleproof);
    }

    // Leave if not found:
    if (!found)
    {
        printf("Checked %llu possibilities\n", (unsigned long long)(header.nNonce - startNonce));
        return ret;
    }

    printf("Solution! Checked %llu possibilities\n", (unsigned long long )(header.nNonce - startNonce));

    tmpstr = HexStr(coinbaseBytes.begin(), coinbaseBytes.end());
    tmp.pushKV("coinbase", tmpstr);
    tmp.pushKV("id", params["id"]);
    tmp.pushKV("time", UniValue(header.nTime)); // Optional. We have changed so must send.
    tmp.pushKV("nonce", UniValue(header.nNonce));
    tmp.pushKV("version", UniValue(header.nVersion)); // Optional. We may have changed so sending.
    ret.push_back(tmp);

    return ret;
}

static UniValue RPCSubmitSolution(const UniValue &solution, int &nblocks)
{
    UniValue reply = CallRPC("submitminingsolution", solution);

    const UniValue &error = find_value(reply, "error");

    if (!error.isNull())
    {
        fprintf(stderr, "Block Candidate submission error: %d %s\n", error["code"].get_int(),
            error["message"].get_str().c_str());
        return reply;
    }

    const UniValue &result = find_value(reply, "result");

    if (result.isStr())
    {
        fprintf(stderr, "Block Candidate rejected. Error: %s\n", result.get_str().c_str());
        // Print some debug info if the block is rejected
        UniValue dbg = solution[0].get_obj();
        fprintf(stderr, "id: %d  time: %d  nonce: %d  version: 0x%x\n", (unsigned int)dbg["id"].get_int64(),
            (uint32_t)dbg["time"].get_int64(), (uint32_t)dbg["nonce"].get_int64(), (uint32_t)dbg["version"].get_int());
        fprintf(stderr, "coinbase: %s\n", dbg["coinbase"].get_str().c_str());
    }
    else
    {
        if (result.isNull())
        {
            printf("Block Candidate accepted.\n");
            if (nblocks > 0)
                nblocks--; // Processed a block
        }
        else
        {
            fprintf(stderr, "Unknown \"submitminingsolution\" Error.\n");
        }
    }

    return reply;
}

int CpuMiner(void)
{
    int searchDuration = GetArg("-duration", 30);
    int nblocks = GetArg("-nblocks", -1); //-1 mine forever
    int coinbasesize = GetArg("-coinbasesize", 0);

    if (coinbasesize < 0)
    {
        printf("Negative coinbasesize not reasonable/supported.\n");
        return 0;
    }

    UniValue mineresult;
    bool found = false;

    if (0 == nblocks)
    {
        printf("Nothing to do for zero (0) blocks\n");
        return 0;
    }

    while (0 != nblocks)
    {
        UniValue reply;
        UniValue result;
        string strPrint;
        int nRet = 0;
        try
        {
            // Execute and handle connection failures with -rpcwait
            const bool fWait = true;
            do
            {
                try
                {
                    UniValue params(UniValue::VARR);
                    if (found)
                    {
                        // Submit the solution.
                        // Called here so all exceptions are handled properly below.
                        reply = RPCSubmitSolution(mineresult, nblocks);
                        if (nblocks == 0)
                            return 0; // Done mining exit program
                        found = false; // Mine again
                    }

                    if (!found)
                    {
                        if (coinbasesize > 0)
                        {
                            params.push_back(UniValue(coinbasesize));
                        }
                        reply = CallRPC("getminingcandidate", params);
                    }

                    // Parse reply
                    result = find_value(reply, "result");
                    const UniValue &error = find_value(reply, "error");

                    if (!error.isNull())
                    {
                        // Error
                        int code = error["code"].get_int();
                        if (fWait && code == RPC_IN_WARMUP)
                            throw CConnectionFailed("server in warmup");
                        strPrint = "error: " + error.write();
                        nRet = abs(code);
                        if (error.isObject())
                        {
                            UniValue errCode = find_value(error, "code");
                            UniValue errMsg = find_value(error, "message");
                            strPrint = errCode.isNull() ? "" : "error code: " + errCode.getValStr() + "\n";

                            if (errMsg.isStr())
                                strPrint += "error message:\n" + errMsg.get_str();
                        }
                    }
                    else
                    {
                        // Result
                        if (result.isNull())
                            strPrint = "";
                        else if (result.isStr())
                            strPrint = result.get_str();
                        else
                            strPrint = result.write(2);
                    }
                    // Connection succeeded, no need to retry.
                    break;
                }
                catch (const CConnectionFailed &c)
                {
                    if (fWait)
                    {
                        printf("Warning: %s\n", c.what());
                        MilliSleep(1000);
                    }
                    else
                        throw;
                }
            } while (fWait);
        }
        catch (const boost::thread_interrupted &)
        {
            throw;
        }
        catch (const std::exception &e)
        {
            strPrint = string("error: ") + e.what();
            nRet = EXIT_FAILURE;
        }
        catch (...)
        {
            PrintExceptionContinue(NULL, "CommandLineRPC()");
            throw;
        }

        if (strPrint != "")
        {
            if (nRet != 0)
                fprintf(stderr, "%s\n", strPrint.c_str());
            // Actually do some mining
            if (result.isNull())
            {
                MilliSleep(1000);
            }
            else
            {
                found = false;
                mineresult = CpuMineBlock(searchDuration, result, found);
                if (!found)
                {
                    // printf("Mining did not succeed\n");
                    mineresult.setNull();
                }
                // The result is sent to bitcoind above when the loop gets to it.
                // See:   RPCSubmitSolution(mineresult,nblocks);
                // This is so RPC Exceptions are handled in one place.
            }
        }
    }
    return 0;
}

void static MinerThread()
{
    while (1)
    {
        try
        {
            CpuMiner();
        }
        catch (const std::exception &e)
        {
            PrintExceptionContinue(&e, "CommandLineRPC()");
        }
        catch (...)
        {
            PrintExceptionContinue(NULL, "CommandLineRPC()");
        }
    }
}

int main(int argc, char *argv[])
{
    SetupEnvironment();
    if (!SetupNetworking())
    {
        fprintf(stderr, "Error: Initializing networking failed\n");
        exit(1);
    }

    try
    {
        std::string appname("bitcoin-miner");
        std::string usage = "\n" + _("Usage:") + "\n" + "  " + appname + " [options] " + "\n";
        int ret = AppInitRPC(usage, BitcoinMinerArgs(), argc, argv);
        if (ret != CONTINUE_EXECUTION)
            return ret;
    }
    catch (const std::exception &e)
    {
        PrintExceptionContinue(&e, "AppInitRPC()");
        return EXIT_FAILURE;
    }
    catch (...)
    {
        PrintExceptionContinue(NULL, "AppInitRPC()");
        return EXIT_FAILURE;
    }

    int nThreads = GetArg("-cpus", 1);
    boost::thread_group minerThreads;
    for (int i = 0; i < nThreads - 1; i++)
        minerThreads.create_thread(MinerThread);

    int ret = EXIT_FAILURE;
    try
    {
        ret = CpuMiner();
    }
    catch (const std::exception &e)
    {
        PrintExceptionContinue(&e, "CommandLineRPC()");
    }
    catch (...)
    {
        PrintExceptionContinue(NULL, "CommandLineRPC()");
    }
    return ret;
}

max_stars_repo_name: diskcoin-apps-team/Diskcoin

max_issues_repo_name: diskcoin-apps-team/Diskcoin

max_forks_repo_name: diskcoin-apps-team/Diskcoin


text:
/*
 ******************************************************************************
 Project:      OWA EPANET
 Version:      2.2
 Module:       util/test_filemanager.cpp
 Description:  Tests for util/filemanager.c
 Authors:      see AUTHORS
 Copyright:    see AUTHORS
 License:      see LICENSE
 Last Updated: 04/01/2019
 ******************************************************************************
*/

#define BOOST_TEST_MODULE filemanager

#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>

#include "shared/filemanager.h"

#define DATA_PATH_OUTPUT "./example1.out"

boost::test_tools::predicate_result check_string(std::string test, std::string ref)
{
    if (ref.compare(test) == 0)
        return true;
    else
        return false;
}

BOOST_AUTO_TEST_SUITE(test_filemanager)

BOOST_AUTO_TEST_CASE (test_create_destroy)
{
    file_handle_t *file_handle = NULL;

    file_handle = create_file_manager();
    BOOST_CHECK(file_handle != NULL);
	BOOST_CHECK(is_valid(file_handle) == true);

    delete_file_manager(file_handle);
}

BOOST_AUTO_TEST_CASE(test_open_close)
{
    int error = 0;
    file_handle_t *file_handle = NULL;

    file_handle = create_file_manager();
    BOOST_CHECK(file_handle != NULL);

    error = open_file(file_handle, DATA_PATH_OUTPUT, "rb");
    BOOST_REQUIRE(error == 0);
	BOOST_CHECK(is_valid(file_handle) == true);

    error = close_file(file_handle);
    BOOST_REQUIRE(error == 0);

    delete_file_manager(file_handle);
}

struct Fixture{
    Fixture() {
		error = 0;
        file_handle = NULL;

		file_handle = create_file_manager();
        open_file(file_handle, NULL, "wt");
    }
    ~Fixture() {
        close_file(file_handle);
        delete_file_manager(file_handle);
  }
  int error;
  file_handle_t *file_handle;
};

BOOST_FIXTURE_TEST_CASE(test_temp_file, Fixture)
{
    char *filename;

    printf_file(file_handle, "%s", "This is a test.");

    error = get_filename(file_handle, &filename);
    BOOST_REQUIRE(error == 0);
    BOOST_CHECK(is_valid(file_handle) == true);

    BOOST_CHECK(boost::filesystem::exists(filename) == true);

    free(filename);
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_issues_repo_name: michaeltryby/epanet-solver

max_forks_repo_name: michaeltryby/epanet-solver


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

#include <boost/program_options.hpp>

#include <iostream>
#include <fstream>
#include <string>

#include "libcppl.hh"
#include "performance.h"

namespace  {
    const size_t SUCCESS = 0;
    const size_t ERROR_IN_COMMAND_LINE = 1;
    const size_t ERROR_UNHANDLED_EXCEPTION = 2;
    const size_t POLICY_ERROR = 3;
}

int main (int argc, char *argv[])  {
    try  {
        //default options that can be overwriten by the program options
        bool traceParsingEnabled = false;
        bool traceScanningEnabled = false;
        string inputFile;
        string policyDefinitionFile;
        string outputFile;

        //Define and parse the program options
        namespace po = boost::program_options;
        po::options_description desc("Options");
        desc.add_options()
            ("help", "Print help message")
            ("input-file", po::value<string>(), "input file")
            ("policy-definition-file", po::value<string>(), "JSON file that represents the policy definition")
            ("output-file,o", po::value<string>(), "Writes the compressed policy to this file (example: $(basename <input-file>).ccppl)")
            ("trace-parsing,p", "Print the parser trace (for debugging)")
            ("trace-scanning,s", "Print the scanning trace (for debugging)");

        //all positional options should be translated into "input-file" options
        po::positional_options_description p;
        p.add("input-file", -1);

        po::variables_map vm;
        try  {
            po::store(po::command_line_parser(argc, argv).
                              options(desc).positional(p).run(), vm);

            //--help option
            if(vm.count("help"))  {
                std::cout << "Compact Privacy Policy Language Generator" << std::endl
                    << desc << std::endl;
                return SUCCESS;
            }

            //trace parsing options
            if(vm.count("trace-parsing"))  {
                traceParsingEnabled = true;
            }

            //trace scanning options
            if(vm.count("trace-scanning"))  {
                traceScanningEnabled = true;
            }

            //input-file
            if(vm.count("input-file"))  {
                inputFile = vm["input-file"].as<string>();
            } else  {
                std::cerr << "No input file!" << std::endl;
                return ERROR_IN_COMMAND_LINE;
            }

            //policy-definition-file
            if(vm.count("policy-definition-file"))  {
                policyDefinitionFile = vm["policy-definition-file"].as<string>();
            } else  {
                std::cerr << "No policy definition file parameter!" << std::endl;
                return ERROR_IN_COMMAND_LINE;
            }

            //output-file
            if(vm.count("output-file"))  {
                outputFile = vm["output-file"].as<string>();
            } else  {
                std::cerr << "No output file!" << std::endl;
                return ERROR_IN_COMMAND_LINE;
            }

            po::notify(vm); // throws on error
        }
        catch(po::error& e)  {
            std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
            std::cerr << desc << std::endl;
            return ERROR_IN_COMMAND_LINE;
        }

        //application code
#if EVALUATION_OUTPUT
		performance_start_benchmark();
#endif
		PolicyDefinition * policyDefinition = cppl_read_policy_definition_from_file(policyDefinitionFile);
		cppl_compress_policy_to_file(cppl_read_policy_from_file(inputFile), *policyDefinition, outputFile, traceParsingEnabled, traceScanningEnabled);
#if EVALUATION_OUTPUT
		performance_stop_benchmark("Gen compressor time");
#endif

    }
    catch(char const *msg)  {
        std::cerr << "Policy Error: " << msg << std::endl;
        return POLICY_ERROR;
    }
    catch(std::exception& e)  {
        std::cerr << "Unhandled Exception reached the top of main: "
            << e.what() << ", application will now exit" << std::endl;
        return ERROR_UNHANDLED_EXCEPTION;

    }

    return SUCCESS;
}

ext: cc

max_stars_repo_name: SSICLOPS/cppl

max_issues_repo_name: SSICLOPS/cppl

max_forks_repo_name: SSICLOPS/cppl


text: #include <boost/type_traits/is_empty.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Sylko Olzscher
 *
 */

#include "cluster.h"
#include "system.h"
#include <smf/cluster/generator.h>

#include <cyng/async/task/task_builder.hpp>
#include <cyng/io/serializer.h>
#include <cyng/vm/generator.h>
#include <cyng/vm/domain/log_domain.h>
#include <cyng/table/meta.hpp>
#include <cyng/tuple_cast.hpp>
#include <cyng/set_cast.h>
#include <cyng/factory/set_factory.h>
#include <cyng/dom/reader.h>
#include <cyng/json.h>
#include <cyng/xml.h>
#include <cyng/parser/chrono_parser.h>
#include <cyng/io/io_chrono.hpp>

#include <boost/uuid/nil_generator.hpp>
#include <boost/uuid/string_generator.hpp>
#include <boost/algorithm/string/predicate.hpp>

namespace node
{
	cluster::cluster(cyng::async::base_task* btp
		, cyng::logging::log_ptr logger
		, boost::uuids::uuid cluster_tag
		, cluster_config_t const& cfg_cls
		, boost::asio::ip::tcp::endpoint ep
		, std::string const& doc_root
#ifdef NODE_SSL_INSTALLED
		, auth_dirs const& ad
#endif
		, std::set<boost::asio::ip::address> const& blacklist
		, bool https_rewrite)
	: base_(*btp)
		, uidgen_()
		, bus_(bus_factory(btp->mux_, logger, cluster_tag, btp->get_id()))
		, logger_(logger)
		, config_(cfg_cls)
		, cache_()
		, server_(logger
			, btp->mux_.get_io_service()
			, ep
			, doc_root
			, ""	//	no blog
#ifdef NODE_SSL_INSTALLED
			, ad
#endif
			, blacklist
			, bus_->vm_
			, https_rewrite)
		, dispatcher_(logger, server_.get_cm())
		, db_sync_(logger, cache_)
		, forward_(logger, cache_, server_.get_cm())
		, form_data_(logger)
		, sys_tsk_(cyng::async::NO_TASK)
	{
		CYNG_LOG_INFO(logger_, "initialize task #"
			<< base_.get_id()
			<< " <"
			<< base_.get_class_name()
			<< ">");

		//
		//	init cache
		//
		create_cache(logger_, cache_);

		//
		//	handle form data
		//
		form_data_.register_this(bus_->vm_);

		//
		//	implement request handler
		//
		bus_->vm_.register_function("bus.reconfigure", 1, std::bind(&cluster::reconfigure, this, std::placeholders::_1));

		//
		//	data handling
		//
		bus_->vm_.register_function("db.trx.start", 0, [this](cyng::context& ctx) {
			CYNG_LOG_TRACE(logger_, "db.trx.start");
		});
		bus_->vm_.register_function("db.trx.commit", 0, [this](cyng::context& ctx) {
			CYNG_LOG_TRACE(logger_, "db.trx.commit");
		});
		bus_->vm_.register_function("bus.res.subscribe", 6, std::bind(&cluster::res_subscribe, this, std::placeholders::_1));
		db_sync_.register_this(bus_->vm_);

		forward_.register_this(bus_->vm_);

		bus_->vm_.register_function("http.session.launch", 3, [this](cyng::context& ctx) {
			//	[849a5b98-429c-431e-911d-18a467a818ca,false,127.0.0.1:61383]
			const cyng::vector_t frame = ctx.get_frame();
			CYNG_LOG_INFO(logger_, "http.session.launch " << cyng::io::to_str(frame));
		});

		bus_->vm_.register_function("http.authorized", 4, [this](cyng::context& ctx) {
			//	[7f1f9096-dd3b-4a64-a2ed-3b4c97ac9246,true,Basic,sol,/,127.0.0.1:59138]
			const cyng::vector_t frame = ctx.get_frame();
			CYNG_LOG_INFO(logger_, "http.authorized " << cyng::io::to_str(frame));

			auto tpl = cyng::tuple_cast<
				boost::uuids::uuid,		//	[0] origin session id
				bool,					//	[1] success
				std::string,			//	[2] authorization type
				std::string,			//	[3] user
				std::string,			//	[4] path
				boost::asio::ip::tcp::endpoint	//	[5] remote endpoint
			>(frame);

			//
			//	emit system message
			//
			std::stringstream ss;
			ss
				<< std::get<3>(tpl)
				<< " authorized for "
				<< std::get<4>(tpl)
				<< " from "
				<< std::get<5>(tpl)
				<< (std::get<1>(tpl) ? " with" : " without")
				<< " success"
				;

			ctx.queue(bus_insert_msg((std::get<1>(tpl) ? cyng::logging::severity::LEVEL_TRACE : cyng::logging::severity::LEVEL_WARNING), ss.str()));

		});

		//
		//	input from HTTP session / ws
		//
		bus_->vm_.register_function("ws.read", 2, std::bind(&cluster::ws_read, this, std::placeholders::_1));

		bus_->vm_.async_run(cyng::generate_invoke("log.msg.info", cyng::invoke("lib.size"), "callbacks registered"));

		//
		//	subscribe to database
		//
		dispatcher_.subscribe(cache_);
		dispatcher_.register_this(bus_->vm_);

	}

    void cluster::start_sys_task()
    {
        //
        // start collecting system data
        //
        auto r = cyng::async::start_task_delayed<system>(base_.mux_, std::chrono::seconds(2), logger_, cache_, bus_->vm_.tag());
        if (r.second)
        {
            sys_tsk_ = r.first;
        }
        else
        {
            CYNG_LOG_ERROR(logger_, "could not start system task");
        }
    }

    void cluster::stop_sys_task()
    {
        if (sys_tsk_ != cyng::async::NO_TASK)
        {
            base_.mux_.stop(sys_tsk_);
        }
    }

	cyng::continuation cluster::run()
	{
		if (!bus_->is_online())
		{
			connect();
		}
		else
		{
			CYNG_LOG_DEBUG(logger_, "cluster bus is online");
		}

		return cyng::continuation::TASK_CONTINUE;
	}

	void cluster::stop()
	{
        //
        //  stop collecting system data
        //
        stop_sys_task();

		//
		//	stop server
		//
		server_.close();

		//
		//	sign off from cluster
		//
        bus_->stop();

		CYNG_LOG_INFO(logger_, "task #"
			<< base_.get_id()
			<< " <"
			<< base_.get_class_name()
			<< "> stopped - leaving cluster");
	}

	//	slot 0
	cyng::continuation cluster::process(cyng::version const& v)
	{
		if (v < cyng::version(NODE_VERSION_MAJOR, NODE_VERSION_MINOR))
		{
			CYNG_LOG_WARNING(logger_, "insufficient cluster protocol version: "	<< v);
		}

        //
        //  collect system data
        //
        start_sys_task();

		//
		//	start http server
		//
		server_.run();

		//
		//	sync tables
		//
		sync_table("TDevice");
		sync_table("TGateway");
		sync_table("TLoRaDevice");
		sync_table("TMeter");
		sync_table("_Session");
		sync_table("_Target");
		sync_table("_Connection");
		sync_table("_Cluster");
		sync_table("_Config");
		cache_.clear("_SysMsg", bus_->vm_.tag());
		sync_table("_SysMsg");
		cache_.clear("_TimeSeries", bus_->vm_.tag());
		sync_table("_TimeSeries");
		cache_.clear("_LoRaUplink", bus_->vm_.tag());
		sync_table("_LoRaUplink");
		sync_table("_CSV");

		return cyng::continuation::TASK_CONTINUE;
	}

	void cluster::sync_table(std::string const& name)
	{
		CYNG_LOG_INFO(logger_, "sync table " << name);

		//
		//	manage table state
		//
		cache_.set_state(name, 0);

		//
		//	Get existing records from master. This could be setup data
		//	from another redundancy or data collected during a line disruption.
		//
		bus_->vm_.async_run(bus_req_subscribe(name, base_.get_id()));

	}

	cyng::continuation cluster::process()
	{
		//
		//	Connection to master lost
		//

        //
        //  stop collecting system data
        //
        stop_sys_task();

		//
		//	tell server to discard all data
		//
		clear_cache(cache_, bus_->vm_.tag());

		//
		//	switch to other configuration
		//
		reconfigure_impl();

		//
		//	continue task
		//
		return cyng::continuation::TASK_CONTINUE;
	}

	void cluster::connect()
	{
		BOOST_ASSERT_MSG(!bus_->vm_.is_halted(), "cluster bus is halted");
		bus_->vm_.async_run(bus_req_login(config_.get().host_
			, config_.get().service_
			, config_.get().account_
			, config_.get().pwd_
			, config_.get().auto_config_
			, config_.get().group_
			, "dash"));

		CYNG_LOG_INFO(logger_, "cluster login request is sent to "
			<< config_.get().host_
			<< ':'
			<< config_.get().service_);

	}

	void cluster::reconfigure(cyng::context& ctx)
	{
		reconfigure_impl();
	}

	void cluster::reconfigure_impl()
	{
		//
		//	switch to other master
		//
		if (config_.next())
		{
			CYNG_LOG_INFO(logger_, "switch to redundancy "
				<< config_.get().host_
				<< ':'
				<< config_.get().service_);
		}
		else
		{
			CYNG_LOG_ERROR(logger_, "cluster login failed - no other redundancy available");
		}

		//
		//	trigger reconnect
		//
		CYNG_LOG_INFO(logger_, "reconnect to cluster in "
			<< config_.get().monitor_.count()
			<< " seconds");
		base_.suspend(config_.get().monitor_);

	}

	void cluster::res_subscribe(cyng::context& ctx)
	{
		const cyng::vector_t frame = ctx.get_frame();
		//
		//	examples:
		//	[TDevice,[911fc4a1-8d9b-4d18-97f7-84a1cd576139],[00000006,2018-02-04 15:31:37.00000000,true,v88,ID,comment #88,1088,secret,device-88],88,dfa6b9a1-4170-41bd-8945-80b936059231,1]
		//	[TGateway,[dca135f3-ff2b-4bf7-8371-a9904c74522b],[operator,operator,mbus,pwd,user,00:01:02:03:04:06,00:01:02:03:04:05,factory-nr,VSES-1.13_1133000038X025d,2018-06-05 16:01:06.29959300,EMH-VSES,EMH,05000000000000],0,e197fc51-0f13-4643-968d-8d0332bae068,1]
		//	[*SysMsg,[14],[cluster member dash:63efc328-218a-4635-a582-1cb4ddc7af25 closed,4,2018-06-05 16:17:50.88472100],1,e197fc51-0f13-4643-968d-8d0332bae068,1]
		//
		//	* table name
		//	* record key
		//	* record data
		//	* generation
		//	* origin session id
		//	* optional task id
		//
		//CYNG_LOG_TRACE(logger_, "res.subscribe - " << cyng::io::to_str(frame));

		auto tpl = cyng::tuple_cast<
			std::string,			//	[0] table name
			cyng::table::key_type,	//	[1] table key
			cyng::table::data_type,	//	[2] record
			std::uint64_t,			//	[3] generation
			boost::uuids::uuid,		//	[4] origin session id
			std::size_t				//	[5] optional task id
		>(frame);

		CYNG_LOG_TRACE(logger_, "res.subscribe "
			<< std::get<0>(tpl)		// table name
			<< " - "
			<< cyng::io::to_str(std::get<1>(tpl)));

		//
		//	reorder vectors
		//
		std::reverse(std::get<1>(tpl).begin(), std::get<1>(tpl).end());
		std::reverse(std::get<2>(tpl).begin(), std::get<2>(tpl).end());

		node::res_subscribe(logger_
			, cache_
			, std::get<0>(tpl)	//	[0] table name
			, std::get<1>(tpl)	//	[1] table key
			, std::get<2>(tpl)	//	[2] record
			, std::get<3>(tpl)	//	[3] generation
			, std::get<4>(tpl)	//	[4] origin session id
			, std::get<5>(tpl));
	}

	void cluster::ws_read(cyng::context& ctx)
	{
		//	[1adb06d2-bfbf-4b00-a7b1-80b49ba48f79,{("cmd":subscribe),("channel":status.session),("push":true)}]
		//
		//	* session tag
		//	* ws object
		//	* json object
		const cyng::vector_t frame = ctx.get_frame();

		//
		//	get session tag of websocket
		//
		auto tag_ws = cyng::value_cast(frame.at(0), boost::uuids::nil_uuid());
		BOOST_ASSERT_MSG(!tag_ws.is_nil(), "no websocket");

		//
		//	reader for JSON data
		//
		auto reader = cyng::make_reader(frame.at(1));
		const std::string cmd = cyng::value_cast<std::string>(reader.get("cmd"), "");
		const std::string channel = cyng::value_cast<std::string>(reader.get("channel"), "generic");

		if (boost::algorithm::equals(cmd, "subscribe"))
		{
			//const std::string channel = cyng::value_cast<std::string>(reader.get("channel"), "");
			CYNG_LOG_TRACE(logger_, "ws.read - subscribe channel [" << channel << "]");

			//
			//	Subscribe a table and start initial upload
			//
			dispatcher_.subscribe_channel(cache_, channel, tag_ws);

		}
		else if (boost::algorithm::equals(cmd, "update"))
		{
			//const std::string channel = cyng::value_cast<std::string>(reader.get("channel"), "");
			CYNG_LOG_TRACE(logger_, "ws.read - pull channel [" << channel << "]");
			dispatcher_.pull(cache_, channel, tag_ws);
		}
		else if (boost::algorithm::equals(cmd, "insert"))
		{
			node::fwd_insert(logger_
				, ctx
				, reader
				, uidgen_());
		}
		else if (boost::algorithm::equals(cmd, "delete"))
		{
			node::fwd_delete(logger_
				, ctx
				, reader);
		}
		else if (boost::algorithm::equals(cmd, "modify"))
		{
			node::fwd_modify(logger_
				, ctx
				, reader);
		}
		else if (boost::algorithm::equals(cmd, "stop"))
		{
			node::fwd_stop(logger_
				, ctx
				, reader);
		}
		else if (boost::algorithm::equals(cmd, "config:gateway"))
		{
			node::fwd_config_gateway(logger_
				, ctx
				, tag_ws
				, channel
				, reader);
		}
		else
		{
			CYNG_LOG_WARNING(logger_, "ws.read - unknown command " << cmd);
		}
	}
}

max_stars_repo_name: solosTec/node

max_issues_repo_name: solosTec/node

max_forks_repo_name: solosTec/node


text:
//  (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
//  Use, modification, and distribution is subject to the Boost Software
//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See library home page at http://www.boost.org/libs/numeric/conversion
//
// Contact the author at: fernando_cacciola@hotmail.com
//
//
//  Revision History
//
//    19 Nov 2001 Syntatic changes as suggested by Darin Adler (Fernando Cacciola)
//    08 Nov 2001 Fixes to accommodate MSVC (Fernando Cacciola)
//    04 Nov 2001 Fixes to accommodate gcc2.92 (Fernando Cacciola)
//    30 Oct 2001 Some fixes suggested by Daryle Walker (Fernando Cacciola)
//    25 Oct 2001 Initial boostification (Fernando Cacciola)
//    23 Jan 2004 Inital add to cvs (post review)s
//
#ifndef BOOST_NUMERIC_CONVERSION_CAST_25OCT2001_HPP
#define BOOST_NUMERIC_CONVERSION_CAST_25OCT2001_HPP

#include <boost/detail/workaround.hpp>

#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))

#  include<boost/numeric/conversion/detail/old_numeric_cast.hpp>

#else

#include <boost/type.hpp>
#include <boost/numeric/conversion/converter.hpp>

namespace boost
{
  template<typename Target, typename Source>
  inline
  Target numeric_cast ( Source arg )
  {
    typedef boost::numeric::converter<Target,Source> Converter ;
    return Converter::convert(arg);
  }

  using numeric::bad_numeric_cast;

} // namespace boost

#endif

#endif

max_stars_repo_name: dyzmapl/BumpTop

max_issues_repo_name: dyzmapl/BumpTop

max_forks_repo_name: dyzmapl/BumpTop


text:
/*
 * Copyright 2019,
 * François Bleibel,
 * Olivier Stasse,
 *
 * CNRS/AIST
 *
 */

/* -------------------------------------------------------------------------- */
/* --- INCLUDES ------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include <iostream>

#include <pinocchio/algorithm/frames.hpp>
#include <pinocchio/algorithm/jacobian.hpp>
#include <pinocchio/algorithm/joint-configuration.hpp>
#include <pinocchio/algorithm/kinematics.hpp>
#include <pinocchio/multibody/data.hpp>
#include <pinocchio/multibody/model.hpp>
#include <pinocchio/parsers/sample-models.hpp>

#include <pinocchio/multibody/liegroup/liegroup.hpp>

#define BOOST_TEST_MODULE features
#include <boost/test/unit_test.hpp>

#include <Eigen/SVD>
#include <dynamic-graph/linear-algebra.h>
#include <sot/core/debug.hh>
#include <sot/core/feature-abstract.hh>
#include <sot/core/feature-generic.hh>
#include <sot/core/feature-pose.hh>
#include <sot/core/gain-adaptive.hh>
#include <sot/core/sot.hh>
#include <sot/core/task.hh>

using namespace std;
using namespace dynamicgraph::sot;
using namespace dynamicgraph;

#define EIGEN_VECTOR_IS_APPROX(Va, Vb, precision)                              \
  BOOST_CHECK_MESSAGE((Va).isApprox(Vb, precision),                            \
                      "check " #Va ".isApprox(" #Vb ") failed "                \
                      "[\n"                                                    \
                          << (Va).transpose() << "\n!=\n"                      \
                          << (Vb).transpose() << "\n]")
#define EIGEN_MATRIX_IS_APPROX(Va, Vb, precision)                              \
  BOOST_CHECK_MESSAGE((Va).isApprox(Vb, precision),                            \
                      "check " #Va ".isApprox(" #Vb ") failed "                \
                      "[\n"                                                    \
                          << (Va) << "\n!=\n"                                  \
                          << (Vb) << "\n]")

class FeatureTestBase {
public:
  Task task_;
  int time_;
  dynamicgraph::Vector expectedTaskOutput_;

  FeatureTestBase(unsigned dim, const std::string &name)
      : task_("task" + name), time_(0) {
    expectedTaskOutput_.resize(dim);
  }

  virtual void init() {
    task_.addFeature(featureAbstract());
    task_.setWithDerivative(true);
  }

  void computeExpectedTaskOutput(const Vector &error,
                                 const Vector &errorDrift) {
    double gain = task_.controlGainSIN;
    expectedTaskOutput_ = -gain * error - errorDrift;
  }

  template <typename LG_t>
  void computeExpectedTaskOutput(const Vector &s, const Vector &sdes,
                                 const Vector &sDesDot, const LG_t &lg) {
    Vector s_sd(lg.nv());
    lg.difference(sdes, s, s_sd);

    Eigen::Matrix<typename LG_t::Scalar, LG_t::NV, LG_t::NV> Jminus(lg.nv(),
                                                                    lg.nv());
    lg.template dDifference<pinocchio::ARG0>(sdes, s, Jminus);

    computeExpectedTaskOutput(s_sd, Jminus * sDesDot);
  }

  void checkTaskOutput() {
    BOOST_REQUIRE_EQUAL(task_.taskSOUT.accessCopy().size(),
                        expectedTaskOutput_.size());
    Vector taskOutput(expectedTaskOutput_.size());
    for (int i = 0; i < expectedTaskOutput_.size(); ++i)
      taskOutput[i] = task_.taskSOUT.accessCopy()[i].getSingleBound();
    EIGEN_VECTOR_IS_APPROX(taskOutput, expectedTaskOutput_, 1e-6);
  }

  void setGain(double gain) {
    task_.controlGainSIN = gain;
    task_.controlGainSIN.access(time_);
    task_.controlGainSIN.setReady();
  }

  template <typename SignalType, typename ValueType>
  void setSignal(SignalType &sig, const ValueType &v) {
    sig = v;
    sig.access(time_);
    sig.setReady();
  }

  virtual FeatureAbstract &featureAbstract() = 0;

  virtual void setInputs() = 0;

  virtual void printInputs() {}

  virtual void recompute() {
    task_.taskSOUT.recompute(time_);

    // Check that recomputing went fine.
    FeatureAbstract &f(featureAbstract());
    BOOST_CHECK_EQUAL(time_, f.errorSOUT.getTime());
    BOOST_CHECK_EQUAL(time_, f.errordotSOUT.getTime());
    BOOST_CHECK_EQUAL(time_, task_.errorSOUT.getTime());
    BOOST_CHECK_EQUAL(time_, task_.errorTimeDerivativeSOUT.getTime());

    // TODO check that the output is correct
    // computeExpectedTaskOutput (s - sd, - vd);
  }

  virtual void printOutputs() {}

  virtual void checkValue() {
    time_++;
    setInputs();
    printInputs();
    recompute();
    printOutputs();
  }
};

class TestFeatureGeneric : public FeatureTestBase {
public:
  FeatureGeneric feature_, featureDes_;
  int dim_;

  TestFeatureGeneric(unsigned dim, const std::string &name)
      : FeatureTestBase(dim, name), feature_("feature" + name),
        featureDes_("featureDes" + name), dim_(dim) {
    feature_.setReference(&featureDes_);
    feature_.selectionSIN = Flags(true);

    dynamicgraph::Matrix Jq(dim, dim);
    Jq.setIdentity();
    feature_.jacobianSIN.setReference(&Jq);

    init();
  }

  FeatureAbstract &featureAbstract() { return feature_; }

  void setInputs() {
    dynamicgraph::Vector s(dim_), sd(dim_), vd(dim_);
    double gain;

    switch (time_) {
    case 0:
      BOOST_TEST_MESSAGE(" ----- Test Velocity -----");
      s.setZero();
      sd.setZero();
      vd.setZero();
      gain = 0.0;
      break;
    case 1:
      BOOST_TEST_MESSAGE(" ----- Test Position -----");
      s.setZero();
      sd.setConstant(2.);
      vd.setZero();
      gain = 1.0;
      break;
    case 2:
      BOOST_TEST_MESSAGE(" ----- Test both -----");
      s.setZero();
      sd.setConstant(2.);
      vd.setConstant(1.);
      gain = 3.0;
      break;
    default:
      s.setRandom();
      sd.setRandom();
      vd.setRandom();
      gain = 1.0;
    }

    feature_.errorSIN = s;
    feature_.errorSIN.access(time_);
    feature_.errorSIN.setReady();

    featureDes_.errorSIN = sd;
    featureDes_.errorSIN.access(time_);
    featureDes_.errorSIN.setReady();

    featureDes_.errordotSIN = vd;
    featureDes_.errordotSIN.access(time_);
    featureDes_.errordotSIN.setReady();

    setGain(gain);
  }

  void printInputs() {
    BOOST_TEST_MESSAGE("----- inputs -----");
    BOOST_TEST_MESSAGE(
        "feature_.errorSIN: " << feature_.errorSIN(time_).transpose());
    BOOST_TEST_MESSAGE(
        "featureDes_.errorSIN: " << featureDes_.errorSIN(time_).transpose());
    BOOST_TEST_MESSAGE("featureDes_.errordotSIN: "
                       << featureDes_.errordotSIN(time_).transpose());
    BOOST_TEST_MESSAGE("task.controlGain: " << task_.controlGainSIN(time_));
  }

  void recompute() {
    FeatureTestBase::recompute();

    dynamicgraph::Vector s = feature_.errorSIN;
    dynamicgraph::Vector sd = featureDes_.errorSIN;
    dynamicgraph::Vector vd = featureDes_.errordotSIN;

    computeExpectedTaskOutput(s - sd, -vd);

    checkTaskOutput();
  }

  void printOutputs() {
    BOOST_TEST_MESSAGE("----- output -----");
    BOOST_TEST_MESSAGE("time: " << time_);
    BOOST_TEST_MESSAGE(
        "feature.errorSOUT: " << feature_.errorSOUT(time_).transpose());
    BOOST_TEST_MESSAGE(
        "feature.errordotSOUT: " << feature_.errordotSOUT(time_).transpose());
    BOOST_TEST_MESSAGE("task.taskSOUT: " << task_.taskSOUT(time_));
    // BOOST_TEST_MESSAGE("task.errorSOUT: " << task_.errorSOUT(time_));
    // BOOST_TEST_MESSAGE("task.errordtSOUT: " <<
    // task_.errorTimeDerivativeSOUT(time_));
    BOOST_TEST_MESSAGE(
        "Expected task output: " << expectedTaskOutput_.transpose());
  }
};

BOOST_AUTO_TEST_SUITE(feature_generic)

BOOST_AUTO_TEST_CASE(check_value) {
  std::string srobot("test");
  unsigned int dim = 6;

  TestFeatureGeneric testFeatureGeneric(dim, srobot);

  for (int i = 0; i < 10; ++i)
    testFeatureGeneric.checkValue();
}

BOOST_AUTO_TEST_SUITE_END() // feature_generic

MatrixHomogeneous randomM() {
  MatrixHomogeneous M;
  M.translation().setRandom();
  Eigen::Vector3d w(Eigen::Vector3d::Random());
  M.linear() = Eigen::AngleAxisd(w.norm(), w.normalized()).matrix();
  return M;
}

typedef pinocchio::SE3 SE3;
typedef pinocchio::SpecialEuclideanOperationTpl<3, double> SE3_t;
typedef pinocchio::CartesianProductOperation<
    pinocchio::VectorSpaceOperationTpl<3, double>,
    pinocchio::SpecialOrthogonalOperationTpl<3, double> >
    R3xSO3_t;
template <Representation_t representation> struct LG_t {
  typedef typename boost::mpl::if_c<representation == SE3Representation, SE3_t,
                                    R3xSO3_t>::type type;
};

Vector7 toVector(const pinocchio::SE3 &M) {
  Vector7 v;
  v.head<3>() = M.translation();
  QuaternionMap(v.tail<4>().data()) = M.rotation();
  return v;
}

Vector toVector(const std::vector<MultiBound> &in) {
  Vector out(in.size());
  for (int i = 0; i < (int)in.size(); ++i)
    out[i] = in[i].getSingleBound();
  return out;
}

template <Representation_t representation>
class TestFeaturePose : public FeatureTestBase {
public:
  typedef typename LG_t<representation>::type LieGroup_t;
  FeaturePose<representation> feature_;
  bool relative_;
  pinocchio::Model model_;
  pinocchio::Data data_;
  pinocchio::JointIndex ja_, jb_;
  pinocchio::FrameIndex fa_, fb_;

  TestFeaturePose(bool relative, const std::string &name)
      : FeatureTestBase(6, name), feature_("feature" + name),
        relative_(relative), data_(model_) {
    pinocchio::buildModels::humanoid(model_, true); // use freeflyer
    model_.lowerPositionLimit.head<3>().setConstant(-1.);
    model_.upperPositionLimit.head<3>().setConstant(1.);
    jb_ = model_.getJointId("rarm_wrist2_joint");
    fb_ = model_.addFrame(pinocchio::Model::Frame(
        "frame_b", jb_,
        model_.getFrameId("rarm_wrist2_joint", pinocchio::JOINT),
        SE3::Identity(), pinocchio::OP_FRAME));
    if (relative) {
      ja_ = model_.getJointId("larm_wrist2_joint");
      fa_ = model_.addFrame(pinocchio::Model::Frame(
          "frame_a", ja_,
          model_.getFrameId("larm_wrist2_joint", pinocchio::JOINT),
          SE3::Identity(), pinocchio::OP_FRAME));
    } else {
      ja_ = 0;
      fa_ = model_.addFrame(pinocchio::Model::Frame(
          "frame_a", 0, 0, SE3::Identity(), pinocchio::OP_FRAME));
    }
    data_ = pinocchio::Data(model_);

    init();

    setJointFrame();
  }

  void _setFrame() {
    setSignal(
        feature_.jaMfa,
        MatrixHomogeneous(model_.frames[fa_].placement.toHomogeneousMatrix()));
    setSignal(
        feature_.jbMfb,
        MatrixHomogeneous(model_.frames[fb_].placement.toHomogeneousMatrix()));
  }

  void setJointFrame() {
    model_.frames[fa_].placement.setIdentity();
    model_.frames[fb_].placement.setIdentity();
    _setFrame();
  }

  void setRandomFrame() {
    model_.frames[fa_].placement.setRandom();
    model_.frames[fb_].placement.setRandom();
    _setFrame();
  }

  FeatureAbstract &featureAbstract() { return feature_; }

  void setInputs() {
    Vector q(pinocchio::randomConfiguration(model_));
    pinocchio::framesForwardKinematics(model_, data_, q);
    pinocchio::computeJointJacobians(model_, data_);

    // Poses
    setSignal(feature_.oMjb,
              MatrixHomogeneous(data_.oMi[jb_].toHomogeneousMatrix()));
    if (relative_) {
      setSignal(feature_.oMja,
                MatrixHomogeneous(data_.oMi[ja_].toHomogeneousMatrix()));
    }

    // Jacobians
    Matrix J(6, model_.nv);
    J.setZero();
    pinocchio::getJointJacobian(model_, data_, jb_, pinocchio::LOCAL, J);
    setSignal(feature_.jbJjb, J);
    if (relative_) {
      J.setZero();
      pinocchio::getJointJacobian(model_, data_, ja_, pinocchio::LOCAL, J);
      setSignal(feature_.jaJja, J);
    }

    // Desired
    setSignal(feature_.faMfbDes, randomM());
    setSignal(feature_.faNufafbDes, Vector::Random(6));

    double gain = 0;
    // if (time_ % 5 != 0)
    // gain = 2 * (double)rand() / RAND_MAX;
    if (time_ % 2 != 0)
      gain = 1;
    setGain(gain);
  }

  void printInputs() {
    BOOST_TEST_MESSAGE("----- inputs -----");
    // BOOST_TEST_MESSAGE("feature_.errorSIN: " <<
    // feature_.errorSIN(time_).transpose());
    BOOST_TEST_MESSAGE("task.controlGain: " << task_.controlGainSIN(time_));
  }

  void recompute() {
    FeatureTestBase::recompute();

    const SE3 oMfb = data_.oMf[fb_], oMfa = data_.oMf[fa_],
              faMfb(feature_.faMfb.accessCopy().matrix()),
              faMfbDes(feature_.faMfbDes.accessCopy().matrix());
    const Vector &nu(feature_.faNufafbDes.accessCopy());

    computeExpectedTaskOutput(
        toVector(oMfa.inverse() * oMfb), toVector(faMfbDes),
        (boost::is_same<LieGroup_t, SE3_t>::value
             ? faMfbDes.toActionMatrixInverse() * nu
             : (Vector6d() << nu.head<3>() -
                                  faMfb.translation().cross(nu.tail<3>()),
                faMfbDes.rotation().transpose() * nu.tail<3>())
                   .finished()),
        LieGroup_t());

    checkTaskOutput();
  }

  void printOutputs() {
    BOOST_TEST_MESSAGE("----- output -----");
    BOOST_TEST_MESSAGE("time: " << time_);
    BOOST_TEST_MESSAGE(
        "feature.errorSOUT: " << feature_.errorSOUT(time_).transpose());
    BOOST_TEST_MESSAGE(
        "feature.errordotSOUT: " << feature_.errordotSOUT(time_).transpose());
    BOOST_TEST_MESSAGE("task.taskSOUT: " << task_.taskSOUT(time_));
    // BOOST_TEST_MESSAGE("task.errorSOUT: " << task_.errorSOUT(time_));
    // BOOST_TEST_MESSAGE("task.errordtSOUT: " <<
    // task_.errorTimeDerivativeSOUT(time_));
    BOOST_TEST_MESSAGE(
        "Expected task output: " << expectedTaskOutput_.transpose());
  }

  virtual void checkJacobian() {
    time_++;
    // We want to check that e (q+dq, t) ~ e(q, t) + de/dq(q,t) dq

    setGain(1.);

    Vector q(pinocchio::randomConfiguration(model_));
    pinocchio::framesForwardKinematics(model_, data_, q);
    pinocchio::computeJointJacobians(model_, data_);

    // Poses
    setSignal(feature_.oMjb,
              MatrixHomogeneous(data_.oMi[jb_].toHomogeneousMatrix()));
    if (relative_) {
      setSignal(feature_.oMja,
                MatrixHomogeneous(data_.oMi[ja_].toHomogeneousMatrix()));
    }

    // Jacobians
    Matrix J(6, model_.nv);
    J.setZero();
    pinocchio::getJointJacobian(model_, data_, jb_, pinocchio::LOCAL, J);
    setSignal(feature_.jbJjb, J);
    if (relative_) {
      J.setZero();
      pinocchio::getJointJacobian(model_, data_, ja_, pinocchio::LOCAL, J);
      setSignal(feature_.jaJja, J);
    }

    // Desired
    setSignal(feature_.faMfbDes, randomM());

    // Get task jacobian
    Vector e_q = task_.errorSOUT.access(time_);
    J = task_.jacobianSOUT.access(time_);

    Eigen::IOFormat PyVectorFmt(Eigen::FullPrecision, 0, ", ", ", ", "", "",
                                "[", "]\n");
    Eigen::IOFormat PyMatrixFmt(Eigen::FullPrecision, 0, ", ", ",\n", "[", "]",
                                "[", "]\n");

    Vector qdot(Vector::Zero(model_.nv));
    double eps = 1e-6;
    BOOST_TEST_MESSAGE(
        data_.oMi[ja_].toHomogeneousMatrix().format(PyMatrixFmt)
        << data_.oMi[jb_].toHomogeneousMatrix().format(PyMatrixFmt)
        << model_.frames[fa_].placement.toHomogeneousMatrix().format(
               PyMatrixFmt)
        << model_.frames[fb_].placement.toHomogeneousMatrix().format(
               PyMatrixFmt)
        << J.format(PyMatrixFmt));

    for (int i = 0; i < model_.nv; ++i) {
      time_++;
      qdot(i) = eps;

      // Update pose signals
      Vector q_qdot = pinocchio::integrate(model_, q, qdot);
      pinocchio::framesForwardKinematics(model_, data_, q_qdot);
      setSignal(feature_.oMjb,
                MatrixHomogeneous(data_.oMi[jb_].toHomogeneousMatrix()));
      if (relative_) {
        setSignal(feature_.oMja,
                  MatrixHomogeneous(data_.oMi[ja_].toHomogeneousMatrix()));
      }

      // Recompute output and check finite diff
      Vector e_q_dq = task_.errorSOUT.access(time_);
      BOOST_CHECK_MESSAGE(
          (((e_q_dq - e_q) / eps) - J.col(i)).maxCoeff() < 1e-4,
          "Jacobian col " << i << " does not match finite difference.\n"
                          << ((e_q_dq - e_q) / eps).format(PyVectorFmt) << '\n'
                          << J.col(i).format(PyVectorFmt) << '\n');

      qdot(i) = 0.;
    }
    time_++;
  }

  virtual void checkFeedForward() {
    setGain(0.);
    // random config
    // set inputs
    // compute e = task_.taskSOUT and J = task_.jacobianSOUT
    // check that e (q + eps*qdot) - e (q) ~= eps * J * qdot
    // compute qdot = J^+ * e
    // check that faMfb (q+eps*qdot) ~= faMfb(q) + eps * faNufafbDes

    time_++;
    Vector q(pinocchio::randomConfiguration(model_));
    pinocchio::framesForwardKinematics(model_, data_, q);
    pinocchio::computeJointJacobians(model_, data_);

    SE3 faMfb = data_.oMf[fa_].actInv(data_.oMf[fb_]);

    // Poses
    setSignal(feature_.oMjb,
              MatrixHomogeneous(data_.oMi[jb_].toHomogeneousMatrix()));
    if (relative_) {
      setSignal(feature_.oMja,
                MatrixHomogeneous(data_.oMi[ja_].toHomogeneousMatrix()));
    }

    // Jacobians
    Matrix J(6, model_.nv);
    J.setZero();
    pinocchio::getJointJacobian(model_, data_, jb_, pinocchio::LOCAL, J);
    setSignal(feature_.jbJjb, J);
    if (relative_) {
      J.setZero();
      pinocchio::getJointJacobian(model_, data_, ja_, pinocchio::LOCAL, J);
      setSignal(feature_.jaJja, J);
    }

    Matrix faJfafb;
    J.setZero();
    pinocchio::getFrameJacobian(model_, data_, fb_, pinocchio::LOCAL, J);
    faJfafb = faMfb.toActionMatrix() * J;
    J.setZero();
    pinocchio::getFrameJacobian(model_, data_, fa_, pinocchio::LOCAL, J);
    faJfafb -= J;

    // Desired
    setSignal(feature_.faMfbDes, randomM());

    // Get task jacobian
    task_.jacobianSOUT.recompute(time_);
    J = task_.jacobianSOUT.accessCopy();
    Eigen::JacobiSVD<Matrix> svd(J, Eigen::ComputeThinU | Eigen::ComputeThinV);

    Vector faNufafbDes(Vector::Zero(6));
    double eps = 1e-6;
    for (int i = 0; i < 6; ++i) {
      time_++;
      faNufafbDes(i) = 1.;
      setSignal(feature_.faNufafbDes, faNufafbDes);
      task_.taskSOUT.recompute(time_);

      Vector qdot = svd.solve(toVector(task_.taskSOUT.accessCopy()));

      Vector faNufafb = faJfafb * qdot;
      EIGEN_VECTOR_IS_APPROX(faNufafbDes, faNufafb, eps);

      faNufafbDes(i) = 0.;
    }
    time_++;
  }
};

template <typename TestClass>
void runTest(TestClass &runner, int N = 2)
// int N = 10)
{
  for (int i = 0; i < N; ++i)
    runner.checkValue();
  for (int i = 0; i < N; ++i)
    runner.checkJacobian();
  for (int i = 0; i < N; ++i)
    runner.checkFeedForward();
}

BOOST_AUTO_TEST_SUITE(feature_pose)

template <Representation_t representation>
void feature_pose_absolute_tpl(const std::string &repr) {
  BOOST_TEST_MESSAGE("absolute " << repr);
  TestFeaturePose<representation> testAbsolute(false, "abs" + repr);
  testAbsolute.setJointFrame();
  runTest(testAbsolute);

  testAbsolute.setRandomFrame();
  runTest(testAbsolute);
}

BOOST_AUTO_TEST_SUITE(absolute)

BOOST_AUTO_TEST_CASE(r3xso3) {
  feature_pose_absolute_tpl<R3xSO3Representation>("R3xSO3");
}

BOOST_AUTO_TEST_CASE(se3) {
  feature_pose_absolute_tpl<SE3Representation>("SE3");
}

BOOST_AUTO_TEST_SUITE_END() // absolute

template <Representation_t representation>
void feature_pose_relative_tpl(const std::string &repr) {
  BOOST_TEST_MESSAGE("relative " << repr);
  TestFeaturePose<representation> testRelative(true, "rel" + repr);
  runTest(testRelative);

  testRelative.setRandomFrame();
  runTest(testRelative);
}

BOOST_AUTO_TEST_SUITE(relative)

BOOST_AUTO_TEST_CASE(r3xso3) {
  feature_pose_relative_tpl<R3xSO3Representation>("R3xSO3");
}

BOOST_AUTO_TEST_CASE(se3) {
  feature_pose_relative_tpl<SE3Representation>("SE3");
}

BOOST_AUTO_TEST_SUITE_END() // relative

BOOST_AUTO_TEST_SUITE_END() // feature_pose

max_stars_repo_name: Rascof/sot-core

max_issues_repo_name: Rascof/sot-core

max_forks_repo_name: Rascof/sot-core


text:
#include <string>
#include <string.h>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <crypto++/gcm.h>
#include <crypto++/aes.h>
#include <crypto++/filters.h>
#include <crypto++/osrng.h>

#include <nar/lib/Exception/Exception.h>

#include "aes.h"

void byte_to_string( byte* data, std::string& str, int len) {
    for(int i=0; i<len; i++) {
        str.push_back(data[i]);
    }
    return;
}

byte* string_to_byte(std::string& key) {
    int len = key.length();
    byte *aes = new byte[len];
    for(int i=0; i<len; i++) {
        aes[i] = key[i];
    }
    return aes;
}

AesCryptor::AesCryptor(std::string key): _keyString(key) {
    int keyLen = _keyString.length();
    const char *str = _keyString.c_str();
    _aes = string_to_byte(_keyString);
}

AesCryptor::~AesCryptor() {
    free(_aes);
}

void AesCryptor::encrypt(std::string &text, std::string &crypted) {
    try {
        byte iv[256];
        const int TAG_SIZE = 12;

        CryptoPP::AutoSeededRandomPool pool;
        pool.GenerateBlock(iv, 256);

        CryptoPP::GCM<CryptoPP::AES>::Encryption enc;
        enc.SetKeyWithIV(_aes, 16, iv, 256);

        CryptoPP::StringSource ss1(text, true, new CryptoPP::AuthenticatedEncryptionFilter(enc, new CryptoPP::StringSink(crypted), false, TAG_SIZE));

        std::string bla;
        byte_to_string(iv,bla,256);

        std::string test = crypted;
        crypted = bla + crypted;
    }
    catch (CryptoPP::Exception& e){
        throw nar::Exception::Cryption::AesError(std::string("Error in Aes encryption").append(e.what()));
    }
    return;
}

void AesCryptor::decrypt(std::string& data, std::string& result) {
    try {
        std::string ivStr = data.substr(0,256);
        byte* iv = string_to_byte(ivStr);
        CryptoPP::GCM<CryptoPP::AES>::Decryption dec;
        dec.SetKeyWithIV(_aes, 16, iv, 256);

        const int TAG_SIZE = 12;

        CryptoPP::AuthenticatedDecryptionFilter df(dec, new CryptoPP::StringSink(result), CryptoPP::AuthenticatedDecryptionFilter::DEFAULT_FLAGS, TAG_SIZE);

        CryptoPP::StringSource ss(data.substr(256), true, new CryptoPP::Redirector(df));
        free(iv);
    }
    catch (CryptoPP::Exception& e){
        throw nar::Exception::Cryption::AesError(std::string("Error in Aes decryption").append(e.what()));
    }
    return;
}

void AesCryptor::generate_key(std::string &key, int length) {
    try {
        std::string chars(
            "abcdefghijklmnopqrstuvwxyz"
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "1234567890"
            "!@#$%^&*()"
            "`~-_=+[{]}\\|;:'\",<.>/? ");
        boost::random::random_device rng;
        boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
        for(int i = 0; i < length; ++i) {
            key.push_back(chars[index_dist(rng)]);
        }
    }
    catch (CryptoPP::Exception& e){
        throw nar::Exception::Cryption::AesError(std::string("Error in Aes key-generation").append(e.what()));
    }
    return;
}

max_stars_repo_name: webcok/nar

max_issues_repo_name: webcok/nar

max_forks_repo_name: webcok/nar


text:
/*
	Copyright (C) 2003-2013 by David White <davewx7@gmail.com>

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

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

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NO_EDITOR
#include <boost/bind.hpp>

#include "dialog.hpp"
#include "editor_dialogs.hpp"
#include "foreach.hpp"
#include "grid_widget.hpp"
#include "label.hpp"
#include "load_level.hpp"
#include "raster.hpp"
#include "widget.hpp"

namespace {
void do_select_level(gui::dialog* d, const std::vector<std::string>& levels, int index, std::string* result) {
	if(index >= 0 && index < levels.size()) {
		d->close();
		*result = levels[index];
	}
}
}

std::string show_choose_level_dialog(const std::string& prompt)
{
	using namespace gui;
	dialog d(0, 0, graphics::screen_width(), graphics::screen_height());
	d.add_widget(widget_ptr(new label(prompt, graphics::color_white(), 48)));

	std::string result;
	std::vector<std::string> levels = get_known_levels();
	gui::grid* grid = new gui::grid(1);
	grid->set_max_height(graphics::screen_height() - 80);
	grid->set_show_background(true);
	grid->allow_selection();

	grid->register_selection_callback(boost::bind(&do_select_level, &d, levels, _1, &result));
	foreach(const std::string& lvl, levels) {
		grid->add_col(widget_ptr(new label(lvl, graphics::color_white())));
	}

	d.add_widget(widget_ptr(grid));
	d.show_modal();
	return result;
}
#endif // NO_EDITOR

max_stars_repo_name: sweetkristas/anura

max_issues_repo_name: sweetkristas/anura

max_forks_repo_name: sweetkristas/anura


text:
#pragma once

#include "DataStructures.hpp"
#include "mathtypes.hpp"
#include <bgfx/bgfx.h>
#include "Ref.hpp"
#include "Common3D.hpp"
#include "WeakRef.hpp"
#include "SpinLock.hpp"
#include "Manager.hpp"
#include <boost/container_hash/hash.hpp>

struct aiMesh;

namespace RavEngine{

struct MeshAssetOptions{
    bool keepInSystemRAM = false;
    bool uploadToGPU = true;
    float scale = 1.0;

    inline bool operator==(const MeshAssetOptions& other) const{
        return keepInSystemRAM == other.keepInSystemRAM && uploadToGPU == other.uploadToGPU && scale == other.scale;
    }
};

class MeshAsset {
public:
	typedef VertexNormalUV vertex_t;

	struct MeshPart{
		RavEngine::Vector<uint32_t> indices;
        RavEngine::Vector<vertex_t> vertices;
	};

    // if we do not want this meshasset having ownership of the mesh (for example in use with Exchange)
    // set this to false
    bool destroyOnDestruction = true;

	/**
	Convert an assimp mesh to a MeshPart
	@param mesh the assimp mesh to convert
	@param scaleMat the matrix to apply to each vertex of the mesh
	@return converted MeshPart
	*/
	static MeshPart AIMesh2MeshPart(const aiMesh* mesh, const matrix4& scaleMat);

    struct Bounds{
        float min[3] = {0,0,0};
        float max[3] = {0,0,0};
    };

protected:
	bgfx::VertexBufferHandle vertexBuffer = BGFX_INVALID_HANDLE;
	bgfx::IndexBufferHandle indexBuffer = BGFX_INVALID_HANDLE;

	size_t totalVerts = 0, totalIndices = 0;
    Bounds bounds;

	inline void Destroy(){
        if (destroyOnDestruction){
            if (bgfx::isValid(vertexBuffer)){
                bgfx::destroy(vertexBuffer);
            }
            if (bgfx::isValid(indexBuffer)){
                bgfx::destroy(indexBuffer);
            }
        }
		vertexBuffer = BGFX_INVALID_HANDLE;
		indexBuffer = BGFX_INVALID_HANDLE;
	}

	/**
	 Initialize from multiple meshs consisting of a single vertex and index list
	 @param mp the meshes to initialize from
	 */
	void InitializeFromMeshPartFragments(const  RavEngine::Vector<MeshPart>& mp, const MeshAssetOptions& options = MeshAssetOptions());

	/**
	 Initialize from a complete mesh consisting of a single vertex and index list
	 @param mp the mesh to initialize from
	 */
	void InitializeFromRawMesh(const MeshPart& mp, const MeshAssetOptions& options = MeshAssetOptions());

	// optionally stores a copy of the mesh in system memory
	MeshPart systemRAMcopy;

public:

    struct Manager : public GenericWeakCache<std::string,MeshAsset>{
    public:

        /**
         Load a mesh from cache. If the mesh is not cached in memory, it will be loaded from disk.
         @param str the name of the mesh
         */
        static Ref<MeshAsset> GetDefault(const std::string& str){
            return ::RavEngine::GenericWeakCache<std::string,MeshAsset>::Get(str,MeshAssetOptions());
        }
    };

	/**
	 Default constructor that creates an invalid MeshAsset. Useful in conjunction with Exchange.
	 */
	MeshAsset(){}

	/**
	 Create a MeshAsset
	 @param path the path to the asset in the embedded filesystem
	 @param scale the scale factor when loading
	 @param keepCopyInSystemMemory maintain a copy of the mesh data in system RAM, for use in features that need it like mesh colliders
	 */
	MeshAsset(const std::string& path, const MeshAssetOptions& options = MeshAssetOptions());

	/**
	 Create a MeshAsset from a specific mesh inside the scene file. To load all meshes into one mesh, use the other constructor.
	 @param path the path to the asset in the embedded filesystem
	 @param modelName the name of the mesh inside the scene file to load
	 @param scale the scale factor when loading
	 @param keepCopyInSystemMemory maintain a copy of the mesh data in system RAM, for use in features that need it like mesh colliders
	 */
	MeshAsset(const std::string& path, const std::string& modelName, const MeshAssetOptions& options = MeshAssetOptions());

	/**
	 Create a MeshAsset from multiple vertex and index lists
	 @param rawMeshData the index and triangle data
	 @param keepCopyInSystemMemory maintain a copy of the mesh data in system RAM, for use in features that need it like mesh colliders
	 */
	MeshAsset(const  RavEngine::Vector<MeshPart>& rawMeshData, const MeshAssetOptions& options = MeshAssetOptions()){
		InitializeFromMeshPartFragments(rawMeshData, options);
	}

	/**
	 Create a MeshAsset from a single vertex and index list
	 @param mesh the index and triangle data
	 */
	MeshAsset(const MeshPart& mesh, const MeshAssetOptions& options = MeshAssetOptions()){
		InitializeFromRawMesh(mesh, options);
	}

	/**
	 Move a MeshAsset's data into this MeshAsset.
	 @param other the other MeshAsset, which will become invalid after this call and should not be used.
	 */
	inline void Exchange(Ref<MeshAsset> other, bool destroyCurrent = true){
		if (destroyCurrent){
			Destroy();
		}
		vertexBuffer = other->vertexBuffer;
		indexBuffer = other->indexBuffer;
		totalVerts = other->totalVerts;
		totalIndices = other->totalIndices;

		other->vertexBuffer = BGFX_INVALID_HANDLE;
		other->vertexBuffer = BGFX_INVALID_HANDLE;
	}

	constexpr inline const bgfx::VertexBufferHandle getVertexBuffer() const{
		return vertexBuffer;
	}
    constexpr inline const bgfx::IndexBufferHandle getIndexBuffer() const{
		return indexBuffer;
	}

    constexpr inline const decltype(bounds)& GetBounds() const{
        return bounds;
    }

	virtual ~MeshAsset(){
		Destroy();
	}

    constexpr inline const decltype(totalVerts) GetNumVerts() const {
		return totalVerts;
	}

    constexpr inline const decltype(totalIndices) GetNumIndices() const {
		return totalIndices;
	}

    constexpr inline decltype(systemRAMcopy)& GetSystemCopy(){
		return systemRAMcopy;
	}

    inline bool hasSystemRAMCopy() const{
        return systemRAMcopy.vertices.size() > 0;
    }

	/**
	 In case the system memory copy is no longer needed, destroy it.
	 This is not undoable.
	 */
    inline void DeallocSystemCopy(){
		systemRAMcopy = MeshPart{};
	}
};

}

namespace boost{
    template<>
struct hash<RavEngine::MeshAssetOptions>{
    inline size_t operator()(const RavEngine::MeshAssetOptions& opt){
            size_t seed = 0;
            boost::hash_combine(seed,opt.keepInSystemRAM);
            boost::hash_combine(seed,opt.uploadToGPU);
            boost::hash_combine(seed,opt.scale);
            return seed;
        }
    };
}

max_stars_repo_name: Ravbug/RavEngine

max_issues_repo_name: Ravbug/RavEngine

max_forks_repo_name: Ravbug/RavEngine