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

#include "oerushield/oerushield.h"

#include "base58.h"
#include "chainparams.h"
#include "oerushield/oerudb.h"
#include "oerushield/oerutx.h"
#include "oerushield/signaturechecker.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "util.h"
#include "utilstrencodings.h"

#include <string>
#include <vector>

const std::vector<unsigned char> COeruShield::OERU_BYTES = { 0x4f, 0x45, 0x52, 0x55 }; // "OERU"
const uint64_t COeruShield::MAX_HEIGHT_DIFFERENCE = 720;

const std::vector<std::vector<unsigned char>> COeruShield::MASTER_KEYS =
{
    ParseHex("1e58eb7273d4ce30e9a961600aaa49871beec551aba5b6f5a5712d6ccd1a8e3a"),
    ParseHex("b752e70e9b8343719491edfb524db6599e21d98269c1e720509636a6bb5db7ba"),
    ParseHex("f6b2c579d2bc9c86603d0689546ca989c543049d5bdd8486c9b72eee4ccca5b1")
};

COeruShield::COeruShield(COeruDB *oeruDB)
{
    this->oeruDB = oeruDB;
}

bool COeruShield::CheckMasterTx(CTransaction tx, int nHeight) const
{
    if (tx.IsCoinBase())
        return false;

    if (tx.vout.size() != 3)
        return false;

    CTxOut minerOut = tx.vout[0];
    CTxOut masterOut = tx.vout[1];
    CTxOut signatureOut = tx.vout[2];

    CBitcoinAddress master;
    if (!GetDestinationAddress(masterOut, master))
        return false;

    if (!IsMasterKey(master))
        return false;

    CBitcoinAddress miner;
    if (!GetDestinationAddress(minerOut, miner))
        return false;

    COeruTxOut masterOeruOut(&signatureOut);
    COeruMasterData masterData;
    if (!masterOeruOut.GetOeruMasterData(masterData))
        return false;

    if (!masterData.IsValid())
        return false;

    uint64_t masterHeight;
    if (!masterData.GetHeight(masterHeight))
        return false;

    if (masterHeight < nHeight - COeruShield::MAX_HEIGHT_DIFFERENCE)
        return false;

    if (!masterData.HasValidSignature(master))
        return false;

    bool enable;
    if (!masterData.GetEnable(enable))
        return false;

    if (enable)
        oeruDB->AddCertifiedAddress(miner);
    else
        oeruDB->RemoveCertifiedAddress(miner);

    return true;
}

bool COeruShield::FindOeruVOut(const CTransaction& coinbaseTx, COeruTxOut& oeruTxOut) const
{
    if (!coinbaseTx.IsCoinBase())
        return false;

    for (auto &vout : coinbaseTx.vout)
    {
        oeruTxOut = COeruTxOut(&vout);

        if (oeruTxOut.HasOeruBytes())
        {
            return true;
        }
    }
    return false;
}

bool COeruShield::GetCoinbaseAddress(const CTransaction& coinbaseTx, CBitcoinAddress& coinbaseAddress) const
{
    if (coinbaseTx.vout.size() < 1)
        return false;

    return GetDestinationAddress(coinbaseTx.vout[0], coinbaseAddress);
}

bool COeruShield::GetCoinbaseTx(const CBlock& block, CTransaction& coinbaseTx) const
{
    if (block.vtx.size() < 1)
        return false;

    coinbaseTx = block.vtx[0];

    if (!coinbaseTx.IsCoinBase())
        return false;

    return true;
}

bool COeruShield::GetDestinationAddress(const CTxOut txOut, CBitcoinAddress &destination) const
{
    CTxDestination txDestination;
    if (!ExtractDestination(txOut.scriptPubKey, txDestination))
        return false;

    destination = CBitcoinAddress(txDestination);
    if (!destination.IsValid())
        return false;

    return true;
}

bool COeruShield::IsActive() const
{
    int minAddresses = Params().OeruShieldMinCertifiedAddresses();
    return oeruDB->NumCertifiedAddresses() >= minAddresses;
}

bool COeruShield::IsBlockIdentified(const CBlock& block, const int nHeight) const
{
    CTransaction coinbaseTx;
    if ( ! GetCoinbaseTx(block, coinbaseTx))
        return false;

    CBitcoinAddress coinbaseAddress;
    if ( ! GetCoinbaseAddress(coinbaseTx, coinbaseAddress))
        return false;

    COeruTxOut oeruTxOut;
    if ( ! FindOeruVOut(coinbaseTx, oeruTxOut)) {
       LogPrint("OeruShield", "%s: No valid oeru vout found\n", __FUNCTION__);
       return false;
    }

    std::vector<unsigned char> vchData;
    if (!oeruTxOut.GetOpReturnData(vchData)) {
       LogPrint("OeruShield", "%s: No OP_RETURN data found\n", __FUNCTION__);
       return false;
    }

    std::vector<unsigned char> vchSig(vchData.begin() + COeruShield::OERU_BYTES.size(), vchData.end());
    std::string strMessage = std::to_string(nHeight);

    CSignatureChecker signatureChecker;
    if (signatureChecker.VerifySignature(strMessage, vchSig, coinbaseAddress)) {
        LogPrint("OeruShield", "%s: Valid OERU signature\n", __FUNCTION__);
        return true;
    } else {
        LogPrint("OeruShield", "%s: No valid OERU signature\n", __FUNCTION__);
        return false;
    }
}

bool COeruShield::IsBlockCertified(const CBlock& block, const int nHeight) const
{
    if ( ! IsBlockIdentified(block, nHeight))
        return false;

    CTransaction coinbaseTx;
    if ( ! GetCoinbaseTx(block, coinbaseTx) || coinbaseTx.vout.size() < 2)
        return false;

    CBitcoinAddress coinbaseAddress;
    if ( ! GetCoinbaseAddress(coinbaseTx, coinbaseAddress))
        return false;

    return oeruDB->IsAddressCertified(coinbaseAddress);
}

bool COeruShield::IsMasterKey(std::vector<unsigned char> addrHash) const
{
    for (auto it = COeruShield::MASTER_KEYS.begin(); it != COeruShield::MASTER_KEYS.end(); ++it)
    {
        if (*it == addrHash)
        {
            return true;
        }
    }

    return false;
}

bool COeruShield::IsMasterKey(CBitcoinAddress addr) const
{
    std::string strAddr = addr.ToString();
    std::vector<unsigned char> hash;
    hash.resize(CSHA256::OUTPUT_SIZE);

    CSHA256().Write((unsigned char*) &strAddr[0], strAddr.size())
        .Finalize(&hash[0]);

    return IsMasterKey(hash);
}
<commit_msg>Write file when any address is certified or decertified<commit_after>// Copyright (c) 2017 The e-Gulden Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "oerushield/oerushield.h"

#include "base58.h"
#include "chainparams.h"
#include "oerushield/oerudb.h"
#include "oerushield/oerutx.h"
#include "oerushield/signaturechecker.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "util.h"
#include "utilstrencodings.h"

#include <string>
#include <vector>

const std::vector<unsigned char> COeruShield::OERU_BYTES = { 0x4f, 0x45, 0x52, 0x55 }; // "OERU"
const uint64_t COeruShield::MAX_HEIGHT_DIFFERENCE = 720;

const std::vector<std::vector<unsigned char>> COeruShield::MASTER_KEYS =
{
    ParseHex("1e58eb7273d4ce30e9a961600aaa49871beec551aba5b6f5a5712d6ccd1a8e3a"),
    ParseHex("b752e70e9b8343719491edfb524db6599e21d98269c1e720509636a6bb5db7ba"),
    ParseHex("f6b2c579d2bc9c86603d0689546ca989c543049d5bdd8486c9b72eee4ccca5b1")
};

COeruShield::COeruShield(COeruDB *oeruDB)
{
    this->oeruDB = oeruDB;
}

bool COeruShield::CheckMasterTx(CTransaction tx, int nHeight) const
{
    if (tx.IsCoinBase())
        return false;

    if (tx.vout.size() != 3)
        return false;

    CTxOut minerOut = tx.vout[0];
    CTxOut masterOut = tx.vout[1];
    CTxOut signatureOut = tx.vout[2];

    CBitcoinAddress master;
    if (!GetDestinationAddress(masterOut, master))
        return false;

    if (!IsMasterKey(master))
        return false;

    CBitcoinAddress miner;
    if (!GetDestinationAddress(minerOut, miner))
        return false;

    COeruTxOut masterOeruOut(&signatureOut);
    COeruMasterData masterData;
    if (!masterOeruOut.GetOeruMasterData(masterData))
        return false;

    if (!masterData.IsValid())
        return false;

    uint64_t masterHeight;
    if (!masterData.GetHeight(masterHeight))
        return false;

    if (masterHeight < nHeight - COeruShield::MAX_HEIGHT_DIFFERENCE)
        return false;

    if (!masterData.HasValidSignature(master))
        return false;

    bool enable;
    if (!masterData.GetEnable(enable))
        return false;

    if (enable)
        oeruDB->AddCertifiedAddress(miner);
    else
        oeruDB->RemoveCertifiedAddress(miner);

    oeruDB->WriteFile();

    return true;
}

bool COeruShield::FindOeruVOut(const CTransaction& coinbaseTx, COeruTxOut& oeruTxOut) const
{
    if (!coinbaseTx.IsCoinBase())
        return false;

    for (auto &vout : coinbaseTx.vout)
    {
        oeruTxOut = COeruTxOut(&vout);

        if (oeruTxOut.HasOeruBytes())
        {
            return true;
        }
    }
    return false;
}

bool COeruShield::GetCoinbaseAddress(const CTransaction& coinbaseTx, CBitcoinAddress& coinbaseAddress) const
{
    if (coinbaseTx.vout.size() < 1)
        return false;

    return GetDestinationAddress(coinbaseTx.vout[0], coinbaseAddress);
}

bool COeruShield::GetCoinbaseTx(const CBlock& block, CTransaction& coinbaseTx) const
{
    if (block.vtx.size() < 1)
        return false;

    coinbaseTx = block.vtx[0];

    if (!coinbaseTx.IsCoinBase())
        return false;

    return true;
}

bool COeruShield::GetDestinationAddress(const CTxOut txOut, CBitcoinAddress &destination) const
{
    CTxDestination txDestination;
    if (!ExtractDestination(txOut.scriptPubKey, txDestination))
        return false;

    destination = CBitcoinAddress(txDestination);
    if (!destination.IsValid())
        return false;

    return true;
}

bool COeruShield::IsActive() const
{
    int minAddresses = Params().OeruShieldMinCertifiedAddresses();
    return oeruDB->NumCertifiedAddresses() >= minAddresses;
}

bool COeruShield::IsBlockIdentified(const CBlock& block, const int nHeight) const
{
    CTransaction coinbaseTx;
    if ( ! GetCoinbaseTx(block, coinbaseTx))
        return false;

    CBitcoinAddress coinbaseAddress;
    if ( ! GetCoinbaseAddress(coinbaseTx, coinbaseAddress))
        return false;

    COeruTxOut oeruTxOut;
    if ( ! FindOeruVOut(coinbaseTx, oeruTxOut)) {
       LogPrint("OeruShield", "%s: No valid oeru vout found\n", __FUNCTION__);
       return false;
    }

    std::vector<unsigned char> vchData;
    if (!oeruTxOut.GetOpReturnData(vchData)) {
       LogPrint("OeruShield", "%s: No OP_RETURN data found\n", __FUNCTION__);
       return false;
    }

    std::vector<unsigned char> vchSig(vchData.begin() + COeruShield::OERU_BYTES.size(), vchData.end());
    std::string strMessage = std::to_string(nHeight);

    CSignatureChecker signatureChecker;
    if (signatureChecker.VerifySignature(strMessage, vchSig, coinbaseAddress)) {
        LogPrint("OeruShield", "%s: Valid OERU signature\n", __FUNCTION__);
        return true;
    } else {
        LogPrint("OeruShield", "%s: No valid OERU signature\n", __FUNCTION__);
        return false;
    }
}

bool COeruShield::IsBlockCertified(const CBlock& block, const int nHeight) const
{
    if ( ! IsBlockIdentified(block, nHeight))
        return false;

    CTransaction coinbaseTx;
    if ( ! GetCoinbaseTx(block, coinbaseTx) || coinbaseTx.vout.size() < 2)
        return false;

    CBitcoinAddress coinbaseAddress;
    if ( ! GetCoinbaseAddress(coinbaseTx, coinbaseAddress))
        return false;

    return oeruDB->IsAddressCertified(coinbaseAddress);
}

bool COeruShield::IsMasterKey(std::vector<unsigned char> addrHash) const
{
    for (auto it = COeruShield::MASTER_KEYS.begin(); it != COeruShield::MASTER_KEYS.end(); ++it)
    {
        if (*it == addrHash)
        {
            return true;
        }
    }

    return false;
}

bool COeruShield::IsMasterKey(CBitcoinAddress addr) const
{
    std::string strAddr = addr.ToString();
    std::vector<unsigned char> hash;
    hash.resize(CSHA256::OUTPUT_SIZE);

    CSHA256().Write((unsigned char*) &strAddr[0], strAddr.size())
        .Finalize(&hash[0]);

    return IsMasterKey(hash);
}
<|endoftext|>


<commit_before>#include "PictureRenderer.h"
#include "SamplePipeControllers.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkGPipe.h"
#include "SkPicture.h"
#include "SkTDArray.h"
#include "SkTypes.h"
#include "picture_utils.h"

#if SK_SUPPORT_GPU
#include "SkGpuDevice.h"
#endif

namespace sk_tools {

enum {
    kDefaultTileWidth = 256,
    kDefaultTileHeight = 256
};

void PictureRenderer::init(SkPicture* pict) {
    SkASSERT(NULL == fPicture);
    SkASSERT(NULL == fCanvas.get());
    if (fPicture != NULL || NULL != fCanvas.get()) {
        return;
    }

    SkASSERT(pict != NULL);
    if (NULL == pict) {
        return;
    }

    fPicture = pict;
    fCanvas.reset(this->setupCanvas());
}

SkCanvas* PictureRenderer::setupCanvas() {
    return this->setupCanvas(fPicture->width(), fPicture->height());
}

SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
    switch(fDeviceType) {
        case kBitmap_DeviceType: {
            SkBitmap bitmap;
            sk_tools::setup_bitmap(&bitmap, width, height);
            return SkNEW_ARGS(SkCanvas, (bitmap));
            break;
        }
#if SK_SUPPORT_GPU
        case kGPU_DeviceType: {
            SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice,
                                                    (fGrContext, SkBitmap::kARGB_8888_Config,
                                                    width, height)));
            return SkNEW_ARGS(SkCanvas, (device.get()));
            break;
        }
#endif
        default:
            SkASSERT(0);
    }

    return NULL;
}

void PictureRenderer::end() {
    this->resetState();
    fPicture = NULL;
    fCanvas.reset(NULL);
}

void PictureRenderer::resetState() {
    fCanvas->flush();

    if (this->isUsingGpuDevice()) {
        SkGLContext* glContext = fGrContextFactory.getGLContext(
            GrContextFactory::kNative_GLContextType);
        SK_GL(*glContext, Finish());
        fGrContext->freeGpuResources();
    }
}

void PipePictureRenderer::render() {
    SkASSERT(fCanvas.get() != NULL);
    SkASSERT(fPicture != NULL);
    if (NULL == fCanvas.get() || NULL == fPicture) {
        return;
    }

    PipeController pipeController(fCanvas.get());
    SkGPipeWriter writer;
    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
    pipeCanvas->drawPicture(*fPicture);
    writer.endRecording();
}

void SimplePictureRenderer::render() {
    SkASSERT(fCanvas.get() != NULL);
    SkASSERT(fPicture != NULL);
    if (NULL == fCanvas.get() || NULL == fPicture) {
        return;
    }

    fCanvas->drawPicture(*fPicture);
}

TiledPictureRenderer::TiledPictureRenderer()
    : fTileWidth(kDefaultTileWidth)
    , fTileHeight(kDefaultTileHeight) {}

void TiledPictureRenderer::init(SkPicture* pict) {
    SkASSERT(pict != NULL);
    SkASSERT(0 == fTiles.count());
    if (NULL == pict || fTiles.count() != 0) {
        return;
    }

    this->INHERITED::init(pict);

    if (fTileWidthPercentage > 0) {
        fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
    }
    if (fTileHeightPercentage > 0) {
        fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
    }

    this->setupTiles();
}

void TiledPictureRenderer::render() {
    SkASSERT(fCanvas.get() != NULL);
    SkASSERT(fPicture != NULL);
    if (NULL == fCanvas.get() || NULL == fPicture) {
        return;
    }

    this->drawTiles();
    this->copyTilesToCanvas();
}

void TiledPictureRenderer::end() {
    this->deleteTiles();
    this->INHERITED::end();
}

TiledPictureRenderer::~TiledPictureRenderer() {
    this->deleteTiles();
}

void TiledPictureRenderer::clipTile(const TileInfo& tile) {
    SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
                                 SkIntToScalar(fPicture->height()));
    tile.fCanvas->clipRect(clip);
}

void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) {
    TileInfo* tile = fTiles.push();

    tile->fCanvas = this->setupCanvas(fTileWidth, fTileHeight);
    tile->fCanvas->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
    this->clipTile(*tile);
}

void TiledPictureRenderer::setupTiles() {
    for (int tile_y_start = 0; tile_y_start < fPicture->height();
         tile_y_start += fTileHeight) {
        for (int tile_x_start = 0; tile_x_start < fPicture->width();
             tile_x_start += fTileWidth) {
            this->addTile(tile_x_start, tile_y_start);
        }
    }
}

void TiledPictureRenderer::deleteTiles() {
    for (int i = 0; i < fTiles.count(); ++i) {
        SkDELETE(fTiles[i].fCanvas);
        SkDELETE(fTiles[i].fBitmap);
    }

    fTiles.reset();
}

void TiledPictureRenderer::drawTiles() {
    for (int i = 0; i < fTiles.count(); ++i) {
        fTiles[i].fCanvas->drawPicture(*(fPicture));
    }
}

void TiledPictureRenderer::resetState() {
    for (int i = 0; i < fTiles.count(); ++i) {
        fTiles[i].fCanvas->flush();
    }

    this->INHERITED::resetState();
}

void TiledPictureRenderer::copyTilesToCanvas() {
    int tile_index = 0;
    for (int tile_y_start = 0; tile_y_start < fPicture->height();
         tile_y_start += fTileHeight) {
        for (int tile_x_start = 0; tile_x_start < fPicture->width();
             tile_x_start += fTileWidth) {
            SkASSERT(tile_index < fTiles.count());
            SkBitmap source = fTiles[tile_index].fCanvas->getDevice()->accessBitmap(false);
            fCanvas->drawBitmap(source,
                                SkIntToScalar(tile_x_start),
                                SkIntToScalar(tile_y_start));
            ++tile_index;
        }
    }
}

}
<commit_msg>Remove fBitmap delete. Tile bitmaps are no longer kept around.<commit_after>#include "PictureRenderer.h"
#include "SamplePipeControllers.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkGPipe.h"
#include "SkPicture.h"
#include "SkTDArray.h"
#include "SkTypes.h"
#include "picture_utils.h"

#if SK_SUPPORT_GPU
#include "SkGpuDevice.h"
#endif

namespace sk_tools {

enum {
    kDefaultTileWidth = 256,
    kDefaultTileHeight = 256
};

void PictureRenderer::init(SkPicture* pict) {
    SkASSERT(NULL == fPicture);
    SkASSERT(NULL == fCanvas.get());
    if (fPicture != NULL || NULL != fCanvas.get()) {
        return;
    }

    SkASSERT(pict != NULL);
    if (NULL == pict) {
        return;
    }

    fPicture = pict;
    fCanvas.reset(this->setupCanvas());
}

SkCanvas* PictureRenderer::setupCanvas() {
    return this->setupCanvas(fPicture->width(), fPicture->height());
}

SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
    switch(fDeviceType) {
        case kBitmap_DeviceType: {
            SkBitmap bitmap;
            sk_tools::setup_bitmap(&bitmap, width, height);
            return SkNEW_ARGS(SkCanvas, (bitmap));
            break;
        }
#if SK_SUPPORT_GPU
        case kGPU_DeviceType: {
            SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice,
                                                    (fGrContext, SkBitmap::kARGB_8888_Config,
                                                    width, height)));
            return SkNEW_ARGS(SkCanvas, (device.get()));
            break;
        }
#endif
        default:
            SkASSERT(0);
    }

    return NULL;
}

void PictureRenderer::end() {
    this->resetState();
    fPicture = NULL;
    fCanvas.reset(NULL);
}

void PictureRenderer::resetState() {
    fCanvas->flush();

    if (this->isUsingGpuDevice()) {
        SkGLContext* glContext = fGrContextFactory.getGLContext(
            GrContextFactory::kNative_GLContextType);
        SK_GL(*glContext, Finish());
        fGrContext->freeGpuResources();
    }
}

void PipePictureRenderer::render() {
    SkASSERT(fCanvas.get() != NULL);
    SkASSERT(fPicture != NULL);
    if (NULL == fCanvas.get() || NULL == fPicture) {
        return;
    }

    PipeController pipeController(fCanvas.get());
    SkGPipeWriter writer;
    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
    pipeCanvas->drawPicture(*fPicture);
    writer.endRecording();
}

void SimplePictureRenderer::render() {
    SkASSERT(fCanvas.get() != NULL);
    SkASSERT(fPicture != NULL);
    if (NULL == fCanvas.get() || NULL == fPicture) {
        return;
    }

    fCanvas->drawPicture(*fPicture);
}

TiledPictureRenderer::TiledPictureRenderer()
    : fTileWidth(kDefaultTileWidth)
    , fTileHeight(kDefaultTileHeight) {}

void TiledPictureRenderer::init(SkPicture* pict) {
    SkASSERT(pict != NULL);
    SkASSERT(0 == fTiles.count());
    if (NULL == pict || fTiles.count() != 0) {
        return;
    }

    this->INHERITED::init(pict);

    if (fTileWidthPercentage > 0) {
        fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
    }
    if (fTileHeightPercentage > 0) {
        fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
    }

    this->setupTiles();
}

void TiledPictureRenderer::render() {
    SkASSERT(fCanvas.get() != NULL);
    SkASSERT(fPicture != NULL);
    if (NULL == fCanvas.get() || NULL == fPicture) {
        return;
    }

    this->drawTiles();
    this->copyTilesToCanvas();
}

void TiledPictureRenderer::end() {
    this->deleteTiles();
    this->INHERITED::end();
}

TiledPictureRenderer::~TiledPictureRenderer() {
    this->deleteTiles();
}

void TiledPictureRenderer::clipTile(const TileInfo& tile) {
    SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
                                 SkIntToScalar(fPicture->height()));
    tile.fCanvas->clipRect(clip);
}

void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) {
    TileInfo* tile = fTiles.push();

    tile->fCanvas = this->setupCanvas(fTileWidth, fTileHeight);
    tile->fCanvas->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
    this->clipTile(*tile);
}

void TiledPictureRenderer::setupTiles() {
    for (int tile_y_start = 0; tile_y_start < fPicture->height();
         tile_y_start += fTileHeight) {
        for (int tile_x_start = 0; tile_x_start < fPicture->width();
             tile_x_start += fTileWidth) {
            this->addTile(tile_x_start, tile_y_start);
        }
    }
}

void TiledPictureRenderer::deleteTiles() {
    for (int i = 0; i < fTiles.count(); ++i) {
        SkDELETE(fTiles[i].fCanvas);
    }

    fTiles.reset();
}

void TiledPictureRenderer::drawTiles() {
    for (int i = 0; i < fTiles.count(); ++i) {
        fTiles[i].fCanvas->drawPicture(*(fPicture));
    }
}

void TiledPictureRenderer::resetState() {
    for (int i = 0; i < fTiles.count(); ++i) {
        fTiles[i].fCanvas->flush();
    }

    this->INHERITED::resetState();
}

void TiledPictureRenderer::copyTilesToCanvas() {
    int tile_index = 0;
    for (int tile_y_start = 0; tile_y_start < fPicture->height();
         tile_y_start += fTileHeight) {
        for (int tile_x_start = 0; tile_x_start < fPicture->width();
             tile_x_start += fTileWidth) {
            SkASSERT(tile_index < fTiles.count());
            SkBitmap source = fTiles[tile_index].fCanvas->getDevice()->accessBitmap(false);
            fCanvas->drawBitmap(source,
                                SkIntToScalar(tile_x_start),
                                SkIntToScalar(tile_y_start));
            ++tile_index;
        }
    }
}

}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
// The LLVM analyze utility
//
// This utility is designed to print out the results of running various analysis
// passes on a program.  This is useful for understanding a program, or for
// debugging an analysis pass.
//
//  analyze --help           - Output information about command line switches
//  analyze --quiet          - Do not print analysis name before output
//
//===----------------------------------------------------------------------===//

#include "llvm/Instruction.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/iPHINode.h"
#include "llvm/Type.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/Writer.h"
#include "llvm/Analysis/InstForest.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/IntervalPartition.h"
#include "llvm/Analysis/Expressions.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/FindUnsafePointerTypes.h"
#include "llvm/Analysis/FindUsedTypes.h"
#include "llvm/Support/InstIterator.h"
#include "Support/CommandLine.h"
#include <algorithm>
#include <iostream>

using std::ostream;
using std::string;

//===----------------------------------------------------------------------===//
// printPass - Specify how to print out a pass.  For most passes, the standard
// way of using operator<< works great, so we use it directly...
//
template<class PassType>
static void printPass(PassType &P, ostream &O, Module *M) {
  O << P;
}

template<class PassType>
static void printPass(PassType &P, ostream &O, Function *F) {
  O << P;
}

// Other classes require more information to print out information, so we
// specialize the template here for them...
//
template<>
static void printPass(DataStructure &P, ostream &O, Module *M) {
  P.print(O, M);
}

template<>
static void printPass(FindUsedTypes &FUT, ostream &O, Module *M) {
  FUT.printTypes(O, M);
}

template<>
static void printPass(FindUnsafePointerTypes &FUPT, ostream &O,
                      Module *M) {
  FUPT.printResults(M, O);
}

template <class PassType, class PassName>
class PassPrinter;  // Do not implement

template <class PassName>
class PassPrinter<Pass, PassName> : public Pass {
  const string Message;
  const AnalysisID ID;
public:
  PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}

  virtual bool run(Module *M) {
    std::cout << Message << "\n";
    printPass(getAnalysis<PassName>(ID), std::cout, M);
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(ID);
  }
};

template <class PassName>
class PassPrinter<FunctionPass, PassName> : public FunctionPass {
  const string Message;
  const AnalysisID ID;
public:
  PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}

  virtual bool runOnFunction(Function *F) {
    std::cout << Message << " on function '" << F->getName() << "'\n";
    printPass(getAnalysis<PassName>(ID), std::cout, F);
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(ID);
    AU.setPreservesAll();
  }
};

template <class PassType, class PassName, AnalysisID &ID>
Pass *New(const string &Message) {
  return new PassPrinter<PassType, PassName>(Message, ID);
}
template <class PassType, class PassName>
Pass *New(const string &Message) {
  return new PassPrinter<PassType, PassName>(Message, PassName::ID);
}

Pass *NewPrintFunction(const string &Message) {
  return new PrintFunctionPass(Message, &std::cout);
}
Pass *NewPrintModule(const string &Message) {
  return new PrintModulePass(&std::cout);
}

struct InstForest : public FunctionPass {
  void doit(Function *F) {
    std::cout << analysis::InstForest<char>(F);
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};

struct IndVars : public FunctionPass {
  void doit(Function *F) {
    LoopInfo &LI = getAnalysis<LoopInfo>();
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
      if (PHINode *PN = dyn_cast<PHINode>(*I)) {
        InductionVariable IV(PN, &LI);
        if (IV.InductionType != InductionVariable::Unknown)
          std::cout << IV;
      }
  }

  void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(LoopInfo::ID);
    AU.setPreservesAll();
  }
};

struct Exprs : public FunctionPass {
  static void doit(Function *F) {
    std::cout << "Classified expressions for: " << F->getName() << "\n";
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
      std::cout << *I;

      if ((*I)->getType() == Type::VoidTy) continue;
      analysis::ExprType R = analysis::ClassifyExpression(*I);
      if (R.Var == *I) continue;  // Doesn't tell us anything

      std::cout << "\t\tExpr =";
      switch (R.ExprTy) {
      case analysis::ExprType::ScaledLinear:
        WriteAsOperand(std::cout << "(", (Value*)R.Scale) << " ) *";
        // fall through
      case analysis::ExprType::Linear:
        WriteAsOperand(std::cout << "(", R.Var) << " )";
        if (R.Offset == 0) break;
        else std::cout << " +";
        // fall through
      case analysis::ExprType::Constant:
        if (R.Offset) WriteAsOperand(std::cout, (Value*)R.Offset);
        else std::cout << " 0";
        break;
      }
      std::cout << "\n\n";
    }
  }
  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};

template<class TraitClass>
class PrinterPass : public TraitClass {
  const string Message;
public:
  PrinterPass(const string &M) : Message(M) {}

  virtual bool runOnFunction(Function *F) {
    std::cout << Message << " on function '" << F->getName() << "'\n";

    TraitClass::doit(F);
    return false;
  }
};

template<class PassClass>
Pass *Create(const string &Message) {
  return new PassClass(Message);
}

enum Ans {
  // global analyses
  print, intervals, exprs, instforest, loops, indvars,

  // ip analyses
  printmodule, callgraph, datastructure, printusedtypes, unsafepointertypes,

  domset, idom, domtree, domfrontier,
  postdomset, postidom, postdomtree, postdomfrontier,
};

cl::String InputFilename ("", "Load <arg> file to analyze", cl::NoFlags, "-");
cl::Flag   Quiet         ("q", "Don't print analysis pass names");
cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
  clEnumVal(print          , "Print each function"),
  clEnumVal(intervals      , "Print Interval Partitions"),
  clEnumVal(exprs          , "Classify Expressions"),
  clEnumVal(instforest     , "Print Instruction Forest"),
  clEnumVal(loops          , "Print natural loops"),
  clEnumVal(indvars        , "Print Induction Variables"),

  clEnumVal(printmodule    , "Print entire module"),
  clEnumVal(callgraph      , "Print Call Graph"),
  clEnumVal(datastructure  , "Print data structure information"),
  clEnumVal(printusedtypes , "Print types used by module"),
  clEnumVal(unsafepointertypes, "Print unsafe pointer types"),

  clEnumVal(domset         , "Print Dominator Sets"),
  clEnumVal(idom           , "Print Immediate Dominators"),
  clEnumVal(domtree        , "Print Dominator Tree"),
  clEnumVal(domfrontier    , "Print Dominance Frontier"),

  clEnumVal(postdomset     , "Print Postdominator Sets"),
  clEnumVal(postidom       , "Print Immediate Postdominators"),
  clEnumVal(postdomtree    , "Print Post Dominator Tree"),
  clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
0);

struct {
  enum Ans AnID;
  Pass *(*PassConstructor)(const string &Message);
} AnTable[] = {
  // Global analyses
  { print             , NewPrintFunction                        },
  { intervals         , New<FunctionPass, IntervalPartition>    },
  { loops             , New<FunctionPass, LoopInfo>             },
  { instforest        , Create<PrinterPass<InstForest> >        },
  { indvars           , Create<PrinterPass<IndVars> >           },
  { exprs             , Create<PrinterPass<Exprs> >             },

  // IP Analyses...
  { printmodule       , NewPrintModule                    },
  { printusedtypes    , New<Pass, FindUsedTypes>          },
  { callgraph         , New<Pass, CallGraph>              },
  { datastructure     , New<Pass, DataStructure>          },
  { unsafepointertypes, New<Pass, FindUnsafePointerTypes> },

  // Dominator analyses
  { domset            , New<FunctionPass, DominatorSet>        },
  { idom              , New<FunctionPass, ImmediateDominators> },
  { domtree           , New<FunctionPass, DominatorTree>       },
  { domfrontier       , New<FunctionPass, DominanceFrontier>   },

  { postdomset        , New<FunctionPass, DominatorSet, DominatorSet::PostDomID> },
  { postidom          , New<FunctionPass, ImmediateDominators, ImmediateDominators::PostDomID> },
  { postdomtree       , New<FunctionPass, DominatorTree, DominatorTree::PostDomID> },
  { postdomfrontier   , New<FunctionPass, DominanceFrontier, DominanceFrontier::PostDomID> },
};

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");

  Module *CurMod = 0;
  try {
    CurMod = ParseBytecodeFile(InputFilename);
    if (!CurMod && !(CurMod = ParseAssemblyFile(InputFilename))){
      std::cerr << "Input file didn't read correctly.\n";
      return 1;
    }
  } catch (const ParseException &E) {
    std::cerr << E.getMessage() << "\n";
    return 1;
  }

  // Create a PassManager to hold and optimize the collection of passes we are
  // about to build...
  //
  PassManager Analyses;

  // Loop over all of the analyses looking for analyses to run...
  for (unsigned i = 0; i < AnalysesList.size(); ++i) {
    enum Ans AnalysisPass = AnalysesList[i];

    for (unsigned j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) {
      if (AnTable[j].AnID == AnalysisPass) {
        string Message;
        if (!Quiet)
          Message = "\nRunning: '" +
            string(AnalysesList.getArgDescription(AnalysisPass)) + "' analysis";
        Analyses.add(AnTable[j].PassConstructor(Message));
        break;                       // get an error later
      }
    }
  }

  Analyses.run(CurMod);

  delete CurMod;
  return 0;
}
<commit_msg>Rename functions to be more consistend with other pass constructors<commit_after>//===----------------------------------------------------------------------===//
// The LLVM analyze utility
//
// This utility is designed to print out the results of running various analysis
// passes on a program.  This is useful for understanding a program, or for
// debugging an analysis pass.
//
//  analyze --help           - Output information about command line switches
//  analyze --quiet          - Do not print analysis name before output
//
//===----------------------------------------------------------------------===//

#include "llvm/Instruction.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/iPHINode.h"
#include "llvm/Type.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/Writer.h"
#include "llvm/Analysis/InstForest.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/IntervalPartition.h"
#include "llvm/Analysis/Expressions.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/FindUnsafePointerTypes.h"
#include "llvm/Analysis/FindUsedTypes.h"
#include "llvm/Support/InstIterator.h"
#include "Support/CommandLine.h"
#include <algorithm>
#include <iostream>

using std::ostream;
using std::string;

//===----------------------------------------------------------------------===//
// printPass - Specify how to print out a pass.  For most passes, the standard
// way of using operator<< works great, so we use it directly...
//
template<class PassType>
static void printPass(PassType &P, ostream &O, Module *M) {
  O << P;
}

template<class PassType>
static void printPass(PassType &P, ostream &O, Function *F) {
  O << P;
}

// Other classes require more information to print out information, so we
// specialize the template here for them...
//
template<>
static void printPass(DataStructure &P, ostream &O, Module *M) {
  P.print(O, M);
}

template<>
static void printPass(FindUsedTypes &FUT, ostream &O, Module *M) {
  FUT.printTypes(O, M);
}

template<>
static void printPass(FindUnsafePointerTypes &FUPT, ostream &O,
                      Module *M) {
  FUPT.printResults(M, O);
}

template <class PassType, class PassName>
class PassPrinter;  // Do not implement

template <class PassName>
class PassPrinter<Pass, PassName> : public Pass {
  const string Message;
  const AnalysisID ID;
public:
  PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}

  virtual bool run(Module *M) {
    std::cout << Message << "\n";
    printPass(getAnalysis<PassName>(ID), std::cout, M);
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(ID);
  }
};

template <class PassName>
class PassPrinter<FunctionPass, PassName> : public FunctionPass {
  const string Message;
  const AnalysisID ID;
public:
  PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}

  virtual bool runOnFunction(Function *F) {
    std::cout << Message << " on function '" << F->getName() << "'\n";
    printPass(getAnalysis<PassName>(ID), std::cout, F);
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(ID);
    AU.setPreservesAll();
  }
};

template <class PassType, class PassName, AnalysisID &ID>
Pass *New(const string &Message) {
  return new PassPrinter<PassType, PassName>(Message, ID);
}
template <class PassType, class PassName>
Pass *New(const string &Message) {
  return new PassPrinter<PassType, PassName>(Message, PassName::ID);
}

Pass *createPrintFunctionPass(const string &Message) {
  return new PrintFunctionPass(Message, &std::cout);
}
Pass *createPrintModulePass(const string &Message) {
  return new PrintModulePass(&std::cout);
}

struct InstForest : public FunctionPass {
  void doit(Function *F) {
    std::cout << analysis::InstForest<char>(F);
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};

struct IndVars : public FunctionPass {
  void doit(Function *F) {
    LoopInfo &LI = getAnalysis<LoopInfo>();
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
      if (PHINode *PN = dyn_cast<PHINode>(*I)) {
        InductionVariable IV(PN, &LI);
        if (IV.InductionType != InductionVariable::Unknown)
          std::cout << IV;
      }
  }

  void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(LoopInfo::ID);
    AU.setPreservesAll();
  }
};

struct Exprs : public FunctionPass {
  static void doit(Function *F) {
    std::cout << "Classified expressions for: " << F->getName() << "\n";
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
      std::cout << *I;

      if ((*I)->getType() == Type::VoidTy) continue;
      analysis::ExprType R = analysis::ClassifyExpression(*I);
      if (R.Var == *I) continue;  // Doesn't tell us anything

      std::cout << "\t\tExpr =";
      switch (R.ExprTy) {
      case analysis::ExprType::ScaledLinear:
        WriteAsOperand(std::cout << "(", (Value*)R.Scale) << " ) *";
        // fall through
      case analysis::ExprType::Linear:
        WriteAsOperand(std::cout << "(", R.Var) << " )";
        if (R.Offset == 0) break;
        else std::cout << " +";
        // fall through
      case analysis::ExprType::Constant:
        if (R.Offset) WriteAsOperand(std::cout, (Value*)R.Offset);
        else std::cout << " 0";
        break;
      }
      std::cout << "\n\n";
    }
  }
  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};

template<class TraitClass>
class PrinterPass : public TraitClass {
  const string Message;
public:
  PrinterPass(const string &M) : Message(M) {}

  virtual bool runOnFunction(Function *F) {
    std::cout << Message << " on function '" << F->getName() << "'\n";

    TraitClass::doit(F);
    return false;
  }
};

template<class PassClass>
Pass *Create(const string &Message) {
  return new PassClass(Message);
}

enum Ans {
  // global analyses
  print, intervals, exprs, instforest, loops, indvars,

  // ip analyses
  printmodule, callgraph, datastructure, printusedtypes, unsafepointertypes,

  domset, idom, domtree, domfrontier,
  postdomset, postidom, postdomtree, postdomfrontier,
};

cl::String InputFilename ("", "Load <arg> file to analyze", cl::NoFlags, "-");
cl::Flag   Quiet         ("q", "Don't print analysis pass names");
cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
  clEnumVal(print          , "Print each function"),
  clEnumVal(intervals      , "Print Interval Partitions"),
  clEnumVal(exprs          , "Classify Expressions"),
  clEnumVal(instforest     , "Print Instruction Forest"),
  clEnumVal(loops          , "Print natural loops"),
  clEnumVal(indvars        , "Print Induction Variables"),

  clEnumVal(printmodule    , "Print entire module"),
  clEnumVal(callgraph      , "Print Call Graph"),
  clEnumVal(datastructure  , "Print data structure information"),
  clEnumVal(printusedtypes , "Print types used by module"),
  clEnumVal(unsafepointertypes, "Print unsafe pointer types"),

  clEnumVal(domset         , "Print Dominator Sets"),
  clEnumVal(idom           , "Print Immediate Dominators"),
  clEnumVal(domtree        , "Print Dominator Tree"),
  clEnumVal(domfrontier    , "Print Dominance Frontier"),

  clEnumVal(postdomset     , "Print Postdominator Sets"),
  clEnumVal(postidom       , "Print Immediate Postdominators"),
  clEnumVal(postdomtree    , "Print Post Dominator Tree"),
  clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
0);

struct {
  enum Ans AnID;
  Pass *(*PassConstructor)(const string &Message);
} AnTable[] = {
  // Global analyses
  { print             , createPrintFunctionPass                 },
  { intervals         , New<FunctionPass, IntervalPartition>    },
  { loops             , New<FunctionPass, LoopInfo>             },
  { instforest        , Create<PrinterPass<InstForest> >        },
  { indvars           , Create<PrinterPass<IndVars> >           },
  { exprs             , Create<PrinterPass<Exprs> >             },

  // IP Analyses...
  { printmodule       , createPrintModulePass            },
  { printusedtypes    , New<Pass, FindUsedTypes>          },
  { callgraph         , New<Pass, CallGraph>              },
  { datastructure     , New<Pass, DataStructure>          },
  { unsafepointertypes, New<Pass, FindUnsafePointerTypes> },

  // Dominator analyses
  { domset            , New<FunctionPass, DominatorSet>        },
  { idom              , New<FunctionPass, ImmediateDominators> },
  { domtree           , New<FunctionPass, DominatorTree>       },
  { domfrontier       , New<FunctionPass, DominanceFrontier>   },

  { postdomset        , New<FunctionPass, DominatorSet, DominatorSet::PostDomID> },
  { postidom          , New<FunctionPass, ImmediateDominators, ImmediateDominators::PostDomID> },
  { postdomtree       , New<FunctionPass, DominatorTree, DominatorTree::PostDomID> },
  { postdomfrontier   , New<FunctionPass, DominanceFrontier, DominanceFrontier::PostDomID> },
};

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");

  Module *CurMod = 0;
  try {
    CurMod = ParseBytecodeFile(InputFilename);
    if (!CurMod && !(CurMod = ParseAssemblyFile(InputFilename))){
      std::cerr << "Input file didn't read correctly.\n";
      return 1;
    }
  } catch (const ParseException &E) {
    std::cerr << E.getMessage() << "\n";
    return 1;
  }

  // Create a PassManager to hold and optimize the collection of passes we are
  // about to build...
  //
  PassManager Analyses;

  // Loop over all of the analyses looking for analyses to run...
  for (unsigned i = 0; i < AnalysesList.size(); ++i) {
    enum Ans AnalysisPass = AnalysesList[i];

    for (unsigned j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) {
      if (AnTable[j].AnID == AnalysisPass) {
        string Message;
        if (!Quiet)
          Message = "\nRunning: '" +
            string(AnalysesList.getArgDescription(AnalysisPass)) + "' analysis";
        Analyses.add(AnTable[j].PassConstructor(Message));
        break;                       // get an error later
      }
    }
  }

  Analyses.run(CurMod);

  delete CurMod;
  return 0;
}
<|endoftext|>


<commit_before>#include "multiverse.h"
#include "game_window.h"
#include "cosmos.h"
#include "game/types_specification/all_component_includes.h"

multiverse::multiverse()
	: main_cosmos_timer(60, 5)
{
	main_cosmos = cosmos();
	main_cosmos.reserve_storage_for_entities(50000);

	main_cosmos.advance_deterministic_schemata(cosmic_entropy(), [this](fixed_step& step) {
		main_cosmos_manager.populate_world_with_entities(step);
	});
}

void multiverse::control(augs::machine_entropy entropy) {
	main_cosmos_player.buffer_entropy_for_next_step(entropy);

	for (auto& raw_input : entropy.local) {
		if (raw_input.key_event == window::event::PRESSED) {
			if (raw_input.key == window::event::keys::_1) {
				main_cosmos_timer = augs::fixed_delta_timer(60, 500000);
			}
			if (raw_input.key == window::event::keys::_2) {
				main_cosmos_timer = augs::fixed_delta_timer(128, 500000);
			}
			if (raw_input.key == window::event::keys::_3) {
				main_cosmos_timer = augs::fixed_delta_timer(400, 500000);
			}
			if (raw_input.key == window::event::keys::_4) {
				stepping_speed = 0.1f;
			}
			if (raw_input.key == window::event::keys::_5) {
				stepping_speed = 1.f;
			}
			if (raw_input.key == window::event::keys::_6) {
				stepping_speed = 6.f;
			}
			if (raw_input.key == window::event::keys::F4) {
				LOG_COLOR(console_color::YELLOW, "Separator");
			}
		}
	}

	main_cosmos_timer.set_stepping_speed_multiplier(stepping_speed);
}

void multiverse::simulate() {
	auto steps_to_perform = main_cosmos_timer.count_logic_steps_to_perform();

	while (steps_to_perform--) {
		auto machine_entropy_for_this_step = main_cosmos_player.obtain_machine_entropy_for_next_step();
		auto cosmic_entropy_for_this_step = main_cosmos_manager.make_cosmic_entropy(machine_entropy_for_this_step, main_cosmos);

		renderer::get_current().clear_logic_lines();

		main_cosmos.delta = main_cosmos_timer.get_fixed_delta();

		main_cosmos.advance_deterministic_schemata(cosmic_entropy_for_this_step,
			[this](fixed_step& step) { main_cosmos_manager.pre_solve(step); },
			[this](fixed_step& step) { main_cosmos_manager.post_solve(step); }
		);

		main_cosmos_timer.increment_total_steps_passed();
	}
}

void multiverse::view(game_window& window) const {
	frame_profiler.fps_counter.new_measurement();

	auto& target = renderer::get_current();

	target.clear_current_fbo();

	target.set_viewport({0, 0, main_cosmos.settings.screen_size.x, main_cosmos.settings.screen_size.y });

	basic_viewing_step main_cosmos_viewing_step(main_cosmos, frame_timer.extract_variable_delta(main_cosmos_timer), target);
	main_cosmos_manager.view_cosmos(main_cosmos_viewing_step);

	frame_profiler.triangles.measure(target.triangles_drawn_total);
	target.triangles_drawn_total = 0;

	window.window.swap_buffers();

	frame_profiler.fps_counter.end_measurement();
}<commit_msg>removed unnecessary cosmic assignment<commit_after>#include "multiverse.h"
#include "game_window.h"
#include "cosmos.h"
#include "game/types_specification/all_component_includes.h"

multiverse::multiverse()
	: main_cosmos_timer(60, 5)
{
	main_cosmos.reserve_storage_for_entities(50000);

	main_cosmos.advance_deterministic_schemata(cosmic_entropy(), [this](fixed_step& step) {
		main_cosmos_manager.populate_world_with_entities(step);
	});
}

void multiverse::control(augs::machine_entropy entropy) {
	main_cosmos_player.buffer_entropy_for_next_step(entropy);

	for (auto& raw_input : entropy.local) {
		if (raw_input.key_event == window::event::PRESSED) {
			if (raw_input.key == window::event::keys::_1) {
				main_cosmos_timer = augs::fixed_delta_timer(60, 500000);
			}
			if (raw_input.key == window::event::keys::_2) {
				main_cosmos_timer = augs::fixed_delta_timer(128, 500000);
			}
			if (raw_input.key == window::event::keys::_3) {
				main_cosmos_timer = augs::fixed_delta_timer(400, 500000);
			}
			if (raw_input.key == window::event::keys::_4) {
				stepping_speed = 0.1f;
			}
			if (raw_input.key == window::event::keys::_5) {
				stepping_speed = 1.f;
			}
			if (raw_input.key == window::event::keys::_6) {
				stepping_speed = 6.f;
			}
			if (raw_input.key == window::event::keys::F4) {
				LOG_COLOR(console_color::YELLOW, "Separator");
			}
		}
	}

	main_cosmos_timer.set_stepping_speed_multiplier(stepping_speed);
}

void multiverse::simulate() {
	auto steps_to_perform = main_cosmos_timer.count_logic_steps_to_perform();

	while (steps_to_perform--) {
		auto machine_entropy_for_this_step = main_cosmos_player.obtain_machine_entropy_for_next_step();
		auto cosmic_entropy_for_this_step = main_cosmos_manager.make_cosmic_entropy(machine_entropy_for_this_step, main_cosmos);

		renderer::get_current().clear_logic_lines();

		main_cosmos.delta = main_cosmos_timer.get_fixed_delta();

		main_cosmos.advance_deterministic_schemata(cosmic_entropy_for_this_step,
			[this](fixed_step& step) { main_cosmos_manager.pre_solve(step); },
			[this](fixed_step& step) { main_cosmos_manager.post_solve(step); }
		);

		main_cosmos_timer.increment_total_steps_passed();
	}
}

void multiverse::view(game_window& window) const {
	frame_profiler.fps_counter.new_measurement();

	auto& target = renderer::get_current();

	target.clear_current_fbo();

	target.set_viewport({0, 0, main_cosmos.settings.screen_size.x, main_cosmos.settings.screen_size.y });

	basic_viewing_step main_cosmos_viewing_step(main_cosmos, frame_timer.extract_variable_delta(main_cosmos_timer), target);
	main_cosmos_manager.view_cosmos(main_cosmos_viewing_step);

	frame_profiler.triangles.measure(target.triangles_drawn_total);
	target.triangles_drawn_total = 0;

	window.window.swap_buffers();

	frame_profiler.fps_counter.end_measurement();
}<|endoftext|>


<commit_before>// Copyright 2019 The TCMalloc 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
//
//     https://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.
//
// Test out of memory handling.  Kept in a separate test since running out
// of memory causes other parts of the runtime to behave improperly.

#include <stddef.h>
#include <stdlib.h>

#include <new>

#include "gtest/gtest.h"
#include "tcmalloc/internal/config.h"
#include "tcmalloc/internal/linked_list.h"
#include "tcmalloc/testing/testutil.h"

namespace tcmalloc {
namespace {

class OutOfMemoryTest : public ::testing::Test {
 public:
  OutOfMemoryTest() { SetTestResourceLimit(); }
};

TEST_F(OutOfMemoryTest, TestUntilFailure) {
  // Check that large allocations fail with NULL instead of crashing.
  static const size_t kIncrement = 100 << 20;
  static const size_t kMaxSize = ~static_cast<size_t>(0);
  for (size_t s = kIncrement; s < kMaxSize - kIncrement; s += kIncrement) {
    SCOPED_TRACE(s);
    void* large_object = ::operator new(s, std::nothrow);
    if (large_object == nullptr) {
      return;
    }
    ::operator delete(large_object);
  }
  ASSERT_TRUE(false) << "Did not run out of memory";
}

TEST_F(OutOfMemoryTest, SmallAllocs) {
  // Check that large allocations fail with NULL instead of crashing.
  static constexpr size_t kSize = tcmalloc_internal::kHugePageSize / 2 - 1;
  void* list = nullptr;
  bool found = false;

  for (int i = 0; i < 8000; i++) {
    void* obj = ::operator new(kSize, std::nothrow);
    if (obj == nullptr) {
      found = true;
      break;
    }

    tcmalloc_internal::SLL_Push(&list, obj);
  }

  // Cleanup
  while (list != nullptr) {
    void* obj = tcmalloc_internal::SLL_Pop(&list);
    operator delete(obj);
  }

  ASSERT_TRUE(found) << "Did not run out of memory";
}

}  // namespace
}  // namespace tcmalloc
<commit_msg>Fix a flakiness issue in outofmemory_test caused by running out of memory while sampling an allocation.<commit_after>// Copyright 2019 The TCMalloc 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
//
//     https://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.
//
// Test out of memory handling.  Kept in a separate test since running out
// of memory causes other parts of the runtime to behave improperly.

#include <stddef.h>
#include <stdlib.h>

#include <new>

#include "gtest/gtest.h"
#include "tcmalloc/internal/config.h"
#include "tcmalloc/internal/linked_list.h"
#include "tcmalloc/testing/testutil.h"

namespace tcmalloc {
namespace {

class OutOfMemoryTest : public ::testing::Test {
 public:
  OutOfMemoryTest() { SetTestResourceLimit(); }
};

TEST_F(OutOfMemoryTest, TestUntilFailure) {
  // Disable sampling.
  ScopedGuardedSamplingRate gs(-1);
  ScopedProfileSamplingRate s(1);

  // Check that large allocations fail with NULL instead of crashing.
  static const size_t kIncrement = 100 << 20;
  static const size_t kMaxSize = ~static_cast<size_t>(0);
  for (size_t s = kIncrement; s < kMaxSize - kIncrement; s += kIncrement) {
    SCOPED_TRACE(s);
    void* large_object = ::operator new(s, std::nothrow);
    if (large_object == nullptr) {
      return;
    }
    ::operator delete(large_object);
  }
  ASSERT_TRUE(false) << "Did not run out of memory";
}

TEST_F(OutOfMemoryTest, SmallAllocs) {
  // Disable sampling.
  ScopedGuardedSamplingRate gs(-1);
  ScopedProfileSamplingRate s(1);

  // Check that large allocations fail with NULL instead of crashing.
  static constexpr size_t kSize = tcmalloc_internal::kHugePageSize / 2 - 1;
  void* list = nullptr;
  bool found = false;

  for (int i = 0; i < 8000; i++) {
    void* obj = ::operator new(kSize, std::nothrow);
    if (obj == nullptr) {
      found = true;
      break;
    }

    tcmalloc_internal::SLL_Push(&list, obj);
  }

  // Cleanup
  while (list != nullptr) {
    void* obj = tcmalloc_internal::SLL_Pop(&list);
    operator delete(obj);
  }

  ASSERT_TRUE(found) << "Did not run out of memory";
}

}  // namespace
}  // namespace tcmalloc
<|endoftext|>


<commit_before>#include "InstructionLexer.hpp"

#include <functional>
#include <iostream>
#include <regex>
#include <utility>
#include <vector>

#include "boost/range/algorithm.hpp"
#include "boost/tokenizer.hpp"

Tokens InstructionLexer::parseInstructions(const std::string& input)
{
    boost::tokenizer<boost::char_separator<char>> lineTokenizer{
        input, boost::char_separator<char>{"\n"}};
    Tokens tokens;
    for (const auto& line : lineTokenizer)
    {
        if (line.at(0) != ' ')
        {
            throw UnknownInstruction("Invalid line: " + line);
        }
        boost::copy(parseLine(line), std::back_inserter(tokens));
    }
    return tokens;
}

Tokens InstructionLexer::parseLine(const std::string& line)
{
    boost::tokenizer<boost::char_separator<char>> instructionTokenizer{
        line, boost::char_separator<char>{", "}};
    Tokens tokens;
    for (const auto& token : instructionTokenizer)
    {
        boost::copy(parseInstruction(token), std::back_inserter(tokens));
    }
    return tokens;
}

const auto alwaysZeroValue = [](const std::string&) -> Token::ValueType {
    return 0;
};

const auto convertToUnsigned = [](const std::string& text) -> Token::ValueType {
    try
    {
        return std::stoi(text);
    }
    catch (const std::exception&)
    {
        return 0;
    }
};

Tokens InstructionLexer::parseInstruction(const std::string& instruction)
{
    const auto trimmedInstruction = trimWhitespacesOnFront(instruction);
    if (trimmedInstruction.empty())
    {
        return {};
    }
    using TextToTokens = std::vector<
        std::tuple<std::regex, TokenType,
                   std::function<Token::ValueType(const std::string&)>>>;
    const TextToTokens acceptableInstructions{
        {std::regex{"out"}, TokenType::Out, alwaysZeroValue},
        {std::regex{"\\(0\\)"}, TokenType::ZeroWithBrackets, alwaysZeroValue},
        {std::regex{"ld"}, TokenType::Ld, alwaysZeroValue},
        {std::regex{"a"}, TokenType::A, alwaysZeroValue},
        {std::regex{"[0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]"},
         TokenType::Number8Bit, convertToUnsigned}};
    const auto noArgumentInstructionPosition = std::find_if(
        acceptableInstructions.begin(), acceptableInstructions.end(),
        [&](const auto& tokenMap) {
            return std::regex_match(trimmedInstruction, std::get<0>(tokenMap));
        });
    if (noArgumentInstructionPosition != acceptableInstructions.end())
    {
        return {
            {std::get<1>(*noArgumentInstructionPosition),
             std::get<2>(*noArgumentInstructionPosition)(trimmedInstruction)}};
    }
    throw UnknownInstruction{"Unknown instruction: " + instruction};
}

std::string
InstructionLexer::trimWhitespacesOnFront(const std::string& instruction)
{
    const auto firstRelevantCharPosition = instruction.find_first_not_of(" \t");
    if (firstRelevantCharPosition != std::string::npos)
    {
        return instruction.substr(firstRelevantCharPosition);
    }
    return {};
}
<commit_msg>Address review issues<commit_after>#include "InstructionLexer.hpp"

#include <functional>
#include <iostream>
#include <regex>
#include <utility>
#include <vector>

#include "boost/algorithm/string/trim.hpp"

#include "boost/range/algorithm.hpp"
#include "boost/tokenizer.hpp"

Tokens InstructionLexer::parseInstructions(const std::string& input)
{
    boost::tokenizer<boost::char_separator<char>> lineTokenizer{
        input, boost::char_separator<char>{"\n"}};
    Tokens tokens;
    for (const auto& line : lineTokenizer)
    {
        if (line.at(0) != ' ')
        {
            throw UnknownInstruction("Invalid line: " + line);
        }
        boost::copy(parseLine(line), std::back_inserter(tokens));
    }
    return tokens;
}

Tokens InstructionLexer::parseLine(const std::string& line)
{
    boost::tokenizer<boost::char_separator<char>> instructionTokenizer{
        line, boost::char_separator<char>{", "}};
    Tokens tokens;
    for (const auto& token : instructionTokenizer)
    {
        boost::copy(parseInstruction(token), std::back_inserter(tokens));
    }
    return tokens;
}

const auto alwaysZeroValue = [](const std::string&) -> Token::ValueType {
    return 0;
};

const auto convertToUnsigned = [](const std::string& text) -> Token::ValueType {
    return std::stoi(text);
};

Tokens InstructionLexer::parseInstruction(const std::string& instruction)
{
    const auto trimmedInstruction = trimWhitespacesOnFront(instruction);
    if (trimmedInstruction.empty())
    {
        return {};
    }
    using TextToTokens = std::vector<
        std::tuple<std::regex, TokenType,
                   std::function<Token::ValueType(const std::string&)>>>;
    const TextToTokens acceptableInstructions{
        {std::regex{"out"}, TokenType::Out, alwaysZeroValue},
        {std::regex{"\\(0\\)"}, TokenType::ZeroWithBrackets, alwaysZeroValue},
        {std::regex{"ld"}, TokenType::Ld, alwaysZeroValue},
        {std::regex{"a"}, TokenType::A, alwaysZeroValue},
        {std::regex{"[0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]"},
         TokenType::Number8Bit, convertToUnsigned}};
    const auto noArgumentInstructionPosition = std::find_if(
        acceptableInstructions.begin(), acceptableInstructions.end(),
        [&](const auto& tokenMap) {
            return std::regex_match(trimmedInstruction, std::get<0>(tokenMap));
        });
    if (noArgumentInstructionPosition != acceptableInstructions.end())
    {
        return {
            {std::get<1>(*noArgumentInstructionPosition),
             std::get<2>(*noArgumentInstructionPosition)(trimmedInstruction)}};
    }
    throw UnknownInstruction{"Unknown instruction: " + instruction};
}

std::string
InstructionLexer::trimWhitespacesOnFront(const std::string& instruction)
{
    return boost::algorithm::trim_left_copy_if(instruction, [](auto character) {
        return character == ' ' || character == '\t';
    });
}
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <cstring>

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class T> struct UnaryAction {
  Handle<Value> apply(Buffer& buffer, const Arguments& args);

  Handle<Value> operator()(const Arguments& args) {
    if (args[0]->IsObject()) {
      Local<Object> object = args[0]->ToObject();
      if (Buffer::HasInstance(object)) {
        Buffer& buffer = *ObjectWrap::Unwrap<Buffer>(object);
        return static_cast<T*>(this)->apply(buffer, args);
      }
    }
    static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First argument should be a buffer."));
    return ThrowException(Exception::TypeError(illegalArgumentException));
  }
};

template <class T> struct BinaryAction {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args);

  Handle<Value> operator()(const Arguments& args) {
    if (args[0]->IsObject() && args[1]->IsObject()) {
      Local<Object> arg0 = args[0]->ToObject();
      Local<Object> arg1 = args[0]->ToObject();
      if (Buffer::HasInstance(arg0) && Buffer::HasInstance(arg1)) {
        Buffer& a = *ObjectWrap::Unwrap<Buffer>(arg0);
        Buffer& b = *ObjectWrap::Unwrap<Buffer>(arg1);
        return static_cast<T*>(this)->apply(a, b, args);
      }
    }
    static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First and second argument should be a buffer."));
    return ThrowException(Exception::TypeError(illegalArgumentException));
  }
};

//
// helper functions
//
Handle<Value> clear(Buffer& buffer, int c) {
  memset(buffer.data(), c, buffer.length());
  return buffer.handle_;
}

Handle<Value> fill(Buffer& buffer, void* pattern, size_t size) {
  if (size >= buffer.length()) {
    memcpy(buffer.data(), pattern, buffer.length());
  } else {
    const int n_copies = buffer.length() / size;
    const int remainder = buffer.length() % size;
    for (int i = 0; i < n_copies; i++) {
      memcpy(buffer.data() + size * i, pattern, size);
    }
    memcpy(buffer.data() + size * n_copies, pattern, remainder);
  }
  return buffer.handle_;
}

int compare(Buffer& a, Buffer& b) {
  if (a.length() != b.length()) {
    return a.length() > b.length() ? 1 : -1;
  }
  return memcmp(a.data(), b.data(), a.length());
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
  Handle<Value> apply(Buffer& buffer, const Arguments& args) {
    const int c = args[1]->IsInt32() ? args[1]->ToInt32()->Int32Value() : 0;
    return clear(buffer, c);
  }
};

struct FillAction: UnaryAction<FillAction> {
  Handle<Value> apply(Buffer& buffer, const Arguments& args) {
    if (args[1]->IsInt32()) {
      int c = args[1]->ToInt32()->Int32Value();
      return clear(buffer, c);
    }
    if (args[1]->IsString()) {
      String::AsciiValue s(args[1]->ToString());
      return fill(buffer, *s, s.length());
    }
    if (args[1]->IsObject()) {
      Local<Object> o = args[1]->ToObject();
      if (Buffer::HasInstance(o)) {
        Buffer& src = *Buffer::Unwrap<Buffer>(o);
        return fill(buffer, src.data(), src.length());
      }
    }
    static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
        "Second argument should be either a string, a buffer or an integer."));
    return ThrowException(Exception::TypeError(illegalArgumentException));
  }
};

struct EqualsAction: BinaryAction<EqualsAction> {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
    HandleScope scope;
    return scope.Close(Boolean::New(compare(a, b)));
  }
};

struct CompareAction: BinaryAction<CompareAction> {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
    HandleScope scope;
    return scope.Close(Integer::New(compare(a, b)));
  }
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
  return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
  return FillAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
  return CompareAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
  return CompareAction()(args);
}

extern "C" void init(Handle<Object> target) {
  HandleScope scope;
  target->Set(String::New("fill"), FunctionTemplate::New(Fill)->GetFunction());
  target->Set(String::New("clear"), FunctionTemplate::New(Clear)->GetFunction());
  target->Set(String::New("equals"), FunctionTemplate::New(Equals)->GetFunction());
  target->Set(String::New("compare"), FunctionTemplate::New(Compare)->GetFunction());
}

}
<commit_msg>Fix indentation. It's fine and dandy that the nodejs source uses two spaces but tabs are just easier to read.<commit_after>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <cstring>

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class T> struct UnaryAction {
	Handle<Value> apply(Buffer& buffer, const Arguments& args);

	Handle<Value> operator()(const Arguments& args) {
		if (args[0]->IsObject()) {
			Local<Object> object = args[0]->ToObject();
			if (Buffer::HasInstance(object)) {
				Buffer& buffer = *ObjectWrap::Unwrap<Buffer>(object);
				return static_cast<T*>(this)->apply(buffer, args);
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First argument should be a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

template <class T> struct BinaryAction {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args);

	Handle<Value> operator()(const Arguments& args) {
		if (args[0]->IsObject() && args[1]->IsObject()) {
			Local<Object> arg0 = args[0]->ToObject();
			Local<Object> arg1 = args[0]->ToObject();
			if (Buffer::HasInstance(arg0) && Buffer::HasInstance(arg1)) {
				Buffer& a = *ObjectWrap::Unwrap<Buffer>(arg0);
				Buffer& b = *ObjectWrap::Unwrap<Buffer>(arg1);
				return static_cast<T*>(this)->apply(a, b, args);
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First and second argument should be a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

//
// helper functions
//
Handle<Value> clear(Buffer& buffer, int c) {
	memset(buffer.data(), c, buffer.length());
	return buffer.handle_;
}

Handle<Value> fill(Buffer& buffer, void* pattern, size_t size) {
	if (size >= buffer.length()) {
		memcpy(buffer.data(), pattern, buffer.length());
	} else {
		const int n_copies = buffer.length() / size;
		const int remainder = buffer.length() % size;
		for (int i = 0; i < n_copies; i++) {
			memcpy(buffer.data() + size * i, pattern, size);
		}
		memcpy(buffer.data() + size * n_copies, pattern, remainder);
	}
	return buffer.handle_;
}

int compare(Buffer& a, Buffer& b) {
	if (a.length() != b.length()) {
		return a.length() > b.length() ? 1 : -1;
	}
	return memcmp(a.data(), b.data(), a.length());
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
	Handle<Value> apply(Buffer& buffer, const Arguments& args) {
		const int c = args[1]->IsInt32() ? args[1]->ToInt32()->Int32Value() : 0;
		return clear(buffer, c);
	}
};

struct FillAction: UnaryAction<FillAction> {
	Handle<Value> apply(Buffer& buffer, const Arguments& args) {
		if (args[1]->IsInt32()) {
			int c = args[1]->ToInt32()->Int32Value();
			return clear(buffer, c);
		}
		if (args[1]->IsString()) {
			String::AsciiValue s(args[1]->ToString());
			return fill(buffer, *s, s.length());
		}
		if (args[1]->IsObject()) {
			Local<Object> o = args[1]->ToObject();
			if (Buffer::HasInstance(o)) {
				Buffer& src = *Buffer::Unwrap<Buffer>(o);
				return fill(buffer, src.data(), src.length());
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument should be either a string, a buffer or an integer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

struct EqualsAction: BinaryAction<EqualsAction> {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
		HandleScope scope;
		return scope.Close(Boolean::New(compare(a, b)));
	}
};

struct CompareAction: BinaryAction<CompareAction> {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
		HandleScope scope;
		return scope.Close(Integer::New(compare(a, b)));
	}
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
	return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
	return FillAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
	return CompareAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
	return CompareAction()(args);
}

extern "C" void init(Handle<Object> target) {
	HandleScope scope;
	target->Set(String::New("fill"), FunctionTemplate::New(Fill)->GetFunction());
	target->Set(String::New("clear"), FunctionTemplate::New(Clear)->GetFunction());
	target->Set(String::New("equals"), FunctionTemplate::New(Equals)->GetFunction());
	target->Set(String::New("compare"), FunctionTemplate::New(Compare)->GetFunction());
}

}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    <sys/types.h>
#include    <sys/stat.h>
#include    <fcntl.h>

#if     qPlatform_Windows
#include    <io.h>
#elif   qPlatform_POSIX
#include    <unistd.h>
#endif

#include    "../../Debug/AssertExternallySynchronizedLock.h"
#include    "../../Debug/Trace.h"
#include    "../../Execution/Common.h"
#include    "../../Execution/ErrNoException.h"
#include    "../../Execution/Exceptions.h"
#if     qPlatform_Windows
#include    "../../Execution/Platform/Windows/Exception.h"
#endif
#include    "../../IO/FileAccessException.h"
#include    "../../Streams/BufferedInputStream.h"

#include    "FileInputStream.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::FileSystem;

using   Execution::make_unique_lock;
using   Streams::InputStream;
using   Streams::SeekOffsetType;

#if     qPlatform_Windows
using   Execution::Platform::Windows::ThrowIfFalseGetLastError;
#endif

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 **************************** FileSystem::FileInputStream ***********************
 ********************************************************************************
 */
class   FileInputStream::Rep_ : public InputStream<Byte>::_IRep, private Debug::AssertExternallySynchronizedLock {
public:
    Rep_ () = delete;
    Rep_ (const Rep_&) = delete;
    Rep_ (const String& fileName, SeekableFlag seekable)
        : fFD_ (-1)
        , fSeekable_ (seekable)
    {
        try {
#if     qPlatform_Windows
            errno_t e = ::_wsopen_s (&fFD_, fileName.c_str (), (O_RDONLY | O_BINARY), _SH_DENYNO, 0);
            if (e != 0) {
                Execution::errno_ErrorException::Throw (e);
            }
            ThrowIfFalseGetLastError (fFD_ != -1);
#else
            Execution::ThrowErrNoIfNegative (fFD_ = ::open (fileName.AsNarrowSDKString ().c_str (), O_RDONLY));
#endif
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"opened fd: %d", fFD_);
#endif
        }
        Stroika_Foundation_IO_FileAccessException_CATCH_REBIND_FILENAME_ACCCESS_HELPER(fileName, FileAccessMode::eRead);
    }
    ~Rep_ ()
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::~Rep_");
        DbgTrace (L"closing %d", fFD_);
#endif
#if     qPlatform_Windows
        ::_close (fFD_);
#else
        ::close (fFD_);
#endif
    }
    nonvirtual  Rep_& operator= (const Rep_&) = delete;

    virtual bool    IsSeekable () const override
    {
        return fSeekable_ == eSeekable;
    }
    virtual size_t  Read (Byte* intoStart, Byte* intoEnd) override
    {
        RequireNotNull (intoStart);
        RequireNotNull (intoEnd);
        Require (intoStart < intoEnd);
        size_t  nRequested  =   intoEnd - intoStart;
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::Read");
        DbgTrace (L"(nRequested: %llu)", static_cast<unsigned long long> (nRequested));
#endif
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     qPlatform_Windows
        return static_cast<size_t> (Execution::ThrowErrNoIfNegative (::_read (fFD_, intoStart, Math::PinToMaxForType<unsigned int> (nRequested))));
#else
        return static_cast<size_t> (Execution::ThrowErrNoIfNegative (::read (fFD_, intoStart, nRequested)));
#endif
    }
    virtual Streams::SeekOffsetType  GetReadOffset () const override
    {
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     qPlatform_Windows
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, 0, SEEK_CUR)));
#else
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, 0, SEEK_CUR)));
#endif
    }
    virtual Streams::SeekOffsetType    SeekRead (Streams::Whence whence, Streams::SignedSeekOffsetType offset) override
    {
        using   namespace Streams;
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::SeekRead");
        DbgTrace (L"(whence: %d, offset: %lld)", whence, static_cast<long long> (offset));
#endif
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
        switch (whence) {
            case    Whence::eFromStart: {
                    if (offset < 0) {
                        Execution::Throw (std::range_error ("seek"));
                    }
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_SET)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_SET)));
#endif
                }
                break;
            case    Whence::eFromCurrent: {
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_CUR)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_CUR)));
#endif
                }
                break;
            case    Whence::eFromEnd: {
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_END)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_END)));
#endif
                }
                break;
        }
        RequireNotReached ();
        return 0;
    }

private:
    int             fFD_;
    SeekableFlag    fSeekable_;
};

FileInputStream::FileInputStream (const String& fileName, SeekableFlag seekable)
    : FileInputStream (make_shared<Rep_> (fileName, seekable))
{
}

FileInputStream::FileInputStream (const shared_ptr<Rep_>& rep)
    : inherited (rep)
{
}

InputStream<Byte>   FileInputStream::mk (const String& fileName, SeekableFlag seekable, BufferFlag bufferFlag)
{
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"FileInputStream::mk");
    DbgTrace (L"(fileName: %s, seekable: %d, bufferFlag: %d)", fileName.c_str (), seekable, bufferFlag);
#endif
    InputStream<Byte>   in  =   FileInputStream (fileName, seekable);
    switch (bufferFlag) {
        case eBuffered:
            return Streams::BufferedInputStream<Byte> (in);
        case eUnbuffered:
            return in;
        default:
            AssertNotReached ();
            return in;
    }
}
<commit_msg>more work - lseek64 - on macos / darwin port<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    <sys/types.h>
#include    <sys/stat.h>
#include    <fcntl.h>

#if     qPlatform_Windows
#include    <io.h>
#elif   qPlatform_POSIX
#include    <unistd.h>
#endif

#include    "../../Debug/AssertExternallySynchronizedLock.h"
#include    "../../Debug/Trace.h"
#include    "../../Execution/Common.h"
#include    "../../Execution/ErrNoException.h"
#include    "../../Execution/Exceptions.h"
#if     qPlatform_Windows
#include    "../../Execution/Platform/Windows/Exception.h"
#endif
#include    "../../IO/FileAccessException.h"
#include    "../../Streams/BufferedInputStream.h"

#include    "FileInputStream.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::FileSystem;

using   Execution::make_unique_lock;
using   Streams::InputStream;
using   Streams::SeekOffsetType;

#if     qPlatform_Windows
using   Execution::Platform::Windows::ThrowIfFalseGetLastError;
#endif

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 **************************** FileSystem::FileInputStream ***********************
 ********************************************************************************
 */
class   FileInputStream::Rep_ : public InputStream<Byte>::_IRep, private Debug::AssertExternallySynchronizedLock {
public:
    Rep_ () = delete;
    Rep_ (const Rep_&) = delete;
    Rep_ (const String& fileName, SeekableFlag seekable)
        : fFD_ (-1)
        , fSeekable_ (seekable)
    {
        try {
#if     qPlatform_Windows
            errno_t e = ::_wsopen_s (&fFD_, fileName.c_str (), (O_RDONLY | O_BINARY), _SH_DENYNO, 0);
            if (e != 0) {
                Execution::errno_ErrorException::Throw (e);
            }
            ThrowIfFalseGetLastError (fFD_ != -1);
#else
            Execution::ThrowErrNoIfNegative (fFD_ = ::open (fileName.AsNarrowSDKString ().c_str (), O_RDONLY));
#endif
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"opened fd: %d", fFD_);
#endif
        }
        Stroika_Foundation_IO_FileAccessException_CATCH_REBIND_FILENAME_ACCCESS_HELPER(fileName, FileAccessMode::eRead);
    }
    ~Rep_ ()
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::~Rep_");
        DbgTrace (L"closing %d", fFD_);
#endif
#if     qPlatform_Windows
        ::_close (fFD_);
#else
        ::close (fFD_);
#endif
    }
    nonvirtual  Rep_& operator= (const Rep_&) = delete;

    virtual bool    IsSeekable () const override
    {
        return fSeekable_ == eSeekable;
    }
    virtual size_t  Read (Byte* intoStart, Byte* intoEnd) override
    {
        RequireNotNull (intoStart);
        RequireNotNull (intoEnd);
        Require (intoStart < intoEnd);
        size_t  nRequested  =   intoEnd - intoStart;
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::Read");
        DbgTrace (L"(nRequested: %llu)", static_cast<unsigned long long> (nRequested));
#endif
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     qPlatform_Windows
        return static_cast<size_t> (Execution::ThrowErrNoIfNegative (::_read (fFD_, intoStart, Math::PinToMaxForType<unsigned int> (nRequested))));
#else
        return static_cast<size_t> (Execution::ThrowErrNoIfNegative (::read (fFD_, intoStart, nRequested)));
#endif
    }
    virtual Streams::SeekOffsetType  GetReadOffset () const override
    {
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     qPlatform_Windows
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, 0, SEEK_CUR)));
#elif   qPlatform_Linux
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, 0, SEEK_CUR)));
#else
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, 0, SEEK_CUR)));
#endif
    }
    virtual Streams::SeekOffsetType    SeekRead (Streams::Whence whence, Streams::SignedSeekOffsetType offset) override
    {
        using   namespace Streams;
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::SeekRead");
        DbgTrace (L"(whence: %d, offset: %lld)", whence, static_cast<long long> (offset));
#endif
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
        switch (whence) {
            case    Whence::eFromStart: {
                    if (offset < 0) {
                        Execution::Throw (std::range_error ("seek"));
                    }
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_SET)));
#elif   qPlatform_Linux
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_SET)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, offset, SEEK_SET)));
#endif
                }
                break;
            case    Whence::eFromCurrent: {
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_CUR)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_CUR)));
#endif
                }
                break;
            case    Whence::eFromEnd: {
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_END)));
#elif   qPlatform_Linux
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_END)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, offset, SEEK_END)));
#endif
                }
                break;
        }
        RequireNotReached ();
        return 0;
    }

private:
    int             fFD_;
    SeekableFlag    fSeekable_;
};

FileInputStream::FileInputStream (const String& fileName, SeekableFlag seekable)
    : FileInputStream (make_shared<Rep_> (fileName, seekable))
{
}

FileInputStream::FileInputStream (const shared_ptr<Rep_>& rep)
    : inherited (rep)
{
}

InputStream<Byte>   FileInputStream::mk (const String& fileName, SeekableFlag seekable, BufferFlag bufferFlag)
{
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"FileInputStream::mk");
    DbgTrace (L"(fileName: %s, seekable: %d, bufferFlag: %d)", fileName.c_str (), seekable, bufferFlag);
#endif
    InputStream<Byte>   in  =   FileInputStream (fileName, seekable);
    switch (bufferFlag) {
        case eBuffered:
            return Streams::BufferedInputStream<Byte> (in);
        case eUnbuffered:
            return in;
        default:
            AssertNotReached ();
            return in;
    }
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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 "itkJoinSeriesImageFilter.h"
#include "itkStreamingImageFilter.h"

#include <iostream>

class ShowProgressObject
{
public:
  ShowProgressObject(itk::ProcessObject* o)
    {m_Process = o;}
  void ShowProgress()
    {std::cout << "Progress " << m_Process->GetProgress() << std::endl;}
  itk::ProcessObject::Pointer m_Process;
};

int itkJoinSeriesImageFilterTest(int, char* [] )
{
  // to write informations to "itkMessageLog.txt" when DebugOn()
//   itk::OutputWindow::SetInstance( itk::FileOutputWindow::New() );

  const unsigned int streamDivisions = 2;
  typedef unsigned char                 PixelType;
  typedef itk::Image< PixelType, 2 >    InputImageType;
  // typedef itk::Image< PixelType, 3 > OutputImageType;
  typedef itk::Image< PixelType, 4 > OutputImageType;

  // the expected result
  OutputImageType::IndexType expectedIndex = {{1, 2, 0, 0}};
  OutputImageType::SizeType expectedSize = {{8, 5, 4, 1}};
  OutputImageType::RegionType expectedRegion;
  expectedRegion.SetIndex( expectedIndex );
  expectedRegion.SetSize( expectedSize );
  OutputImageType::SpacingType expectedSpacing;
  expectedSpacing[0] = 1.1;
  expectedSpacing[1] = 1.2;
  expectedSpacing[2] = 1.3;
  expectedSpacing[3] = 1.0;
  OutputImageType::PointType expectedOrigin;
  expectedOrigin[0] = 0.1;
  expectedOrigin[1] = 0.2;
  expectedOrigin[2] = 0.3;
  expectedOrigin[3] = 0.0;

  // make the input images
  int numInputs = 4;
  InputImageType::IndexType index = {{1, 2}};
  InputImageType::SizeType size = {{8, 5}};
  InputImageType::RegionType region;
  region.SetIndex( index );
  region.SetSize( size );
  const double spacingValue = 1.3;
  InputImageType::SpacingType spacing;
  spacing[0] = 1.1;
  spacing[1] = 1.2;
  const double originValue = 0.3;
  InputImageType::PointType origin;
  origin[0] = 0.1;
  origin[1] = 0.2;

  std::vector<InputImageType::Pointer> inputs;

  PixelType counter1 = 0;
  for ( int i = 0; i < numInputs; i++ )
    {
    inputs.push_back( InputImageType::New() );
    inputs[i]->SetLargestPossibleRegion( region );
    inputs[i]->SetBufferedRegion( region );
    inputs[i]->Allocate();

    itk::ImageRegionIterator<InputImageType>
      inputIter( inputs[i], inputs[i]->GetBufferedRegion() );
    while ( !inputIter.IsAtEnd() )
      {
      inputIter.Set( counter1 );
      ++counter1;
      ++inputIter;
      }

    inputs[i]->SetSpacing( spacing );
    inputs[i]->SetOrigin( origin );
//     inputs[i]->DebugOn();
    }

  // create the filter
  typedef itk::JoinSeriesImageFilter< InputImageType, OutputImageType >
    JoinSeriesImageType;
  JoinSeriesImageType::Pointer joinSeriesImage = JoinSeriesImageType::New();

  // check the default values
  if ( joinSeriesImage->GetSpacing() != 1.0 )
    {
    std::cout << "Default spacing is not 1.0" << std::endl;
    return EXIT_FAILURE;
    }
  if ( joinSeriesImage->GetOrigin() != 0.0 )
    {
    std::cout << "Default origin is not 0.0" << std::endl;
    return EXIT_FAILURE;
    }

  // setup the filter
  joinSeriesImage->SetSpacing( spacingValue );
  joinSeriesImage->SetOrigin( originValue );
  for ( int i = 0; i < numInputs; i++ )
    {
    joinSeriesImage->SetInput( i, inputs[i] );
    }

  // to test ProgressReporter
  ShowProgressObject progressWatch( joinSeriesImage );
  typedef itk::SimpleMemberCommand< ShowProgressObject > CommandType;
  CommandType::Pointer command = CommandType::New();
  command->SetCallbackFunction( &progressWatch,
                                &ShowProgressObject::ShowProgress );
  joinSeriesImage->AddObserver( itk::ProgressEvent(), command );

  // to test streaming
  typedef itk::StreamingImageFilter< OutputImageType, OutputImageType >
    StreamingImageType;
  StreamingImageType::Pointer streamingImage = StreamingImageType::New();
  streamingImage->SetInput( joinSeriesImage->GetOutput() );
  streamingImage->SetNumberOfStreamDivisions( streamDivisions );

  // run
  try
    {
    streamingImage->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << err << std::endl;
    //for InvalidRequestedRegionError
    itk::DataObjectError * errp = dynamic_cast<itk::DataObjectError *>( &err );
    if ( errp )
      {
      errp->GetDataObject()->Print( std::cout );
      }
    return EXIT_FAILURE;
    }

  OutputImageType::Pointer output = streamingImage->GetOutput();

  // check the informations
  if ( output->GetLargestPossibleRegion() != expectedRegion )
    {
    std::cout << "LargestPossibleRegion mismatch" << std::endl;
    return EXIT_FAILURE;
    }
  if ( output->GetSpacing() != expectedSpacing )
    {
    std::cout << "Spacing mismatch" << std::endl;
    return EXIT_FAILURE;
    }
  if ( output->GetOrigin() != expectedOrigin )
    {
    std::cout << "Origin mismatch" << std::endl;
    return EXIT_FAILURE;
    }

  // check the contents
  bool passed = true;

  PixelType counter2 = 0;
  itk::ImageRegionIterator<OutputImageType>
    outputIter( output, output->GetBufferedRegion() );
  while ( !outputIter.IsAtEnd() )
    {
    if ( outputIter.Get() != counter2 )
      {
      passed = false;
      std::cout << "Mismatch at index: " << outputIter.GetIndex() << std::endl;
      }
    ++counter2;
    ++outputIter;
    }

  if ( !passed || counter1 != counter2 )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  // An exception is raised when an input is missing.
  passed = false;

  // set the 2nd input null
  joinSeriesImage->SetInput( 1, ITK_NULLPTR );
  try
    {
    joinSeriesImage->Update();
    }
  catch( itk::InvalidRequestedRegionError & err )
    {
    std::cout << err << std::endl;
    passed = true;
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }

  if ( !passed )
    {
    std::cout << "Expected exception is missing" << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;
}
<commit_msg>ENH: Improve itkJoinSeriesImageFilter coverage.<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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 "itkJoinSeriesImageFilter.h"
#include "itkStreamingImageFilter.h"
#include "itkTestingMacros.h"

#include <iostream>

class ShowProgressObject
{
public:
  ShowProgressObject(itk::ProcessObject* o)
    {m_Process = o;}
  void ShowProgress()
    {std::cout << "Progress " << m_Process->GetProgress() << std::endl;}
  itk::ProcessObject::Pointer m_Process;
};

int itkJoinSeriesImageFilterTest( int, char* [] )
{

  const unsigned int streamDivisions = 2;
  typedef unsigned char                 PixelType;
  typedef itk::Image< PixelType, 2 >    InputImageType;
  typedef itk::Image< PixelType, 4 >    OutputImageType;

  // Expected result
  OutputImageType::IndexType expectedIndex = {{1, 2, 0, 0}};
  OutputImageType::SizeType expectedSize = {{8, 5, 4, 1}};
  OutputImageType::RegionType expectedRegion;
  expectedRegion.SetIndex( expectedIndex );
  expectedRegion.SetSize( expectedSize );
  OutputImageType::SpacingType expectedSpacing;
  expectedSpacing[0] = 1.1;
  expectedSpacing[1] = 1.2;
  expectedSpacing[2] = 1.3;
  expectedSpacing[3] = 1.0;
  OutputImageType::PointType expectedOrigin;
  expectedOrigin[0] = 0.1;
  expectedOrigin[1] = 0.2;
  expectedOrigin[2] = 0.3;
  expectedOrigin[3] = 0.0;

  // Create the input images
  int numInputs = 4;
  InputImageType::IndexType index = {{1, 2}};
  InputImageType::SizeType size = {{8, 5}};
  InputImageType::RegionType region;
  region.SetIndex( index );
  region.SetSize( size );
  const double spacingValue = 1.3;
  InputImageType::SpacingType spacing;
  spacing[0] = 1.1;
  spacing[1] = 1.2;
  const double originValue = 0.3;
  InputImageType::PointType origin;
  origin[0] = 0.1;
  origin[1] = 0.2;

  std::vector<InputImageType::Pointer> inputs;

  PixelType counter1 = 0;
  for ( int i = 0; i < numInputs; i++ )
    {
    inputs.push_back( InputImageType::New() );
    inputs[i]->SetLargestPossibleRegion( region );
    inputs[i]->SetBufferedRegion( region );
    inputs[i]->Allocate();

    itk::ImageRegionIterator<InputImageType>
      inputIter( inputs[i], inputs[i]->GetBufferedRegion() );
    while ( !inputIter.IsAtEnd() )
      {
      inputIter.Set( counter1 );
      ++counter1;
      ++inputIter;
      }

    inputs[i]->SetSpacing( spacing );
    inputs[i]->SetOrigin( origin );
    }

  // Create the filter
  typedef itk::JoinSeriesImageFilter< InputImageType, OutputImageType >
    JoinSeriesImageType;

  JoinSeriesImageType::Pointer joinSeriesImage = JoinSeriesImageType::New();

  EXERCISE_BASIC_OBJECT_METHODS( joinSeriesImage, JoinSeriesImageFilter,
    ImageToImageFilter );

  // Check the default values
  if ( joinSeriesImage->GetSpacing() != 1.0 )
    {
    std::cout << "Default spacing is not 1.0" << std::endl;
    return EXIT_FAILURE;
    }
  if ( joinSeriesImage->GetOrigin() != 0.0 )
    {
    std::cout << "Default origin is not 0.0" << std::endl;
    return EXIT_FAILURE;
    }

  // Setup the filter
  joinSeriesImage->SetSpacing( spacingValue );
  TEST_SET_GET_VALUE( spacingValue, joinSeriesImage->GetSpacing() );

  joinSeriesImage->SetOrigin( originValue );
  TEST_SET_GET_VALUE( originValue, joinSeriesImage->GetOrigin() );

  for ( int i = 0; i < numInputs; i++ )
    {
    joinSeriesImage->SetInput( i, inputs[i] );
    }

  // Test the ProgressReporter
  ShowProgressObject progressWatch( joinSeriesImage );
  typedef itk::SimpleMemberCommand< ShowProgressObject > CommandType;
  CommandType::Pointer command = CommandType::New();
  command->SetCallbackFunction( &progressWatch,
                                &ShowProgressObject::ShowProgress );
  joinSeriesImage->AddObserver( itk::ProgressEvent(), command );

  // Test streaming
  typedef itk::StreamingImageFilter< OutputImageType, OutputImageType >
    StreamingImageType;
  StreamingImageType::Pointer streamingImage = StreamingImageType::New();
  streamingImage->SetInput( joinSeriesImage->GetOutput() );
  streamingImage->SetNumberOfStreamDivisions( streamDivisions );

  try
    {
    streamingImage->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << err << std::endl;
    itk::DataObjectError * errp = dynamic_cast<itk::DataObjectError *>( &err );
    if ( errp )
      {
      errp->GetDataObject()->Print( std::cout );
      }
    return EXIT_FAILURE;
    }

  OutputImageType::Pointer output = streamingImage->GetOutput();

  // Check the informations
  if ( output->GetLargestPossibleRegion() != expectedRegion )
    {
    std::cout << "LargestPossibleRegion mismatch" << std::endl;
    return EXIT_FAILURE;
    }
  if ( output->GetSpacing() != expectedSpacing )
    {
    std::cout << "Spacing mismatch" << std::endl;
    return EXIT_FAILURE;
    }
  if ( output->GetOrigin() != expectedOrigin )
    {
    std::cout << "Origin mismatch" << std::endl;
    return EXIT_FAILURE;
    }

  // Check the contents
  bool passed = true;

  PixelType counter2 = 0;
  itk::ImageRegionIterator<OutputImageType>
    outputIter( output, output->GetBufferedRegion() );
  while ( !outputIter.IsAtEnd() )
    {
    if ( outputIter.Get() != counter2 )
      {
      passed = false;
      std::cout << "Mismatch at index: " << outputIter.GetIndex() << std::endl;
      }
    ++counter2;
    ++outputIter;
    }

  if ( !passed || counter1 != counter2 )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  // An exception is raised when an input is missing.
  passed = false;

  // Set the 2nd input null
  joinSeriesImage->SetInput( 1, ITK_NULLPTR );
  try
    {
    joinSeriesImage->Update();
    }
  catch( itk::InvalidRequestedRegionError & err )
    {
    std::cout << err << std::endl;
    passed = true;
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }

  if ( !passed )
    {
    std::cout << "Expected exception is missing" << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;
}
<|endoftext|>