<commit_before>/*
 * Copyright (c) 2003-2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/miscregfile.hh"
#include "arch/x86/tlb.hh"
#include "cpu/thread_context.hh"
#include "sim/serialize.hh"

using namespace X86ISA;
using namespace std;

class Checkpoint;

//These functions map register indices to names
string X86ISA::getMiscRegName(RegIndex index)
{
    panic("No misc registers in x86 yet!\n");
}

void MiscRegFile::clear()
{
    // Blank everything. 0 might not be an appropriate value for some things.
    memset(regVal, 0, NumMiscRegs * sizeof(MiscReg));
}

MiscReg MiscRegFile::readRegNoEffect(int miscReg)
{
    // Make sure we're not dealing with an illegal control register.
    // Instructions should filter out these indexes, and nothing else should
    // attempt to read them directly.
    assert( miscReg != MISCREG_CR1 &&
            !(miscReg > MISCREG_CR4 &&
              miscReg < MISCREG_CR8) &&
            !(miscReg > MISCREG_CR8 &&
              miscReg <= MISCREG_CR15));

    return regVal[miscReg];
}

MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc)
{
    return readRegNoEffect(miscReg);
}

void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val)
{
    // Make sure we're not dealing with an illegal control register.
    // Instructions should filter out these indexes, and nothing else should
    // attempt to write to them directly.
    assert( miscReg != MISCREG_CR1 &&
            !(miscReg > MISCREG_CR4 &&
              miscReg < MISCREG_CR8) &&
            !(miscReg > MISCREG_CR8 &&
              miscReg <= MISCREG_CR15));
    regVal[miscReg] = val;
}

void MiscRegFile::setReg(int miscReg,
        const MiscReg &val, ThreadContext * tc)
{
    MiscReg newVal = val;
    switch(miscReg)
    {
      case MISCREG_CR0:
        {
            CR0 toggled = regVal[miscReg] ^ val;
            CR0 newCR0 = val;
            Efer efer = regVal[MISCREG_EFER];
            if (toggled.pg && efer.lme) {
                if (newCR0.pg) {
                    //Turning on long mode
                    efer.lma = 1;
                    regVal[MISCREG_EFER] = efer;
                } else {
                    //Turning off long mode
                    efer.lma = 0;
                    regVal[MISCREG_EFER] = efer;
                }
            }
            if (toggled.pg) {
                tc->getITBPtr()->invalidateAll();
                tc->getDTBPtr()->invalidateAll();
            }
            //This must always be 1.
            newCR0.et = 1;
            newVal = newCR0;
        }
        break;
      case MISCREG_CR2:
        break;
      case MISCREG_CR3:
        tc->getITBPtr()->invalidateNonGlobal();
        tc->getDTBPtr()->invalidateNonGlobal();
        break;
      case MISCREG_CR4:
        {
            CR4 toggled = regVal[miscReg] ^ val;
            if (toggled.pae || toggled.pse || toggled.pge) {
                tc->getITBPtr()->invalidateAll();
                tc->getDTBPtr()->invalidateAll();
            }
        }
        break;
      case MISCREG_CR8:
        break;
      case MISCREG_CS_ATTR:
        {
            SegAttr toggled = regVal[miscReg] ^ val;
            SegAttr newCSAttr = val;
            if (toggled.longMode) {
                SegAttr newCSAttr = val;
                if (newCSAttr.longMode) {
                    regVal[MISCREG_ES_EFF_BASE] = 0;
                    regVal[MISCREG_CS_EFF_BASE] = 0;
                    regVal[MISCREG_SS_EFF_BASE] = 0;
                    regVal[MISCREG_DS_EFF_BASE] = 0;
                } else {
                    regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
                    regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
                    regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
                    regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
                }
            }
        }
        break;
      // These segments always actually use their bases, or in other words
      // their effective bases must stay equal to their actual bases.
      case MISCREG_FS:
      case MISCREG_GS:
      case MISCREG_HS:
      case MISCREG_TSL:
      case MISCREG_TSG:
      case MISCREG_TR:
      case MISCREG_IDTR:
        regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_SEL_BASE)] = val;
        break;
      // These segments ignore their bases in 64 bit mode.
      // their effective bases must stay equal to their actual bases.
      case MISCREG_ES:
      case MISCREG_CS:
      case MISCREG_SS:
      case MISCREG_DS:
        {
            Efer efer = regVal[MISCREG_EFER];
            SegAttr csAttr = regVal[MISCREG_CS_ATTR];
            if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode.
                regVal[MISCREG_SEG_EFF_BASE(miscReg -
                        MISCREG_SEG_SEL_BASE)] = val;
        }
        break;
    }
    setRegNoEffect(miscReg, newVal);
}

void MiscRegFile::serialize(std::ostream & os)
{
    SERIALIZE_ARRAY(regVal, NumMiscRegs);
}

void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
{
    UNSERIALIZE_ARRAY(regVal, NumMiscRegs);
}
<commit_msg>X86: Make the effective segment base shadow the regular one, not the selector.<commit_after>/*
 * Copyright (c) 2003-2006, 2008 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

/*
 * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/miscregfile.hh"
#include "arch/x86/tlb.hh"
#include "cpu/thread_context.hh"
#include "sim/serialize.hh"

using namespace X86ISA;
using namespace std;

class Checkpoint;

//These functions map register indices to names
string X86ISA::getMiscRegName(RegIndex index)
{
    panic("No misc registers in x86 yet!\n");
}

void MiscRegFile::clear()
{
    // Blank everything. 0 might not be an appropriate value for some things.
    memset(regVal, 0, NumMiscRegs * sizeof(MiscReg));
}

MiscReg MiscRegFile::readRegNoEffect(int miscReg)
{
    // Make sure we're not dealing with an illegal control register.
    // Instructions should filter out these indexes, and nothing else should
    // attempt to read them directly.
    assert( miscReg != MISCREG_CR1 &&
            !(miscReg > MISCREG_CR4 &&
              miscReg < MISCREG_CR8) &&
            !(miscReg > MISCREG_CR8 &&
              miscReg <= MISCREG_CR15));

    return regVal[miscReg];
}

MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc)
{
    return readRegNoEffect(miscReg);
}

void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val)
{
    // Make sure we're not dealing with an illegal control register.
    // Instructions should filter out these indexes, and nothing else should
    // attempt to write to them directly.
    assert( miscReg != MISCREG_CR1 &&
            !(miscReg > MISCREG_CR4 &&
              miscReg < MISCREG_CR8) &&
            !(miscReg > MISCREG_CR8 &&
              miscReg <= MISCREG_CR15));
    regVal[miscReg] = val;
}

void MiscRegFile::setReg(int miscReg,
        const MiscReg &val, ThreadContext * tc)
{
    MiscReg newVal = val;
    switch(miscReg)
    {
      case MISCREG_CR0:
        {
            CR0 toggled = regVal[miscReg] ^ val;
            CR0 newCR0 = val;
            Efer efer = regVal[MISCREG_EFER];
            if (toggled.pg && efer.lme) {
                if (newCR0.pg) {
                    //Turning on long mode
                    efer.lma = 1;
                    regVal[MISCREG_EFER] = efer;
                } else {
                    //Turning off long mode
                    efer.lma = 0;
                    regVal[MISCREG_EFER] = efer;
                }
            }
            if (toggled.pg) {
                tc->getITBPtr()->invalidateAll();
                tc->getDTBPtr()->invalidateAll();
            }
            //This must always be 1.
            newCR0.et = 1;
            newVal = newCR0;
        }
        break;
      case MISCREG_CR2:
        break;
      case MISCREG_CR3:
        tc->getITBPtr()->invalidateNonGlobal();
        tc->getDTBPtr()->invalidateNonGlobal();
        break;
      case MISCREG_CR4:
        {
            CR4 toggled = regVal[miscReg] ^ val;
            if (toggled.pae || toggled.pse || toggled.pge) {
                tc->getITBPtr()->invalidateAll();
                tc->getDTBPtr()->invalidateAll();
            }
        }
        break;
      case MISCREG_CR8:
        break;
      case MISCREG_CS_ATTR:
        {
            SegAttr toggled = regVal[miscReg] ^ val;
            SegAttr newCSAttr = val;
            if (toggled.longMode) {
                SegAttr newCSAttr = val;
                if (newCSAttr.longMode) {
                    regVal[MISCREG_ES_EFF_BASE] = 0;
                    regVal[MISCREG_CS_EFF_BASE] = 0;
                    regVal[MISCREG_SS_EFF_BASE] = 0;
                    regVal[MISCREG_DS_EFF_BASE] = 0;
                } else {
                    regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
                    regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
                    regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
                    regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
                }
            }
        }
        break;
      // These segments always actually use their bases, or in other words
      // their effective bases must stay equal to their actual bases.
      case MISCREG_FS_BASE:
      case MISCREG_GS_BASE:
      case MISCREG_HS_BASE:
      case MISCREG_TSL_BASE:
      case MISCREG_TSG_BASE:
      case MISCREG_TR_BASE:
      case MISCREG_IDTR_BASE:
        regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val;
        break;
      // These segments ignore their bases in 64 bit mode.
      // their effective bases must stay equal to their actual bases.
      case MISCREG_ES_BASE:
      case MISCREG_CS_BASE:
      case MISCREG_SS_BASE:
      case MISCREG_DS_BASE:
        {
            Efer efer = regVal[MISCREG_EFER];
            SegAttr csAttr = regVal[MISCREG_CS_ATTR];
            if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode.
                regVal[MISCREG_SEG_EFF_BASE(miscReg -
                        MISCREG_SEG_BASE_BASE)] = val;
        }
        break;
    }
    setRegNoEffect(miscReg, newVal);
}

void MiscRegFile::serialize(std::ostream & os)
{
    SERIALIZE_ARRAY(regVal, NumMiscRegs);
}

void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
{
    UNSERIALIZE_ARRAY(regVal, NumMiscRegs);
}
<|endoftext|>


<commit_before>#include <metaverse/consensus/libdevcore/BasicType.h>
#include <metaverse/macros_define.hpp>
#include <metaverse/bitcoin/utility/random.hpp>
#include <metaverse/bitcoin/constants.hpp>
#include <metaverse/bitcoin/formats/base_16.hpp>
#include "crypto/common.h"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <chrono>
#include <ctime>

using namespace libbitcoin;

DEV_SIMPLE_EXCEPTION(GenesisBlockCannotBeCalculated);
/*****************************/
WorkPackage::WorkPackage(chain::header& _bh):
    boundary(HeaderAux::boundary(_bh)),
    headerHash(HeaderAux::hashHead(_bh)),
    seedHash(HeaderAux::seedHash(_bh))
{}
/****************************/

LightAllocation::LightAllocation(h256& _seedHash)
{
    uint64_t blockNumber = HeaderAux::number(_seedHash);
    light = ethash_light_new(blockNumber);
    if (!light)
        BOOST_THROW_EXCEPTION(ExternalFunctionFailure("ethash_light_new()"));
    size = ethash_get_cachesize(blockNumber);
}

LightAllocation::~LightAllocation()
{
    ethash_light_delete(light);
}

Result LightAllocation::compute(h256& _headerHash, Nonce& _nonce)
{
    ethash_return_value r = ethash_light_compute(light, *(ethash_h256_t*)_headerHash.data(), (uint64_t)(u64)_nonce);
    if (!r.success)
        BOOST_THROW_EXCEPTION(ExternalFunctionFailure("DAGCreationFailure"));
    return Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)};
}

/*****************************/
FullAllocation::FullAllocation(ethash_light_t _light, ethash_callback_t _cb)
{
    full = ethash_full_new(_light, _cb);
    if (!full)
    {
        BOOST_THROW_EXCEPTION(ExternalFunctionFailure("ethash_full_new"));
    }
}

Result FullAllocation::compute(h256& _headerHash, Nonce& _nonce)
{
    ethash_return_value_t r = ethash_full_compute(full, *(ethash_h256_t*)_headerHash.data(), (uint64_t)(u64)_nonce);
    if (!r.success)
        BOOST_THROW_EXCEPTION(ExternalFunctionFailure("DAGCreationFailure"));
    return Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)};
}

FullAllocation::~FullAllocation()
{
    ethash_full_delete(full);
}
/*****************************/

HeaderAux* HeaderAux::s_this = nullptr;
bool HeaderAux::is_testnet = false;

HeaderAux* HeaderAux::get()
{
    static std::once_flag flag;
    std::call_once(flag, []{s_this = new HeaderAux();});
    return s_this;
}

h256 HeaderAux::seedHash(const chain::header& bi)
{
    unsigned _number = (unsigned) bi.number;
    unsigned epoch = _number / ETHASH_EPOCH_LENGTH;
    Guard l(get()->x_epochs);

    if (epoch >= get()->m_seedHashes.size()) {
        h256 ret;
        unsigned n = 0;
        if (!get()->m_seedHashes.empty()) {
            ret = get()->m_seedHashes.back();
            n = get()->m_seedHashes.size() - 1;
        }

        get()->m_seedHashes.resize(epoch + 1);
//        cdebug << "Searching for seedHash of epoch " << epoch;

        for (; n <= epoch; ++n, ret = sha3(ret)) {
            get()->m_seedHashes[n] = ret;
//            cdebug << "Epoch" << n << "is" << ret;
        }
    }
    return get()->m_seedHashes[epoch];
}

uint64_t HeaderAux::number(h256& _seedHash)
{
    Guard l(get()->x_epochs);
    unsigned epoch = 0;
    auto epochIter = get()->m_epochs.find(_seedHash);
    if (epochIter == get()->m_epochs.end()) {
        //        cdebug << "Searching for seedHash " << _seedHash;
        for (h256 h; h != _seedHash && epoch < 2048; ++epoch, h = sha3(h), get()->m_epochs[h] = epoch)
        {}

        if (epoch == 2048) {
            std::ostringstream error;
            error << "apparent block number for " << _seedHash << " is too high; max is " << (ETHASH_EPOCH_LENGTH * 2048);
            throw std::invalid_argument(error.str());
        }
    }
    else
        epoch = epochIter->second;
    return epoch * ETHASH_EPOCH_LENGTH;
}

h256 HeaderAux::boundary(const chain::header& bi)
{
    auto d = bi.bits;
    return d ? (h256)u256(((bigint(1) << 255)-bigint(1) +(bigint(1) << 255) ) / d) : h256();
}

h256 HeaderAux::hashHead(const chain::header& bi)
{
    h256 memo;
    RLPStream s;
    s  << (bigint) bi.version << (bigint)bi.bits << (bigint)bi.number << bi.merkle
        << bi.previous_block_hash << (bigint) bi.timestamp ;
    memo = sha3(s.out());
    return memo;
}

h256 HeaderAux::hash_head_pos(const chain::header& bi, const chain::output_info& stake)
{
    RLPStream s;
    s << (bigint) bi.version << (bigint)bi.number
        << bi.previous_block_hash << (bigint) bi.timestamp
        << stake.point.hash << (bigint) stake.point.index;

    auto hash_pos = bitcoin_hash(to_chunk(s.out()));
    h256 memo = h256(encode_hash(hash_pos));
    return memo;
}

uint64_t HeaderAux::cacheSize(const chain::header& _header)
{
    return ethash_get_cachesize((uint64_t)_header.number);
}

uint64_t HeaderAux::dataSize(uint64_t _blockNumber)
{
    return ethash_get_datasize(_blockNumber);
}

u256 HeaderAux::calculate_difficulty(
    const chain::header& current,
    const chain::header::ptr prev,
    const chain::header::ptr pprev)
{
    if (current.number < pos_enabled_height) {
        return calculate_difficulty_v1(current, prev, pprev);
    }

    return calculate_difficulty_v2(current, prev, pprev);
}

// Do not modify this function! It's for backward compatibility.
u256 HeaderAux::calculate_difficulty_v1(
    const chain::header& current,
    const chain::header::ptr prev,
    const chain::header::ptr pprev)
{
    if (!current.number) {
        throw GenesisBlockCannotBeCalculated();
    }

    auto minimumDifficulty = is_testnet ? bigint(300000) : bigint(914572800);
    bigint target(minimumDifficulty);

    // DO NOT MODIFY time_config in release
    if (prev) {
        if (current.timestamp >= prev->timestamp + 24u) { // approach to 24*1.4 seconds
            target = prev->bits - (prev->bits/1024);
        }
        else {
            target = prev->bits + (prev->bits/1024);
        }
    }

    bigint result = std::max<bigint>(minimumDifficulty, target);

#ifdef PRIVATE_CHAIN
    result = bigint(10);
#endif

    return u256(std::min<bigint>(result, std::numeric_limits<u256>::max()));
}

u256 HeaderAux::calculate_difficulty_v2(
    const chain::header& current,
    const chain::header::ptr prev,
    const chain::header::ptr pprev)
{
    bigint minimumDifficulty, result;
    int32_t interval;

    if (current.version == chain::block_version_pow) {
        //////////// PoW ///////////////
        minimumDifficulty = is_testnet ? bigint(300000) : bigint(914572800);
#ifdef PRIVATE_CHAIN
        minimumDifficulty = bigint(300000);
        if (current.number < 10000) {
            return u256(bigint(10));
        }
#endif

        if (nullptr == prev) {
            return u256(minimumDifficulty);
        }

        BITCOIN_ASSERT(current.version == prev->version);
        const bigint& parent_bits = prev->bits;
        interval = current.timestamp - prev->timestamp;
        const bigint adjustvalue = bigint(std::max<int32_t>(2 - interval/10, -99)); // approach to 20*1.4 seconds
        const bigint&& target = parent_bits + parent_bits / 2048 * adjustvalue;
        result = std::max<bigint>(target, minimumDifficulty);
    }
    else {
        //////////// PoS ///////////////
        minimumDifficulty = is_testnet ? bigint(1000000) : bigint(100000000);
        if (nullptr == prev || nullptr == pprev) {
            return u256(minimumDifficulty);
        }

        BITCOIN_ASSERT(current.version == prev->version);
        const bigint& parent_bits = prev->bits;
        interval = prev->timestamp - pprev->timestamp;;
        const bigint adjustvalue = bigint(std::max<int32_t>(18 - interval/10 ,-99)); // approach to 180*1.4 seconds
        const bigint&& target = parent_bits + parent_bits / 2048 * adjustvalue;
        result = std::max<bigint>(target, minimumDifficulty);
    }

    if (current.transaction_count > 0) {
        log::info("difficulty")
            << "{ \"block_type\" : \"" << chain::get_block_version(current) << "\""
            << ", \"last_interval\" : " << interval
            << ", \"current_height\" : " << current.number
            << ", \"difficulty\" : " << result << " }";
    }

    // Retarget
    return u256(std::min<bigint>(result, std::numeric_limits<u256>::max()));
}
<commit_msg>update log<commit_after>#include <metaverse/consensus/libdevcore/BasicType.h>
#include <metaverse/macros_define.hpp>
#include <metaverse/bitcoin/utility/random.hpp>
#include <metaverse/bitcoin/constants.hpp>
#include <metaverse/bitcoin/formats/base_16.hpp>
#include "crypto/common.h"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <chrono>
#include <ctime>

using namespace libbitcoin;

DEV_SIMPLE_EXCEPTION(GenesisBlockCannotBeCalculated);
/*****************************/
WorkPackage::WorkPackage(chain::header& _bh):
    boundary(HeaderAux::boundary(_bh)),
    headerHash(HeaderAux::hashHead(_bh)),
    seedHash(HeaderAux::seedHash(_bh))
{}
/****************************/

LightAllocation::LightAllocation(h256& _seedHash)
{
    uint64_t blockNumber = HeaderAux::number(_seedHash);
    light = ethash_light_new(blockNumber);
    if (!light)
        BOOST_THROW_EXCEPTION(ExternalFunctionFailure("ethash_light_new()"));
    size = ethash_get_cachesize(blockNumber);
}

LightAllocation::~LightAllocation()
{
    ethash_light_delete(light);
}

Result LightAllocation::compute(h256& _headerHash, Nonce& _nonce)
{
    ethash_return_value r = ethash_light_compute(light, *(ethash_h256_t*)_headerHash.data(), (uint64_t)(u64)_nonce);
    if (!r.success)
        BOOST_THROW_EXCEPTION(ExternalFunctionFailure("DAGCreationFailure"));
    return Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)};
}

/*****************************/
FullAllocation::FullAllocation(ethash_light_t _light, ethash_callback_t _cb)
{
    full = ethash_full_new(_light, _cb);
    if (!full)
    {
        BOOST_THROW_EXCEPTION(ExternalFunctionFailure("ethash_full_new"));
    }
}

Result FullAllocation::compute(h256& _headerHash, Nonce& _nonce)
{
    ethash_return_value_t r = ethash_full_compute(full, *(ethash_h256_t*)_headerHash.data(), (uint64_t)(u64)_nonce);
    if (!r.success)
        BOOST_THROW_EXCEPTION(ExternalFunctionFailure("DAGCreationFailure"));
    return Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)};
}

FullAllocation::~FullAllocation()
{
    ethash_full_delete(full);
}
/*****************************/

HeaderAux* HeaderAux::s_this = nullptr;
bool HeaderAux::is_testnet = false;

HeaderAux* HeaderAux::get()
{
    static std::once_flag flag;
    std::call_once(flag, []{s_this = new HeaderAux();});
    return s_this;
}

h256 HeaderAux::seedHash(const chain::header& bi)
{
    unsigned _number = (unsigned) bi.number;
    unsigned epoch = _number / ETHASH_EPOCH_LENGTH;
    Guard l(get()->x_epochs);

    if (epoch >= get()->m_seedHashes.size()) {
        h256 ret;
        unsigned n = 0;
        if (!get()->m_seedHashes.empty()) {
            ret = get()->m_seedHashes.back();
            n = get()->m_seedHashes.size() - 1;
        }

        get()->m_seedHashes.resize(epoch + 1);
//        cdebug << "Searching for seedHash of epoch " << epoch;

        for (; n <= epoch; ++n, ret = sha3(ret)) {
            get()->m_seedHashes[n] = ret;
//            cdebug << "Epoch" << n << "is" << ret;
        }
    }
    return get()->m_seedHashes[epoch];
}

uint64_t HeaderAux::number(h256& _seedHash)
{
    Guard l(get()->x_epochs);
    unsigned epoch = 0;
    auto epochIter = get()->m_epochs.find(_seedHash);
    if (epochIter == get()->m_epochs.end()) {
        //        cdebug << "Searching for seedHash " << _seedHash;
        for (h256 h; h != _seedHash && epoch < 2048; ++epoch, h = sha3(h), get()->m_epochs[h] = epoch)
        {}

        if (epoch == 2048) {
            std::ostringstream error;
            error << "apparent block number for " << _seedHash << " is too high; max is " << (ETHASH_EPOCH_LENGTH * 2048);
            throw std::invalid_argument(error.str());
        }
    }
    else
        epoch = epochIter->second;
    return epoch * ETHASH_EPOCH_LENGTH;
}

h256 HeaderAux::boundary(const chain::header& bi)
{
    auto d = bi.bits;
    return d ? (h256)u256(((bigint(1) << 255)-bigint(1) +(bigint(1) << 255) ) / d) : h256();
}

h256 HeaderAux::hashHead(const chain::header& bi)
{
    h256 memo;
    RLPStream s;
    s  << (bigint) bi.version << (bigint)bi.bits << (bigint)bi.number << bi.merkle
        << bi.previous_block_hash << (bigint) bi.timestamp ;
    memo = sha3(s.out());
    return memo;
}

h256 HeaderAux::hash_head_pos(const chain::header& bi, const chain::output_info& stake)
{
    RLPStream s;
    s << (bigint) bi.version << (bigint)bi.number
        << bi.previous_block_hash << (bigint) bi.timestamp
        << stake.point.hash << (bigint) stake.point.index;

    auto hash_pos = bitcoin_hash(to_chunk(s.out()));
    h256 memo = h256(encode_hash(hash_pos));
    return memo;
}

uint64_t HeaderAux::cacheSize(const chain::header& _header)
{
    return ethash_get_cachesize((uint64_t)_header.number);
}

uint64_t HeaderAux::dataSize(uint64_t _blockNumber)
{
    return ethash_get_datasize(_blockNumber);
}

u256 HeaderAux::calculate_difficulty(
    const chain::header& current,
    const chain::header::ptr prev,
    const chain::header::ptr pprev)
{
    if (current.number < pos_enabled_height) {
        return calculate_difficulty_v1(current, prev, pprev);
    }

    return calculate_difficulty_v2(current, prev, pprev);
}

// Do not modify this function! It's for backward compatibility.
u256 HeaderAux::calculate_difficulty_v1(
    const chain::header& current,
    const chain::header::ptr prev,
    const chain::header::ptr pprev)
{
    if (!current.number) {
        throw GenesisBlockCannotBeCalculated();
    }

    auto minimumDifficulty = is_testnet ? bigint(300000) : bigint(914572800);
    bigint target(minimumDifficulty);

    // DO NOT MODIFY time_config in release
    if (prev) {
        if (current.timestamp >= prev->timestamp + 24u) { // approach to 24*1.4 seconds
            target = prev->bits - (prev->bits/1024);
        }
        else {
            target = prev->bits + (prev->bits/1024);
        }
    }

    bigint result = std::max<bigint>(minimumDifficulty, target);

#ifdef PRIVATE_CHAIN
    result = bigint(10);
#endif

    return u256(std::min<bigint>(result, std::numeric_limits<u256>::max()));
}

u256 HeaderAux::calculate_difficulty_v2(
    const chain::header& current,
    const chain::header::ptr prev,
    const chain::header::ptr pprev)
{
    bigint minimumDifficulty, result;
    int32_t interval;

    if (current.version == chain::block_version_pow) {
        //////////// PoW ///////////////
        minimumDifficulty = is_testnet ? bigint(300000) : bigint(914572800);
#ifdef PRIVATE_CHAIN
        minimumDifficulty = bigint(300000);
        if (current.number < 10000) {
            return u256(bigint(10));
        }
#endif

        if (nullptr == prev) {
            return u256(minimumDifficulty);
        }

        BITCOIN_ASSERT(current.version == prev->version);
        const bigint& parent_bits = prev->bits;
        interval = current.timestamp - prev->timestamp;
        const bigint adjustvalue = bigint(std::max<int32_t>(2 - interval/10, -99)); // approach to 20*1.4 seconds
        const bigint&& target = parent_bits + parent_bits / 2048 * adjustvalue;
        result = std::max<bigint>(target, minimumDifficulty);
    }
    else {
        //////////// PoS ///////////////
        minimumDifficulty = is_testnet ? bigint(1000000) : bigint(100000000);
        if (nullptr == prev || nullptr == pprev) {
            return u256(minimumDifficulty);
        }

        BITCOIN_ASSERT(current.version == prev->version);
        const bigint& parent_bits = prev->bits;
        interval = prev->timestamp - pprev->timestamp;;
        const bigint adjustvalue = bigint(std::max<int32_t>(18 - interval/10 ,-99)); // approach to 180*1.4 seconds
        const bigint&& target = parent_bits + parent_bits / 2048 * adjustvalue;
        result = std::max<bigint>(target, minimumDifficulty);
    }

    if (current.transaction_count > 0) {
        log::debug("difficulty")
            << "{ \"block_type\" : \"" << chain::get_block_version(current) << "\""
            << ", \"last_interval\" : " << interval
            << ", \"current_height\" : " << current.number
            << ", \"difficulty\" : " << result << " }";
    }

    // Retarget
    return u256(std::min<bigint>(result, std::numeric_limits<u256>::max()));
}
<|endoftext|>


<commit_before>/*
 * Use and distribution licensed under the Apache license version 2.
 *
 * See the COPYING file in the root project directory for full text.
 */

#include <iostream>
#include <cctype>
#include <sstream>

#include "parser/statements/create_table.h"
#include "parser/error.h"
#include "parser/token.h"
#include "statements/create_table.h"

namespace sqltoast {

//
// The CREATE TABLE statement follows this EBNF form for the following SQL
// dialects:
//
// * SQL_DIALECT_ANSI_1992
//
//  <table definition> ::=
//      CREATE [{GLOBAL|LOCAL} TEMPORARY] TABLE <table name>
//      <table element list>
//      [ON COMMIT {DELETE|PRESERVE} ROWS]
//

bool parse_create_table(parse_context_t& ctx) {
    tokens_t::iterator tok_it = ctx.tokens.begin();
    tokens_t::iterator tok_ident = ctx.tokens.end();
    symbol_t exp_sym = SYMBOL_CREATE;
    symbol_t cur_sym = (*tok_it).symbol;
    statements::table_type_t table_type = statements::TABLE_TYPE_NORMAL;

    goto next_token;

    // BEGIN STATE MACHINE

    table_kw_or_table_type:
        // We get here after successfully finding the CREATE symbol. We can
        // either match the table keyword or the table type clause
        tok_it = ctx.skip_comments(tok_it);
        cur_sym = (*tok_it).symbol;
        if (cur_sym == SYMBOL_GLOBAL) {
            table_type = statements::TABLE_TYPE_TEMPORARY_GLOBAL;
            tok_it++;
            goto table_type;
        } else if (cur_sym == SYMBOL_LOCAL) {
            table_type = statements::TABLE_TYPE_TEMPORARY_LOCAL;
            tok_it++;
            goto table_type;
        } else if (cur_sym == SYMBOL_TEMPORARY) {
            table_type = statements::TABLE_TYPE_TEMPORARY_GLOBAL;
            tok_it++;
            goto table_name;
        } else {
            exp_sym = SYMBOL_TABLE;
            goto next_token;
        }
        SQLTOAST_UNREACHABLE();
    table_type:
        // We get here if we successfully matched CREATE followed by either the
        // GLOBAL or LOCAL symbol. If this is the case, we expect to find the
        // TEMPORARY keyword followed by the TABLE keyword.
        tok_it = ctx.skip_comments(tok_it);
        if (tok_it == ctx.tokens.end())
            goto err_expect_temporary;
        cur_sym = (*tok_it).symbol;
        if (cur_sym != SYMBOL_TEMPORARY)
            goto err_expect_temporary;
        tok_it = ctx.skip_comments(++tok_it);
        if (tok_it == ctx.tokens.end())
            goto err_expect_table;
        cur_sym = (*tok_it).symbol;
        if (cur_sym != SYMBOL_TABLE)
            goto err_expect_table;
        tok_it++;
        goto table_name;
        SQLTOAST_UNREACHABLE();
    err_expect_temporary:
        {
            parse_position_t err_pos = (*(tok_it)).start;
            std::stringstream estr;
            if (tok_it == ctx.tokens.end()) {
                estr << "Expected TEMPORARY after CREATE {GLOBAL | LOCAL} but found EOS";
            } else {
                cur_sym = (*tok_it).symbol;
                estr << "Expected TEMPORARY after CREATE {GLOBAL | LOCAL} but found "
                     << symbol_map::to_string(cur_sym);
            }
            estr << std::endl;
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    err_expect_table:
        {
            parse_position_t err_pos = (*(tok_it)).start;
            std::stringstream estr;
            if (tok_it == ctx.tokens.end()) {
                estr << "Expected TABLE after CREATE {GLOBAL | LOCAL} TEMPORARY but found EOS";
            } else {
                cur_sym = (*tok_it).symbol;
                estr << "Expected TABLE after CREATE {GLOBAL | LOCAL} TEMPORARY but found "
                     << symbol_map::to_string(cur_sym);
            }
            estr << std::endl;
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    table_name:
        // We get here after successfully finding CREATE followed by the TABLE
        // symbol (after optionally processing the table type modifier). We now
        // need to find an identifier
        tok_it = ctx.skip_comments(tok_it);
        cur_sym = (*tok_it).symbol;
        if (cur_sym == SYMBOL_IDENTIFIER) {
            tok_ident = tok_it++;
            goto statement_ending;
        }
        goto err_expect_identifier;
        SQLTOAST_UNREACHABLE();
    err_expect_identifier:
        {
            parse_position_t err_pos = (*(tok_it)).start;
            std::stringstream estr;
            if (tok_it == ctx.tokens.end()) {
                estr << "Expected <identifier> after CREATE TABLE but found EOS";
            } else {
                cur_sym = (*tok_it).symbol;
                estr << "Expected <identifier> after CREATE TABLE keyword but found "
                     << symbol_map::to_string(cur_sym);
            }
            estr << std::endl;
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    statement_ending:
        // We get here if we have already successfully processed the CREATE
        // TABLE statement and are expecting EOS or SEMICOLON as the next
        // non-comment token
        tok_it = ctx.skip_comments(tok_it);
        if (tok_it == ctx.tokens.end()) {
            goto push_statement;
        }

        cur_sym = (*tok_it).symbol;
        if (cur_sym == SYMBOL_SEMICOLON) {
            // skip-consume the semicolon token
            tok_it++;
            goto push_statement;
        }
        {
            parse_position_t err_pos = (*tok_it).start;
            std::stringstream estr;
            estr << "Expected EOS or SEMICOLON but found "
                 << symbol_map::to_string(cur_sym) << std::endl;
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    push_statement:
        {
            ctx.trim_to(tok_it);
            if (ctx.opts.disable_statement_construction)
                return true;
            identifier_t table_ident((*tok_ident).start, (*tok_ident).end);
            auto stmt_p = std::make_unique<statements::create_table_t>(table_type, table_ident);
            ctx.result.statements.emplace_back(std::move(stmt_p));
            return true;
        }
    eos:
        if (exp_sym == SYMBOL_CREATE || exp_sym == SYMBOL_TABLE) {
            // Reached the end of the token stack and never found the
            // CREATE TABLE so just return false
            return false;
        }
        {
            // Reached the end of the token stream after already finding the
            // CREATE and TABLE symbols. Return a syntax error.
            parse_position_t err_pos = (*tok_it).start;
            std::stringstream estr;
            estr << "Expected <table_name_clause> but found EOS";
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    next_token:
        tok_it = ctx.skip_comments(tok_it);
        if (tok_it == ctx.tokens.end()) {
            goto eos;
        }
        cur_sym = (*tok_it).symbol;
        tok_it++;
        switch (cur_sym) {
            case SYMBOL_CREATE:
                if (exp_sym == SYMBOL_CREATE) {
                    goto table_kw_or_table_type;
                }
                goto next_token;
            case SYMBOL_TABLE:
                if (exp_sym == SYMBOL_TABLE) {
                    goto table_name;
                }
                goto next_token;
            default:
                return false;
        }
        SQLTOAST_UNREACHABLE();
}

} // namespace sqltoast
<commit_msg>Fix failure to parse TEMPORARY properly<commit_after>/*
 * Use and distribution licensed under the Apache license version 2.
 *
 * See the COPYING file in the root project directory for full text.
 */

#include <iostream>
#include <cctype>
#include <sstream>

#include "parser/statements/create_table.h"
#include "parser/error.h"
#include "parser/token.h"
#include "statements/create_table.h"

namespace sqltoast {

//
// The CREATE TABLE statement follows this EBNF form for the following SQL
// dialects:
//
// * SQL_DIALECT_ANSI_1992
//
//  <table definition> ::=
//      CREATE [{GLOBAL|LOCAL} TEMPORARY] TABLE <table name>
//      <table element list>
//      [ON COMMIT {DELETE|PRESERVE} ROWS]
//

bool parse_create_table(parse_context_t& ctx) {
    tokens_t::iterator tok_it = ctx.tokens.begin();
    tokens_t::iterator tok_ident = ctx.tokens.end();
    symbol_t exp_sym = SYMBOL_CREATE;
    symbol_t cur_sym = (*tok_it).symbol;
    statements::table_type_t table_type = statements::TABLE_TYPE_NORMAL;

    goto next_token;

    // BEGIN STATE MACHINE

    table_kw_or_table_type:
        // We get here after successfully finding the CREATE symbol. We can
        // either match the table keyword or the table type clause
        tok_it = ctx.skip_comments(tok_it);
        cur_sym = (*tok_it).symbol;
        if (cur_sym == SYMBOL_GLOBAL) {
            table_type = statements::TABLE_TYPE_TEMPORARY_GLOBAL;
            tok_it++;
            goto expect_temporary;
        } else if (cur_sym == SYMBOL_LOCAL) {
            table_type = statements::TABLE_TYPE_TEMPORARY_LOCAL;
            tok_it++;
            goto expect_temporary;
        } else if (cur_sym == SYMBOL_TEMPORARY) {
            table_type = statements::TABLE_TYPE_TEMPORARY_GLOBAL;
            tok_it++;
        }
        exp_sym = SYMBOL_TABLE;
        goto next_token;
        SQLTOAST_UNREACHABLE();
    expect_temporary:
        // We get here if we successfully matched CREATE followed by either the
        // GLOBAL or LOCAL symbol. If this is the case, we expect to find the
        // TEMPORARY keyword followed by the TABLE keyword.
        tok_it = ctx.skip_comments(tok_it);
        if (tok_it == ctx.tokens.end())
            goto err_expect_temporary;
        cur_sym = (*tok_it).symbol;
        if (cur_sym != SYMBOL_TEMPORARY)
            goto err_expect_temporary;
        tok_it = ctx.skip_comments(++tok_it);
        if (tok_it == ctx.tokens.end())
            goto err_expect_table;
        cur_sym = (*tok_it).symbol;
        if (cur_sym != SYMBOL_TABLE)
            goto err_expect_table;
        tok_it++;
        goto expect_table_name;
        SQLTOAST_UNREACHABLE();
    err_expect_temporary:
        {
            parse_position_t err_pos = (*(tok_it)).start;
            std::stringstream estr;
            if (tok_it == ctx.tokens.end()) {
                estr << "Expected TEMPORARY after CREATE {GLOBAL | LOCAL} but found EOS";
            } else {
                cur_sym = (*tok_it).symbol;
                estr << "Expected TEMPORARY after CREATE {GLOBAL | LOCAL} but found "
                     << symbol_map::to_string(cur_sym);
            }
            estr << std::endl;
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    err_expect_table:
        {
            parse_position_t err_pos = (*(tok_it)).start;
            std::stringstream estr;
            if (tok_it == ctx.tokens.end()) {
                estr << "Expected TABLE after CREATE {GLOBAL | LOCAL} TEMPORARY but found EOS";
            } else {
                cur_sym = (*tok_it).symbol;
                estr << "Expected TABLE after CREATE {GLOBAL | LOCAL} TEMPORARY but found "
                     << symbol_map::to_string(cur_sym);
            }
            estr << std::endl;
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    expect_table_name:
        // We get here after successfully finding CREATE followed by the TABLE
        // symbol (after optionally processing the table type modifier). We now
        // need to find an identifier
        tok_it = ctx.skip_comments(tok_it);
        cur_sym = (*tok_it).symbol;
        if (cur_sym == SYMBOL_IDENTIFIER) {
            tok_ident = tok_it++;
            goto statement_ending;
        }
        goto err_expect_identifier;
        SQLTOAST_UNREACHABLE();
    err_expect_identifier:
        {
            parse_position_t err_pos = (*(tok_it)).start;
            std::stringstream estr;
            if (tok_it == ctx.tokens.end()) {
                estr << "Expected <identifier> after CREATE TABLE but found EOS";
            } else {
                cur_sym = (*tok_it).symbol;
                estr << "Expected <identifier> after CREATE TABLE keyword but found "
                     << symbol_map::to_string(cur_sym);
            }
            estr << std::endl;
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    statement_ending:
        // We get here if we have already successfully processed the CREATE
        // TABLE statement and are expecting EOS or SEMICOLON as the next
        // non-comment token
        tok_it = ctx.skip_comments(tok_it);
        if (tok_it == ctx.tokens.end()) {
            goto push_statement;
        }

        cur_sym = (*tok_it).symbol;
        if (cur_sym == SYMBOL_SEMICOLON) {
            // skip-consume the semicolon token
            tok_it++;
            goto push_statement;
        }
        {
            parse_position_t err_pos = (*tok_it).start;
            std::stringstream estr;
            estr << "Expected EOS or SEMICOLON but found "
                 << symbol_map::to_string(cur_sym) << std::endl;
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    push_statement:
        {
            ctx.trim_to(tok_it);
            if (ctx.opts.disable_statement_construction)
                return true;
            identifier_t table_ident((*tok_ident).start, (*tok_ident).end);
            auto stmt_p = std::make_unique<statements::create_table_t>(table_type, table_ident);
            ctx.result.statements.emplace_back(std::move(stmt_p));
            return true;
        }
    eos:
        if (exp_sym == SYMBOL_CREATE || exp_sym == SYMBOL_TABLE) {
            // Reached the end of the token stack and never found the
            // CREATE TABLE so just return false
            return false;
        }
        {
            // Reached the end of the token stream after already finding the
            // CREATE and TABLE symbols. Return a syntax error.
            parse_position_t err_pos = (*tok_it).start;
            std::stringstream estr;
            estr << "Expected <table_name_clause> but found EOS";
            create_syntax_error_marker(ctx, estr, err_pos);
            return false;
        }
        SQLTOAST_UNREACHABLE();
    next_token:
        tok_it = ctx.skip_comments(tok_it);
        if (tok_it == ctx.tokens.end()) {
            goto eos;
        }
        cur_sym = (*tok_it).symbol;
        tok_it++;
        switch (cur_sym) {
            case SYMBOL_CREATE:
                if (exp_sym == SYMBOL_CREATE) {
                    goto table_kw_or_table_type;
                }
                goto next_token;
            case SYMBOL_TABLE:
                if (exp_sym == SYMBOL_TABLE) {
                    goto expect_table_name;
                }
                goto next_token;
            default:
                return false;
        }
        SQLTOAST_UNREACHABLE();
}

} // namespace sqltoast
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2013 Viktor Gal
 * Copyright (C) 2013 Viktor Gal
 */

#include <shogun/mathematics/Random.h>
#include <shogun/base/Parameter.h>

using namespace shogun;

CRandom::CRandom()
 : m_seed(12345)
{
	init();
}

CRandom::CRandom(uint32_t seed)
 : m_seed(seed)
{
	init();
}

CRandom::~CRandom()
{
	SG_FREE(m_sfmt_32);
	SG_FREE(m_sfmt_64);
	SG_FREE(m_dsfmt);
}

void CRandom::set_seed(uint32_t seed)
{
	reinit(seed);
}

uint32_t CRandom::get_seed() const
{
	return m_seed;
}

void CRandom::init()
{
	m_sfmt_32 = SG_MALLOC(sfmt_t, 1);
	m_sfmt_64 = SG_MALLOC(sfmt_t, 1);
	m_dsfmt = SG_MALLOC(dsfmt_t, 1);
#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_INIT(&m_state_lock);
#endif
	reinit(m_seed);
}

uint32_t CRandom::random_32() const
{
	return sfmt_genrand_uint32(m_sfmt_32);
}

uint64_t CRandom::random_64() const
{
	return sfmt_genrand_uint64(m_sfmt_64);
}

void CRandom::fill_array(uint32_t* array, int32_t size) const
{
	if ((size >= sfmt_get_min_array_size32(m_sfmt_32)) && (size % 4) == 0)
	{
		sfmt_fill_array32(m_sfmt_32, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = random_32();
	}
}

void CRandom::fill_array(uint64_t* array, int32_t size) const
{
	if ((size >= sfmt_get_min_array_size64(m_sfmt_64)) && (size % 2) == 0)
	{
		sfmt_fill_array64(m_sfmt_64, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = random_64();
	}
}

void CRandom::fill_array_oc(float64_t* array, int32_t size) const
{
	if ((size >= dsfmt_get_min_array_size()) && (size % 2) == 0)
	{
		dsfmt_fill_array_open_close(m_dsfmt, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = dsfmt_genrand_open_close(m_dsfmt);
	}
}

void CRandom::fill_array_co(float64_t* array, int32_t size) const
{
	if ((size >= dsfmt_get_min_array_size()) && (size % 2) == 0)
	{
		dsfmt_fill_array_close_open(m_dsfmt, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = dsfmt_genrand_close_open(m_dsfmt);
	}
}

void CRandom::fill_array_oo(float64_t* array, int32_t size) const
{
	if ((size >= dsfmt_get_min_array_size()) && (size % 2) == 0)
	{
		dsfmt_fill_array_open_open(m_dsfmt, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = dsfmt_genrand_open_open(m_dsfmt);
	}
}

void CRandom::fill_array_c1o2(float64_t* array, int32_t size) const
{
	if ((size >= dsfmt_get_min_array_size()) && (size % 2) == 0)
	{
		dsfmt_fill_array_close1_open2(m_dsfmt, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = dsfmt_genrand_close1_open2(m_dsfmt);
	}
}

float64_t CRandom::random_close() const
{
	return sfmt_genrand_real1(m_sfmt_32);
}

float64_t CRandom::random_open() const
{
	return dsfmt_genrand_open_open(m_dsfmt);
}

float64_t CRandom::random_half_open() const
{
	return dsfmt_genrand_close_open(m_dsfmt);
}
<commit_msg>Random: Initialize class variables to NULL<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2013 Viktor Gal
 * Copyright (C) 2013 Viktor Gal
 */

#include <shogun/mathematics/Random.h>
#include <shogun/base/Parameter.h>

using namespace shogun;

CRandom::CRandom()
 : m_seed(12345),
 m_sfmt_32(NULL),
 m_sfmt_64(NULL),
 m_dsfmt(NULL)
{
	init();
}

CRandom::CRandom(uint32_t seed)
 : m_seed(seed),
 m_sfmt_32(NULL),
 m_sfmt_64(NULL),
 m_dsfmt(NULL)
{
	init();
}

CRandom::~CRandom()
{
	SG_FREE(m_sfmt_32);
	SG_FREE(m_sfmt_64);
	SG_FREE(m_dsfmt);
}

void CRandom::set_seed(uint32_t seed)
{
	reinit(seed);
}

uint32_t CRandom::get_seed() const
{
	return m_seed;
}

void CRandom::init()
{
	m_sfmt_32 = SG_MALLOC(sfmt_t, 1);
	m_sfmt_64 = SG_MALLOC(sfmt_t, 1);
	m_dsfmt = SG_MALLOC(dsfmt_t, 1);
#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_INIT(&m_state_lock);
#endif
	reinit(m_seed);
}

uint32_t CRandom::random_32() const
{
	return sfmt_genrand_uint32(m_sfmt_32);
}

uint64_t CRandom::random_64() const
{
	return sfmt_genrand_uint64(m_sfmt_64);
}

void CRandom::fill_array(uint32_t* array, int32_t size) const
{
	if ((size >= sfmt_get_min_array_size32(m_sfmt_32)) && (size % 4) == 0)
	{
		sfmt_fill_array32(m_sfmt_32, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = random_32();
	}
}

void CRandom::fill_array(uint64_t* array, int32_t size) const
{
	if ((size >= sfmt_get_min_array_size64(m_sfmt_64)) && (size % 2) == 0)
	{
		sfmt_fill_array64(m_sfmt_64, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = random_64();
	}
}

void CRandom::fill_array_oc(float64_t* array, int32_t size) const
{
	if ((size >= dsfmt_get_min_array_size()) && (size % 2) == 0)
	{
		dsfmt_fill_array_open_close(m_dsfmt, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = dsfmt_genrand_open_close(m_dsfmt);
	}
}

void CRandom::fill_array_co(float64_t* array, int32_t size) const
{
	if ((size >= dsfmt_get_min_array_size()) && (size % 2) == 0)
	{
		dsfmt_fill_array_close_open(m_dsfmt, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = dsfmt_genrand_close_open(m_dsfmt);
	}
}

void CRandom::fill_array_oo(float64_t* array, int32_t size) const
{
	if ((size >= dsfmt_get_min_array_size()) && (size % 2) == 0)
	{
		dsfmt_fill_array_open_open(m_dsfmt, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = dsfmt_genrand_open_open(m_dsfmt);
	}
}

void CRandom::fill_array_c1o2(float64_t* array, int32_t size) const
{
	if ((size >= dsfmt_get_min_array_size()) && (size % 2) == 0)
	{
		dsfmt_fill_array_close1_open2(m_dsfmt, array, size);
	}
	else
	{
		for (int32_t i=0; i < size; i++)
			array[i] = dsfmt_genrand_close1_open2(m_dsfmt);
	}
}

float64_t CRandom::random_close() const
{
	return sfmt_genrand_real1(m_sfmt_32);
}

float64_t CRandom::random_open() const
{
	return dsfmt_genrand_open_open(m_dsfmt);
}

float64_t CRandom::random_half_open() const
{
	return dsfmt_genrand_close_open(m_dsfmt);
}
<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
// audio_devices.cpp
// C++ functions for creating and configuring AudioDevice instances for input
// and output.
//

#include <string.h>
#include <RTcmix.h>
#include <sndlibsupport.h>
#include <ugens.h>
#include <prototypes.h>
#include <assert.h>
#include <Option.h>

#include "AudioDevice.h"
#include "AudioFileDevice.h"
#include "AudioIODevice.h"
#include "AudioOutputGroupDevice.h"
#include "DualOutputAudioDevice.h"
#include "audio_devices.h"

#define DEBUG	1

#ifdef NETAUDIO
char globalNetworkPath[128];			// Set by Minc/setnetplay.c
#endif

// Return pointers to the most recently specified audio device strings.
// "indevice" always overrides "device", and same with "outdevice".

const char *get_audio_device_name()
{
	if (strlen(Option::inDevice()) || strlen(Option::outDevice()))
		return NULL;
	if (strlen(Option::device()))
		return Option::device();
	return NULL;
}

const char *get_audio_indevice_name()
{
	if (strlen(Option::inDevice()))
		return Option::inDevice();
	else if (strlen(Option::device()))
		return Option::device();
	return NULL;
}

const char *get_audio_outdevice_name()
{
	if (strlen(Option::outDevice()))
		return Option::outDevice();
	else if (strlen(Option::device()))
		return Option::device();
	return NULL;
}

AudioDevice *
create_audio_devices(int record, int play, int chans, float srate, int *buffersize, int numBuffers)
{
	int status;
	const char *inDeviceName = get_audio_indevice_name();
	const char *outDeviceName = get_audio_outdevice_name();
	AudioDevice *device = NULL;

#ifdef NETAUDIO
	// For backwards compatibility, we check to see if a network path was set
	// via the command line and stored in the global.
	if (strlen(globalNetworkPath) > 0)
		outDeviceName = globalNetworkPath;
#endif	// NETAUDIO

	// See audio_dev_creator.cpp for this function.
	device = createAudioDevice(inDeviceName, outDeviceName, record, play);
	if (device == NULL) {
		die("rtsetparams", "Failed to create audio device.");
		return NULL;
	}

	// We hand the device noninterleaved, full-range floating point buffers.
	int audioFormat = NATIVE_FLOAT_FMT | MUS_NON_INTERLEAVED;
	device->setFrameFormat(audioFormat, chans);

	int openMode = (record && play) ? AudioDevice::RecordPlayback
				   : (record) ? AudioDevice::Record
				   : AudioDevice::Playback;
	if (Option::checkPeaks())
		openMode |= AudioDevice::CheckPeaks;
	if (Option::reportClipping())
		openMode |= AudioDevice::ReportClipping;

#if DEBUG > 0
	printf("DEBUG: audio device: peak check: %d report clip: %d\n",
		   !!(openMode & AudioDevice::CheckPeaks),
		   !!(openMode & AudioDevice::ReportClipping));
#endif

	if ((status = device->open(openMode, audioFormat, chans, srate)) == 0)
	{
		int reqsize = *buffersize;
		int reqcount = numBuffers;
		if ((status = device->setQueueSize(&reqsize, &reqcount)) < 0) {
			die("rtsetparams", "%s", device->getLastError());
			delete device;
			return NULL;
		}
		int newSize = reqsize * numBuffers / reqcount;
		if (newSize != *buffersize) {
			advise("rtsetparams",
				   "Buffer size reset by audio device from %d to %d frames.",
					*buffersize, newSize);
			*buffersize = newSize;
		}
	}
	else
	{
		die("rtsetparams", "%s", device->getLastError());
		delete device;
		return NULL;
	}

	return device;
}

AudioDevice *
create_audio_file_device(AudioDevice *inDevice,
						 const char *outfilename,
						 int header_type,
						 int sample_format,
						 int chans,
						 float srate,
						 int normalize_output_floats,
						 int check_peaks)
{
	assert(rtsetparams_was_called());

	AudioDevice *device = NULL;

	AudioFileDevice *fileDevice = new AudioFileDevice(outfilename,
													  header_type);

	if (fileDevice == NULL) {
		rterror("rtoutput", "Failed to create audio file device");
		return NULL;
	}

	// Here is the logic for opening the file device.  We do this all in
	// advance now, rather than over and over during rtwritesamps().

	const bool recording = Option::record();
	const bool playing = Option::play();
	const bool fileIsRawFloats = IS_FLOAT_FORMAT(sample_format) && !normalize_output_floats;

	int openMode = AudioFileDevice::Playback;
	if (playing | recording)
		openMode |= AudioDevice::Passive;		// Don't run thread for file device.
	if (!fileIsRawFloats || (check_peaks && !playing))
		openMode |= AudioDevice::CheckPeaks;	// Dont check peaks if HW already doing so.
	if (Option::reportClipping() && !playing)
		openMode |= AudioDevice::ReportClipping;	// Ditto for reporting of clipping

#if DEBUG > 0
	printf("DEBUG: file device: peak check: %d report clip: %d\n",
		   openMode & AudioDevice::CheckPeaks, openMode & AudioDevice::ReportClipping);
#endif

	// We send the device noninterleaved, floating point buffers.  If we are playing
	// to HW at the same time, the data received by the file device will already be
	// clipped.

	int audioFormat = NATIVE_FLOAT_FMT | MUS_NON_INTERLEAVED;
	if (playing) audioFormat |= MUS_CLIPPED;

	fileDevice->setFrameFormat(audioFormat, chans);

	// File format is interleaved and may be normalized.
	sample_format |= MUS_INTERLEAVED;
	if (normalize_output_floats)
		sample_format |= MUS_NORMALIZED;
	int ret = fileDevice->open(openMode, sample_format, chans, srate);

	if (ret == -1) {
		rterror("rtoutput", "Can't create output for \"%s\": %s",
				 outfilename, fileDevice->getLastError());
		delete fileDevice;
		return NULL;
	}
	// Cheating -- should hand in queue size as argument!
	int queueSize = RTcmix::bufsamps();
	int count = 1;
	ret = fileDevice->setQueueSize(&queueSize, &count);
	if (ret == -1) {
		rterror("rtoutput", "Failed to set queue size on file device:  %s",
				 fileDevice->getLastError());
		delete fileDevice;
		return NULL;
	}

	if (!playing && !recording) {	// To file only.
		// If we are only writing to disk, we only have a single output device.
		assert(inDevice == NULL);	// We should not have been passed anything.
		device = fileDevice;
	}
	else {							// To file, plus record and/or playback.
		assert(inDevice != NULL);
		if (playing && !recording) {		// Dual outputs to both HW and file.
#if DEBUG > 0
			printf("DEBUG: Group output device for file and HW playback\n");
#endif
			bool fileDoesLimiting = !fileIsRawFloats;
			device = new DualOutputAudioDevice(inDevice,
											  fileDevice,
											  fileDoesLimiting);
		}
		else if (recording && !playing) {	// Record from HW, write to file.
#if DEBUG > 0
			printf("DEBUG: Dual device for HW record, file playback\n");
#endif
			device = new AudioIODevice(inDevice, fileDevice, true);
		}
		else {	// HW Record and playback, plus write to file.
#if DEBUG > 0
			printf("DEBUG: Dual device for HW record/playback, file playback\n");
#endif
			bool fileDoesLimiting = !fileIsRawFloats;
			device = new DualOutputAudioDevice(inDevice,
											   fileDevice,
											   fileDoesLimiting);
		}
	}

	if (Option::print()) {
		 printf("Output file set for writing:\n");
		 printf("      name:  %s\n", outfilename);
		 printf("      type:  %s\n", mus_header_type_name(header_type));
		 printf("    format:  %s\n", mus_data_format_name(MUS_GET_FORMAT(sample_format)));
		 printf("     srate:  %g\n", srate);
		 printf("     chans:  %d\n", chans);
	}

	return device;
}

<commit_msg>oops, turn off debugging msgs.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
// audio_devices.cpp
// C++ functions for creating and configuring AudioDevice instances for input
// and output.
//

#include <string.h>
#include <RTcmix.h>
#include <sndlibsupport.h>
#include <ugens.h>
#include <prototypes.h>
#include <assert.h>
#include <Option.h>

#include "AudioDevice.h"
#include "AudioFileDevice.h"
#include "AudioIODevice.h"
#include "AudioOutputGroupDevice.h"
#include "DualOutputAudioDevice.h"
#include "audio_devices.h"

#define DEBUG	0

#ifdef NETAUDIO
char globalNetworkPath[128];			// Set by Minc/setnetplay.c
#endif

// Return pointers to the most recently specified audio device strings.
// "indevice" always overrides "device", and same with "outdevice".

const char *get_audio_device_name()
{
	if (strlen(Option::inDevice()) || strlen(Option::outDevice()))
		return NULL;
	if (strlen(Option::device()))
		return Option::device();
	return NULL;
}

const char *get_audio_indevice_name()
{
	if (strlen(Option::inDevice()))
		return Option::inDevice();
	else if (strlen(Option::device()))
		return Option::device();
	return NULL;
}

const char *get_audio_outdevice_name()
{
	if (strlen(Option::outDevice()))
		return Option::outDevice();
	else if (strlen(Option::device()))
		return Option::device();
	return NULL;
}

AudioDevice *
create_audio_devices(int record, int play, int chans, float srate, int *buffersize, int numBuffers)
{
	int status;
	const char *inDeviceName = get_audio_indevice_name();
	const char *outDeviceName = get_audio_outdevice_name();
	AudioDevice *device = NULL;

#ifdef NETAUDIO
	// For backwards compatibility, we check to see if a network path was set
	// via the command line and stored in the global.
	if (strlen(globalNetworkPath) > 0)
		outDeviceName = globalNetworkPath;
#endif	// NETAUDIO

	// See audio_dev_creator.cpp for this function.
	device = createAudioDevice(inDeviceName, outDeviceName, record, play);
	if (device == NULL) {
		die("rtsetparams", "Failed to create audio device.");
		return NULL;
	}

	// We hand the device noninterleaved, full-range floating point buffers.
	int audioFormat = NATIVE_FLOAT_FMT | MUS_NON_INTERLEAVED;
	device->setFrameFormat(audioFormat, chans);

	int openMode = (record && play) ? AudioDevice::RecordPlayback
				   : (record) ? AudioDevice::Record
				   : AudioDevice::Playback;
	if (Option::checkPeaks())
		openMode |= AudioDevice::CheckPeaks;
	if (Option::reportClipping())
		openMode |= AudioDevice::ReportClipping;

#if DEBUG > 0
	printf("DEBUG: audio device: peak check: %d report clip: %d\n",
		   !!(openMode & AudioDevice::CheckPeaks),
		   !!(openMode & AudioDevice::ReportClipping));
#endif

	if ((status = device->open(openMode, audioFormat, chans, srate)) == 0)
	{
		int reqsize = *buffersize;
		int reqcount = numBuffers;
		if ((status = device->setQueueSize(&reqsize, &reqcount)) < 0) {
			die("rtsetparams", "%s", device->getLastError());
			delete device;
			return NULL;
		}
		int newSize = reqsize * numBuffers / reqcount;
		if (newSize != *buffersize) {
			advise("rtsetparams",
				   "Buffer size reset by audio device from %d to %d frames.",
					*buffersize, newSize);
			*buffersize = newSize;
		}
	}
	else
	{
		die("rtsetparams", "%s", device->getLastError());
		delete device;
		return NULL;
	}

	return device;
}

AudioDevice *
create_audio_file_device(AudioDevice *inDevice,
						 const char *outfilename,
						 int header_type,
						 int sample_format,
						 int chans,
						 float srate,
						 int normalize_output_floats,
						 int check_peaks)
{
	assert(rtsetparams_was_called());

	AudioDevice *device = NULL;

	AudioFileDevice *fileDevice = new AudioFileDevice(outfilename,
													  header_type);

	if (fileDevice == NULL) {
		rterror("rtoutput", "Failed to create audio file device");
		return NULL;
	}

	// Here is the logic for opening the file device.  We do this all in
	// advance now, rather than over and over during rtwritesamps().

	const bool recording = Option::record();
	const bool playing = Option::play();
	const bool fileIsRawFloats = IS_FLOAT_FORMAT(sample_format) && !normalize_output_floats;

	int openMode = AudioFileDevice::Playback;
	if (playing | recording)
		openMode |= AudioDevice::Passive;		// Don't run thread for file device.
	if (!fileIsRawFloats || (check_peaks && !playing))
		openMode |= AudioDevice::CheckPeaks;	// Dont check peaks if HW already doing so.
	if (Option::reportClipping() && !playing)
		openMode |= AudioDevice::ReportClipping;	// Ditto for reporting of clipping

#if DEBUG > 0
	printf("DEBUG: file device: peak check: %d report clip: %d\n",
		   openMode & AudioDevice::CheckPeaks, openMode & AudioDevice::ReportClipping);
#endif

	// We send the device noninterleaved, floating point buffers.  If we are playing
	// to HW at the same time, the data received by the file device will already be
	// clipped.

	int audioFormat = NATIVE_FLOAT_FMT | MUS_NON_INTERLEAVED;
	if (playing) audioFormat |= MUS_CLIPPED;

	fileDevice->setFrameFormat(audioFormat, chans);

	// File format is interleaved and may be normalized.
	sample_format |= MUS_INTERLEAVED;
	if (normalize_output_floats)
		sample_format |= MUS_NORMALIZED;
	int ret = fileDevice->open(openMode, sample_format, chans, srate);

	if (ret == -1) {
		rterror("rtoutput", "Can't create output for \"%s\": %s",
				 outfilename, fileDevice->getLastError());
		delete fileDevice;
		return NULL;
	}
	// Cheating -- should hand in queue size as argument!
	int queueSize = RTcmix::bufsamps();
	int count = 1;
	ret = fileDevice->setQueueSize(&queueSize, &count);
	if (ret == -1) {
		rterror("rtoutput", "Failed to set queue size on file device:  %s",
				 fileDevice->getLastError());
		delete fileDevice;
		return NULL;
	}

	if (!playing && !recording) {	// To file only.
		// If we are only writing to disk, we only have a single output device.
		assert(inDevice == NULL);	// We should not have been passed anything.
		device = fileDevice;
	}
	else {							// To file, plus record and/or playback.
		assert(inDevice != NULL);
		if (playing && !recording) {		// Dual outputs to both HW and file.
#if DEBUG > 0
			printf("DEBUG: Group output device for file and HW playback\n");
#endif
			bool fileDoesLimiting = !fileIsRawFloats;
			device = new DualOutputAudioDevice(inDevice,
											  fileDevice,
											  fileDoesLimiting);
		}
		else if (recording && !playing) {	// Record from HW, write to file.
#if DEBUG > 0
			printf("DEBUG: Dual device for HW record, file playback\n");
#endif
			device = new AudioIODevice(inDevice, fileDevice, true);
		}
		else {	// HW Record and playback, plus write to file.
#if DEBUG > 0
			printf("DEBUG: Dual device for HW record/playback, file playback\n");
#endif
			bool fileDoesLimiting = !fileIsRawFloats;
			device = new DualOutputAudioDevice(inDevice,
											   fileDevice,
											   fileDoesLimiting);
		}
	}

	if (Option::print()) {
		 printf("Output file set for writing:\n");
		 printf("      name:  %s\n", outfilename);
		 printf("      type:  %s\n", mus_header_type_name(header_type));
		 printf("    format:  %s\n", mus_data_format_name(MUS_GET_FORMAT(sample_format)));
		 printf("     srate:  %g\n", srate);
		 printf("     chans:  %d\n", chans);
	}

	return device;
}

<|endoftext|>


<commit_before>// Source : https://oj.leetcode.com/problems/pascals-triangle/
// Author : Hao Chen
// Date   : 2014-06-18

/**********************************************************************************
*
* Given numRows, generate the first numRows of Pascal's triangle.
*
* For example, given numRows = 5,
* Return
*
* [
*      [1],
*     [1,1],
*    [1,2,1],
*   [1,3,3,1],
*  [1,4,6,4,1]
* ]
*
*
**********************************************************************************/

#include <stdlib.h>
#include <vector>
#include <iostream>
using namespace std;

vector<vector<int> > generate(int numRows)
{
    vector<vector<int> > pascalTriangle;
    for (int i=0; i<numRows; i++){
        vector<int> v;
        if (i==0){
            v.push_back(1);
        } else {
            v.push_back(1);
            for(int j=0; j<pascalTriangle[i-1].size()-1; j++){
                v.push_back(pascalTriangle[i-1][j] + pascalTriangle[i-1][j+1]);
            }
            v.push_back(1);
        }
        pascalTriangle.push_back(v);
    }
    return pascalTriangle;
}

void printVector(vector< vector<int> > pt)
{
    for(int i=0; i<pt.size(); i++){
        cout << "{ ";
        for(int j=0; j<pt[i].size(); j++){
            cout << pt[i][j] << ", ";
        }
        cout << "} " << endl;
    }
}

int main(int argc, char** argv)
{
    int n = atoi(argv[1]);
    printVector(generate(n));
}
<commit_msg>format output<commit_after>// Source : https://oj.leetcode.com/problems/pascals-triangle/
// Author : Hao Chen
// Date   : 2014-06-18

/**********************************************************************************
*
* Given numRows, generate the first numRows of Pascal's triangle.
*
* For example, given numRows = 5,
* Return
*
* [
*      [1],
*     [1,1],
*    [1,2,1],
*   [1,3,3,1],
*  [1,4,6,4,1]
* ]
*
*
**********************************************************************************/

#include <stdlib.h>
#include <vector>
#include <iostream>
using namespace std;

vector<vector<int> > generate(int numRows)
{
    vector<vector<int> > pascalTriangle;
    for (int i=0; i<numRows; i++){
        vector<int> v;
        if (i==0){
            v.push_back(1);
        } else {
            v.push_back(1);
            for(int j=0; j<pascalTriangle[i-1].size()-1; j++){
                v.push_back(pascalTriangle[i-1][j] + pascalTriangle[i-1][j+1]);
            }
            v.push_back(1);
        }
        pascalTriangle.push_back(v);
    }
    return pascalTriangle;
}

void printVector(vector< vector<int> > pt)
{
	cout << "[" << endl;
    for(int i=0; i<pt.size(); i++){
    	for(int space=(pt.size()-i-1); space>=0; space--){
    		cout << " ";
    	}
        cout << "[";
        for(int j=0; j<pt[i].size(); j++){
            cout << pt[i][j];
            if(j<pt[i].size()-1){
            	cout << ",";
            }
        }
        cout << "]";
        if(i<pt.size()-1){
        	cout << ",";
        }
        cout << endl;
    }
    cout << "]" << endl;
}

int main(int argc, char** argv)
{
    int n = atoi(argv[1]);
    printVector(generate(n));
}
<|endoftext|>


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

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"
#include "otbCoordinateToName.h"

namespace otb
{
namespace Wrapper
{

class ReadImageInfo : public Application
{
public:
  /** Standard class typedefs. */
  typedef ReadImageInfo                 Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(ReadImageInfo, otb::Application);

private:
  ReadImageInfo()
  {
    SetName("ReadImageInfo");
    SetDescription("Get information about the image");

    // Documentation
    SetDocName("Read image information Application");
    SetDocLongDescription("Display informations about the input image like: image size, metadata, projections...");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag("Utilities");
    AddDocTag(Tags::Meta);
  }

  virtual ~ReadImageInfo()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImage,  "in",   "Input Image");

    //Create output parameters to store image informations
    AddParameter(ParameterType_Int,"sizex","Size X");
    GetParameterByKey("sizex")->SetRole(Role_Output);
    AddParameter(ParameterType_Int,"sizey","Size Y");
    GetParameterByKey("sizey")->SetRole(Role_Output);

    AddParameter(ParameterType_Int,"spacingx","Pixel Size X");
    GetParameterByKey("spacingx")->SetRole(Role_Output);
    AddParameter(ParameterType_Int,"spacingy","Pixel Size Y");
    GetParameterByKey("spacingy")->SetRole(Role_Output);
    AddParameter(ParameterType_Int,"numberbands","Number Of Bands");
    GetParameterByKey("numberbands")->SetRole(Role_Output);

    AddParameter(ParameterType_String,"sensor","Sensor id");
    GetParameterByKey("sensor")->SetRole(Role_Output);
    MandatoryOff("sensor");

    AddParameter(ParameterType_String,"id","Id of the image");
    GetParameterByKey("id")->SetRole(Role_Output);

    AddParameter(ParameterType_String,"time","Acquisition time");
    GetParameterByKey("time")->SetRole(Role_Output);

    AddParameter(ParameterType_Float,"ullat","Upper left lattitude");
    GetParameterByKey("ullat")->SetRole(Role_Output);
    SetDefaultParameterFloat("ullat", 0);
    AddParameter(ParameterType_Float,"ullon","Upper left longitude");
    GetParameterByKey("ullon")->SetRole(Role_Output);
    SetDefaultParameterFloat("ullon", 0);
    AddParameter(ParameterType_Float,"urlat","Upper right lattitude");
    GetParameterByKey("urlat")->SetRole(Role_Output);
    SetDefaultParameterFloat("urlat", 0);
    AddParameter(ParameterType_Float,"urlon","Upper right longitude");
    GetParameterByKey("urlon")->SetRole(Role_Output);
    SetDefaultParameterFloat("urlon", 0);
    AddParameter(ParameterType_Float,"lrlat","Lower right lattitude");
    GetParameterByKey("lrlat")->SetRole(Role_Output);
    SetDefaultParameterFloat("lrlat", 0);
    AddParameter(ParameterType_Float,"lrlon","Lower right longitude");
    GetParameterByKey("lrlon")->SetRole(Role_Output);
    SetDefaultParameterFloat("lrlon", 0);
    AddParameter(ParameterType_Float,"lllat","Lower left lattitude");
    GetParameterByKey("lllat")->SetRole(Role_Output);
    SetDefaultParameterFloat("lllat", 0);
    AddParameter(ParameterType_Float,"lllon","Lower left longitude");
    GetParameterByKey("lllon")->SetRole(Role_Output);
    SetDefaultParameterFloat("lllon", 0);

    AddParameter(ParameterType_String,"town","Main town near center of image");
    GetParameterByKey("town")->SetRole(Role_Output);

    AddParameter(ParameterType_String,"country","Country of the image");
    GetParameterByKey("country")->SetRole(Role_Output);

    AddParameter(ParameterType_Group, "rgb", "Default RGB Display");
    SetParameterDescription("rgb","This group of parameters allows to access to the default rgb composition.");
    GetParameterByKey("rgb")->SetRole(Role_Output);

    AddParameter(ParameterType_Int, "rgb.r", "Red Band");
    SetParameterDescription("rgb.r","Red band Number");
    SetDefaultParameterInt("rgb.r", 1);

    AddParameter(ParameterType_Int, "rgb.g", "Green Band");
    SetParameterDescription("rgb.g","Green band Number");
    SetDefaultParameterInt("rgb.g", 2);

    AddParameter(ParameterType_Int, "rgb.b", "Blue Band");
    SetParameterDescription("rgb.b","Blue band Number");
    SetDefaultParameterInt("rgb.b", 3);

    AddParameter(ParameterType_String,"projectionref","Projection Coordinate System");
    GetParameterByKey("projectionref")->SetRole(Role_Output);

    AddParameter(ParameterType_String,"keywordlist","Image Keywordlist");
    GetParameterByKey("keywordlist")->SetRole(Role_Output);

    AddParameter(ParameterType_Group, "gcp", "Ground Control Points informations");
    SetParameterDescription("gcp","This group of parameters allows to access to the GCPs informations.");
    GetParameterByKey("gcp")->SetRole(Role_Output);

    AddParameter(ParameterType_Int, "gcp.count", "GCPs Number");
    SetParameterDescription("gcp.count","Number of GCPs");
    SetDefaultParameterInt("gcp.count", 0);

    AddParameter(ParameterType_String,"gcp.proj","GCP Projection System");

    AddParameter(ParameterType_StringList,"gcp.ids","GCPs Id");
    AddParameter(ParameterType_StringList,"gcp.info","GCPs Info");

    // Doc example parameter settings
    SetDocExampleParameterValue("in", "QB_Toulouse_Ortho_XS.tif");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    try
      {
      FloatVectorImageType::Pointer inImage = GetParameterImage("in");
      // Read informations
      typedef otb::ImageMetadataInterfaceBase ImageMetadataInterfaceType;
      ImageMetadataInterfaceType::Pointer metadataInterface = ImageMetadataInterfaceFactory::CreateIMI(inImage->GetMetaDataDictionary());

      //Get image size
      SetParameterInt("sizex",inImage->GetLargestPossibleRegion().GetSize()[0]);
      SetParameterInt("sizey",inImage->GetLargestPossibleRegion().GetSize()[1]);

      //Get image spacing
      SetParameterInt("spacingx",inImage->GetSpacing()[0]);
      SetParameterInt("spacingy",inImage->GetSpacing()[1]);

      SetParameterInt("numberbands",inImage->GetNumberOfComponentsPerPixel());

      //std::cout << "metadata " << metadataInterface << std::endl;
      SetParameterString("sensor",metadataInterface->GetSensorID());
      SetParameterString("id",metadataInterface->GetImageKeywordlist().GetMetadataByKey("image_id"));
      SetParameterString("projectionref",metadataInterface->GetProjectionRef());

      // Format acquisition time
      itk::OStringStream osstime;
      osstime<<metadataInterface->GetYear()<<"-";
      if(metadataInterface->GetMonth()<10)
        osstime<<"0";
      osstime<<metadataInterface->GetMonth()<<"-";
      if(metadataInterface->GetDay()<10)
        osstime<<"0";
      osstime<<metadataInterface->GetDay()<<"T";
      if(metadataInterface->GetHour()<10)
        osstime<<"0";
      osstime<<metadataInterface->GetHour()<<":";
      if(metadataInterface->GetMinute()<10)
        osstime<<"0";
      osstime<<metadataInterface->GetMinute();
      osstime<<":00";
      SetParameterString("time",osstime.str());

      itk::OStringStream osskeywordlist;
      osskeywordlist<<metadataInterface->GetImageKeywordlist() << std::endl;
      SetParameterString("keywordlist",osskeywordlist.str());

      double ullat = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ul_lat").c_str());
      double ullon = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ul_lon").c_str());
      double urlat = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ur_lat").c_str());
      double urlon = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ur_lon").c_str());
      double lrlat = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("lr_lat").c_str());
      double lrlon = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("lr_lon").c_str());
      double lllat = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ll_lat").c_str());
      double lllon = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ll_lon").c_str());

      SetParameterInt("rgb.r",metadataInterface->GetDefaultDisplay()[0]);
      SetParameterInt("rgb.g",metadataInterface->GetDefaultDisplay()[1]);
      SetParameterInt("rgb.b",metadataInterface->GetDefaultDisplay()[2]);

      SetParameterInt("gcp.count",metadataInterface->GetGCPCount());
      SetParameterString("gcp.proj",metadataInterface->GetGCPProjection());

      std::vector<std::string> gcp_ids;
      std::vector<std::string> gcp_infos;

      for(int gcpIdx = 0; gcpIdx  < GetParameterInt("gcp.count"); ++ gcpIdx)
        {
        gcp_ids.push_back(metadataInterface->GetGCPId(gcpIdx));
        gcp_infos.push_back(metadataInterface->GetGCPInfo(gcpIdx));
        }

      SetParameterStringList("gcp.ids",gcp_ids);
      SetParameterStringList("gcp.info",gcp_infos);

      // Retrieve footprint
      SetParameterFloat("ullat",ullat);
      SetParameterFloat("ullon",ullon);
      SetParameterFloat("urlat",urlat);
      SetParameterFloat("urlon",urlon);
      SetParameterFloat("lrlat",lrlat);
      SetParameterFloat("lrlon",lrlon);
      SetParameterFloat("lllat",lllat);
      SetParameterFloat("lllon",lllon);

      double centerlat = 0.25*(ullat+urlat+lrlat+lllat);
      double centerlon = 0.25*(ullon+urlon+lrlon+lllon);

      CoordinateToName::Pointer coord2name = CoordinateToName::New();
      coord2name->SetLat(centerlat);
      coord2name->SetLon(centerlon);
      coord2name->Evaluate();

      SetParameterString("town",coord2name->GetPlaceName());
      SetParameterString("country",coord2name->GetCountryName());
      }
    catch ( itk::ExceptionObject & err )
      {
      //Do nothing at all
      }
    //FIXME Logger must output also parameter groups
    this->GetLogger()->Info("");
  }

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::ReadImageInfo)
<commit_msg>STYLE:kwstyle<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"
#include "otbCoordinateToName.h"

namespace otb
{
namespace Wrapper
{

class ReadImageInfo : public Application
{
public:
  /** Standard class typedefs. */
  typedef ReadImageInfo                 Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(ReadImageInfo, otb::Application);

private:
  ReadImageInfo()
  {
    SetName("ReadImageInfo");
    SetDescription("Get information about the image");

    // Documentation
    SetDocName("Read image information Application");
    SetDocLongDescription("Display informations about the input image like: image size, metadata, projections...");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag("Utilities");
    AddDocTag(Tags::Meta);
  }

  virtual ~ReadImageInfo()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImage,  "in",   "Input Image");

    //Create output parameters to store image informations
    AddParameter(ParameterType_Int,"sizex","Size X");
    GetParameterByKey("sizex")->SetRole(Role_Output);
    AddParameter(ParameterType_Int,"sizey","Size Y");
    GetParameterByKey("sizey")->SetRole(Role_Output);

    AddParameter(ParameterType_Int,"spacingx","Pixel Size X");
    GetParameterByKey("spacingx")->SetRole(Role_Output);
    AddParameter(ParameterType_Int,"spacingy","Pixel Size Y");
    GetParameterByKey("spacingy")->SetRole(Role_Output);
    AddParameter(ParameterType_Int,"numberbands","Number Of Bands");
    GetParameterByKey("numberbands")->SetRole(Role_Output);

    AddParameter(ParameterType_String,"sensor","Sensor id");
    GetParameterByKey("sensor")->SetRole(Role_Output);
    MandatoryOff("sensor");

    AddParameter(ParameterType_String,"id","Id of the image");
    GetParameterByKey("id")->SetRole(Role_Output);

    AddParameter(ParameterType_String,"time","Acquisition time");
    GetParameterByKey("time")->SetRole(Role_Output);

    AddParameter(ParameterType_Float,"ullat","Upper left lattitude");
    GetParameterByKey("ullat")->SetRole(Role_Output);
    SetDefaultParameterFloat("ullat", 0);
    AddParameter(ParameterType_Float,"ullon","Upper left longitude");
    GetParameterByKey("ullon")->SetRole(Role_Output);
    SetDefaultParameterFloat("ullon", 0);
    AddParameter(ParameterType_Float,"urlat","Upper right lattitude");
    GetParameterByKey("urlat")->SetRole(Role_Output);
    SetDefaultParameterFloat("urlat", 0);
    AddParameter(ParameterType_Float,"urlon","Upper right longitude");
    GetParameterByKey("urlon")->SetRole(Role_Output);
    SetDefaultParameterFloat("urlon", 0);
    AddParameter(ParameterType_Float,"lrlat","Lower right lattitude");
    GetParameterByKey("lrlat")->SetRole(Role_Output);
    SetDefaultParameterFloat("lrlat", 0);
    AddParameter(ParameterType_Float,"lrlon","Lower right longitude");
    GetParameterByKey("lrlon")->SetRole(Role_Output);
    SetDefaultParameterFloat("lrlon", 0);
    AddParameter(ParameterType_Float,"lllat","Lower left lattitude");
    GetParameterByKey("lllat")->SetRole(Role_Output);
    SetDefaultParameterFloat("lllat", 0);
    AddParameter(ParameterType_Float,"lllon","Lower left longitude");
    GetParameterByKey("lllon")->SetRole(Role_Output);
    SetDefaultParameterFloat("lllon", 0);

    AddParameter(ParameterType_String,"town","Main town near center of image");
    GetParameterByKey("town")->SetRole(Role_Output);

    AddParameter(ParameterType_String,"country","Country of the image");
    GetParameterByKey("country")->SetRole(Role_Output);

    AddParameter(ParameterType_Group, "rgb", "Default RGB Display");
    SetParameterDescription("rgb","This group of parameters allows to access to the default rgb composition.");
    GetParameterByKey("rgb")->SetRole(Role_Output);

    AddParameter(ParameterType_Int, "rgb.r", "Red Band");
    SetParameterDescription("rgb.r","Red band Number");
    SetDefaultParameterInt("rgb.r", 1);

    AddParameter(ParameterType_Int, "rgb.g", "Green Band");
    SetParameterDescription("rgb.g","Green band Number");
    SetDefaultParameterInt("rgb.g", 2);

    AddParameter(ParameterType_Int, "rgb.b", "Blue Band");
    SetParameterDescription("rgb.b","Blue band Number");
    SetDefaultParameterInt("rgb.b", 3);

    AddParameter(ParameterType_String,"projectionref","Projection Coordinate System");
    GetParameterByKey("projectionref")->SetRole(Role_Output);

    AddParameter(ParameterType_String,"keywordlist","Image Keywordlist");
    GetParameterByKey("keywordlist")->SetRole(Role_Output);

    AddParameter(ParameterType_Group, "gcp", "Ground Control Points informations");
    SetParameterDescription("gcp","This group of parameters allows to access to the GCPs informations.");
    GetParameterByKey("gcp")->SetRole(Role_Output);

    AddParameter(ParameterType_Int, "gcp.count", "GCPs Number");
    SetParameterDescription("gcp.count","Number of GCPs");
    SetDefaultParameterInt("gcp.count", 0);

    AddParameter(ParameterType_String,"gcp.proj","GCP Projection System");

    AddParameter(ParameterType_StringList,"gcp.ids","GCPs Id");
    AddParameter(ParameterType_StringList,"gcp.info","GCPs Info");

    // Doc example parameter settings
    SetDocExampleParameterValue("in", "QB_Toulouse_Ortho_XS.tif");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    try
      {
      FloatVectorImageType::Pointer inImage = GetParameterImage("in");
      // Read informations
      typedef otb::ImageMetadataInterfaceBase ImageMetadataInterfaceType;
      ImageMetadataInterfaceType::Pointer metadataInterface = ImageMetadataInterfaceFactory::CreateIMI(inImage->GetMetaDataDictionary());

      //Get image size
      SetParameterInt("sizex",inImage->GetLargestPossibleRegion().GetSize()[0]);
      SetParameterInt("sizey",inImage->GetLargestPossibleRegion().GetSize()[1]);

      //Get image spacing
      SetParameterInt("spacingx",inImage->GetSpacing()[0]);
      SetParameterInt("spacingy",inImage->GetSpacing()[1]);

      SetParameterInt("numberbands",inImage->GetNumberOfComponentsPerPixel());

      //std::cout << "metadata " << metadataInterface << std::endl;
      SetParameterString("sensor",metadataInterface->GetSensorID());
      SetParameterString("id",metadataInterface->GetImageKeywordlist().GetMetadataByKey("image_id"));
      SetParameterString("projectionref",metadataInterface->GetProjectionRef());

      // Format acquisition time
      itk::OStringStream osstime;
      osstime<<metadataInterface->GetYear()<<"-";
      if(metadataInterface->GetMonth()<10)
        osstime<<"0";
      osstime<<metadataInterface->GetMonth()<<"-";
      if(metadataInterface->GetDay()<10)
        osstime<<"0";
      osstime<<metadataInterface->GetDay()<<"T";
      if(metadataInterface->GetHour()<10)
        osstime<<"0";
      osstime<<metadataInterface->GetHour()<<":";
      if(metadataInterface->GetMinute()<10)
        osstime<<"0";
      osstime<<metadataInterface->GetMinute();
      osstime<<":00";
      SetParameterString("time",osstime.str());

      itk::OStringStream osskeywordlist;
      osskeywordlist<<metadataInterface->GetImageKeywordlist() << std::endl;
      SetParameterString("keywordlist",osskeywordlist.str());

      double ullat = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ul_lat").c_str());
      double ullon = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ul_lon").c_str());
      double urlat = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ur_lat").c_str());
      double urlon = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ur_lon").c_str());
      double lrlat = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("lr_lat").c_str());
      double lrlon = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("lr_lon").c_str());
      double lllat = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ll_lat").c_str());
      double lllon = atof(metadataInterface->GetImageKeywordlist().GetMetadataByKey("ll_lon").c_str());

      SetParameterInt("rgb.r",metadataInterface->GetDefaultDisplay()[0]);
      SetParameterInt("rgb.g",metadataInterface->GetDefaultDisplay()[1]);
      SetParameterInt("rgb.b",metadataInterface->GetDefaultDisplay()[2]);

      SetParameterInt("gcp.count",metadataInterface->GetGCPCount());
      SetParameterString("gcp.proj",metadataInterface->GetGCPProjection());

      std::vector<std::string> gcp_ids;
      std::vector<std::string> gcp_infos;

      for(int gcpIdx = 0; gcpIdx  < GetParameterInt("gcp.count"); ++ gcpIdx)
        {
        gcp_ids.push_back(metadataInterface->GetGCPId(gcpIdx));
        gcp_infos.push_back(metadataInterface->GetGCPInfo(gcpIdx));
        }

      SetParameterStringList("gcp.ids",gcp_ids);
      SetParameterStringList("gcp.info",gcp_infos);

      // Retrieve footprint
      SetParameterFloat("ullat",ullat);
      SetParameterFloat("ullon",ullon);
      SetParameterFloat("urlat",urlat);
      SetParameterFloat("urlon",urlon);
      SetParameterFloat("lrlat",lrlat);
      SetParameterFloat("lrlon",lrlon);
      SetParameterFloat("lllat",lllat);
      SetParameterFloat("lllon",lllon);

      double centerlat = 0.25*(ullat+urlat+lrlat+lllat);
      double centerlon = 0.25*(ullon+urlon+lrlon+lllon);

      CoordinateToName::Pointer coord2name = CoordinateToName::New();
      coord2name->SetLat(centerlat);
      coord2name->SetLon(centerlon);
      coord2name->Evaluate();

      SetParameterString("town",coord2name->GetPlaceName());
      SetParameterString("country",coord2name->GetCountryName());
      }
    catch ( itk::ExceptionObject & err )
      {
      //Do nothing at all
      }
    //FIXME Logger must output also parameter groups
    this->GetLogger()->Info("");
  }

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::ReadImageInfo)
<|endoftext|>