<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * SscReader.tcc
 *
 *  Created on: Nov 1, 2018
 *      Author: Jason Wang
 */

#ifndef ADIOS2_ENGINE_SSCREADER_TCC_
#define ADIOS2_ENGINE_SSCREADER_TCC_

#include "SscReader.h"
#include "adios2/helper/adiosMemory.h"
#include <iostream>

namespace adios2
{
namespace core
{
namespace engine
{

template <class T>
inline void SscReader::GetSyncCommon(Variable<T> &variable, T *data)
{
    TAU_SCOPED_TIMER_FUNC();
    GetDeferredCommon(variable, data);
    PerformGets();
}

template <class T>
void SscReader::GetDeferredCommon(Variable<T> &variable, T *data)
{
    TAU_SCOPED_TIMER_FUNC();
    if (m_CurrentStep == 0)
    {
        m_LocalReadPattern.emplace_back();
        auto &b = m_LocalReadPattern.back();
        b.name = variable.m_Name;
        b.count = variable.m_Count;
        b.start = variable.m_Start;
        b.shape = variable.m_Shape;
        b.type = helper::GetType<T>();

        for (const auto &d : b.count)
        {
            if (d == 0)
            {
                throw(std::runtime_error(
                    "SetSelection count dimensions cannot be 0"));
            }
        }

        m_LocalReadPatternJson["Variables"].emplace_back();
        auto &jref = m_LocalReadPatternJson["Variables"].back();
        jref["Name"] = variable.m_Name;
        jref["Type"] = helper::GetType<T>();
        jref["Start"] = variable.m_Start;
        jref["Count"] = variable.m_Count;
        jref["Shape"] = variable.m_Shape;
        jref["BufferStart"] = 0;
        jref["BufferCount"] = 0;

        ssc::JsonToBlockVecVec(m_GlobalWritePatternJson, m_GlobalWritePattern);
        ssc::CalculateOverlap(m_GlobalWritePattern, m_LocalReadPattern);
        m_AllReceivingWriterRanks = ssc::AllOverlapRanks(m_GlobalWritePattern);
        CalculatePosition(m_GlobalWritePattern, m_AllReceivingWriterRanks);
        size_t totalDataSize = 0;
        for (auto i : m_AllReceivingWriterRanks)
        {
            totalDataSize += i.second.second;
        }
        m_Buffer.resize(totalDataSize);
        std::vector<MPI_Request> requests;
        for (const auto &i : m_AllReceivingWriterRanks)
        {
            requests.emplace_back();
            MPI_Rget(m_Buffer.data() + i.second.first, i.second.second,
                     MPI_CHAR, i.first, 0, i.second.second, MPI_CHAR, m_MpiWin,
                     &requests.back());
        }
        MPI_Status statuses[requests.size()];
        MPI_Waitall(requests.size(), requests.data(), statuses);
    }

    for (const auto &i : m_AllReceivingWriterRanks)
    {
        const auto &v = m_GlobalWritePattern[i.first];
        for (const auto &b : v)
        {
            if (b.name == variable.m_Name)
            {
                if (b.start.size() == 1 and b.count.size() == 1 and
                    b.shape.size() == 1 and b.start[0] == 0 and
                    b.count[0] == 1 and b.shape[0] == 1)
                {
                    std::memcpy(data, m_Buffer.data() + b.bufferStart,
                                sizeof(T));
                }
                else
                {
                    helper::NdCopy<T>(
                        m_Buffer.data() + b.bufferStart, b.start, b.count, true,
                        true, reinterpret_cast<char *>(data), variable.m_Start,
                        variable.m_Count, true, true);
                }
            }
        }
    }
}

template <typename T>
std::map<size_t, std::vector<typename Variable<T>::Info>>
SscReader::AllStepsBlocksInfoCommon(const Variable<T> &variable) const
{
    TAU_SCOPED_TIMER_FUNC();
    std::map<size_t, std::vector<typename Variable<T>::Info>> m;
    return m;
}

template <typename T>
std::vector<typename Variable<T>::Info>
SscReader::BlocksInfoCommon(const Variable<T> &variable,
                            const size_t step) const
{
    TAU_SCOPED_TIMER_FUNC();
    std::vector<typename Variable<T>::Info> ret;

    for (const auto &r : m_GlobalWritePattern)
    {
        for (auto &v : r)
        {
            if (v.name != variable.m_Name)
            {
                continue;
            }
            typename Variable<T>::Info b;
            b.Start = v.start;
            b.Count = v.count;
            b.Shape = v.shape;
            b.IsValue = false;
            if (v.shape.size() == 1)
            {
                if (v.shape[0] == 1)
                {
                    b.IsValue = true;
                }
            }
            ret.push_back(b);
        }
    }
    return ret;
}

} // end namespace engine
} // end namespace core
} // end namespace adios2

#endif // ADIOS2_ENGINE_SSCREADER_TCC_
<commit_msg>removed specific handling for single value<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * SscReader.tcc
 *
 *  Created on: Nov 1, 2018
 *      Author: Jason Wang
 */

#ifndef ADIOS2_ENGINE_SSCREADER_TCC_
#define ADIOS2_ENGINE_SSCREADER_TCC_

#include "SscReader.h"
#include "adios2/helper/adiosMemory.h"
#include <iostream>

namespace adios2
{
namespace core
{
namespace engine
{

template <class T>
inline void SscReader::GetSyncCommon(Variable<T> &variable, T *data)
{
    TAU_SCOPED_TIMER_FUNC();
    GetDeferredCommon(variable, data);
    PerformGets();
}

template <class T>
void SscReader::GetDeferredCommon(Variable<T> &variable, T *data)
{
    TAU_SCOPED_TIMER_FUNC();
    if (m_CurrentStep == 0)
    {
        m_LocalReadPattern.emplace_back();
        auto &b = m_LocalReadPattern.back();
        b.name = variable.m_Name;
        b.count = variable.m_Count;
        b.start = variable.m_Start;
        b.shape = variable.m_Shape;
        b.type = helper::GetType<T>();

        for (const auto &d : b.count)
        {
            if (d == 0)
            {
                throw(std::runtime_error(
                    "SetSelection count dimensions cannot be 0"));
            }
        }

        m_LocalReadPatternJson["Variables"].emplace_back();
        auto &jref = m_LocalReadPatternJson["Variables"].back();
        jref["Name"] = variable.m_Name;
        jref["Type"] = helper::GetType<T>();
        jref["Start"] = variable.m_Start;
        jref["Count"] = variable.m_Count;
        jref["Shape"] = variable.m_Shape;
        jref["BufferStart"] = 0;
        jref["BufferCount"] = 0;

        ssc::JsonToBlockVecVec(m_GlobalWritePatternJson, m_GlobalWritePattern);
        ssc::CalculateOverlap(m_GlobalWritePattern, m_LocalReadPattern);
        m_AllReceivingWriterRanks = ssc::AllOverlapRanks(m_GlobalWritePattern);
        CalculatePosition(m_GlobalWritePattern, m_AllReceivingWriterRanks);
        size_t totalDataSize = 0;
        for (auto i : m_AllReceivingWriterRanks)
        {
            totalDataSize += i.second.second;
        }
        m_Buffer.resize(totalDataSize);
        std::vector<MPI_Request> requests;
        for (const auto &i : m_AllReceivingWriterRanks)
        {
            requests.emplace_back();
            MPI_Rget(m_Buffer.data() + i.second.first, i.second.second,
                     MPI_CHAR, i.first, 0, i.second.second, MPI_CHAR, m_MpiWin,
                     &requests.back());
        }
        MPI_Status statuses[requests.size()];
        MPI_Waitall(requests.size(), requests.data(), statuses);
    }

    for (const auto &i : m_AllReceivingWriterRanks)
    {
        const auto &v = m_GlobalWritePattern[i.first];
        for (const auto &b : v)
        {
            if (b.name == variable.m_Name)
            {
                helper::NdCopy<T>(
                    m_Buffer.data() + b.bufferStart, b.start, b.count, true,
                    true, reinterpret_cast<char *>(data), variable.m_Start,
                    variable.m_Count, true, true);
            }
        }
    }
}

template <typename T>
std::map<size_t, std::vector<typename Variable<T>::Info>>
SscReader::AllStepsBlocksInfoCommon(const Variable<T> &variable) const
{
    TAU_SCOPED_TIMER_FUNC();
    std::map<size_t, std::vector<typename Variable<T>::Info>> m;
    return m;
}

template <typename T>
std::vector<typename Variable<T>::Info>
SscReader::BlocksInfoCommon(const Variable<T> &variable,
                            const size_t step) const
{
    TAU_SCOPED_TIMER_FUNC();
    std::vector<typename Variable<T>::Info> ret;

    for (const auto &r : m_GlobalWritePattern)
    {
        for (auto &v : r)
        {
            if (v.name != variable.m_Name)
            {
                continue;
            }
            typename Variable<T>::Info b;
            b.Start = v.start;
            b.Count = v.count;
            b.Shape = v.shape;
            b.IsValue = false;
            if (v.shape.size() == 1)
            {
                if (v.shape[0] == 1)
                {
                    b.IsValue = true;
                }
            }
            ret.push_back(b);
        }
    }
    return ret;
}

} // end namespace engine
} // end namespace core
} // end namespace adios2

#endif // ADIOS2_ENGINE_SSCREADER_TCC_
<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * SscWriter.cpp
 *
 *  Created on: Nov 1, 2018
 *      Author: Jason Wang
 */

#include "SscWriter.tcc"
#include "adios2/helper/adiosComm.h"
#include "adios2/helper/adiosCommMPI.h"
#include "adios2/helper/adiosString.h"

namespace adios2
{
namespace core
{
namespace engine
{

SscWriter::SscWriter(IO &io, const std::string &name, const Mode mode,
                     helper::Comm comm)
: Engine("SscWriter", io, name, mode, std::move(comm))
{
    TAU_SCOPED_TIMER_FUNC();

    helper::GetParameter(m_IO.m_Parameters, "MpiMode", m_MpiMode);
    helper::GetParameter(m_IO.m_Parameters, "Verbose", m_Verbosity);
    helper::GetParameter(m_IO.m_Parameters, "MaxFilenameLength",
                         m_MaxFilenameLength);
    helper::GetParameter(m_IO.m_Parameters, "RendezvousAppCount",
                         m_RendezvousAppCount);
    helper::GetParameter(m_IO.m_Parameters, "MaxStreamsPerApp",
                         m_MaxStreamsPerApp);
    helper::GetParameter(m_IO.m_Parameters, "OpenTimeoutSecs",
                         m_OpenTimeoutSecs);

    m_Buffer.resize(1);

    SyncMpiPattern();
    m_WriterRank = m_Comm.Rank();
    m_WriterSize = m_Comm.Size();
    MPI_Comm_rank(m_StreamComm, &m_StreamRank);
    MPI_Comm_size(m_StreamComm, &m_StreamSize);

    m_GlobalWritePattern.resize(m_StreamSize);
    m_GlobalReadPattern.resize(m_StreamSize);
}

StepStatus SscWriter::BeginStep(StepMode mode, const float timeoutSeconds)
{
    TAU_SCOPED_TIMER_FUNC();

    MpiWait();

    if (m_InitialStep)
    {
        m_InitialStep = false;
    }
    else
    {
        ++m_CurrentStep;
    }

    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::BeginStep, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << ", Step "
                  << m_CurrentStep << std::endl;
    }

    return StepStatus::OK;
}

size_t SscWriter::CurrentStep() const
{
    TAU_SCOPED_TIMER_FUNC();
    return m_CurrentStep;
}

void SscWriter::PerformPuts() { TAU_SCOPED_TIMER_FUNC(); }

void SscWriter::PutOneSidedPostPush()
{
    TAU_SCOPED_TIMER_FUNC();
    MPI_Win_start(m_MpiAllReadersGroup, 0, m_MpiWin);
    for (const auto &i : m_AllSendingReaderRanks)
    {
        MPI_Put(m_Buffer.data(), m_Buffer.size(), MPI_CHAR, i.first,
                i.second.first, m_Buffer.size(), MPI_CHAR, m_MpiWin);
    }
    MPI_Win_complete(m_MpiWin);
}

void SscWriter::PutOneSidedFencePush()
{
    TAU_SCOPED_TIMER_FUNC();
    MPI_Win_fence(0, m_MpiWin);
    for (const auto &i : m_AllSendingReaderRanks)
    {
        MPI_Put(m_Buffer.data(), m_Buffer.size(), MPI_CHAR, i.first,
                i.second.first, m_Buffer.size(), MPI_CHAR, m_MpiWin);
    }
    MPI_Win_fence(0, m_MpiWin);
}

void SscWriter::PutOneSidedPostPull()
{
    TAU_SCOPED_TIMER_FUNC();
    MPI_Win_post(m_MpiAllReadersGroup, 0, m_MpiWin);
    MPI_Win_wait(m_MpiWin);
}

void SscWriter::PutOneSidedFencePull()
{
    TAU_SCOPED_TIMER_FUNC();
    MPI_Win_fence(0, m_MpiWin);
    MPI_Win_fence(0, m_MpiWin);
}

void SscWriter::PutTwoSided()
{
    TAU_SCOPED_TIMER_FUNC();
    for (const auto &i : m_AllSendingReaderRanks)
    {
        m_MpiRequests.emplace_back();
        MPI_Isend(m_Buffer.data(), m_Buffer.size(), MPI_CHAR, i.first, 0,
                  m_StreamComm, &m_MpiRequests.back());
    }
    m_NeedWait = true;
}

void SscWriter::EndStep()
{
    TAU_SCOPED_TIMER_FUNC();
    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::EndStep, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << ", Step "
                  << m_CurrentStep << std::endl;
    }

    if (m_CurrentStep == 0)
    {
        SyncWritePattern();
        MPI_Win_create(m_Buffer.data(), m_Buffer.size(), 1, MPI_INFO_NULL,
                       m_StreamComm, &m_MpiWin);
        PutOneSidedPostPull();
        MPI_Win_free(&m_MpiWin);
        SyncReadPattern();
        MPI_Win_create(m_Buffer.data(), m_Buffer.size(), 1, MPI_INFO_NULL,
                       m_StreamComm, &m_MpiWin);
    }
    else
    {
        if (m_MpiMode == "twosided")
        {
            PutTwoSided();
        }
        else if (m_MpiMode == "onesidedfencepush")
        {
            PutOneSidedFencePush();
        }
        else if (m_MpiMode == "onesidedpostpush")
        {
            PutOneSidedPostPush();
        }
        else if (m_MpiMode == "onesidedfencepull")
        {
            PutOneSidedFencePull();
        }
        else if (m_MpiMode == "onesidedpostpull")
        {
            PutOneSidedPostPull();
        }
    }
}

void SscWriter::Flush(const int transportIndex) { TAU_SCOPED_TIMER_FUNC(); }

// PRIVATE

void SscWriter::MpiWait()
{
    if (m_NeedWait)
    {
        if (m_MpiMode == "twosided")
        {
            MPI_Status statuses[m_MpiRequests.size()];
            MPI_Waitall(m_MpiRequests.size(), m_MpiRequests.data(), statuses);
            m_MpiRequests.clear();
        }
        else if (m_MpiMode == "onesidedfencepush")
        {
        }
        else if (m_MpiMode == "onesidedpostpush")
        {
        }
        else if (m_MpiMode == "onesidedfencepull")
        {
        }
        else if (m_MpiMode == "onesidedpostpull")
        {
        }
        m_NeedWait = false;
    }
}

void SscWriter::SyncMpiPattern()
{
    TAU_SCOPED_TIMER_FUNC();

    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::SyncMpiPattern, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << std::endl;
    }

    m_MpiHandshake.Handshake(m_Name, 'w', m_OpenTimeoutSecs, m_MaxStreamsPerApp,
                             m_MaxFilenameLength, m_RendezvousAppCount,
                             CommAsMPI(m_Comm));

    std::vector<int> allStreamRanks;
    std::vector<int> allReaderRanks;

    for (const auto &app : m_MpiHandshake.GetWriterMap(m_Name))
    {
        for (int rank : app.second)
        {
            allStreamRanks.push_back(rank);
        }
    }

    for (const auto &app : m_MpiHandshake.GetReaderMap(m_Name))
    {
        for (int rank : app.second)
        {
            allStreamRanks.push_back(rank);
            allReaderRanks.push_back(rank);
        }
    }
    MPI_Group worldGroup;
    MPI_Group allReadersGroup;
    MPI_Comm_group(MPI_COMM_WORLD, &worldGroup);
    MPI_Group_incl(worldGroup, allReaderRanks.size(), allReaderRanks.data(),
                   &m_MpiAllReadersGroup);

    MPI_Comm_group(MPI_COMM_WORLD, &worldGroup);
    std::sort(allStreamRanks.begin(), allStreamRanks.end());
    MPI_Group allWorkersGroup;
    MPI_Group_incl(worldGroup, allStreamRanks.size(), allStreamRanks.data(),
                   &allWorkersGroup);
    MPI_Comm_create_group(MPI_COMM_WORLD, allWorkersGroup, 0, &m_StreamComm);
}

void SscWriter::SyncWritePattern()
{
    TAU_SCOPED_TIMER_FUNC();
    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::SyncWritePattern, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << std::endl;
    }

    nlohmann::json localRankMetaJ;

    ssc::BlockVecToJson(m_GlobalWritePattern[m_StreamRank], localRankMetaJ);

    if (m_WriterRank == 0)
    {
        ssc::AttributeMapToJson(m_IO, localRankMetaJ);
    }

    std::string localStr = localRankMetaJ.dump();

    // aggregate global write pattern
    size_t localSize = localStr.size();
    size_t maxLocalSize;
    MPI_Allreduce(&localSize, &maxLocalSize, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX,
                  m_StreamComm);
    std::vector<char> localVec(maxLocalSize, '\0');
    std::memcpy(localVec.data(), localStr.data(), localStr.size());
    std::vector<char> globalVec(maxLocalSize * m_StreamSize, '\0');
    MPI_Allgather(localVec.data(), maxLocalSize, MPI_CHAR, globalVec.data(),
                  maxLocalSize, MPI_CHAR, m_StreamComm);

    // deserialize global metadata Json
    nlohmann::json globalJson;
    ssc::LocalJsonToGlobalJson(globalVec, maxLocalSize, m_StreamSize,
                               globalJson);

    // deserialize variables metadata
    ssc::JsonToBlockVecVec(globalJson, m_GlobalWritePattern);
}

void SscWriter::SyncReadPattern()
{
    TAU_SCOPED_TIMER_FUNC();
    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::SyncReadPattern, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << std::endl;
    }

    size_t localSize = 0;
    size_t maxLocalSize;
    MPI_Allreduce(&localSize, &maxLocalSize, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX,
                  m_StreamComm);
    std::vector<char> localVec(maxLocalSize, '\0');
    std::vector<char> globalVec(maxLocalSize * m_StreamSize);
    MPI_Allgather(localVec.data(), maxLocalSize, MPI_CHAR, globalVec.data(),
                  maxLocalSize, MPI_CHAR, m_StreamComm);

    // deserialize global metadata Json
    nlohmann::json globalJson;
    try
    {
        for (size_t i = 0; i < m_StreamSize; ++i)
        {
            if (globalVec[i * maxLocalSize] == '\0')
            {
                globalJson[i] = nullptr;
            }
            else
            {
                globalJson[i] = nlohmann::json::parse(
                    globalVec.begin() + i * maxLocalSize,
                    globalVec.begin() + (i + 1) * maxLocalSize);
            }
        }
    }
    catch (std::exception &e)
    {
        throw(std::runtime_error(
            std::string("corrupted global read pattern metadata, ") +
            std::string(e.what())));
    }

    ssc::JsonToBlockVecVec(globalJson, m_GlobalReadPattern);
    m_AllSendingReaderRanks = ssc::CalculateOverlap(
        m_GlobalReadPattern, m_GlobalWritePattern[m_StreamRank]);
    CalculatePosition(m_GlobalWritePattern, m_GlobalReadPattern, m_WriterRank,
                      m_AllSendingReaderRanks);

    if (m_Verbosity >= 10)
    {
        ssc::PrintBlockVecVec(m_GlobalWritePattern, "Global Write Pattern");
        ssc::PrintBlockVec(m_GlobalWritePattern[m_WriterRank],
                           "Local Write Pattern");
    }
}

void SscWriter::CalculatePosition(ssc::BlockVecVec &writerVecVec,
                                  ssc::BlockVecVec &readerVecVec,
                                  const int writerRank,
                                  ssc::RankPosMap &allOverlapRanks)
{
    TAU_SCOPED_TIMER_FUNC();
    for (auto &overlapRank : allOverlapRanks)
    {
        auto &readerRankMap = readerVecVec[overlapRank.first];
        auto currentReaderOverlapWriterRanks =
            CalculateOverlap(writerVecVec, readerRankMap);
        size_t bufferPosition = 0;
        for (size_t rank = 0; rank < writerVecVec.size(); ++rank)
        {
            bool hasOverlap = false;
            for (const auto r : currentReaderOverlapWriterRanks)
            {
                if (r.first == rank)
                {
                    hasOverlap = true;
                    break;
                }
            }
            if (hasOverlap)
            {
                currentReaderOverlapWriterRanks[rank].first = bufferPosition;
                auto &bv = writerVecVec[rank];
                size_t currentRankTotalSize = TotalDataSize(bv) + 1;
                currentReaderOverlapWriterRanks[rank].second =
                    currentRankTotalSize;
                bufferPosition += currentRankTotalSize;
            }
        }
        allOverlapRanks[overlapRank.first] =
            currentReaderOverlapWriterRanks[writerRank];
    }
}

#define declare_type(T)                                                        \
    void SscWriter::DoPutSync(Variable<T> &variable, const T *data)            \
    {                                                                          \
        PutDeferredCommon(variable, data);                                     \
        PerformPuts();                                                         \
    }                                                                          \
    void SscWriter::DoPutDeferred(Variable<T> &variable, const T *data)        \
    {                                                                          \
        PutDeferredCommon(variable, data);                                     \
    }
ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type

void SscWriter::DoClose(const int transportIndex)
{
    TAU_SCOPED_TIMER_FUNC();

    MpiWait();

    m_Buffer[0] = 1;

    if (m_MpiMode == "twosided")
    {
        std::vector<MPI_Request> requests;
        for (const auto &i : m_AllSendingReaderRanks)
        {
            requests.emplace_back();
            MPI_Isend(m_Buffer.data(), 1, MPI_CHAR, i.first, 0, m_StreamComm,
                      &requests.back());
        }
        MPI_Status statuses[requests.size()];
        MPI_Waitall(requests.size(), requests.data(), statuses);
    }
    else if (m_MpiMode == "onesidedfencepush")
    {
        MPI_Win_fence(0, m_MpiWin);
        for (const auto &i : m_AllSendingReaderRanks)
        {
            MPI_Put(m_Buffer.data(), 1, MPI_CHAR, i.first, 0, 1, MPI_CHAR,
                    m_MpiWin);
        }
        MPI_Win_fence(0, m_MpiWin);
    }
    else if (m_MpiMode == "onesidedpostpush")
    {
        MPI_Win_start(m_MpiAllReadersGroup, 0, m_MpiWin);
        for (const auto &i : m_AllSendingReaderRanks)
        {
            MPI_Put(m_Buffer.data(), 1, MPI_CHAR, i.first, 0, 1, MPI_CHAR,
                    m_MpiWin);
        }
        MPI_Win_complete(m_MpiWin);
    }
    else if (m_MpiMode == "onesidedfencepull")
    {
        MPI_Win_fence(0, m_MpiWin);
        MPI_Win_fence(0, m_MpiWin);
    }
    else if (m_MpiMode == "onesidedpostpull")
    {
        MPI_Win_post(m_MpiAllReadersGroup, 0, m_MpiWin);
        MPI_Win_wait(m_MpiWin);
    }

    MPI_Win_free(&m_MpiWin);
}

} // end namespace engine
} // end namespace core
} // end namespace adios2
<commit_msg>moved MPI_Win_fence from EndStep to BeginStep<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * SscWriter.cpp
 *
 *  Created on: Nov 1, 2018
 *      Author: Jason Wang
 */

#include "SscWriter.tcc"
#include "adios2/helper/adiosComm.h"
#include "adios2/helper/adiosCommMPI.h"
#include "adios2/helper/adiosString.h"

namespace adios2
{
namespace core
{
namespace engine
{

SscWriter::SscWriter(IO &io, const std::string &name, const Mode mode,
                     helper::Comm comm)
: Engine("SscWriter", io, name, mode, std::move(comm))
{
    TAU_SCOPED_TIMER_FUNC();

    helper::GetParameter(m_IO.m_Parameters, "MpiMode", m_MpiMode);
    helper::GetParameter(m_IO.m_Parameters, "Verbose", m_Verbosity);
    helper::GetParameter(m_IO.m_Parameters, "MaxFilenameLength",
                         m_MaxFilenameLength);
    helper::GetParameter(m_IO.m_Parameters, "RendezvousAppCount",
                         m_RendezvousAppCount);
    helper::GetParameter(m_IO.m_Parameters, "MaxStreamsPerApp",
                         m_MaxStreamsPerApp);
    helper::GetParameter(m_IO.m_Parameters, "OpenTimeoutSecs",
                         m_OpenTimeoutSecs);

    m_Buffer.resize(1);

    SyncMpiPattern();
    m_WriterRank = m_Comm.Rank();
    m_WriterSize = m_Comm.Size();
    MPI_Comm_rank(m_StreamComm, &m_StreamRank);
    MPI_Comm_size(m_StreamComm, &m_StreamSize);

    m_GlobalWritePattern.resize(m_StreamSize);
    m_GlobalReadPattern.resize(m_StreamSize);
}

StepStatus SscWriter::BeginStep(StepMode mode, const float timeoutSeconds)
{
    TAU_SCOPED_TIMER_FUNC();

    MpiWait();

    if (m_InitialStep)
    {
        m_InitialStep = false;
    }
    else
    {
        ++m_CurrentStep;
    }

    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::BeginStep, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << ", Step "
                  << m_CurrentStep << std::endl;
    }

    return StepStatus::OK;
}

size_t SscWriter::CurrentStep() const
{
    TAU_SCOPED_TIMER_FUNC();
    return m_CurrentStep;
}

void SscWriter::PerformPuts() { TAU_SCOPED_TIMER_FUNC(); }

void SscWriter::PutOneSidedPostPush()
{
    TAU_SCOPED_TIMER_FUNC();
    MPI_Win_start(m_MpiAllReadersGroup, 0, m_MpiWin);
    for (const auto &i : m_AllSendingReaderRanks)
    {
        MPI_Put(m_Buffer.data(), m_Buffer.size(), MPI_CHAR, i.first,
                i.second.first, m_Buffer.size(), MPI_CHAR, m_MpiWin);
    }
    MPI_Win_complete(m_MpiWin);
}

void SscWriter::PutOneSidedFencePush()
{
    TAU_SCOPED_TIMER_FUNC();
    MPI_Win_fence(0, m_MpiWin);
    for (const auto &i : m_AllSendingReaderRanks)
    {
        MPI_Put(m_Buffer.data(), m_Buffer.size(), MPI_CHAR, i.first,
                i.second.first, m_Buffer.size(), MPI_CHAR, m_MpiWin);
    }
    m_NeedWait = true;
}

void SscWriter::PutOneSidedPostPull()
{
    TAU_SCOPED_TIMER_FUNC();
    MPI_Win_post(m_MpiAllReadersGroup, 0, m_MpiWin);
    MPI_Win_wait(m_MpiWin);
}

void SscWriter::PutOneSidedFencePull()
{
    TAU_SCOPED_TIMER_FUNC();
    MPI_Win_fence(0, m_MpiWin);
    m_NeedWait = true;
}

void SscWriter::PutTwoSided()
{
    TAU_SCOPED_TIMER_FUNC();
    for (const auto &i : m_AllSendingReaderRanks)
    {
        m_MpiRequests.emplace_back();
        MPI_Isend(m_Buffer.data(), m_Buffer.size(), MPI_CHAR, i.first, 0,
                  m_StreamComm, &m_MpiRequests.back());
    }
    m_NeedWait = true;
}

void SscWriter::EndStep()
{
    TAU_SCOPED_TIMER_FUNC();
    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::EndStep, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << ", Step "
                  << m_CurrentStep << std::endl;
    }

    if (m_CurrentStep == 0)
    {
        SyncWritePattern();
        MPI_Win_create(m_Buffer.data(), m_Buffer.size(), 1, MPI_INFO_NULL,
                       m_StreamComm, &m_MpiWin);
        PutOneSidedPostPull();
        MPI_Win_free(&m_MpiWin);
        SyncReadPattern();
        MPI_Win_create(m_Buffer.data(), m_Buffer.size(), 1, MPI_INFO_NULL,
                       m_StreamComm, &m_MpiWin);
    }
    else
    {
        if (m_MpiMode == "twosided")
        {
            PutTwoSided();
        }
        else if (m_MpiMode == "onesidedfencepush")
        {
            PutOneSidedFencePush();
        }
        else if (m_MpiMode == "onesidedpostpush")
        {
            PutOneSidedPostPush();
        }
        else if (m_MpiMode == "onesidedfencepull")
        {
            PutOneSidedFencePull();
        }
        else if (m_MpiMode == "onesidedpostpull")
        {
            PutOneSidedPostPull();
        }
    }
}

void SscWriter::Flush(const int transportIndex) { TAU_SCOPED_TIMER_FUNC(); }

// PRIVATE

void SscWriter::MpiWait()
{
    if (m_NeedWait)
    {
        if (m_MpiMode == "twosided")
        {
            MPI_Status statuses[m_MpiRequests.size()];
            MPI_Waitall(m_MpiRequests.size(), m_MpiRequests.data(), statuses);
            m_MpiRequests.clear();
        }
        else if (m_MpiMode == "onesidedfencepush")
        {
            MPI_Win_fence(0, m_MpiWin);
        }
        else if (m_MpiMode == "onesidedpostpush")
        {
        }
        else if (m_MpiMode == "onesidedfencepull")
        {
            MPI_Win_fence(0, m_MpiWin);
        }
        else if (m_MpiMode == "onesidedpostpull")
        {
        }
        m_NeedWait = false;
    }
}

void SscWriter::SyncMpiPattern()
{
    TAU_SCOPED_TIMER_FUNC();

    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::SyncMpiPattern, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << std::endl;
    }

    m_MpiHandshake.Handshake(m_Name, 'w', m_OpenTimeoutSecs, m_MaxStreamsPerApp,
                             m_MaxFilenameLength, m_RendezvousAppCount,
                             CommAsMPI(m_Comm));

    std::vector<int> allStreamRanks;
    std::vector<int> allReaderRanks;

    for (const auto &app : m_MpiHandshake.GetWriterMap(m_Name))
    {
        for (int rank : app.second)
        {
            allStreamRanks.push_back(rank);
        }
    }

    for (const auto &app : m_MpiHandshake.GetReaderMap(m_Name))
    {
        for (int rank : app.second)
        {
            allStreamRanks.push_back(rank);
            allReaderRanks.push_back(rank);
        }
    }
    MPI_Group worldGroup;
    MPI_Group allReadersGroup;
    MPI_Comm_group(MPI_COMM_WORLD, &worldGroup);
    MPI_Group_incl(worldGroup, allReaderRanks.size(), allReaderRanks.data(),
                   &m_MpiAllReadersGroup);

    MPI_Comm_group(MPI_COMM_WORLD, &worldGroup);
    std::sort(allStreamRanks.begin(), allStreamRanks.end());
    MPI_Group allWorkersGroup;
    MPI_Group_incl(worldGroup, allStreamRanks.size(), allStreamRanks.data(),
                   &allWorkersGroup);
    MPI_Comm_create_group(MPI_COMM_WORLD, allWorkersGroup, 0, &m_StreamComm);
}

void SscWriter::SyncWritePattern()
{
    TAU_SCOPED_TIMER_FUNC();
    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::SyncWritePattern, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << std::endl;
    }

    nlohmann::json localRankMetaJ;

    ssc::BlockVecToJson(m_GlobalWritePattern[m_StreamRank], localRankMetaJ);

    if (m_WriterRank == 0)
    {
        ssc::AttributeMapToJson(m_IO, localRankMetaJ);
    }

    std::string localStr = localRankMetaJ.dump();

    // aggregate global write pattern
    size_t localSize = localStr.size();
    size_t maxLocalSize;
    MPI_Allreduce(&localSize, &maxLocalSize, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX,
                  m_StreamComm);
    std::vector<char> localVec(maxLocalSize, '\0');
    std::memcpy(localVec.data(), localStr.data(), localStr.size());
    std::vector<char> globalVec(maxLocalSize * m_StreamSize, '\0');
    MPI_Allgather(localVec.data(), maxLocalSize, MPI_CHAR, globalVec.data(),
                  maxLocalSize, MPI_CHAR, m_StreamComm);

    // deserialize global metadata Json
    nlohmann::json globalJson;
    ssc::LocalJsonToGlobalJson(globalVec, maxLocalSize, m_StreamSize,
                               globalJson);

    // deserialize variables metadata
    ssc::JsonToBlockVecVec(globalJson, m_GlobalWritePattern);
}

void SscWriter::SyncReadPattern()
{
    TAU_SCOPED_TIMER_FUNC();
    if (m_Verbosity >= 5)
    {
        std::cout << "SscWriter::SyncReadPattern, World Rank " << m_StreamRank
                  << ", Writer Rank " << m_WriterRank << std::endl;
    }

    size_t localSize = 0;
    size_t maxLocalSize;
    MPI_Allreduce(&localSize, &maxLocalSize, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX,
                  m_StreamComm);
    std::vector<char> localVec(maxLocalSize, '\0');
    std::vector<char> globalVec(maxLocalSize * m_StreamSize);
    MPI_Allgather(localVec.data(), maxLocalSize, MPI_CHAR, globalVec.data(),
                  maxLocalSize, MPI_CHAR, m_StreamComm);

    // deserialize global metadata Json
    nlohmann::json globalJson;
    try
    {
        for (size_t i = 0; i < m_StreamSize; ++i)
        {
            if (globalVec[i * maxLocalSize] == '\0')
            {
                globalJson[i] = nullptr;
            }
            else
            {
                globalJson[i] = nlohmann::json::parse(
                    globalVec.begin() + i * maxLocalSize,
                    globalVec.begin() + (i + 1) * maxLocalSize);
            }
        }
    }
    catch (std::exception &e)
    {
        throw(std::runtime_error(
            std::string("corrupted global read pattern metadata, ") +
            std::string(e.what())));
    }

    ssc::JsonToBlockVecVec(globalJson, m_GlobalReadPattern);
    m_AllSendingReaderRanks = ssc::CalculateOverlap(
        m_GlobalReadPattern, m_GlobalWritePattern[m_StreamRank]);
    CalculatePosition(m_GlobalWritePattern, m_GlobalReadPattern, m_WriterRank,
                      m_AllSendingReaderRanks);

    if (m_Verbosity >= 10)
    {
        ssc::PrintBlockVecVec(m_GlobalWritePattern, "Global Write Pattern");
        ssc::PrintBlockVec(m_GlobalWritePattern[m_WriterRank],
                           "Local Write Pattern");
    }
}

void SscWriter::CalculatePosition(ssc::BlockVecVec &writerVecVec,
                                  ssc::BlockVecVec &readerVecVec,
                                  const int writerRank,
                                  ssc::RankPosMap &allOverlapRanks)
{
    TAU_SCOPED_TIMER_FUNC();
    for (auto &overlapRank : allOverlapRanks)
    {
        auto &readerRankMap = readerVecVec[overlapRank.first];
        auto currentReaderOverlapWriterRanks =
            CalculateOverlap(writerVecVec, readerRankMap);
        size_t bufferPosition = 0;
        for (size_t rank = 0; rank < writerVecVec.size(); ++rank)
        {
            bool hasOverlap = false;
            for (const auto r : currentReaderOverlapWriterRanks)
            {
                if (r.first == rank)
                {
                    hasOverlap = true;
                    break;
                }
            }
            if (hasOverlap)
            {
                currentReaderOverlapWriterRanks[rank].first = bufferPosition;
                auto &bv = writerVecVec[rank];
                size_t currentRankTotalSize = TotalDataSize(bv) + 1;
                currentReaderOverlapWriterRanks[rank].second =
                    currentRankTotalSize;
                bufferPosition += currentRankTotalSize;
            }
        }
        allOverlapRanks[overlapRank.first] =
            currentReaderOverlapWriterRanks[writerRank];
    }
}

#define declare_type(T)                                                        \
    void SscWriter::DoPutSync(Variable<T> &variable, const T *data)            \
    {                                                                          \
        PutDeferredCommon(variable, data);                                     \
        PerformPuts();                                                         \
    }                                                                          \
    void SscWriter::DoPutDeferred(Variable<T> &variable, const T *data)        \
    {                                                                          \
        PutDeferredCommon(variable, data);                                     \
    }
ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type

void SscWriter::DoClose(const int transportIndex)
{
    TAU_SCOPED_TIMER_FUNC();

    MpiWait();

    m_Buffer[0] = 1;

    if (m_MpiMode == "twosided")
    {
        std::vector<MPI_Request> requests;
        for (const auto &i : m_AllSendingReaderRanks)
        {
            requests.emplace_back();
            MPI_Isend(m_Buffer.data(), 1, MPI_CHAR, i.first, 0, m_StreamComm,
                      &requests.back());
        }
        MPI_Status statuses[requests.size()];
        MPI_Waitall(requests.size(), requests.data(), statuses);
    }
    else if (m_MpiMode == "onesidedfencepush")
    {
        MPI_Win_fence(0, m_MpiWin);
        for (const auto &i : m_AllSendingReaderRanks)
        {
            MPI_Put(m_Buffer.data(), 1, MPI_CHAR, i.first, 0, 1, MPI_CHAR,
                    m_MpiWin);
        }
        MPI_Win_fence(0, m_MpiWin);
    }
    else if (m_MpiMode == "onesidedpostpush")
    {
        MPI_Win_start(m_MpiAllReadersGroup, 0, m_MpiWin);
        for (const auto &i : m_AllSendingReaderRanks)
        {
            MPI_Put(m_Buffer.data(), 1, MPI_CHAR, i.first, 0, 1, MPI_CHAR,
                    m_MpiWin);
        }
        MPI_Win_complete(m_MpiWin);
    }
    else if (m_MpiMode == "onesidedfencepull")
    {
        MPI_Win_fence(0, m_MpiWin);
        MPI_Win_fence(0, m_MpiWin);
    }
    else if (m_MpiMode == "onesidedpostpull")
    {
        MPI_Win_post(m_MpiAllReadersGroup, 0, m_MpiWin);
        MPI_Win_wait(m_MpiWin);
    }

    MPI_Win_free(&m_MpiWin);
}

} // end namespace engine
} // end namespace core
} // end namespace adios2
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include "consoleui.h"
#include "scientist.h"

using namespace std;

ConsoleUI::ConsoleUI()
{

}

// Should not contain logic for individual commands, that should be in separate functions!
void ConsoleUI::run()
{
    string command;
    do
    {
        cout << "Select one of the following options: " << endl;
        cout << "Add - add a programmer/computer scientist" << endl;
        cout << "List - show a list of all programmer's/computer scientist's" << endl;
        cout << "Search - search the list of programmer's/computer scientist's" << endl;
        cout << "Quit - end program" << endl;

        cin >> command;
        for(unsigned int i = 0; i < command.length(); i++) // to make all lowercase, taken from c++ site
        {
            command[i] = tolower(command[i]);
        }

        cout << endl;

        if(command == "add") // Could possibly be improved upon
        {
           userMenuAdd();
        }
        else if(command == "list") // Could possibly be improved upon
        {
           userMenuList();
        }
        else if(command == "search") // Could possibly be improved upon
        {
           userMenuSearch();
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(command != "quit");

}
void ConsoleUI::userMenuAdd()
{
    string name;
    char gender;
    int birthYear;
    int deathYear = 0;

    cout << "Enter the programmer's/computer scientist's name: ";
    cin.ignore();
    getline(cin, name);

    bool check = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's gender (m/f): ";
        cin >> gender;

        if((gender != 'm') && (gender != 'f'))
        {
            cout << "Invalid input" << endl;
        }
        else
        {
            check = false;
        }
    }while(check == true);

    bool check2 = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's year of birth: ";
        cin >> birthYear;
        if(birthYear < 2016) // Just in case we find a programmer of the univers
        {
            check2 = false;
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(check2 == true);

    bool check3 = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's year of death (type 0 if not applicable): ";
        cin >> deathYear;
        if (deathYear == 0)
        {
            check3 = false;
        }
        else if(deathYear >= birthYear)
        {
            check3 = false;
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(check3 == true);

    _service.addScientist(name, gender, birthYear, deathYear);
}
void ConsoleUI::userMenuList()
{
    vector<Scientist> scientist = _service.getScientists();

    cout << "Scientist name:" << endl;
    cout << "===============" << endl;
    for (size_t i = 0; i< scientist.size(); ++i)
    {
        cout << scientist[i].getName() << "\t"
             << scientist[i].getGender() << "\t"
             << scientist[i].getAge() << "\t"
             << scientist[i].getDeath() << endl;
    }
    cout << endl;
}
void ConsoleUI::userMenuSearch()
{
    string command;
    cout << "Select a search option: " << endl;
    cout << "Name - Search by name" << endl;
    cout << "Birth - Search by year of birth" << endl;
    cout << "Death - search by year of death" << endl;
    cin >> command;

    if(command == "name" || command == "Name" || command == "NAME")
    {
        vector<Scientist> scientist = _service.getScientists();
        string nameInputSearch;
        cout << "Enter a name to search: ";
        cin >> nameInputSearch;

        for(unsigned int i = 0; i < scientist.size(); ++i)
        {
            if(scientist[i].getName() == nameInputSearch)
            {
                cout << scientist[i].getName() << endl;
            }
        }
    }
    else if(command == "birth" || command == "Birth" || command == "BIRTH")
    {

    }
    else if(command == "death" || command == "Death" || command == "DEATH")
    {

    }

}
<commit_msg>console printout update<commit_after>#include <iostream>
#include <string>
#include "consoleui.h"
#include "scientist.h"

using namespace std;

ConsoleUI::ConsoleUI()
{

}

// Should not contain logic for individual commands, that should be in separate functions!
void ConsoleUI::run()
{
    string command;
    do
    {
        cout << "Select one of the following options: " << endl;
        cout << "Add - add a programmer/computer scientist" << endl;
        cout << "List - show a list of all programmer's/computer scientist's" << endl;
        cout << "Search - search the list of programmer's/computer scientist's" << endl;
        cout << "Quit - end program" << endl;

        cin >> command;
        for(unsigned int i = 0; i < command.length(); i++) // to make all lowercase, taken from c++ site
        {
            command[i] = tolower(command[i]);
        }

        cout << endl;

        if(command == "add") // Could possibly be improved upon
        {
           userMenuAdd();
        }
        else if(command == "list") // Could possibly be improved upon
        {
           userMenuList();
        }
        else if(command == "search") // Could possibly be improved upon
        {
           userMenuSearch();
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(command != "quit");

}
void ConsoleUI::userMenuAdd()
{
    string name;
    char gender;
    int birthYear;
    int deathYear = 0;

    cout << "Enter the programmer's/computer scientist's name: ";
    cin.ignore();
    getline(cin, name);

    bool check = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's gender (m/f): ";
        cin >> gender;

        if((gender != 'm') && (gender != 'f'))
        {
            cout << "Invalid input" << endl;
        }
        else
        {
            check = false;
        }
    }while(check == true);

    bool check2 = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's year of birth: ";
        cin >> birthYear;
        if(birthYear < 2016) // Just in case we find a programmer of the univers
        {
            check2 = false;
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(check2 == true);

    bool check3 = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's year of death (type 0 if not applicable): ";
        cin >> deathYear;
        if (deathYear == 0)
        {
            check3 = false;
        }
        else if(deathYear >= birthYear)
        {
            check3 = false;
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(check3 == true);
    cout << endl;

    _service.addScientist(name, gender, birthYear, deathYear);
}
void ConsoleUI::userMenuList()
{
    vector<Scientist> scientist = _service.getScientists();

    cout << "Scientist name: \t" << "gender: \t" << "age: \t" << "died:" << endl;
    cout << "================================================================" << endl;
    for (size_t i = 0; i< scientist.size(); ++i)
    {
        cout << scientist[i].getName() << "\t"
             << scientist[i].getGender() << "\t\t"
             << scientist[i].getAge() << "\t"
             << scientist[i].getDeath() << endl;
    }
    cout << endl;
}
void ConsoleUI::userMenuSearch()
{
    string command;
    cout << "Select a search option: " << endl;
    cout << "Name - Search by name" << endl;
    cout << "Birth - Search by year of birth" << endl;
    cout << "Death - search by year of death" << endl;
    cin >> command;

    if(command == "name" || command == "Name" || command == "NAME")
    {
        vector<Scientist> scientist = _service.getScientists();
        string nameInputSearch;
        cout << "Enter a name to search: ";
        cin >> nameInputSearch;

        for(unsigned int i = 0; i < scientist.size(); ++i)
        {
            if(scientist[i].getName() == nameInputSearch)
            {
                cout << scientist[i].getName() << endl;
            }
        }
    }
    else if(command == "birth" || command == "Birth" || command == "BIRTH")
    {

    }
    else if(command == "death" || command == "Death" || command == "DEATH")
    {

    }

}
<|endoftext|>


<commit_before>#ifndef _SOSPD_HPP_
#define _SOSPD_HPP_

/** \file sospd.hpp
 * Sum-of-submodular Primal Dual algorithm for multilabel problems
 */

//#define PROGRESS_DISPLAY
//#define CHECK_INVARIANTS

#include "energy-common.hpp"
#include <vector>
#include <functional>

#include "clique.hpp"
#include "submodular-ibfs.hpp"
#include "submodular-functions.hpp"

/** Optimizer using Sum-of-submodular Primal Dual algorithm.
 *
 * Implements SoSPD algorithm from Fix, Wang, Zabih in CVPR 14.
 */
class SoSPD {
    public:
        typedef MultilabelEnergy::NodeId NodeId;
        typedef MultilabelEnergy::Label Label;

        /** Proposal callbacks take as input the iteration number and current
         * labeling (as a vector of labels) and write the next proposal to the
         * final parameter.
         */
        typedef std::function<
              void(int niter,
                   const std::vector<Label>& current,
                   std::vector<Label>& proposed)
            > ProposalCallback;

        /** Set up SoSPD to optimize a particular energy function
         *
         * \param energy Energy function to optimize.
         */
        explicit SoSPD(const MultilabelEnergy* energy);

        /** Run SoSPD algorithm either to completion, or for a number of steps.
         *
         * Each iteration has a single proposal (determined by
         * SetProposalCallback), and solves a corresponding Sum-of-Submodular
         * flow problem.
         *
         * Resulting labeling can be queried from GetLabel.
         *
         * \param niters Number of iterations
         */
        void Solve(int niters = std::numeric_limits<int>::max());

        /** Return label of a node i, returns -1 if Solve has not been called.*/
        int GetLabel(NodeId i) const;

        /** Give hint that energy is expansion submodular. Enables optimizations
         * because we don't need to find submodular upper/lower bounds for the
         * function.
         */
        void SetExpansionSubmodular(bool b) { m_expansion_submodular = b; }

        /** Choose whether to use lower/upper bound in approximating function.
         */
        void SetLowerBound(bool b) { m_lower_bound = b; }

        /** Specify method for choosing proposals. */
        void SetProposalCallback(const ProposalCallback& pc) { m_pc = pc; }

        /** Set the proposal method to alpha-expansion
         *
         * Alpha-expansion proposals simply cycle through the labels, proposing
         * a constant labeling (i.e., all "alpha") at each iteration.
         */
        void SetAlphaExpansion() {
            m_pc = [&](int, const std::vector<Label>&, std::vector<Label>&) {
                AlphaProposal();
            };
        }

        /** Set the proposal method to best-height alpha-expansion
         *
         * Best-height alpha-expansion, instead of cycling through labels,
         * chooses the single alpha with the biggest sum of differences in
         * heights.
         */
        void SetHeightAlphaExpansion() {
            m_pc = [&](int, const std::vector<Label>&, std::vector<Label>&) {
                HeightAlphaProposal();
            };
        }

        /** Return lower bound on optimum, determined by current dual */
        double LowerBound();

    private:
        typedef MultilabelEnergy::CliquePtr CliquePtr;
        typedef std::vector<std::vector<REAL> > Dual;
        typedef std::vector<std::pair<size_t, size_t>> NodeNeighborList;
        typedef std::vector<NodeNeighborList> NodeCliqueList;

        REAL ComputeHeight(NodeId, Label);
        REAL ComputeHeightDiff(NodeId i, Label l1, Label l2) const;
        void SetupGraph(SubmodularIBFS& crf);
        void SetupAlphaEnergy(SubmodularIBFS& crf);
        void InitialLabeling();
        void InitialDual();
        void InitialNodeCliqueList();
        bool InitialFusionLabeling();
        void PreEditDual(SubmodularIBFS& crf);
        bool UpdatePrimalDual(SubmodularIBFS& crf);
        void PostEditDual();
        void DualFit();
        bool CheckHeightInvariant();
        bool CheckLabelInvariant();
        bool CheckDualBoundInvariant();
        bool CheckActiveInvariant();
        REAL& Height(NodeId i, Label l) { return m_heights[i*m_num_labels+l]; }

        // Move Proposals
        void HeightAlphaProposal();
        void AlphaProposal();

        const MultilabelEnergy* m_energy;
        SubmodularIBFS m_ibfs;
        const size_t m_num_labels;
        std::vector<Label> m_labels;
        std::vector<Label> m_fusion_labels;
        NodeCliqueList m_node_clique_list;
        std::vector<Dual> m_dual;
        std::vector<REAL> m_heights;
        bool m_expansion_submodular;
        bool m_lower_bound;
        int m_iter;
        ProposalCallback m_pc;
};

#endif
<commit_msg>Fixmes in sospd<commit_after>#ifndef _SOSPD_HPP_
#define _SOSPD_HPP_

/** \file sospd.hpp
 * Sum-of-submodular Primal Dual algorithm for multilabel problems
 */

//#define PROGRESS_DISPLAY
//#define CHECK_INVARIANTS

#include "energy-common.hpp"
#include <vector>
#include <functional>

#include "clique.hpp"
#include "submodular-ibfs.hpp"
#include "submodular-functions.hpp"

/** Optimizer using Sum-of-submodular Primal Dual algorithm.
 *
 * Implements SoSPD algorithm from Fix, Wang, Zabih in CVPR 14.
 */
class SoSPD {
    public:
        typedef MultilabelEnergy::NodeId NodeId;
        typedef MultilabelEnergy::Label Label;

        /** Proposal callbacks take as input the iteration number and current
         * labeling (as a vector of labels) and write the next proposal to the
         * final parameter.
         */
        typedef std::function<
              void(int niter,
                   const std::vector<Label>& current,
                   std::vector<Label>& proposed)
            > ProposalCallback;

        /** Set up SoSPD to optimize a particular energy function
         *
         * \param energy Energy function to optimize.
         */
        explicit SoSPD(const MultilabelEnergy* energy);

        /** Run SoSPD algorithm either to completion, or for a number of steps.
         *
         * Each iteration has a single proposal (determined by
         * SetProposalCallback), and solves a corresponding Sum-of-Submodular
         * flow problem.
         *
         * Resulting labeling can be queried from GetLabel.
         *
         * \param niters Number of iterations
         */
        void Solve(int niters = std::numeric_limits<int>::max());

        /** Return label of a node i, returns -1 if Solve has not been called.*/
        int GetLabel(NodeId i) const;

        /** Give hint that energy is expansion submodular. Enables optimizations
         * because we don't need to find submodular upper/lower bounds for the
         * function.
         */
        void SetExpansionSubmodular(bool b) { m_expansion_submodular = b; }

        /** Choose whether to use lower/upper bound in approximating function.
         */
        void SetLowerBound(bool b) { m_lower_bound = b; }

        /** Specify method for choosing proposals. */
        void SetProposalCallback(const ProposalCallback& pc) { m_pc = pc; }

        /** Set the proposal method to alpha-expansion
         *
         * Alpha-expansion proposals simply cycle through the labels, proposing
         * a constant labeling (i.e., all "alpha") at each iteration.
         */
        void SetAlphaExpansion() {
            m_pc = [&](int, const std::vector<Label>&, std::vector<Label>&) {
                AlphaProposal();
            };
        }

        /** Set the proposal method to best-height alpha-expansion
         *
         * Best-height alpha-expansion, instead of cycling through labels,
         * chooses the single alpha with the biggest sum of differences in
         * heights.
         */
        void SetHeightAlphaExpansion() {
            m_pc = [&](int, const std::vector<Label>&, std::vector<Label>&) {
                HeightAlphaProposal();
            };
        }

        /** Return lower bound on optimum, determined by current dual */
        double LowerBound();

    private:
        typedef MultilabelEnergy::CliquePtr CliquePtr;
        typedef std::vector<std::vector<REAL> > Dual;
        typedef std::vector<std::pair<size_t, size_t>> NodeNeighborList;
        typedef std::vector<NodeNeighborList> NodeCliqueList;

        REAL ComputeHeight(NodeId, Label);
        REAL ComputeHeightDiff(NodeId i, Label l1, Label l2) const;
        void SetupGraph(SubmodularIBFS& crf);
        // TODO(afix): redo this
        void SetupAlphaEnergy(SubmodularIBFS& crf);
        void InitialLabeling();
        void InitialDual();
        void InitialNodeCliqueList();
        bool InitialFusionLabeling();
        void PreEditDual(SubmodularIBFS& crf);
        bool UpdatePrimalDual(SubmodularIBFS& crf);
        void PostEditDual();
        void DualFit();
        bool CheckHeightInvariant();
        bool CheckLabelInvariant();
        bool CheckDualBoundInvariant();
        bool CheckActiveInvariant();
        REAL& Height(NodeId i, Label l) { return m_heights[i*m_num_labels+l]; }

        // Move Proposals
        void HeightAlphaProposal();
        void AlphaProposal();

        const MultilabelEnergy* m_energy;
        // Unique ptr so we can forward declare?
        SubmodularIBFS m_ibfs;
        const size_t m_num_labels;
        std::vector<Label> m_labels;
        /// The proposed labeling in a given iteration
        std::vector<Label> m_fusion_labels;
        // Factor this list back into a node list?
        NodeCliqueList m_node_clique_list;
        // FIXME(afix) change way m_dual is stored. Put lambda_alpha as separate
        // double* for each clique, indexed by i, l.
        std::vector<Dual> m_dual;
        std::vector<REAL> m_heights;
        bool m_expansion_submodular;
        bool m_lower_bound;
        int m_iter;
        ProposalCallback m_pc;
};

#endif
<|endoftext|>


<commit_before>#include "stack.hpp"
#include <stdexcept>
#ifndef STACK_CPP
#define STACK_CPP

bitset::bitset(size_t size) : ptr_(std::make_unique<bool[]>(size)),size_(size),counter_(0)
{}

auto bitset::set(size_t index)->void //инициализация всех битов единицами или изменение значения тдельного бита
{
	if (index >= 0 && index < size_)
	{
		ptr_[index] = true; ++counter_;
	}
	else throw("problem with index");
}

auto bitset::reset(size_t index) throw(std::out_of_range) -> void //обнуление указанных битов
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	ptr_[index] = false;
	--counter_;
}

auto bitset::test(size_t index) const throw(std::out_of_range) -> bool //возвращает значение указанного бита
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	return ptr_[index];
}

auto bitset::size() const -> size_t
{
	return size_;
}
auto bitset::counter() const -> size_t
{
	return counter_;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)operator new(size*sizeof(T))), size_(size), map_(std::make_unique<bitset>(size))//конструктор с параметром
{}

template<typename T>
allocator<T>::allocator(allocator const& other) : allocator<T>(other.size_) //конструктор копирования
{
	for (size_t i=0; i < size_; i++)
	{
		if (map_->test(i))
		{
			destroy(ptr_, ptr_ +i);
		}
	construct(ptr_ + i, other.ptr_[i]);
}

template<typename T>
allocator<T>::~allocator()
{
	if (this->count() > 0)
	{
		destroy(ptr_, ptr_ + size_());
	}
	operator delete(ptr_);
}

template<typename T> //увеличение памяти
auto allocator<T>::resize()->void
{
	allocator<T> alloc(size_ * 2 + (size_ == 0));
	for (size_t i = 0; i < size_; ++i) if(map_->test(i)) alloc.construct(alloc.get() + i, ptr_[i]);
	this->swap(alloc);
}

template<typename T>
auto allocator<T>::construct(T * ptr, T const & value)->void
{
	if (ptr >= ptr_&&ptr < ptr_ + size_)
	{
		new(ptr)T(value);
		map_->set(ptr - ptr_);
	}
	else { throw("error"); }
}
template <typename T>
auto allocator<T>::destroy(T * ptr)->void
{
if (ptr < ptr_ || ptr >= ptr_ + size_ || map_->test(ptr-ptr_) == false)
{
		throw std::out_of_range("Error");
}
	ptr->~T();
	map_->reset(ptr - ptr_);

}

template<typename T> //получаем ptr_
auto allocator<T>::get()-> T* { return ptr_; }

template<typename T>
auto allocator<T>::get() const -> T const * { return ptr_; }

template<typename T>
auto allocator<T>::count() const -> size_t{ return map_->counter(); }

template<typename T> //заполненность
auto allocator<T>::full() const -> bool { return (map_->counter() == size_); }

template<typename T>
auto allocator<T>::empty() const -> bool { return (map_->counter() == 0); }

template<typename T>
auto allocator<T>::destroy(T * first, T * last)->void
{
	if(first>=ptr_&&last<=ptr_+this->count())
		for (; first != last; ++first)
		{
			destroy(&*first);
		}
}

template<typename T>
auto allocator<T>::swap(allocator & other)->void{
	std::swap(ptr_, other.ptr_);
	std::swap(size_, other.size_);
	std::swap(map_, other.map_);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template<typename T>
stack<T>::stack(size_t size) : allocator_(size)
{}

template<typename T>
auto stack<T>::operator =(stack const & other)-> stack &
{
	if (this != &other)
	{
		(allocator<T>(other.allocator_)).swap(allocator_);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const ->bool
{
return allocator_.empty();
}

template<typename T>
auto stack<T>::count()const->size_t
{
return allocator_.count();
}

template<typename T>
auto stack<T>::push(T const & value)->void
{
	if (allocator_.full()) allocator_.resize();
	allocator_.construct(allocator_.get() + this->count(), value);
}

template<typename T>
auto stack<T>::pop()->void
{
	if (allocator_.count() == 0) throw std::logic_error("Empty");
	allocator_.destroy(allocator_.get() + (this->count() - 1));
}

template<typename T>
auto stack<T>::top()->T&
{
	if (this->count() > 0) return(*(allocator_.get() + this->count() - 1));
	else this->throw_is_empty();
}

template<typename T>
auto stack<T>::top()const->T const &
{
	if (this->count() > 0) return(*(allocator_.get() + this->count() - 1));
	else this->throw_is_empty();
}

template<typename T>
auto stack<T>::throw_is_empty()const->void
{
throw("Stack is empty");
}

#endif
<commit_msg>Update stack.cpp<commit_after>#include "stack.hpp"
#include <stdexcept>
#ifndef STACK_CPP
#define STACK_CPP

bitset::bitset(size_t size) : ptr_(std::make_unique<bool[]>(size)),size_(size),counter_(0)
{}

auto bitset::set(size_t index)->void //инициализация всех битов единицами или изменение значения тдельного бита
{
	if (index >= 0 && index < size_)
	{
		ptr_[index] = true; ++counter_;
	}
	else throw("problem with index");
}

auto bitset::reset(size_t index) throw(std::out_of_range) -> void //обнуление указанных битов
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	ptr_[index] = false;
	--counter_;
}

auto bitset::test(size_t index) const throw(std::out_of_range) -> bool //возвращает значение указанного бита
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	return ptr_[index];
}

auto bitset::size() const -> size_t
{
	return size_;
}
auto bitset::counter() const -> size_t
{
	return counter_;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)operator new(size*sizeof(T))), size_(size), map_(std::make_unique<bitset>(size))//конструктор с параметром
{}

template<typename T>
allocator<T>::allocator(allocator const& other) : allocator<T>(other.size_) //конструктор копирования
{
	for (size_t i=0; i < size_; i++)
	{
		if (map_->test(i))
		{
			destroy(ptr_, ptr_ +i);
		}
	construct(ptr_ + i, other.ptr_[i]);
}}

template<typename T>
allocator<T>::~allocator()
{
	if (this->count() > 0)
	{
		destroy(ptr_, ptr_ + size_());
	}
	operator delete(ptr_);
}

template<typename T> //увеличение памяти
auto allocator<T>::resize()->void
{
	allocator<T> alloc(size_ * 2 + (size_ == 0));
	for (size_t i = 0; i < size_; ++i) if(map_->test(i)) alloc.construct(alloc.get() + i, ptr_[i]);
	this->swap(alloc);
}

template<typename T>
auto allocator<T>::construct(T * ptr, T const & value)->void
{
	if (ptr >= ptr_&&ptr < ptr_ + size_)
	{
		new(ptr)T(value);
		map_->set(ptr - ptr_);
	}
	else { throw("error"); }
}
template <typename T>
auto allocator<T>::destroy(T * ptr)->void
{
if (ptr < ptr_ || ptr >= ptr_ + size_ || map_->test(ptr-ptr_) == false)
{
		throw std::out_of_range("Error");
}
	ptr->~T();
	map_->reset(ptr - ptr_);

}

template<typename T> //получаем ptr_
auto allocator<T>::get()-> T* { return ptr_; }

template<typename T>
auto allocator<T>::get() const -> T const * { return ptr_; }

template<typename T>
auto allocator<T>::count() const -> size_t{ return map_->counter(); }

template<typename T> //заполненность
auto allocator<T>::full() const -> bool { return (map_->counter() == size_); }

template<typename T>
auto allocator<T>::empty() const -> bool { return (map_->counter() == 0); }

template<typename T>
auto allocator<T>::destroy(T * first, T * last)->void
{
	if(first>=ptr_&&last<=ptr_+this->count())
		for (; first != last; ++first)
		{
			destroy(&*first);
		}
}

template<typename T>
auto allocator<T>::swap(allocator & other)->void{
	std::swap(ptr_, other.ptr_);
	std::swap(size_, other.size_);
	std::swap(map_, other.map_);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template<typename T>
stack<T>::stack(size_t size) : allocator_(size)
{}

template<typename T>
auto stack<T>::operator =(stack const & other)-> stack &
{
	if (this != &other)
	{
		(allocator<T>(other.allocator_)).swap(allocator_);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const ->bool
{
return allocator_.empty();
}

template<typename T>
auto stack<T>::count()const->size_t
{
return allocator_.count();
}

template<typename T>
auto stack<T>::push(T const & value)->void
{
	if (allocator_.full()) allocator_.resize();
	allocator_.construct(allocator_.get() + this->count(), value);
}

template<typename T>
auto stack<T>::pop()->void
{
	if (allocator_.count() == 0) throw std::logic_error("Empty");
	allocator_.destroy(allocator_.get() + (this->count() - 1));
}

template<typename T>
auto stack<T>::top()->T&
{
	if (this->count() > 0) return(*(allocator_.get() + this->count() - 1));
	else this->throw_is_empty();
}

template<typename T>
auto stack<T>::top()const->T const &
{
	if (this->count() > 0) return(*(allocator_.get() + this->count() - 1));
	else this->throw_is_empty();
}

template<typename T>
auto stack<T>::throw_is_empty()const->void
{
throw("Stack is empty");
}

#endif
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef __itkRawImageIO_hxx
#define __itkRawImageIO_hxx
#include "itkRawImageIO.h"

namespace itk
{
template< class TPixel, unsigned int VImageDimension >
RawImageIO< TPixel, VImageDimension >::RawImageIO():
  ImageIOBase()
{
  this->SetNumberOfComponents(1);
  this->SetPixelTypeInfo( static_cast<const PixelType *>(0) );
  this->SetNumberOfDimensions(VImageDimension);

  for ( unsigned int idx = 0; idx < VImageDimension; ++idx )
    {
    m_Spacing.insert(m_Spacing.begin() + idx, 1.0);
    m_Origin.insert(m_Origin.begin() + idx, 0.0);
    }

  m_HeaderSize = 0;
  m_ManualHeaderSize = false;

  // Left over from short reader
  m_ImageMask = 0xffff;
  m_ByteOrder = ImageIOBase::BigEndian;
  m_FileDimensionality = 2;
  m_FileType = Binary;
}

template< class TPixel, unsigned int VImageDimension >
RawImageIO< TPixel, VImageDimension >::~RawImageIO()
{}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "ImageMask: " << m_ImageMask << std::endl;
  os << indent << "FileDimensionality: " << m_FileDimensionality << std::endl;
}

template< class TPixel, unsigned int VImageDimension >
SizeValueType RawImageIO< TPixel, VImageDimension >::GetHeaderSize()
{
  std::ifstream file;

  if ( m_FileName == "" )
    {
    itkExceptionMacro(<< "A FileName must be specified.");
    }

  if ( !m_ManualHeaderSize )
    {
    if ( m_FileType == ASCII )
      {
      return 0;                          //cannot determine it
      }
    this->ComputeStrides();

    // make sure we figure out a filename to open
    this->OpenFileForReading(file);

    // Get the size of the header from the size of the image
    file.seekg(0, std::ios::end);

    m_HeaderSize = static_cast<SizeValueType>(
      static_cast<typename ::itk::intmax_t>( file.tellg() )
      - static_cast<typename ::itk::intmax_t>( this->m_Strides[m_FileDimensionality + 1] )
    );
    }

  return m_HeaderSize;
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >::OpenFileForReading(std::ifstream & is)
{
  if ( m_FileName == "" )
    {
    itkExceptionMacro(<< "A FileName must be specified.");
    }

  // Close file from any previous image
  if ( is.is_open() )
    {
    is.close();
    }

  // Open the new file
  itkDebugMacro(<< "Initialize: opening file " << m_FileName);
#ifdef _WIN32
  is.open(m_FileName.c_str(), std::ios::in | std::ios::binary);
#else
  is.open(m_FileName.c_str(), std::ios::in);
#endif
  if ( is.fail() )
    {
    itkExceptionMacro(<< "Could not open file: " << m_FileName);
    }
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >::OpenFileForWriting(std::ofstream & os)
{
  if ( m_FileName == "" )
    {
    itkExceptionMacro(<< "A FileName must be specified.");
    }

  std::ofstream tFile(m_FileName.c_str(), std::ios::out);
  tFile.close();

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file
  itkDebugMacro(<< "Initialize: opening file " << m_FileName);
#ifdef _WIN32
  os.open(m_FileName.c_str(), std::ios::out | std::ios::binary);
#else
  os.open(m_FileName.c_str(), std::ios::out);
#endif
  if ( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file: " << m_FileName);
    }
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >
::SetHeaderSize(SizeValueType size)
{
  if ( size != m_HeaderSize )
    {
    m_HeaderSize = size;
    this->Modified();
    }
  m_ManualHeaderSize = true;
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >
::Read(void *buffer)
{
  std::ifstream file;

  // Open the file
  this->OpenFileForReading(file);
  this->ComputeStrides();

  // Offset into file
  SizeValueType streamStart = this->GetHeaderSize();
  file.seekg( (OffsetValueType)streamStart, std::ios::beg );
  if ( file.fail() )
    {
    itkExceptionMacro(<< "File seek failed");
    }

  const SizeValueType numberOfBytesToBeRead =
    static_cast< SizeValueType >( this->GetImageSizeInBytes() );

  itkDebugMacro(<< "Reading " << numberOfBytesToBeRead << " bytes");

  if ( m_FileType == Binary )
    {
    if ( !this->ReadBufferAsBinary(file, buffer, numberOfBytesToBeRead) )
      {
      itkExceptionMacro(<< "Read failed: Wanted "
                        << numberOfBytesToBeRead
                        << " bytes, but read "
                        << file.gcount() << " bytes.");
      }
    }
  else
    {
    this->ReadBufferAsASCII( file, buffer, this->GetComponentType(),
                             this->GetImageSizeInComponents() );
    }

  itkDebugMacro(<< "Reading Done");

#define itkReadRawBytesAfterSwappingMacro(StrongType, WeakType)   \
  ( this->GetComponentType() == WeakType )                        \
    {                                                             \
    typedef ByteSwapper< StrongType > InternalByteSwapperType;    \
    if ( m_ByteOrder == LittleEndian )                            \
      {                                                           \
      InternalByteSwapperType::SwapRangeFromSystemToLittleEndian( \
        (StrongType *)buffer, this->GetImageSizeInComponents() ); \
      }                                                           \
    else if ( m_ByteOrder == BigEndian )                          \
      {                                                           \
      InternalByteSwapperType::SwapRangeFromSystemToBigEndian(    \
        (StrongType *)buffer, this->GetImageSizeInComponents() ); \
      }                                                           \
    }

  // Swap bytes if necessary
  if itkReadRawBytesAfterSwappingMacro(unsigned short, USHORT)
  else if itkReadRawBytesAfterSwappingMacro(short, SHORT)
  else if itkReadRawBytesAfterSwappingMacro(char, CHAR)
  else if itkReadRawBytesAfterSwappingMacro(unsigned char, UCHAR)
  else if itkReadRawBytesAfterSwappingMacro(unsigned int, UINT)
  else if itkReadRawBytesAfterSwappingMacro(int, INT)
  else if itkReadRawBytesAfterSwappingMacro(long, LONG)
  else if itkReadRawBytesAfterSwappingMacro(unsigned long, ULONG)
  else if itkReadRawBytesAfterSwappingMacro(float, FLOAT)
  else if itkReadRawBytesAfterSwappingMacro(double, DOUBLE)
}

template< class TPixel, unsigned int VImageDimension >
bool RawImageIO< TPixel, VImageDimension >
::CanWriteFile(const char *fname)
{
  std::string filename(fname);

  if ( filename == "" )
    {
    return false;
    }

  return true;
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >
::Write(const void *buffer)
{
  std::ofstream file;

  // Open the file
  //
  this->OpenFileForWriting(file);

  // Set up for reading
  this->ComputeStrides();

  // Actually do the writing
  //
  if ( m_FileType == ASCII )
    {
    this->WriteBufferAsASCII( file, buffer, this->GetComponentType(),
                              this->GetImageSizeInComponents() );
    }
  else //binary
    {
    const SizeValueType numberOfBytes      = this->GetImageSizeInBytes();
    const SizeValueType numberOfComponents = this->GetImageSizeInComponents();

#define itkWriteRawBytesAfterSwappingMacro(StrongType, WeakType)        \
  ( this->GetComponentType() == WeakType )                              \
    {                                                                   \
    typedef ByteSwapper< StrongType > InternalByteSwapperType;          \
    if ( m_ByteOrder == LittleEndian )                                  \
      {                                                                 \
      char *tempBuffer = new char[numberOfBytes];                       \
      memcpy(tempBuffer, buffer, numberOfBytes);                        \
      InternalByteSwapperType::SwapRangeFromSystemToLittleEndian(       \
        (StrongType *)tempBuffer, numberOfComponents);                  \
      file.write(tempBuffer, numberOfBytes);                            \
      delete[] tempBuffer;                                              \
      }                                                                 \
    else if ( m_ByteOrder == BigEndian )                                \
      {                                                                 \
      char *tempBuffer = new char[numberOfBytes];                       \
      memcpy(tempBuffer, buffer, numberOfBytes);                        \
      InternalByteSwapperType::SwapRangeFromSystemToBigEndian(          \
        (StrongType *)tempBuffer, numberOfComponents);                  \
      file.write(tempBuffer, numberOfBytes);                            \
      delete[] tempBuffer;                                              \
      }                                                                 \
    else                                                                \
      {                                                                 \
      file.write(static_cast< const char * >( buffer ), numberOfBytes); \
      }                                                                 \
    }

    // Swap bytes if necessary
    if itkWriteRawBytesAfterSwappingMacro(unsigned short, USHORT)
    else if itkWriteRawBytesAfterSwappingMacro(short, SHORT)
    else if itkWriteRawBytesAfterSwappingMacro(char, CHAR)
    else if itkWriteRawBytesAfterSwappingMacro(unsigned char, UCHAR)
    else if itkWriteRawBytesAfterSwappingMacro(unsigned int, UINT)
    else if itkWriteRawBytesAfterSwappingMacro(int, INT)
    else if itkWriteRawBytesAfterSwappingMacro(long, LONG)
    else if itkWriteRawBytesAfterSwappingMacro(unsigned long, ULONG)
    else if itkWriteRawBytesAfterSwappingMacro(float, FLOAT)
    else if itkWriteRawBytesAfterSwappingMacro(double, DOUBLE)
    }

  file.close();
}
} // namespace itk
#endif
<commit_msg>COMP: missing include<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef __itkRawImageIO_hxx
#define __itkRawImageIO_hxx

#include "itkRawImageIO.h"
#include "itkIntTypes.h"

namespace itk
{
template< class TPixel, unsigned int VImageDimension >
RawImageIO< TPixel, VImageDimension >::RawImageIO():
  ImageIOBase()
{
  this->SetNumberOfComponents(1);
  this->SetPixelTypeInfo( static_cast<const PixelType *>(0) );
  this->SetNumberOfDimensions(VImageDimension);

  for ( unsigned int idx = 0; idx < VImageDimension; ++idx )
    {
    m_Spacing.insert(m_Spacing.begin() + idx, 1.0);
    m_Origin.insert(m_Origin.begin() + idx, 0.0);
    }

  m_HeaderSize = 0;
  m_ManualHeaderSize = false;

  // Left over from short reader
  m_ImageMask = 0xffff;
  m_ByteOrder = ImageIOBase::BigEndian;
  m_FileDimensionality = 2;
  m_FileType = Binary;
}

template< class TPixel, unsigned int VImageDimension >
RawImageIO< TPixel, VImageDimension >::~RawImageIO()
{}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "ImageMask: " << m_ImageMask << std::endl;
  os << indent << "FileDimensionality: " << m_FileDimensionality << std::endl;
}

template< class TPixel, unsigned int VImageDimension >
SizeValueType RawImageIO< TPixel, VImageDimension >::GetHeaderSize()
{
  std::ifstream file;

  if ( m_FileName == "" )
    {
    itkExceptionMacro(<< "A FileName must be specified.");
    }

  if ( !m_ManualHeaderSize )
    {
    if ( m_FileType == ASCII )
      {
      return 0;                          //cannot determine it
      }
    this->ComputeStrides();

    // make sure we figure out a filename to open
    this->OpenFileForReading(file);

    // Get the size of the header from the size of the image
    file.seekg(0, std::ios::end);

    m_HeaderSize = static_cast<SizeValueType>(
      static_cast<typename ::itk::intmax_t>( file.tellg() )
      - static_cast<typename ::itk::intmax_t>( this->m_Strides[m_FileDimensionality + 1] )
    );
    }

  return m_HeaderSize;
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >::OpenFileForReading(std::ifstream & is)
{
  if ( m_FileName == "" )
    {
    itkExceptionMacro(<< "A FileName must be specified.");
    }

  // Close file from any previous image
  if ( is.is_open() )
    {
    is.close();
    }

  // Open the new file
  itkDebugMacro(<< "Initialize: opening file " << m_FileName);
#ifdef _WIN32
  is.open(m_FileName.c_str(), std::ios::in | std::ios::binary);
#else
  is.open(m_FileName.c_str(), std::ios::in);
#endif
  if ( is.fail() )
    {
    itkExceptionMacro(<< "Could not open file: " << m_FileName);
    }
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >::OpenFileForWriting(std::ofstream & os)
{
  if ( m_FileName == "" )
    {
    itkExceptionMacro(<< "A FileName must be specified.");
    }

  std::ofstream tFile(m_FileName.c_str(), std::ios::out);
  tFile.close();

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file
  itkDebugMacro(<< "Initialize: opening file " << m_FileName);
#ifdef _WIN32
  os.open(m_FileName.c_str(), std::ios::out | std::ios::binary);
#else
  os.open(m_FileName.c_str(), std::ios::out);
#endif
  if ( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file: " << m_FileName);
    }
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >
::SetHeaderSize(SizeValueType size)
{
  if ( size != m_HeaderSize )
    {
    m_HeaderSize = size;
    this->Modified();
    }
  m_ManualHeaderSize = true;
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >
::Read(void *buffer)
{
  std::ifstream file;

  // Open the file
  this->OpenFileForReading(file);
  this->ComputeStrides();

  // Offset into file
  SizeValueType streamStart = this->GetHeaderSize();
  file.seekg( (OffsetValueType)streamStart, std::ios::beg );
  if ( file.fail() )
    {
    itkExceptionMacro(<< "File seek failed");
    }

  const SizeValueType numberOfBytesToBeRead =
    static_cast< SizeValueType >( this->GetImageSizeInBytes() );

  itkDebugMacro(<< "Reading " << numberOfBytesToBeRead << " bytes");

  if ( m_FileType == Binary )
    {
    if ( !this->ReadBufferAsBinary(file, buffer, numberOfBytesToBeRead) )
      {
      itkExceptionMacro(<< "Read failed: Wanted "
                        << numberOfBytesToBeRead
                        << " bytes, but read "
                        << file.gcount() << " bytes.");
      }
    }
  else
    {
    this->ReadBufferAsASCII( file, buffer, this->GetComponentType(),
                             this->GetImageSizeInComponents() );
    }

  itkDebugMacro(<< "Reading Done");

#define itkReadRawBytesAfterSwappingMacro(StrongType, WeakType)   \
  ( this->GetComponentType() == WeakType )                        \
    {                                                             \
    typedef ByteSwapper< StrongType > InternalByteSwapperType;    \
    if ( m_ByteOrder == LittleEndian )                            \
      {                                                           \
      InternalByteSwapperType::SwapRangeFromSystemToLittleEndian( \
        (StrongType *)buffer, this->GetImageSizeInComponents() ); \
      }                                                           \
    else if ( m_ByteOrder == BigEndian )                          \
      {                                                           \
      InternalByteSwapperType::SwapRangeFromSystemToBigEndian(    \
        (StrongType *)buffer, this->GetImageSizeInComponents() ); \
      }                                                           \
    }

  // Swap bytes if necessary
  if itkReadRawBytesAfterSwappingMacro(unsigned short, USHORT)
  else if itkReadRawBytesAfterSwappingMacro(short, SHORT)
  else if itkReadRawBytesAfterSwappingMacro(char, CHAR)
  else if itkReadRawBytesAfterSwappingMacro(unsigned char, UCHAR)
  else if itkReadRawBytesAfterSwappingMacro(unsigned int, UINT)
  else if itkReadRawBytesAfterSwappingMacro(int, INT)
  else if itkReadRawBytesAfterSwappingMacro(long, LONG)
  else if itkReadRawBytesAfterSwappingMacro(unsigned long, ULONG)
  else if itkReadRawBytesAfterSwappingMacro(float, FLOAT)
  else if itkReadRawBytesAfterSwappingMacro(double, DOUBLE)
}

template< class TPixel, unsigned int VImageDimension >
bool RawImageIO< TPixel, VImageDimension >
::CanWriteFile(const char *fname)
{
  std::string filename(fname);

  if ( filename == "" )
    {
    return false;
    }

  return true;
}

template< class TPixel, unsigned int VImageDimension >
void RawImageIO< TPixel, VImageDimension >
::Write(const void *buffer)
{
  std::ofstream file;

  // Open the file
  //
  this->OpenFileForWriting(file);

  // Set up for reading
  this->ComputeStrides();

  // Actually do the writing
  //
  if ( m_FileType == ASCII )
    {
    this->WriteBufferAsASCII( file, buffer, this->GetComponentType(),
                              this->GetImageSizeInComponents() );
    }
  else //binary
    {
    const SizeValueType numberOfBytes      = this->GetImageSizeInBytes();
    const SizeValueType numberOfComponents = this->GetImageSizeInComponents();

#define itkWriteRawBytesAfterSwappingMacro(StrongType, WeakType)        \
  ( this->GetComponentType() == WeakType )                              \
    {                                                                   \
    typedef ByteSwapper< StrongType > InternalByteSwapperType;          \
    if ( m_ByteOrder == LittleEndian )                                  \
      {                                                                 \
      char *tempBuffer = new char[numberOfBytes];                       \
      memcpy(tempBuffer, buffer, numberOfBytes);                        \
      InternalByteSwapperType::SwapRangeFromSystemToLittleEndian(       \
        (StrongType *)tempBuffer, numberOfComponents);                  \
      file.write(tempBuffer, numberOfBytes);                            \
      delete[] tempBuffer;                                              \
      }                                                                 \
    else if ( m_ByteOrder == BigEndian )                                \
      {                                                                 \
      char *tempBuffer = new char[numberOfBytes];                       \
      memcpy(tempBuffer, buffer, numberOfBytes);                        \
      InternalByteSwapperType::SwapRangeFromSystemToBigEndian(          \
        (StrongType *)tempBuffer, numberOfComponents);                  \
      file.write(tempBuffer, numberOfBytes);                            \
      delete[] tempBuffer;                                              \
      }                                                                 \
    else                                                                \
      {                                                                 \
      file.write(static_cast< const char * >( buffer ), numberOfBytes); \
      }                                                                 \
    }

    // Swap bytes if necessary
    if itkWriteRawBytesAfterSwappingMacro(unsigned short, USHORT)
    else if itkWriteRawBytesAfterSwappingMacro(short, SHORT)
    else if itkWriteRawBytesAfterSwappingMacro(char, CHAR)
    else if itkWriteRawBytesAfterSwappingMacro(unsigned char, UCHAR)
    else if itkWriteRawBytesAfterSwappingMacro(unsigned int, UINT)
    else if itkWriteRawBytesAfterSwappingMacro(int, INT)
    else if itkWriteRawBytesAfterSwappingMacro(long, LONG)
    else if itkWriteRawBytesAfterSwappingMacro(unsigned long, ULONG)
    else if itkWriteRawBytesAfterSwappingMacro(float, FLOAT)
    else if itkWriteRawBytesAfterSwappingMacro(double, DOUBLE)
    }

  file.close();
}
} // namespace itk
#endif
<|endoftext|>


<commit_before>#ifndef stack_cpp
#define stack_cpp
#pragma once
#include <iostream>
using namespace std;
template<typename T>
auto newcopy( const T * item, size_t size, size_t count) -> T*
{
	T * buff = new T[size];
	copy(item, item + count, buff);
	return buff;
}
template <typename T>
class stack
{
public:
	stack();
	stack(stack const &);
	~stack();
	size_t count() const;
	auto push(T const &) -> void;
	T pop();
	auto operator=(stack const & right)->stack &;
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};
template <typename T>
size_t stack<T>::count() const
{
	return count_;
}
template <typename T>
stack<T>::stack():(array_ T[array_size_], array_size_(0), count_(0))
{

}

template<typename T>
stack<T>::stack(stack const & item):array_size_(item.array_size_), count_(item.count_),array_(newcopy(item.array_, item.array_size_,item.count_))
{

}

template <typename T>
stack<T>::~stack()
{
	delete[] array_;
}

template<typename T>
auto stack<T>::push(T const & item) -> void {
	if (count_ == array_size_) {
		size_t size = array_size_ * 2 + (array_size_ == 0) ;
		T * buff = newcopy(array_, size, array_size_);
		buff[count_] = size;
		delete[] array_;
		array_ = buff;
		array_size_ = size;
	}
	array_[count_] = item;
	++count_;
}

template<typename T>
T stack<T>::pop() {
	if (count_ == 0) {
		throw std::logic_error("Stack is empty!");
	}
	return array_[--count_];
}
template<typename T>
auto stack<T>::operator=(stack const & right) -> stack & {
	if (this != &right) {
	delete[] array_;
	count_ = right.count_;
	array_size_ = right.array_size_;
	newcopy(right.array_, array_size_, count_);
	}
	return *this;
}

#endif
<commit_msg>Update stack.cpp<commit_after>#ifndef stack_cpp
#define stack_cpp
#pragma once
#include <iostream>
using namespace std;
template<typename T>
auto newcopy( const T * item, size_t size, size_t count) -> T*
{
	T * buff = new T[size];
	copy(item, item + count, buff);
	return buff;
}
template <typename T>
class stack
{
public:
	stack();
	stack(stack const &);
	~stack();
	size_t count() const;
	auto push(T const &) -> void;
	T pop();
	auto operator=(stack const & right)->stack &;
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};
template <typename T>
size_t stack<T>::count() const
{
	return count_;
}
template <typename T>
stack<T>::stack():array_ (new T[array_size_]), array_size_(0), count_(0)
{

}

template<typename T>
stack<T>::stack(stack const & item):array_size_(item.array_size_), count_(item.count_),array_(newcopy(item.array_, item.array_size_,item.count_))
{

}

template <typename T>
stack<T>::~stack()
{
	delete[] array_;
}

template<typename T>
auto stack<T>::push(T const & item) -> void {
	if (count_ == array_size_) {
		size_t size = array_size_ * 2 + (array_size_ == 0) ;
		T * buff = newcopy(array_, size, array_size_);
		buff[count_] = size;
		delete[] array_;
		array_ = buff;
		array_size_ = size;
	}
	array_[count_] = item;
	++count_;
}

template<typename T>
T stack<T>::pop() {
	if (count_ == 0) {
		throw std::logic_error("Stack is empty!");
	}
	return array_[--count_];
}
template<typename T>
auto stack<T>::operator=(stack const & right) -> stack & {
	if (this != &right) {
	delete[] array_;
	count_ = right.count_;
	array_size_ = right.array_size_;
	newcopy(right.array_, array_size_, count_);
	}
	return *this;
}

#endif
<|endoftext|>


<commit_before>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "common/RhoPort.h"
#include "ruby/ext/rho/rhoruby.h"
#include "rubyext/WebView.h"
#include "common/RhodesApp.h"
#include "common/StringConverter.h"
#include "MainWindowImpl.h"

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "WebView"

using namespace rho;
using namespace rho::common;

static wchar_t *dup_wcs(const wchar_t *s)
{
    size_t len = wcslen(s);
    wchar_t *ret = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
    wcscpy(ret, s);
    return ret;
}

extern "C" {

void rho_webview_refresh(int index)
{
    CMainWindow::getInstance()->refreshCommand(index);
}

void rho_webview_navigate(const char* url, int index)
{
    if ( !url )
    {
        RAWLOG_ERROR("WebView.navigate failed: url is nil");
        return;
    }

    String strUrl = RHODESAPP().canonicalizeRhoUrl(url);

    TNavigateData* nd = (TNavigateData*)malloc(sizeof(TNavigateData));
    nd->index = index;
    nd->url = dup_wcs(convertToStringW(strUrl).c_str());
    CMainWindow::getInstance()->navigateCommand(nd);
}

void rho_webview_navigate_back()
{
    CMainWindow::getInstance()->navigateBackCommand();
}

void rho_webview_navigate_forward()
{
    CMainWindow::getInstance()->navigateForwardCommand();
}

const char* rho_webview_execute_js(const char* js, int index)
{
    String strJS = "javascript:";
    strJS += js;
    rho_webview_navigate(strJS.c_str(), index);
    return "";
}

const char* rho_webview_current_location(int index)
{
    return RHODESAPP().getCurrentUrl(index).c_str();
}

int rho_webview_active_tab()
{
    return CMainWindow::getInstance()->tabbarGetCurrent();
}

void rho_webview_set_menu_items(VALUE valMenu)
{
    rho_rhodesapp_setViewMenu(valMenu);
}

void rho_webview_full_screen_mode(int enable)
{
    CMainWindow::getInstance()->fullscreenCommand(enable);
}

void rho_webview_set_cookie(const char *url, const char *cookie)
{
    CMainWindow::getInstance()->setCookie(url, cookie);
}

void rho_webview_save(const char* format, const char* path, int tab_index)
{
    RAWLOG_ERROR("rho_webview_save is not implemented");
}

VALUE rho_webview_get_current_url(int tab_index)
{
    RAWLOG_ERROR("rho_webview_get_current_url is not implemented");
    return rho_ruby_get_NIL();
}

} //extern "C"
<commit_msg>rhosimulator/macosx: build fixed<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "common/RhoPort.h"
#include "ruby/ext/rho/rhoruby.h"
#include "rubyext/WebView.h"
#include "common/RhodesApp.h"
#include "common/StringConverter.h"
#include "MainWindowImpl.h"

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "WebView"

using namespace rho;
using namespace rho::common;

static wchar_t *dup_wcs(const wchar_t *s)
{
    size_t len = wcslen(s);
    wchar_t *ret = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
    wcscpy(ret, s);
    return ret;
}

extern "C" {

void rho_webview_refresh(int index)
{
    CMainWindow::getInstance()->refreshCommand(index);
}

void rho_webview_navigate(const char* url, int index)
{
    if ( !url )
    {
        RAWLOG_ERROR("WebView.navigate failed: url is nil");
        return;
    }

    String strUrl = RHODESAPP().canonicalizeRhoUrl(url);

    TNavigateData* nd = (TNavigateData*)malloc(sizeof(TNavigateData));
    nd->index = index;
    nd->url = dup_wcs(convertToStringW(strUrl).c_str());
    CMainWindow::getInstance()->navigateCommand(nd);
}

void rho_webview_navigate_back()
{
    CMainWindow::getInstance()->navigateBackCommand();
}

void rho_webview_navigate_forward()
{
    CMainWindow::getInstance()->navigateForwardCommand();
}

const char* rho_webview_execute_js(const char* js, int index)
{
    String strJS = "javascript:";
    strJS += js;
    rho_webview_navigate(strJS.c_str(), index);
    return "";
}

const char* rho_webview_current_location(int index)
{
    return RHODESAPP().getCurrentUrl(index).c_str();
}

int rho_webview_active_tab()
{
    return CMainWindow::getInstance()->tabbarGetCurrent();
}

void rho_webview_set_menu_items(VALUE valMenu)
{
    rho_rhodesapp_setViewMenu(valMenu);
}

void rho_webview_full_screen_mode(int enable)
{
    CMainWindow::getInstance()->fullscreenCommand(enable);
}

void rho_webview_set_cookie(const char *url, const char *cookie)
{
    CMainWindow::getInstance()->setCookie(url, cookie);
}

void rho_webview_save(const char* format, const char* path, int tab_index)
{
    RAWLOG_ERROR("rho_webview_save is not implemented");
}

const char* rho_webview_get_current_url(int tab_index)
{
    RAWLOG_ERROR("rho_webview_get_current_url is not implemented");
    return NULL;
}

} //extern "C"
<|endoftext|>