<commit_before>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin 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 "main.h"
#include "kernel.h"
#include "checkpoints.h"

using namespace json_spirit;
using namespace std;

extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry);

double GetDifficulty(const CBlockIndex* blockindex)
{
    // Floating point number that is a multiple of the minimum difficulty,
    // minimum difficulty = 1.0.
    if (blockindex == NULL)
    {
        if (pindexBest == NULL)
            return 1.0;
        else
            blockindex = GetLastBlockIndex(pindexBest, false);
    }

    int nShift = (blockindex->nBits >> 24) & 0xff;

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

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

    return dDiff;
}

double GetPoWMHashPS()
{
    if (pindexBest->nHeight >= Params().LastPOWBlock())
        return 0;

    int nPoWInterval = 72;
    int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30;

    CBlockIndex* pindex = pindexGenesisBlock;
    CBlockIndex* pindexPrevWork = pindexGenesisBlock;

    while (pindex)
    {
        if (pindex->IsProofOfWork())
        {
            int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime();
            nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1);
            nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin);
            pindexPrevWork = pindex;
        }

        pindex = pindex->pnext;
    }

    return GetDifficulty() * 4294.967296 / nTargetSpacingWork;
}

double GetPoSKernelPS()
{
    int nPoSInterval = 72;
    double dStakeKernelsTriedAvg = 0;
    int nStakesHandled = 0, nStakesTime = 0;

    CBlockIndex* pindex = pindexBest;;
    CBlockIndex* pindexPrevStake = NULL;

    while (pindex && nStakesHandled < nPoSInterval)
    {
        if (pindex->IsProofOfStake())
        {
            if (pindexPrevStake)
            {
                dStakeKernelsTriedAvg += GetDifficulty(pindexPrevStake) * 4294967296.0;
                nStakesTime += pindexPrevStake->nTime - pindex->nTime;
                nStakesHandled++;
            }
            pindexPrevStake = pindex;
        }

        pindex = pindex->pprev;
    }

    double result = 0;

    if (nStakesTime)
        result = dStakeKernelsTriedAvg / nStakesTime;

    result *= STAKE_TIMESTAMP_MASK + 1;

    return result;
}

Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail)
{
    Object result;
    result.push_back(Pair("hash", block.GetHash().GetHex()));
    int confirmations = -1;
    // Only report confirmations if the block is on the main chain
    if (blockindex->IsInMainChain())
        confirmations = nBestHeight - blockindex->nHeight + 1;
    result.push_back(Pair("confirmations", confirmations));
    result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
    result.push_back(Pair("height", blockindex->nHeight));
    result.push_back(Pair("version", block.nVersion));
    result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
    result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint)));
    result.push_back(Pair("time", (int64_t)block.GetBlockTime()));
    result.push_back(Pair("nonce", (uint64_t)block.nNonce));
    result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
    result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
    result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0')));
    result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0')));
    if (blockindex->pprev)
        result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
    if (blockindex->pnext)
        result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));

    result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": "")));
    result.push_back(Pair("proofhash", blockindex->hashProof.GetHex()));
    result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit()));
    result.push_back(Pair("modifier", strprintf("%016x", blockindex->nStakeModifier)));
    result.push_back(Pair("modifierv2", blockindex->bnStakeModifierV2.GetHex()));
    Array txinfo;
    BOOST_FOREACH (const CTransaction& tx, block.vtx)
    {
        if (fPrintTransactionDetail)
        {
            Object entry;

            entry.push_back(Pair("txid", tx.GetHash().GetHex()));
            TxToJSON(tx, 0, entry);

            txinfo.push_back(entry);
        }
        else
            txinfo.push_back(tx.GetHash().GetHex());
    }

    result.push_back(Pair("tx", txinfo));

    if (block.IsProofOfStake())
        result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));

    return result;
}

Value getbestblockhash(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getbestblockhash\n"
            "Returns the hash of the best block in the longest block chain.");

    return hashBestChain.GetHex();
}

Value getblockcount(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getblockcount\n"
            "Returns the number of blocks in the longest block chain.");

    return nBestHeight;
}

Value getdifficulty(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getdifficulty\n"
            "Returns the difficulty as a multiple of the minimum difficulty.");

    //Object obj;
    //obj.push_back(Pair("proof-of-work",        GetDifficulty()));
    //obj.push_back(Pair("proof-of-stake",       GetDifficulty(GetLastBlockIndex(pindexBest, true))));
    return GetDifficulty(GetLastBlockIndex(pindexBest, true));
}

Value getrawmempool(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getrawmempool\n"
            "Returns all transaction ids in memory pool.");

    vector<uint256> vtxid;
    mempool.queryHashes(vtxid);

    Array a;
    BOOST_FOREACH(const uint256& hash, vtxid)
        a.push_back(hash.ToString());

    return a;
}
Value mempoolInfoToJSON()
{
    //Value ret(Value::VOBJ);
    ret.push_back(Pair("size", (int64_t) mempool.size()));
    //ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
    //ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
    //size_t maxmempool = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
    //ret.push_back(Pair("maxmempool", (int64_t) maxmempool));
    //ret.push_back(Pair("mempoolminfee", ValueFromAmount(mempool.GetMinFee(maxmempool).GetFeePerK())));

    return ret;
}

Value getmempoolinfo(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getmempoolinfo\n"
            "\nReturns details on the active state of the TX memory pool.\n"
            "\nResult:\n"
            "{\n"
            "  \"size\": xxxxx,               (numeric) Current tx count\n"
            "  \"bytes\": xxxxx,              (numeric) Sum of all tx sizes\n"
            "  \"usage\": xxxxx,              (numeric) Total memory usage for the mempool\n"
            "  \"maxmempool\": xxxxx,         (numeric) Maximum memory usage for the mempool\n"
            "  \"mempoolminfee\": xxxxx       (numeric) Minimum fee for tx to be accepted\n"
            "}\n"
            "\nExamples:\n");

    return mempoolInfoToJSON();
}

Value getblockhash(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 1)
        throw runtime_error(
            "getblockhash <index>\n"
            "Returns hash of block in best-block-chain at <index>.");

    int nHeight = params[0].get_int();
    if (nHeight < 0 || nHeight > nBestHeight)
        throw runtime_error("Block number out of range.");

    CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
    return pblockindex->phashBlock->GetHex();
}

Value getblock(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2)
        throw runtime_error(
            "getblock <hash> [txinfo]\n"
            "txinfo optional to print more detailed tx info\n"
            "Returns details of a block with given block-hash.");

    std::string strHash = params[0].get_str();
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    block.ReadFromDisk(pblockindex, true);

    return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
}

Value getblockbynumber(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2)
        throw runtime_error(
            "getblockbynumber <number> [txinfo]\n"
            "txinfo optional to print more detailed tx info\n"
            "Returns details of a block with given block-number.");

    int nHeight = params[0].get_int();
    if (nHeight < 0 || nHeight > nBestHeight)
        throw runtime_error("Block number out of range.");

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
    while (pblockindex->nHeight > nHeight)
        pblockindex = pblockindex->pprev;

    uint256 hash = *pblockindex->phashBlock;

    pblockindex = mapBlockIndex[hash];
    block.ReadFromDisk(pblockindex, true);

    return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
}

// ppcoin: get information of sync-checkpoint
Value getcheckpoint(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getcheckpoint\n"
            "Show info of synchronized checkpoint.\n");

    Object result;
    const CBlockIndex* pindexCheckpoint = Checkpoints::AutoSelectSyncCheckpoint();

    result.push_back(Pair("synccheckpoint", pindexCheckpoint->GetBlockHash().ToString().c_str()));
    result.push_back(Pair("height", pindexCheckpoint->nHeight));
    result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str()));

    result.push_back(Pair("policy", "rolling"));

    return result;
}
<commit_msg>getmempoolinfo fix<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin 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 "main.h"
#include "kernel.h"
#include "checkpoints.h"

using namespace json_spirit;
using namespace std;

extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry);

double GetDifficulty(const CBlockIndex* blockindex)
{
    // Floating point number that is a multiple of the minimum difficulty,
    // minimum difficulty = 1.0.
    if (blockindex == NULL)
    {
        if (pindexBest == NULL)
            return 1.0;
        else
            blockindex = GetLastBlockIndex(pindexBest, false);
    }

    int nShift = (blockindex->nBits >> 24) & 0xff;

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

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

    return dDiff;
}

double GetPoWMHashPS()
{
    if (pindexBest->nHeight >= Params().LastPOWBlock())
        return 0;

    int nPoWInterval = 72;
    int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30;

    CBlockIndex* pindex = pindexGenesisBlock;
    CBlockIndex* pindexPrevWork = pindexGenesisBlock;

    while (pindex)
    {
        if (pindex->IsProofOfWork())
        {
            int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime();
            nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1);
            nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin);
            pindexPrevWork = pindex;
        }

        pindex = pindex->pnext;
    }

    return GetDifficulty() * 4294.967296 / nTargetSpacingWork;
}

double GetPoSKernelPS()
{
    int nPoSInterval = 72;
    double dStakeKernelsTriedAvg = 0;
    int nStakesHandled = 0, nStakesTime = 0;

    CBlockIndex* pindex = pindexBest;;
    CBlockIndex* pindexPrevStake = NULL;

    while (pindex && nStakesHandled < nPoSInterval)
    {
        if (pindex->IsProofOfStake())
        {
            if (pindexPrevStake)
            {
                dStakeKernelsTriedAvg += GetDifficulty(pindexPrevStake) * 4294967296.0;
                nStakesTime += pindexPrevStake->nTime - pindex->nTime;
                nStakesHandled++;
            }
            pindexPrevStake = pindex;
        }

        pindex = pindex->pprev;
    }

    double result = 0;

    if (nStakesTime)
        result = dStakeKernelsTriedAvg / nStakesTime;

    result *= STAKE_TIMESTAMP_MASK + 1;

    return result;
}

Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail)
{
    Object result;
    result.push_back(Pair("hash", block.GetHash().GetHex()));
    int confirmations = -1;
    // Only report confirmations if the block is on the main chain
    if (blockindex->IsInMainChain())
        confirmations = nBestHeight - blockindex->nHeight + 1;
    result.push_back(Pair("confirmations", confirmations));
    result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
    result.push_back(Pair("height", blockindex->nHeight));
    result.push_back(Pair("version", block.nVersion));
    result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
    result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint)));
    result.push_back(Pair("time", (int64_t)block.GetBlockTime()));
    result.push_back(Pair("nonce", (uint64_t)block.nNonce));
    result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
    result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
    result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0')));
    result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0')));
    if (blockindex->pprev)
        result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
    if (blockindex->pnext)
        result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));

    result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": "")));
    result.push_back(Pair("proofhash", blockindex->hashProof.GetHex()));
    result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit()));
    result.push_back(Pair("modifier", strprintf("%016x", blockindex->nStakeModifier)));
    result.push_back(Pair("modifierv2", blockindex->bnStakeModifierV2.GetHex()));
    Array txinfo;
    BOOST_FOREACH (const CTransaction& tx, block.vtx)
    {
        if (fPrintTransactionDetail)
        {
            Object entry;

            entry.push_back(Pair("txid", tx.GetHash().GetHex()));
            TxToJSON(tx, 0, entry);

            txinfo.push_back(entry);
        }
        else
            txinfo.push_back(tx.GetHash().GetHex());
    }

    result.push_back(Pair("tx", txinfo));

    if (block.IsProofOfStake())
        result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));

    return result;
}

Value getbestblockhash(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getbestblockhash\n"
            "Returns the hash of the best block in the longest block chain.");

    return hashBestChain.GetHex();
}

Value getblockcount(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getblockcount\n"
            "Returns the number of blocks in the longest block chain.");

    return nBestHeight;
}

Value getdifficulty(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getdifficulty\n"
            "Returns the difficulty as a multiple of the minimum difficulty.");

    //Object obj;
    //obj.push_back(Pair("proof-of-work",        GetDifficulty()));
    //obj.push_back(Pair("proof-of-stake",       GetDifficulty(GetLastBlockIndex(pindexBest, true))));
    return GetDifficulty(GetLastBlockIndex(pindexBest, true));
}

Value getrawmempool(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getrawmempool\n"
            "Returns all transaction ids in memory pool.");

    vector<uint256> vtxid;
    mempool.queryHashes(vtxid);

    Array a;
    BOOST_FOREACH(const uint256& hash, vtxid)
        a.push_back(hash.ToString());

    return a;
}
Value mempoolInfoToJSON()
{
    //Value ret;
    //ret.push_back(Pair("size", (int64_t) mempool.size()));
    //ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
    //ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
    //size_t maxmempool = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
    //ret.push_back(Pair("maxmempool", (int64_t) maxmempool));
    //ret.push_back(Pair("mempoolminfee", ValueFromAmount(mempool.GetMinFee(maxmempool).GetFeePerK())));

    //return ret;
}

Value getmempoolinfo(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getmempoolinfo\n"
            "\nReturns details on the active state of the TX memory pool.\n"
            "\nResult:\n"
            "{\n"
            "  \"size\": xxxxx,               (numeric) Current tx count\n"
            "  \"bytes\": xxxxx,              (numeric) Sum of all tx sizes\n"
            "  \"usage\": xxxxx,              (numeric) Total memory usage for the mempool\n"
            "  \"maxmempool\": xxxxx,         (numeric) Maximum memory usage for the mempool\n"
            "  \"mempoolminfee\": xxxxx       (numeric) Minimum fee for tx to be accepted\n"
            "}\n"
            "\nExamples:\n");

    return mempoolInfoToJSON();
}

Value getblockhash(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 1)
        throw runtime_error(
            "getblockhash <index>\n"
            "Returns hash of block in best-block-chain at <index>.");

    int nHeight = params[0].get_int();
    if (nHeight < 0 || nHeight > nBestHeight)
        throw runtime_error("Block number out of range.");

    CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
    return pblockindex->phashBlock->GetHex();
}

Value getblock(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2)
        throw runtime_error(
            "getblock <hash> [txinfo]\n"
            "txinfo optional to print more detailed tx info\n"
            "Returns details of a block with given block-hash.");

    std::string strHash = params[0].get_str();
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    block.ReadFromDisk(pblockindex, true);

    return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
}

Value getblockbynumber(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2)
        throw runtime_error(
            "getblockbynumber <number> [txinfo]\n"
            "txinfo optional to print more detailed tx info\n"
            "Returns details of a block with given block-number.");

    int nHeight = params[0].get_int();
    if (nHeight < 0 || nHeight > nBestHeight)
        throw runtime_error("Block number out of range.");

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
    while (pblockindex->nHeight > nHeight)
        pblockindex = pblockindex->pprev;

    uint256 hash = *pblockindex->phashBlock;

    pblockindex = mapBlockIndex[hash];
    block.ReadFromDisk(pblockindex, true);

    return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
}

// ppcoin: get information of sync-checkpoint
Value getcheckpoint(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getcheckpoint\n"
            "Show info of synchronized checkpoint.\n");

    Object result;
    const CBlockIndex* pindexCheckpoint = Checkpoints::AutoSelectSyncCheckpoint();

    result.push_back(Pair("synccheckpoint", pindexCheckpoint->GetBlockHash().ToString().c_str()));
    result.push_back(Pair("height", pindexCheckpoint->nHeight));
    result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str()));

    result.push_back(Pair("policy", "rolling"));

    return result;
}
<|endoftext|>


<commit_before>// OK -- this is now RTcmix.C, hacked from the original "main.C"
// 	in standalone RTcmix.  The idea is to make this a compile-in
//	imbRTcmix.o lib that can be called from within other main()
//	progs.  -- BGG 11/2002

/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/

#include "RTcmix.h"

//#define DBUG
//#define DENORMAL_CHECK
#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <iostream.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <signal.h>
#ifdef LINUX
   #include <sys/soundcard.h>
#endif
#ifdef SGI
   #include <dmedia/audio.h>
#endif

#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <version.h>
#include "rt.h"
#include "../rtstuff/heap/heap.h"
#include "maxdispargs.h"
#include "dbug.h"

extern "C" {
	int ug_intro();
	// I don't call the profiles here, because dead-time instruments
	// won't be compiled into the object file unless they are present at
	// the build (i.e. they aren't DSO's).  RT instruments have the
	// rtprofile() called when they get loaded.  Go Doug, go!
#ifdef SGI
	void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
	void sigfpe_handler(int sig);
#endif
}

rt_item *rt_list;     /* can't put this in globals.h because of rt.h trouble */

/* --------------------------------------------------------- init_globals --- */
static void
init_globals()
{
	int i;

	RTBUFSAMPS = 8192; //default, modifiable with rtsetparams
	NCHANS = 2;
	audioNCHANS = 0;
	SR = 44100.0; // what the heck...
	bufStartSamp = 0;

#ifdef LINUX
	for (i = 0; i < MAXBUS; i++) in_port[i] = out_port[i] = 0;
#endif /* LINUX */
#ifdef MACOSX
#endif
#ifdef SGI
	in_port = 0;
	out_port = 0;
#endif /* SGI */

	rtQueue = new RTQueue[MAXBUS*3];

	rtInteractive = 1; // keep the heap going for this object
	rtsetparams_called = 0; // will call at object instantiation, though

	audio_on = 0;
	audio_config = 1;
	play_audio = 1;              /* modified with set_option */
	full_duplex = 0;
	check_peaks = 1;
	report_clipping = 1;

	/* I can't believe these were never initialized */
	// hey, I'm that kinda guy! :-)
// 	baseTime = 0;
// 	schedtime = 0;
	elapsed = 0;

	output_data_format = -1;
	output_header_type = -1;
	normalize_output_floats = 0;
	is_float_format = 0;
	rtoutsfname = NULL;

	rtfileit = 0;                /* signal writing to soundfile */
	rtoutfile = 0;

	print_is_on = 0; // default is off for the RTcmix object

	for (i = 0; i < MAXBUS; i++) {
		AuxToAuxPlayList[i] = -1; /* The playback order for AUX buses */
		ToOutPlayList[i] = -1;    /* The playback order for AUX buses */
		ToAuxPlayList[i] =-1;     /* The playback order for AUX buses */
	}

	for (i = 0; i < MAX_INPUT_FDS; i++) inputFileTable[i].fd = NO_FD;

	init_buf_ptrs();
}

/* ----------------------------------------------------- detect_denormals --- */
/* Unmask "denormalized operand" bit of the x86 FPU control word, so that
   any operations with denormalized numbers will raise a SIGFPE signal,
   and our handler will be called.  NOTE: This is for debugging only!
   This will not tell you how many denormal ops there are, so just because
   the exception is thrown doesn't mean there's a serious problem.  For
   more info, see: http://www.smartelectronix.com/musicdsp/text/other001.txt.
*/
#ifdef LINUX
#ifdef DENORMAL_CHECK
static void
detect_denormals()
{
	#include <fpu_control.h>
	int cw = 0;
	_FPU_GETCW(cw);
	cw &= ~_FPU_MASK_DM;
	_FPU_SETCW(cw);
}
#endif /* DENORMAL_CHECK */
#endif /* LINUX */

//  The RTcmix constructor with default SR, NCHANS, and RTBUFSAMPS
RTcmix::RTcmix()
{
	init_globals();
	init(SR, NCHANS, RTBUFSAMPS);
}

//  The RTcmix constructor with settable SR, NCHANS; default RTBUFSAMPS
RTcmix::RTcmix(float tsr, int tnchans)
{
	init_globals();
	init(tsr, tnchans, RTBUFSAMPS);
}

//  The RTcmix constructor with settable SR, NCHANS, and RTBUFSAMPS
RTcmix::RTcmix(float tsr, int tnchans, int bsize)
{
	init_globals();
	init(tsr, tnchans, bsize);
}

//  The actual initialization method called by the constructors

void
RTcmix::init(float tsr, int tnchans, int bsize)
{
	int retcode;		/* for mutexes */
	pthread_t inTraverseThread;

	// for rtsetparams -- I forget why it's set up with both double
	// and float p-field arrays.  Also, these aren't 0-ed out
	// so no need to dimension them at MAXDISPARGS
	float p[3];
	double pp[3];

#ifdef SGI
	flush_all_underflows_to_zero();
#endif

	// set up the command lists, etc.
	ug_intro();		/* introduce standard routines */
	// no profiles!  See the note above about DSOs

	setbuf(stdout, NULL);	/*  Want to see stdout errors */

	// set the sampling rate and nchannels
	p[0] = pp[0] = tsr;
	p[1] = pp[1] = tnchans;
	p[2] = pp[2] = bsize;
	rtsetparams(p, 3, pp);

	retcode = pthread_create(&inTraverseThread, NULL, inTraverse,
					(void *) "");
	if (retcode != 0)
		fprintf(stderr, "inTraverse() thread create failed\n");
}

// numeric p-field sending command.  The first "double" is to disambiguate
// from the string-sending command (below).  An old holdover from ancient
// cmix, but it's a handy thing
Instrument *RTcmix::cmd(char name[], int n_args, double p0, ...)
{
// 	double buftime,sec,usec;
// 	struct timeval tv;
// 	struct timezone tz;
	va_list ap;
	int i;
	double p[MAXDISPARGS];
	void   *retval;

// 	buftime = (double)RTBUFSAMPS/SR;
//
// 	gettimeofday(&tv, &tz);
// 	sec = (double)tv.tv_sec;
// 	usec = (double)tv.tv_usec;
// 	pthread_mutex_lock(&schedtime_lock);
// 	schedtime = (((sec * 1e6) + usec) - baseTime) * 1e-6;
// 	schedtime += ((double)elapsed/(double)SR);
// 	schedtime += buftime;
// 	pthread_mutex_unlock(&schedtime_lock);

	// schedtime is accessed in rtsetoutput() to set the current
	// time.  Plus, in interactive mode we have to run a slight delay
	// from "0" or we wind up scheduling events in the past.

	p[0] = p0;
	va_start(ap, p0); // start variable list after p0
		for (i = 1; i < n_args; i++)
			p[i] = va_arg(ap, double);
	va_end(ap);

	(double) parse_dispatch(name, p, n_args, &retval);

	return (Instrument *) retval;
}

// string p-field sending command.  the first "char*" is to disambiguate
// from the double version above
Instrument *RTcmix::cmd(char name[], int n_args, char* p0, ...)
{
	// these are not time-stamped as above... change if we need to!
	va_list ap;
	int i;
	char st[MAXDISPARGS][100];
	int tmpint;
	double p[MAXDISPARGS];
	void *retval;

	// this kludge dates from the olden days!
	strcpy(st[0], p0);
	tmpint = (int)st[0];
	p[0] = (double)tmpint;
	va_start(ap, p0); // start variable list after p0
		for (i = 1; i < n_args; i++) {
			strcpy(st[i], va_arg(ap, char*));
			tmpint = (int)st[i];
			p[i] = (double)tmpint;
		}
	va_end(ap);

	(double) parse_dispatch(name, p, n_args, &retval);

	return (Instrument *) retval;
}

// for commands with no params -- the double return val is because
// that's what these commands generally do.
double RTcmix::cmd(char name[])
{
	// these are not time-stamped as above... change if we need to!
	double p[MAXDISPARGS]; // for passing into parse_dispatch only
	double retval;

	retval = parse_dispatch(name, p, 0, NULL);

	return(retval);
}

// This is s duplicate of the RTcmix::cmd() function, except that
// instead of returning an Inst*, it returns the double value
// of the RTcmix command that was invoked
double RTcmix::cmdval(char name[], int n_args, double p0, ...)
{
// 	double buftime,sec,usec;
// 	struct timeval tv;
// 	struct timezone tz;
	va_list ap;
	int i;
	double p[MAXDISPARGS];
	void   *retval;

// 	buftime = (double)RTBUFSAMPS/SR;
//
// 	gettimeofday(&tv, &tz);
// 	sec = (double)tv.tv_sec;
// 	usec = (double)tv.tv_usec;
// 	pthread_mutex_lock(&schedtime_lock);
// 	schedtime = (((sec * 1e6) + usec) - baseTime) * 1e-6;
// 	schedtime += ((double)elapsed/(double)SR);
// 	schedtime += buftime;
// 	pthread_mutex_unlock(&schedtime_lock);

	// schedtime is accessed in rtsetoutput() to set the current
	// time.  Plus, in interactive mode we have to run a slight delay
	// from "0" or we wind up scheduling events in the past.

	p[0] = p0;
	va_start(ap, p0); // start variable list after p0
		for (i = 1; i < n_args; i++)
			p[i] = va_arg(ap, double);
	va_end(ap);

	return ((double) parse_dispatch(name, p, n_args, &retval));
}

// This is s duplicate of the RTcmix::cmd() string-passing function, except
// that instead of returning an Inst*, it returns the double value
// of the RTcmix command that was invoked
double RTcmix::cmdval(char name[], int n_args, char* p0, ...)
{
	// these are not time-stamped as above... change if we need to!
	va_list ap;
	int i;
	char st[MAXDISPARGS][100];
	int tmpint;
	double p[MAXDISPARGS];
	void *retval;

	// this kludge dates from the olden days!
	strcpy(st[0], p0);
	tmpint = (int)st[0];
	p[0] = (double)tmpint;
	va_start(ap, p0); // start variable list after p0
		for (i = 1; i < n_args; i++) {
			strcpy(st[i], va_arg(ap, char*));
			tmpint = (int)st[i];
			p[i] = (double)tmpint;
		}
	va_end(ap);

	return ((double) parse_dispatch(name, p, n_args, &retval));
}

void RTcmix::printOn()
{
	print_is_on = 1;
	report_clipping = 1;

	/* Banner */
	if (print_is_on) printf("--------> %s %s <--------\n",
			RTCMIX_NAME, RTCMIX_VERSION);
}

void RTcmix::printOff()
{
	print_is_on = 0;
	report_clipping = 0;
}

void RTcmix::panic()
{
	run_status = RT_PANIC;
	sleep(2);
	run_status = RT_GOOD;
}

void RTcmix::close()
{
	run_status = RT_SHUTDOWN;
	closesf_noexit();
}

// This is from the RTsockfuncs.c file in ../lib.  It's such a handy
// function, I just had to have it here, too!  BGG
/* RTtimeit takes a floating point number of seconds (interval) and a pointer
   to a void-returning function and sets up a timer to call that function
   every interval seconds.  Setting interval to 0.0 should disable the
   timer */
// I notice that because this uses SIGALRM it will wake up sleep()'s
// put sleep()s in a while loop to keep the process alive...
void RTtimeit(float interval, sig_t func)
{
	struct timeval tv;
	struct itimerval itv;

	tv.tv_sec = (int)(interval);
	tv.tv_usec = (int)((interval - (float)tv.tv_sec) * 1000000.0);
	itv.it_interval = tv;
	itv.it_value = tv;
	setitimer(ITIMER_REAL, &itv, NULL);
	signal(SIGALRM, func);
}
<commit_msg>Resetting status to RT_GOOD in init()<commit_after>// OK -- this is now RTcmix.C, hacked from the original "main.C"
// 	in standalone RTcmix.  The idea is to make this a compile-in
//	imbRTcmix.o lib that can be called from within other main()
//	progs.  -- BGG 11/2002

/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/

#include "RTcmix.h"

//#define DBUG
//#define DENORMAL_CHECK
#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <iostream.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <signal.h>
#ifdef LINUX
   #include <sys/soundcard.h>
#endif
#ifdef SGI
   #include <dmedia/audio.h>
#endif

#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <version.h>
#include "rt.h"
#include "../rtstuff/heap/heap.h"
#include "maxdispargs.h"
#include "dbug.h"

extern "C" {
	int ug_intro();
	// I don't call the profiles here, because dead-time instruments
	// won't be compiled into the object file unless they are present at
	// the build (i.e. they aren't DSO's).  RT instruments have the
	// rtprofile() called when they get loaded.  Go Doug, go!
#ifdef SGI
	void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
	void sigfpe_handler(int sig);
#endif
}

rt_item *rt_list;     /* can't put this in globals.h because of rt.h trouble */

/* --------------------------------------------------------- init_globals --- */
static void
init_globals()
{
	int i;

	RTBUFSAMPS = 8192; //default, modifiable with rtsetparams
	NCHANS = 2;
	audioNCHANS = 0;
	SR = 44100.0; // what the heck...
	bufStartSamp = 0;

#ifdef LINUX
	for (i = 0; i < MAXBUS; i++) in_port[i] = out_port[i] = 0;
#endif /* LINUX */
#ifdef MACOSX
#endif
#ifdef SGI
	in_port = 0;
	out_port = 0;
#endif /* SGI */

	rtQueue = new RTQueue[MAXBUS*3];

	rtInteractive = 1; // keep the heap going for this object
	rtsetparams_called = 0; // will call at object instantiation, though

	audio_on = 0;
	audio_config = 1;
	play_audio = 1;              /* modified with set_option */
	full_duplex = 0;
	check_peaks = 1;
	report_clipping = 1;

	/* I can't believe these were never initialized */
	// hey, I'm that kinda guy! :-)
// 	baseTime = 0;
// 	schedtime = 0;
	elapsed = 0;

	output_data_format = -1;
	output_header_type = -1;
	normalize_output_floats = 0;
	is_float_format = 0;
	rtoutsfname = NULL;

	rtfileit = 0;                /* signal writing to soundfile */
	rtoutfile = 0;

	print_is_on = 0; // default is off for the RTcmix object

	for (i = 0; i < MAXBUS; i++) {
		AuxToAuxPlayList[i] = -1; /* The playback order for AUX buses */
		ToOutPlayList[i] = -1;    /* The playback order for AUX buses */
		ToAuxPlayList[i] =-1;     /* The playback order for AUX buses */
	}

	for (i = 0; i < MAX_INPUT_FDS; i++) inputFileTable[i].fd = NO_FD;

	init_buf_ptrs();
}

/* ----------------------------------------------------- detect_denormals --- */
/* Unmask "denormalized operand" bit of the x86 FPU control word, so that
   any operations with denormalized numbers will raise a SIGFPE signal,
   and our handler will be called.  NOTE: This is for debugging only!
   This will not tell you how many denormal ops there are, so just because
   the exception is thrown doesn't mean there's a serious problem.  For
   more info, see: http://www.smartelectronix.com/musicdsp/text/other001.txt.
*/
#ifdef LINUX
#ifdef DENORMAL_CHECK
static void
detect_denormals()
{
	#include <fpu_control.h>
	int cw = 0;
	_FPU_GETCW(cw);
	cw &= ~_FPU_MASK_DM;
	_FPU_SETCW(cw);
}
#endif /* DENORMAL_CHECK */
#endif /* LINUX */

//  The RTcmix constructor with default SR, NCHANS, and RTBUFSAMPS
RTcmix::RTcmix()
{
	init_globals();
	init(SR, NCHANS, RTBUFSAMPS);
}

//  The RTcmix constructor with settable SR, NCHANS; default RTBUFSAMPS
RTcmix::RTcmix(float tsr, int tnchans)
{
	init_globals();
	init(tsr, tnchans, RTBUFSAMPS);
}

//  The RTcmix constructor with settable SR, NCHANS, and RTBUFSAMPS
RTcmix::RTcmix(float tsr, int tnchans, int bsize)
{
	init_globals();
	init(tsr, tnchans, bsize);
}

//  The actual initialization method called by the constructors

void
RTcmix::init(float tsr, int tnchans, int bsize)
{
	int retcode;		/* for mutexes */
	pthread_t inTraverseThread;

	// for rtsetparams -- I forget why it's set up with both double
	// and float p-field arrays.  Also, these aren't 0-ed out
	// so no need to dimension them at MAXDISPARGS
	float p[3];
	double pp[3];

#ifdef SGI
	flush_all_underflows_to_zero();
#endif

	run_status = RT_GOOD;	// Make sure status is good.

	// set up the command lists, etc.
	ug_intro();		/* introduce standard routines */
	// no profiles!  See the note above about DSOs

	setbuf(stdout, NULL);	/*  Want to see stdout errors */

	// set the sampling rate and nchannels
	p[0] = pp[0] = tsr;
	p[1] = pp[1] = tnchans;
	p[2] = pp[2] = bsize;
	rtsetparams(p, 3, pp);

	retcode = pthread_create(&inTraverseThread, NULL, inTraverse,
					(void *) "");
	if (retcode != 0)
		fprintf(stderr, "inTraverse() thread create failed\n");
}

// numeric p-field sending command.  The first "double" is to disambiguate
// from the string-sending command (below).  An old holdover from ancient
// cmix, but it's a handy thing
Instrument *RTcmix::cmd(char name[], int n_args, double p0, ...)
{
// 	double buftime,sec,usec;
// 	struct timeval tv;
// 	struct timezone tz;
	va_list ap;
	int i;
	double p[MAXDISPARGS];
	void   *retval;

// 	buftime = (double)RTBUFSAMPS/SR;
//
// 	gettimeofday(&tv, &tz);
// 	sec = (double)tv.tv_sec;
// 	usec = (double)tv.tv_usec;
// 	pthread_mutex_lock(&schedtime_lock);
// 	schedtime = (((sec * 1e6) + usec) - baseTime) * 1e-6;
// 	schedtime += ((double)elapsed/(double)SR);
// 	schedtime += buftime;
// 	pthread_mutex_unlock(&schedtime_lock);

	// schedtime is accessed in rtsetoutput() to set the current
	// time.  Plus, in interactive mode we have to run a slight delay
	// from "0" or we wind up scheduling events in the past.

	p[0] = p0;
	va_start(ap, p0); // start variable list after p0
		for (i = 1; i < n_args; i++)
			p[i] = va_arg(ap, double);
	va_end(ap);

	(double) parse_dispatch(name, p, n_args, &retval);

	return (Instrument *) retval;
}

// string p-field sending command.  the first "char*" is to disambiguate
// from the double version above
Instrument *RTcmix::cmd(char name[], int n_args, char* p0, ...)
{
	// these are not time-stamped as above... change if we need to!
	va_list ap;
	int i;
	char st[MAXDISPARGS][100];
	int tmpint;
	double p[MAXDISPARGS];
	void *retval;

	// this kludge dates from the olden days!
	strcpy(st[0], p0);
	tmpint = (int)st[0];
	p[0] = (double)tmpint;
	va_start(ap, p0); // start variable list after p0
		for (i = 1; i < n_args; i++) {
			strcpy(st[i], va_arg(ap, char*));
			tmpint = (int)st[i];
			p[i] = (double)tmpint;
		}
	va_end(ap);

	(double) parse_dispatch(name, p, n_args, &retval);

	return (Instrument *) retval;
}

// for commands with no params -- the double return val is because
// that's what these commands generally do.
double RTcmix::cmd(char name[])
{
	// these are not time-stamped as above... change if we need to!
	double p[MAXDISPARGS]; // for passing into parse_dispatch only
	double retval;

	retval = parse_dispatch(name, p, 0, NULL);

	return(retval);
}

// This is s duplicate of the RTcmix::cmd() function, except that
// instead of returning an Inst*, it returns the double value
// of the RTcmix command that was invoked
double RTcmix::cmdval(char name[], int n_args, double p0, ...)
{
// 	double buftime,sec,usec;
// 	struct timeval tv;
// 	struct timezone tz;
	va_list ap;
	int i;
	double p[MAXDISPARGS];
	void   *retval;

// 	buftime = (double)RTBUFSAMPS/SR;
//
// 	gettimeofday(&tv, &tz);
// 	sec = (double)tv.tv_sec;
// 	usec = (double)tv.tv_usec;
// 	pthread_mutex_lock(&schedtime_lock);
// 	schedtime = (((sec * 1e6) + usec) - baseTime) * 1e-6;
// 	schedtime += ((double)elapsed/(double)SR);
// 	schedtime += buftime;
// 	pthread_mutex_unlock(&schedtime_lock);

	// schedtime is accessed in rtsetoutput() to set the current
	// time.  Plus, in interactive mode we have to run a slight delay
	// from "0" or we wind up scheduling events in the past.

	p[0] = p0;
	va_start(ap, p0); // start variable list after p0
		for (i = 1; i < n_args; i++)
			p[i] = va_arg(ap, double);
	va_end(ap);

	return ((double) parse_dispatch(name, p, n_args, &retval));
}

// This is s duplicate of the RTcmix::cmd() string-passing function, except
// that instead of returning an Inst*, it returns the double value
// of the RTcmix command that was invoked
double RTcmix::cmdval(char name[], int n_args, char* p0, ...)
{
	// these are not time-stamped as above... change if we need to!
	va_list ap;
	int i;
	char st[MAXDISPARGS][100];
	int tmpint;
	double p[MAXDISPARGS];
	void *retval;

	// this kludge dates from the olden days!
	strcpy(st[0], p0);
	tmpint = (int)st[0];
	p[0] = (double)tmpint;
	va_start(ap, p0); // start variable list after p0
		for (i = 1; i < n_args; i++) {
			strcpy(st[i], va_arg(ap, char*));
			tmpint = (int)st[i];
			p[i] = (double)tmpint;
		}
	va_end(ap);

	return ((double) parse_dispatch(name, p, n_args, &retval));
}

void RTcmix::printOn()
{
	print_is_on = 1;
	report_clipping = 1;

	/* Banner */
	if (print_is_on) printf("--------> %s %s <--------\n",
			RTCMIX_NAME, RTCMIX_VERSION);
}

void RTcmix::printOff()
{
	print_is_on = 0;
	report_clipping = 0;
}

void RTcmix::panic()
{
	run_status = RT_PANIC;
	sleep(2);
	run_status = RT_GOOD;
}

void RTcmix::close()
{
	run_status = RT_SHUTDOWN;
	closesf_noexit();
}

// This is from the RTsockfuncs.c file in ../lib.  It's such a handy
// function, I just had to have it here, too!  BGG
/* RTtimeit takes a floating point number of seconds (interval) and a pointer
   to a void-returning function and sets up a timer to call that function
   every interval seconds.  Setting interval to 0.0 should disable the
   timer */
// I notice that because this uses SIGALRM it will wake up sleep()'s
// put sleep()s in a while loop to keep the process alive...
void RTtimeit(float interval, sig_t func)
{
	struct timeval tv;
	struct itimerval itv;

	tv.tv_sec = (int)(interval);
	tv.tv_usec = (int)((interval - (float)tv.tv_sec) * 1000000.0);
	itv.it_interval = tv;
	itv.it_value = tv;
	setitimer(ITIMER_REAL, &itv, NULL);
	signal(SIGALRM, func);
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#ifndef mitkCLVoxeFeatures_cpp
#define mitkCLVoxeFeatures_cpp

#include "time.h"
#include <sstream>
#include <fstream>

#include <mitkIOUtil.h>
#include <mitkImageAccessByItk.h>
#include <mitkImageCast.h>
#include "mitkCommandLineParser.h"

#include <mitkGIFCooccurenceMatrix.h>
#include <mitkGIFGrayLevelRunLength.h>

#include "itkDiscreteGaussianImageFilter.h"
#include <itkLaplacianRecursiveGaussianImageFilter.h>
#include "itkHessianRecursiveGaussianImageFilter.h"
#include "itkUnaryFunctorImageFilter.h"
#include "vnl/algo/vnl_symmetric_eigensystem.h"

static vector<double> splitDouble(string str, char delimiter) {
  vector<double> internal;
  stringstream ss(str); // Turn the string into a stream.
  string tok;
  double val;
  while(getline(ss, tok, delimiter)) {
    stringstream s2(tok);
    s2 >> val;
    internal.push_back(val);
  }

  return internal;
}

namespace Functor
{
  template <class TInput, class TOutput>
  class MatrixFirstEigenvalue
  {
  public:
    MatrixFirstEigenvalue() {}
    virtual ~MatrixFirstEigenvalue() {}

    int order;

    inline TOutput operator ()(const TInput& input)
    {
      double a,b,c;
      if (input[0] < 0.01 && input[1] < 0.01 &&input[2] < 0.01 &&input[3] < 0.01 &&input[4] < 0.01 &&input[5] < 0.01)
        return 0;
      vnl_symmetric_eigensystem_compute_eigenvals(input[0], input[1],input[2],input[3],input[4],input[5],a,b,c);
      switch (order)
      {
      case 0: return a;
      case 1: return b;
      case 2: return c;
      default: return a;
      }
    }
    bool operator !=(const MatrixFirstEigenvalue) const
    {
      return false;
    }
    bool operator ==(const MatrixFirstEigenvalue& other) const
    {
      return !(*this != other);
    }
  };
}

template<typename TPixel, unsigned int VImageDimension>
void
  GaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, mitk::Image::Pointer &output)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType >  GaussFilterType;

  GaussFilterType::Pointer gaussianFilter = GaussFilterType::New();
  gaussianFilter->SetInput( itkImage );
  gaussianFilter->SetVariance(variance);
  gaussianFilter->Update();
  mitk::CastToMitkImage(gaussianFilter->GetOutput(), output);
}

template<typename TPixel, unsigned int VImageDimension>
void
  LaplacianOfGaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, mitk::Image::Pointer &output)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType >  GaussFilterType;
  typedef itk::LaplacianRecursiveGaussianImageFilter<ImageType, ImageType>    LaplacianFilter;

  GaussFilterType::Pointer gaussianFilter = GaussFilterType::New();
  gaussianFilter->SetInput( itkImage );
  gaussianFilter->SetVariance(variance);
  gaussianFilter->Update();
  LaplacianFilter::Pointer laplaceFilter = LaplacianFilter::New();
  laplaceFilter->SetInput(gaussianFilter->GetOutput());
  laplaceFilter->Update();
  mitk::CastToMitkImage(laplaceFilter->GetOutput(), output);
}

template<typename TPixel, unsigned int VImageDimension>
void
  HessianOfGaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, std::vector<mitk::Image::Pointer> &out)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::Image<double, VImageDimension> FloatImageType;
  typedef itk::HessianRecursiveGaussianImageFilter <ImageType> HessianFilterType;
  typedef typename HessianFilterType::OutputImageType VectorImageType;
  typedef Functor::MatrixFirstEigenvalue<VectorImageType::PixelType, double> DeterminantFunctorType;
  typedef itk::UnaryFunctorImageFilter<VectorImageType, FloatImageType, DeterminantFunctorType> DetFilterType;

  HessianFilterType::Pointer hessianFilter = HessianFilterType::New();
  hessianFilter->SetInput(itkImage);
  hessianFilter->SetSigma(std::sqrt(variance));
  for (int i = 0; i < VImageDimension; ++i)
  {
    DetFilterType::Pointer detFilter = DetFilterType::New();
    detFilter->SetInput(hessianFilter->GetOutput());
    detFilter->GetFunctor().order = i;
    detFilter->Update();
    mitk::CastToMitkImage(detFilter->GetOutput(), out[i]);
  }
}

int main(int argc, char* argv[])
{
  mitkCommandLineParser parser;
  parser.setArgumentPrefix("--", "-");
  // required params
  parser.addArgument("image", "i", mitkCommandLineParser::InputImage, "Input Image", "Path to the input VTK polydata", us::Any(), false);
  parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output text file", "Target file. The output statistic is appended to this file.", us::Any(), false);

  parser.addArgument("gaussian","g",mitkCommandLineParser::String, "Gaussian Filtering of the input images", "Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
  parser.addArgument("laplace-of-gauss","log",mitkCommandLineParser::String, "Laplacian of Gaussian Filtering", "Laplacian of Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
  parser.addArgument("hessian-of-gauss","hog",mitkCommandLineParser::String, "Hessian of Gaussian Filtering", "Hessian of Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
  // Miniapp Infos
  parser.setCategory("Classification Tools");
  parser.setTitle("Global Image Feature calculator");
  parser.setDescription("Calculates different global statistics for a given segmentation / image combination");
  parser.setContributor("MBI");

  map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);

  if (parsedArgs.size()==0)
  {
    return EXIT_FAILURE;
  }
  if ( parsedArgs.count("help") || parsedArgs.count("h"))
  {
    return EXIT_SUCCESS;
  }
  bool useCooc = parsedArgs.count("cooccurence");

  mitk::Image::Pointer image = mitk::IOUtil::LoadImage(parsedArgs["image"].ToString());
  std::string filename=parsedArgs["output"].ToString();

  mitk::AbstractGlobalImageFeature::FeatureListType stats;
  ////////////////////////////////////////////////////////////////
  // CAlculate Gaussian Features
  ////////////////////////////////////////////////////////////////
  if (parsedArgs.count("gaussian"))
  {
    auto ranges = splitDouble(parsedArgs["gaussian"].ToString(),';');

    for (int i = 0; i < ranges.size(); ++i)
    {
      mitk::Image::Pointer output;
      AccessByItk_2(image, GaussianFilter, ranges[i], output);
      std::string name = filename + "-gaussian-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(output, name);
    }
  }

  ////////////////////////////////////////////////////////////////
  // CAlculate Laplacian Of Gauss Features
  ////////////////////////////////////////////////////////////////
  if (parsedArgs.count("laplace-of-gauss"))
  {
    auto ranges = splitDouble(parsedArgs["laplace-of-gauss"].ToString(),';');

    for (int i = 0; i < ranges.size(); ++i)
    {
      mitk::Image::Pointer output;
      AccessByItk_2(image, LaplacianOfGaussianFilter, ranges[i], output);
      std::string name = filename + "-log-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(output, name);
    }
  }

  ////////////////////////////////////////////////////////////////
  // CAlculate Hessian Of Gauss Features
  ////////////////////////////////////////////////////////////////
  if (parsedArgs.count("hessian-of-gauss"))
  {
    auto ranges = splitDouble(parsedArgs["hessian-of-gauss"].ToString(),';');

    for (int i = 0; i < ranges.size(); ++i)
    {
      std::vector<mitk::Image::Pointer> outs;
      outs.push_back(mitk::Image::New());
      outs.push_back(mitk::Image::New());
      outs.push_back(mitk::Image::New());
      AccessByItk_2(image, HessianOfGaussianFilter, ranges[i], outs);
      std::string name = filename + "-hog0-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(outs[0], name);
      name = filename + "-hog1-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(outs[1], name);
      name = filename + "-hog2-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(outs[2], name);
    }
  }

  return 0;
}

#endif<commit_msg>Added new features<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#ifndef mitkCLVoxeFeatures_cpp
#define mitkCLVoxeFeatures_cpp

#include "time.h"
#include <sstream>
#include <fstream>

#include <mitkIOUtil.h>
#include <mitkImageAccessByItk.h>
#include <mitkImageCast.h>
#include "mitkCommandLineParser.h"

#include <mitkGIFCooccurenceMatrix.h>
#include <mitkGIFGrayLevelRunLength.h>

#include "itkDiscreteGaussianImageFilter.h"
#include <itkLaplacianRecursiveGaussianImageFilter.h>
#include "itkHessianRecursiveGaussianImageFilter.h"
#include "itkUnaryFunctorImageFilter.h"
#include "vnl/algo/vnl_symmetric_eigensystem.h"
#include <itkSubtractImageFilter.h>

static vector<double> splitDouble(string str, char delimiter) {
  vector<double> internal;
  stringstream ss(str); // Turn the string into a stream.
  string tok;
  double val;
  while(getline(ss, tok, delimiter)) {
    stringstream s2(tok);
    s2 >> val;
    internal.push_back(val);
  }

  return internal;
}

namespace Functor
{
  template <class TInput, class TOutput>
  class MatrixFirstEigenvalue
  {
  public:
    MatrixFirstEigenvalue() {}
    virtual ~MatrixFirstEigenvalue() {}

    int order;

    inline TOutput operator ()(const TInput& input)
    {
      double a,b,c;
      if (input[0] < 0.01 && input[1] < 0.01 &&input[2] < 0.01 &&input[3] < 0.01 &&input[4] < 0.01 &&input[5] < 0.01)
        return 0;
      vnl_symmetric_eigensystem_compute_eigenvals(input[0], input[1],input[2],input[3],input[4],input[5],a,b,c);
      switch (order)
      {
      case 0: return a;
      case 1: return b;
      case 2: return c;
      default: return a;
      }
    }
    bool operator !=(const MatrixFirstEigenvalue) const
    {
      return false;
    }
    bool operator ==(const MatrixFirstEigenvalue& other) const
    {
      return !(*this != other);
    }
  };
}

template<typename TPixel, unsigned int VImageDimension>
void
  GaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, mitk::Image::Pointer &output)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType >  GaussFilterType;

  GaussFilterType::Pointer gaussianFilter = GaussFilterType::New();
  gaussianFilter->SetInput( itkImage );
  gaussianFilter->SetVariance(variance);
  gaussianFilter->Update();
  mitk::CastToMitkImage(gaussianFilter->GetOutput(), output);
}

template<typename TPixel, unsigned int VImageDimension>
void
  DifferenceOfGaussFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, mitk::Image::Pointer &output)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType >  GaussFilterType;
  typedef itk::SubtractImageFilter<ImageType, ImageType, ImageType> SubFilterType;

  GaussFilterType::Pointer gaussianFilter1 = GaussFilterType::New();
  gaussianFilter1->SetInput( itkImage );
  gaussianFilter1->SetVariance(variance);
  gaussianFilter1->Update();
  GaussFilterType::Pointer gaussianFilter2 = GaussFilterType::New();
  gaussianFilter2->SetInput( itkImage );
  gaussianFilter2->SetVariance(variance*0.66*0.66);
  gaussianFilter2->Update();
  SubFilterType::Pointer subFilter = SubFilterType::New();
  subFilter->SetInput1(gaussianFilter1->GetOutput());
  subFilter->SetInput2(gaussianFilter2->GetOutput());
  subFilter->Update();
  mitk::CastToMitkImage(subFilter->GetOutput(), output);
}

template<typename TPixel, unsigned int VImageDimension>
void
  LaplacianOfGaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, mitk::Image::Pointer &output)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType >  GaussFilterType;
  typedef itk::LaplacianRecursiveGaussianImageFilter<ImageType, ImageType>    LaplacianFilter;

  GaussFilterType::Pointer gaussianFilter = GaussFilterType::New();
  gaussianFilter->SetInput( itkImage );
  gaussianFilter->SetVariance(variance);
  gaussianFilter->Update();
  LaplacianFilter::Pointer laplaceFilter = LaplacianFilter::New();
  laplaceFilter->SetInput(gaussianFilter->GetOutput());
  laplaceFilter->Update();
  mitk::CastToMitkImage(laplaceFilter->GetOutput(), output);
}

template<typename TPixel, unsigned int VImageDimension>
void
  HessianOfGaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, std::vector<mitk::Image::Pointer> &out)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::Image<double, VImageDimension> FloatImageType;
  typedef itk::HessianRecursiveGaussianImageFilter <ImageType> HessianFilterType;
  typedef typename HessianFilterType::OutputImageType VectorImageType;
  typedef Functor::MatrixFirstEigenvalue<VectorImageType::PixelType, double> DeterminantFunctorType;
  typedef itk::UnaryFunctorImageFilter<VectorImageType, FloatImageType, DeterminantFunctorType> DetFilterType;

  HessianFilterType::Pointer hessianFilter = HessianFilterType::New();
  hessianFilter->SetInput(itkImage);
  hessianFilter->SetSigma(std::sqrt(variance));
  for (int i = 0; i < VImageDimension; ++i)
  {
    DetFilterType::Pointer detFilter = DetFilterType::New();
    detFilter->SetInput(hessianFilter->GetOutput());
    detFilter->GetFunctor().order = i;
    detFilter->Update();
    mitk::CastToMitkImage(detFilter->GetOutput(), out[i]);
  }
}

int main(int argc, char* argv[])
{
  mitkCommandLineParser parser;
  parser.setArgumentPrefix("--", "-");
  // required params
  parser.addArgument("image", "i", mitkCommandLineParser::InputImage, "Input Image", "Path to the input VTK polydata", us::Any(), false);
  parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output text file", "Target file. The output statistic is appended to this file.", us::Any(), false);

  parser.addArgument("gaussian","g",mitkCommandLineParser::String, "Gaussian Filtering of the input images", "Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
  parser.addArgument("difference-of-gaussian","dog",mitkCommandLineParser::String, "Difference of Gaussian Filtering of the input images", "Difference of Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
  parser.addArgument("laplace-of-gauss","log",mitkCommandLineParser::String, "Laplacian of Gaussian Filtering", "Laplacian of Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
  parser.addArgument("hessian-of-gauss","hog",mitkCommandLineParser::String, "Hessian of Gaussian Filtering", "Hessian of Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
  // Miniapp Infos
  parser.setCategory("Classification Tools");
  parser.setTitle("Global Image Feature calculator");
  parser.setDescription("Calculates different global statistics for a given segmentation / image combination");
  parser.setContributor("MBI");

  map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);

  if (parsedArgs.size()==0)
  {
    return EXIT_FAILURE;
  }
  if ( parsedArgs.count("help") || parsedArgs.count("h"))
  {
    return EXIT_SUCCESS;
  }
  bool useCooc = parsedArgs.count("cooccurence");

  mitk::Image::Pointer image = mitk::IOUtil::LoadImage(parsedArgs["image"].ToString());
  std::string filename=parsedArgs["output"].ToString();

  ////////////////////////////////////////////////////////////////
  // CAlculate Gaussian Features
  ////////////////////////////////////////////////////////////////
  MITK_INFO << "Check for Gaussian...";
  if (parsedArgs.count("gaussian"))
  {
    MITK_INFO << "Calculate Gaussian... " << parsedArgs["gaussian"].ToString();
    auto ranges = splitDouble(parsedArgs["gaussian"].ToString(),';');

    for (int i = 0; i < ranges.size(); ++i)
    {
      mitk::Image::Pointer output;
      AccessByItk_2(image, GaussianFilter, ranges[i], output);
      std::string name = filename + "-gaussian-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(output, name);
    }
  }

  ////////////////////////////////////////////////////////////////
  // CAlculate Difference of Gaussian Features
  ////////////////////////////////////////////////////////////////
  MITK_INFO << "Check for DoG...";
  if (parsedArgs.count("difference-of-gaussian"))
  {
    MITK_INFO << "Calculate Difference of Gaussian... " << parsedArgs["difference-of-gaussian"].ToString();
    auto ranges = splitDouble(parsedArgs["difference-of-gaussian"].ToString(),';');

    for (int i = 0; i < ranges.size(); ++i)
    {
      mitk::Image::Pointer output;
      AccessByItk_2(image, DifferenceOfGaussFilter, ranges[i], output);
      std::string name = filename + "-dog-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(output, name);
    }
  }

  MITK_INFO << "Check for LoG...";
  ////////////////////////////////////////////////////////////////
  // CAlculate Laplacian Of Gauss Features
  ////////////////////////////////////////////////////////////////
  if (parsedArgs.count("laplace-of-gauss"))
  {
    MITK_INFO << "Calculate LoG... " << parsedArgs["laplace-of-gauss"].ToString();
    auto ranges = splitDouble(parsedArgs["laplace-of-gauss"].ToString(),';');

    for (int i = 0; i < ranges.size(); ++i)
    {
      mitk::Image::Pointer output;
      AccessByItk_2(image, LaplacianOfGaussianFilter, ranges[i], output);
      std::string name = filename + "-log-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(output, name);
    }
  }

  MITK_INFO << "Check for HoG...";
  ////////////////////////////////////////////////////////////////
  // CAlculate Hessian Of Gauss Features
  ////////////////////////////////////////////////////////////////
  if (parsedArgs.count("hessian-of-gauss"))
  {
    MITK_INFO << "Calculate HoG... " << parsedArgs["hessian-of-gauss"].ToString();
    auto ranges = splitDouble(parsedArgs["hessian-of-gauss"].ToString(),';');

    for (int i = 0; i < ranges.size(); ++i)
    {
      std::vector<mitk::Image::Pointer> outs;
      outs.push_back(mitk::Image::New());
      outs.push_back(mitk::Image::New());
      outs.push_back(mitk::Image::New());
      AccessByItk_2(image, HessianOfGaussianFilter, ranges[i], outs);
      std::string name = filename + "-hog0-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(outs[0], name);
      name = filename + "-hog1-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(outs[1], name);
      name = filename + "-hog2-" + us::any_value_to_string(ranges[i])+".nrrd";
      mitk::IOUtil::SaveImage(outs[2], name);
    }
  }

  return 0;
}

#endif<|endoftext|>


<commit_before>/**
 *  @copyright Copyright 2017 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetOptionValidator.cpp
 */

#include "./JPetOptionValidator.h"
#include "./JPetCommonTools/JPetCommonTools.h"
#include "./JPetLoggerInclude.h"
#include "./JPetAdditionalValidators.h"

using boost::any_cast;

JPetOptionValidator::JPetOptionValidator()
{
  fValidatorMap = generateValidationMap();
}

bool JPetOptionValidator::areCorrectOptions(const std::map<std::string, boost::any>& optionsMap, std::vector<std::string>& isOption)
{
  for (auto& checkGroup : fValidatorMap) {
    if (std::find(isOption.begin(), isOption.end(), checkGroup.first ) != isOption.end()) {
      for (auto& checkFunc : checkGroup.second) {
        if (( !checkFunc(std::make_pair(checkGroup.first, optionsMap.at(checkGroup.first))) )) {
          ERROR("ERROR VALIDATON FOR " + checkGroup.first);
          return false;
        }
      }
    }
  }
  return true;
}

std::map<std::string, std::vector<bool(*)(std::pair <std::string, boost::any>)> > JPetOptionValidator::generateValidationMap()
{
  std::map<std::string, std::vector<bool(*)(std::pair <std::string, boost::any>)> > validationMap;
  validationMap["range_std::vector<int>"].push_back(&isNumberBoundsInRangeValid);
  validationMap["range_std::vector<int>"].push_back(&isRangeOfEventsValid);
  validationMap["type_std::string"].push_back(&isCorrectFileType);
  validationMap["file_std::vector<std::string>"].push_back(&areFilesValid);
  validationMap["runId_int"].push_back(&isRunIdValid);
  validationMap["localDB_std::string"].push_back(&isLocalDBValid);
  validationMap["outputPath_std::string"].push_back(&isOutputDirectoryValid);
  return validationMap;
}

void JPetOptionValidator::addValidatorFunction(const std::string& name, bool(*validatorFunction)(std::pair <std::string, boost::any>) )
{
  fValidatorMap[name].push_back(validatorFunction);
}

bool JPetOptionValidator::isNumberBoundsInRangeValid(std::pair <std::string, boost::any> option)
{
  if ( any_cast<std::vector<int>>(option.second).size() != 2) {
    ERROR("Wrong number of bounds in range: " + std::to_string(any_cast<std::vector<int>>(option.second).size()));
    return false;
  }
  return true;
}

bool JPetOptionValidator::isRangeOfEventsValid(std::pair <std::string, boost::any> option)
{
  if ( any_cast<std::vector<int>>(option.second).at(0) > any_cast<std::vector<int>>(option.second).at(1)) {
    ERROR("Wrong number of bounds in range: " + std::to_string(any_cast<std::vector<int>>(option.second).size()));
    return false;
  }
  return true;
}

bool JPetOptionValidator::isCorrectFileType(std::pair <std::string, boost::any> option)
{
  std::string type = any_cast<std::string>(option.second);
  if (type == "hld" || type == "root" || type == "scope" || type == "zip") {
    return true;
  } else {
    ERROR("Wrong type of file:" + type);
    return false;
  }
}

bool JPetOptionValidator::isRunIdValid(std::pair <std::string, boost::any> option)
{
  if ( any_cast<int>(option.second) <= 0) {
    ERROR("Run id must be a number larger than 0.");
    return false;
  }
  return true;
}

bool JPetOptionValidator::isLocalDBValid(std::pair <std::string, boost::any> option)
{
  if ( !JPetCommonTools::ifFileExisting(any_cast<std::string>(option.second)) ) {
    ERROR("File doed not exist.");
    return false;
  }
  return true;
}

bool JPetOptionValidator::areFilesValid(std::pair <std::string, boost::any> option)
{
  std::vector<std::string> fileNames = any_cast<std::vector<std::string>>(option.second);
  for ( unsigned int i = 0; i < fileNames.size(); i++ ) {
    if ( !JPetCommonTools::ifFileExisting(fileNames[i])) {
      ERROR("File : " + fileNames[i] + " does not exist.");
      return false;
    }
  }
  return true;
}

bool JPetOptionValidator::isOutputDirectoryValid(std::pair <std::string, boost::any> option)
{
  if (!JPetCommonTools::isDirectory(any_cast<std::string>(option.second))) {
    ERROR("Output directory does not exist.");
    return false;
  }
  return true;
}
<commit_msg>add -t/-f option check<commit_after>/**
 *  @copyright Copyright 2017 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetOptionValidator.cpp
 */

#include "./JPetOptionValidator.h"
#include "./JPetCommonTools/JPetCommonTools.h"
#include "./JPetLoggerInclude.h"

using boost::any_cast;

JPetOptionValidator::JPetOptionValidator()
{
  fValidatorMap = generateValidationMap();
}

bool JPetOptionValidator::areCorrectOptions(const std::map<std::string, boost::any>& optionsMap, std::vector<std::string>& isOption)
{
  for (auto& checkGroup : fValidatorMap) {
    if (std::find(isOption.begin(), isOption.end(), checkGroup.first ) != isOption.end()) {
      for (auto& checkFunc : checkGroup.second) {
        if (( !checkFunc(std::make_pair(checkGroup.first, optionsMap.at(checkGroup.first))) )) {
          ERROR("ERROR VALIDATON FOR " + checkGroup.first);
          return false;
        }
      }
    }
  }
  return true;
}

std::map<std::string, std::vector<bool(*)(std::pair <std::string, boost::any>)> > JPetOptionValidator::generateValidationMap()
{
  std::map<std::string, std::vector<bool(*)(std::pair <std::string, boost::any>)> > validationMap;
  validationMap["range_std::vector<int>"].push_back(&isNumberBoundsInRangeValid);
  validationMap["range_std::vector<int>"].push_back(&isRangeOfEventsValid);
  validationMap["type_std::string"].push_back(&isCorrectFileType);
  validationMap["file_std::vector<std::string>"].push_back(&areFilesValid);
  validationMap["type_std::string, file_std::vector<std::string>"].push_back(&isFileTypeMatchingExtensions);
  validationMap["runId_int"].push_back(&isRunIdValid);
  validationMap["localDB_std::string"].push_back(&isLocalDBValid);
  validationMap["outputPath_std::string"].push_back(&isOutputDirectoryValid);
  return validationMap;
}

void JPetOptionValidator::addValidatorFunction(const std::string& name, bool(*validatorFunction)(std::pair <std::string, boost::any>) )
{
  fValidatorMap[name].push_back(validatorFunction);
}

bool JPetOptionValidator::isNumberBoundsInRangeValid(std::pair <std::string, boost::any> option)
{
  if ( any_cast<std::vector<int>>(option.second).size() != 2) {
    ERROR("Wrong number of bounds in range: " + std::to_string(any_cast<std::vector<int>>(option.second).size()));
    return false;
  }
  return true;
}

bool JPetOptionValidator::isRangeOfEventsValid(std::pair <std::string, boost::any> option)
{
  if ( any_cast<std::vector<int>>(option.second).at(0) > any_cast<std::vector<int>>(option.second).at(1)) {
    ERROR("Wrong number of bounds in range: " + std::to_string(any_cast<std::vector<int>>(option.second).size()));
    return false;
  }
  return true;
}

bool JPetOptionValidator::isCorrectFileType(std::pair <std::string, boost::any> option)
{
  std::string type = any_cast<std::string>(option.second);
  if (type == "hld" || type == "root" || type == "scope" || type == "zip") {
    return true;
  } else {
    ERROR("Wrong type of file:" + type);
    return false;
  }
}

bool JPetOptionValidator::isFileTypeMatchingExtensions(std::pair<std::string, boost::any> option)
{
  ManyOptionsWrapper optionsWrapper = any_cast<ManyOptionsWrapper>(option.second);
  std::vector<boost::any> optionsVector = any_cast<std::vector<boost::any>>(optionsWrapper.getOptionsVector());
  std::string fileType = any_cast<std::string>(optionsVector[0]);
  std::vector<std::string> fileNames = any_cast<std::vector<std::string>>(optionsVector[1]);
  for (const std::string &fileName : fileNames) {
    if (fileName.substr(fileName.find_last_of('.') + 1) != fileType) {
      ERROR("Wrong extension of file: " + fileName);
      return false;
    }
  }
  return true;
}

bool JPetOptionValidator::isRunIdValid(std::pair <std::string, boost::any> option)
{
  if ( any_cast<int>(option.second) <= 0) {
    ERROR("Run id must be a number larger than 0.");
    return false;
  }
  return true;
}

bool JPetOptionValidator::isLocalDBValid(std::pair <std::string, boost::any> option)
{
  if ( !JPetCommonTools::ifFileExisting(any_cast<std::string>(option.second)) ) {
    ERROR("File doed not exist.");
    return false;
  }
  return true;
}

bool JPetOptionValidator::areFilesValid(std::pair <std::string, boost::any> option)
{
  std::vector<std::string> fileNames = any_cast<std::vector<std::string>>(option.second);
  for ( unsigned int i = 0; i < fileNames.size(); i++ ) {
    if ( !JPetCommonTools::ifFileExisting(fileNames[i])) {
      ERROR("File : " + fileNames[i] + " does not exist.");
      return false;
    }
  }
  return true;
}

bool JPetOptionValidator::isOutputDirectoryValid(std::pair <std::string, boost::any> option)
{
  if (!JPetCommonTools::isDirectory(any_cast<std::string>(option.second))) {
    ERROR("Output directory does not exist.");
    return false;
  }
  return true;
}

JPetOptionValidator::ManyOptionsWrapper::ManyOptionsWrapper(std::initializer_list<boost::any> options)
{
  optionsVector = options;
}

std::vector<boost::any> JPetOptionValidator::ManyOptionsWrapper::getOptionsVector()
{
  return optionsVector;
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

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

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

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

namespace Ogre {

	//---------------------------------------------------------------------
    GLHardwareVertexBuffer::GLHardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
        size_t numVertices, HardwareBuffer::Usage usage, bool useShadowBuffer)
        : HardwareVertexBuffer(mgr, vertexSize, numVertices, usage, false, useShadowBuffer)
    {
        glGenBuffersARB( 1, &mBufferId );

        if (!mBufferId)
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                "Cannot create GL vertex buffer",
                "GLHardwareVertexBuffer::GLHardwareVertexBuffer");
        }

        static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

        // Initialise mapped buffer and set usage
        glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL,
            GLHardwareBufferManager::getGLUsage(usage));

        //std::cerr << "creating vertex buffer = " << mBufferId << std::endl;
    }
	//---------------------------------------------------------------------
    GLHardwareVertexBuffer::~GLHardwareVertexBuffer()
    {
        static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->deleteGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);
    }
	//---------------------------------------------------------------------
    void* GLHardwareVertexBuffer::lockImpl(size_t offset,
        size_t length, LockOptions options)
    {
        if(mIsLocked)
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                "Invalid attempt to lock an vertex buffer that has already been locked",
                "GLHardwareVertexBuffer::lock");
        }

		void* retPtr = 0;

		GLHardwareBufferManager* glBufManager = static_cast<GLHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr());

		// Try to use scratch buffers for smaller buffers
		if( length < glBufManager->getGLMapBufferThreshold() )
		{
			// if this fails, we fall back on mapping
			retPtr = glBufManager->allocateScratch((uint32)length);

			if (retPtr)
			{
				mLockedToScratch = true;
				mScratchOffset = offset;
				mScratchSize = length;
				mScratchPtr = retPtr;
				mScratchUploadOnUnlock = (options != HBL_READ_ONLY);

				if (options != HBL_DISCARD && options != HBL_NO_OVERWRITE)
				{
					// have to read back the data before returning the pointer
					readData(offset, length, retPtr);
				}
			}
		}

		if (!retPtr)
		{
            GLenum access = 0;
			// Use glMapBuffer
            static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);
			// Use glMapBuffer
			if(options == HBL_DISCARD || options == HBL_NO_OVERWRITE) // TODO: check possibility to use GL_MAP_UNSYNCHRONIZED_BIT for HBL_NO_OVERWRITE locking promise
			{
				// Discard the buffer
				glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL,
					GLHardwareBufferManager::getGLUsage(mUsage));
			}
			if (mUsage & HBU_WRITE_ONLY)
				access = GL_WRITE_ONLY_ARB;
			else if (options == HBL_READ_ONLY)
				access = GL_READ_ONLY_ARB;
			else
				access = GL_READ_WRITE_ARB;

			void* pBuffer = glMapBufferARB( GL_ARRAY_BUFFER_ARB, access);
            if(pBuffer == 0)
			{
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
					"Vertex Buffer: Out of memory", "GLHardwareVertexBuffer::lock");
			}

			// return offsetted
			retPtr = static_cast<void*>(
				static_cast<unsigned char*>(pBuffer) + offset);

			mLockedToScratch = false;
		}
		mIsLocked = true;
		return retPtr;
    }
	//---------------------------------------------------------------------
	void GLHardwareVertexBuffer::unlockImpl(void)
    {
		if (mLockedToScratch)
		{
			if (mScratchUploadOnUnlock)
			{
				// have to write the data back to vertex buffer
				writeData(mScratchOffset, mScratchSize, mScratchPtr,
					mScratchOffset == 0 && mScratchSize == getSizeInBytes());
			}

			// deallocate from scratch buffer
			static_cast<GLHardwareBufferManager*>(
				HardwareBufferManager::getSingletonPtr())->deallocateScratch(mScratchPtr);

			mLockedToScratch = false;
		}
		else
		{
            static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

			if(!glUnmapBufferARB( GL_ARRAY_BUFFER_ARB ))
			{
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
					"Buffer data corrupted, please reload",
					"GLHardwareVertexBuffer::unlock");
			}
		}

        mIsLocked = false;
    }
	//---------------------------------------------------------------------
    void GLHardwareVertexBuffer::readData(size_t offset, size_t length,
        void* pDest)
    {
        if(mUseShadowBuffer)
        {
            // get data from the shadow buffer
            void* srcData = mShadowBuffer->lock(offset, length, HBL_READ_ONLY);
            memcpy(pDest, srcData, length);
            mShadowBuffer->unlock();
        }
        else
        {
            // get data from the real buffer
            static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

            glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, pDest);
        }
    }
	//---------------------------------------------------------------------
    void GLHardwareVertexBuffer::writeData(size_t offset, size_t length,
            const void* pSource, bool discardWholeBuffer)
    {
        static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

        // Update the shadow buffer
        if(mUseShadowBuffer)
        {
            void* destData = mShadowBuffer->lock(offset, length,
                discardWholeBuffer ? HBL_DISCARD : HBL_NORMAL);
            memcpy(destData, pSource, length);
            mShadowBuffer->unlock();
        }

        if (offset == 0 && length == mSizeInBytes)
        {
            glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, pSource,
                GLHardwareBufferManager::getGLUsage(mUsage));
        }
        else
        {
            if(discardWholeBuffer)
            {
                glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL,
                    GLHardwareBufferManager::getGLUsage(mUsage));
            }

            // Now update the real buffer
            glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, pSource);
        }
    }
	//---------------------------------------------------------------------
    void GLHardwareVertexBuffer::_updateFromShadow(void)
    {
        if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate)
        {
            const void *srcData = mShadowBuffer->lock(
                mLockStart, mLockSize, HBL_READ_ONLY);

            static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

            // Update whole buffer if possible, otherwise normal
            if (mLockStart == 0 && mLockSize == mSizeInBytes)
            {
                glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, srcData,
                    GLHardwareBufferManager::getGLUsage(mUsage));
            }
            else
            {
                glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, mLockStart, mLockSize, srcData);
            }

            mShadowBuffer->unlock();
            mShadowUpdated = false;
        }
    }
}
<commit_msg>Recover GLHardwareVertexBuffer if glBufferDataARB fails (happens on OSX Mavericks)<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

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

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

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

namespace Ogre {

	//---------------------------------------------------------------------
    GLHardwareVertexBuffer::GLHardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
        size_t numVertices, HardwareBuffer::Usage usage, bool useShadowBuffer)
        : HardwareVertexBuffer(mgr, vertexSize, numVertices, usage, false, useShadowBuffer)
    {
        glGenBuffersARB( 1, &mBufferId );

        if (!mBufferId)
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                "Cannot create GL vertex buffer",
                "GLHardwareVertexBuffer::GLHardwareVertexBuffer");
        }

        static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

        // Initialise mapped buffer and set usage
        glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL,
            GLHardwareBufferManager::getGLUsage(usage));

        //std::cerr << "creating vertex buffer = " << mBufferId << std::endl;
    }
	//---------------------------------------------------------------------
    GLHardwareVertexBuffer::~GLHardwareVertexBuffer()
    {
        static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->deleteGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);
    }
	//---------------------------------------------------------------------
    void* GLHardwareVertexBuffer::lockImpl(size_t offset,
        size_t length, LockOptions options)
    {
        if(mIsLocked)
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                "Invalid attempt to lock an vertex buffer that has already been locked",
                "GLHardwareVertexBuffer::lock");
        }

		void* retPtr = 0;

		GLHardwareBufferManager* glBufManager = static_cast<GLHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr());

		// Try to use scratch buffers for smaller buffers
		if( length < glBufManager->getGLMapBufferThreshold() )
		{
			// if this fails, we fall back on mapping
			retPtr = glBufManager->allocateScratch((uint32)length);

			if (retPtr)
			{
				mLockedToScratch = true;
				mScratchOffset = offset;
				mScratchSize = length;
				mScratchPtr = retPtr;
				mScratchUploadOnUnlock = (options != HBL_READ_ONLY);

				if (options != HBL_DISCARD && options != HBL_NO_OVERWRITE)
				{
					// have to read back the data before returning the pointer
					readData(offset, length, retPtr);
				}
			}
		}

		if (!retPtr)
		{
            GLenum access = 0;
			// Use glMapBuffer
            static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);
			// Use glMapBuffer
			if(options == HBL_DISCARD || options == HBL_NO_OVERWRITE) // TODO: check possibility to use GL_MAP_UNSYNCHRONIZED_BIT for HBL_NO_OVERWRITE locking promise
			{
				// Discard the buffer
				glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL,
					GLHardwareBufferManager::getGLUsage(mUsage));

                GLenum error = glGetError();
                if(error != 0)
                {
                    String glErrDesc;
                    const char* glerrStr = (const char*)gluErrorString(error);
                    if (glerrStr)
                        glErrDesc = glerrStr;

                    LogManager::getSingleton().logMessage("GLHardwareVertexBuffer::lock - Error: failed to Discard the buffer. Try to recreate the buffer", LML_CRITICAL);

                    static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->deleteGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);
                    mBufferId = 0;

                    glGenBuffersARB( 1, &mBufferId );

                    static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

                    glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL,
                                    GLHardwareBufferManager::getGLUsage(mUsage));
                }
			}

			if (mUsage & HBU_WRITE_ONLY)
				access = GL_WRITE_ONLY_ARB;
			else if (options == HBL_READ_ONLY)
				access = GL_READ_ONLY_ARB;
			else
				access = GL_READ_WRITE_ARB;

			void* pBuffer = glMapBufferARB( GL_ARRAY_BUFFER_ARB, access);
            if(pBuffer == 0)
			{
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
					"Vertex Buffer: Out of memory", "GLHardwareVertexBuffer::lock");
			}

			// return offsetted
			retPtr = static_cast<void*>(
				static_cast<unsigned char*>(pBuffer) + offset);

			mLockedToScratch = false;
		}
		mIsLocked = true;
		return retPtr;
    }
	//---------------------------------------------------------------------
	void GLHardwareVertexBuffer::unlockImpl(void)
    {
		if (mLockedToScratch)
		{
			if (mScratchUploadOnUnlock)
			{
				// have to write the data back to vertex buffer
				writeData(mScratchOffset, mScratchSize, mScratchPtr,
					mScratchOffset == 0 && mScratchSize == getSizeInBytes());
			}

			// deallocate from scratch buffer
			static_cast<GLHardwareBufferManager*>(
				HardwareBufferManager::getSingletonPtr())->deallocateScratch(mScratchPtr);

			mLockedToScratch = false;
		}
		else
		{
            static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

			if(!glUnmapBufferARB( GL_ARRAY_BUFFER_ARB ))
			{
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
					"Buffer data corrupted, please reload",
					"GLHardwareVertexBuffer::unlock");
			}
		}

        mIsLocked = false;
    }
	//---------------------------------------------------------------------
    void GLHardwareVertexBuffer::readData(size_t offset, size_t length,
        void* pDest)
    {
        if(mUseShadowBuffer)
        {
            // get data from the shadow buffer
            void* srcData = mShadowBuffer->lock(offset, length, HBL_READ_ONLY);
            memcpy(pDest, srcData, length);
            mShadowBuffer->unlock();
        }
        else
        {
            // get data from the real buffer
            static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

            glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, pDest);
        }
    }
	//---------------------------------------------------------------------
    void GLHardwareVertexBuffer::writeData(size_t offset, size_t length,
            const void* pSource, bool discardWholeBuffer)
    {
        static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

        // Update the shadow buffer
        if(mUseShadowBuffer)
        {
            void* destData = mShadowBuffer->lock(offset, length,
                discardWholeBuffer ? HBL_DISCARD : HBL_NORMAL);
            memcpy(destData, pSource, length);
            mShadowBuffer->unlock();
        }

        if (offset == 0 && length == mSizeInBytes)
        {
            glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, pSource,
                GLHardwareBufferManager::getGLUsage(mUsage));
        }
        else
        {
            if(discardWholeBuffer)
            {
                glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL,
                    GLHardwareBufferManager::getGLUsage(mUsage));
            }

            // Now update the real buffer
            glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, pSource);
        }
    }
	//---------------------------------------------------------------------
    void GLHardwareVertexBuffer::_updateFromShadow(void)
    {
        if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate)
        {
            const void *srcData = mShadowBuffer->lock(
                mLockStart, mLockSize, HBL_READ_ONLY);

            static_cast<GLHardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER_ARB, mBufferId);

            // Update whole buffer if possible, otherwise normal
            if (mLockStart == 0 && mLockSize == mSizeInBytes)
            {
                glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, srcData,
                    GLHardwareBufferManager::getGLUsage(mUsage));
            }
            else
            {
                glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, mLockStart, mLockSize, srcData);
            }

            mShadowBuffer->unlock();
            mShadowUpdated = false;
        }
    }
}
<|endoftext|>