<commit_before>/*************************************************************************
 *
 *  $RCSfile: init.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2004-11-17 10:21:06 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "svxdlg.hxx"
#include "dialogs.hrc"

#include "vos/mutex.hxx"
#include <vcl/edit.hxx>
#include <vcl/svapp.hxx>
#include <vcl/dialog.hxx>
#include <vcl/msgbox.hxx>

// ------------------------------------------------------------------------
//Sonderzeichen einfuegen fuer Edits

String GetSpecialCharsForEdit(Window* pParent, const Font& rFont)
{
    String sRet;
    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
    if(pFact)
    {
        AbstractSvxCharacterMap* aDlg = pFact->CreateSvxCharacterMap( pParent, ResId(RID_SVXDLG_CHARMAP) );
        aDlg->DisableFontSelection();
        aDlg->SetCharFont(rFont);
        if ( aDlg->Execute() == RET_OK )
            sRet = aDlg->GetChar();
        delete aDlg;
    }
    return sRet;
}

// ------------------------------------------------------------------------

class Initialize
{
    public:
        Initialize();
        ~Initialize();
};

// ------------------------------------------------------------------------

Initialize::Initialize()
{
#if 0 // commented out since it does not work in nonoffice scenario
    ::vos::OGuard aGuard( Application::GetSolarMutex() );

    // Set special characters callback on vcl edit control
    Edit::SetGetSpecialCharsFunction(&GetSpecialCharsForEdit);
#endif
}

// ------------------------------------------------------------------------

Initialize::~Initialize()
{
}

// ------------------------------------------------------------------------

Initialize aInit;
<commit_msg>INTEGRATION: CWS cd02 (1.2.106); FILE MERGED 2005/01/11 12:44:42 cd 1.2.106.1: #i33483# Make svx based function extern 'C'<commit_after>/*************************************************************************
 *
 *  $RCSfile: init.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-13 18:52:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "svxdlg.hxx"
#include "dialogs.hrc"

#include "vos/mutex.hxx"
#include <vcl/edit.hxx>
#include <vcl/svapp.hxx>
#include <vcl/dialog.hxx>
#include <vcl/msgbox.hxx>

// ------------------------------------------------------------------------
//Sonderzeichen einfuegen fuer Edits

extern "C" String GetSpecialCharsForEdit(Window* pParent, const Font& rFont)
{
    String sRet;
    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
    if(pFact)
    {
        AbstractSvxCharacterMap* aDlg = pFact->CreateSvxCharacterMap( pParent, ResId(RID_SVXDLG_CHARMAP) );
        aDlg->DisableFontSelection();
        aDlg->SetCharFont(rFont);
        if ( aDlg->Execute() == RET_OK )
            sRet = aDlg->GetChar();
        delete aDlg;
    }
    return sRet;
}
<|endoftext|>


<commit_before>//
//  air.hpp
//  OpenTsiolkovsky
//
//  Created by Takahiro Inagawa on 2015/11/23.
//  Copyright © 2015 Takahiro Inagawa. All rights reserved.
//

#ifndef air_hpp
#define air_hpp

#include <stdio.h>
#include "../lib/Eigen/Core"

using namespace std;
using namespace Eigen;

class Air{
private:
    double g = 9.80655;
    double gamma = 1.4;
    double R = 287.0531;
    //    height of atmospheric layer
    int HAL[8] = {0, 11000, 20000, 32000, 47000, 51000, 71000, 84852};
    //    Lapse Rate Kelvin per meter
    double LR[8] = {-0.0065, 0.0, 0.001, 0.0028, 0, -0.0028, -0.002, 0.0};
    //    Tempareture Kelvin
    double T0[8] = {288.15, 216.65, 216.65, 228.65, 270.65, 270.65, 214.65, 186.95};
    //    Pressure Pa
    double P0[8] = {101325, 22632, 5474.9, 868.02, 110.91, 66.939, 3.9564, 0.3734};
    int k = 0;

public:
    double temperature = 300;
    double airspeed = 1200;
    double pressure = 101300;
    double density = 1.2;
    Air altitude(double altitude);
    Air altitude_with_variation(double altitude, double input_percent);
    double coef_density_variance(double altitude, double input_percent);

};

double linear_interp1_from_y(double y, vector<double> x_array, vector<double> y_array);
void test_air();

#endif /* air_hpp */
<commit_msg>#include <vector><commit_after>//
//  air.hpp
//  OpenTsiolkovsky
//
//  Created by Takahiro Inagawa on 2015/11/23.
//  Copyright © 2015 Takahiro Inagawa. All rights reserved.
//

#ifndef air_hpp
#define air_hpp

#include <stdio.h>
#include <vector>
#include "../lib/Eigen/Core"

using namespace std;
using namespace Eigen;

class Air{
private:
    double g = 9.80655;
    double gamma = 1.4;
    double R = 287.0531;
    //    height of atmospheric layer
    int HAL[8] = {0, 11000, 20000, 32000, 47000, 51000, 71000, 84852};
    //    Lapse Rate Kelvin per meter
    double LR[8] = {-0.0065, 0.0, 0.001, 0.0028, 0, -0.0028, -0.002, 0.0};
    //    Tempareture Kelvin
    double T0[8] = {288.15, 216.65, 216.65, 228.65, 270.65, 270.65, 214.65, 186.95};
    //    Pressure Pa
    double P0[8] = {101325, 22632, 5474.9, 868.02, 110.91, 66.939, 3.9564, 0.3734};
    int k = 0;

public:
    double temperature = 300;
    double airspeed = 1200;
    double pressure = 101300;
    double density = 1.2;
    Air altitude(double altitude);
    Air altitude_with_variation(double altitude, double input_percent);
    double coef_density_variance(double altitude, double input_percent);

};

double linear_interp1_from_y(double y, vector<double> x_array, vector<double> y_array);
void test_air();

#endif /* air_hpp */
<|endoftext|>


<commit_before>#include "channel.hpp"

#include "user_channel/channel_layer.hpp"

#include <arpa/inet.h>

#include <boost/process/child.hpp>
#include <fstream>
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <set>
#include <string>
#include <xyz/openbmc_project/Common/error.hpp>

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;

namespace cipher
{

/** @brief Get the supported Cipher records
 *
 * The cipher records are read from the JSON file and converted into
 * 1. cipher suite record format mentioned in the IPMI specification. The
 * records can be either OEM or standard cipher. Each json entry is parsed and
 * converted into the cipher record format and pushed into the vector.
 * 2. Algorithms listed in vector format
 *
 * @return pair of vector containing 1. all the cipher suite records. 2.
 * Algorithms supported
 *
 */
std::pair<std::vector<uint8_t>, std::vector<uint8_t>> getCipherRecords()
{
    std::vector<uint8_t> cipherRecords;
    std::vector<uint8_t> supportedAlgorithmRecords;
    // create set to get the unique supported algorithms
    std::set<uint8_t> supportedAlgorithmSet;

    std::ifstream jsonFile(configFile);
    if (!jsonFile.is_open())
    {
        log<level::ERR>("Channel Cipher suites file not found");
        elog<InternalFailure>();
    }

    auto data = Json::parse(jsonFile, nullptr, false);
    if (data.is_discarded())
    {
        log<level::ERR>("Parsing channel cipher suites JSON failed");
        elog<InternalFailure>();
    }

    for (const auto& record : data)
    {
        if (record.find(oem) != record.end())
        {
            // OEM cipher suite - 0xC1
            cipherRecords.push_back(oemCipherSuite);
            // Cipher Suite ID
            cipherRecords.push_back(record.value(cipher, 0));
            // OEM IANA - 3 bytes
            cipherRecords.push_back(record.value(oem, 0));
            cipherRecords.push_back(record.value(oem, 0) >> 8);
            cipherRecords.push_back(record.value(oem, 0) >> 16);
        }
        else
        {
            // Standard cipher suite - 0xC0
            cipherRecords.push_back(stdCipherSuite);
            // Cipher Suite ID
            cipherRecords.push_back(record.value(cipher, 0));
        }

        // Authentication algorithm number
        cipherRecords.push_back(record.value(auth, 0));
        supportedAlgorithmSet.insert(record.value(auth, 0));

        // Integrity algorithm number
        cipherRecords.push_back(record.value(integrity, 0) | integrityTag);
        supportedAlgorithmSet.insert(record.value(integrity, 0) | integrityTag);

        // Confidentiality algorithm number
        cipherRecords.push_back(record.value(conf, 0) | confTag);
        supportedAlgorithmSet.insert(record.value(conf, 0) | confTag);
    }

    // copy the set to supportedAlgorithmRecord which is vector based.
    std::copy(supportedAlgorithmSet.begin(), supportedAlgorithmSet.end(),
              std::back_inserter(supportedAlgorithmRecords));

    return std::make_pair(cipherRecords, supportedAlgorithmRecords);
}

} // namespace cipher

/** @brief this command is used to look up what authentication, integrity,
 *  confidentiality algorithms are supported.
 *
 *  @ param ctx - context pointer
 *  @ param channelNumber - channel number
 *  @ param payloadType - payload type
 *  @ param listIndex - list index
 *  @ param algoSelectBit - list algorithms
 *
 *  @returns ipmi completion code plus response data
 *  - rspChannel - channel number for authentication algorithm.
 *  - rspRecords - cipher suite records.
 **/
ipmi::RspType<uint8_t,             // Channel Number
              std::vector<uint8_t> // Cipher Records
              >
    getChannelCipherSuites(ipmi::Context::ptr ctx, uint4_t channelNumber,
                           uint4_t reserved1, uint8_t payloadType,
                           uint6_t listIndex, uint1_t reserved2,
                           uint1_t algoSelectBit)
{
    static std::vector<uint8_t> cipherRecords;
    static std::vector<uint8_t> supportedAlgorithms;
    static auto recordInit = false;

    uint8_t rspChannel = ipmi::convertCurrentChannelNum(
        static_cast<uint8_t>(channelNumber), ctx->channel);

    if (!ipmi::isValidChannel(rspChannel) || reserved1 != 0 || reserved2 != 0)
    {
        return ipmi::responseInvalidFieldRequest();
    }

    if (!recordInit)
    {
        try
        {
            std::tie(cipherRecords, supportedAlgorithms) =
                cipher::getCipherRecords();
            recordInit = true;
        }
        catch (const std::exception& e)
        {
            return ipmi::responseUnspecifiedError();
        }
    }

    const std::vector<uint8_t>& records =
        algoSelectBit ? cipherRecords : supportedAlgorithms;
    static constexpr auto respSize = 16;

    // Session support is available in active LAN channels.
    if ((ipmi::getChannelSessionSupport(rspChannel) ==
         ipmi::EChannelSessSupported::none) ||
        !(ipmi::doesDeviceExist(rspChannel)))
    {
        log<level::DEBUG>("Get channel cipher suites - Device does not exist");
        return ipmi::responseInvalidFieldRequest();
    }

    // List index(00h-3Fh), 0h selects the first set of 16, 1h selects the next
    // set of 16 and so on.

    // Calculate the number of record data bytes to be returned.
    auto start =
        std::min(static_cast<size_t>(listIndex) * respSize, records.size());
    auto end = std::min((static_cast<size_t>(listIndex) * respSize) + respSize,
                        records.size());
    auto size = end - start;

    std::vector<uint8_t> rspRecords;
    std::copy_n(records.data() + start, size, std::back_inserter(rspRecords));

    return ipmi::responseSuccess(rspChannel, rspRecords);
}

template <typename... ArgTypes>
static int executeCmd(const char* path, ArgTypes&&... tArgs)
{
    boost::process::child execProg(path, const_cast<char*>(tArgs)...);
    execProg.wait();
    return execProg.exit_code();
}

/** @brief Enable the network IPMI service on the specified ethernet interface.
 *
 *  @param[in] intf - ethernet interface on which to enable IPMI
 */
void enableNetworkIPMI(const std::string& intf)
{
    // Check if there is a iptable filter to drop IPMI packets for the
    // interface.
    auto retCode =
        executeCmd("/usr/sbin/iptables", "-C", "INPUT", "-p", "udp", "-i",
                   intf.c_str(), "--dport", "623", "-j", "DROP");

    // If the iptable filter exists, delete the filter.
    if (!retCode)
    {
        auto response =
            executeCmd("/usr/sbin/iptables", "-D", "INPUT", "-p", "udp", "-i",
                       intf.c_str(), "--dport", "623", "-j", "DROP");

        if (response)
        {
            log<level::ERR>("Dropping the iptables filter failed",
                            entry("INTF=%s", intf.c_str()),
                            entry("RETURN_CODE:%d", response));
        }
    }
}

/** @brief Disable the network IPMI service on the specified ethernet interface.
 *
 *  @param[in] intf - ethernet interface on which to disable IPMI
 */
void disableNetworkIPMI(const std::string& intf)
{
    // Check if there is a iptable filter to drop IPMI packets for the
    // interface.
    auto retCode =
        executeCmd("/usr/sbin/iptables", "-C", "INPUT", "-p", "udp", "-i",
                   intf.c_str(), "--dport", "623", "-j", "DROP");

    // If the iptable filter does not exist, add filter to drop network IPMI
    // packets
    if (retCode)
    {
        auto response =
            executeCmd("/usr/sbin/iptables", "-I", "INPUT", "-p", "udp", "-i",
                       intf.c_str(), "--dport", "623", "-j", "DROP");

        if (response)
        {
            log<level::ERR>("Inserting iptables filter failed",
                            entry("INTF=%s", intf.c_str()),
                            entry("RETURN_CODE:%d", response));
        }
    }
}
<commit_msg>channel:Fix get channel ciphersuite - payloadtypes<commit_after>#include "channel.hpp"

#include "user_channel/channel_layer.hpp"

#include <arpa/inet.h>

#include <boost/process/child.hpp>
#include <fstream>
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <set>
#include <string>
#include <xyz/openbmc_project/Common/error.hpp>

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;

namespace cipher
{

/** @brief Get the supported Cipher records
 *
 * The cipher records are read from the JSON file and converted into
 * 1. cipher suite record format mentioned in the IPMI specification. The
 * records can be either OEM or standard cipher. Each json entry is parsed and
 * converted into the cipher record format and pushed into the vector.
 * 2. Algorithms listed in vector format
 *
 * @return pair of vector containing 1. all the cipher suite records. 2.
 * Algorithms supported
 *
 */
std::pair<std::vector<uint8_t>, std::vector<uint8_t>> getCipherRecords()
{
    std::vector<uint8_t> cipherRecords;
    std::vector<uint8_t> supportedAlgorithmRecords;
    // create set to get the unique supported algorithms
    std::set<uint8_t> supportedAlgorithmSet;

    std::ifstream jsonFile(configFile);
    if (!jsonFile.is_open())
    {
        log<level::ERR>("Channel Cipher suites file not found");
        elog<InternalFailure>();
    }

    auto data = Json::parse(jsonFile, nullptr, false);
    if (data.is_discarded())
    {
        log<level::ERR>("Parsing channel cipher suites JSON failed");
        elog<InternalFailure>();
    }

    for (const auto& record : data)
    {
        if (record.find(oem) != record.end())
        {
            // OEM cipher suite - 0xC1
            cipherRecords.push_back(oemCipherSuite);
            // Cipher Suite ID
            cipherRecords.push_back(record.value(cipher, 0));
            // OEM IANA - 3 bytes
            cipherRecords.push_back(record.value(oem, 0));
            cipherRecords.push_back(record.value(oem, 0) >> 8);
            cipherRecords.push_back(record.value(oem, 0) >> 16);
        }
        else
        {
            // Standard cipher suite - 0xC0
            cipherRecords.push_back(stdCipherSuite);
            // Cipher Suite ID
            cipherRecords.push_back(record.value(cipher, 0));
        }

        // Authentication algorithm number
        cipherRecords.push_back(record.value(auth, 0));
        supportedAlgorithmSet.insert(record.value(auth, 0));

        // Integrity algorithm number
        cipherRecords.push_back(record.value(integrity, 0) | integrityTag);
        supportedAlgorithmSet.insert(record.value(integrity, 0) | integrityTag);

        // Confidentiality algorithm number
        cipherRecords.push_back(record.value(conf, 0) | confTag);
        supportedAlgorithmSet.insert(record.value(conf, 0) | confTag);
    }

    // copy the set to supportedAlgorithmRecord which is vector based.
    std::copy(supportedAlgorithmSet.begin(), supportedAlgorithmSet.end(),
              std::back_inserter(supportedAlgorithmRecords));

    return std::make_pair(cipherRecords, supportedAlgorithmRecords);
}

} // namespace cipher

/** @brief this command is used to look up what authentication, integrity,
 *  confidentiality algorithms are supported.
 *
 *  @ param ctx - context pointer
 *  @ param channelNumber - channel number
 *  @ param payloadType - payload type
 *  @ param listIndex - list index
 *  @ param algoSelectBit - list algorithms
 *
 *  @returns ipmi completion code plus response data
 *  - rspChannel - channel number for authentication algorithm.
 *  - rspRecords - cipher suite records.
 **/
ipmi::RspType<uint8_t,             // Channel Number
              std::vector<uint8_t> // Cipher Records
              >
    getChannelCipherSuites(ipmi::Context::ptr ctx, uint4_t channelNumber,
                           uint4_t reserved1, uint8_t payloadType,
                           uint6_t listIndex, uint1_t reserved2,
                           uint1_t algoSelectBit)
{
    static std::vector<uint8_t> cipherRecords;
    static std::vector<uint8_t> supportedAlgorithms;
    static auto recordInit = false;

    uint8_t rspChannel = ipmi::convertCurrentChannelNum(
        static_cast<uint8_t>(channelNumber), ctx->channel);

    if (!ipmi::isValidChannel(rspChannel) || reserved1 != 0 || reserved2 != 0)
    {
        return ipmi::responseInvalidFieldRequest();
    }
    if (!ipmi::isValidPayloadType(static_cast<ipmi::PayloadType>(payloadType)))
    {
        log<level::DEBUG>("Get channel cipher suites - Invalid payload type");
        constexpr uint8_t ccPayloadTypeNotSupported = 0x80;
        return ipmi::response(ccPayloadTypeNotSupported);
    }

    if (!recordInit)
    {
        try
        {
            std::tie(cipherRecords, supportedAlgorithms) =
                cipher::getCipherRecords();
            recordInit = true;
        }
        catch (const std::exception& e)
        {
            return ipmi::responseUnspecifiedError();
        }
    }

    const std::vector<uint8_t>& records =
        algoSelectBit ? cipherRecords : supportedAlgorithms;
    static constexpr auto respSize = 16;

    // Session support is available in active LAN channels.
    if ((ipmi::getChannelSessionSupport(rspChannel) ==
         ipmi::EChannelSessSupported::none) ||
        !(ipmi::doesDeviceExist(rspChannel)))
    {
        log<level::DEBUG>("Get channel cipher suites - Device does not exist");
        return ipmi::responseInvalidFieldRequest();
    }

    // List index(00h-3Fh), 0h selects the first set of 16, 1h selects the next
    // set of 16 and so on.

    // Calculate the number of record data bytes to be returned.
    auto start =
        std::min(static_cast<size_t>(listIndex) * respSize, records.size());
    auto end = std::min((static_cast<size_t>(listIndex) * respSize) + respSize,
                        records.size());
    auto size = end - start;

    std::vector<uint8_t> rspRecords;
    std::copy_n(records.data() + start, size, std::back_inserter(rspRecords));

    return ipmi::responseSuccess(rspChannel, rspRecords);
}

template <typename... ArgTypes>
static int executeCmd(const char* path, ArgTypes&&... tArgs)
{
    boost::process::child execProg(path, const_cast<char*>(tArgs)...);
    execProg.wait();
    return execProg.exit_code();
}

/** @brief Enable the network IPMI service on the specified ethernet interface.
 *
 *  @param[in] intf - ethernet interface on which to enable IPMI
 */
void enableNetworkIPMI(const std::string& intf)
{
    // Check if there is a iptable filter to drop IPMI packets for the
    // interface.
    auto retCode =
        executeCmd("/usr/sbin/iptables", "-C", "INPUT", "-p", "udp", "-i",
                   intf.c_str(), "--dport", "623", "-j", "DROP");

    // If the iptable filter exists, delete the filter.
    if (!retCode)
    {
        auto response =
            executeCmd("/usr/sbin/iptables", "-D", "INPUT", "-p", "udp", "-i",
                       intf.c_str(), "--dport", "623", "-j", "DROP");

        if (response)
        {
            log<level::ERR>("Dropping the iptables filter failed",
                            entry("INTF=%s", intf.c_str()),
                            entry("RETURN_CODE:%d", response));
        }
    }
}

/** @brief Disable the network IPMI service on the specified ethernet interface.
 *
 *  @param[in] intf - ethernet interface on which to disable IPMI
 */
void disableNetworkIPMI(const std::string& intf)
{
    // Check if there is a iptable filter to drop IPMI packets for the
    // interface.
    auto retCode =
        executeCmd("/usr/sbin/iptables", "-C", "INPUT", "-p", "udp", "-i",
                   intf.c_str(), "--dport", "623", "-j", "DROP");

    // If the iptable filter does not exist, add filter to drop network IPMI
    // packets
    if (retCode)
    {
        auto response =
            executeCmd("/usr/sbin/iptables", "-I", "INPUT", "-p", "udp", "-i",
                       intf.c_str(), "--dport", "623", "-j", "DROP");

        if (response)
        {
            log<level::ERR>("Inserting iptables filter failed",
                            entry("INTF=%s", intf.c_str()),
                            entry("RETURN_CODE:%d", response));
        }
    }
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////////////////////////
// OpenGL Mathematics Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net)
///////////////////////////////////////////////////////////////////////////////////////////////////
// Created : 2005-12-21
// Updated : 2007-08-14
// Licence : This source is under MIT License
// File    : glm/gtx/euler_angles.inl
///////////////////////////////////////////////////////////////////////////////////////////////////

namespace glm
{
	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleX
	(
		valType const & angleX
	)
	{
		valType cosX = glm::cos(angleX);
		valType sinX = glm::sin(angleX);

		return detail::tmat4x4<valType>(
			valType(1), valType(0), valType(0), valType(0),
			valType(0), cosX,		sinX,		valType(0),
			valType(0),-sinX,		cosX,		valType(0),
			valType(0), valType(0), valType(0), valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleY
	(
		valType const & angleY
	)
	{
		valType cosY = glm::cos(angleY);
		valType sinY = glm::sin(angleY);

		return detail::tmat4x4<valType>(
			cosY,		valType(0),	sinY,		valType(0),
			valType(0),	valType(1),	valType(0), valType(0),
			-sinY,		valType(0),	cosY,		valType(0),
			valType(0),	valType(0),	valType(0), valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleZ
	(
		valType const & angleZ
	)
	{
		valType cosZ = glm::cos(angleZ);
		valType sinZ = glm::sin(angleZ);

		return detail::tmat4x4<valType>(
			cosZ,		sinZ,		valType(0), valType(0),
			-sinZ,		cosZ,		valType(0), valType(0),
			valType(0),	valType(0),	valType(1), valType(0),
			valType(0),	valType(0),	valType(0), valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleXY
	(
		valType const & angleX,
		valType const & angleY
	)
	{
		valType cosX = glm::cos(angleX);
		valType sinX = glm::sin(angleX);
		valType cosY = glm::cos(angleY);
		valType sinY = glm::sin(angleY);

		return detail::tmat4x4<valType>(
			cosY,		-sinX * sinY,	cosX * sinY,	valType(0),
			valType(0), cosX,			sinX,			valType(0),
			-sinY ,		-sinX * cosY,	cosX * cosY,	valType(0),
			valType(0), valType(0),     valType(0),		valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleYX
	(
		valType const & angleY,
		valType const & angleX
	)
	{
		valType cosX = glm::cos(angleX);
		valType sinX = glm::sin(angleX);
		valType cosY = glm::cos(angleY);
		valType sinY = glm::sin(angleY);

		return detail::tmat4x4<valType>(
			cosY,			valType(0),		sinY,			valType(0),
			-sinX * sinY,	cosX,			sinX * cosY,	valType(0),
			-cosX * sinY,	-sinX,			cosX * cosY,	valType(0),
			valType(0),		valType(0),		valType(0),		valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleXZ
	(
		valType const & angleX,
		valType const & angleZ
	)
	{
		return eulerAngleX(angleX) * eulerAngleZ(angleZ);
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleZX
	(
		valType const & angleZ,
		valType const & angleX
	)
	{
		return eulerAngleZ(angleZ) * eulerAngleX(angleX);
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleYXZ
	(
		valType const & yaw,
		valType const & pitch,
		valType const & roll
	)
	{
		valType tmp_ch = glm::cos(yaw);
		valType tmp_sh = glm::sin(yaw);
		valType tmp_cp = glm::cos(pitch);
		valType tmp_sp = glm::sin(pitch);
		valType tmp_cb = glm::cos(roll);
		valType tmp_sb = glm::sin(roll);

		detail::tmat4x4<valType> Result;
		Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb;
		Result[0][1] = tmp_sb * tmp_cp;
		Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb;
		Result[0][3] = valType(0);
		Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb;
		Result[1][1] = tmp_cb * tmp_cp;
		Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb;
		Result[1][3] = valType(0);
		Result[2][0] = tmp_sh * tmp_cp;
		Result[2][1] = -tmp_sp;
		Result[2][2] = tmp_ch * tmp_cp;
		Result[2][3] = valType(0);
		Result[3][0] = valType(0);
		Result[3][1] = valType(0);
		Result[3][2] = valType(0);
		Result[3][3] = valType(1);
		return Result;
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> yawPitchRoll
	(
		valType const & yaw,
		valType const & pitch,
		valType const & roll
	)
	{
		valType tmp_ch = glm::cos(yaw);
		valType tmp_sh = glm::sin(yaw);
		valType tmp_cp = glm::cos(pitch);
		valType tmp_sp = glm::sin(pitch);
		valType tmp_cb = glm::cos(roll);
		valType tmp_sb = glm::sin(roll);

		detail::tmat4x4<valType> Result;
		Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb;
		Result[0][1] = tmp_sb * tmp_cp;
		Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb;
		Result[0][3] = valType(0);
		Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb;
		Result[1][1] = tmp_cb * tmp_cp;
		Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb;
		Result[1][3] = valType(0);
		Result[2][0] = tmp_sh * tmp_cp;
		Result[2][1] = -tmp_sp;
		Result[2][2] = tmp_ch * tmp_cp;
		Result[2][3] = valType(0);
		Result[3][0] = valType(0);
		Result[3][1] = valType(0);
		Result[3][2] = valType(0);
		Result[3][3] = valType(1);
		return Result;
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat2x2<valType> orientate2
	(
		valType const & angle
	)
	{
		valType c = glm::cos(angle);
		valType s = glm::sin(angle);

		detail::tmat2x2<valType> Result;
		Result[0][0] = c;
		Result[0][1] = s;
		Result[1][0] = -s;
		Result[1][1] = c;
		return Result;
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat3x3<valType> orientate3
	(
		valType const & angle
	)
	{
		valType c = glm::cos(angle);
		valType s = glm::sin(angle);

		detail::tmat3x3<valType> Result;
		Result[0][0] = c;
		Result[0][1] = s;
		Result[0][2] = 0.0f;
		Result[1][0] = -s;
		Result[1][1] = c;
		Result[1][2] = 0.0f;
		Result[2][0] = 0.0f;
		Result[2][1] = 0.0f;
		Result[2][2] = 1.0f;
		return Result;
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat3x3<valType> orientate3
	(
		detail::tvec3<valType> const & angles
	)
	{
		return detail::tmat3x3<valType>(yawPitchRoll(angles.x, angles.y, angles.z));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> orientate4
	(
		detail::tvec3<valType> const & angles
	)
	{
		return yawPitchRoll(angles.z, angles.x, angles.y);
	}
}//namespace glm
<commit_msg>Fixed eulerAngleY rotation orientation<commit_after>///////////////////////////////////////////////////////////////////////////////////////////////////
// OpenGL Mathematics Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net)
///////////////////////////////////////////////////////////////////////////////////////////////////
// Created : 2005-12-21
// Updated : 2007-08-14
// Licence : This source is under MIT License
// File    : glm/gtx/euler_angles.inl
///////////////////////////////////////////////////////////////////////////////////////////////////

namespace glm
{
	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleX
	(
		valType const & angleX
	)
	{
		valType cosX = glm::cos(angleX);
		valType sinX = glm::sin(angleX);

		return detail::tmat4x4<valType>(
			valType(1), valType(0), valType(0), valType(0),
			valType(0), cosX,		sinX,		valType(0),
			valType(0),-sinX,		cosX,		valType(0),
			valType(0), valType(0), valType(0), valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleY
	(
		valType const & angleY
	)
	{
		valType cosY = glm::cos(angleY);
		valType sinY = glm::sin(angleY);

		return detail::tmat4x4<valType>(
			cosY,		valType(0),-sinY,		valType(0),
			valType(0),	valType(1),	valType(0), valType(0),
			sinY,		valType(0),	cosY,		valType(0),
			valType(0),	valType(0),	valType(0), valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleZ
	(
		valType const & angleZ
	)
	{
		valType cosZ = glm::cos(angleZ);
		valType sinZ = glm::sin(angleZ);

		return detail::tmat4x4<valType>(
			cosZ,		sinZ,		valType(0), valType(0),
			-sinZ,		cosZ,		valType(0), valType(0),
			valType(0),	valType(0),	valType(1), valType(0),
			valType(0),	valType(0),	valType(0), valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleXY
	(
		valType const & angleX,
		valType const & angleY
	)
	{
		valType cosX = glm::cos(angleX);
		valType sinX = glm::sin(angleX);
		valType cosY = glm::cos(angleY);
		valType sinY = glm::sin(angleY);

		return detail::tmat4x4<valType>(
			cosY,		-sinX * sinY,	cosX * sinY,	valType(0),
			valType(0), cosX,			sinX,			valType(0),
			-sinY ,		-sinX * cosY,	cosX * cosY,	valType(0),
			valType(0), valType(0),     valType(0),		valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleYX
	(
		valType const & angleY,
		valType const & angleX
	)
	{
		valType cosX = glm::cos(angleX);
		valType sinX = glm::sin(angleX);
		valType cosY = glm::cos(angleY);
		valType sinY = glm::sin(angleY);

		return detail::tmat4x4<valType>(
			cosY,			valType(0),		sinY,			valType(0),
			-sinX * sinY,	cosX,			sinX * cosY,	valType(0),
			-cosX * sinY,	-sinX,			cosX * cosY,	valType(0),
			valType(0),		valType(0),		valType(0),		valType(1));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleXZ
	(
		valType const & angleX,
		valType const & angleZ
	)
	{
		return eulerAngleX(angleX) * eulerAngleZ(angleZ);
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleZX
	(
		valType const & angleZ,
		valType const & angleX
	)
	{
		return eulerAngleZ(angleZ) * eulerAngleX(angleX);
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> eulerAngleYXZ
	(
		valType const & yaw,
		valType const & pitch,
		valType const & roll
	)
	{
		valType tmp_ch = glm::cos(yaw);
		valType tmp_sh = glm::sin(yaw);
		valType tmp_cp = glm::cos(pitch);
		valType tmp_sp = glm::sin(pitch);
		valType tmp_cb = glm::cos(roll);
		valType tmp_sb = glm::sin(roll);

		detail::tmat4x4<valType> Result;
		Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb;
		Result[0][1] = tmp_sb * tmp_cp;
		Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb;
		Result[0][3] = valType(0);
		Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb;
		Result[1][1] = tmp_cb * tmp_cp;
		Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb;
		Result[1][3] = valType(0);
		Result[2][0] = tmp_sh * tmp_cp;
		Result[2][1] = -tmp_sp;
		Result[2][2] = tmp_ch * tmp_cp;
		Result[2][3] = valType(0);
		Result[3][0] = valType(0);
		Result[3][1] = valType(0);
		Result[3][2] = valType(0);
		Result[3][3] = valType(1);
		return Result;
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> yawPitchRoll
	(
		valType const & yaw,
		valType const & pitch,
		valType const & roll
	)
	{
		valType tmp_ch = glm::cos(yaw);
		valType tmp_sh = glm::sin(yaw);
		valType tmp_cp = glm::cos(pitch);
		valType tmp_sp = glm::sin(pitch);
		valType tmp_cb = glm::cos(roll);
		valType tmp_sb = glm::sin(roll);

		detail::tmat4x4<valType> Result;
		Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb;
		Result[0][1] = tmp_sb * tmp_cp;
		Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb;
		Result[0][3] = valType(0);
		Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb;
		Result[1][1] = tmp_cb * tmp_cp;
		Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb;
		Result[1][3] = valType(0);
		Result[2][0] = tmp_sh * tmp_cp;
		Result[2][1] = -tmp_sp;
		Result[2][2] = tmp_ch * tmp_cp;
		Result[2][3] = valType(0);
		Result[3][0] = valType(0);
		Result[3][1] = valType(0);
		Result[3][2] = valType(0);
		Result[3][3] = valType(1);
		return Result;
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat2x2<valType> orientate2
	(
		valType const & angle
	)
	{
		valType c = glm::cos(angle);
		valType s = glm::sin(angle);

		detail::tmat2x2<valType> Result;
		Result[0][0] = c;
		Result[0][1] = s;
		Result[1][0] = -s;
		Result[1][1] = c;
		return Result;
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat3x3<valType> orientate3
	(
		valType const & angle
	)
	{
		valType c = glm::cos(angle);
		valType s = glm::sin(angle);

		detail::tmat3x3<valType> Result;
		Result[0][0] = c;
		Result[0][1] = s;
		Result[0][2] = 0.0f;
		Result[1][0] = -s;
		Result[1][1] = c;
		Result[1][2] = 0.0f;
		Result[2][0] = 0.0f;
		Result[2][1] = 0.0f;
		Result[2][2] = 1.0f;
		return Result;
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat3x3<valType> orientate3
	(
		detail::tvec3<valType> const & angles
	)
	{
		return detail::tmat3x3<valType>(yawPitchRoll(angles.x, angles.y, angles.z));
	}

	template <typename valType>
	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> orientate4
	(
		detail::tvec3<valType> const & angles
	)
	{
		return yawPitchRoll(angles.z, angles.x, angles.y);
	}
}//namespace glm
<|endoftext|>


<commit_before><commit_msg>Icon themes DAGView<commit_after><|endoftext|>


<commit_before>#pragma once

#include "rectangle_renderer_component.h"
#include <cassert>

namespace bowtie
{

namespace
{

RectangleRendererComponentData initialize_data(void* buffer, unsigned size)
{
	RectangleRendererComponentData new_data;
	new_data.color = (Color*)buffer;
	new_data.rect = (Rect*)(new_data.color + size);
	new_data.render_handle = (RenderResourceHandle*)(new_data.rect + size);
	return new_data;
}

void grow(RectangleRendererComponent& c, Allocator& allocator)
{
	const unsigned new_capacity = c.capacity == 0 ? 8 : c.capacity * 2;
	const unsigned bytes = new_capacity * rectangle_renderer_component::component_size;
	void* buffer = allocator.allocate(bytes);

	auto new_data = initialize_data(buffer, new_capacity);

	memcpy(new_data.color, c.data.color, c.num * sizeof(Color));
	memcpy(new_data.rect, c.data.rect, c.num * sizeof(Rect));
	memcpy(new_data.render_handle, c.data.render_handle, c.num * sizeof(RenderResourceHandle));

	c.data = new_data;

	allocator.deallocate(c.buffer);
	c.buffer = buffer;
	c.capacity = new_capacity;
}

void mark_dirty(RectangleRendererComponent& c, Entity e)
{
	auto entity_index = hash::get(c.map, e, 0u);

	if (c.last_dirty_index != (unsigned)-1 && entity_index <= c.last_dirty_index)
		return;

	auto current_dirty_index = ++c.last_dirty_index;

	if (current_dirty_index == entity_index)
		return;

	auto color_at_index = c.data.color[current_dirty_index];
	auto rect_at_index = c.data.rect[current_dirty_index];
	auto render_handle_at_index = c.data.render_handle[current_dirty_index];
	c.data.color[current_dirty_index] = rectangle_renderer_component::color(c, e);
	c.data.rect[current_dirty_index] = rectangle_renderer_component::rect(c, e);
	c.data.render_handle[current_dirty_index] = rectangle_renderer_component::render_handle(c, e);
	c.data.color[entity_index] = color_at_index;
	c.data.rect[entity_index] = rect_at_index;
	c.data.render_handle[entity_index] = render_handle_at_index;
}

}

namespace rectangle_renderer_component
{

void init(RectangleRendererComponent& c, Allocator& allocator)
{
	memset(&c, 0, sizeof(RectangleRendererComponent));
	c.map = hash::create<unsigned>(allocator);
	c.last_dirty_index = (unsigned)-1;
}

void deinit(RectangleRendererComponent& c, Allocator& allocator)
{
	hash::deinit(c.map);
	allocator.deallocate(c.buffer);
}

void create(RectangleRendererComponent& c, Entity e, Allocator& allocator)
{
	if (c.num >= c.capacity)
		grow(c, allocator);

	unsigned i = c.num++;
	hash::set(c.map, e, i);
	c.data.color[i] = Color(1, 1, 1, 1);
	c.data.rect[i] = Rect();
	c.data.render_handle[i] = RenderResourceHandle::NotInitialized;
}

void destroy(RectangleRendererComponent& c, Entity e)
{
	unsigned i = hash::get(c.map, e, 0u);
	hash::remove(c.map, e);
	--c.num;

	if (i == c.num)
		return;

	c.data.color[i] = c.data.color[c.num];
	c.data.rect[i] = c.data.rect[c.num];
	c.data.render_handle[i] = c.data.render_handle[c.num];
}

void set_rect(RectangleRendererComponent& c, Entity e, const Rect& rect)
{
	c.data.rect[hash::get(c.map, e)] = rect;
	mark_dirty(c, e);
}

const Rect& rect(RectangleRendererComponent& c, Entity e)
{
	return c.data.rect[hash::get(c.map, e)];
}

void set_color(RectangleRendererComponent& c, Entity e, const Color& color)
{
	c.data.color[hash::get(c.map, e)] = color;
	mark_dirty(c, e);
}

const Color& color(RectangleRendererComponent& c, Entity e)
{
	return c.data.color[hash::get(c.map, e)];
}

void set_render_handle(RectangleRendererComponent& c, Entity e, RenderResourceHandle render_handle)
{
	c.data.render_handle[hash::get(c.map, e)] = render_handle;
}

RenderResourceHandle render_handle(RectangleRendererComponent& c, Entity e)
{
	return c.data.render_handle[hash::get(c.map, e)];
}

RectangleRendererComponentData* copy_data(RectangleRendererComponent& c, Entity e, Allocator& allocator)
{
	RectangleRendererComponentData* data = (RectangleRendererComponentData*)allocator.allocate(sizeof(RectangleRendererComponentData));
	*data = initialize_data(allocator.allocate(component_size), 1);
	*data->color = color(c, e);
	*data->rect = rect(c, e);
	*data->render_handle = render_handle(c, e);
	return data;
}

RectangleRendererComponentData* copy_dirty_data(RectangleRendererComponent& c, Allocator& allocator)
{
	RectangleRendererComponentData* data = (RectangleRendererComponentData*)allocator.allocate(sizeof(RectangleRendererComponentData));
	auto num_dirty = c.last_dirty_index + 1;
	*data = initialize_data(allocator.allocate(component_size), num_dirty);
	memcpy(data->color, c.data.color, sizeof(Color) * num_dirty);
	memcpy(data->rect, c.data.rect, sizeof(Rect) * num_dirty);
	memcpy(data->render_handle, c.data.render_handle, sizeof(RenderResourceHandle) * num_dirty);
	return data;
}

} // rectangle_renderer_component

} // namespace bowtie
<commit_msg>Revised growing of rect component.<commit_after>#pragma once

#include "rectangle_renderer_component.h"
#include <cassert>

namespace bowtie
{

namespace
{

RectangleRendererComponentData initialize_data(void* buffer, unsigned size)
{
	RectangleRendererComponentData new_data;
	new_data.color = (Color*)buffer;
	new_data.rect = (Rect*)(new_data.color + size);
	new_data.render_handle = (RenderResourceHandle*)(new_data.rect + size);
	return new_data;
}

void grow(RectangleRendererComponent& c, Allocator& allocator)
{
	const unsigned new_capacity = c.capacity == 0 ? 8 : c.capacity * 2;
	const unsigned bytes = new_capacity * rectangle_renderer_component::component_size;
	void* buffer = allocator.allocate(bytes);

	auto new_data = initialize_data(buffer, new_capacity);
	memcpy(new_data.color, c.data.color, c.num * sizeof(Color));
	memcpy(new_data.rect, c.data.rect, c.num * sizeof(Rect));
	memcpy(new_data.render_handle, c.data.render_handle, c.num * sizeof(RenderResourceHandle));
	c.data = new_data;

	allocator.deallocate(c.buffer);
	c.buffer = buffer;
	c.capacity = new_capacity;
}

void mark_dirty(RectangleRendererComponent& c, Entity e)
{
	auto entity_index = hash::get(c.map, e, 0u);

	if (c.last_dirty_index != (unsigned)-1 && entity_index <= c.last_dirty_index)
		return;

	auto current_dirty_index = ++c.last_dirty_index;

	if (current_dirty_index == entity_index)
		return;

	auto color_at_index = c.data.color[current_dirty_index];
	auto rect_at_index = c.data.rect[current_dirty_index];
	auto render_handle_at_index = c.data.render_handle[current_dirty_index];
	c.data.color[current_dirty_index] = c.data.color[entity_index];
	c.data.rect[current_dirty_index] = c.data.rect[entity_index];
	c.data.render_handle[current_dirty_index] = c.data.render_handle[entity_index];
	c.data.color[entity_index] = color_at_index;
	c.data.rect[entity_index] = rect_at_index;
	c.data.render_handle[entity_index] = render_handle_at_index;
}

}

namespace rectangle_renderer_component
{

void init(RectangleRendererComponent& c, Allocator& allocator)
{
	memset(&c, 0, sizeof(RectangleRendererComponent));
	c.map = hash::create<unsigned>(allocator);
	c.last_dirty_index = (unsigned)-1;
}

void deinit(RectangleRendererComponent& c, Allocator& allocator)
{
	hash::deinit(c.map);
	allocator.deallocate(c.buffer);
}

void create(RectangleRendererComponent& c, Entity e, Allocator& allocator)
{
	if (c.num >= c.capacity)
		grow(c, allocator);

	unsigned i = c.num++;
	hash::set(c.map, e, i);
	c.data.color[i] = Color(1, 1, 1, 1);
	c.data.rect[i] = Rect();
	c.data.render_handle[i] = RenderResourceHandle::NotInitialized;
}

void destroy(RectangleRendererComponent& c, Entity e)
{
	unsigned i = hash::get(c.map, e, 0u);
	hash::remove(c.map, e);
	--c.num;

	if (i == c.num)
		return;

	c.data.color[i] = c.data.color[c.num];
	c.data.rect[i] = c.data.rect[c.num];
	c.data.render_handle[i] = c.data.render_handle[c.num];
}

void set_rect(RectangleRendererComponent& c, Entity e, const Rect& rect)
{
	c.data.rect[hash::get(c.map, e)] = rect;
	mark_dirty(c, e);
}

const Rect& rect(RectangleRendererComponent& c, Entity e)
{
	return c.data.rect[hash::get(c.map, e)];
}

void set_color(RectangleRendererComponent& c, Entity e, const Color& color)
{
	c.data.color[hash::get(c.map, e)] = color;
	mark_dirty(c, e);
}

const Color& color(RectangleRendererComponent& c, Entity e)
{
	return c.data.color[hash::get(c.map, e)];
}

void set_render_handle(RectangleRendererComponent& c, Entity e, RenderResourceHandle render_handle)
{
	c.data.render_handle[hash::get(c.map, e)] = render_handle;
}

RenderResourceHandle render_handle(RectangleRendererComponent& c, Entity e)
{
	return c.data.render_handle[hash::get(c.map, e)];
}

RectangleRendererComponentData* copy_data(RectangleRendererComponent& c, Entity e, Allocator& allocator)
{
	RectangleRendererComponentData* data = (RectangleRendererComponentData*)allocator.allocate(sizeof(RectangleRendererComponentData));
	*data = initialize_data(allocator.allocate(component_size), 1);
	*data->color = color(c, e);
	*data->rect = rect(c, e);
	*data->render_handle = render_handle(c, e);
	return data;
}

RectangleRendererComponentData* copy_dirty_data(RectangleRendererComponent& c, Allocator& allocator)
{
	RectangleRendererComponentData* data = (RectangleRendererComponentData*)allocator.allocate(sizeof(RectangleRendererComponentData));
	auto num_dirty = c.last_dirty_index + 1;
	*data = initialize_data(allocator.allocate(component_size), num_dirty);
	memcpy(data->color, c.data.color, sizeof(Color) * num_dirty);
	memcpy(data->rect, c.data.rect, sizeof(Rect) * num_dirty);
	memcpy(data->render_handle, c.data.render_handle, sizeof(RenderResourceHandle) * num_dirty);
	return data;
}

} // rectangle_renderer_component

} // namespace bowtie
<|endoftext|>


<commit_before>
#include <fstream>
#include <memory>

#include <pangolin/image/typed_image.h>

#ifdef HAVE_ZSTD
#  include <zstd.h>
#endif

namespace pangolin {

#pragma pack(push, 1)
struct zstd_image_header
{
    char magic[4];
    char fmt[16];
    size_t w, h;
};
#pragma pack(pop)

void SaveZstd(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level)
{
#ifdef HAVE_ZSTD
    // Write out header, uncompressed
    zstd_image_header header;
    strncpy(header.magic,"ZSTD",4);
    strncpy(header.fmt, fmt.format.c_str(), sizeof(header.fmt));
    header.w = image.w;
    header.h = image.h;
    out.write((char*)&header, sizeof(header));

    // Write out image data
    const size_t output_buffer_size = ZSTD_CStreamOutSize();
    std::unique_ptr<char[]> output_buffer(new char[output_buffer_size]);

    ZSTD_CStream* const cstream = ZSTD_createCStream();
    if (cstream==nullptr) {
        throw std::runtime_error("ZSTD_createCStream() error");
    }

    size_t const initResult = ZSTD_initCStream(cstream, compression_level);
    if (ZSTD_isError(initResult)) {
        throw std::runtime_error(FormatString("ZSTD_initCStream() error : %", ZSTD_getErrorName(initResult)));
    }

    const size_t row_size_bytes = (fmt.bpp * image.w)/8;

    for(size_t y=0; y < image.h; ++y) {
        ZSTD_inBuffer input = { image.RowPtr(y), row_size_bytes, 0 };

        while (input.pos < input.size) {
            ZSTD_outBuffer output = { output_buffer.get(), output_buffer_size, 0 };
            size_t left_to_read = ZSTD_compressStream(cstream, &output , &input);
            if (ZSTD_isError(left_to_read)) {
                throw std::runtime_error(FormatString("ZSTD_compressStream() error : %", ZSTD_getErrorName(left_to_read)));
            }
            out.write(output_buffer.get(), output.pos);
        }
    }

    ZSTD_outBuffer output = { output_buffer.get(), output_buffer_size, 0 };
    size_t const remainingToFlush = ZSTD_endStream(cstream, &output);   /* close frame */
    if (remainingToFlush) {
        throw std::runtime_error("not fully flushed");
    }
    out.write(output_buffer.get(), output.pos);

    ZSTD_freeCStream(cstream);
#else
    PANGOLIN_UNUSED(image);
    PANGOLIN_UNUSED(fmt);
    PANGOLIN_UNUSED(out);
    PANGOLIN_UNUSED(compression_level);
    throw std::runtime_error("Rebuild Pangolin for ZSTD support.");
#endif // HAVE_ZSTD
}

TypedImage LoadZstd(std::istream& in)
{
#ifdef HAVE_ZSTD
    // Read in header, uncompressed
    zstd_image_header header;
    in.read( (char*)&header, sizeof(header));

    TypedImage img(header.w, header.h, PixelFormatFromString(header.fmt));

    const size_t input_buffer_size = ZSTD_DStreamInSize();
    std::unique_ptr<char[]> input_buffer(new char[input_buffer_size]);

    ZSTD_DStream* dstream = ZSTD_createDStream();
    if(!dstream) {
        throw std::runtime_error("ZSTD_createDStream() error");
    }

    size_t read_size_hint = ZSTD_initDStream(dstream);
    if (ZSTD_isError(read_size_hint)) {
        throw std::runtime_error(FormatString("ZSTD_initDStream() error : % \n", ZSTD_getErrorName(read_size_hint)));
    }

    // Image represents our fixed buffer.
    ZSTD_outBuffer output = { img.ptr, img.SizeBytes(), 0 };

    while(read_size_hint)
    {
        const size_t read = in.readsome(input_buffer.get(), read_size_hint);
        ZSTD_inBuffer input = { input_buffer.get(), read, 0 };
        while (input.pos < input.size) {
            read_size_hint = ZSTD_decompressStream(dstream, &output , &input);
            if (ZSTD_isError(read_size_hint)) {
                throw std::runtime_error(FormatString("ZSTD_decompressStream() error : %", ZSTD_getErrorName(read_size_hint)));
            }
        }
    }

    ZSTD_freeDStream(dstream);

    return img;
#else
    PANGOLIN_UNUSED(in);
    throw std::runtime_error("Rebuild Pangolin for ZSTD support.");
#endif // HAVE_ZSTD
}

}
<commit_msg>Image: fix for zstd inf loop bug.<commit_after>
#include <fstream>
#include <memory>

#include <pangolin/image/typed_image.h>

#ifdef HAVE_ZSTD
#  include <zstd.h>
#endif

namespace pangolin {

#pragma pack(push, 1)
struct zstd_image_header
{
    char magic[4];
    char fmt[16];
    size_t w, h;
};
#pragma pack(pop)

void SaveZstd(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level)
{
#ifdef HAVE_ZSTD
    // Write out header, uncompressed
    zstd_image_header header;
    strncpy(header.magic,"ZSTD",4);
    strncpy(header.fmt, fmt.format.c_str(), sizeof(header.fmt));
    header.w = image.w;
    header.h = image.h;
    out.write((char*)&header, sizeof(header));

    // Write out image data
    const size_t output_buffer_size = ZSTD_CStreamOutSize();
    std::unique_ptr<char[]> output_buffer(new char[output_buffer_size]);

    ZSTD_CStream* const cstream = ZSTD_createCStream();
    if (cstream==nullptr) {
        throw std::runtime_error("ZSTD_createCStream() error");
    }

    size_t const initResult = ZSTD_initCStream(cstream, compression_level);
    if (ZSTD_isError(initResult)) {
        throw std::runtime_error(FormatString("ZSTD_initCStream() error : %", ZSTD_getErrorName(initResult)));
    }

    const size_t row_size_bytes = (fmt.bpp * image.w)/8;

    for(size_t y=0; y < image.h; ++y) {
        ZSTD_inBuffer input = { image.RowPtr(y), row_size_bytes, 0 };

        while (input.pos < input.size) {
            ZSTD_outBuffer output = { output_buffer.get(), output_buffer_size, 0 };
            size_t left_to_read = ZSTD_compressStream(cstream, &output , &input);
            if (ZSTD_isError(left_to_read)) {
                throw std::runtime_error(FormatString("ZSTD_compressStream() error : %", ZSTD_getErrorName(left_to_read)));
            }
            out.write(output_buffer.get(), output.pos);
        }
    }

    ZSTD_outBuffer output = { output_buffer.get(), output_buffer_size, 0 };
    size_t const remainingToFlush = ZSTD_endStream(cstream, &output);   /* close frame */
    if (remainingToFlush) {
        throw std::runtime_error("not fully flushed");
    }
    out.write(output_buffer.get(), output.pos);

    ZSTD_freeCStream(cstream);
#else
    PANGOLIN_UNUSED(image);
    PANGOLIN_UNUSED(fmt);
    PANGOLIN_UNUSED(out);
    PANGOLIN_UNUSED(compression_level);
    throw std::runtime_error("Rebuild Pangolin for ZSTD support.");
#endif // HAVE_ZSTD
}

TypedImage LoadZstd(std::istream& in)
{
#ifdef HAVE_ZSTD
    // Read in header, uncompressed
    zstd_image_header header;
    in.read( (char*)&header, sizeof(header));

    TypedImage img(header.w, header.h, PixelFormatFromString(header.fmt));

    const size_t input_buffer_size = ZSTD_DStreamInSize();
    std::unique_ptr<char[]> input_buffer(new char[input_buffer_size]);

    ZSTD_DStream* dstream = ZSTD_createDStream();
    if(!dstream) {
        throw std::runtime_error("ZSTD_createDStream() error");
    }

    size_t read_size_hint = ZSTD_initDStream(dstream);
    if (ZSTD_isError(read_size_hint)) {
        throw std::runtime_error(FormatString("ZSTD_initDStream() error : % \n", ZSTD_getErrorName(read_size_hint)));
    }

    // Image represents our fixed buffer.
    ZSTD_outBuffer output = { img.ptr, img.SizeBytes(), 0 };

    while(read_size_hint)
    {
        in.read(input_buffer.get(), read_size_hint);
        ZSTD_inBuffer input = { input_buffer.get(), read_size_hint, 0 };
        while (input.pos < input.size) {
            read_size_hint = ZSTD_decompressStream(dstream, &output , &input);
            if (ZSTD_isError(read_size_hint)) {
                throw std::runtime_error(FormatString("ZSTD_decompressStream() error : %", ZSTD_getErrorName(read_size_hint)));
            }
        }
    }

    ZSTD_freeDStream(dstream);

    return img;
#else
    PANGOLIN_UNUSED(in);
    throw std::runtime_error("Rebuild Pangolin for ZSTD support.");
#endif // HAVE_ZSTD
}

}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2010-2011, Image Engine Design Inc. 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 Image Engine Design nor the names of any
//       other contributors to this software 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.
//
//////////////////////////////////////////////////////////////////////////

#include "IECore/TriangulateOp.h"
#include "IECore/FileNameParameter.h"

#include "IECoreRI/GXEvaluator.h"
#include "IECoreRI/Renderer.h"
#include "IECoreRI/ScopedContext.h"

using namespace std;
using namespace IECore;
using namespace IECoreRI;

GXEvaluator::GXEvaluator( const IECore::Primitive *primitive )
{
	RtContextHandle prevContext = RiGetContext();
	RiBegin( 0 );
	m_context = RiGetContext();

	RendererPtr renderer = new IECoreRI::Renderer();
	RtObjectHandle objectHandle = RiObjectBegin();

		primitive->render( renderer );

	RiObjectEnd();

	m_geo = GxGetGeometry( objectHandle );

	RiContext( prevContext );

	for( PrimitiveVariableMap::const_iterator it=primitive->variables.begin(); it!=primitive->variables.end(); it++ )
	{
		if( !it->second.data )
		{
			continue;
		}
		IECore::TypeId type = it->second.data->typeId();
		if( type!=V3fVectorDataTypeId && type!=Color3fVectorDataTypeId && type!=FloatVectorDataTypeId )
		{
			m_primitiveVariableTypes[it->first] = InvalidTypeId;
		}
		else
		{
			m_primitiveVariableTypes[it->first] = type;
		}
	}
	m_primitiveVariableTypes["N"] = V3fVectorDataTypeId;     // these can be queried even if a primitive variable
	m_primitiveVariableTypes["Ng"] = V3fVectorDataTypeId;    // of that name hasn't been supplied.
	m_primitiveVariableTypes["dPdu"] = V3fVectorDataTypeId;
	m_primitiveVariableTypes["dPdv"] = V3fVectorDataTypeId;
}

GXEvaluator::~GXEvaluator()
{
	RtContextHandle c = RiGetContext();
	RiContext( m_context );
	RiEnd();
	if( c!=m_context )
	{
		RiContext( c );
	}
}

unsigned GXEvaluator::numFaces() const
{
	ScopedContext context( m_context );
	return GxGetFaceCount( m_geo );
}

template<typename T>
static DataPtr evaluatePrimitiveVariable( std::vector<GxSurfacePoint> &points, const std::string &primVarName )
{
	typename T::Ptr result = new T;
	result->writable().resize( points.size() );
	if( points.size() )
	{
		GxEvaluateSurface( points.size(), &(points[0]), primVarName.c_str(), result->baseSize() / points.size(), result->baseWritable() );
	}
	return result;
}

IECore::CompoundDataPtr GXEvaluator::evaluate( const IECore::IntVectorData *faceIndices, const IECore::FloatVectorData *u, const IECore::FloatVectorData *v, const std::vector<std::string> &primVarNames ) const
{
	// do some basic validation of our input

	size_t numPoints = faceIndices->readable().size();
	if( u->readable().size() != numPoints || v->readable().size() != numPoints )
	{
		throw InvalidArgumentException( "faceIndices, u and v must all have the same length" );
	}

	validatePrimVarNames( primVarNames );

	// create surface points
	ScopedContext context( m_context );

	const std::vector<int> faceIndicesReadable = faceIndices->readable();
	const std::vector<float> uReadable = u->readable();
	const std::vector<float> vReadable = v->readable();

	std::vector<GxSurfacePoint> surfacePoints( numPoints );
	for( unsigned i=0; i<numPoints; i++ )
	{
		int status = GxCreateSurfacePoint( m_geo, faceIndicesReadable[i], uReadable[i], vReadable[i], 0.0f, &(surfacePoints[i]) );
		if( status==RIE_RANGE )
		{
			for( unsigned j=0; j<i; j++ )
			{
				GxFreeSurfacePoint( surfacePoints[j] );
			}
			throw InvalidArgumentException( boost::str( boost::format( "faceIndex %d out of range" ) % faceIndicesReadable[i] ) );
		}
	}

	// query all the primvars

	IECore::CompoundDataPtr result = new IECore::CompoundData;
	for( vector<string>::const_iterator it=primVarNames.begin(); it!=primVarNames.end(); it++ )
	{
		switch( m_primitiveVariableTypes.find( *it )->second )
		{
			case FloatVectorDataTypeId :
				result->writable()[*it] = evaluatePrimitiveVariable<FloatVectorData>( surfacePoints, *it );
				break;
			case V3fVectorDataTypeId :
				result->writable()[*it] = evaluatePrimitiveVariable<V3fVectorData>( surfacePoints, *it );
				break;
			case Color3fVectorDataTypeId :
				result->writable()[*it] = evaluatePrimitiveVariable<Color3fVectorData>( surfacePoints, *it );
				break;
			default :
				assert( 0 ); // shouldnt be here as we checked types earlier
		}
	}

	// clean up

	for( unsigned i=0; i<numPoints; i++ )
	{
		GxFreeSurfacePoint( surfacePoints[i] );
	}

	return result;
}

IECore::CompoundDataPtr GXEvaluator::evaluate( const IECore::FloatVectorData *s, const IECore::FloatVectorData *t, const std::vector<std::string> &primVarNames ) const
{
	size_t numPoints = s->readable().size();
	if( t->readable().size() != numPoints )
	{
		throw InvalidArgumentException( "s and t must have the same length" );
	}

	buildSTEvaluator();

	MeshPrimitiveEvaluator::ResultPtr evaluatorResult = staticPointerCast<MeshPrimitiveEvaluator::Result>( m_stEvaluator->createResult() );
	IntVectorDataPtr fData = new IntVectorData;
	FloatVectorDataPtr uData = new FloatVectorData;
	FloatVectorDataPtr vData = new FloatVectorData;
	BoolVectorDataPtr statusData = new BoolVectorData;
	std::vector<int> &fWritable = fData->writable(); fWritable.resize( numPoints );
	std::vector<float> &uWritable = uData->writable(); uWritable.resize( numPoints );
	std::vector<float> &vWritable = vData->writable(); vWritable.resize( numPoints );
	std::vector<bool> &statusWritable = statusData->writable(); statusWritable.resize( numPoints );

	const std::vector<float> &sReadable = s->readable();
	const std::vector<float> &tReadable = t->readable();

	const PrimitiveVariable &uPrimVar = m_stEvaluator->primitive()->variables.find( "u" )->second;
	const PrimitiveVariable &vPrimVar = m_stEvaluator->primitive()->variables.find( "v" )->second;
	for( size_t i=0; i<numPoints; i++ )
	{
		bool success = m_stEvaluator->pointAtUV( Imath::V2f( sReadable[i], tReadable[i] ), evaluatorResult );
		// dividing by 2 maps from the triangle index to the original face index of the mesh before it
		// was triangulated - we can guarantee this because the original mesh was all quads.
		fWritable[i] = success ? evaluatorResult->triangleIndex() / 2 : 0;
		uWritable[i] = success ? evaluatorResult->floatPrimVar( uPrimVar ) : 0;
		vWritable[i] = success ? evaluatorResult->floatPrimVar( vPrimVar ) : 0;
		statusWritable[i] = success;
	}

	CompoundDataPtr result = evaluate( fData, uData, vData, primVarNames );
	result->writable()["gxStatus"] = statusData;

	return result;
}

void GXEvaluator::validatePrimVarNames( const std::vector<std::string> &primVarNames ) const
{
	for( vector<string>::const_iterator it=primVarNames.begin(); it!=primVarNames.end(); it++ )
	{
		PrimitiveVariableTypeMap::const_iterator pvIt = m_primitiveVariableTypes.find( *it );
		if( pvIt == m_primitiveVariableTypes.end() )
		{
			throw InvalidArgumentException( boost::str( boost::format( "Primitive variable \"%s\" does not exist" ) % *it ) );
		}
		if( pvIt->second==InvalidTypeId )
		{
			throw InvalidArgumentException( boost::str( boost::format( "Primitive variable \"%s\" has unsupported type" ) % *it ) );
		}
	}
}

void GXEvaluator::buildSTEvaluator() const
{
	Mutex::scoped_lock lock( m_stEvaluatorMutex, false ); // read only lock
	if( m_stEvaluator )
	{
		return;
	}
	lock.upgrade_to_writer();
	if( m_stEvaluator )
	{
		return;
	}

	size_t nFaces = numFaces();
	size_t nVertices = nFaces * 4;

	IntVectorDataPtr faceIndicesData = new IntVectorData;
	FloatVectorDataPtr uData = new FloatVectorData;
	FloatVectorDataPtr vData = new FloatVectorData;
	std::vector<int> &faceIndicesWritable = faceIndicesData->writable(); faceIndicesWritable.resize( nVertices );
	std::vector<float> &uWritable = uData->writable(); uWritable.resize( nVertices );
	std::vector<float> &vWritable = vData->writable(); vWritable.resize( nVertices );

	size_t vi = 0;
	for( size_t fi=0; fi<nFaces; fi++ )
	{
		faceIndicesWritable[vi] = fi;
		faceIndicesWritable[vi+1] = fi;
		faceIndicesWritable[vi+2] = fi;
		faceIndicesWritable[vi+3] = fi;
		uWritable[vi] = 0;
		uWritable[vi+1] = 0;
		uWritable[vi+2] = 1;
		uWritable[vi+3] = 1;
		vWritable[vi] = 0;
		vWritable[vi+1] = 1;
		vWritable[vi+2] = 1;
		vWritable[vi+3] = 0;
		vi += 4;
	}

	std::vector<std::string> primVarNames;
	primVarNames.push_back( "P" );
	primVarNames.push_back( "s" );
	primVarNames.push_back( "t" );
	CompoundDataPtr vertexData = evaluate( faceIndicesData, uData, vData, primVarNames );

	IntVectorDataPtr verticesPerFaceData = new IntVectorData;
	IntVectorDataPtr vertexIdsData = new IntVectorData;
	std::vector<int> &verticesPerFace = verticesPerFaceData->writable(); verticesPerFace.resize( nFaces, 4 );
	std::vector<int> &vertexIds = vertexIdsData->writable(); vertexIds.resize( nVertices );
	for( size_t i=0; i<nVertices; i++ )
	{
		vertexIds[i] = i;
	}
	MeshPrimitivePtr mesh = new MeshPrimitive( verticesPerFaceData, vertexIdsData );
	mesh->variables["P"] = PrimitiveVariable( PrimitiveVariable::Vertex, vertexData->member<V3fVectorData>( "P" ) );
	mesh->variables["s"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, vertexData->member<FloatVectorData>( "s" ) );
	mesh->variables["t"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, vertexData->member<FloatVectorData>( "t" ) );
	mesh->variables["u"] = PrimitiveVariable( PrimitiveVariable::Vertex, uData );
	mesh->variables["v"] = PrimitiveVariable( PrimitiveVariable::Vertex, vData );

	TriangulateOpPtr op = new TriangulateOp();
	op->inputParameter()->setValue( mesh );
	op->copyParameter()->setTypedValue( false );
	op->throwExceptionsParameter()->setTypedValue( false );
	op->operate();

	m_stEvaluator = new MeshPrimitiveEvaluator( mesh );
}
<commit_msg>Fixing memory leak.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2010-2011, Image Engine Design Inc. 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 Image Engine Design nor the names of any
//       other contributors to this software 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.
//
//////////////////////////////////////////////////////////////////////////

#include "IECore/TriangulateOp.h"
#include "IECore/FileNameParameter.h"

#include "IECoreRI/GXEvaluator.h"
#include "IECoreRI/Renderer.h"
#include "IECoreRI/ScopedContext.h"

using namespace std;
using namespace IECore;
using namespace IECoreRI;

GXEvaluator::GXEvaluator( const IECore::Primitive *primitive )
{
	RtContextHandle prevContext = RiGetContext();
	RiBegin( 0 );
	m_context = RiGetContext();

	RendererPtr renderer = new IECoreRI::Renderer();
	RtObjectHandle objectHandle = RiObjectBegin();

		primitive->render( renderer );

	RiObjectEnd();

	m_geo = GxGetGeometry( objectHandle );

	RiContext( prevContext );

	for( PrimitiveVariableMap::const_iterator it=primitive->variables.begin(); it!=primitive->variables.end(); it++ )
	{
		if( !it->second.data )
		{
			continue;
		}
		IECore::TypeId type = it->second.data->typeId();
		if( type!=V3fVectorDataTypeId && type!=Color3fVectorDataTypeId && type!=FloatVectorDataTypeId )
		{
			m_primitiveVariableTypes[it->first] = InvalidTypeId;
		}
		else
		{
			m_primitiveVariableTypes[it->first] = type;
		}
	}
	m_primitiveVariableTypes["N"] = V3fVectorDataTypeId;     // these can be queried even if a primitive variable
	m_primitiveVariableTypes["Ng"] = V3fVectorDataTypeId;    // of that name hasn't been supplied.
	m_primitiveVariableTypes["dPdu"] = V3fVectorDataTypeId;
	m_primitiveVariableTypes["dPdv"] = V3fVectorDataTypeId;
}

GXEvaluator::~GXEvaluator()
{
	RtContextHandle c = RiGetContext();
	RiContext( m_context );
	GxFreeGeometry( m_geo );
	RiEnd();
	if( c!=m_context )
	{
		RiContext( c );
	}
}

unsigned GXEvaluator::numFaces() const
{
	ScopedContext context( m_context );
	return GxGetFaceCount( m_geo );
}

template<typename T>
static DataPtr evaluatePrimitiveVariable( std::vector<GxSurfacePoint> &points, const std::string &primVarName )
{
	typename T::Ptr result = new T;
	result->writable().resize( points.size() );
	if( points.size() )
	{
		GxEvaluateSurface( points.size(), &(points[0]), primVarName.c_str(), result->baseSize() / points.size(), result->baseWritable() );
	}
	return result;
}

IECore::CompoundDataPtr GXEvaluator::evaluate( const IECore::IntVectorData *faceIndices, const IECore::FloatVectorData *u, const IECore::FloatVectorData *v, const std::vector<std::string> &primVarNames ) const
{
	// do some basic validation of our input

	size_t numPoints = faceIndices->readable().size();
	if( u->readable().size() != numPoints || v->readable().size() != numPoints )
	{
		throw InvalidArgumentException( "faceIndices, u and v must all have the same length" );
	}

	validatePrimVarNames( primVarNames );

	// create surface points
	ScopedContext context( m_context );

	const std::vector<int> faceIndicesReadable = faceIndices->readable();
	const std::vector<float> uReadable = u->readable();
	const std::vector<float> vReadable = v->readable();

	std::vector<GxSurfacePoint> surfacePoints( numPoints );
	for( unsigned i=0; i<numPoints; i++ )
	{
		int status = GxCreateSurfacePoint( m_geo, faceIndicesReadable[i], uReadable[i], vReadable[i], 0.0f, &(surfacePoints[i]) );
		if( status==RIE_RANGE )
		{
			for( unsigned j=0; j<i; j++ )
			{
				GxFreeSurfacePoint( surfacePoints[j] );
			}
			throw InvalidArgumentException( boost::str( boost::format( "faceIndex %d out of range" ) % faceIndicesReadable[i] ) );
		}
	}

	// query all the primvars

	IECore::CompoundDataPtr result = new IECore::CompoundData;
	for( vector<string>::const_iterator it=primVarNames.begin(); it!=primVarNames.end(); it++ )
	{
		switch( m_primitiveVariableTypes.find( *it )->second )
		{
			case FloatVectorDataTypeId :
				result->writable()[*it] = evaluatePrimitiveVariable<FloatVectorData>( surfacePoints, *it );
				break;
			case V3fVectorDataTypeId :
				result->writable()[*it] = evaluatePrimitiveVariable<V3fVectorData>( surfacePoints, *it );
				break;
			case Color3fVectorDataTypeId :
				result->writable()[*it] = evaluatePrimitiveVariable<Color3fVectorData>( surfacePoints, *it );
				break;
			default :
				assert( 0 ); // shouldnt be here as we checked types earlier
		}
	}

	// clean up

	for( unsigned i=0; i<numPoints; i++ )
	{
		GxFreeSurfacePoint( surfacePoints[i] );
	}

	return result;
}

IECore::CompoundDataPtr GXEvaluator::evaluate( const IECore::FloatVectorData *s, const IECore::FloatVectorData *t, const std::vector<std::string> &primVarNames ) const
{
	size_t numPoints = s->readable().size();
	if( t->readable().size() != numPoints )
	{
		throw InvalidArgumentException( "s and t must have the same length" );
	}

	buildSTEvaluator();

	MeshPrimitiveEvaluator::ResultPtr evaluatorResult = staticPointerCast<MeshPrimitiveEvaluator::Result>( m_stEvaluator->createResult() );
	IntVectorDataPtr fData = new IntVectorData;
	FloatVectorDataPtr uData = new FloatVectorData;
	FloatVectorDataPtr vData = new FloatVectorData;
	BoolVectorDataPtr statusData = new BoolVectorData;
	std::vector<int> &fWritable = fData->writable(); fWritable.resize( numPoints );
	std::vector<float> &uWritable = uData->writable(); uWritable.resize( numPoints );
	std::vector<float> &vWritable = vData->writable(); vWritable.resize( numPoints );
	std::vector<bool> &statusWritable = statusData->writable(); statusWritable.resize( numPoints );

	const std::vector<float> &sReadable = s->readable();
	const std::vector<float> &tReadable = t->readable();

	const PrimitiveVariable &uPrimVar = m_stEvaluator->primitive()->variables.find( "u" )->second;
	const PrimitiveVariable &vPrimVar = m_stEvaluator->primitive()->variables.find( "v" )->second;
	for( size_t i=0; i<numPoints; i++ )
	{
		bool success = m_stEvaluator->pointAtUV( Imath::V2f( sReadable[i], tReadable[i] ), evaluatorResult );
		// dividing by 2 maps from the triangle index to the original face index of the mesh before it
		// was triangulated - we can guarantee this because the original mesh was all quads.
		fWritable[i] = success ? evaluatorResult->triangleIndex() / 2 : 0;
		uWritable[i] = success ? evaluatorResult->floatPrimVar( uPrimVar ) : 0;
		vWritable[i] = success ? evaluatorResult->floatPrimVar( vPrimVar ) : 0;
		statusWritable[i] = success;
	}

	CompoundDataPtr result = evaluate( fData, uData, vData, primVarNames );
	result->writable()["gxStatus"] = statusData;

	return result;
}

void GXEvaluator::validatePrimVarNames( const std::vector<std::string> &primVarNames ) const
{
	for( vector<string>::const_iterator it=primVarNames.begin(); it!=primVarNames.end(); it++ )
	{
		PrimitiveVariableTypeMap::const_iterator pvIt = m_primitiveVariableTypes.find( *it );
		if( pvIt == m_primitiveVariableTypes.end() )
		{
			throw InvalidArgumentException( boost::str( boost::format( "Primitive variable \"%s\" does not exist" ) % *it ) );
		}
		if( pvIt->second==InvalidTypeId )
		{
			throw InvalidArgumentException( boost::str( boost::format( "Primitive variable \"%s\" has unsupported type" ) % *it ) );
		}
	}
}

void GXEvaluator::buildSTEvaluator() const
{
	Mutex::scoped_lock lock( m_stEvaluatorMutex, false ); // read only lock
	if( m_stEvaluator )
	{
		return;
	}
	lock.upgrade_to_writer();
	if( m_stEvaluator )
	{
		return;
	}

	size_t nFaces = numFaces();
	size_t nVertices = nFaces * 4;

	IntVectorDataPtr faceIndicesData = new IntVectorData;
	FloatVectorDataPtr uData = new FloatVectorData;
	FloatVectorDataPtr vData = new FloatVectorData;
	std::vector<int> &faceIndicesWritable = faceIndicesData->writable(); faceIndicesWritable.resize( nVertices );
	std::vector<float> &uWritable = uData->writable(); uWritable.resize( nVertices );
	std::vector<float> &vWritable = vData->writable(); vWritable.resize( nVertices );

	size_t vi = 0;
	for( size_t fi=0; fi<nFaces; fi++ )
	{
		faceIndicesWritable[vi] = fi;
		faceIndicesWritable[vi+1] = fi;
		faceIndicesWritable[vi+2] = fi;
		faceIndicesWritable[vi+3] = fi;
		uWritable[vi] = 0;
		uWritable[vi+1] = 0;
		uWritable[vi+2] = 1;
		uWritable[vi+3] = 1;
		vWritable[vi] = 0;
		vWritable[vi+1] = 1;
		vWritable[vi+2] = 1;
		vWritable[vi+3] = 0;
		vi += 4;
	}

	std::vector<std::string> primVarNames;
	primVarNames.push_back( "P" );
	primVarNames.push_back( "s" );
	primVarNames.push_back( "t" );
	CompoundDataPtr vertexData = evaluate( faceIndicesData, uData, vData, primVarNames );

	IntVectorDataPtr verticesPerFaceData = new IntVectorData;
	IntVectorDataPtr vertexIdsData = new IntVectorData;
	std::vector<int> &verticesPerFace = verticesPerFaceData->writable(); verticesPerFace.resize( nFaces, 4 );
	std::vector<int> &vertexIds = vertexIdsData->writable(); vertexIds.resize( nVertices );
	for( size_t i=0; i<nVertices; i++ )
	{
		vertexIds[i] = i;
	}
	MeshPrimitivePtr mesh = new MeshPrimitive( verticesPerFaceData, vertexIdsData );
	mesh->variables["P"] = PrimitiveVariable( PrimitiveVariable::Vertex, vertexData->member<V3fVectorData>( "P" ) );
	mesh->variables["s"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, vertexData->member<FloatVectorData>( "s" ) );
	mesh->variables["t"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, vertexData->member<FloatVectorData>( "t" ) );
	mesh->variables["u"] = PrimitiveVariable( PrimitiveVariable::Vertex, uData );
	mesh->variables["v"] = PrimitiveVariable( PrimitiveVariable::Vertex, vData );

	TriangulateOpPtr op = new TriangulateOp();
	op->inputParameter()->setValue( mesh );
	op->copyParameter()->setTypedValue( false );
	op->throwExceptionsParameter()->setTypedValue( false );
	op->operate();

	m_stEvaluator = new MeshPrimitiveEvaluator( mesh );
}
<|endoftext|>


<commit_before>#ifndef __TIME_ELAPSED_HPP__
#define	__TIME_ELAPSED_HPP__

#include <chrono>
#include <iostream>
#include <iomanip>
#include <string>

#ifdef NO_TIME_ELAPSED_MEASUREMENT
#  define	TIME_ELAPSED_N(n,body)					time_elapsed_impl_noop<n>([&]{body;})
#  define	TIME_ELAPSED_EXP_N(n,body)				time_elapsed_impl_noop<n>([&]{body;})
#  define	TIME_ELAPSED_MARKER_N(n,marker,body)	time_elapsed_impl_noop<n>([&]{body;})
#else
#  define	TIME_ELAPSED_N(n,body)					time_elapsed_impl1<n>([&]{body;},__FILE__,__LINE__)
#  define	TIME_ELAPSED_EXP_N(n,body)				time_elapsed_impl2<n>([&]{body;},#body)
#  define	TIME_ELAPSED_MARKER_N(n,marker,body)	time_elapsed_impl_core<n>([&]{body;},marker)
#endif

#define	TIME_ELAPSED(body)							TIME_ELAPSED_N(1,body)
#define	TIME_ELAPSED_EXP(body)						TIME_ELAPSED_EXP_N(1,body)
#define	TIME_ELAPSED_MARKER(marker,body)			TIME_ELAPSED_MARKER_N(1,marker,body)

#define	TIME_ELAPSED_HEADER							"ElapsedTime: "
#define	TIME_ELAPSED_HEADER_WIDTH					48

template <const int count, typename BlockBody>
inline void time_elapsed_impl_core(BlockBody body, const std::string& header, std::ostream &o = std::cout)
{
	using namespace std;
	using namespace std::chrono;

	auto t0 = high_resolution_clock::now();

	for (int i = 0; i < count; i++)
		body();

	auto t1 = high_resolution_clock::now();

	// Now, print out the elapsed time with its header
	auto prev_flags = o.flags();
	auto prev_precision = o.precision();
	auto prev_width = o.width();

	o << left << setw(TIME_ELAPSED_HEADER_WIDTH) << (TIME_ELAPSED_HEADER + header);
	o << "cnt:" << setw(8) << count;
	o << setw(12) << right << fixed << setprecision(3)
		<< (float)duration_cast<microseconds>(t1 - t0).count()/1000 << " msec" << endl;

	o.width(prev_width);
	o.precision(prev_precision);
	o.flags(prev_flags);
}

template <const int count, typename BlockBody>
inline void time_elapsed_impl_noop(BlockBody body, std::ostream &o = std::cout)
{
	for (int i = 0; i < count; i++)
		body();
}

template <int count, typename BlockBody>
inline void time_elapsed_impl1(BlockBody body, const char * const path, const int lno, std::ostream &o = std::cout)
{
	std::string basename{ path + std::string(path).find_last_of("\\/") + 1 };
	time_elapsed_impl_core<count>(body, basename + " at L." + std::to_string(lno), o);
}

template <int count, typename BlockBody>
inline void time_elapsed_impl2(BlockBody body, const char * const bodystr, std::ostream &o = std::cout)
{
	std::string heading{ std::string(bodystr).substr(0,TIME_ELAPSED_HEADER_WIDTH - sizeof(TIME_ELAPSED_HEADER) - 2)	};
	time_elapsed_impl_core<count>(body, heading, o);
}

#endif // !__TIME_ELAPSED_HPP__
<commit_msg>Fix a bug that a comma passed to the macro arguments will trigger C4002<commit_after>#ifndef __TIME_ELAPSED_HPP__
#define	__TIME_ELAPSED_HPP__

#include <chrono>
#include <iostream>
#include <iomanip>
#include <string>

#ifdef NO_TIME_ELAPSED_MEASUREMENT
#  define	TIME_ELAPSED_N(n,...)					time_elapsed_impl_noop<n>([&]{__VA_ARGS__;})
#  define	TIME_ELAPSED_EXP_N(n,...)				time_elapsed_impl_noop<n>([&]{__VA_ARGS__;})
#  define	TIME_ELAPSED_MARKER_N(n,marker,...)		time_elapsed_impl_noop<n>([&]{__VA_ARGS__;})
#else
#  define	TIME_ELAPSED_N(n,...)					time_elapsed_impl1<n>([&]{__VA_ARGS__;},__FILE__,__LINE__)
#  define	TIME_ELAPSED_EXP_N(n,...)				time_elapsed_impl2<n>([&]{__VA_ARGS__;},#__VA_ARGS__)
#  define	TIME_ELAPSED_MARKER_N(n,marker,...)		time_elapsed_impl_core<n>([&]{__VA_ARGS__;},marker)
#endif

#define	TIME_ELAPSED(...)							TIME_ELAPSED_N(1,__VA_ARGS__)
#define	TIME_ELAPSED_EXP(...)						TIME_ELAPSED_EXP_N(1,__VA_ARGS__)
#define	TIME_ELAPSED_MARKER(marker,...)				TIME_ELAPSED_MARKER_N(1,marker,__VA_ARGS__)

#define	TIME_ELAPSED_HEADER							"ElapsedTime: "
#define	TIME_ELAPSED_HEADER_WIDTH					48

template <const int count, typename BlockBody>
inline void time_elapsed_impl_core(BlockBody body, const std::string& header, std::ostream &o = std::cout)
{
	using namespace std;
	using namespace std::chrono;

	auto t0 = high_resolution_clock::now();

	for (int i = 0; i < count; i++)
		body();

	auto t1 = high_resolution_clock::now();

	// Now, print out the elapsed time with its header
	auto prev_flags = o.flags();
	auto prev_precision = o.precision();
	auto prev_width = o.width();

	o << left << setw(TIME_ELAPSED_HEADER_WIDTH) << (TIME_ELAPSED_HEADER + header);
	o << "cnt:" << setw(8) << count;
	o << setw(12) << right << fixed << setprecision(3)
		<< (float)duration_cast<microseconds>(t1 - t0).count()/1000 << " msec" << endl;

	o.width(prev_width);
	o.precision(prev_precision);
	o.flags(prev_flags);
}

template <const int count, typename BlockBody>
inline void time_elapsed_impl_noop(BlockBody body, std::ostream &o = std::cout)
{
	for (int i = 0; i < count; i++)
		body();
}

template <int count, typename BlockBody>
inline void time_elapsed_impl1(BlockBody body, const char * const path, const int lno, std::ostream &o = std::cout)
{
	std::string basename{ path + std::string(path).find_last_of("\\/") + 1 };
	time_elapsed_impl_core<count>(body, basename + " at L." + std::to_string(lno), o);
}

template <int count, typename BlockBody>
inline void time_elapsed_impl2(BlockBody body, const char * const bodystr, std::ostream &o = std::cout)
{
	std::string heading{ std::string(bodystr).substr(0,TIME_ELAPSED_HEADER_WIDTH - sizeof(TIME_ELAPSED_HEADER) - 2)	};
	time_elapsed_impl_core<count>(body, heading, o);
}

#endif // !__TIME_ELAPSED_HPP__
<|endoftext|>


<commit_before>//
// Created by Kevin on 22/10/2016.
//

#include <stdexcept>
#include "Timer.h"

using namespace std;
using namespace Gameboy::CPU;
using namespace Gameboy::Timer;

Timer::Timer(IInterruptible &p_interruptible)
    : interruptible (p_interruptible),
      timerReg (),
      divClock (),
      timerClock ()
{}

// Cpu speed is 4,194,304 Hz
const uint16_t Timer::ticksForSpeed[4] = {
        1024, // 4096 Hz
          16, // 262144 Hz
          64, // 65536 Hz
         256  // 16384 Hz
};

uint8_t Timer::getTimerSpeed() {
    return static_cast<uint8_t>(timerReg[OffTAC] & 0x03);
}

bool Timer::isTimerEnabled() {
    return (timerReg[OffTAC] & (1 << 2)) != 0;
}

bool Timer::next(uint32_t ticks) {
    // Handle Div Register
    divClock += ticks;
    if (divClock >= ticksForSpeed[3]) {
        divClock = 0;
        ++timerReg[OffDIV];
    }

    // Handle Timer Register
    if (isTimerEnabled()) {
        timerClock += ticks;
        if (timerClock >= ticksForSpeed[getTimerSpeed()]) {
            timerClock = 0;
            if (++timerReg[OffTIMA] == 0) {
                // overflow - Load Module Value
                timerReg[OffTIMA] = timerReg[OffTMA];
                // interrupt
                interruptible.requestInterrupt(TimerIrq);
            }
        }
    } /*else {
        timerClock = 0; // Not sure about this, but I don't think so
    }*/

    return true;
}

uint8_t Timer::read(uint16_t address) const {
    if (address >= DIV && address <= TAC) {
        return timerReg[address - DIV];
    }
    throw runtime_error("Wrong read address for Timer: " + to_string(address));
}

void Timer::write(uint16_t address, uint8_t datum) {
    if (address >= DIV && address <= TAC) {
        const RegisterOffset offset = static_cast<RegisterOffset>(address - DIV);
        switch (offset) {
            case OffDIV:
                timerReg[offset] = 0;
                // divClock = 0; // Not sure about this, but I don't think so
                break;
            case OffTIMA:
            case OffTMA:
                timerReg[offset] = datum;
                break;
            case OffTAC:
                timerReg[offset] = datum; //static_cast<uint8_t>(datum & 0x07);
                if (datum > 7) {
                    throw runtime_error ("Writing value: " + to_string(datum) + " to Timer Control Register");
                }
                break;
        }
    } else {
        throw runtime_error("Wrong write address for Timer: " + to_string(address));
    }
}
<commit_msg>Fix current Timer bugs<commit_after>//
// Created by Kevin on 22/10/2016.
//

#include <stdexcept>
#include "Timer.h"

using namespace std;
using namespace Gameboy::CPU;
using namespace Gameboy::Timer;

Timer::Timer(IInterruptible &p_interruptible)
    : interruptible (p_interruptible),
      timerReg (),
      divClock (),
      timerClock ()
{}

// Cpu speed is 4,194,304 Hz
const uint16_t Timer::ticksForSpeed[4] = {
        1024, // 4096 Hz
          16, // 262144 Hz
          64, // 65536 Hz
         256  // 16384 Hz
};

uint8_t Timer::getTimerSpeed() {
    return static_cast<uint8_t>(timerReg[OffTAC] & 0x03);
}

bool Timer::isTimerEnabled() {
    return (timerReg[OffTAC] & (1 << 2)) != 0;
}

bool Timer::next(uint32_t ticks) {
    // Handle Div Register
    divClock += ticks;
    if (divClock >= ticksForSpeed[3]) {
        divClock -= ticksForSpeed[3];
        ++timerReg[OffDIV];
    }

    // Handle Timer Register
    if (isTimerEnabled()) {
        timerClock += ticks;
        uint16_t ticksFS = ticksForSpeed[getTimerSpeed()];
        if (timerClock >= ticksFS) {
            timerClock -= ticksFS;
            if (++timerReg[OffTIMA] == 0) {
                // overflow - Load Module Value
                timerReg[OffTIMA] = timerReg[OffTMA];
                // interrupt
                interruptible.requestInterrupt(TimerIrq);
            }
        }
    } /*else {
        timerClock = 0; // Not sure about this, but I don't think so
    }*/

    return true;
}

uint8_t Timer::read(uint16_t address) const {
    if (address >= DIV && address <= TAC) {
        return timerReg[address - DIV];
    }
    throw runtime_error("Wrong read address for Timer: " + to_string(address));
}

void Timer::write(uint16_t address, uint8_t datum) {
    if (address >= DIV && address <= TAC) {
        const RegisterOffset offset = static_cast<RegisterOffset>(address - DIV);
        switch (offset) {
            case OffDIV:
                timerReg[offset] = 0;
                divClock = 0; // Not sure about this, but I don't think so
                break;
            case OffTIMA:
            case OffTMA:
                timerReg[offset] = datum;
                break;
            case OffTAC:
                timerReg[offset] = datum; //static_cast<uint8_t>(datum & 0x07);
                timerClock = 0;
                if (datum > 7) {
                    throw runtime_error ("Writing value: " + to_string(datum) + " to Timer Control Register");
                }
                break;
        }
    } else {
        throw runtime_error("Wrong write address for Timer: " + to_string(address));
    }
}
<|endoftext|>