<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * BPBase.cpp
 *
 *  Created on: Sep 5, 2019
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include "BPBase.h"
#include "BPBase.tcc"

#include "adios2/helper/adiosFunctions.h"

#include "adios2/toolkit/format/bp/bpOperation/compress/BPBZIP2.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPBlosc.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPMGARD.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPPNG.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPSZ.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPZFP.h"

namespace adios2
{
namespace format
{

// PUBLIC
BPBase::SerialElementIndex::SerialElementIndex(const uint32_t memberID,
                                               const size_t bufferSize)
: MemberID(memberID)
{
    Buffer.reserve(bufferSize);
}

BPBase::Minifooter::Minifooter(const int8_t version) : Version(version) {}

BPBase::BPBase(helper::Comm const &comm, const bool debugMode)
: m_Comm(comm), m_DebugMode(debugMode)
{
    m_RankMPI = m_Comm.Rank();
    m_SizeMPI = m_Comm.Size();
    m_Profiler.m_IsActive = true; // default
}

void BPBase::Init(const Params &parameters, const std::string hint)
{
    // Parse Parameters
    for (const auto &parameter : parameters)
    {
        const std::string key = helper::LowerCase(parameter.first);
        const std::string value = helper::LowerCase(parameter.second);

        if (key == "profile")
        {
            m_Profiler.m_IsActive = helper::StringTo<bool>(
                value, m_DebugMode, " in Parameter key=Profile " + hint);
        }
        else if (key == "profileunits")
        {
            m_Parameters.ProfileUnit =
                helper::StringToTimeUnit(value, m_DebugMode, hint);
        }
        else if (key == "opentimeoutsecs")
        {
            m_Parameters.OpenTimeoutSecs = helper::StringTo<float>(
                value, m_DebugMode,
                " in Parameter key=OpenTimeOutSecs " + hint);

            if (m_Parameters.OpenTimeoutSecs < 0.0)
            {
                m_Parameters.OpenTimeoutSecs =
                    std::numeric_limits<float>::max() / 10000;
            }
        }
        else if (key == "beginsteppollingfrequencysecs")
        {
            m_Parameters.BeginStepPollingFrequencySecs =
                helper::StringTo<float>(value, m_DebugMode,
                                        " in Parameter key=OpenTimeOutSecs " +
                                            hint);

            if (m_Parameters.BeginStepPollingFrequencySecs < 0.0)
            {
                m_Parameters.BeginStepPollingFrequencySecs = 1.0; // a second
            }
            m_Parameters.BeginStepPollingFrequencyIsSet = true;
        }
        else if (key == "buffergrowthfactor")
        {
            m_Parameters.GrowthFactor = helper::StringTo<float>(
                value, m_DebugMode,
                " in Parameter key=BufferGrowthFactor " + hint);
        }
        else if (key == "initialbuffersize")
        {
            // it will resize m_Data
            m_Parameters.InitialBufferSize = helper::StringToByteUnits(
                value, m_DebugMode,
                "for Parameter key=InitialBufferSize, in call to Open");

            if (m_DebugMode && m_Parameters.InitialBufferSize <
                                   DefaultInitialBufferSize) // 16384b
            {
                throw std::invalid_argument(
                    "ERROR: wrong value for Parameter key=InitialBufferSize, "
                    "it must be larger than 16Kb (minimum default), " +
                    hint);
            }
        }
        else if (key == "maxbuffersize")
        {
            m_Parameters.MaxBufferSize = helper::StringToByteUnits(
                value, m_DebugMode,
                "for Parameter key=MaxBufferSize, in call to Open");
        }
        else if (key == "threads")
        {
            m_Parameters.Threads =
                static_cast<unsigned int>(helper::StringTo<uint32_t>(
                    value, m_DebugMode, " in Parameter key=Threads " + hint));
        }
        else if (key == "asynctasks")
        {
            m_Parameters.AsyncTasks = helper::StringTo<bool>(
                value, m_DebugMode, " in Parameter key=AsyncTasks " + hint);
        }
        else if (key == "statslevel")
        {
            m_Parameters.StatsLevel =
                static_cast<unsigned int>(helper::StringTo<uint32_t>(
                    value, m_DebugMode,
                    " in Parameter key=StatsLevel " + hint));
            if (m_DebugMode &&
                m_Parameters.StatsLevel > 5)
            {
                throw std::invalid_argument(
                    "ERROR: value for Parameter key=StatsLevel must be "
                    "an integer in the range [0,5], " +
                    hint);
            }
        }
        else if (key == "statsblocksize")
        {
            m_Parameters.StatsBlockSize = helper::StringToSizeT(
                value, m_DebugMode, " in Parameter key=StatsBlockSize " + hint);
        }
        else if (key == "collectivemetadata")
        {
            m_Parameters.CollectiveMetadata = helper::StringTo<bool>(
                value, m_DebugMode,
                " in Parameter key=CollectiveMetadata " + hint);
        }
        else if (key == "flushstepscount")
        {
            m_Parameters.FlushStepsCount = helper::StringToSizeT(
                value, m_DebugMode,
                " in Parameter key=FlushStepsCount " + hint);
        }
        else if (key == "substreams")
        {
            int subStreams = static_cast<int>(helper::StringTo<int32_t>(
                value, m_DebugMode, " in Parameter key=SubStreams " + hint));

            if (subStreams < 1)
            {
                subStreams = 1;
            }
            else if (subStreams > m_SizeMPI)
            {
                subStreams = m_SizeMPI;
            }

            if (subStreams < m_SizeMPI)
            {
                m_Aggregator.Init(subStreams, m_Comm);
            }
        }
        else if (key == "node-local")
        {
            m_Parameters.NodeLocal = helper::StringTo<bool>(
                value, m_DebugMode, " in Parameter key=node-local " + hint);
        }
    }

    // set timers if active
    if (m_Profiler.m_IsActive)
    {
        const TimeUnit timeUnit = m_Parameters.ProfileUnit;
        m_Profiler.m_Timers.emplace(
            "buffering", profiling::Timer("buffering", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "memcpy", profiling::Timer("memcpy", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "minmax", profiling::Timer("minmax", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "meta_sort_merge",
            profiling::Timer("meta_sort_merge", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "aggregation",
            profiling::Timer("aggregation", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "mkdir", profiling::Timer("mkdir", timeUnit, m_DebugMode));
        m_Profiler.m_Bytes.emplace("buffering", 0);
    }

    // set initial buffer size
    m_Profiler.Start("buffering");
    m_Data.Resize(m_Parameters.InitialBufferSize, hint);
    m_Profiler.Stop("buffering");
}

BPBase::ResizeResult BPBase::ResizeBuffer(const size_t dataIn,
                                          const std::string hint)
{
    m_Profiler.Start("buffering");
    const size_t currentSize = m_Data.m_Buffer.size();
    const size_t requiredSize = dataIn + m_Data.m_Position;
    const size_t maxBufferSize = m_Parameters.MaxBufferSize;

    ResizeResult result = ResizeResult::Unchanged;

    if (dataIn > maxBufferSize)
    {
        throw std::runtime_error(
            "ERROR: data size: " +
            std::to_string(static_cast<float>(dataIn) / (1024. * 1024.)) +
            " Mb is too large for adios2 bp MaxBufferSize=" +
            std::to_string(static_cast<float>(maxBufferSize) /
                           (1024. * 1024.)) +
            "Mb, try increasing MaxBufferSize in call to IO SetParameters " +
            hint + "\n");
    }

    if (requiredSize <= currentSize)
    {
        // do nothing, unchanged is default
    }
    else if (requiredSize > maxBufferSize)
    {
        if (currentSize < maxBufferSize)
        {
            m_Data.Resize(maxBufferSize, " when resizing buffer to " +
                                             std::to_string(maxBufferSize) +
                                             "bytes, " + hint + "\n");
        }
        result = ResizeResult::Flush;
    }
    else // buffer must grow
    {
        if (currentSize < maxBufferSize)
        {
            const float growthFactor = m_Parameters.GrowthFactor;
            const size_t nextSize = std::min(
                maxBufferSize, helper::NextExponentialSize(
                                   requiredSize, currentSize, growthFactor));
            m_Data.Resize(nextSize, " when resizing buffer to " +
                                        std::to_string(nextSize) + "bytes, " +
                                        hint);
            result = ResizeResult::Success;
        }
    }

    m_Profiler.Stop("buffering");
    return result;
}

void BPBase::ResetBuffer(Buffer &buffer, const bool resetAbsolutePosition,
                         const bool zeroInitialize)
{
    m_Profiler.Start("buffering");
    buffer.Reset(resetAbsolutePosition, zeroInitialize);
    m_Profiler.Stop("buffering");
}

// PROTECTED
std::vector<uint8_t>
BPBase::GetTransportIDs(const std::vector<std::string> &transportsTypes) const
    noexcept
{
    auto lf_GetTransportID = [](const std::string method) -> uint8_t {
        int id = METHOD_UNKNOWN;
        if (method == "File_NULL")
        {
            id = METHOD_NULL;
        }
        else if (method == "File_POSIX")
        {
            id = METHOD_POSIX;
        }
        else if (method == "File_fstream")
        {
            id = METHOD_FSTREAM;
        }
        else if (method == "File_stdio")
        {
            id = METHOD_FILE;
        }
        else if (method == "WAN_zmq")
        {
            id = METHOD_ZMQ;
        }

        return static_cast<uint8_t>(id);
    };

    std::vector<uint8_t> transportsIDs;
    transportsIDs.reserve(transportsTypes.size());

    for (const std::string transportType : transportsTypes)
    {
        transportsIDs.push_back(lf_GetTransportID(transportType));
    }

    return transportsIDs;
}

size_t BPBase::GetProcessGroupIndexSize(const std::string name,
                                        const std::string timeStepName,
                                        const size_t transportsSize) const
    noexcept
{
    // pgIndex + list of methods (transports)
    const size_t pgSize =
        (name.length() + timeStepName.length() + 23) + (3 + transportsSize);
    return pgSize;
}

BPBase::ProcessGroupIndex
BPBase::ReadProcessGroupIndexHeader(const std::vector<char> &buffer,
                                    size_t &position,
                                    const bool isLittleEndian) const noexcept
{
    ProcessGroupIndex index;
    index.Length =
        helper::ReadValue<uint16_t>(buffer, position, isLittleEndian);
    index.Name = ReadBPString(buffer, position, isLittleEndian);
    index.IsColumnMajor =
        helper::ReadValue<char>(buffer, position, isLittleEndian);
    index.ProcessID =
        helper::ReadValue<int32_t>(buffer, position, isLittleEndian);
    index.StepName = ReadBPString(buffer, position, isLittleEndian);
    index.Step = helper::ReadValue<uint32_t>(buffer, position, isLittleEndian);
    index.Offset =
        helper::ReadValue<uint64_t>(buffer, position, isLittleEndian);
    return index;
}

std::string BPBase::ReadBPString(const std::vector<char> &buffer,
                                 size_t &position,
                                 const bool isLittleEndian) const noexcept
{
    const size_t size = static_cast<size_t>(
        helper::ReadValue<uint16_t>(buffer, position, isLittleEndian));

    if (size == 0)
    {
        return "";
    }

    const std::string values(&buffer[position], size);
    position += size;
    return values;
}

// static members
const std::set<std::string> BPBase::m_TransformTypes = {
    {"unknown", "none", "identity", "bzip2", "sz", "zfp", "mgard", "png",
     "blosc"}};

const std::map<int, std::string> BPBase::m_TransformTypesToNames = {
    {transform_unknown, "unknown"},   {transform_none, "none"},
    {transform_identity, "identity"}, {transform_sz, "sz"},
    {transform_zfp, "zfp"},           {transform_mgard, "mgard"},
    {transform_png, "png"},           {transform_bzip2, "bzip2"},
    {transform_blosc, "blosc"}};

BPBase::TransformTypes
BPBase::TransformTypeEnum(const std::string transformType) const noexcept
{
    TransformTypes transformEnum = transform_unknown;

    for (const auto &pair : m_TransformTypesToNames)
    {
        if (pair.second == transformType)
        {
            transformEnum = static_cast<TransformTypes>(pair.first);
            break;
        }
    }
    return transformEnum;
}

std::shared_ptr<BPOperation>
BPBase::SetBPOperation(const std::string type) const noexcept
{
    std::shared_ptr<BPOperation> bpOp;
    if (type == "sz")
    {
        bpOp = std::make_shared<BPSZ>();
    }
    else if (type == "zfp")
    {
        bpOp = std::make_shared<BPZFP>();
    }
    else if (type == "mgard")
    {
        bpOp = std::make_shared<BPMGARD>();
    }
    else if (type == "bzip2")
    {
        bpOp = std::make_shared<BPBZIP2>();
    }
    else if (type == "png")
    {
        bpOp = std::make_shared<BPPNG>();
    }
    else if (type == "blosc")
    {
        bpOp = std::make_shared<BPBlosc>();
    }

    return bpOp;
}

std::map<size_t, std::shared_ptr<BPOperation>> BPBase::SetBPOperations(
    const std::vector<core::VariableBase::Operation> &operations) const
{
    std::map<size_t, std::shared_ptr<BPOperation>> bpOperations;

    for (size_t i = 0; i < operations.size(); ++i)
    {
        const std::string type = operations[i].Op->m_Type;
        std::shared_ptr<BPOperation> bpOperation = SetBPOperation(type);

        if (bpOperation) // if the result is a supported type
        {
            bpOperations.emplace(i, bpOperation);
        }
    }
    return bpOperations;
}

#define declare_template_instantiation(T)                                      \
    template BPBase::Characteristics<T>                                        \
    BPBase::ReadElementIndexCharacteristics(const std::vector<char> &,         \
                                            size_t &, const BPBase::DataTypes, \
                                            const bool, const bool) const;

ADIOS2_FOREACH_STDTYPE_1ARG(declare_template_instantiation)
#undef declare_template_instantiation

} // end namespace format
} // end namespace adios2
<commit_msg>fix clang-format<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * BPBase.cpp
 *
 *  Created on: Sep 5, 2019
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include "BPBase.h"
#include "BPBase.tcc"

#include "adios2/helper/adiosFunctions.h"

#include "adios2/toolkit/format/bp/bpOperation/compress/BPBZIP2.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPBlosc.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPMGARD.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPPNG.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPSZ.h"
#include "adios2/toolkit/format/bp/bpOperation/compress/BPZFP.h"

namespace adios2
{
namespace format
{

// PUBLIC
BPBase::SerialElementIndex::SerialElementIndex(const uint32_t memberID,
                                               const size_t bufferSize)
: MemberID(memberID)
{
    Buffer.reserve(bufferSize);
}

BPBase::Minifooter::Minifooter(const int8_t version) : Version(version) {}

BPBase::BPBase(helper::Comm const &comm, const bool debugMode)
: m_Comm(comm), m_DebugMode(debugMode)
{
    m_RankMPI = m_Comm.Rank();
    m_SizeMPI = m_Comm.Size();
    m_Profiler.m_IsActive = true; // default
}

void BPBase::Init(const Params &parameters, const std::string hint)
{
    // Parse Parameters
    for (const auto &parameter : parameters)
    {
        const std::string key = helper::LowerCase(parameter.first);
        const std::string value = helper::LowerCase(parameter.second);

        if (key == "profile")
        {
            m_Profiler.m_IsActive = helper::StringTo<bool>(
                value, m_DebugMode, " in Parameter key=Profile " + hint);
        }
        else if (key == "profileunits")
        {
            m_Parameters.ProfileUnit =
                helper::StringToTimeUnit(value, m_DebugMode, hint);
        }
        else if (key == "opentimeoutsecs")
        {
            m_Parameters.OpenTimeoutSecs = helper::StringTo<float>(
                value, m_DebugMode,
                " in Parameter key=OpenTimeOutSecs " + hint);

            if (m_Parameters.OpenTimeoutSecs < 0.0)
            {
                m_Parameters.OpenTimeoutSecs =
                    std::numeric_limits<float>::max() / 10000;
            }
        }
        else if (key == "beginsteppollingfrequencysecs")
        {
            m_Parameters.BeginStepPollingFrequencySecs =
                helper::StringTo<float>(value, m_DebugMode,
                                        " in Parameter key=OpenTimeOutSecs " +
                                            hint);

            if (m_Parameters.BeginStepPollingFrequencySecs < 0.0)
            {
                m_Parameters.BeginStepPollingFrequencySecs = 1.0; // a second
            }
            m_Parameters.BeginStepPollingFrequencyIsSet = true;
        }
        else if (key == "buffergrowthfactor")
        {
            m_Parameters.GrowthFactor = helper::StringTo<float>(
                value, m_DebugMode,
                " in Parameter key=BufferGrowthFactor " + hint);
        }
        else if (key == "initialbuffersize")
        {
            // it will resize m_Data
            m_Parameters.InitialBufferSize = helper::StringToByteUnits(
                value, m_DebugMode,
                "for Parameter key=InitialBufferSize, in call to Open");

            if (m_DebugMode && m_Parameters.InitialBufferSize <
                                   DefaultInitialBufferSize) // 16384b
            {
                throw std::invalid_argument(
                    "ERROR: wrong value for Parameter key=InitialBufferSize, "
                    "it must be larger than 16Kb (minimum default), " +
                    hint);
            }
        }
        else if (key == "maxbuffersize")
        {
            m_Parameters.MaxBufferSize = helper::StringToByteUnits(
                value, m_DebugMode,
                "for Parameter key=MaxBufferSize, in call to Open");
        }
        else if (key == "threads")
        {
            m_Parameters.Threads =
                static_cast<unsigned int>(helper::StringTo<uint32_t>(
                    value, m_DebugMode, " in Parameter key=Threads " + hint));
        }
        else if (key == "asynctasks")
        {
            m_Parameters.AsyncTasks = helper::StringTo<bool>(
                value, m_DebugMode, " in Parameter key=AsyncTasks " + hint);
        }
        else if (key == "statslevel")
        {
            m_Parameters.StatsLevel =
                static_cast<unsigned int>(helper::StringTo<uint32_t>(
                    value, m_DebugMode,
                    " in Parameter key=StatsLevel " + hint));
            if (m_DebugMode && m_Parameters.StatsLevel > 5)
            {
                throw std::invalid_argument(
                    "ERROR: value for Parameter key=StatsLevel must be "
                    "an integer in the range [0,5], " +
                    hint);
            }
        }
        else if (key == "statsblocksize")
        {
            m_Parameters.StatsBlockSize = helper::StringToSizeT(
                value, m_DebugMode, " in Parameter key=StatsBlockSize " + hint);
        }
        else if (key == "collectivemetadata")
        {
            m_Parameters.CollectiveMetadata = helper::StringTo<bool>(
                value, m_DebugMode,
                " in Parameter key=CollectiveMetadata " + hint);
        }
        else if (key == "flushstepscount")
        {
            m_Parameters.FlushStepsCount = helper::StringToSizeT(
                value, m_DebugMode,
                " in Parameter key=FlushStepsCount " + hint);
        }
        else if (key == "substreams")
        {
            int subStreams = static_cast<int>(helper::StringTo<int32_t>(
                value, m_DebugMode, " in Parameter key=SubStreams " + hint));

            if (subStreams < 1)
            {
                subStreams = 1;
            }
            else if (subStreams > m_SizeMPI)
            {
                subStreams = m_SizeMPI;
            }

            if (subStreams < m_SizeMPI)
            {
                m_Aggregator.Init(subStreams, m_Comm);
            }
        }
        else if (key == "node-local")
        {
            m_Parameters.NodeLocal = helper::StringTo<bool>(
                value, m_DebugMode, " in Parameter key=node-local " + hint);
        }
    }

    // set timers if active
    if (m_Profiler.m_IsActive)
    {
        const TimeUnit timeUnit = m_Parameters.ProfileUnit;
        m_Profiler.m_Timers.emplace(
            "buffering", profiling::Timer("buffering", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "memcpy", profiling::Timer("memcpy", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "minmax", profiling::Timer("minmax", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "meta_sort_merge",
            profiling::Timer("meta_sort_merge", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "aggregation",
            profiling::Timer("aggregation", timeUnit, m_DebugMode));
        m_Profiler.m_Timers.emplace(
            "mkdir", profiling::Timer("mkdir", timeUnit, m_DebugMode));
        m_Profiler.m_Bytes.emplace("buffering", 0);
    }

    // set initial buffer size
    m_Profiler.Start("buffering");
    m_Data.Resize(m_Parameters.InitialBufferSize, hint);
    m_Profiler.Stop("buffering");
}

BPBase::ResizeResult BPBase::ResizeBuffer(const size_t dataIn,
                                          const std::string hint)
{
    m_Profiler.Start("buffering");
    const size_t currentSize = m_Data.m_Buffer.size();
    const size_t requiredSize = dataIn + m_Data.m_Position;
    const size_t maxBufferSize = m_Parameters.MaxBufferSize;

    ResizeResult result = ResizeResult::Unchanged;

    if (dataIn > maxBufferSize)
    {
        throw std::runtime_error(
            "ERROR: data size: " +
            std::to_string(static_cast<float>(dataIn) / (1024. * 1024.)) +
            " Mb is too large for adios2 bp MaxBufferSize=" +
            std::to_string(static_cast<float>(maxBufferSize) /
                           (1024. * 1024.)) +
            "Mb, try increasing MaxBufferSize in call to IO SetParameters " +
            hint + "\n");
    }

    if (requiredSize <= currentSize)
    {
        // do nothing, unchanged is default
    }
    else if (requiredSize > maxBufferSize)
    {
        if (currentSize < maxBufferSize)
        {
            m_Data.Resize(maxBufferSize, " when resizing buffer to " +
                                             std::to_string(maxBufferSize) +
                                             "bytes, " + hint + "\n");
        }
        result = ResizeResult::Flush;
    }
    else // buffer must grow
    {
        if (currentSize < maxBufferSize)
        {
            const float growthFactor = m_Parameters.GrowthFactor;
            const size_t nextSize = std::min(
                maxBufferSize, helper::NextExponentialSize(
                                   requiredSize, currentSize, growthFactor));
            m_Data.Resize(nextSize, " when resizing buffer to " +
                                        std::to_string(nextSize) + "bytes, " +
                                        hint);
            result = ResizeResult::Success;
        }
    }

    m_Profiler.Stop("buffering");
    return result;
}

void BPBase::ResetBuffer(Buffer &buffer, const bool resetAbsolutePosition,
                         const bool zeroInitialize)
{
    m_Profiler.Start("buffering");
    buffer.Reset(resetAbsolutePosition, zeroInitialize);
    m_Profiler.Stop("buffering");
}

// PROTECTED
std::vector<uint8_t>
BPBase::GetTransportIDs(const std::vector<std::string> &transportsTypes) const
    noexcept
{
    auto lf_GetTransportID = [](const std::string method) -> uint8_t {
        int id = METHOD_UNKNOWN;
        if (method == "File_NULL")
        {
            id = METHOD_NULL;
        }
        else if (method == "File_POSIX")
        {
            id = METHOD_POSIX;
        }
        else if (method == "File_fstream")
        {
            id = METHOD_FSTREAM;
        }
        else if (method == "File_stdio")
        {
            id = METHOD_FILE;
        }
        else if (method == "WAN_zmq")
        {
            id = METHOD_ZMQ;
        }

        return static_cast<uint8_t>(id);
    };

    std::vector<uint8_t> transportsIDs;
    transportsIDs.reserve(transportsTypes.size());

    for (const std::string transportType : transportsTypes)
    {
        transportsIDs.push_back(lf_GetTransportID(transportType));
    }

    return transportsIDs;
}

size_t BPBase::GetProcessGroupIndexSize(const std::string name,
                                        const std::string timeStepName,
                                        const size_t transportsSize) const
    noexcept
{
    // pgIndex + list of methods (transports)
    const size_t pgSize =
        (name.length() + timeStepName.length() + 23) + (3 + transportsSize);
    return pgSize;
}

BPBase::ProcessGroupIndex
BPBase::ReadProcessGroupIndexHeader(const std::vector<char> &buffer,
                                    size_t &position,
                                    const bool isLittleEndian) const noexcept
{
    ProcessGroupIndex index;
    index.Length =
        helper::ReadValue<uint16_t>(buffer, position, isLittleEndian);
    index.Name = ReadBPString(buffer, position, isLittleEndian);
    index.IsColumnMajor =
        helper::ReadValue<char>(buffer, position, isLittleEndian);
    index.ProcessID =
        helper::ReadValue<int32_t>(buffer, position, isLittleEndian);
    index.StepName = ReadBPString(buffer, position, isLittleEndian);
    index.Step = helper::ReadValue<uint32_t>(buffer, position, isLittleEndian);
    index.Offset =
        helper::ReadValue<uint64_t>(buffer, position, isLittleEndian);
    return index;
}

std::string BPBase::ReadBPString(const std::vector<char> &buffer,
                                 size_t &position,
                                 const bool isLittleEndian) const noexcept
{
    const size_t size = static_cast<size_t>(
        helper::ReadValue<uint16_t>(buffer, position, isLittleEndian));

    if (size == 0)
    {
        return "";
    }

    const std::string values(&buffer[position], size);
    position += size;
    return values;
}

// static members
const std::set<std::string> BPBase::m_TransformTypes = {
    {"unknown", "none", "identity", "bzip2", "sz", "zfp", "mgard", "png",
     "blosc"}};

const std::map<int, std::string> BPBase::m_TransformTypesToNames = {
    {transform_unknown, "unknown"},   {transform_none, "none"},
    {transform_identity, "identity"}, {transform_sz, "sz"},
    {transform_zfp, "zfp"},           {transform_mgard, "mgard"},
    {transform_png, "png"},           {transform_bzip2, "bzip2"},
    {transform_blosc, "blosc"}};

BPBase::TransformTypes
BPBase::TransformTypeEnum(const std::string transformType) const noexcept
{
    TransformTypes transformEnum = transform_unknown;

    for (const auto &pair : m_TransformTypesToNames)
    {
        if (pair.second == transformType)
        {
            transformEnum = static_cast<TransformTypes>(pair.first);
            break;
        }
    }
    return transformEnum;
}

std::shared_ptr<BPOperation>
BPBase::SetBPOperation(const std::string type) const noexcept
{
    std::shared_ptr<BPOperation> bpOp;
    if (type == "sz")
    {
        bpOp = std::make_shared<BPSZ>();
    }
    else if (type == "zfp")
    {
        bpOp = std::make_shared<BPZFP>();
    }
    else if (type == "mgard")
    {
        bpOp = std::make_shared<BPMGARD>();
    }
    else if (type == "bzip2")
    {
        bpOp = std::make_shared<BPBZIP2>();
    }
    else if (type == "png")
    {
        bpOp = std::make_shared<BPPNG>();
    }
    else if (type == "blosc")
    {
        bpOp = std::make_shared<BPBlosc>();
    }

    return bpOp;
}

std::map<size_t, std::shared_ptr<BPOperation>> BPBase::SetBPOperations(
    const std::vector<core::VariableBase::Operation> &operations) const
{
    std::map<size_t, std::shared_ptr<BPOperation>> bpOperations;

    for (size_t i = 0; i < operations.size(); ++i)
    {
        const std::string type = operations[i].Op->m_Type;
        std::shared_ptr<BPOperation> bpOperation = SetBPOperation(type);

        if (bpOperation) // if the result is a supported type
        {
            bpOperations.emplace(i, bpOperation);
        }
    }
    return bpOperations;
}

#define declare_template_instantiation(T)                                      \
    template BPBase::Characteristics<T>                                        \
    BPBase::ReadElementIndexCharacteristics(const std::vector<char> &,         \
                                            size_t &, const BPBase::DataTypes, \
                                            const bool, const bool) const;

ADIOS2_FOREACH_STDTYPE_1ARG(declare_template_instantiation)
#undef declare_template_instantiation

} // end namespace format
} // end namespace adios2
<|endoftext|>


<commit_before><commit_msg>ENG-16026 do not migrate  migrated tuples<commit_after><|endoftext|>


<commit_before><commit_msg>memory_resource still needs init_priority when built with GCC 4.9<commit_after><|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 "lineplotprocessor.h"

#include <inviwo/core/datastructures/geometry/basicmesh.h>
#include <inviwo/core/datastructures/buffer/bufferramprecision.h>
#include <modules/animation/datastructures/interpolation.h>

namespace inviwo {

using plot::DataFrame;
using plot::Column;

// The Class Identifier has to be globally unique. Use a reverse DNS naming scheme
const ProcessorInfo lineplotprocessor::processorInfo_{
    "org.inviwo.lineplotprocessor",      // Class identifier
    "lineplotprocessor",                // Display name
    "Undefined",              // Category
    CodeState::Experimental,  // Code state
    Tags::None,               // Tags
};
const ProcessorInfo lineplotprocessor::getProcessorInfo() const {
    return processorInfo_;
}

lineplotprocessor::lineplotprocessor()
    : Processor()
    , dataFrameInport_("dataFrameInport")
    , meshOutport_("outport")
    , position_("position", "Position", vec3(0.0f), vec3(-100.0f), vec3(100.0f)) {

    addPort(dataFrameInport_);
    addPort(meshOutport_);
    addProperty(position_);
}

void lineplotprocessor::process() {
    std::shared_ptr<BasicMesh> mesh = std::make_shared<BasicMesh>();
    IndexBufferRAM* indices = mesh->addIndexBuffer(DrawType::Lines, ConnectivityType::None);

    //auto p = Interpolation<vec3, float>::linear(vec3(0, 0, 0), , percent);

    std::shared_ptr<const DataFrame> inputFrame = dataFrameInport_.getData();

    // We want at least two columns. One named X and one named Y.
    if (inputFrame->getNumberOfColumns() >= 2) {
        std::shared_ptr<const Column> x = nullptr;
        std::shared_ptr<const Column> y = nullptr;

        // Find the columns named X and Y.
        for (size_t i = 0; i < inputFrame->getNumberOfColumns(); i++) {
            if (inputFrame->getHeader(i) == "X") {
                x = inputFrame->getColumn(i);
            } else if (inputFrame->getHeader(i) == "Y") {
                y = inputFrame->getColumn(i);
            }
        }

        if (!x) {
            LogError("Could not find any column named X in the DataFrame!");
            return;
        }

        if (!y) {
            LogError("Could not fin dany column named Y in the DataFrame!");
            return;
        }

        size_t y_size = y->getSize();
        size_t x_size = x->getSize();

        if (y_size != x_size) {
            LogError("The X and Y columns need to contain the same number"
                     " of values!");
        }

        if (y_size == 0 || x_size == 0) {
            return;
        }

        // Find the maximum and minimum values, respectively, and
        // normalise the data ranges to [0, 1].
        double x_min = x->getAsDouble(0);
        double y_min = y->getAsDouble(0);
        double x_max = x->getAsDouble(0);
        double y_max = y->getAsDouble(0);

        // x_size = y_size at this point, only need to check one.
        if (x_size > 1) {
            for (size_t i = 1; i < x_size; i++) {
                double x_val = x->getAsDouble(i);
                double y_val = y->getAsDouble(i);

                x_min = x_val < x_min ? x_val : x_min;
                y_min = y_val < y_min ? y_val : y_min;

                x_max = x_val > x_max ? x_val : x_max;
                y_max = y_val > y_max ? y_val : y_max;
            }
        }

        // Each line segment should start on the current point and end
        // at the next point. Subtract one from the end criteria,
        // since the last point is included when the segment is drawn
        // from the next-to-last point.
        for (size_t i = 0; i < x_size - 1; i++) {
            // Get coordinates and normalise to [0, 1].
            double x_start = (x->getAsDouble(i) - x_min) / (x_max - x_min);
            double y_start = (y->getAsDouble(i) - y_min) / (y_max - y_min);
            double x_end = (x->getAsDouble(i + 1) - x_min) / (x_max - x_min);
            double y_end = (y->getAsDouble(i + 1) - y_min) / (y_max - y_min);

            vec3 start_point = vec3(x_start, y_start, 0);
            indices->add(mesh->addVertex(start_point, start_point,
                         start_point, vec4(255, 255, 255, 0)));

            vec3 end_point = vec3(x_end, y_end, 0);
            indices->add(mesh->addVertex(end_point, end_point,
                         end_point, vec4(255, 255, 255, 0)));
        }
    } else {
        LogInfo("This processor needs two columns to exist in the DataFrame."
                " One named X and one named Y.")
        return;
    }

    meshOutport_.setData(mesh);
}

} // namespace

<commit_msg>Prevent division by zero if all points are equal in one dimension.<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 "lineplotprocessor.h"

#include <inviwo/core/datastructures/geometry/basicmesh.h>
#include <inviwo/core/datastructures/buffer/bufferramprecision.h>
#include <modules/animation/datastructures/interpolation.h>

namespace inviwo {

using plot::DataFrame;
using plot::Column;

// The Class Identifier has to be globally unique. Use a reverse DNS naming scheme
const ProcessorInfo lineplotprocessor::processorInfo_{
    "org.inviwo.lineplotprocessor",      // Class identifier
    "lineplotprocessor",                // Display name
    "Undefined",              // Category
    CodeState::Experimental,  // Code state
    Tags::None,               // Tags
};
const ProcessorInfo lineplotprocessor::getProcessorInfo() const {
    return processorInfo_;
}

lineplotprocessor::lineplotprocessor()
    : Processor()
    , dataFrameInport_("dataFrameInport")
    , meshOutport_("outport")
    , position_("position", "Position", vec3(0.0f), vec3(-100.0f), vec3(100.0f)) {

    addPort(dataFrameInport_);
    addPort(meshOutport_);
    addProperty(position_);
}

void lineplotprocessor::process() {
    std::shared_ptr<BasicMesh> mesh = std::make_shared<BasicMesh>();
    IndexBufferRAM* indices = mesh->addIndexBuffer(DrawType::Lines, ConnectivityType::None);

    //auto p = Interpolation<vec3, float>::linear(vec3(0, 0, 0), , percent);

    std::shared_ptr<const DataFrame> inputFrame = dataFrameInport_.getData();

    // We want at least two columns. One named X and one named Y.
    if (inputFrame->getNumberOfColumns() >= 2) {
        std::shared_ptr<const Column> x = nullptr;
        std::shared_ptr<const Column> y = nullptr;

        // Find the columns named X and Y.
        for (size_t i = 0; i < inputFrame->getNumberOfColumns(); i++) {
            if (inputFrame->getHeader(i) == "X") {
                x = inputFrame->getColumn(i);
            } else if (inputFrame->getHeader(i) == "Y") {
                y = inputFrame->getColumn(i);
            }
        }

        if (!x) {
            LogError("Could not find any column named X in the DataFrame!");
            return;
        }

        if (!y) {
            LogError("Could not fin dany column named Y in the DataFrame!");
            return;
        }

        size_t y_size = y->getSize();
        size_t x_size = x->getSize();

        if (y_size != x_size) {
            LogError("The X and Y columns need to contain the same number"
                     " of values!");
        }

        if (y_size == 0 || x_size == 0) {
            return;
        }

        // Find the maximum and minimum values, respectively, and
        // normalise the data ranges to [0, 1].
        double x_min = x->getAsDouble(0);
        double y_min = y->getAsDouble(0);
        double x_max = x->getAsDouble(0);
        double y_max = y->getAsDouble(0);

        // x_size = y_size at this point, only need to check one.
        if (x_size > 1) {
            for (size_t i = 1; i < x_size; i++) {
                double x_val = x->getAsDouble(i);
                double y_val = y->getAsDouble(i);

                x_min = x_val < x_min ? x_val : x_min;
                y_min = y_val < y_min ? y_val : y_min;

                x_max = x_val > x_max ? x_val : x_max;
                y_max = y_val > y_max ? y_val : y_max;
            }
        }

        // If all values in one dimension have the same value we let
        // them normalise to one by setting the min values to zero.
        if (y_max == y_min) {
            y_min = 0;
        }

        if (x_max == x_min) {
            x_min = 0;
        }

        // Each line segment should start on the current point and end
        // at the next point. Subtract one from the end criteria,
        // since the last point is included when the segment is drawn
        // from the next-to-last point.
        for (size_t i = 0; i < x_size - 1; i++) {
            // Get coordinates and normalise to [0, 1].
            double x_start = (x->getAsDouble(i) - x_min) / (x_max - x_min);
            double y_start = (y->getAsDouble(i) - y_min) / (y_max - y_min);
            double x_end = (x->getAsDouble(i + 1) - x_min) / (x_max - x_min);
            double y_end = (y->getAsDouble(i + 1) - y_min) / (y_max - y_min);

            vec3 start_point = vec3(x_start, y_start, 0);
            indices->add(mesh->addVertex(start_point, start_point,
                         start_point, vec4(255, 255, 255, 0)));

            vec3 end_point = vec3(x_end, y_end, 0);
            indices->add(mesh->addVertex(end_point, end_point,
                         end_point, vec4(255, 255, 255, 0)));
        }
    } else {
        LogInfo("This processor needs two columns to exist in the DataFrame."
                " One named X and one named Y.")
        return;
    }

    meshOutport_.setData(mesh);
}

} // namespace

<|endoftext|>


<commit_before>#include "ClassWrapper.h"
#include "JavaClassUtils.h"
#include "JavaExceptionUtils.h"
#include "JniWeakGlobalRef.h"
#include <string.h>

namespace spotify {
namespace jni {

ClassWrapper::~ClassWrapper() {
  // TODO: Delete mappings
}

bool ClassWrapper::isInitialized() const {
  return _clazz.get() != NULL;
}

const char* ClassWrapper::getSimpleName() const {
  const char* lastSlash = strrchr(getCanonicalName(), '/');
  return lastSlash != NULL ? lastSlash + 1 : getCanonicalName();
}

void ClassWrapper::merge(const ClassWrapper *globalInstance) {
  _clazz = globalInstance->_clazz;
  _methods = globalInstance->_methods;
  _fields = globalInstance->_fields;
  _constructor = globalInstance->_constructor;
}

bool ClassWrapper::persist(JNIEnv *env, jobject javaThis) {
  if (isPersisted()) {
    if (javaThis == NULL) {
      JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalArgumentException,
        "Cannot persist object without corresponding Java instance");
      return false;
    }
    jlong resultPtr = reinterpret_cast<jlong>(this);
    env->SetLongField(javaThis, getField(PERSIST_FIELD_NAME), resultPtr);
    return true;
  }
  return false;
}

bool ClassWrapper::isPersisted() const {
  // TODO: Need test for this
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalStateException,
      "Cannot call isPersisted without class info (forgot to merge?)");
    return false;
  }

  // We expect the persisted field to be cached, otherwise searching for persisted
  // fields in non-persisted classes will throw java.lang.NoSuchField exception. :(
  const std::string key(PERSIST_FIELD_NAME);
  FieldMap::const_iterator mapFindIter = _fields.find(key);
  return mapFindIter != _fields.end();
}

ClassWrapper* ClassWrapper::getPersistedInstance(JNIEnv *env, jobject javaThis) const {
  if (isPersisted()) {
    jlong resultPtr = env->GetLongField(javaThis, getField(PERSIST_FIELD_NAME));
    return reinterpret_cast<ClassWrapper*>(resultPtr);
  } else {
    return NULL;
  }
}

void ClassWrapper::destroy(JNIEnv *env, jobject javaThis) {
  if (isPersisted()) {
    if (javaThis == NULL) {
      JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalArgumentException,
        "Cannot destroy persisted object without corresponding Java instance");
      return;
    }

    jfieldID persistField = getField(PERSIST_FIELD_NAME);
    if (persistField == NULL) {
      JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
        "Cannot destroy, object lacks persist field");
      return;
    }

    jlong resultPtr = env->GetLongField(javaThis, persistField);
    ClassWrapper *instance = reinterpret_cast<ClassWrapper*>(resultPtr);
    if (instance != NULL) {
      delete instance;
      env->SetLongField(javaThis, persistField, 0);
    }
  }
}

void ClassWrapper::setJavaObject(JNIEnv *env, jobject javaThis) {
  // Set up field mappings, if this has not already been done
  if (_field_mappings.empty()) {
    mapFields();
  }

  FieldMap::iterator iter;
  for (iter = _fields.begin(); iter != _fields.end(); ++iter) {
    std::string key = iter->first;
    jfieldID field = iter->second;
    FieldMapping *mapping = getFieldMapping(key.c_str());
    if (field != NULL && mapping != NULL) {
      if (TYPE_EQUALS(mapping->type, kTypeInt)) {
        int *address = static_cast<int*>(mapping->address);
        *address = env->GetIntField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeShort)) {
        short *address = static_cast<short*>(mapping->address);
        *address = env->GetShortField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeBool)) {
        bool *address = static_cast<bool*>(mapping->address);
        *address = env->GetBooleanField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeFloat)) {
        float *address = static_cast<float*>(mapping->address);
        *address = env->GetFloatField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeDouble)) {
        double *address = static_cast<double*>(mapping->address);
        *address = env->GetDoubleField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeString)) {
        jstring string = (jstring)env->GetObjectField(javaThis, field);
        JavaString *address = static_cast<JavaString*>(mapping->address);
        address->setValue(env, string);
      } else if (TYPE_EQUALS(mapping->type, kTypeByte)) {
        unsigned char *address = static_cast<unsigned char*>(mapping->address);
        *address = env->GetByteField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeChar)) {
        wchar_t *address = static_cast<wchar_t*>(mapping->address);
        *address = env->GetCharField(javaThis, field);
      } else {
        // TODO throw
      }
    }
  }
}

jobject ClassWrapper::toJavaObject(JNIEnv *env) {
  if (_constructor == NULL) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Cannot call toJavaObject without a constructor (did you forget to call cacheConstructor() in initialize()?");
    return NULL;
  } else if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Cannot call toJavaObject without registering class info");
    return NULL;
  }

  // Set up field mappings, if this has not already been done
  if (_field_mappings.empty()) {
    mapFields();
  }

  // Create a new Java argument with the default constructor
  // TODO: It would be nice to remove the requirement for a no-arg ctor
  // However, I'm not really sure how to do that without cluttering the interface.
  // Maybe provide an extra argument to setClass()? However, then we would lack
  // the corresponding arguments we'd want to pass in here.
  JniLocalRef<jobject> result;
  result.set(env->NewObject(_clazz.get(), _constructor));

  FieldMap::iterator iter;
  for (iter = _fields.begin(); iter != _fields.end(); ++iter) {
    std::string key = iter->first;
    jfieldID field = iter->second;
    FieldMapping *mapping = getFieldMapping(key.c_str());
    if (field != NULL && mapping != NULL) {
      if (TYPE_EQUALS(mapping->type, kTypeInt)) {
        int *address = static_cast<int*>(mapping->address);
        env->SetIntField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeShort)) {
        short *address = static_cast<short*>(mapping->address);
        env->SetShortField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeBool)) {
        bool *address = static_cast<bool*>(mapping->address);
        env->SetBooleanField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeFloat)) {
        float *address = static_cast<float*>(mapping->address);
        env->SetFloatField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeDouble)) {
        double *address = static_cast<double*>(mapping->address);
        env->SetDoubleField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeString)) {
        JavaString *address = static_cast<JavaString*>(mapping->address);
        JniLocalRef<jstring> string = address->getJavaString(env);
        env->SetObjectField(result, field, string.get());
      } else if (TYPE_EQUALS(mapping->type, kTypeByte)) {
        unsigned char *address = static_cast<unsigned char*>(mapping->address);
        env->SetByteField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeChar)) {
        wchar_t *address = static_cast<wchar_t*>(mapping->address);
        env->SetCharField(result, field, *address);
      } else {
        // TODO throw
      }
    }
  }

  // Persist the current object address to the Java instance
  persist(env, result);
  return result.leak();
}

JniGlobalRef<jclass> ClassWrapper::getClass() const {
  return _clazz;
}

jmethodID ClassWrapper::getMethod(const char *method_name) const {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalStateException,
      "Cannot call getMethod without class info (forgot to merge?)");
    return NULL;
  }

  const std::string key(method_name);
  MethodMap::const_iterator mapFindIter = _methods.find(key);
  if (mapFindIter == _methods.end()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalArgumentException,
      "Method '%s' is not cached in class '%s'", method_name, getCanonicalName());
    return NULL;
  }

  return mapFindIter->second;
}

jfieldID ClassWrapper::getField(const char* field_name) const {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalStateException,
      "Cannot call getField without class info (forgot to merge?)");
    return NULL;
  }

  const std::string key(field_name);
  FieldMap::const_iterator mapFindIter = _fields.find(key);
  if (mapFindIter == _fields.end()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalArgumentException,
      "Field '%s' is not cached in class '%s'", field_name, getCanonicalName());
    return NULL;
  }

  return mapFindIter->second;
}

void ClassWrapper::setClass(JNIEnv *env) {
  _clazz.set(env->FindClass(getCanonicalName()));
  JavaExceptionUtils::checkException(env);
}

void ClassWrapper::cacheConstructor(JNIEnv *env) {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Attempt to call cacheMethod without having set class info");
    return;
  }

  std::string signature;
  JavaClassUtils::makeSignature(signature, kTypeVoid, NULL);
  _constructor = env->GetMethodID(_clazz.get(), "<init>", signature.c_str());
  // TODO: Check if ctor was found
}

void ClassWrapper::cacheMethod(JNIEnv *env, const char* method_name, const char* return_type, ...) {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Attempt to call cacheMethod without having set class info");
    return;
  }

  va_list arguments;
  va_start(arguments, return_type);
  std::string signature;
  JavaClassUtils::makeSignatureWithList(signature, return_type, arguments);
  va_end(arguments);

  jmethodID method = env->GetMethodID(_clazz.get(), method_name, signature.c_str());
  JavaExceptionUtils::checkException(env);
  if (method != NULL) {
    _methods[method_name] = method;
  }
}

void ClassWrapper::cacheField(JNIEnv *env, const char *field_name, const char *field_type) {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Attempt to call cacheField without having set class info");
    return;
  }

  jfieldID field = env->GetFieldID(_clazz.get(), field_name, field_type);
  JavaExceptionUtils::checkException(env);
  if (field != NULL) {
    _fields[field_name] = field;
  }
}

void ClassWrapper::mapField(const char *field_name, const char *field_type, void *field_ptr) {
  FieldMapping *mapping = new FieldMapping;
  mapping->type = field_type;
  mapping->address = field_ptr;
  _field_mappings[field_name] = mapping;
}

FieldMapping* ClassWrapper::getFieldMapping(const char *key) const {
  std::string keyString(key);
  std::map<std::string, FieldMapping*>::const_iterator findMapIter = _field_mappings.find(keyString);
  return findMapIter != _field_mappings.end() ? findMapIter->second : NULL;
}

void ClassWrapper::addNativeMethod(const char *method_name, void *function, const char *return_type, ...) {
  JNINativeMethod nativeMethod;
  nativeMethod.name = const_cast<char*>(method_name);
  nativeMethod.fnPtr = function;

  va_list arguments;
  va_start(arguments, return_type);
  std::string signature;
  JavaClassUtils::makeSignatureWithList(signature, return_type, arguments);
  nativeMethod.signature = const_cast<char*>(strdup(signature.c_str()));
  va_end(arguments);

  _jni_methods.push_back(nativeMethod);
}

bool ClassWrapper::registerNativeMethods(JNIEnv *env) {
  if (_jni_methods.empty()) {
    return false;
  }

  if (!isInitialized()) {
    JavaExceptionUtils::throwRuntimeException(env, "Could not find cached class for %s", getCanonicalName());
    return false;
  }

  return (env->RegisterNatives(_clazz.get(), &_jni_methods[0], (jint)_jni_methods.size()) < 0);
}

} // namespace jni
} // namespace spotify
<commit_msg>Fix performance warning on Windows<commit_after>#include "ClassWrapper.h"
#include "JavaClassUtils.h"
#include "JavaExceptionUtils.h"
#include "JniWeakGlobalRef.h"
#include <string.h>

namespace spotify {
namespace jni {

ClassWrapper::~ClassWrapper() {
  // TODO: Delete mappings
}

bool ClassWrapper::isInitialized() const {
  return _clazz.get() != NULL;
}

const char* ClassWrapper::getSimpleName() const {
  const char* lastSlash = strrchr(getCanonicalName(), '/');
  return lastSlash != NULL ? lastSlash + 1 : getCanonicalName();
}

void ClassWrapper::merge(const ClassWrapper *globalInstance) {
  _clazz = globalInstance->_clazz;
  _methods = globalInstance->_methods;
  _fields = globalInstance->_fields;
  _constructor = globalInstance->_constructor;
}

bool ClassWrapper::persist(JNIEnv *env, jobject javaThis) {
  if (isPersisted()) {
    if (javaThis == NULL) {
      JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalArgumentException,
        "Cannot persist object without corresponding Java instance");
      return false;
    }
    jlong resultPtr = reinterpret_cast<jlong>(this);
    env->SetLongField(javaThis, getField(PERSIST_FIELD_NAME), resultPtr);
    return true;
  }
  return false;
}

bool ClassWrapper::isPersisted() const {
  // TODO: Need test for this
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalStateException,
      "Cannot call isPersisted without class info (forgot to merge?)");
    return false;
  }

  // We expect the persisted field to be cached, otherwise searching for persisted
  // fields in non-persisted classes will throw java.lang.NoSuchField exception. :(
  const std::string key(PERSIST_FIELD_NAME);
  FieldMap::const_iterator mapFindIter = _fields.find(key);
  return mapFindIter != _fields.end();
}

ClassWrapper* ClassWrapper::getPersistedInstance(JNIEnv *env, jobject javaThis) const {
  if (isPersisted()) {
    jlong resultPtr = env->GetLongField(javaThis, getField(PERSIST_FIELD_NAME));
    return reinterpret_cast<ClassWrapper*>(resultPtr);
  } else {
    return NULL;
  }
}

void ClassWrapper::destroy(JNIEnv *env, jobject javaThis) {
  if (isPersisted()) {
    if (javaThis == NULL) {
      JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalArgumentException,
        "Cannot destroy persisted object without corresponding Java instance");
      return;
    }

    jfieldID persistField = getField(PERSIST_FIELD_NAME);
    if (persistField == NULL) {
      JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
        "Cannot destroy, object lacks persist field");
      return;
    }

    jlong resultPtr = env->GetLongField(javaThis, persistField);
    ClassWrapper *instance = reinterpret_cast<ClassWrapper*>(resultPtr);
    if (instance != NULL) {
      delete instance;
      env->SetLongField(javaThis, persistField, 0);
    }
  }
}

void ClassWrapper::setJavaObject(JNIEnv *env, jobject javaThis) {
  // Set up field mappings, if this has not already been done
  if (_field_mappings.empty()) {
    mapFields();
  }

  FieldMap::iterator iter;
  for (iter = _fields.begin(); iter != _fields.end(); ++iter) {
    std::string key = iter->first;
    jfieldID field = iter->second;
    FieldMapping *mapping = getFieldMapping(key.c_str());
    if (field != NULL && mapping != NULL) {
      if (TYPE_EQUALS(mapping->type, kTypeInt)) {
        int *address = static_cast<int*>(mapping->address);
        *address = env->GetIntField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeShort)) {
        short *address = static_cast<short*>(mapping->address);
        *address = env->GetShortField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeBool)) {
        bool *address = static_cast<bool*>(mapping->address);
        // The somewhat odd "? true : false" fixes a performance warning on windows,
        // since GetBooleanField actually returns jboolean, not bool.
        *address = env->GetBooleanField(javaThis, field) ? true : false;
      } else if (TYPE_EQUALS(mapping->type, kTypeFloat)) {
        float *address = static_cast<float*>(mapping->address);
        *address = env->GetFloatField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeDouble)) {
        double *address = static_cast<double*>(mapping->address);
        *address = env->GetDoubleField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeString)) {
        jstring string = (jstring)env->GetObjectField(javaThis, field);
        JavaString *address = static_cast<JavaString*>(mapping->address);
        address->setValue(env, string);
      } else if (TYPE_EQUALS(mapping->type, kTypeByte)) {
        unsigned char *address = static_cast<unsigned char*>(mapping->address);
        *address = env->GetByteField(javaThis, field);
      } else if (TYPE_EQUALS(mapping->type, kTypeChar)) {
        wchar_t *address = static_cast<wchar_t*>(mapping->address);
        *address = env->GetCharField(javaThis, field);
      } else {
        // TODO throw
      }
    }
  }
}

jobject ClassWrapper::toJavaObject(JNIEnv *env) {
  if (_constructor == NULL) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Cannot call toJavaObject without a constructor (did you forget to call cacheConstructor() in initialize()?");
    return NULL;
  } else if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Cannot call toJavaObject without registering class info");
    return NULL;
  }

  // Set up field mappings, if this has not already been done
  if (_field_mappings.empty()) {
    mapFields();
  }

  // Create a new Java argument with the default constructor
  // TODO: It would be nice to remove the requirement for a no-arg ctor
  // However, I'm not really sure how to do that without cluttering the interface.
  // Maybe provide an extra argument to setClass()? However, then we would lack
  // the corresponding arguments we'd want to pass in here.
  JniLocalRef<jobject> result;
  result.set(env->NewObject(_clazz.get(), _constructor));

  FieldMap::iterator iter;
  for (iter = _fields.begin(); iter != _fields.end(); ++iter) {
    std::string key = iter->first;
    jfieldID field = iter->second;
    FieldMapping *mapping = getFieldMapping(key.c_str());
    if (field != NULL && mapping != NULL) {
      if (TYPE_EQUALS(mapping->type, kTypeInt)) {
        int *address = static_cast<int*>(mapping->address);
        env->SetIntField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeShort)) {
        short *address = static_cast<short*>(mapping->address);
        env->SetShortField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeBool)) {
        bool *address = static_cast<bool*>(mapping->address);
        env->SetBooleanField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeFloat)) {
        float *address = static_cast<float*>(mapping->address);
        env->SetFloatField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeDouble)) {
        double *address = static_cast<double*>(mapping->address);
        env->SetDoubleField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeString)) {
        JavaString *address = static_cast<JavaString*>(mapping->address);
        JniLocalRef<jstring> string = address->getJavaString(env);
        env->SetObjectField(result, field, string.get());
      } else if (TYPE_EQUALS(mapping->type, kTypeByte)) {
        unsigned char *address = static_cast<unsigned char*>(mapping->address);
        env->SetByteField(result, field, *address);
      } else if (TYPE_EQUALS(mapping->type, kTypeChar)) {
        wchar_t *address = static_cast<wchar_t*>(mapping->address);
        env->SetCharField(result, field, *address);
      } else {
        // TODO throw
      }
    }
  }

  // Persist the current object address to the Java instance
  persist(env, result);
  return result.leak();
}

JniGlobalRef<jclass> ClassWrapper::getClass() const {
  return _clazz;
}

jmethodID ClassWrapper::getMethod(const char *method_name) const {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalStateException,
      "Cannot call getMethod without class info (forgot to merge?)");
    return NULL;
  }

  const std::string key(method_name);
  MethodMap::const_iterator mapFindIter = _methods.find(key);
  if (mapFindIter == _methods.end()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalArgumentException,
      "Method '%s' is not cached in class '%s'", method_name, getCanonicalName());
    return NULL;
  }

  return mapFindIter->second;
}

jfieldID ClassWrapper::getField(const char* field_name) const {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalStateException,
      "Cannot call getField without class info (forgot to merge?)");
    return NULL;
  }

  const std::string key(field_name);
  FieldMap::const_iterator mapFindIter = _fields.find(key);
  if (mapFindIter == _fields.end()) {
    JavaExceptionUtils::throwExceptionOfType(JavaThreadUtils::getEnvForCurrentThread(),
      kTypeIllegalArgumentException,
      "Field '%s' is not cached in class '%s'", field_name, getCanonicalName());
    return NULL;
  }

  return mapFindIter->second;
}

void ClassWrapper::setClass(JNIEnv *env) {
  _clazz.set(env->FindClass(getCanonicalName()));
  JavaExceptionUtils::checkException(env);
}

void ClassWrapper::cacheConstructor(JNIEnv *env) {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Attempt to call cacheMethod without having set class info");
    return;
  }

  std::string signature;
  JavaClassUtils::makeSignature(signature, kTypeVoid, NULL);
  _constructor = env->GetMethodID(_clazz.get(), "<init>", signature.c_str());
  // TODO: Check if ctor was found
}

void ClassWrapper::cacheMethod(JNIEnv *env, const char* method_name, const char* return_type, ...) {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Attempt to call cacheMethod without having set class info");
    return;
  }

  va_list arguments;
  va_start(arguments, return_type);
  std::string signature;
  JavaClassUtils::makeSignatureWithList(signature, return_type, arguments);
  va_end(arguments);

  jmethodID method = env->GetMethodID(_clazz.get(), method_name, signature.c_str());
  JavaExceptionUtils::checkException(env);
  if (method != NULL) {
    _methods[method_name] = method;
  }
}

void ClassWrapper::cacheField(JNIEnv *env, const char *field_name, const char *field_type) {
  if (!isInitialized()) {
    JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
      "Attempt to call cacheField without having set class info");
    return;
  }

  jfieldID field = env->GetFieldID(_clazz.get(), field_name, field_type);
  JavaExceptionUtils::checkException(env);
  if (field != NULL) {
    _fields[field_name] = field;
  }
}

void ClassWrapper::mapField(const char *field_name, const char *field_type, void *field_ptr) {
  FieldMapping *mapping = new FieldMapping;
  mapping->type = field_type;
  mapping->address = field_ptr;
  _field_mappings[field_name] = mapping;
}

FieldMapping* ClassWrapper::getFieldMapping(const char *key) const {
  std::string keyString(key);
  std::map<std::string, FieldMapping*>::const_iterator findMapIter = _field_mappings.find(keyString);
  return findMapIter != _field_mappings.end() ? findMapIter->second : NULL;
}

void ClassWrapper::addNativeMethod(const char *method_name, void *function, const char *return_type, ...) {
  JNINativeMethod nativeMethod;
  nativeMethod.name = const_cast<char*>(method_name);
  nativeMethod.fnPtr = function;

  va_list arguments;
  va_start(arguments, return_type);
  std::string signature;
  JavaClassUtils::makeSignatureWithList(signature, return_type, arguments);
  nativeMethod.signature = const_cast<char*>(strdup(signature.c_str()));
  va_end(arguments);

  _jni_methods.push_back(nativeMethod);
}

bool ClassWrapper::registerNativeMethods(JNIEnv *env) {
  if (_jni_methods.empty()) {
    return false;
  }

  if (!isInitialized()) {
    JavaExceptionUtils::throwRuntimeException(env, "Could not find cached class for %s", getCanonicalName());
    return false;
  }

  return (env->RegisterNatives(_clazz.get(), &_jni_methods[0], (jint)_jni_methods.size()) < 0);
}

} // namespace jni
} // namespace spotify
<|endoftext|>


<commit_before>//#include <pch.h>
#include "GameObject.h"

#include <Component/AABB.h>
#include <Component/Mesh.h>
#include <Component/Renderer.h>
#include <Component/Transform.h>
#include <Component/ObjectInput.h>
#include <GPU/Shader.h>

#include <Manager/DebugInfo.h>
#include <Manager/Manager.h>
#include <Manager/ColorPicking.h>

#ifdef PHYSICS_ENGINE
	#include <Component/Physics.h>
	#include <Manager/PhysicsManager.h>
#endif

GameObject::GameObject(const char *name)
{
	Init();
	if (name) {
		refID = new char[strlen(name)];
		refID = strcpy(refID, name);
	}
	renderer = new Renderer();
	transform = new Transform();
}

GameObject::GameObject(const GameObject &obj) {
	Init();
	refID = obj.refID;
	mesh	= obj.mesh;
	shader	= obj.shader;
	input	= obj.input;
	renderer = obj.renderer;
	transform = new Transform(*obj.transform);
	SetupAABB();

#ifdef PHYSICS_ENGINE
	if (obj.physics) {
		physics = new Physics(this);
		physics->body = Manager::Physics->GetCopyOf(obj.physics->body);
	}
#endif
}

GameObject::~GameObject() {
	Manager::Debug->Remove(this);
}

void GameObject::Init()
{
	aabb = nullptr;
	mesh = nullptr;
	shader = nullptr;
	renderer = nullptr;
	transform = nullptr;
	input = nullptr;

#ifdef PHYSICS_ENGINE
	physics = nullptr;
#endif

	colorID = Manager::ColorPick->GetColorUID();
	SetDebugView(true);
}

void GameObject::SetupAABB() {
	if (mesh) {
		aabb = new AABB(this);
		aabb->Update();
	}
}

void GameObject::Update() {
	#ifdef PHYSICS_ENGINE
	if (physics) {
		physics->Update();
	}
	#endif
}

bool GameObject::ColidesWith(GameObject *object) {
	if (!object->aabb)
		return false;
	return aabb->Overlaps(object->aabb);
}

void GameObject::Render() const {
	if (!mesh || !shader) return;
	glUniformMatrix4fv(shader->loc_model_matrix, 1, GL_FALSE, glm::value_ptr(transform->model));
	mesh->Render(shader);
}

void GameObject::Render(const Shader *shader) const {
	if (!mesh) return;
	glUniformMatrix4fv(shader->loc_model_matrix, 1, GL_FALSE, glm::value_ptr(transform->model));
	mesh->Render(shader);
}

void GameObject::RenderInstanced(const Shader *shader, unsigned int instances) const
{
	if (!mesh) return;
	glUniformMatrix4fv(shader->loc_model_matrix, 1, GL_FALSE, glm::value_ptr(transform->model));
	mesh->RenderInstanced(instances);
}

void GameObject::UseShader(Shader *shader) {
	this->shader = shader;
}

void GameObject::SetDebugView(bool value) {
	debugView = value;
	debugView ? Manager::Debug->Add(this) : Manager::Debug->Remove(this);
}

float GameObject::DistTo(GameObject *object)
{
	glm::vec3 d = transform->position - object->transform->position;
	float d2 = (d.x * d.x) + (d.y * d.y) + (d.z * d.z);
	return sqrt(d2);
}
<commit_msg>code re-factoring<commit_after>//#include <pch.h>
#include "GameObject.h"

#include <Component/AABB.h>
#include <Component/Mesh.h>
#include <Component/Renderer.h>
#include <Component/Transform.h>
#include <Component/ObjectInput.h>
#include <GPU/Shader.h>

#include <Manager/DebugInfo.h>
#include <Manager/Manager.h>
#include <Manager/ColorPicking.h>

#ifdef PHYSICS_ENGINE
	#include <Component/Physics.h>
	#include <Manager/PhysicsManager.h>
#endif

GameObject::GameObject(const char *name)
{
	Init();
	if (name) {
		refID = new char[strlen(name)];
		refID = strcpy(refID, name);
	}
	renderer = new Renderer();
	transform = new Transform();
}

GameObject::GameObject(const GameObject &obj) {
	Init();
	refID	= obj.refID;
	mesh	= obj.mesh;
	shader	= obj.shader;
	input	= obj.input;
	renderer = obj.renderer;
	transform = new Transform(*obj.transform);
	SetupAABB();

#ifdef PHYSICS_ENGINE
	if (obj.physics) {
		physics = new Physics(this);
		physics->body = Manager::Physics->GetCopyOf(obj.physics->body);
	}
#endif
}

GameObject::~GameObject() {
	Manager::Debug->Remove(this);
}

void GameObject::Init()
{
	aabb = nullptr;
	mesh = nullptr;
	shader = nullptr;
	renderer = nullptr;
	transform = nullptr;
	input = nullptr;

#ifdef PHYSICS_ENGINE
	physics = nullptr;
#endif

	colorID = Manager::ColorPick->GetColorUID();
	SetDebugView(true);
}

void GameObject::SetupAABB() {
	if (mesh) {
		aabb = new AABB(this);
		aabb->Update();
	}
}

void GameObject::Update() {
	#ifdef PHYSICS_ENGINE
	if (physics) {
		physics->Update();
	}
	#endif
}

bool GameObject::ColidesWith(GameObject *object) {
	if (!object->aabb)
		return false;
	return aabb->Overlaps(object->aabb);
}

void GameObject::Render() const {
	if (!mesh || !shader) return;
	glUniformMatrix4fv(shader->loc_model_matrix, 1, GL_FALSE, glm::value_ptr(transform->model));
	mesh->Render(shader);
}

void GameObject::Render(const Shader *shader) const {
	if (!mesh) return;
	glUniformMatrix4fv(shader->loc_model_matrix, 1, GL_FALSE, glm::value_ptr(transform->model));
	mesh->Render(shader);
}

void GameObject::RenderInstanced(const Shader *shader, unsigned int instances) const
{
	if (!mesh) return;
	glUniformMatrix4fv(shader->loc_model_matrix, 1, GL_FALSE, glm::value_ptr(transform->model));
	mesh->RenderInstanced(instances);
}

void GameObject::UseShader(Shader *shader) {
	this->shader = shader;
}

void GameObject::SetDebugView(bool value) {
	debugView = value;
	debugView ? Manager::Debug->Add(this) : Manager::Debug->Remove(this);
}

float GameObject::DistTo(GameObject *object)
{
	glm::vec3 d = transform->position - object->transform->position;
	float d2 = (d.x * d.x) + (d.y * d.y) + (d.z * d.z);
	return sqrt(d2);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <ncurses.h>
#include <unistd.h>
#include <string.h>
#include <string>
using namespace std;

int main()
{
	initscr();
	cbreak();
	printw("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
	printw("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
	printw("@@@                    THE BUNNY GAME                   @@@\n");
	printw("@@@ This is a simple program i wipped up, you could     @@@\n");
	printw("@@@ call it a game, i suppose. No its not a game.       @@@\n");
	printw("@@@ don't call it that, EVER. Oh well this not game     @@@\n");
	printw("@@@ has 5 err i mean 4 commands, its pretty self        @@@\n");
	printw("@@@ explanitory. just play it. If this program closes,  @@@\n");
	printw("@@@ you lose                                            @@@\n");
	printw("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
	printw("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");

	printw( "Press enter to continue ...");
	refresh();
	getch();
	clear();

	int loop = 0;
	while (loop < 1)
	{
		clear();
		printw( "     (\\__/)\n");
		printw( "     ( -.-)\n");
		printw( "    C(\")(\")\n");
		printw( "What do you want to do with it?\n");
		printw( " 1) Pet\n");
		printw( " 2) Poke\n");
		printw( " 3) Tell Joke\n");
		printw( " 4) Steal nose\n");
		refresh();
		char choice;
		choice = getch();

		if (choice  == '1')
		{
			clear();
			printw( "     (\\__/) Bunny like pets. Now let me sleep.\n");
			printw( "     ( -.-) That means leave.                 \n");
			printw( "    C(\")(\")                                   \n");
			printw( " umm, I think its best to do what it says.... \n\n");
			printw( "Press enter to continue ...");
			refresh();
			getch();

		}
		else if (choice == '2')
		{
			clear();
			printw("     (\\__/)\n");
			printw("     ( -.-)\n");
			printw("    C(\")(\")\n");
			clear();
			refresh();
			sleep(1);
			printw("     (\\__/)\n");
			printw("     ( 0.0)\n");
			printw("    C(\")(\")\n");
			printw(" WHO STOLE MY CARROTS???\n");
			printw(" I WILL DESTROY THE WOLRD\n");
			printw(" MWAHAHA\n");
			refresh();
			sleep(2);
			int count = 10;
			while (count >= 0)
			{
				clear();
				printw("%d\n", count);
				count -= 2;
				sleep(1);
				refresh();
			}
			refresh();
			printw("SOMEONE POKED THE BUNNY. THE WORLD IS OVER.\n");
			printw("Guess the bunny beat those terrorists to it...\n");
			getch();
		}
		else if (choice == '3')
		{
			clear();
			printw("     (\\__/)\n");
			printw("     ( -.-)\n");
			printw("    C(\")(\")\n");
			sleep(1);
			printw(" random joke  im to lazy to think of\n");
			sleep(3);
			clear();
			printw("     (\\__/) gasp\n");
			printw("     ( 0.0)\n");
			printw("    C(\")(\")\n");
			refresh();
			sleep(3);
			clear();
			printw("     (\\__/) Giggle, lol\n");
			printw("     ( *.*)\n");
			printw("    C(\")(\")\n");
			refresh();
			sleep(3);
			clear();
			printw(" You made the bunny laugh, awwww cute.\n");
			printw("Press enter to continue ...\n");
			getch();
			clear();
			refresh();
		}
		else if (choice == '4')
		{
			clear();
			printw("     (\\__/)");
			printw("     ( -.-)");
			printw("    C(\")(\")");
			printw(" hey bunny");
			refresh();
			sleep(3);
			clear();
			printw("     (\\__/) ?");
			printw("     ( o.o)");
			printw("    C(\")(\")");
			sleep(3);
			refresh();
			clear();
			printw("     (\\__/) ?");
			printw("     ( o o)");
			printw("    C(\")(\")");
			printw(" I got your nose");
			sleep(3);
			refresh();
			clear();
			printw("     (\\__/) AHHHHH!!");
			printw("     ( o o)");
			printw("    C(\")(\")");
			sleep(4);
			printw("You stole the bunny's nose. why, why did you do that??? \nWhy??");
			refresh();
			sleep(1);
			printw("Press enter\n");
			getch();
			clear();
		}
		else if (choice == '5')
		{
			clear();
			std::string name;
			std::string answer ("bunny");
			refresh();

			while (name != answer)
			{
				printw("name: ");
				refresh();
				//std::getline (std::cin,name);
				getline(std::cin >> name);
				printw("name   is %s \n",name);
				printw("answer is %s \n",answer);
				refresh();
				getch();
				if (name.compare(answer) != 0)
				{
					clear();
					printw("Congratulations! you have won the game!\n");
					printw("When i first made the game a song played at this part\n");
					printw("I did not include it for copyright reasons. Thanks for playing\n\n");
					printw("Press enter\n");
					getch();
					clear();
					loop = 2;
					endwin();
					return 0;
				}
				else
				{
					clear();
					printw("EXTERMANATE!!!, wait sorry WRONG USER\n");
					refresh();
					sleep(1);

				}
			}

		}
	}

	endwin();
	return 0;
}

<commit_msg>fixed bunnygame.cpp, should all work now<commit_after>#include <iostream>
#include <ncurses.h>
#include <unistd.h>
#include <string.h>
using namespace std;

int main()
{
	initscr();
	cbreak();
	printw("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
	printw("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
	printw("@@@                    THE BUNNY GAME                   @@@\n");
	printw("@@@ This is a simple program i wipped up, you could     @@@\n");
	printw("@@@ call it a game, i suppose. No its not a game.       @@@\n");
	printw("@@@ don't call it that, EVER. Oh well this not game     @@@\n");
	printw("@@@ has 5 err i mean 4 commands, its pretty self        @@@\n");
	printw("@@@ explanitory. just play it. If this program closes,  @@@\n");
	printw("@@@ you lose                                            @@@\n");
	printw("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
	printw("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");

	printw( "Press enter to continue ...");
	refresh();
	getch();
	clear();

	while (true)
	{
		clear();
		printw( "     (\\__/)\n");
		printw( "     ( -.-)\n");
		printw( "    C(\")(\")\n");
		printw( "What do you want to do with it?\n");
		printw( " 1) Pet\n");
		printw( " 2) Poke\n");
		printw( " 3) Tell Joke\n");
		printw( " 4) Steal nose\n");
		refresh();
		char choice;
		choice = getch();

		if (choice  == '1')
		{
			clear();
			printw( "     (\\__/) Bunny like pets. Now let me sleep.\n");
			printw( "     ( -.-) That means leave.                 \n");
			printw( "    C(\")(\")                                   \n");
			printw( " umm, I think its best to do what it says.... \n\n");
			printw( "Press enter to continue ...");
			refresh();
			getch();

		}
		else if (choice == '2')
		{
			clear();
			printw("     (\\__/)\n");
			printw("     ( -.-)\n");
			printw("    C(\")(\")\n");
			clear();
			refresh();
			sleep(1);
			printw("     (\\__/)\n");
			printw("     ( 0.0)\n");
			printw("    C(\")(\")\n");
			printw(" WHO STOLE MY CARROTS???\n");
			printw(" I WILL DESTROY THE WOLRD\n");
			printw(" MWAHAHA\n");
			refresh();
			sleep(2);
			int count = 10;
			while (count > 0)
			{
				clear();
				printw("%d\n", count);
				count -= 2;
				sleep(1);
				refresh();
			}
			clear();
			refresh();
			printw("SOMEONE POKED THE BUNNY. THE WORLD IS OVER.\n");
			printw("Guess the bunny beat those terrorists to it...\n");
			refresh();
			getch();
			break;
		}
		else if (choice == '3')
		{
			clear();
			printw("     (\\__/)\n");
			printw("     ( -.-)\n");
			printw("    C(\")(\")\n");
			refresh();
			sleep(1);
			printw("random joke  im to lazy to think of\n");
			refresh();
			sleep(2);
			clear();
			printw("     (\\__/) gasp\n");
			printw("     ( 0.0)\n");
			printw("    C(\")(\")\n");
			refresh();
			sleep(3);
			clear();
			printw("     (\\__/) Giggle, lol\n");
			printw("     ( *.*)\n");
			printw("    C(\")(\")\n");
			refresh();
			sleep(3);
			clear();
			printw(" You made the bunny laugh, awwww cute.\n");
			printw("Press enter to continue ...\n");
			getch();
			clear();
			refresh();
		}
		else if (choice == '4')
		{
			clear();
			printw("     (\\__/)\n");
			printw("     ( -.-)\n");
			printw("    C(\")(\")\n");
			printw(" hey bunny\n");
			refresh();
			sleep(1);
			clear();
			printw("     (\\__/) ?\n");
			printw("     ( o.o)\n");
			printw("    C(\")(\")\n");
			sleep(3);
			refresh();
			clear();
			printw("     (\\__/) ?\n");
			printw("     ( o o)\n");
			printw("    C(\")(\")\n");
			printw(" I got your nose\n");
			sleep(3);
			refresh();
			clear();
			printw("     (\\__/) AHHHHH!!\n");
			printw("     ( o o)\n");
			printw("    C(\")(\")\n");
			sleep(4);
			printw("You stole the bunny's nose. why, why did you do that??? \nWhy??\n");
			refresh();
			sleep(1);
			printw("Press enter\n");
			getch();
			clear();
			break;
		}
		else if (choice == '5')
		{
			clear();
			char name[21];
			char answer[7] = "bunny";
			refresh();

			while (name != answer)
			{
				printw("name: ");
				refresh();
				scanw("%20s", name);
				refresh();
				sleep(1);
				if (strcmp(name, "bunny")  == 0)
				{
					clear();
					printw("Congratulations! you have won the game!\n");
					printw("When i first made the game a song played at this part\n");
					printw("I did not include it for copyright reasons. Thanks for playing\n\n");
					printw("Press enter\n");
					getch();
					clear();
					endwin();
					return 0;
				}
				else
				{
					clear();
					printw("EXTERMANATE!!!, wait sorry WRONG USER\n");
					refresh();
					sleep(1);

				}

			}

		}
	}

	endwin();
	return 0;
}

<|endoftext|>