<commit_before>/*
 * Copyright 2021 The CFU-Playground Authors
 *
 * 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 "blocks.h"

#include <cstdio>

#include "hps_cfu.h"

namespace hps_accel {

namespace {

constexpr size_t BYTES_PER_WORD = 4;

inline uint32_t pack32(int8_t a, int8_t b, int8_t c, int8_t d) {
  return static_cast<uint32_t>(static_cast<uint8_t>(a)) |
         (static_cast<uint32_t>(static_cast<uint8_t>(b)) << 8) |
         (static_cast<uint32_t>(static_cast<uint8_t>(c)) << 16) |
         (static_cast<uint32_t>(static_cast<uint8_t>(d)) << 24);
}

// Load input when in_channels = 1
void LoadInput1(size_t width, const int8_t* values) {
  size_t input_words = 4;
  cfu_set_sw(REG_INPUT_NUM_WORDS, input_words);

  // For each of four consecutive rows, take data from four consecutive pixels
  for (size_t row_index = 0; row_index < 4; row_index++) {
    const int8_t* source = values + (row_index * width);
    cfu_set_sw(REG_SET_INPUT, pack32(source[0], source[1], source[2], source[3]));
  }
}

// Load input when in_channels is divisible by 4
void LoadInputN(size_t width, size_t in_channels, const int8_t* values) {
  const size_t pixels_per_input_row = 4;
  const size_t words_per_input_row =
      pixels_per_input_row * in_channels / BYTES_PER_WORD;
  const size_t bytes_per_width = width * in_channels;
  size_t input_words =
      FILTER_WIDTH * FILTER_HEIGHT * in_channels / BYTES_PER_WORD;
  cfu_set_sw(REG_INPUT_NUM_WORDS, input_words);

  // For each of four consecutive rows, take data from four consecutive pixels
  for (size_t row_index = 0; row_index < 4; row_index++) {
    const uint32_t* source = reinterpret_cast<const uint32_t*>(
        values + (row_index * bytes_per_width));
    for (size_t i = 0; i < words_per_input_row; i++) {
      cfu_set_sw(REG_SET_INPUT, *source++);
    }
  }
}

};  // anonymous namespace

Vector16 Vector16::build(int8_t a, int8_t b, int8_t c, int8_t d, int8_t e,
                         int8_t f, int8_t g, int8_t h, int8_t i, int8_t j,
                         int8_t k, int8_t l, int8_t m, int8_t n, int8_t o,
                         int8_t p) {
  return Vector16{{pack32(a, b, c, d), pack32(e, f, g, h), pack32(i, j, k, l),
                   pack32(m, n, o, p)}};
}

Vector16 Vector16::zeroes() { return Vector16{{0, 0, 0, 0}}; }

// Performs a 16 x 16 vector multiplication
int32_t multiply_accumulate(Vector16 input, Vector16 filter,
                            int32_t input_offset) {
  cfu_set(REG_INPUT_OFFSET, input_offset);
  cfu_set(REG_MACC_INPUT_0, input.values[0]);
  cfu_set(REG_MACC_INPUT_1, input.values[1]);
  cfu_set(REG_MACC_INPUT_2, input.values[2]);
  cfu_set(REG_MACC_INPUT_3, input.values[3]);
  cfu_set(REG_MACC_FILTER_0, filter.values[0]);
  cfu_set(REG_MACC_FILTER_1, filter.values[1]);
  cfu_set(REG_MACC_FILTER_2, filter.values[2]);
  cfu_set(REG_MACC_FILTER_3, filter.values[3]);
  asm volatile("nop"); // One cycle for last set to complete fully
  asm volatile("nop"); // Two more cycles for MACC to complete
  asm volatile("nop");
  return cfu_get(REG_MACC_OUT);
}

void LoadFilter(size_t in_channels, size_t out_channels, const int8_t* values) {
  const uint32_t* values_as_words = reinterpret_cast<const uint32_t*>(values);
  size_t filter_words =
      FILTER_WIDTH * FILTER_HEIGHT / 4 * in_channels * out_channels;
  cfu_set_sw(REG_FILTER_NUM_WORDS, filter_words);
  const uint32_t* end = values_as_words + filter_words;
  while (values_as_words != end) {
    cfu_set_sw(REG_SET_FILTER, *values_as_words++);
  }
}

Vector16 GetFilter() {
  uint32_t word0 = cfu_get_sw(REG_FILTER_0);
  uint32_t word1 = cfu_get_sw(REG_FILTER_1);
  uint32_t word2 = cfu_get_sw(REG_FILTER_2);
  uint32_t word3 = cfu_get_sw(REG_FILTER_3);
  return Vector16{{word0, word1, word2, word3}};
}

void LoadInput(size_t width, size_t in_channels, const int8_t* values) {
  if (in_channels == 1) {
    LoadInput1(width, values);
  } else if ((in_channels & 0x3) == 0) {
    LoadInputN(width, in_channels, values);
  } else {
    printf("Failed to load\n");
  }
}

Vector16 GetInput() {
  uint32_t word0 = cfu_get_sw(REG_INPUT_0);
  uint32_t word1 = cfu_get_sw(REG_INPUT_1);
  uint32_t word2 = cfu_get_sw(REG_INPUT_2);
  uint32_t word3 = cfu_get_sw(REG_INPUT_3);
  return Vector16{{word0, word1, word2, word3}};
}

};  // namespace hps_accel<commit_msg>hps_accel/blocks.cc: Allow HW input<commit_after>/*
 * Copyright 2021 The CFU-Playground Authors
 *
 * 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 "blocks.h"

#include <cstdio>

#include "hps_cfu.h"

namespace hps_accel {

namespace {

constexpr size_t BYTES_PER_WORD = 4;

inline uint32_t pack32(int8_t a, int8_t b, int8_t c, int8_t d) {
  return static_cast<uint32_t>(static_cast<uint8_t>(a)) |
         (static_cast<uint32_t>(static_cast<uint8_t>(b)) << 8) |
         (static_cast<uint32_t>(static_cast<uint8_t>(c)) << 16) |
         (static_cast<uint32_t>(static_cast<uint8_t>(d)) << 24);
}

// Load input when in_channels = 1
void LoadInput1(size_t width, const int8_t* values) {
  size_t input_words = 4;
  cfu_set(REG_INPUT_NUM_WORDS, input_words);

  // For each of four consecutive rows, take data from four consecutive pixels
  for (size_t row_index = 0; row_index < 4; row_index++) {
    const int8_t* source = values + (row_index * width);
    cfu_set(REG_SET_INPUT, pack32(source[0], source[1], source[2], source[3]));
  }
}

// Load input when in_channels is divisible by 4
void LoadInputN(size_t width, size_t in_channels, const int8_t* values) {
  const size_t pixels_per_input_row = 4;
  const size_t words_per_input_row =
      pixels_per_input_row * in_channels / BYTES_PER_WORD;
  const size_t bytes_per_width = width * in_channels;
  size_t input_words =
      FILTER_WIDTH * FILTER_HEIGHT * in_channels / BYTES_PER_WORD;
  cfu_set(REG_INPUT_NUM_WORDS, input_words);

  // For each of four consecutive rows, take data from four consecutive pixels
  for (size_t row_index = 0; row_index < 4; row_index++) {
    const uint32_t* source = reinterpret_cast<const uint32_t*>(
        values + (row_index * bytes_per_width));
    for (size_t i = 0; i < words_per_input_row; i++) {
      cfu_set(REG_SET_INPUT, *source++);
    }
  }
}

};  // anonymous namespace

Vector16 Vector16::build(int8_t a, int8_t b, int8_t c, int8_t d, int8_t e,
                         int8_t f, int8_t g, int8_t h, int8_t i, int8_t j,
                         int8_t k, int8_t l, int8_t m, int8_t n, int8_t o,
                         int8_t p) {
  return Vector16{{pack32(a, b, c, d), pack32(e, f, g, h), pack32(i, j, k, l),
                   pack32(m, n, o, p)}};
}

Vector16 Vector16::zeroes() { return Vector16{{0, 0, 0, 0}}; }

// Performs a 16 x 16 vector multiplication
int32_t multiply_accumulate(Vector16 input, Vector16 filter,
                            int32_t input_offset) {
  cfu_set(REG_INPUT_OFFSET, input_offset);
  cfu_set(REG_MACC_INPUT_0, input.values[0]);
  cfu_set(REG_MACC_INPUT_1, input.values[1]);
  cfu_set(REG_MACC_INPUT_2, input.values[2]);
  cfu_set(REG_MACC_INPUT_3, input.values[3]);
  cfu_set(REG_MACC_FILTER_0, filter.values[0]);
  cfu_set(REG_MACC_FILTER_1, filter.values[1]);
  cfu_set(REG_MACC_FILTER_2, filter.values[2]);
  cfu_set(REG_MACC_FILTER_3, filter.values[3]);
  asm volatile("nop"); // One cycle for last set to complete fully
  asm volatile("nop"); // Two more cycles for MACC to complete
  asm volatile("nop");
  return cfu_get(REG_MACC_OUT);
}

void LoadFilter(size_t in_channels, size_t out_channels, const int8_t* values) {
  const uint32_t* values_as_words = reinterpret_cast<const uint32_t*>(values);
  size_t filter_words =
      FILTER_WIDTH * FILTER_HEIGHT / 4 * in_channels * out_channels;
  cfu_set_sw(REG_FILTER_NUM_WORDS, filter_words);
  const uint32_t* end = values_as_words + filter_words;
  while (values_as_words != end) {
    cfu_set_sw(REG_SET_FILTER, *values_as_words++);
  }
}

Vector16 GetFilter() {
  uint32_t word0 = cfu_get_sw(REG_FILTER_0);
  uint32_t word1 = cfu_get_sw(REG_FILTER_1);
  uint32_t word2 = cfu_get_sw(REG_FILTER_2);
  uint32_t word3 = cfu_get_sw(REG_FILTER_3);
  return Vector16{{word0, word1, word2, word3}};
}

void LoadInput(size_t width, size_t in_channels, const int8_t* values) {
  if (in_channels == 1) {
    LoadInput1(width, values);
  } else if ((in_channels & 0x3) == 0) {
    LoadInputN(width, in_channels, values);
  } else {
    printf("Failed to load\n");
  }
}

Vector16 GetInput() {
  uint32_t word0 = cfu_get(REG_INPUT_0);
  uint32_t word1 = cfu_get(REG_INPUT_1);
  uint32_t word2 = cfu_get(REG_INPUT_2);
  uint32_t word3 = cfu_get(REG_INPUT_3);
  return Vector16{{word0, word1, word2, word3}};
}

};  // namespace hps_accel<|endoftext|>


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

#define BOOST_TEST_MODULE Pivx Test Suite

#include "test/test_pivx.h"

#include "blockassembler.h"
#include "guiinterface.h"
#include "miner.h"
#include "net_processing.h"
#include "random.h"
#include "rpc/server.h"
#include "rpc/register.h"
#include "script/sigcache.h"
#include "sporkdb.h"
#include "txmempool.h"
#include "txdb.h"
#include "validation.h"

#include <boost/test/unit_test.hpp>

std::unique_ptr<CConnman> g_connman;

CClientUIInterface uiInterface;  // Declared but not defined in guiinterface.h

uint256 insecure_rand_seed = GetRandHash();
FastRandomContext insecure_rand_ctx(insecure_rand_seed);

extern bool fPrintToConsole;
extern void noui_connect();

BasicTestingSetup::BasicTestingSetup()
{
        RandomInit();
        ECC_Start();
        SetupEnvironment();
        InitSignatureCache();
        fCheckBlockIndex = true;
        SelectParams(CBaseChainParams::MAIN);
}
BasicTestingSetup::~BasicTestingSetup()
{
        ECC_Stop();
        g_connman.reset();
}

TestingSetup::TestingSetup()
{
        ClearDatadirCache();
        pathTemp = GetTempPath() / strprintf("test_pivx_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000)));
        fs::create_directories(pathTemp);
        gArgs.ForceSetArg("-datadir", pathTemp.string());

        // Note that because we don't bother running a scheduler thread here,
        // callbacks via CValidationInterface are unreliable, but that's OK,
        // our unit tests aren't testing multiple parts of the code at once.
        GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);

        // Ideally we'd move all the RPC tests to the functional testing framework
        // instead of unit tests, but for now we need these here.
        RegisterAllCoreRPCCommands(tableRPC);
        zerocoinDB = new CZerocoinDB(0, true);
        pSporkDB = new CSporkDB(0, true);
        pblocktree = new CBlockTreeDB(1 << 20, true);
        pcoinsdbview = new CCoinsViewDB(1 << 23, true);
        pcoinsTip = new CCoinsViewCache(pcoinsdbview);
        InitBlockIndex();
        {
            CValidationState state;
            bool ok = ActivateBestChain(state);
            BOOST_CHECK(ok);
        }
        nScriptCheckThreads = 3;
        for (int i=0; i < nScriptCheckThreads-1; i++)
            threadGroup.create_thread(&ThreadScriptCheck);
        g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests.
        connman = g_connman.get();
        RegisterNodeSignals(GetNodeSignals());
}

TestingSetup::~TestingSetup()
{
        UnregisterNodeSignals(GetNodeSignals());
        threadGroup.interrupt_all();
        threadGroup.join_all();
        GetMainSignals().FlushBackgroundCallbacks();
        GetMainSignals().UnregisterBackgroundSignalScheduler();
        UnloadBlockIndex();
        delete pcoinsTip;
        delete pcoinsdbview;
        delete pblocktree;
        delete zerocoinDB;
        delete pSporkDB;
        fs::remove_all(pathTemp);
}

TestChainSetup::TestChainSetup(int blockCount)
{
    SelectParams(CBaseChainParams::REGTEST);

    // if blockCount is over PoS start, delay it to 100 blocks after.
    if (blockCount > Params().GetConsensus().vUpgrades[Consensus::UPGRADE_POS].nActivationHeight) {
        UpdateNetworkUpgradeParameters(Consensus::UPGRADE_POS, blockCount + 100);
        UpdateNetworkUpgradeParameters(Consensus::UPGRADE_V3_4, blockCount + 101);
    }

    // Generate a blockCount-block chain:
    coinbaseKey.MakeNewKey(true);
    CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
    for (int i = 0; i < blockCount; i++)
    {
        std::vector<CMutableTransaction> noTxns;
        CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);
        coinbaseTxns.push_back(*b.vtx[0]);
    }
}

//
// Create a new block with just given transactions, coinbase paying to
// scriptPubKey, and try to add it to the current chain.
//
CBlock TestChainSetup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)
{
    CBlock block = CreateBlock(txns, scriptPubKey);
    CValidationState state;
    ProcessNewBlock(state, nullptr, std::make_shared<const CBlock>(block), nullptr);
    return block;
}

CBlock TestChainSetup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey)
{
    CScript scriptPubKey = CScript() <<  ToByteVector(scriptKey.GetPubKey()) << OP_CHECKSIG;
    return CreateAndProcessBlock(txns, scriptPubKey);
}

CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)
{
    std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(
            Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, nullptr, false);
    std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);

    // Replace mempool-selected txns with just coinbase plus passed-in txns:
    pblock->vtx.resize(1);
    for (const CMutableTransaction& tx : txns)
        pblock->vtx.push_back(MakeTransactionRef(tx));

    // IncrementExtraNonce creates a valid coinbase and merkleRoot
    unsigned int extraNonce = 0;
    {
        LOCK(cs_main);
        IncrementExtraNonce(pblock, chainActive.Tip(), extraNonce);
    }

    while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits)) ++pblock->nNonce;
    return *pblock;
}

CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey)
{
    CScript scriptPubKey = CScript() <<  ToByteVector(scriptKey.GetPubKey()) << OP_CHECKSIG;
    return CreateBlock(txns, scriptPubKey);
}

TestChainSetup::~TestChainSetup()
{
}

CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPool *pool) {
    const CTransactionRef txn = MakeTransactionRef(tx); // todo: move to the caller side..
    bool hasNoDependencies = pool ? pool->HasNoInputsOf(tx) : hadNoDependencies;
    // Hack to assume either its completely dependent on other mempool txs or not at all
    CAmount inChainValue = hasNoDependencies ? txn->GetValueOut() : 0;

    return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight,
                           hasNoDependencies, inChainValue, spendsCoinbaseOrCoinstake, sigOpCount);
}

[[noreturn]] void Shutdown(void* parg)
{
    std::exit(0);
}

[[noreturn]] void StartShutdown()
{
    std::exit(0);
}

bool ShutdownRequested()
{
  return false;
}
<commit_msg>unit test framework: missing scheduler service loop start added.<commit_after>// Copyright (c) 2011-2013 The Bitcoin Core developers
// Copyright (c) 2017-2020 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#define BOOST_TEST_MODULE Pivx Test Suite

#include "test/test_pivx.h"

#include "blockassembler.h"
#include "guiinterface.h"
#include "miner.h"
#include "net_processing.h"
#include "random.h"
#include "rpc/server.h"
#include "rpc/register.h"
#include "script/sigcache.h"
#include "sporkdb.h"
#include "txmempool.h"
#include "txdb.h"
#include "validation.h"

#include <boost/test/unit_test.hpp>

std::unique_ptr<CConnman> g_connman;

CClientUIInterface uiInterface;  // Declared but not defined in guiinterface.h

uint256 insecure_rand_seed = GetRandHash();
FastRandomContext insecure_rand_ctx(insecure_rand_seed);

extern bool fPrintToConsole;
extern void noui_connect();

BasicTestingSetup::BasicTestingSetup()
{
        RandomInit();
        ECC_Start();
        SetupEnvironment();
        InitSignatureCache();
        fCheckBlockIndex = true;
        SelectParams(CBaseChainParams::MAIN);
}
BasicTestingSetup::~BasicTestingSetup()
{
        ECC_Stop();
        g_connman.reset();
}

TestingSetup::TestingSetup()
{
        ClearDatadirCache();
        pathTemp = GetTempPath() / strprintf("test_pivx_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000)));
        fs::create_directories(pathTemp);
        gArgs.ForceSetArg("-datadir", pathTemp.string());

        // Start the lightweight task scheduler thread
        CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
        threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));

        // Note that because we don't bother running a scheduler thread here,
        // callbacks via CValidationInterface are unreliable, but that's OK,
        // our unit tests aren't testing multiple parts of the code at once.
        GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
        GetMainSignals().RegisterWithMempoolSignals(mempool);

        // Ideally we'd move all the RPC tests to the functional testing framework
        // instead of unit tests, but for now we need these here.
        RegisterAllCoreRPCCommands(tableRPC);
        zerocoinDB = new CZerocoinDB(0, true);
        pSporkDB = new CSporkDB(0, true);
        pblocktree = new CBlockTreeDB(1 << 20, true);
        pcoinsdbview = new CCoinsViewDB(1 << 23, true);
        pcoinsTip = new CCoinsViewCache(pcoinsdbview);
        InitBlockIndex();
        {
            CValidationState state;
            bool ok = ActivateBestChain(state);
            BOOST_CHECK(ok);
        }
        nScriptCheckThreads = 3;
        for (int i=0; i < nScriptCheckThreads-1; i++)
            threadGroup.create_thread(&ThreadScriptCheck);
        g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests.
        connman = g_connman.get();
        RegisterNodeSignals(GetNodeSignals());
}

TestingSetup::~TestingSetup()
{
        UnregisterNodeSignals(GetNodeSignals());
        threadGroup.interrupt_all();
        threadGroup.join_all();
        GetMainSignals().FlushBackgroundCallbacks();
        UnregisterAllValidationInterfaces();
        GetMainSignals().UnregisterBackgroundSignalScheduler();
        GetMainSignals().UnregisterWithMempoolSignals(mempool);
        UnloadBlockIndex();
        delete pcoinsTip;
        delete pcoinsdbview;
        delete pblocktree;
        delete zerocoinDB;
        delete pSporkDB;
        fs::remove_all(pathTemp);
}

TestChainSetup::TestChainSetup(int blockCount)
{
    SelectParams(CBaseChainParams::REGTEST);

    // if blockCount is over PoS start, delay it to 100 blocks after.
    if (blockCount > Params().GetConsensus().vUpgrades[Consensus::UPGRADE_POS].nActivationHeight) {
        UpdateNetworkUpgradeParameters(Consensus::UPGRADE_POS, blockCount + 100);
        UpdateNetworkUpgradeParameters(Consensus::UPGRADE_V3_4, blockCount + 101);
    }

    // Generate a blockCount-block chain:
    coinbaseKey.MakeNewKey(true);
    CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
    for (int i = 0; i < blockCount; i++)
    {
        std::vector<CMutableTransaction> noTxns;
        CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);
        coinbaseTxns.push_back(*b.vtx[0]);
    }
}

//
// Create a new block with just given transactions, coinbase paying to
// scriptPubKey, and try to add it to the current chain.
//
CBlock TestChainSetup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)
{
    CBlock block = CreateBlock(txns, scriptPubKey);
    CValidationState state;
    ProcessNewBlock(state, nullptr, std::make_shared<const CBlock>(block), nullptr);
    return block;
}

CBlock TestChainSetup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey)
{
    CScript scriptPubKey = CScript() <<  ToByteVector(scriptKey.GetPubKey()) << OP_CHECKSIG;
    return CreateAndProcessBlock(txns, scriptPubKey);
}

CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)
{
    std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(
            Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, nullptr, false);
    std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);

    // Replace mempool-selected txns with just coinbase plus passed-in txns:
    pblock->vtx.resize(1);
    for (const CMutableTransaction& tx : txns)
        pblock->vtx.push_back(MakeTransactionRef(tx));

    // IncrementExtraNonce creates a valid coinbase and merkleRoot
    unsigned int extraNonce = 0;
    {
        LOCK(cs_main);
        IncrementExtraNonce(pblock, chainActive.Tip(), extraNonce);
    }

    while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits)) ++pblock->nNonce;
    return *pblock;
}

CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey)
{
    CScript scriptPubKey = CScript() <<  ToByteVector(scriptKey.GetPubKey()) << OP_CHECKSIG;
    return CreateBlock(txns, scriptPubKey);
}

TestChainSetup::~TestChainSetup()
{
}

CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPool *pool) {
    const CTransactionRef txn = MakeTransactionRef(tx); // todo: move to the caller side..
    bool hasNoDependencies = pool ? pool->HasNoInputsOf(tx) : hadNoDependencies;
    // Hack to assume either its completely dependent on other mempool txs or not at all
    CAmount inChainValue = hasNoDependencies ? txn->GetValueOut() : 0;

    return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight,
                           hasNoDependencies, inChainValue, spendsCoinbaseOrCoinstake, sigOpCount);
}

[[noreturn]] void Shutdown(void* parg)
{
    std::exit(0);
}

[[noreturn]] void StartShutdown()
{
    std::exit(0);
}

bool ShutdownRequested()
{
  return false;
}
<|endoftext|>


<commit_before>#include "user_mark_container.hpp"

#include "drawer.hpp"
#include "framework.hpp"
#include "anim_phase_chain.hpp"

#include "../graphics/display_list.hpp"
#include "../graphics/screen.hpp"

#include "../geometry/transformations.hpp"

#include "../anim/task.hpp"
#include "../anim/controller.hpp"

#include "../base/macros.hpp"
#include "../base/stl_add.hpp"

#include "../std/scoped_ptr.hpp"
#include "../std/algorithm.hpp"

////////////////////////////////////////////////////////////////////////

namespace
{
  class PinAnimation : public AnimPhaseChain
  {
  public:
    PinAnimation(Framework & f)
      : AnimPhaseChain(f, m_scale)
    {
      InitDefaultPinAnim(this);
    }

    double GetScale() const
    {
      return m_scale;
    }

  private:
    double m_scale;
  };

  class FindMarkFunctor
  {
  public:
    FindMarkFunctor(UserMark ** mark, double & minD, m2::AnyRectD const & rect)
      : m_mark(mark)
      , m_minD(minD)
      , m_rect(rect)
    {
      m_globalCenter = rect.GlobalCenter();
    }

    void operator()(UserMark * mark)
    {
      m2::PointD const & org = mark->GetOrg();
      if (m_rect.IsPointInside(org))
      {
        double minDCandidate = m_globalCenter.SquareLength(org);
        if (minDCandidate < m_minD)
        {
          *m_mark = mark;
          m_minD = minDCandidate;
        }
      }
    }

    UserMark ** m_mark;
    double & m_minD;
    m2::AnyRectD const & m_rect;
    m2::PointD m_globalCenter;
  };
}

UserMarkContainer::UserMarkContainer(double layerDepth, Framework & framework)
  : m_controller(this)
  , m_isVisible(true)
  , m_layerDepth(layerDepth)
  , m_activeMark(NULL)
  , m_framework(framework)
{
}

UserMarkContainer::~UserMarkContainer()
{
  Clear();
}

UserMark const * UserMarkContainer::FindMarkInRect(m2::AnyRectD const & rect, double & d)
{
  UserMark * mark = NULL;
  d = numeric_limits<double>::max();
  FindMarkFunctor f(&mark, d, rect);
  for_each(m_userMarks.begin(), m_userMarks.end(), f);
  return mark;
}

void UserMarkContainer::Draw(PaintOverlayEvent const & e, UserMarkDLCache * cache) const
{
  if (m_isVisible == false)
    return;

  if (m_activeMark != NULL)
  {
    UserMarkDLCache::Key defaultKey(GetActiveTypeName(), graphics::EPosCenter, m_layerDepth);
    DefaultDrawUserMark(GetActiveMarkScale(), e, cache, defaultKey, m_activeMark);
  }

  UserMarkDLCache::Key defaultKey(GetTypeName(), graphics::EPosCenter, m_layerDepth);
  for_each(m_userMarks.begin(), m_userMarks.end(), bind(&UserMarkContainer::DrawUserMark, this,
                                                         1.0, e, cache, defaultKey, _1));
}

void UserMarkContainer::ActivateMark(UserMark const * mark)
{
  ASSERT(mark->GetContainer() == this, ());
  m_activeMark = mark;
  StartActivationAnim();
}

void UserMarkContainer::DiactivateMark()
{
  if (m_activeMark != NULL)
  {
    KillActivationAnim();
    m_activeMark = NULL;
  }
}

void UserMarkContainer::Clear()
{
  DeleteRange(m_userMarks, DeleteFunctor());
  m_activeMark = NULL;
}

namespace
{
  static scoped_ptr<PoiMarkPoint> s_selectionUserMark;
}

void UserMarkContainer::InitPoiSelectionMark(UserMarkContainer * container)
{
  ASSERT(s_selectionUserMark == NULL, ());
  s_selectionUserMark.reset(new PoiMarkPoint(container));
}

PoiMarkPoint * UserMarkContainer::UserMarkForPoi(m2::PointD const & ptOrg)
{
  ASSERT(s_selectionUserMark != NULL, ());
  s_selectionUserMark->SetPtOrg(ptOrg);
  return s_selectionUserMark.get();
}

UserMark * UserMarkContainer::CreateUserMark(m2::PointD const & ptOrg)
{
  m_userMarks.push_back(AllocateUserMark(ptOrg));
  return m_userMarks.back();
}

size_t UserMarkContainer::GetUserMarkCount() const
{
  return m_userMarks.size();
}

UserMark const * UserMarkContainer::GetUserMark(size_t index) const
{
  ASSERT_LESS(index, m_userMarks.size(), ());
  return m_userMarks[index];
}

UserMark * UserMarkContainer::GetUserMark(size_t index)
{
  ASSERT_LESS(index, m_userMarks.size(), ());
  return m_userMarks[index];
}

namespace
{

template <class T> void DeleteItem(vector<T> & v, size_t i)
{
  if (i < v.size())
  {
    delete v[i];
    v.erase(v.begin() + i);
  }
  else
  {
    LOG(LWARNING, ("Trying to delete non-existing item at index", i));
  }
}

}

void UserMarkContainer::DeleteUserMark(size_t index)
{
  ASSERT_LESS(index, m_userMarks.size(), ());
  if (m_activeMark == m_userMarks[index])
    m_activeMark = NULL;

  DeleteItem(m_userMarks, index);
}

void UserMarkContainer::DeleteUserMark(UserMark const * mark)
{
  vector<UserMark *>::iterator it = find(m_userMarks.begin(), m_userMarks.end(), mark);
  if (it != m_userMarks.end())
    DeleteUserMark(distance(m_userMarks.begin(), it));
}

void UserMarkContainer::DrawUserMarkImpl(double scale,
                                         m2::PointD const & pixelOfsset,
                                         PaintOverlayEvent const & event,
                                         graphics::DisplayList * dl,
                                         UserMark const * mark) const
{
  ScreenBase modelView = event.GetModelView();
  graphics::Screen * screen = event.GetDrawer()->screen();
  m2::PointD pxPoint = modelView.GtoP(mark->GetOrg());
  pxPoint += (pixelOfsset * m_framework.GetVisualScale());
  math::Matrix<double, 3, 3> m = math::Shift(math::Scale(math::Identity<double, 3>(),
                                                         scale, scale),
                                             pxPoint.x, pxPoint.y);
  dl->draw(screen, m);
}

void UserMarkContainer::DrawUserMark(double scale,
                                     PaintOverlayEvent const & event,
                                     UserMarkDLCache * cache,
                                     UserMarkDLCache::Key const & defaultKey,
                                     UserMark const * mark) const
{
  if (mark->IsCustomDrawable())
  {
    ICustomDrawable const * drawable = static_cast<ICustomDrawable const *>(mark);
    DrawUserMarkImpl(drawable->GetAnimScaleFactor(), drawable->GetPixelOffset(), event, drawable->GetDisplayList(cache), mark);
  }
  else
    DefaultDrawUserMark(scale, event, cache, defaultKey, mark);
}

void UserMarkContainer::DefaultDrawUserMark(double scale,
                                            PaintOverlayEvent const & event,
                                            UserMarkDLCache * cache,
                                            UserMarkDLCache::Key const & defaultKey,
                                            const UserMark * mark) const
{
  DrawUserMarkImpl(scale, m2::PointD(0.0, 0.0), event, cache->FindUserMark(defaultKey), mark);
}

void UserMarkContainer::StartActivationAnim()
{
  m_animTask.reset(new PinAnimation(m_framework));
  m_framework.GetAnimController()->AddTask(m_animTask);
}

void UserMarkContainer::KillActivationAnim()
{
  m_animTask.reset();
}

double UserMarkContainer::GetActiveMarkScale() const
{
  if (m_animTask != NULL)
  {
    PinAnimation * a = static_cast<PinAnimation *>(m_animTask.get());
    return a->GetScale();
  }

  return 1.0;
}

SearchUserMarkContainer::SearchUserMarkContainer(double layerDepth, Framework & framework)
  : UserMarkContainer(layerDepth, framework)
{
}

string SearchUserMarkContainer::GetTypeName() const
{
  return "search-result";
}

string SearchUserMarkContainer::GetActiveTypeName() const
{
  return "search-result-active";
}

UserMark * SearchUserMarkContainer::AllocateUserMark(const m2::PointD & ptOrg)
{
  return new SearchMarkPoint(ptOrg, this);
}

ApiUserMarkContainer::ApiUserMarkContainer(double layerDepth, Framework & framework)
  : UserMarkContainer(layerDepth, framework)
{
}

string ApiUserMarkContainer::GetTypeName() const
{
  return "api-result";
}

string ApiUserMarkContainer::GetActiveTypeName() const
{
  return "search-result-active";
}

UserMark * ApiUserMarkContainer::AllocateUserMark(const m2::PointD & ptOrg)
{
  return new ApiMarkPoint(ptOrg, this);
}
<commit_msg>[core] pin anim scale factor initialization<commit_after>#include "user_mark_container.hpp"

#include "drawer.hpp"
#include "framework.hpp"
#include "anim_phase_chain.hpp"

#include "../graphics/display_list.hpp"
#include "../graphics/screen.hpp"

#include "../geometry/transformations.hpp"

#include "../anim/task.hpp"
#include "../anim/controller.hpp"

#include "../base/macros.hpp"
#include "../base/stl_add.hpp"

#include "../std/scoped_ptr.hpp"
#include "../std/algorithm.hpp"

////////////////////////////////////////////////////////////////////////

namespace
{
  class PinAnimation : public AnimPhaseChain
  {
  public:
    PinAnimation(Framework & f)
      : AnimPhaseChain(f, m_scale)
      , m_scale(0.0)
    {
      InitDefaultPinAnim(this);
    }

    double GetScale() const
    {
      return m_scale;
    }

  private:
    double m_scale;
  };

  class FindMarkFunctor
  {
  public:
    FindMarkFunctor(UserMark ** mark, double & minD, m2::AnyRectD const & rect)
      : m_mark(mark)
      , m_minD(minD)
      , m_rect(rect)
    {
      m_globalCenter = rect.GlobalCenter();
    }

    void operator()(UserMark * mark)
    {
      m2::PointD const & org = mark->GetOrg();
      if (m_rect.IsPointInside(org))
      {
        double minDCandidate = m_globalCenter.SquareLength(org);
        if (minDCandidate < m_minD)
        {
          *m_mark = mark;
          m_minD = minDCandidate;
        }
      }
    }

    UserMark ** m_mark;
    double & m_minD;
    m2::AnyRectD const & m_rect;
    m2::PointD m_globalCenter;
  };
}

UserMarkContainer::UserMarkContainer(double layerDepth, Framework & framework)
  : m_controller(this)
  , m_isVisible(true)
  , m_layerDepth(layerDepth)
  , m_activeMark(NULL)
  , m_framework(framework)
{
}

UserMarkContainer::~UserMarkContainer()
{
  Clear();
}

UserMark const * UserMarkContainer::FindMarkInRect(m2::AnyRectD const & rect, double & d)
{
  UserMark * mark = NULL;
  d = numeric_limits<double>::max();
  FindMarkFunctor f(&mark, d, rect);
  for_each(m_userMarks.begin(), m_userMarks.end(), f);
  return mark;
}

void UserMarkContainer::Draw(PaintOverlayEvent const & e, UserMarkDLCache * cache) const
{
  if (m_isVisible == false)
    return;

  if (m_activeMark != NULL)
  {
    UserMarkDLCache::Key defaultKey(GetActiveTypeName(), graphics::EPosCenter, m_layerDepth);
    DefaultDrawUserMark(GetActiveMarkScale(), e, cache, defaultKey, m_activeMark);
  }

  UserMarkDLCache::Key defaultKey(GetTypeName(), graphics::EPosCenter, m_layerDepth);
  for_each(m_userMarks.begin(), m_userMarks.end(), bind(&UserMarkContainer::DrawUserMark, this,
                                                         1.0, e, cache, defaultKey, _1));
}

void UserMarkContainer::ActivateMark(UserMark const * mark)
{
  ASSERT(mark->GetContainer() == this, ());
  m_activeMark = mark;
  StartActivationAnim();
}

void UserMarkContainer::DiactivateMark()
{
  if (m_activeMark != NULL)
  {
    KillActivationAnim();
    m_activeMark = NULL;
  }
}

void UserMarkContainer::Clear()
{
  DeleteRange(m_userMarks, DeleteFunctor());
  m_activeMark = NULL;
}

namespace
{
  static scoped_ptr<PoiMarkPoint> s_selectionUserMark;
}

void UserMarkContainer::InitPoiSelectionMark(UserMarkContainer * container)
{
  ASSERT(s_selectionUserMark == NULL, ());
  s_selectionUserMark.reset(new PoiMarkPoint(container));
}

PoiMarkPoint * UserMarkContainer::UserMarkForPoi(m2::PointD const & ptOrg)
{
  ASSERT(s_selectionUserMark != NULL, ());
  s_selectionUserMark->SetPtOrg(ptOrg);
  return s_selectionUserMark.get();
}

UserMark * UserMarkContainer::CreateUserMark(m2::PointD const & ptOrg)
{
  m_userMarks.push_back(AllocateUserMark(ptOrg));
  return m_userMarks.back();
}

size_t UserMarkContainer::GetUserMarkCount() const
{
  return m_userMarks.size();
}

UserMark const * UserMarkContainer::GetUserMark(size_t index) const
{
  ASSERT_LESS(index, m_userMarks.size(), ());
  return m_userMarks[index];
}

UserMark * UserMarkContainer::GetUserMark(size_t index)
{
  ASSERT_LESS(index, m_userMarks.size(), ());
  return m_userMarks[index];
}

namespace
{

template <class T> void DeleteItem(vector<T> & v, size_t i)
{
  if (i < v.size())
  {
    delete v[i];
    v.erase(v.begin() + i);
  }
  else
  {
    LOG(LWARNING, ("Trying to delete non-existing item at index", i));
  }
}

}

void UserMarkContainer::DeleteUserMark(size_t index)
{
  ASSERT_LESS(index, m_userMarks.size(), ());
  if (m_activeMark == m_userMarks[index])
    m_activeMark = NULL;

  DeleteItem(m_userMarks, index);
}

void UserMarkContainer::DeleteUserMark(UserMark const * mark)
{
  vector<UserMark *>::iterator it = find(m_userMarks.begin(), m_userMarks.end(), mark);
  if (it != m_userMarks.end())
    DeleteUserMark(distance(m_userMarks.begin(), it));
}

void UserMarkContainer::DrawUserMarkImpl(double scale,
                                         m2::PointD const & pixelOfsset,
                                         PaintOverlayEvent const & event,
                                         graphics::DisplayList * dl,
                                         UserMark const * mark) const
{
  ScreenBase modelView = event.GetModelView();
  graphics::Screen * screen = event.GetDrawer()->screen();
  m2::PointD pxPoint = modelView.GtoP(mark->GetOrg());
  pxPoint += (pixelOfsset * m_framework.GetVisualScale());
  math::Matrix<double, 3, 3> m = math::Shift(math::Scale(math::Identity<double, 3>(),
                                                         scale, scale),
                                             pxPoint.x, pxPoint.y);
  dl->draw(screen, m);
}

void UserMarkContainer::DrawUserMark(double scale,
                                     PaintOverlayEvent const & event,
                                     UserMarkDLCache * cache,
                                     UserMarkDLCache::Key const & defaultKey,
                                     UserMark const * mark) const
{
  if (mark->IsCustomDrawable())
  {
    ICustomDrawable const * drawable = static_cast<ICustomDrawable const *>(mark);
    DrawUserMarkImpl(drawable->GetAnimScaleFactor(), drawable->GetPixelOffset(), event, drawable->GetDisplayList(cache), mark);
  }
  else
    DefaultDrawUserMark(scale, event, cache, defaultKey, mark);
}

void UserMarkContainer::DefaultDrawUserMark(double scale,
                                            PaintOverlayEvent const & event,
                                            UserMarkDLCache * cache,
                                            UserMarkDLCache::Key const & defaultKey,
                                            const UserMark * mark) const
{
  DrawUserMarkImpl(scale, m2::PointD(0.0, 0.0), event, cache->FindUserMark(defaultKey), mark);
}

void UserMarkContainer::StartActivationAnim()
{
  m_animTask.reset(new PinAnimation(m_framework));
  m_framework.GetAnimController()->AddTask(m_animTask);
}

void UserMarkContainer::KillActivationAnim()
{
  m_animTask.reset();
}

double UserMarkContainer::GetActiveMarkScale() const
{
  if (m_animTask != NULL)
  {
    PinAnimation * a = static_cast<PinAnimation *>(m_animTask.get());
    return a->GetScale();
  }

  return 1.0;
}

SearchUserMarkContainer::SearchUserMarkContainer(double layerDepth, Framework & framework)
  : UserMarkContainer(layerDepth, framework)
{
}

string SearchUserMarkContainer::GetTypeName() const
{
  return "search-result";
}

string SearchUserMarkContainer::GetActiveTypeName() const
{
  return "search-result-active";
}

UserMark * SearchUserMarkContainer::AllocateUserMark(const m2::PointD & ptOrg)
{
  return new SearchMarkPoint(ptOrg, this);
}

ApiUserMarkContainer::ApiUserMarkContainer(double layerDepth, Framework & framework)
  : UserMarkContainer(layerDepth, framework)
{
}

string ApiUserMarkContainer::GetTypeName() const
{
  return "api-result";
}

string ApiUserMarkContainer::GetActiveTypeName() const
{
  return "search-result-active";
}

UserMark * ApiUserMarkContainer::AllocateUserMark(const m2::PointD & ptOrg)
{
  return new ApiMarkPoint(ptOrg, this);
}
<|endoftext|>


<commit_before>#include <string.h>
#include <cmath>

#include "networkRecorder.h"
#include "multiplayer.h"
#include "multiplayer_client.h"
#include "multiplayer_internal.h"
#include "input.h"
#include "logging.h"

#include <opus.h>

NetworkAudioRecorder::NetworkAudioRecorder()
{
    LOG(INFO) << "Using \"" << getDefaultDevice() << "\" for voice communication";
    setProcessingInterval(sf::milliseconds(10));
}

NetworkAudioRecorder::~NetworkAudioRecorder()
{
    stop();

    if (encoder)
    {
        opus_encoder_destroy(encoder);
    }
}

void NetworkAudioRecorder::addKeyActivation(sf::Keyboard::Key key, int target_identifier)
{
    keys.push_back({key, target_identifier});
}

/// Called from a seperate thread, be sure to watch for thread safety!
bool NetworkAudioRecorder::onProcessSamples(const sf::Int16* samples, std::size_t sample_count)
{
    //Add samples to the sample buffer. The update function (which is run from the main thread) will handle sending of the actual audio packet.
    sample_buffer_mutex.lock();
    unsigned int old_size = sample_buffer.size();
    sample_buffer.resize(old_size + sample_count);
    memcpy(&sample_buffer[old_size], samples, sizeof(sf::Int16) * sample_count);
    sample_buffer_mutex.unlock();
    return true;
}

void NetworkAudioRecorder::update(float delta)
{
    for(size_t idx=0; idx<keys.size(); idx++)
    {
        if (InputHandler::keyboardIsPressed(keys[idx].key) && active_key_index == -1)
        {
            if (active_key_index == -1)
            {
                samples_till_stop = -1;
                active_key_index = idx;
                start(48000);
                startSending();
            } else if (idx == size_t(active_key_index))
            {
                samples_till_stop = -1;
            }
        }
    }
    while(sendAudioPacket())
    {
    }
    if (active_key_index != -1)
    {
        if (InputHandler::keyboardIsReleased(keys[active_key_index].key))
        {
            samples_till_stop = 48000 * 0.5;
        }
    }
    if (samples_till_stop == 0)
    {
        stop();
        finishSending();
        active_key_index = -1;
        samples_till_stop = -1;
    }
}

void NetworkAudioRecorder::startSending()
{
    int error = 0;
    encoder = opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, &error);
    if (!encoder)
    {
        LOG(ERROR) << "Failed to create opus encoder:" << error;
    }

    if (game_client)
    {
        sf::Packet audio_packet;
        audio_packet << CMD_AUDIO_COMM_START << game_client->getClientId() << int32_t(keys[active_key_index].target_identifier);
        game_client->sendPacket(audio_packet);
    }
    else if (game_server)
    {
        game_server->startAudio(0, keys[active_key_index].target_identifier);
    }
}

bool NetworkAudioRecorder::sendAudioPacket()
{
    bool result = false;
    sample_buffer_mutex.lock();
    if (sample_buffer.size() >= frame_size)
    {
        unsigned char packet_buffer[4096];
        int packet_size = 0;
        if (encoder)
            packet_size = opus_encode(encoder, sample_buffer.data(), frame_size, packet_buffer, sizeof(packet_buffer));
        if (game_client)
        {
            sf::Packet audio_packet;
            audio_packet << CMD_AUDIO_COMM_DATA << game_client->getClientId();
            audio_packet.append(packet_buffer, packet_size);

            game_client->sendPacket(audio_packet);
        }
        else if (game_server)
        {
            game_server->gotAudioPacket(0, packet_buffer, packet_size);
        }
        sample_buffer.erase(sample_buffer.begin(), sample_buffer.begin() + frame_size);
        result = true;

        if (samples_till_stop > -1)
        {
            samples_till_stop = std::max(0, samples_till_stop - frame_size);
        }
    }
    sample_buffer_mutex.unlock();
    return result;
}

void NetworkAudioRecorder::finishSending()
{
    while(sendAudioPacket())
    {
    }
    sample_buffer_mutex.lock();
    while(sample_buffer.size() < frame_size)
        sample_buffer.push_back(0);
    sample_buffer_mutex.unlock();
    sendAudioPacket();
    opus_encoder_destroy(encoder);
    encoder = nullptr;

    if (game_client)
    {
        sf::Packet audio_packet;
        audio_packet << CMD_AUDIO_COMM_STOP << game_client->getClientId();
        game_client->sendPacket(audio_packet);
    }
    else if (game_server)
    {
        game_server->stopAudio(0);
    }
}
<commit_msg>Update networkRecorder.cpp (#97)<commit_after>#include <string.h>
#include <cmath>

#include "networkRecorder.h"
#include "multiplayer.h"
#include "multiplayer_client.h"
#include "multiplayer_internal.h"
#include "input.h"
#include "logging.h"

#include <opus.h>

NetworkAudioRecorder::NetworkAudioRecorder()
{
    LOG(INFO) << "Using \"" << getDefaultDevice() << "\" for voice communication";
    setProcessingInterval(sf::milliseconds(10));
}

NetworkAudioRecorder::~NetworkAudioRecorder()
{
    stop();

    if (encoder)
    {
        opus_encoder_destroy(encoder);
    }
}

void NetworkAudioRecorder::addKeyActivation(sf::Keyboard::Key key, int target_identifier)
{
    keys.push_back({key, target_identifier});
}

/// Called from a seperate thread, be sure to watch for thread safety!
bool NetworkAudioRecorder::onProcessSamples(const sf::Int16* samples, std::size_t sample_count)
{
    //Add samples to the sample buffer. The update function (which is run from the main thread) will handle sending of the actual audio packet.
    sample_buffer_mutex.lock();
    auto old_size = sample_buffer.size();
    sample_buffer.resize(old_size + sample_count);
    memcpy(&sample_buffer[old_size], samples, sizeof(sf::Int16) * sample_count);
    sample_buffer_mutex.unlock();
    return true;
}

void NetworkAudioRecorder::update(float /*delta*/)
{
    for(size_t idx=0; idx<keys.size(); idx++)
    {
        if (InputHandler::keyboardIsPressed(keys[idx].key) && active_key_index == -1)
        {
            if (active_key_index == -1)
            {
                samples_till_stop = -1;
                active_key_index = static_cast<int>(idx);
                start(48000);
                startSending();
            } else if (idx == size_t(active_key_index))
            {
                samples_till_stop = -1;
            }
        }
    }
    while(sendAudioPacket())
    {
    }
    if (active_key_index != -1)
    {
        if (InputHandler::keyboardIsReleased(keys[active_key_index].key))
        {
            samples_till_stop = 48000 / 2;
        }
    }
    if (samples_till_stop == 0)
    {
        stop();
        finishSending();
        active_key_index = -1;
        samples_till_stop = -1;
    }
}

void NetworkAudioRecorder::startSending()
{
    int error = 0;
    encoder = opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, &error);
    if (!encoder)
    {
        LOG(ERROR) << "Failed to create opus encoder:" << error;
    }

    if (game_client)
    {
        sf::Packet audio_packet;
        audio_packet << CMD_AUDIO_COMM_START << game_client->getClientId() << int32_t(keys[active_key_index].target_identifier);
        game_client->sendPacket(audio_packet);
    }
    else if (game_server)
    {
        game_server->startAudio(0, keys[active_key_index].target_identifier);
    }
}

bool NetworkAudioRecorder::sendAudioPacket()
{
    bool result = false;
    sample_buffer_mutex.lock();
    if (sample_buffer.size() >= frame_size)
    {
        unsigned char packet_buffer[4096];
        int packet_size = 0;
        if (encoder)
            packet_size = opus_encode(encoder, sample_buffer.data(), frame_size, packet_buffer, sizeof(packet_buffer));
        if (game_client)
        {
            sf::Packet audio_packet;
            audio_packet << CMD_AUDIO_COMM_DATA << game_client->getClientId();
            audio_packet.append(packet_buffer, packet_size);

            game_client->sendPacket(audio_packet);
        }
        else if (game_server)
        {
            game_server->gotAudioPacket(0, packet_buffer, packet_size);
        }
        sample_buffer.erase(sample_buffer.begin(), sample_buffer.begin() + frame_size);
        result = true;

        if (samples_till_stop > -1)
        {
            samples_till_stop = std::max(0, samples_till_stop - frame_size);
        }
    }
    sample_buffer_mutex.unlock();
    return result;
}

void NetworkAudioRecorder::finishSending()
{
    while(sendAudioPacket())
    {
    }
    sample_buffer_mutex.lock();
    while(sample_buffer.size() < frame_size)
        sample_buffer.push_back(0);
    sample_buffer_mutex.unlock();
    sendAudioPacket();
    opus_encoder_destroy(encoder);
    encoder = nullptr;

    if (game_client)
    {
        sf::Packet audio_packet;
        audio_packet << CMD_AUDIO_COMM_STOP << game_client->getClientId();
        game_client->sendPacket(audio_packet);
    }
    else if (game_server)
    {
        game_server->stopAudio(0);
    }
}
<|endoftext|>


<commit_before>#include "udp_connection.h"
#include "global_include.h"

#ifndef WINDOWS
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#endif

#include <cassert>

namespace dronelink {

UdpConnection::UdpConnection(DroneLinkImpl *parent,
                             int local_port_number) :
    Connection(parent),
    _local_port_number(local_port_number),
    _should_exit(false)
{
    if (_local_port_number == 0) {
        _local_port_number = DEFAULT_UDP_LOCAL_PORT;
    }
}

UdpConnection::~UdpConnection()
{
    // If no one explicitly called stop before, we should at least do it.
    stop();
}

bool UdpConnection::is_ok() const
{
    return true;
}

DroneLink::ConnectionResult UdpConnection::start()
{
    if (!start_mavlink_receiver()) {
        return DroneLink::ConnectionResult::CONNECTIONS_EXHAUSTED;
    }

    DroneLink::ConnectionResult ret = setup_port();
    if (ret != DroneLink::ConnectionResult::SUCCESS) {
        return ret;
    }

    start_recv_thread();

    return DroneLink::ConnectionResult::SUCCESS;
}

DroneLink::ConnectionResult UdpConnection::setup_port()
{
#ifndef WINDOWS
    _socket_fd = socket(AF_INET, SOCK_DGRAM, 0);

    if (_socket_fd < 0) {
        Debug() << "socket error" << strerror(errno);
        return DroneLink::ConnectionResult::SOCKET_ERROR;
    }

    struct sockaddr_in addr;
    memset((char *)&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(_local_port_number);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(_socket_fd, (sockaddr *)&addr, sizeof(addr)) != 0) {
        Debug() << "bind error: " << strerror(errno);
        return DroneLink::ConnectionResult::BIND_ERROR;
    }

    return DroneLink::ConnectionResult::SUCCESS;
#else
    return DroneLink::ConnectionResult::NOT_IMPLEMENTED;
#endif
}

void UdpConnection::start_recv_thread()
{
    _recv_thread = new std::thread(receive, this);
}

DroneLink::ConnectionResult UdpConnection::stop()
{
    _should_exit = true;

#ifndef WINDOWS
    // This should interrupt a recv/recvfrom call.
    shutdown(_socket_fd, SHUT_RDWR);

    // But on Mac, closing is also needed to stop blocking recv/recvfrom.
    close(_socket_fd);
#endif

    if (_recv_thread) {
        _recv_thread->join();
        delete _recv_thread;
        _recv_thread = nullptr;
    }

    // We need to stop this after stopping the receive thread, otherwise
    // it can happen that we interfere with the parsing of a message.
    stop_mavlink_receiver();

    return DroneLink::ConnectionResult::SUCCESS;
}

bool UdpConnection::send_message(const mavlink_message_t &message)
{
    if (_remote_ip.empty()) {
        Debug() << "Remote IP unknown";
        return false;
    }

    if (_remote_port_number == 0) {
        Debug() << "Remote port unknown";
        return false;
    }

#ifndef WINDOWS
    struct sockaddr_in dest_addr;
    memset((char *)&dest_addr, 0, sizeof(dest_addr));
    dest_addr.sin_family = AF_INET;
    inet_pton(AF_INET, _remote_ip.c_str(), &dest_addr.sin_addr.s_addr);

    dest_addr.sin_port = htons(_remote_port_number);

    uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
    uint16_t buffer_len = mavlink_msg_to_send_buffer(buffer, &message);

    // TODO: remove this assert again
    assert(buffer_len <= MAVLINK_MAX_PACKET_LEN);

    int send_len = sendto(_socket_fd, buffer, buffer_len, 0,
                          (const sockaddr *)&dest_addr, sizeof(dest_addr));

    if (send_len != buffer_len) {
        Debug() << "sendto failure: " << strerror(errno);
        return false;
    }

    return true;
#else
    return false;
#endif
}

void UdpConnection::receive(UdpConnection *parent)
{
    // Enough for MTU 1500 bytes.
    char buffer[2048];

    while (!parent->_should_exit) {

#ifndef WINDOWS
        struct sockaddr_in src_addr = {};
        socklen_t src_addr_len = sizeof(src_addr);
        int recv_len = recvfrom(parent->_socket_fd, buffer, sizeof(buffer), 0,
                                (struct sockaddr *)&src_addr, &src_addr_len);

        if (recv_len == 0) {
            // This can happen when shutdown is called on the socket,
            // therefore we check _should_exit again.
            continue;
        }

        if (recv_len < 0) {
            // This happens on desctruction when close(_socket_fd) is called,
            // therefore be quiet.
            //Debug() << "recvfrom error: " << strerror(errno);
            continue;
        }

        int new_remote_port_number = ntohs(src_addr.sin_port);
        std::string new_remote_ip(inet_ntoa(src_addr.sin_addr));

        // TODO make calls to remote threadsafe.

        if (parent->_remote_ip.empty()) {

            if (parent->_remote_port_number == 0 ||
                parent->_remote_port_number == new_remote_port_number) {
                // Set IP if we don't know it yet.
                parent->_remote_ip = new_remote_ip;
                parent->_remote_port_number = new_remote_port_number;

                Debug() << "Partner IP: " << parent->_remote_ip
                        << ":" << parent->_remote_port_number;

            } else {

                Debug() << "Ignoring message from remote port " << new_remote_port_number
                        << " instead of " << parent->_remote_port_number;
                continue;
            }

        } else if (parent->_remote_ip.compare(new_remote_ip) != 0) {
            Debug() << "Ignoring message from IP: " << new_remote_ip;
            continue;

        } else {
            if (parent->_remote_port_number != new_remote_port_number) {
                Debug() << "Ignoring message from remote port " << new_remote_port_number
                        << " instead of " << parent->_remote_port_number;
                continue;
            }
        }

        parent->_mavlink_receiver->set_new_datagram(buffer, recv_len);

        // Parse all mavlink messages in one datagram. Once exhausted, we'll exit while.
        while (parent->_mavlink_receiver->parse_message()) {
            parent->receive_message(parent->_mavlink_receiver->get_last_message());
        }
#else
	sleep(1);
#endif
    }
}

} // namespace dronelink
<commit_msg>udp_connection: add Windows specific code<commit_after>#include "udp_connection.h"
#include "global_include.h"

#ifndef WINDOWS
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#else
#include <winsock2.h>
#include <Ws2tcpip.h> // For InetPton
#undef SOCKET_ERROR // conflicts with ConnectionResult::SOCKET_ERROR
#endif

#include <cassert>

#ifndef WINDOWS
#define GET_ERROR(_x) strerror(_x)
#else
#define GET_ERROR(_x) WSAGetLastError()
#endif

namespace dronelink {

UdpConnection::UdpConnection(DroneLinkImpl *parent,
                             int local_port_number) :
    Connection(parent),
    _local_port_number(local_port_number),
    _should_exit(false)
{
    if (_local_port_number == 0) {
        _local_port_number = DEFAULT_UDP_LOCAL_PORT;
    }
}

UdpConnection::~UdpConnection()
{
    // If no one explicitly called stop before, we should at least do it.
    stop();
}

bool UdpConnection::is_ok() const
{
    return true;
}

DroneLink::ConnectionResult UdpConnection::start()
{
    if (!start_mavlink_receiver()) {
        return DroneLink::ConnectionResult::CONNECTIONS_EXHAUSTED;
    }

    DroneLink::ConnectionResult ret = setup_port();
    if (ret != DroneLink::ConnectionResult::SUCCESS) {
        return ret;
    }

    start_recv_thread();

    return DroneLink::ConnectionResult::SUCCESS;
}

DroneLink::ConnectionResult UdpConnection::setup_port()
{

#ifdef WINDOWS
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
    {
        Debug() << "Error: Winsock failed, error: %d", WSAGetLastError();
	return DroneLink::ConnectionResult::SOCKET_ERROR;
    }
#endif

    _socket_fd = socket(AF_INET, SOCK_DGRAM, 0);

    if (_socket_fd < 0) {
        Debug() << "socket error" << GET_ERROR(errno);
        return DroneLink::ConnectionResult::SOCKET_ERROR;
    }

    struct sockaddr_in addr;
    memset((char *)&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(_local_port_number);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(_socket_fd, (sockaddr *)&addr, sizeof(addr)) != 0) {
        Debug() << "bind error: " << GET_ERROR(errno);
        return DroneLink::ConnectionResult::BIND_ERROR;
    }

    return DroneLink::ConnectionResult::SUCCESS;
}

void UdpConnection::start_recv_thread()
{
    _recv_thread = new std::thread(receive, this);
}

DroneLink::ConnectionResult UdpConnection::stop()
{
    _should_exit = true;

#ifndef WINDOWS
    // This should interrupt a recv/recvfrom call.
    shutdown(_socket_fd, SHUT_RDWR);

    // But on Mac, closing is also needed to stop blocking recv/recvfrom.
    close(_socket_fd);
#else
    shutdown(_socket_fd, SD_BOTH);

    closesocket(_socket_fd);

    WSACleanup();
#endif

    if (_recv_thread) {
        _recv_thread->join();
        delete _recv_thread;
        _recv_thread = nullptr;
    }

    // We need to stop this after stopping the receive thread, otherwise
    // it can happen that we interfere with the parsing of a message.
    stop_mavlink_receiver();

    return DroneLink::ConnectionResult::SUCCESS;
}

bool UdpConnection::send_message(const mavlink_message_t &message)
{
    if (_remote_ip.empty()) {
        Debug() << "Remote IP unknown";
        return false;
    }

    if (_remote_port_number == 0) {
        Debug() << "Remote port unknown";
        return false;
    }

    struct sockaddr_in dest_addr;
    memset((char *)&dest_addr, 0, sizeof(dest_addr));
    dest_addr.sin_family = AF_INET;

    inet_pton(AF_INET, _remote_ip.c_str(), &dest_addr.sin_addr.s_addr);

    dest_addr.sin_port = htons(_remote_port_number);

    uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
    uint16_t buffer_len = mavlink_msg_to_send_buffer(buffer, &message);

    // TODO: remove this assert again
    assert(buffer_len <= MAVLINK_MAX_PACKET_LEN);

    int send_len = sendto(_socket_fd, (const char *)buffer, buffer_len, 0,
                          (const sockaddr *)&dest_addr, sizeof(dest_addr));

    if (send_len != buffer_len) {
        Debug() << "sendto failure: " << GET_ERROR(errno);
        return false;
    }

    return true;
}

void UdpConnection::receive(UdpConnection *parent)
{
    // Enough for MTU 1500 bytes.
    char buffer[2048];

    while (!parent->_should_exit) {

        struct sockaddr_in src_addr = {};
        socklen_t src_addr_len = sizeof(src_addr);
        int recv_len = recvfrom(parent->_socket_fd, buffer, sizeof(buffer), 0,
                                (struct sockaddr *)&src_addr, &src_addr_len);

        if (recv_len == 0) {
            // This can happen when shutdown is called on the socket,
            // therefore we check _should_exit again.
            continue;
        }

        if (recv_len < 0) {
            // This happens on desctruction when close(_socket_fd) is called,
            // therefore be quiet.
            //Debug() << "recvfrom error: " << GET_ERROR(errno);
            continue;
        }

        int new_remote_port_number = ntohs(src_addr.sin_port);
        std::string new_remote_ip(inet_ntoa(src_addr.sin_addr));

        // TODO make calls to remote threadsafe.

        if (parent->_remote_ip.empty()) {

            if (parent->_remote_port_number == 0 ||
                parent->_remote_port_number == new_remote_port_number) {
                // Set IP if we don't know it yet.
                parent->_remote_ip = new_remote_ip;
                parent->_remote_port_number = new_remote_port_number;

                Debug() << "Partner IP: " << parent->_remote_ip
                        << ":" << parent->_remote_port_number;

            } else {

                Debug() << "Ignoring message from remote port " << new_remote_port_number
                        << " instead of " << parent->_remote_port_number;
                continue;
            }

        } else if (parent->_remote_ip.compare(new_remote_ip) != 0) {
            Debug() << "Ignoring message from IP: " << new_remote_ip;
            continue;

        } else {
            if (parent->_remote_port_number != new_remote_port_number) {
                Debug() << "Ignoring message from remote port " << new_remote_port_number
                        << " instead of " << parent->_remote_port_number;
                continue;
            }
        }

        parent->_mavlink_receiver->set_new_datagram(buffer, recv_len);

        // Parse all mavlink messages in one datagram. Once exhausted, we'll exit while.
        while (parent->_mavlink_receiver->parse_message()) {
            parent->receive_message(parent->_mavlink_receiver->get_last_message());
        }
    }
}

} // namespace dronelink
<|endoftext|>


<commit_before>#include "../stdafx.h"

#include "wcsp.h"
#include "../pki/wcert.h"
#include "../helper.h"

void WCsp::Init(v8::Handle<v8::Object> exports) {
	METHOD_BEGIN();

	v8::Local<v8::String> className = Nan::New("Csp").ToLocalChecked();

	// Basic instance setup
	v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);

	tpl->SetClassName(className);
	tpl->InstanceTemplate()->SetInternalFieldCount(1); // req'd by ObjectWrap

	Nan::SetPrototypeMethod(tpl, "isGost2001CSPAvailable", IsGost2001CSPAvailable);
	Nan::SetPrototypeMethod(tpl, "isGost2012_256CSPAvailable", IsGost2012_256CSPAvailable);
	Nan::SetPrototypeMethod(tpl, "isGost2012_512CSPAvailable", IsGost2012_512CSPAvailable);

	Nan::SetPrototypeMethod(tpl, "checkCPCSPLicense", CheckCPCSPLicense);
	Nan::SetPrototypeMethod(tpl, "getCPCSPLicense", GetCPCSPLicense);
	Nan::SetPrototypeMethod(tpl, "getCPCSPVersion", GetCPCSPVersion);
	Nan::SetPrototypeMethod(tpl, "getCPCSPVersionPKZI", GetCPCSPVersionPKZI);
	Nan::SetPrototypeMethod(tpl, "getCPCSPVersionSKZI", GetCPCSPVersionSKZI);
	Nan::SetPrototypeMethod(tpl, "getCPCSPSecurityLvl", GetCPCSPSecurityLvl);

	Nan::SetPrototypeMethod(tpl, "enumProviders", EnumProviders);
	Nan::SetPrototypeMethod(tpl, "enumContainers", EnumContainers);
	Nan::SetPrototypeMethod(tpl, "getCertifiacteFromContainer", GetCertifiacteFromContainer);
	Nan::SetPrototypeMethod(tpl, "installCertifiacteFromContainer", InstallCertifiacteFromContainer);
	Nan::SetPrototypeMethod(tpl, "getContainerNameByCertificate", GetContainerNameByCertificate);
	Nan::SetPrototypeMethod(tpl, "deleteContainer", DeleteContainer);

	// Store the constructor in the target bindings.
	constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());

	exports->Set(className, tpl->GetFunction());
}

NAN_METHOD(WCsp::New) {
	METHOD_BEGIN();

	try {
		WCsp *obj = new WCsp();
		obj->data_ = new Csp();

		obj->Wrap(info.This());

		info.GetReturnValue().Set(info.This());
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::IsGost2001CSPAvailable) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		bool res = _this->isGost2001CSPAvailable();

		info.GetReturnValue().Set(Nan::New<v8::Boolean>(res));
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::IsGost2012_256CSPAvailable) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		bool res = _this->isGost2012_256CSPAvailable();

		info.GetReturnValue().Set(Nan::New<v8::Boolean>(res));
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::IsGost2012_512CSPAvailable) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		bool res = _this->isGost2012_512CSPAvailable();

		info.GetReturnValue().Set(Nan::New<v8::Boolean>(res));
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::CheckCPCSPLicense) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		bool res = _this->checkCPCSPLicense();

		info.GetReturnValue().Set(Nan::New<v8::Boolean>(res));
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPLicense) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> lic = _this->getCPCSPLicense();

		v8::Local<v8::String> v8Lic = Nan::New<v8::String>(lic->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Lic);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPVersion) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> ver = _this->getCPCSPVersion();

		v8::Local<v8::String> v8Ver = Nan::New<v8::String>(ver->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Ver);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPVersionPKZI) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> ver = _this->getCPCSPVersionPKZI();

		v8::Local<v8::String> v8Ver = Nan::New<v8::String>(ver->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Ver);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPVersionSKZI) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> ver = _this->getCPCSPVersionSKZI();

		v8::Local<v8::String> v8Ver = Nan::New<v8::String>(ver->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Ver);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPSecurityLvl) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> lic = _this->getCPCSPSecurityLvl();

		v8::Local<v8::String> v8Lic = Nan::New<v8::String>(lic->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Lic);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::EnumProviders)
{
	METHOD_BEGIN();

	try{
		UNWRAP_DATA(Csp);

		std::vector<ProviderProps> res = _this->enumProviders();

		v8::Isolate* isolate = v8::Isolate::GetCurrent();

		v8::Local<v8::Array> array8 = v8::Array::New(isolate, res.size());

		for (int i = 0; i < res.size(); i++){
			v8::Local<v8::Object> obj = Nan::New<v8::Object>();
			obj->Set(Nan::New("type").ToLocalChecked(), Nan::New<v8::Number>(res[i].type));
			obj->Set(Nan::New("name").ToLocalChecked(), Nan::New<v8::String>(res[i].name->c_str()).ToLocalChecked());

			array8->Set(i, obj);
		}

		info.GetReturnValue().Set(array8);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::EnumContainers)
{
	METHOD_BEGIN();

	try{
		UNWRAP_DATA(Csp);

		int type = NULL;

		LOGGER_ARG("type");
		if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
			type = info[0]->ToNumber()->Int32Value();
		}

		LOGGER_ARG("name");
		v8::String::Utf8Value v8Prov(info[1]->ToString());
		char *provName = *v8Prov;

		std::vector<Handle<std::wstring>> res = _this->enumContainers(type, new std::string(provName));

		v8::Isolate* isolate = v8::Isolate::GetCurrent();

		v8::Local<v8::Array> array8 = v8::Array::New(isolate, res.size());

		for (int i = 0; i < res.size(); i++){
			array8->Set(i, v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), (const uint16_t *)res[i]->c_str()));
		}

		info.GetReturnValue().Set(array8);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCertifiacteFromContainer)
{
	METHOD_BEGIN();

	try{
#ifdef CSP_ENABLE
		UNWRAP_DATA(Csp);

		LOGGER_ARG("container");
		v8::String::Utf8Value v8Cont(info[0]->ToString());
		char *cont = *v8Cont;

		LOGGER_ARG("type");
		int type = info[1]->ToNumber()->Int32Value();

		LOGGER_ARG("provider");
		v8::String::Utf8Value v8Prov(info[2]->ToString());
		char *provName = *v8Prov;

		Handle<Certificate> cert = _this->getCertifiacteFromContainer(new std::string(cont), type, new std::string(provName));
		v8::Local<v8::Object> v8Cert = WCertificate::NewInstance(cert);
		info.GetReturnValue().Set(v8Cert);
		return;
#else
		Nan::ThrowError("Only if CSP_ENABLE");
#endif // CSP_ENABLE
	}
	TRY_END();
}

NAN_METHOD(WCsp::InstallCertifiacteFromContainer)
{
	METHOD_BEGIN();

	try{
#ifdef CSP_ENABLE
		UNWRAP_DATA(Csp);

		LOGGER_ARG("container");
		LPCWSTR wCont = (LPCWSTR)* v8::String::Value(info[0]->ToString());
		char *wcContainerName = new(std::nothrow) char[wcslen(wCont) + 1];
		memset(wcContainerName, 0, wcslen(wCont) + 1);
		std::wcstombs(wcContainerName, wCont, wcslen(wCont));

		LOGGER_ARG("type");
		int type = info[1]->ToNumber()->Int32Value();

		LOGGER_ARG("provider");
		v8::String::Utf8Value v8Prov(info[2]->ToString());
		char *provName = *v8Prov;

		_this->installCertifiacteFromContainer(new std::string(wcContainerName), type, new std::string(provName));

		if (wcContainerName) {
			free(wcContainerName);
		}

		info.GetReturnValue().Set(info.This());
		return;
#else
		Nan::ThrowError("Only if CSP_ENABLE");
#endif // CSP_ENABLE
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetContainerNameByCertificate){
	METHOD_BEGIN();

	try{
#ifdef CSP_ENABLE
		LOGGER_ARG("cert");
		WCertificate * wCert = WCertificate::Unwrap<WCertificate>(info[0]->ToObject());

		LOGGER_ARG("category");
		v8::String::Utf8Value v8Category(info[1]->ToString());
		char *category = *v8Category;

		UNWRAP_DATA(Csp);

		Handle<std::string> cont = _this->getContainerNameByCertificate(wCert->data_, new std::string(category));

		v8::Local<v8::String> v8Cont = Nan::New<v8::String>(cont->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Cont);

		return;
#else
		Nan::ThrowError("Only if CSP_ENABLE");
#endif // CSP_ENABLE
	}

	TRY_END();
}

NAN_METHOD(WCsp::DeleteContainer)
{
	METHOD_BEGIN();

	try{
#ifdef CSP_ENABLE
		UNWRAP_DATA(Csp);

		LOGGER_ARG("container");
		v8::String::Utf8Value v8Cont(info[0]->ToString());
		char *cont = *v8Cont;

		LOGGER_ARG("type");
		int type = info[1]->ToNumber()->Int32Value();

		LOGGER_ARG("provider");
		v8::String::Utf8Value v8Prov(info[2]->ToString());
		char *provName = *v8Prov;

		_this->deleteContainer(new std::string(cont), type, new std::string(provName));

		info.GetReturnValue().Set(info.This());
		return;
#else
		Nan::ThrowError("Only if CSP_ENABLE");
#endif // CSP_ENABLE
	}
	TRY_END();
}
<commit_msg>fix arg type<commit_after>#include "../stdafx.h"

#include "wcsp.h"
#include "../pki/wcert.h"
#include "../helper.h"

void WCsp::Init(v8::Handle<v8::Object> exports) {
	METHOD_BEGIN();

	v8::Local<v8::String> className = Nan::New("Csp").ToLocalChecked();

	// Basic instance setup
	v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);

	tpl->SetClassName(className);
	tpl->InstanceTemplate()->SetInternalFieldCount(1); // req'd by ObjectWrap

	Nan::SetPrototypeMethod(tpl, "isGost2001CSPAvailable", IsGost2001CSPAvailable);
	Nan::SetPrototypeMethod(tpl, "isGost2012_256CSPAvailable", IsGost2012_256CSPAvailable);
	Nan::SetPrototypeMethod(tpl, "isGost2012_512CSPAvailable", IsGost2012_512CSPAvailable);

	Nan::SetPrototypeMethod(tpl, "checkCPCSPLicense", CheckCPCSPLicense);
	Nan::SetPrototypeMethod(tpl, "getCPCSPLicense", GetCPCSPLicense);
	Nan::SetPrototypeMethod(tpl, "getCPCSPVersion", GetCPCSPVersion);
	Nan::SetPrototypeMethod(tpl, "getCPCSPVersionPKZI", GetCPCSPVersionPKZI);
	Nan::SetPrototypeMethod(tpl, "getCPCSPVersionSKZI", GetCPCSPVersionSKZI);
	Nan::SetPrototypeMethod(tpl, "getCPCSPSecurityLvl", GetCPCSPSecurityLvl);

	Nan::SetPrototypeMethod(tpl, "enumProviders", EnumProviders);
	Nan::SetPrototypeMethod(tpl, "enumContainers", EnumContainers);
	Nan::SetPrototypeMethod(tpl, "getCertifiacteFromContainer", GetCertifiacteFromContainer);
	Nan::SetPrototypeMethod(tpl, "installCertifiacteFromContainer", InstallCertifiacteFromContainer);
	Nan::SetPrototypeMethod(tpl, "getContainerNameByCertificate", GetContainerNameByCertificate);
	Nan::SetPrototypeMethod(tpl, "deleteContainer", DeleteContainer);

	// Store the constructor in the target bindings.
	constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());

	exports->Set(className, tpl->GetFunction());
}

NAN_METHOD(WCsp::New) {
	METHOD_BEGIN();

	try {
		WCsp *obj = new WCsp();
		obj->data_ = new Csp();

		obj->Wrap(info.This());

		info.GetReturnValue().Set(info.This());
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::IsGost2001CSPAvailable) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		bool res = _this->isGost2001CSPAvailable();

		info.GetReturnValue().Set(Nan::New<v8::Boolean>(res));
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::IsGost2012_256CSPAvailable) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		bool res = _this->isGost2012_256CSPAvailable();

		info.GetReturnValue().Set(Nan::New<v8::Boolean>(res));
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::IsGost2012_512CSPAvailable) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		bool res = _this->isGost2012_512CSPAvailable();

		info.GetReturnValue().Set(Nan::New<v8::Boolean>(res));
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::CheckCPCSPLicense) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		bool res = _this->checkCPCSPLicense();

		info.GetReturnValue().Set(Nan::New<v8::Boolean>(res));
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPLicense) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> lic = _this->getCPCSPLicense();

		v8::Local<v8::String> v8Lic = Nan::New<v8::String>(lic->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Lic);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPVersion) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> ver = _this->getCPCSPVersion();

		v8::Local<v8::String> v8Ver = Nan::New<v8::String>(ver->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Ver);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPVersionPKZI) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> ver = _this->getCPCSPVersionPKZI();

		v8::Local<v8::String> v8Ver = Nan::New<v8::String>(ver->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Ver);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPVersionSKZI) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> ver = _this->getCPCSPVersionSKZI();

		v8::Local<v8::String> v8Ver = Nan::New<v8::String>(ver->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Ver);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCPCSPSecurityLvl) {
	METHOD_BEGIN();

	try {
		UNWRAP_DATA(Csp);

		Handle<std::string> lic = _this->getCPCSPSecurityLvl();

		v8::Local<v8::String> v8Lic = Nan::New<v8::String>(lic->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Lic);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::EnumProviders)
{
	METHOD_BEGIN();

	try{
		UNWRAP_DATA(Csp);

		std::vector<ProviderProps> res = _this->enumProviders();

		v8::Isolate* isolate = v8::Isolate::GetCurrent();

		v8::Local<v8::Array> array8 = v8::Array::New(isolate, res.size());

		for (int i = 0; i < res.size(); i++){
			v8::Local<v8::Object> obj = Nan::New<v8::Object>();
			obj->Set(Nan::New("type").ToLocalChecked(), Nan::New<v8::Number>(res[i].type));
			obj->Set(Nan::New("name").ToLocalChecked(), Nan::New<v8::String>(res[i].name->c_str()).ToLocalChecked());

			array8->Set(i, obj);
		}

		info.GetReturnValue().Set(array8);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::EnumContainers)
{
	METHOD_BEGIN();

	try{
		UNWRAP_DATA(Csp);

		int type = NULL;

		LOGGER_ARG("type");
		if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
			type = info[0]->ToNumber()->Int32Value();
		}

		LOGGER_ARG("name");
		v8::String::Utf8Value v8Prov(info[1]->ToString());
		char *provName = *v8Prov;

		std::vector<Handle<std::wstring>> res = _this->enumContainers(type, new std::string(provName));

		v8::Isolate* isolate = v8::Isolate::GetCurrent();

		v8::Local<v8::Array> array8 = v8::Array::New(isolate, res.size());

		for (int i = 0; i < res.size(); i++){
			array8->Set(i, v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), (const uint16_t *)res[i]->c_str()));
		}

		info.GetReturnValue().Set(array8);
		return;
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetCertifiacteFromContainer)
{
	METHOD_BEGIN();

	try{
#ifdef CSP_ENABLE
		UNWRAP_DATA(Csp);

		LOGGER_ARG("container");
		LPCWSTR wCont = (LPCWSTR)* v8::String::Value(info[0]->ToString());
		char *wcContainerName = new(std::nothrow) char[wcslen(wCont) + 1];
		memset(wcContainerName, 0, wcslen(wCont) + 1);
		std::wcstombs(wcContainerName, wCont, wcslen(wCont));

		LOGGER_ARG("type");
		int type = info[1]->ToNumber()->Int32Value();

		LOGGER_ARG("provider");
		v8::String::Utf8Value v8Prov(info[2]->ToString());
		char *provName = *v8Prov;

		Handle<Certificate> cert = _this->getCertifiacteFromContainer(new std::string(wcContainerName), type, new std::string(provName));
		v8::Local<v8::Object> v8Cert = WCertificate::NewInstance(cert);
		info.GetReturnValue().Set(v8Cert);
		return;
#else
		Nan::ThrowError("Only if CSP_ENABLE");
#endif // CSP_ENABLE
	}
	TRY_END();
}

NAN_METHOD(WCsp::InstallCertifiacteFromContainer)
{
	METHOD_BEGIN();

	try{
#ifdef CSP_ENABLE
		UNWRAP_DATA(Csp);

		LOGGER_ARG("container");
		LPCWSTR wCont = (LPCWSTR)* v8::String::Value(info[0]->ToString());
		char *wcContainerName = new(std::nothrow) char[wcslen(wCont) + 1];
		memset(wcContainerName, 0, wcslen(wCont) + 1);
		std::wcstombs(wcContainerName, wCont, wcslen(wCont));

		LOGGER_ARG("type");
		int type = info[1]->ToNumber()->Int32Value();

		LOGGER_ARG("provider");
		v8::String::Utf8Value v8Prov(info[2]->ToString());
		char *provName = *v8Prov;

		_this->installCertifiacteFromContainer(new std::string(wcContainerName), type, new std::string(provName));

		if (wcContainerName) {
			free(wcContainerName);
		}

		info.GetReturnValue().Set(info.This());
		return;
#else
		Nan::ThrowError("Only if CSP_ENABLE");
#endif // CSP_ENABLE
	}
	TRY_END();
}

NAN_METHOD(WCsp::GetContainerNameByCertificate){
	METHOD_BEGIN();

	try{
#ifdef CSP_ENABLE
		LOGGER_ARG("cert");
		WCertificate * wCert = WCertificate::Unwrap<WCertificate>(info[0]->ToObject());

		LOGGER_ARG("category");
		v8::String::Utf8Value v8Category(info[1]->ToString());
		char *category = *v8Category;

		UNWRAP_DATA(Csp);

		Handle<std::string> cont = _this->getContainerNameByCertificate(wCert->data_, new std::string(category));

		v8::Local<v8::String> v8Cont = Nan::New<v8::String>(cont->c_str()).ToLocalChecked();

		info.GetReturnValue().Set(v8Cont);

		return;
#else
		Nan::ThrowError("Only if CSP_ENABLE");
#endif // CSP_ENABLE
	}

	TRY_END();
}

NAN_METHOD(WCsp::DeleteContainer)
{
	METHOD_BEGIN();

	try{
#ifdef CSP_ENABLE
		UNWRAP_DATA(Csp);

		LOGGER_ARG("container");
		v8::String::Utf8Value v8Cont(info[0]->ToString());
		char *cont = *v8Cont;

		LOGGER_ARG("type");
		int type = info[1]->ToNumber()->Int32Value();

		LOGGER_ARG("provider");
		v8::String::Utf8Value v8Prov(info[2]->ToString());
		char *provName = *v8Prov;

		_this->deleteContainer(new std::string(cont), type, new std::string(provName));

		info.GetReturnValue().Set(info.This());
		return;
#else
		Nan::ThrowError("Only if CSP_ENABLE");
#endif // CSP_ENABLE
	}
	TRY_END();
}
<|endoftext|>


<commit_before>#include "config.h"

std::string GetName() {
#ifdef _WIN32
    return "config.txt";
#elif defined(__unix) || defined (__APPLE__)
    return "nopassdb.conf";
#endif
}

std::string GetLocation() {
    char* systemenv;
    std::string location;

#ifdef _WIN32
    systemenv = getenv("APPDATA");
    location.assign(systemenv);
    location += "\\nopassdb";
#elif defined(__unix) && !defined(__APPLE__)
    systemenv = getenv("HOME");
    location.assign(systemenv);
    location += "/.config/nopassdb/";
#elif defined (__APPLE__)
    systemenv = getenv("HOME");
    location.assign(systemenv);
    location += "/Documents/nopassdb/";
#endif

    return location;
}

int NoPassDB::CheckConfig(int &length, std::string &salt) {
    std::string line;
    std::ifstream config;

    // Check for config in same location
    config.open(GetName());
    if (config.is_open()) {
        // Get length from config
        getline(config, line);
        length = atoi(line.c_str());;
        if (length == 0) {
            length = 20;
        }

        // Get salt from config
        getline(config, line);
        salt = line;
        if (line != "") {
            config.close();
            return 1;
        }

        config.close();
        return 0;
    }

    // Check for config in system env
    config.open(GetLocation() + GetName());
    if (config.is_open()) {
        // Get length from config
        getline(config, line);
        length = atoi(line.c_str());;
        if (length == 0) {
            length = 20;
        }

        // Get salt from config
        getline(config, line);
        salt = line;
        if (line != "") {
            config.close();
            return 1;
        }

        config.close();
        return 0;
    }

    return 0;
}

int NoPassDB::CreateConfig(std::string salt) {
    std::string location = GetLocation();
    std::string mkdir;

#ifdef _WIN32
    mkdir = "cmd /c mkdir " + location;
#elif defined(__unix) || defined (__APPLE__)
    mkdir = "mkdir " + location;
#endif
    system(mkdir.c_str());

    std::ofstream config(location + GetName());
    if (config.is_open()) {
        config << "20\n";
        config << salt + "\n";

        config.close();
    }

    return 0;
}
<commit_msg>Fix small bug in config location on Windows<commit_after>#include "config.h"

std::string GetName() {
#ifdef _WIN32
    return "config.txt";
#elif defined(__unix) || defined (__APPLE__)
    return "nopassdb.conf";
#endif
}

std::string GetLocation() {
    char* systemenv;
    std::string location;

#ifdef _WIN32
    systemenv = getenv("APPDATA");
    location.assign(systemenv);
    location += "\\nopassdb\\";
#elif defined(__unix) && !defined(__APPLE__)
    systemenv = getenv("HOME");
    location.assign(systemenv);
    location += "/.config/nopassdb/";
#elif defined (__APPLE__)
    systemenv = getenv("HOME");
    location.assign(systemenv);
    location += "/Documents/nopassdb/";
#endif

    return location;
}

int NoPassDB::CheckConfig(int &length, std::string &salt) {
    std::string line;
    std::ifstream config;

    // Check for config in same location
    config.open(GetName());
    if (config.is_open()) {
        // Get length from config
        getline(config, line);
        length = atoi(line.c_str());;
        if (length == 0) {
            length = 20;
        }

        // Get salt from config
        getline(config, line);
        salt = line;
        if (line != "") {
            config.close();
            return 1;
        }

        config.close();
        return 0;
    }

    // Check for config in system env
    config.open(GetLocation() + GetName());
    if (config.is_open()) {
        // Get length from config
        getline(config, line);
        length = atoi(line.c_str());;
        if (length == 0) {
            length = 20;
        }

        // Get salt from config
        getline(config, line);
        salt = line;
        if (line != "") {
            config.close();
            return 1;
        }

        config.close();
        return 0;
    }

    return 0;
}

int NoPassDB::CreateConfig(std::string salt) {
    std::string location = GetLocation();
    std::string mkdir;

#ifdef _WIN32
    mkdir = "cmd /c mkdir " + location;
#elif defined(__unix) || defined (__APPLE__)
    mkdir = "mkdir " + location;
#endif
    system(mkdir.c_str());

    std::ofstream config(location + GetName());
    if (config.is_open()) {
        config << "20\n";
        config << salt + "\n";

        config.close();
    }

    return 0;
}
<|endoftext|>


<commit_before>// ------------------------------------------------------------------
// ofxTPSpriteData.cpp
// ofxTexturePacker - https://www.github.com/danoli3/ofxTexturePacker
// Created by Daniel Rosser and Colin Friend on 9/06/2014.
// ------------------------------------------------------------------

#include "ofxTPSpriteData.h"

ofxTPSpriteData::ofxTPSpriteData() : name(""), animationName(""), x(0), y(0), w(0), h(0), oX(0), oY(0), oW(0), oH(0), frame(0), isAnimated(false) {

}

void ofxTPSpriteData::determineAnimated() {
    Poco::RegularExpression reg("((?:(?![\\d]*[.].*$)[\\w\\s])+)([\\d]*)([.].*)$");
//    int match(const std::string& subject, Match& mtch, int options = 0) const;
    Poco::RegularExpression::MatchVec matches;
    int numberOfMatches = reg.match(name, 0, matches);
    if(matches[0].length != 0) {
        if (matches[2].length > 0) {
            if (matches[1].length > 0) {
                animationName = name.substr(matches[1].offset, matches[1].length);
            }
            isAnimated = true;
            frame = ofToInt(name.substr(matches[2].offset, matches[2].length));
        } else {
            isAnimated = false;
        }
    }
    else {
        ofLog(OF_LOG_ERROR, "ERROR: Filename format not recognised for " + name);
    }
//---------- CP-11 version
/**
    if (reg.match(name, matches)) {
        if (subStrings.length(2) > 0) {
            if (subStrings.length(1) > 0) {
                animationName = subStrings[1];
            }
            isAnimated = true;
            frame = ofToInt(subStrings[2]);
        } else {
            isAnimated = false;
        }
    } else {
        ofLog(OF_LOG_ERROR, "ERROR: Filename format not recognised for " + name);
    }

    smatch subStrings;
    regex expression ("((?:(?![\\d]*[.].*$)[\\w\\s])+)([\\d]*)([.].*)$");

    if (regex_match(name, subStrings, expression)) {
        if (subStrings.length(2) > 0) {
            if (subStrings.length(1) > 0) {
                animationName = subStrings[1];
            }
            isAnimated = true;
            frame = ofToInt(subStrings[2]);
        } else {
            isAnimated = false;
        }
    } else {
        ofLog(OF_LOG_ERROR, "ERROR: Filename format not recognised for " + name);
    }
*/

}

void ofxTPSpriteData::extractFrame() {

}<commit_msg>Fixes texture name if underscores used.<commit_after>// ------------------------------------------------------------------
// ofxTPSpriteData.cpp
// ofxTexturePacker - https://www.github.com/danoli3/ofxTexturePacker
// Created by Daniel Rosser and Colin Friend on 9/06/2014.
// ------------------------------------------------------------------

#include "ofxTPSpriteData.h"

ofxTPSpriteData::ofxTPSpriteData() : name(""), animationName(""), x(0), y(0), w(0), h(0), oX(0), oY(0), oW(0), oH(0), frame(0), isAnimated(false) {

}

void ofxTPSpriteData::determineAnimated() {
    Poco::RegularExpression reg("((?:(?![\\d]*[.].*$)[\\w\\s])+)([\\d]*)([.].*)$");
//    int match(const std::string& subject, Match& mtch, int options = 0) const;
    Poco::RegularExpression::MatchVec matches;
    int numberOfMatches = reg.match(name, 0, matches);
    if(matches[0].length != 0) {
        if (matches[2].length > 0) {
            if (matches[1].length > 0) {
                animationName = name.substr(matches[1].offset, matches[1].length);
                if(animationName.substr(animationName.size()-1, animationName.size()) == "_") {
                    animationName = animationName.substr(0, animationName.size()-1);
                }
            }
            isAnimated = true;
            frame = ofToInt(name.substr(matches[2].offset, matches[2].length));
        } else {
            isAnimated = false;
        }
    }
    else {
        ofLog(OF_LOG_ERROR, "ERROR: Filename format not recognised for " + name);
    }
//---------- CP-11 version
/**
    if (reg.match(name, matches)) {
        if (subStrings.length(2) > 0) {
            if (subStrings.length(1) > 0) {
                animationName = subStrings[1];
            }
            isAnimated = true;
            frame = ofToInt(subStrings[2]);
        } else {
            isAnimated = false;
        }
    } else {
        ofLog(OF_LOG_ERROR, "ERROR: Filename format not recognised for " + name);
    }

    smatch subStrings;
    regex expression ("((?:(?![\\d]*[.].*$)[\\w\\s])+)([\\d]*)([.].*)$");

    if (regex_match(name, subStrings, expression)) {
        if (subStrings.length(2) > 0) {
            if (subStrings.length(1) > 0) {
                animationName = subStrings[1];
            }
            isAnimated = true;
            frame = ofToInt(subStrings[2]);
        } else {
            isAnimated = false;
        }
    } else {
        ofLog(OF_LOG_ERROR, "ERROR: Filename format not recognised for " + name);
    }
*/

}

void ofxTPSpriteData::extractFrame() {

}<|endoftext|>