<commit_before>//*****************************************************************************
// Copyright 2017-2018 Intel Corporation
//
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************

#include <cstring>

#include "ngraph/runtime/gpu/gpu_memory_manager.hpp"
#include "ngraph/runtime/gpu/gpu_primitive_emitter.hpp"
#include "ngraph/runtime/gpu/gpu_util.hpp"

using namespace ngraph;

constexpr const uint32_t initial_buffer_size = 10 * 1024 * 1024;

runtime::gpu::GPUMemoryManager::GPUMemoryManager(GPUPrimitiveEmitter* emitter)
    : m_buffer_offset(0)
    , m_buffered_mem(initial_buffer_size)
    , m_workspace_manager(new pass::MemoryManager(runtime::gpu::GPUMemoryManager::alignment))
    , m_argspace_mem(1, {nullptr, 0})
    , m_workspace_mem(1, {nullptr, 0})
    , m_primitive_emitter(emitter)
{
}

size_t runtime::gpu::GPUMemoryManager::get_allocation_size() const
{
    size_t allocation_size = 0;
    for (auto const& alloc : m_argspace_mem)
    {
        allocation_size += alloc.size;
    }
    for (auto const& alloc : m_workspace_mem)
    {
        allocation_size += alloc.size;
    }
    return allocation_size;
}

runtime::gpu::GPUMemoryManager::~GPUMemoryManager()
{
    for (auto& alloc : m_argspace_mem)
    {
        runtime::gpu::free_gpu_buffer(alloc.ptr);
    }
    for (auto& alloc : m_workspace_mem)
    {
        runtime::gpu::free_gpu_buffer(alloc.ptr);
    }
}

void runtime::gpu::GPUMemoryManager::allocate()
{
    if (m_workspace_manager->get_node_list().size() != 1)
    {
        throw std::runtime_error(
            "Attempt to allocate memory while reservations are inprogress. Ensure all "
            "GPUAllocators are closed before allocating.");
    }
    if (m_buffer_offset)
    {
        m_buffer_offset = ngraph::pass::MemoryManager::align(
            m_buffer_offset, runtime::gpu::GPUMemoryManager::alignment);
        // the back most node is always empty, fill it here
        m_argspace_mem.back().ptr = runtime::gpu::create_gpu_buffer(m_buffer_offset);
        m_argspace_mem.back().size = m_buffer_offset;
        // copy buffered kernel arguments to device
        runtime::gpu::cuda_memcpyHtD(
            m_argspace_mem.back().ptr, m_buffered_mem.data(), m_buffer_offset);
        // add an empty node to the end of the list and zero offset
        m_argspace_mem.push_back({nullptr, 0});
        m_buffer_offset = 0;
    }

    auto workspace_size = m_workspace_manager->max_allocated();
    if (workspace_size)
    {
        m_workspace_mem.back().ptr = runtime::gpu::create_gpu_buffer(workspace_size);
        m_workspace_mem.back().size = workspace_size;
        m_workspace_mem.push_back({nullptr, 0});
        m_workspace_manager.reset(
            new pass::MemoryManager(runtime::gpu::GPUMemoryManager::alignment));
    }
}

size_t runtime::gpu::GPUMemoryManager::queue_for_transfer(const void* data, size_t size)
{
    // if the current allocation will overflow the host buffer
    if (m_buffer_offset + size > m_buffered_mem.size())
    {
        // add more space to the managed buffer
        size_t new_size = m_buffered_mem.size() / initial_buffer_size + 1;
        m_buffered_mem.resize(new_size);
    }

    size_t offset = m_buffer_offset;
    std::memcpy(m_buffered_mem.data() + offset, data, size);
    m_buffer_offset += size;

    return offset;
}

runtime::gpu::GPUAllocator::GPUAllocator(GPUMemoryManager* mgr)
    : m_manager(mgr)
{
}

runtime::gpu::GPUAllocator::GPUAllocator(const GPUAllocator& g)
{
    m_manager = g.m_manager;
    m_active = g.m_active;
}

size_t runtime::gpu::GPUAllocator::reserve_argspace(const void* data, size_t size)
{
    // add parameter data to host buffer that will be transfered to device
    size = ngraph::pass::MemoryManager::align(size, runtime::gpu::GPUMemoryManager::alignment);
    size_t offset = m_manager->queue_for_transfer(data, size);
    auto local = std::prev(m_manager->m_argspace_mem.end());
    // return a lambda that will yield the gpu memory address. this
    // should only be evaluated by the runtime invoked primitive
    gpu::memory_primitive mem_primitive = [=]() {
        void* argspace = (*local).ptr;
        if (argspace == nullptr)
        {
            throw std::runtime_error("An attempt was made to use unallocated device memory.");
        }
        auto gpu_mem = static_cast<uint8_t*>(argspace);
        return static_cast<void*>(gpu_mem + offset);
    };
    return m_manager->m_primitive_emitter->insert(mem_primitive);
}

size_t runtime::gpu::GPUAllocator::reserve_workspace(size_t size, bool zero_initialize)
{
    size_t offset = m_manager->m_workspace_manager->allocate(size);
    m_active.push(offset);
    auto local = std::prev(m_manager->m_workspace_mem.end());
    // return a lambda that will yield the gpu memory address. this
    // should only be evaluated by the runtime invoked primitive
    gpu::memory_primitive mem_primitive = [=]() {
        void* workspace = (*local).ptr;
        if (workspace == nullptr)
        {
            throw std::runtime_error("An attempt was made to use unallocated device memory.");
        }
        auto gpu_mem = static_cast<uint8_t*>(workspace);
        auto workspace_ptr = static_cast<void*>(gpu_mem + offset);
        if (zero_initialize)
        {
            runtime::gpu::cuda_memset(workspace_ptr, 0, size);
        }
        return workspace_ptr;
    };
    return m_manager->m_primitive_emitter->insert(mem_primitive);
}

void runtime::gpu::GPUAllocator::close()
{
    while (!m_active.empty())
    {
        m_manager->m_workspace_manager->free(m_active.top());
        m_active.pop();
    }
}
runtime::gpu::GPUAllocator::~GPUAllocator()
{
    this->close();
}
<commit_msg>fix resize bug (#1745)<commit_after>//*****************************************************************************
// Copyright 2017-2018 Intel Corporation
//
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************

#include <cstring>

#include "ngraph/runtime/gpu/gpu_memory_manager.hpp"
#include "ngraph/runtime/gpu/gpu_primitive_emitter.hpp"
#include "ngraph/runtime/gpu/gpu_util.hpp"

using namespace ngraph;

constexpr const uint32_t initial_buffer_size = 10 * 1024 * 1024;

runtime::gpu::GPUMemoryManager::GPUMemoryManager(GPUPrimitiveEmitter* emitter)
    : m_buffer_offset(0)
    , m_buffered_mem(initial_buffer_size)
    , m_workspace_manager(new pass::MemoryManager(runtime::gpu::GPUMemoryManager::alignment))
    , m_argspace_mem(1, {nullptr, 0})
    , m_workspace_mem(1, {nullptr, 0})
    , m_primitive_emitter(emitter)
{
}

size_t runtime::gpu::GPUMemoryManager::get_allocation_size() const
{
    size_t allocation_size = 0;
    for (auto const& alloc : m_argspace_mem)
    {
        allocation_size += alloc.size;
    }
    for (auto const& alloc : m_workspace_mem)
    {
        allocation_size += alloc.size;
    }
    return allocation_size;
}

runtime::gpu::GPUMemoryManager::~GPUMemoryManager()
{
    for (auto& alloc : m_argspace_mem)
    {
        runtime::gpu::free_gpu_buffer(alloc.ptr);
    }
    for (auto& alloc : m_workspace_mem)
    {
        runtime::gpu::free_gpu_buffer(alloc.ptr);
    }
}

void runtime::gpu::GPUMemoryManager::allocate()
{
    if (m_workspace_manager->get_node_list().size() != 1)
    {
        throw std::runtime_error(
            "Attempt to allocate memory while reservations are inprogress. Ensure all "
            "GPUAllocators are closed before allocating.");
    }
    if (m_buffer_offset)
    {
        m_buffer_offset = ngraph::pass::MemoryManager::align(
            m_buffer_offset, runtime::gpu::GPUMemoryManager::alignment);
        // the back most node is always empty, fill it here
        m_argspace_mem.back().ptr = runtime::gpu::create_gpu_buffer(m_buffer_offset);
        m_argspace_mem.back().size = m_buffer_offset;
        // copy buffered kernel arguments to device
        runtime::gpu::cuda_memcpyHtD(
            m_argspace_mem.back().ptr, m_buffered_mem.data(), m_buffer_offset);
        // add an empty node to the end of the list and zero offset
        m_argspace_mem.push_back({nullptr, 0});
        m_buffer_offset = 0;
    }

    auto workspace_size = m_workspace_manager->max_allocated();
    if (workspace_size)
    {
        m_workspace_mem.back().ptr = runtime::gpu::create_gpu_buffer(workspace_size);
        m_workspace_mem.back().size = workspace_size;
        m_workspace_mem.push_back({nullptr, 0});
        m_workspace_manager.reset(
            new pass::MemoryManager(runtime::gpu::GPUMemoryManager::alignment));
    }
}

size_t runtime::gpu::GPUMemoryManager::queue_for_transfer(const void* data, size_t size)
{
    // if the current allocation will overflow the host buffer
    size_t new_size = m_buffer_offset + size;
    size_t buffer_size = m_buffered_mem.size();
    bool need_resize = false;
    while (buffer_size < new_size)
    {
        // add more space to the managed buffer
        buffer_size <<= 1;
        need_resize = true;
    }

    if (need_resize)
    {
        m_buffered_mem.resize(buffer_size);
    }

    size_t offset = m_buffer_offset;
    std::memcpy(m_buffered_mem.data() + offset, data, size);
    m_buffer_offset += size;

    return offset;
}

runtime::gpu::GPUAllocator::GPUAllocator(GPUMemoryManager* mgr)
    : m_manager(mgr)
{
}

runtime::gpu::GPUAllocator::GPUAllocator(const GPUAllocator& g)
{
    m_manager = g.m_manager;
    m_active = g.m_active;
}

size_t runtime::gpu::GPUAllocator::reserve_argspace(const void* data, size_t size)
{
    // add parameter data to host buffer that will be transfered to device
    size = ngraph::pass::MemoryManager::align(size, runtime::gpu::GPUMemoryManager::alignment);
    size_t offset = m_manager->queue_for_transfer(data, size);
    auto local = std::prev(m_manager->m_argspace_mem.end());
    // return a lambda that will yield the gpu memory address. this
    // should only be evaluated by the runtime invoked primitive
    gpu::memory_primitive mem_primitive = [=]() {
        void* argspace = (*local).ptr;
        if (argspace == nullptr)
        {
            throw std::runtime_error("An attempt was made to use unallocated device memory.");
        }
        auto gpu_mem = static_cast<uint8_t*>(argspace);
        return static_cast<void*>(gpu_mem + offset);
    };
    return m_manager->m_primitive_emitter->insert(mem_primitive);
}

size_t runtime::gpu::GPUAllocator::reserve_workspace(size_t size, bool zero_initialize)
{
    size_t offset = m_manager->m_workspace_manager->allocate(size);
    m_active.push(offset);
    auto local = std::prev(m_manager->m_workspace_mem.end());
    // return a lambda that will yield the gpu memory address. this
    // should only be evaluated by the runtime invoked primitive
    gpu::memory_primitive mem_primitive = [=]() {
        void* workspace = (*local).ptr;
        if (workspace == nullptr)
        {
            throw std::runtime_error("An attempt was made to use unallocated device memory.");
        }
        auto gpu_mem = static_cast<uint8_t*>(workspace);
        auto workspace_ptr = static_cast<void*>(gpu_mem + offset);
        if (zero_initialize)
        {
            runtime::gpu::cuda_memset(workspace_ptr, 0, size);
        }
        return workspace_ptr;
    };
    return m_manager->m_primitive_emitter->insert(mem_primitive);
}

void runtime::gpu::GPUAllocator::close()
{
    while (!m_active.empty())
    {
        m_manager->m_workspace_manager->free(m_active.top());
        m_active.pop();
    }
}
runtime::gpu::GPUAllocator::~GPUAllocator()
{
    this->close();
}
<|endoftext|>


<commit_before><commit_msg>remove itself from parent when deleted.  In most case, this won't happen because  the parent view sets child view's parent to  NULL before deletion. This is necessary to safely  delete view that is not owned by parent.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2016 timercrack
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "MdSpi.h"
#include "global.h"

using namespace std;

void CMdSpi::OnRspError(CThostFtdcRspInfoField *pRspInfo,
                        int nRequestID, bool bIsLast) {
    Json::Value root;
    root["nRequestID"] = nRequestID;
    root["bIsLast"] = bIsLast;
    root["ErrorID"] = pRspInfo->ErrorID;
    publisher.publish(CHANNEL_MARKET_DATA+"OnRspError:" + ntos(nRequestID), writer.write(root));
}

void CMdSpi::OnFrontDisconnected(int nReason) {
    publisher.publish(CHANNEL_MARKET_DATA + "OnFrontDisconnected", ntos(nReason));
    market_login = false;
}

void CMdSpi::OnHeartBeatWarning(int nTimeLapse) {
    publisher.publish(CHANNEL_MARKET_DATA + "OnHeartBeatWarning", ntos(nTimeLapse));
}

void CMdSpi::OnFrontConnected() {
    publisher.publish(CHANNEL_MARKET_DATA + "OnFrontConnected", "OnFrontConnected");
}

void CMdSpi::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin,
                            CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
    Json::Value root;
    root["nRequestID"] = nRequestID;
    root["bIsLast"] = bIsLast;
    root["ErrorID"] = 0;

    if (pRspInfo && pRspInfo->ErrorID != 0) {
        root["ErrorID"] = pRspInfo->ErrorID;
    } else {
        root["TradingDay"] = pRspUserLogin->TradingDay;
        root["LoginTime"] = pRspUserLogin->LoginTime;
        root["BrokerID"] = pRspUserLogin->BrokerID;
        root["UserID"] = pRspUserLogin->UserID;
        root["SystemName"] = pRspUserLogin->SystemName;
        root["FrontID"] = pRspUserLogin->FrontID;
        root["SessionID"] = pRspUserLogin->SessionID;
        root["MaxOrderRef"] = pRspUserLogin->MaxOrderRef;
        root["SHFETime"] = pRspUserLogin->SHFETime;
        root["DCETime"] = pRspUserLogin->DCETime;
        root["CZCETime"] = pRspUserLogin->CZCETime;
        root["FFEXTime"] = pRspUserLogin->FFEXTime;
        root["INETime"] = pRspUserLogin->INETime;
        market_login = true;
    }
    publisher.publish(CHANNEL_MARKET_DATA + "OnRspUserLogin", writer.write(root));
}

void CMdSpi::OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument,
                                CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
    Json::Value root;
    root["nRequestID"] = nRequestID;
    root["bIsLast"] = bIsLast;
    root["ErrorID"] = 0;
    if (pRspInfo && pRspInfo->ErrorID != 0) {
        root["ErrorID"] = pRspInfo->ErrorID;
    } else {
        root["InstrumentID"] = "InstrumentID", pSpecificInstrument->InstrumentID;
    }
    publisher.publish(CHANNEL_MARKET_DATA + "OnRspSubMarketData", writer.write(root));
}

void CMdSpi::OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument,
                                  CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
    Json::Value root;
    root["nRequestID"] = nRequestID;
    root["bIsLast"] = bIsLast;
    root["ErrorID"] = 0;
    if (pRspInfo && pRspInfo->ErrorID != 0) {
        root["ErrorID"] = pRspInfo->ErrorID;
    } else {
        root["InstrumentID"] = "InstrumentID", pSpecificInstrument->InstrumentID;
    }
    publisher.publish(CHANNEL_MARKET_DATA + "OnRspUnSubMarketData", writer.write(root));
}

void CMdSpi::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pData) {
    Json::Value root;
    root["TradingDay"] = pData->TradingDay;
    root["InstrumentID"] = pData->InstrumentID;
    root["ExchangeID"] = pData->ExchangeID;
    root["ExchangeInstID"] = pData->ExchangeInstID;
    root["LastPrice"] = pData->LastPrice;
    root["PreSettlementPrice"] = pData->PreSettlementPrice;
    root["PreClosePrice"] = pData->PreClosePrice;
    root["PreOpenInterest"] = pData->PreOpenInterest;
    root["OpenPrice"] = pData->OpenPrice;
    root["HighestPrice"] = pData->HighestPrice;
    root["LowestPrice"] = pData->LowestPrice;
    root["Volume"] = pData->Volume;
    root["Turnover"] = pData->Turnover;
    root["OpenInterest"] = pData->OpenInterest;
    root["ClosePrice"] = pData->ClosePrice;
    root["SettlementPrice"] = pData->SettlementPrice;
    root["UpperLimitPrice"] = pData->UpperLimitPrice;
    root["LowerLimitPrice"] = pData->LowerLimitPrice;
    root["PreDelta"] = pData->PreDelta;
    root["CurrDelta"] = pData->CurrDelta;
    root["UpdateMillisec"] = pData->UpdateMillisec;
    root["BidPrice1"] = pData->BidPrice1;
    root["BidVolume1"] = pData->BidVolume1;
    root["AskPrice1"] = pData->AskPrice1;
    root["AskVolume1"] = pData->AskVolume1;
    root["BidPrice2"] = pData->BidPrice2;
    root["BidVolume2"] = pData->BidVolume2;
    root["AskPrice2"] = pData->AskPrice2;
    root["AskVolume2"] = pData->AskVolume2;
    root["BidPrice3"] = pData->BidPrice3;
    root["BidVolume3"] = pData->BidVolume3;
    root["AskPrice3"] = pData->AskPrice3;
    root["AskVolume3"] = pData->AskVolume3;
    root["BidPrice4"] = pData->BidPrice4;
    root["BidVolume4"] = pData->BidVolume4;
    root["AskPrice4"] = pData->AskPrice4;
    root["AskVolume4"] = pData->AskVolume4;
    root["BidPrice5"] = pData->BidPrice5;
    root["BidVolume5"] = pData->BidVolume5;
    root["AskPrice5"] = pData->AskPrice5;
    root["AskVolume5"] = pData->AskVolume5;
    root["AveragePrice"] = pData->AveragePrice;
    root["ActionDay"] = pData->ActionDay;
    publisher.publish(CHANNEL_MARKET_DATA + "OnRtnDepthMarketData", writer.write(root));
}
<commit_msg>add request id<commit_after>/*
 * Copyright 2016 timercrack
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "MdSpi.h"
#include "global.h"

using namespace std;

void CMdSpi::OnRspError(CThostFtdcRspInfoField *pRspInfo,
                        int nRequestID, bool bIsLast) {
    Json::Value root;
    root["nRequestID"] = nRequestID;
    root["bIsLast"] = bIsLast;
    root["ErrorID"] = pRspInfo->ErrorID;
    publisher.publish(CHANNEL_MARKET_DATA + "OnRspError:" + ntos(nRequestID), writer.write(root));
}

void CMdSpi::OnFrontDisconnected(int nReason) {
    publisher.publish(CHANNEL_MARKET_DATA + "OnFrontDisconnected", ntos(nReason));
    market_login = false;
}

void CMdSpi::OnHeartBeatWarning(int nTimeLapse) {
    publisher.publish(CHANNEL_MARKET_DATA + "OnHeartBeatWarning", ntos(nTimeLapse));
}

void CMdSpi::OnFrontConnected() {
    publisher.publish(CHANNEL_MARKET_DATA + "OnFrontConnected", "OnFrontConnected");
}

void CMdSpi::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin,
                            CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
    Json::Value root;
    root["nRequestID"] = nRequestID;
    root["bIsLast"] = bIsLast;
    root["ErrorID"] = 0;

    if (pRspInfo && pRspInfo->ErrorID != 0) {
        root["ErrorID"] = pRspInfo->ErrorID;
    } else {
        root["TradingDay"] = pRspUserLogin->TradingDay;
        root["LoginTime"] = pRspUserLogin->LoginTime;
        root["BrokerID"] = pRspUserLogin->BrokerID;
        root["UserID"] = pRspUserLogin->UserID;
        root["SystemName"] = pRspUserLogin->SystemName;
        root["FrontID"] = pRspUserLogin->FrontID;
        root["SessionID"] = pRspUserLogin->SessionID;
        root["MaxOrderRef"] = pRspUserLogin->MaxOrderRef;
        root["SHFETime"] = pRspUserLogin->SHFETime;
        root["DCETime"] = pRspUserLogin->DCETime;
        root["CZCETime"] = pRspUserLogin->CZCETime;
        root["FFEXTime"] = pRspUserLogin->FFEXTime;
        root["INETime"] = pRspUserLogin->INETime;
        market_login = true;
    }
    publisher.publish(CHANNEL_MARKET_DATA + "OnRspUserLogin", writer.write(root));
}

void CMdSpi::OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument,
                                CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
    Json::Value root;
    root["nRequestID"] = nRequestID;
    root["bIsLast"] = bIsLast;
    root["ErrorID"] = 0;
    if (pRspInfo && pRspInfo->ErrorID != 0) {
        root["ErrorID"] = pRspInfo->ErrorID;
    } else {
        root["InstrumentID"] = "InstrumentID", pSpecificInstrument->InstrumentID;
    }
    publisher.publish(CHANNEL_MARKET_DATA + "OnRspSubMarketData:" + ntos(nRequestID), writer.write(root));
}

void CMdSpi::OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument,
                                  CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
    Json::Value root;
    root["nRequestID"] = nRequestID;
    root["bIsLast"] = bIsLast;
    root["ErrorID"] = 0;
    if (pRspInfo && pRspInfo->ErrorID != 0) {
        root["ErrorID"] = pRspInfo->ErrorID;
    } else {
        root["InstrumentID"] = "InstrumentID", pSpecificInstrument->InstrumentID;
    }
    publisher.publish(CHANNEL_MARKET_DATA + "OnRspUnSubMarketData:" + ntos(nRequestID), writer.write(root));
}

void CMdSpi::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pData) {
    Json::Value root;
    root["TradingDay"] = pData->TradingDay;
    root["InstrumentID"] = pData->InstrumentID;
    root["ExchangeID"] = pData->ExchangeID;
    root["ExchangeInstID"] = pData->ExchangeInstID;
    root["LastPrice"] = pData->LastPrice;
    root["PreSettlementPrice"] = pData->PreSettlementPrice;
    root["PreClosePrice"] = pData->PreClosePrice;
    root["PreOpenInterest"] = pData->PreOpenInterest;
    root["OpenPrice"] = pData->OpenPrice;
    root["HighestPrice"] = pData->HighestPrice;
    root["LowestPrice"] = pData->LowestPrice;
    root["Volume"] = pData->Volume;
    root["Turnover"] = pData->Turnover;
    root["OpenInterest"] = pData->OpenInterest;
    root["ClosePrice"] = pData->ClosePrice;
    root["SettlementPrice"] = pData->SettlementPrice;
    root["UpperLimitPrice"] = pData->UpperLimitPrice;
    root["LowerLimitPrice"] = pData->LowerLimitPrice;
    root["PreDelta"] = pData->PreDelta;
    root["CurrDelta"] = pData->CurrDelta;
    root["UpdateMillisec"] = pData->UpdateMillisec;
    root["BidPrice1"] = pData->BidPrice1;
    root["BidVolume1"] = pData->BidVolume1;
    root["AskPrice1"] = pData->AskPrice1;
    root["AskVolume1"] = pData->AskVolume1;
    root["BidPrice2"] = pData->BidPrice2;
    root["BidVolume2"] = pData->BidVolume2;
    root["AskPrice2"] = pData->AskPrice2;
    root["AskVolume2"] = pData->AskVolume2;
    root["BidPrice3"] = pData->BidPrice3;
    root["BidVolume3"] = pData->BidVolume3;
    root["AskPrice3"] = pData->AskPrice3;
    root["AskVolume3"] = pData->AskVolume3;
    root["BidPrice4"] = pData->BidPrice4;
    root["BidVolume4"] = pData->BidVolume4;
    root["AskPrice4"] = pData->AskPrice4;
    root["AskVolume4"] = pData->AskVolume4;
    root["BidPrice5"] = pData->BidPrice5;
    root["BidVolume5"] = pData->BidVolume5;
    root["AskPrice5"] = pData->AskPrice5;
    root["AskVolume5"] = pData->AskVolume5;
    root["AveragePrice"] = pData->AveragePrice;
    root["ActionDay"] = pData->ActionDay;
    publisher.publish(CHANNEL_MARKET_DATA + "OnRtnDepthMarketData:" + root["InstrumentID"].asString(),
                      writer.write(root));
}
<|endoftext|>


<commit_before>#pragma once
#include "./mozart/function.hpp"
#include "./mozart/switcher.hpp"
#include "./mozart/tuple.hpp"
#include "./mozart/any.hpp"
#include <stdexcept>
#include <cstdio>
#include <string>
#include <deque>
#include <list>
namespace cov_basic {
	enum class signs {
		Null,And,Or,Not,Above,Under,
		Equ,NotEqu,AboveEqu,UnderEqu
	};
	using number=long double;
	using boolean=bool;
	using string=std::string;
	class function {
		std::deque<string> mArgs;
		std::deque<string> mBuf;
	public:
		number* retval=nullptr;
		function()=delete;
		function(const std::deque<string>& args,const std::deque<string>& buf):mArgs(args),mBuf(buf) {}
		~function()=default;
		number call(const std::deque<cov::any>&);
		bool operator==(const function& f) const
		{
			return this==&f;
		}
	};
	class native_interface {
		cov::function<number(const std::deque<cov::any>&)> mFunc;
	public:
		native_interface()=delete;
		native_interface(const cov::function<number(const std::deque<cov::any>&)>& func):mFunc(func) {}
		~native_interface()=default;
		number call(const std::deque<cov::any>& args)
		{
			return mFunc(args);
		}
		bool operator==(const native_interface& n) const
		{
			return this==&n;
		}
	};
	class domain_manager {
		std::list<std::list<cov::tuple<string,cov::any>>> m_data;
	public:
		domain_manager()
		{
			m_data.emplace_front();
		}
		domain_manager(const domain_manager&)=delete;
		~domain_manager()=default;
		void add_domain()
		{
			m_data.emplace_front();
		}
		void remove_domain()
		{
			if(m_data.size()>1)
				m_data.pop_front();
		}
		bool var_exsist(const string& name)
		{
			for(auto& domain:m_data)
				for(auto& var:domain)
					if(var.get<0>()==name)
						return true;
			return false;
		}
		bool var_exsist_global(const string& name)
		{
			for(auto& var:m_data.back())
				if(var.get<0>()==name)
					return true;
			return false;
		}
		cov::any& get_var(const string& name)
		{
			for(auto& domain:m_data)
				for(auto& var:domain)
					if(var.get<0>()==name)
						return var.get<1>();
			throw std::logic_error("Use of undefined variable.");
		}
		cov::any& get_var_global(const string& name)
		{
			for(auto& var:m_data.back())
				if(var.get<0>()==name)
					return var.get<1>();
			throw std::logic_error("Use of undefined variable.");
		}
		void add_var(const string& name,const cov::any& var)
		{
			if(var_exsist(name))
				get_var(name)=var;
			else
				m_data.front().push_front({name,var});
		}
		void add_var_global(const string& name,const cov::any& var)
		{
			if(var_exsist(name))
				get_var_global(name)=var;
			else
				m_data.back().push_front({name,var});
		}
	};
	static domain_manager storage;
	void split_str(char signal,const string& str,std::deque<string>& data)
	{
		string tmp;
		bool is_str=false;
		for(auto& c:str) {
			if(c=='\"'){
				is_str=is_str?false:true;
				tmp+=c;
				continue;
			}
			if(is_str){
				tmp+=c;
				continue;
			}
			if(c==signal) {
				if(!tmp.empty()) {
					data.push_back(tmp);
					tmp.clear();
				}
				continue;
			}
			tmp+=c;
		}
		if(!tmp.empty())
			data.push_back(tmp);
	}
	signs match_signal(const string& str)
	{
		signs ret;
		Switch(str) {
			Default {
				ret=signs::Null;
			} EndCase;
			Case("&&") {
				ret=signs::And;
			}
			EndCase;
			Case("||") {
				ret=signs::Or;
			}
			EndCase;
			Case("!") {
				ret=signs::Not;
			}
			EndCase;
			Case(">") {
				ret=signs::Above;
			}
			EndCase;
			Case("<") {
				ret=signs::Under;
			}
			EndCase;
			Case("==") {
				ret=signs::Equ;
			}
			EndCase;
			Case("!=") {
				ret=signs::NotEqu;
			}
			EndCase;
			Case(">=") {
				ret=signs::AboveEqu;
			}
			EndCase;
			Case("<=") {
				ret=signs::UnderEqu;
			}
			EndCase;
		}
		EndSwitch;
		return ret;
	}
	bool is_signal(char signal)
	{
		switch(signal) {
		case '>':
			break;
		case '<':
			break;
		case '=':
			break;
		case '!':
			break;
		case '&':
			break;
		case '|':
			break;
		default:
			return false;
		}
		return true;
	}
	bool is_bool_exp(const string& str)
	{
		for(auto& ch:str) {
			if(is_signal(ch))
				return true;
		}
		return false;
	}
	cov::any& get_value(const string& name)
	{
		auto pos=name.find("::");
		if(pos!=string::npos&&name.substr(0,pos)=="global") {
			string n=name.substr(pos+2);
			if(storage.var_exsist_global(n))
				return storage.get_var_global(n);
		}
		return storage.get_var(name);
	}
	bool exsist(const string& name)
	{
		auto pos=name.find("::");
		if(pos!=string::npos&&name.substr(0,pos)=="global") {
			string n=name.substr(pos+2);
			return storage.var_exsist_global(n);
		}
		return storage.var_exsist(name);
	}
	bool compute_boolean(const string&);
	number compute_number(const string&);
	cov::any infer_value(const string& str)
	{
		if(exsist(str))
			return get_value(str);
		if(str.find('\"')!=string::npos)
			return str.substr(str.find('\"')+1,str.rfind('\"')-str.find('\"')-1);
		if(str=="True")
			return true;
		if(str=="False")
			return false;
		if(is_bool_exp(str))
			return compute_boolean(str);
		else
			return compute_number(str);
	}
	bool compute_boolean(const string & exp)
	{
		bool reverse = false;
		bool is_str = false;
		std::deque < signs > signals;
		std::deque < string > conditions;
		string tmp;
		for (int i = 0; i < exp.size();) {
			if (std::isspace(exp[i])&&!is_str) {
				++i;
				continue;
			}
			if(exp[i]=='\"')
				is_str=is_str?false:true;
			/*if (exp[i] == '(') {
				int level(1), pos(++i);
				for (; pos < exp.size() && level > 0; ++pos) {
					if (exp[pos] == '(')
						++level;
					if (exp[pos] == ')')
						--level;
				}
				if (level > 0)
					throw std::logic_error("The lack of corresponding brackets.");
				if(compute_boolean(exp.substr(i, pos - i - 1))?(reverse?false:true):(reverse?true:false))
					conditions.push_back("True");
				else
					conditions.push_back("False");
				reverse=false;
				i = pos;
				continue;
			}*/
			if (is_signal(exp[i])&&(i<exp.size()?(is_signal(exp[i+1])?true:exp[i]!='!'):exp[i]!='!')) {
				if(!tmp.empty())
					conditions.push_back(tmp);
				tmp.clear();
				string currentSignal(1,exp[i]);
				if(i<exp.size()) {
					if(is_signal(exp[++i]))
						currentSignal+=exp[i];
					else
						tmp+=exp[i];
				}
				signals.push_back(match_signal(currentSignal));
				++i;
				continue;
			}
			if(i<exp.size()&&exp[i]=='!'&&exp[i+1]=='(') {
				reverse=true;
				++i;
				continue;
			}
			tmp+=exp[i];
			++i;
		}
		if(!tmp.empty())
			conditions.push_back(tmp);
		cov::any val;
		auto parse=[](const string& str) {
			cov::any value;
			if(str[0]=='!') {
				value=infer_value(str.substr(1));
				if(value.type()!=typeid(bool))
					throw std::logic_error("DE0003");
				value=value.val<bool>()?false:true;
			} else
				value=infer_value(str);
			return value;
		};
		val=parse(conditions.front());
		conditions.pop_front();
		for(auto &it:conditions) {
			cov::any v=parse(it);
			switch(signals.front()) {
			case signs::And:
				val=(v.val<bool>()&&val.val<bool>());
				break;
			case signs::Or:
				val=(v.val<bool>()||val.val<bool>());
				break;
			case signs::Above:
				if(val.type()==v.type()) {
					if(val.type()==typeid(number)) {
						val=(val.val<number>()>v.val<number>());
						break;
					}
				}
				throw std::logic_error("DE0003");
				break;
			case signs::Under:
				if(val.type()==v.type()) {
					if(val.type()==typeid(number)) {
						val=(val.val<number>()<v.val<number>());
						break;
					}
				}
				throw std::logic_error("DE0003");
				break;
			case signs::Equ:
				val=(val==v);
				break;
			case signs::NotEqu:
				val=(val!=v);
				break;
			case signs::AboveEqu:
				if(val.type()==v.type()) {
					if(val.type()==typeid(number)) {
						val=(val.val<number>()>=v.val<number>());
						break;
					}
				}
				throw std::logic_error("DE0003");
				break;
			case signs::UnderEqu:
				if(val.type()==v.type()) {
					if(val.type()==typeid(number)) {
						val=(val.val<number>()<=v.val<number>());
						break;
					}
				}
				throw std::logic_error("DE0003");
				break;
			}
			signals.pop_front();
		}
		return val.val<bool>();
	}
	number compute_number(const string& exp)
	{
		bool reverse = false;
		std::deque<number> nums;
		std::deque<char>operators;
		string tmp;
		for (int i = 0; i < exp.size();) {
			if (std::isspace(exp[i])) {
				++i;
				continue;
			}
			if (exp[i] == '(') {
				int level(1), pos(++i);
				for (; pos < exp.size() && level > 0; ++pos) {
					if (exp[pos] == '(')
						++level;
					if (exp[pos] == ')')
						--level;
				}
				if (level > 0)
					throw std::logic_error("The lack of corresponding brackets.");
				nums.push_back(compute_number(exp.substr(i, pos - i - 1)));
				i = pos;
				continue;
			}
			if (std::ispunct(exp[i])&&exp[i]!=':') {
				if (nums.empty()) {
					switch (exp[i]) {
					case '+':
						reverse = false;
						break;
					case '-':
						reverse = true;
						break;
					default:
						throw std::logic_error("Operator does not recognize.~~~");
					}
					++i;
					continue;
				}
				operators.push_back(exp[i]);
				++i;
				continue;
			}
			if (std::isdigit(exp[i]) || exp[i] == '.') {
				tmp.clear();
				for (; i < exp.size() && (isdigit(exp[i]) || exp[i] == '.'); ++i)
					tmp += exp[i];
				nums.push_back(std::stof(tmp));
				continue;
			}
			if (std::isalpha(exp[i]) || exp[i]==':') {
				tmp.clear();
				for (; i < exp.size() && (std::isalnum(exp[i]) || exp[i] == '_' || exp[i]==':'); ++i)
					tmp += exp[i];
				cov::any& obj=get_value(tmp);
				if (obj.type()==typeid(function)||obj.type()==typeid(native_interface)) {
					int level(1), pos(++i);
					for (; pos < exp.size() && level > 0; ++pos) {
						if (exp[pos] == '(')
							++level;
						if (exp[pos] == ')')
							--level;
					}
					if (level > 0)
						throw std::logic_error("The lack of corresponding brackets.");
					std::deque <cov::any> args;
					if(pos-i>1) {
						string arglist = exp.substr(i, pos - i - 1);
						string temp;
						bool is_str=false;
						for (int i = 0; i < arglist.size(); ++i) {
							if(arglist[i]=='(')
								++level;
							if(arglist[i]==')')
								--level;
							if(arglist[i]=='\"')
								is_str=is_str?false:true;
							if (is_str || level>0 || arglist[i] != ',') {
								temp += arglist[i];
							} else {
								args.push_back(infer_value(temp));
								temp.clear();
							}
						}
						args.push_back(infer_value(temp));
					}
					Switch(obj.type()) {
						Case(typeid(function)) {
							nums.push_back(obj.val<function>().call(args));
						}
						EndCase;
						Case(typeid(native_interface)) {
							nums.push_back(obj.val<native_interface>().call(args));
						}
						EndCase;
					}
					EndSwitch;
					i = pos;
					continue;
				}
				nums.push_back(infer_value(tmp).val<number>());
				continue;
			}
			throw std::logic_error("Operator does not recognize.-----");
		}
		if (nums.empty())
			return -1;
		number left = nums.front();
		number right = 0;
		char signal = 0;
		nums.pop_front();
		for (auto & current:nums) {
			switch (operators.front()) {
			case '+': {
				if (right != 0) {
					switch (signal) {
					case '+':
						left += right;
						break;
					case '-':
						left -= right;
						break;
					}
				}
				right = current;
				signal = '+';
				break;
			}
			case '-': {
				if (right != 0) {
					switch (signal) {
					case '+':
						left += right;
						break;
					case '-':
						left -= right;
						break;
					}
				}
				right = current;
				signal = '-';
				break;
			}
			case '*': {
				if (right != 0)
					right *= current;
				else
					left *= current;
				break;
			}
			case '/': {
				if (right != 0)
					right /= current;
				else
					left /= current;
				break;
			}
			default:
				throw std::logic_error("Operator does not recognize.");
			}
			operators.pop_front();
		}
		number result = 0;
		switch (signal) {
		case '+':
			result = left + right;
			break;
		case '-':
			result = left - right;
			break;
		default:
			result = left;
			break;
		}
		if (reverse)
			result = -result;
		return result;
	}
	enum class statements {
		If,While,For,Function
	};
	std::deque<cov::tuple<statements,std::deque<string>>> buffer;
	int bracket_count=0;
	function* current_func=nullptr;
	void parse_define(const string& raw_str)
	{
		string str=raw_str.substr(raw_str.find("Define")+6);
		string name;
		for(auto& ch:str) {
			if(std::isspace(ch))
				continue;
			if(ch=='=')
				break;
			name+=ch;
		}
		storage.add_var(name,infer_value(raw_str.substr(raw_str.find('=')+1)));
	}
	void parse_assign(const string& raw_str)
	{
		string name;
		for(auto& ch:raw_str) {
			if(std::isspace(ch))
				continue;
			if(ch=='=')
				break;
			name+=ch;
		}
		storage.add_var(name,infer_value(raw_str.substr(raw_str.find('=')+1)));
	}
	void parse_return(const string& str)
	{
		if(current_func==nullptr)
			throw std::logic_error("Return in non-function area.");
		current_func->retval=new number(compute_number(str.substr(str.find("Return")+6)));
	}
	void parse_if(const std::deque<string>&);
	void parse_while(const std::deque<string>&);
	void parse_function(const std::deque<string>&);
	void parse(const string& str)
	{
		if(bracket_count!=0) {
			if(str.find("If")!=string::npos||str.find("While")!=string::npos||str.find("Function")!=string::npos)
				++bracket_count;
			else if(str.find("End")!=string::npos) {
				--bracket_count;
				if(bracket_count==0) {
					switch(buffer.front().get<0>()) {
					case statements::If:
						parse_if(buffer.front().get<1>());
						buffer.pop_front();
						break;
					case statements::While:
						parse_while(buffer.front().get<1>());
						buffer.pop_front();
						break;
					case statements::Function:
						parse_function(buffer.front().get<1>());
						buffer.pop_front();
						break;
					}
					return;
				}
			}
			buffer.front().get<1>().push_back(str);
			return;
		}
		if(str.find("Define")!=string::npos) {
			parse_define(str);
			return;
		}
		if(str.find("Return")!=string::npos) {
			parse_return(str);
			return;
		}
		if(str.find("If")!=string::npos) {
			buffer.push_front(cov::tuple<statements,std::deque<string>>(statements::If,std::deque<string>({str})));
			++bracket_count;
			return;
		}
		if(str.find("While")!=string::npos) {
			buffer.push_front(cov::tuple<statements,std::deque<string>>(statements::While,std::deque<string>({str})));
			++bracket_count;
			return;
		}
		if(str.find("Function")!=string::npos) {
			buffer.push_front(cov::tuple<statements,std::deque<string>>(statements::Function,std::deque<string>({str})));
			++bracket_count;
			return;
		}
		if(str.find('=')!=string::npos) {
			parse_assign(str);
			return;
		}
		if(is_bool_exp(str))
			compute_boolean(str);
		else
			compute_number(str);
	}
	void parse_if(const std::deque<string>& raw_buf)
	{
		if(raw_buf.empty())
			throw std::logic_error(__func__);
		storage.add_domain();
		string head=raw_buf.front();
		auto if_pos=head.find("If");
		auto then_pos=head.rfind("Then");
		bool result=compute_boolean(head.substr(if_pos+2,then_pos-if_pos-2));
		std::size_t pos=0;
		for(std::size_t i=1; i<raw_buf.size(); ++i) {
			if(raw_buf.at(i).find("Else")!=string::npos) {
				pos=i;
				break;
			}
		}
		if(pos==0)
			pos=raw_buf.size();
		if(result) {
			for(std::size_t i=1; i<pos; ++i)
				parse(raw_buf.at(i));
		} else {
			for(std::size_t i=pos+1; i<raw_buf.size(); ++i)
				parse(raw_buf.at(i));
		}
		storage.remove_domain();
	}
	void parse_while(const std::deque<string>& raw_buf)
	{
		if(raw_buf.empty())
			throw std::logic_error(__func__);
		storage.add_domain();
		string head=raw_buf.front();
		auto while_pos=head.find("While")+5;
		auto do_pos=head.rfind("Do");
		string condition=head.substr(while_pos,do_pos-while_pos);
		while(compute_boolean(condition)){
			for(std::size_t i=1; i<raw_buf.size(); ++i)
				parse(raw_buf.at(i));
		}
		storage.remove_domain();
	}
	void parse_function(const std::deque<string>& raw_buf)
	{
		if(raw_buf.empty())
			throw std::logic_error(__func__);
		string head=raw_buf.front();
		string name;
		std::deque<string> arglist;
		auto lpos=head.find('(')+1;
		auto rpos=head.rfind(')');
		if(lpos!=rpos)
			split_str(',',head.substr(lpos,rpos-lpos),arglist);
		for(auto i=head.find("Function")+8; i<lpos-1; ++i)
			if(!std::isspace(head.at(i)))
				name+=head.at(i);
		storage.add_var_global(name,function(arglist,std::deque<string>(raw_buf.begin()+1,raw_buf.end())));
	}
	number function::call(const std::deque<cov::any>& args)
	{
		if(args.size()!=mArgs.size())
			throw std::logic_error("Wrong size of arguments");
		current_func=this;
		storage.add_domain();
		for(std::size_t i=0; i<args.size(); ++i)
			storage.add_var(mArgs.at(i),args.at(i));
		for(auto& it:mBuf){
			parse(it);
			if(retval!=nullptr)
			{
				current_func=nullptr;
				number ret=*retval;
				delete retval;
				return ret;
			}
		}
		storage.remove_domain();
		current_func=nullptr;
		return number(0);
	}
}
namespace std {
	template<>std::string to_string<bool>(const bool& v)
	{
		if(v)
			return "True";
		else
			return "False";
	}
}<commit_msg>Delete core.hpp<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "Movie.h"
#include "Media.h"
#include "database/SqliteTools.h"
#include "database/SqliteQuery.h"

namespace medialibrary
{

const std::string Movie::Table::Name = "Movie";
const std::string Movie::Table::PrimaryKeyColumn = "id_movie";
int64_t Movie::* const Movie::Table::PrimaryKey = &Movie::m_id;

Movie::Movie(MediaLibraryPtr ml, sqlite::Row& row )
    : m_ml( ml )
    , m_id( row.extract<decltype(m_id)>() )
    , m_mediaId( row.extract<decltype(m_mediaId)>() )
    , m_summary( row.extract<decltype(m_summary)>() )
    , m_imdbId( row.extract<decltype(m_imdbId)>() )
{
    assert( row.hasRemainingColumns() == false );
}

Movie::Movie( MediaLibraryPtr ml, int64_t mediaId )
    : m_ml( ml )
    , m_id( 0 )
    , m_mediaId( mediaId )
{
}

int64_t Movie::id() const
{
    return m_id;
}

const std::string& Movie::shortSummary() const
{
    return m_summary;
}

bool Movie::setShortSummary( const std::string& summary )
{
    static const std::string req = "UPDATE " + Movie::Table::Name
            + " SET summary = ? WHERE id_movie = ?";
    if ( sqlite::Tools::executeUpdate( m_ml->getConn(), req, summary, m_id ) == false )
        return false;
    m_summary = summary;
    return true;
}

const std::string& Movie::imdbId() const
{
    return m_imdbId;
}

bool Movie::setImdbId( const std::string& imdbId )
{
    static const std::string req = "UPDATE " + Movie::Table::Name
            + " SET imdb_id = ? WHERE id_movie = ?";
    if ( sqlite::Tools::executeUpdate( m_ml->getConn(), req, imdbId, m_id ) == false )
        return false;
    m_imdbId = imdbId;
    return true;
}

void Movie::createTable( sqlite::Connection* dbConnection )
{
    const std::string reqs[] = {
        schema( Table::Name, Settings::DbModelVersion ),
        "CREATE INDEX IF NOT EXISTS movie_media_idx ON " + Table::Name + "(media_id)",
    };
    for ( const auto& req : reqs )
        sqlite::Tools::executeRequest( dbConnection, req );
}

std::string Movie::schema( const std::string& tableName, uint32_t )
{
    assert( tableName == Table::Name );
    return "CREATE TABLE " + Table::Name +
    "("
        "id_movie INTEGER PRIMARY KEY AUTOINCREMENT,"
        "media_id UNSIGNED INTEGER NOT NULL,"
        "summary TEXT,"
        "imdb_id TEXT,"
        "FOREIGN KEY(media_id) REFERENCES " + Media::Table::Name
            + "(id_media) ON DELETE CASCADE"
    ")";
}

bool Movie::checkDbModel(MediaLibraryPtr ml)
{
    return sqlite::Tools::checkSchema( ml->getConn(),
                                       schema( Table::Name, Settings::DbModelVersion ),
                                       Table::Name );
}

std::shared_ptr<Movie> Movie::create(MediaLibraryPtr ml, int64_t mediaId )
{
    auto movie = std::make_shared<Movie>( ml, mediaId );
    static const std::string req = "INSERT INTO " + Movie::Table::Name
            + "(media_id) VALUES(?)";
    if ( insert( ml, movie, req, mediaId ) == false )
        return nullptr;
    return movie;
}

MoviePtr Movie::fromMedia( MediaLibraryPtr ml, int64_t mediaId )
{
    static const std::string req = "SELECT * FROM " + Movie::Table::Name + " WHERE media_id = ?";
    return fetch( ml, req, mediaId );
}

}
<commit_msg>Movie.cpp: Remove unneeded include<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "Movie.h"
#include "Media.h"
#include "database/SqliteTools.h"

namespace medialibrary
{

const std::string Movie::Table::Name = "Movie";
const std::string Movie::Table::PrimaryKeyColumn = "id_movie";
int64_t Movie::* const Movie::Table::PrimaryKey = &Movie::m_id;

Movie::Movie(MediaLibraryPtr ml, sqlite::Row& row )
    : m_ml( ml )
    , m_id( row.extract<decltype(m_id)>() )
    , m_mediaId( row.extract<decltype(m_mediaId)>() )
    , m_summary( row.extract<decltype(m_summary)>() )
    , m_imdbId( row.extract<decltype(m_imdbId)>() )
{
    assert( row.hasRemainingColumns() == false );
}

Movie::Movie( MediaLibraryPtr ml, int64_t mediaId )
    : m_ml( ml )
    , m_id( 0 )
    , m_mediaId( mediaId )
{
}

int64_t Movie::id() const
{
    return m_id;
}

const std::string& Movie::shortSummary() const
{
    return m_summary;
}

bool Movie::setShortSummary( const std::string& summary )
{
    static const std::string req = "UPDATE " + Movie::Table::Name
            + " SET summary = ? WHERE id_movie = ?";
    if ( sqlite::Tools::executeUpdate( m_ml->getConn(), req, summary, m_id ) == false )
        return false;
    m_summary = summary;
    return true;
}

const std::string& Movie::imdbId() const
{
    return m_imdbId;
}

bool Movie::setImdbId( const std::string& imdbId )
{
    static const std::string req = "UPDATE " + Movie::Table::Name
            + " SET imdb_id = ? WHERE id_movie = ?";
    if ( sqlite::Tools::executeUpdate( m_ml->getConn(), req, imdbId, m_id ) == false )
        return false;
    m_imdbId = imdbId;
    return true;
}

void Movie::createTable( sqlite::Connection* dbConnection )
{
    const std::string reqs[] = {
        schema( Table::Name, Settings::DbModelVersion ),
        "CREATE INDEX IF NOT EXISTS movie_media_idx ON " + Table::Name + "(media_id)",
    };
    for ( const auto& req : reqs )
        sqlite::Tools::executeRequest( dbConnection, req );
}

std::string Movie::schema( const std::string& tableName, uint32_t )
{
    assert( tableName == Table::Name );
    return "CREATE TABLE " + Table::Name +
    "("
        "id_movie INTEGER PRIMARY KEY AUTOINCREMENT,"
        "media_id UNSIGNED INTEGER NOT NULL,"
        "summary TEXT,"
        "imdb_id TEXT,"
        "FOREIGN KEY(media_id) REFERENCES " + Media::Table::Name
            + "(id_media) ON DELETE CASCADE"
    ")";
}

bool Movie::checkDbModel(MediaLibraryPtr ml)
{
    return sqlite::Tools::checkSchema( ml->getConn(),
                                       schema( Table::Name, Settings::DbModelVersion ),
                                       Table::Name );
}

std::shared_ptr<Movie> Movie::create(MediaLibraryPtr ml, int64_t mediaId )
{
    auto movie = std::make_shared<Movie>( ml, mediaId );
    static const std::string req = "INSERT INTO " + Movie::Table::Name
            + "(media_id) VALUES(?)";
    if ( insert( ml, movie, req, mediaId ) == false )
        return nullptr;
    return movie;
}

MoviePtr Movie::fromMedia( MediaLibraryPtr ml, int64_t mediaId )
{
    static const std::string req = "SELECT * FROM " + Movie::Table::Name + " WHERE media_id = ?";
    return fetch( ml, req, mediaId );
}

}
<|endoftext|>


<commit_before>#include "AirwaySegmentation.hpp"
#include "FAST/Algorithms/GaussianSmoothingFilter/GaussianSmoothingFilter.hpp"
#include "FAST/Data/Segmentation.hpp"
#include <unordered_set>
#include <stack>

namespace fast {

AirwaySegmentation::AirwaySegmentation() {
	createInputPort<Image>(0);
	createOutputPort<Segmentation>(0, OUTPUT_DEPENDS_ON_INPUT, 0);

	createOpenCLProgram(std::string(FAST_SOURCE_DIR) + "Algorithms/AirwaySegmentation/AirwaySegmentation.cl");
}

Vector3i findSeedVoxel(Image::pointer volume) {

	ImageAccess::pointer access = volume->getImageAccess(ACCESS_READ);
	short* data = (short*)access->get();

    int slice = volume->getDepth()*0.6;

    int threshold = -700;
    int Tseed = -1000;
    float minArea = 7.5f*7.5f*3.14f; // min radius of 7.5
    float maxArea = 25.0f*25.0f*3.14f; // max radius of 25.0
    Vector3i currentSeed(0,0,0);
    float currentCentricity = 99999.0f; // Distance from center
    float spacing = 1.0f;//volume->getSpacing().x();

    std::unordered_set<int> visited;
    int width = volume->getWidth();
    int height = volume->getHeight();
    int depth = volume->getDepth();

    for(int x = width*0.25; x < width*0.75; ++x) {
        for(int y = height*0.25; y < height*0.75; ++y) {
            Vector3i testSeed(x,y,slice);
            if(data[testSeed.x() + testSeed.y()*width + testSeed.z()*width*height] > Tseed)
                continue;
            std::stack<Vector3i> stack;
            stack.push(testSeed);
            int perimenter = 0;
            bool invalid = false;
            visited.clear();
            visited.insert(testSeed.x()+testSeed.y()*width);

            while(!stack.empty() && !invalid) {
                Vector3i v = stack.top();
                stack.pop();

                for(int a = -1; a < 2 && !invalid; ++a) {
                for(int b = -1; b < 2; ++b) {
                    Vector3i c(v.x()+a, v.y()+b, v.z());
                    if(c.x() < 0 || c.y() < 0 ||
                    		c.x() >= width || c.y() >= height) {
                        invalid = true;
                        break;
                    }

                    if(data[c.x() + c.y()*width + c.z()*width*height] <= threshold && visited.find(c.x()+c.y()*volume->getWidth()) == visited.end()) {
                        visited.insert(c.x()+c.y()*volume->getWidth());
                        stack.push(c);
                        if(visited.size()*spacing*spacing > maxArea) {
                            invalid = true;
                            break;
                        }
                    }
                }}
            }

            //float compaction = (4.0f*3.14*area)/(perimenter*perimenter);
            if(!invalid && visited.size()*spacing*spacing > minArea) {
                float centricity = sqrt(pow(testSeed.x()-volume->getWidth()*0.5f,2.0f)+pow(testSeed.y()-volume->getHeight()*0.5f,2.0f));
                if(centricity < currentCentricity) {
                    // Accept as new seed
                    currentSeed = testSeed;
                    currentCentricity = centricity;
                }
            }
        }
    }

    return currentSeed;
}

int grow(uchar* segmentation, const Vector3i neighbors[25], std::vector<Vector3i>* voxels, short* data, float threshold, int width, int height, int depth) {
    std::vector<Vector3i>::iterator it;
    std::stack<Vector3i> stack;
    // TODO voxels coming in here consists of all voxels, should only need to add the front..
    for(it = voxels->begin(); it != voxels->end(); it++) {
        stack.push(*it);
    }

    while(!stack.empty()) {
        Vector3i x = stack.top();
        stack.pop();
        segmentation[x.x() + x.y()*width + x.z()*width*height] = 1; // TODO is this needed?

        // Add 26 neighbors
        for(int i = 0; i < 25; ++i) {
        	Vector3i neighbor = neighbors[i];
            Vector3i y(x.x()+neighbor.x(), x.y()+neighbor.y(), x.z()+neighbor.z());
			if(y.x() < 0 || y.y() < 0 || y.z() < 0 ||
				y.x() >= width || y.y() >= height || y.z() >= depth) {
                continue;
            }

            if(data[y.x() + y.y()*width + y.z()*width*height] <= threshold && segmentation[y.x() + y.y()*width + y.z()*width*height] == 0) {
				segmentation[y.x() + y.y()*width + y.z()*width*height] = 1;
                voxels->push_back(y);
                stack.push(y);
            }
        }
    }

    return voxels->size();
}

void regionGrowing(Image::pointer volume, Segmentation::pointer segmentation, Vector3i seed) {
    int width = volume->getWidth();
    int height = volume->getHeight();
    int depth = volume->getDepth();
	segmentation->createFromImage(volume);
	ImageAccess::pointer access = volume->getImageAccess(ACCESS_READ);
	short* data = (short*)access->get();
	ImageAccess::pointer access2 = segmentation->getImageAccess(ACCESS_READ_WRITE);
	uchar* segmentationData = (uchar*)access2->get();
	memset(segmentationData, 0, width*height*depth);
    std::vector<Vector3i> voxels;
    segmentationData[seed.x() + seed.y()*width + seed.z()*width*height] = 1;
    voxels.push_back(seed);
    float threshold = data[seed.x() + seed.y()*width + seed.z()*width*height];
    float volumeIncreaseLimit = 20000.0f;
    float volumeMinimum = 100000.0f;
    float VT = 0.0f; // volume with given threshold
    float deltaT = 2.0f;
    float spacing = 1.0f;

    // Create neighbor list
    Vector3i neighbors[25];
    int counter = 0;
	for(int a = -1; a < 2; a++) {
	for(int b = -1; b < 2; b++) {
	for(int c = -1; c < 2; c++) {
		if(a == 0 && b == 0 && c == 0)
			continue;
		neighbors[counter] = Vector3i(a,b,c);
		counter++;
	}}}

    float Vnew = spacing*grow(segmentationData, neighbors, &voxels, data, threshold, width, height, depth);
    // Loop until explosion is detected
    do {
        VT = Vnew;
        threshold += deltaT;
		Vnew = spacing*grow(segmentationData, neighbors, &voxels, data, threshold, width, height, depth);
        Reporter::info() << "using threshold: " << threshold << Reporter::end;
        Reporter::info() << "gives volume size: " << Vnew << Reporter::end;
    } while(Vnew-VT < volumeIncreaseLimit || Vnew < volumeMinimum);

    float explosionVolume = Vnew;
	Reporter::info() << "Ungrowing.." << Vnew << Reporter::end;
    threshold -= deltaT;
    VT = Vnew;

    // Ungrow until the volume is less than 95% of V
    while(VT >= 0.95f*explosionVolume) {
        voxels.clear();
        voxels.push_back(seed);
		memset(segmentationData, 0, width*height*depth);
		segmentationData[seed.x() + seed.y()*width + seed.z()*width*height] = 1;
        VT = spacing*grow(segmentationData, neighbors, &voxels, data, threshold, width, height, depth);
        Reporter::info() << "using threshold: " << threshold << Reporter::end;
        Reporter::info() << "gives volume size: " << VT << Reporter::end;
        threshold -= deltaT;
    }
}

Image::pointer AirwaySegmentation::convertToHU(Image::pointer image) {
	// TODO need support for no 3d write
	OpenCLDevice::pointer device = getMainDevice();
	cl::Program program = getOpenCLProgram(device);

	OpenCLImageAccess::pointer input = image->getOpenCLImageAccess(ACCESS_READ, device);
	Image::pointer newImage = Image::New();
	newImage->create(image->getSize(), TYPE_INT16, 1);
	newImage->setSpacing(image->getSpacing());
	SceneGraph::setParentNode(newImage, image);

	cl::Kernel kernel(program, "convertToHU");

	kernel.setArg(0, *input->get3DImage());
	if(device->isWritingTo3DTexturesSupported()) {
		OpenCLImageAccess::pointer output = newImage->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		kernel.setArg(1, *output->get3DImage());
	} else {
		OpenCLBufferAccess::pointer output = newImage->getOpenCLBufferAccess(ACCESS_READ_WRITE, device);
		kernel.setArg(1, *output->get());
	}

	device->getCommandQueue().enqueueNDRangeKernel(
			kernel,
			cl::NullRange,
			cl::NDRange(image->getWidth(), image->getHeight(), image->getDepth()),
			cl::NullRange
    );

	return newImage;
}

void AirwaySegmentation::morphologicalClosing(Segmentation::pointer segmentation) {
	int width = segmentation->getWidth();
	int height = segmentation->getHeight();
	int depth = segmentation->getDepth();

	// TODO need support for no 3d write
	OpenCLDevice::pointer device = getMainDevice();
	cl::Program program = getOpenCLProgram(device);

	Segmentation::pointer segmentation2 = Segmentation::New();
	segmentation2->create(segmentation->getSize(), TYPE_UINT8, 1);
	ImageAccess::pointer access = segmentation2->getImageAccess(ACCESS_READ_WRITE);
	uchar* data = (uchar*)access->get();
	memset(data, 0, width*height*depth);
	access->release();

	cl::Kernel dilateKernel(program, "dilate");
	cl::Kernel erodeKernel(program, "erode");

	if(device->isWritingTo3DTexturesSupported()) {
		OpenCLImageAccess::pointer input = segmentation->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		OpenCLImageAccess::pointer input2 = segmentation2->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		dilateKernel.setArg(0, *input->get3DImage());
		dilateKernel.setArg(1, *input2->get3DImage());
	} else {
		OpenCLImageAccess::pointer input = segmentation->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		OpenCLBufferAccess::pointer input2 = segmentation2->getOpenCLBufferAccess(ACCESS_READ_WRITE, device);
		dilateKernel.setArg(0, *input->get3DImage());
		dilateKernel.setArg(1, *input2->get());
	}

	device->getCommandQueue().enqueueNDRangeKernel(
			dilateKernel,
			cl::NullRange,
			cl::NDRange(width, height, depth),
			cl::NullRange
	);

	if(device->isWritingTo3DTexturesSupported()) {
		OpenCLImageAccess::pointer input = segmentation->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		OpenCLImageAccess::pointer input2 = segmentation2->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		erodeKernel.setArg(0, *input2->get3DImage());
		erodeKernel.setArg(1, *input->get3DImage());
	} else {
		OpenCLBufferAccess::pointer input = segmentation->getOpenCLBufferAccess(ACCESS_READ_WRITE, device);
		OpenCLImageAccess::pointer input2 = segmentation2->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		erodeKernel.setArg(0, *input2->get3DImage());
		erodeKernel.setArg(1, *input->get());
	}

	device->getCommandQueue().enqueueNDRangeKernel(
			erodeKernel,
			cl::NullRange,
			cl::NDRange(width, height, depth),
			cl::NullRange
	);

}

void AirwaySegmentation::execute() {
	Image::pointer image = getStaticInputData<Image>();

	// Convert to signed HU if unsigned
	if(image->getDataType() == TYPE_UINT16) {
		image = convertToHU(image);
	}

	// Smooth image
	GaussianSmoothingFilter::pointer filter = GaussianSmoothingFilter::New();
	filter->setInputData(image);
	filter->setStandardDeviation(0.5);
	filter->update();
	image = filter->getOutputData<Image>();

	// Find seed voxel
	Vector3i seed = findSeedVoxel(image);

	if(seed == Vector3i::Zero()) {
		throw Exception("No seed found.");
	}

	reportInfo() << "Seed found at " << seed.transpose() << reportEnd();

	// Do the region growing
	Segmentation::pointer segmentation = getStaticOutputData<Segmentation>();
	regionGrowing(image, segmentation, seed);

	// Do morphological closing to remove holes in segmentation
	morphologicalClosing(segmentation);

}

}
<commit_msg>fixed a bug on mac in airway seg<commit_after>#include "AirwaySegmentation.hpp"
#include "FAST/Algorithms/GaussianSmoothingFilter/GaussianSmoothingFilter.hpp"
#include "FAST/Data/Segmentation.hpp"
#include <unordered_set>
#include <stack>

namespace fast {

AirwaySegmentation::AirwaySegmentation() {
	createInputPort<Image>(0);
	createOutputPort<Segmentation>(0, OUTPUT_DEPENDS_ON_INPUT, 0);

	createOpenCLProgram(std::string(FAST_SOURCE_DIR) + "Algorithms/AirwaySegmentation/AirwaySegmentation.cl");
}

Vector3i findSeedVoxel(Image::pointer volume) {

	ImageAccess::pointer access = volume->getImageAccess(ACCESS_READ);
	short* data = (short*)access->get();

    int slice = volume->getDepth()*0.6;

    int threshold = -700;
    int Tseed = -1000;
    float minArea = 7.5f*7.5f*3.14f; // min radius of 7.5
    float maxArea = 25.0f*25.0f*3.14f; // max radius of 25.0
    Vector3i currentSeed(0,0,0);
    float currentCentricity = 99999.0f; // Distance from center
    float spacing = 1.0f;//volume->getSpacing().x();

    std::unordered_set<int> visited;
    int width = volume->getWidth();
    int height = volume->getHeight();
    int depth = volume->getDepth();

    for(int x = width*0.25; x < width*0.75; ++x) {
        for(int y = height*0.25; y < height*0.75; ++y) {
            Vector3i testSeed(x,y,slice);
            if(data[testSeed.x() + testSeed.y()*width + testSeed.z()*width*height] > Tseed)
                continue;
            std::stack<Vector3i> stack;
            stack.push(testSeed);
            int perimenter = 0;
            bool invalid = false;
            visited.clear();
            visited.insert(testSeed.x()+testSeed.y()*width);

            while(!stack.empty() && !invalid) {
                Vector3i v = stack.top();
                stack.pop();

                for(int a = -1; a < 2 && !invalid; ++a) {
                for(int b = -1; b < 2; ++b) {
                    Vector3i c(v.x()+a, v.y()+b, v.z());
                    if(c.x() < 0 || c.y() < 0 ||
                    		c.x() >= width || c.y() >= height) {
                        invalid = true;
                        break;
                    }

                    if(data[c.x() + c.y()*width + c.z()*width*height] <= threshold && visited.find(c.x()+c.y()*volume->getWidth()) == visited.end()) {
                        visited.insert(c.x()+c.y()*volume->getWidth());
                        stack.push(c);
                        if(visited.size()*spacing*spacing > maxArea) {
                            invalid = true;
                            break;
                        }
                    }
                }}
            }

            //float compaction = (4.0f*3.14*area)/(perimenter*perimenter);
            if(!invalid && visited.size()*spacing*spacing > minArea) {
                float centricity = sqrt(pow(testSeed.x()-volume->getWidth()*0.5f,2.0f)+pow(testSeed.y()-volume->getHeight()*0.5f,2.0f));
                if(centricity < currentCentricity) {
                    // Accept as new seed
                    currentSeed = testSeed;
                    currentCentricity = centricity;
                }
            }
        }
    }

    return currentSeed;
}

int grow(uchar* segmentation, std::vector<Vector3i> neighbors, std::vector<Vector3i>* voxels, short* data, float threshold, int width, int height, int depth) {
    std::vector<Vector3i>::iterator it;
    std::stack<Vector3i> stack;
    // TODO voxels coming in here consists of all voxels, should only need to add the front..
    for(it = voxels->begin(); it != voxels->end(); it++) {
        stack.push(*it);
    }

    while(!stack.empty()) {
        Vector3i x = stack.top();
        stack.pop();
        segmentation[x.x() + x.y()*width + x.z()*width*height] = 1; // TODO is this needed?

        // Add 26 neighbors
        for(int i = 0; i < 25; ++i) {
        	Vector3i neighbor = neighbors[i];
            Vector3i y(x.x()+neighbor.x(), x.y()+neighbor.y(), x.z()+neighbor.z());
			if(y.x() < 0 || y.y() < 0 || y.z() < 0 ||
				y.x() >= width || y.y() >= height || y.z() >= depth) {
                continue;
            }

            if(data[y.x() + y.y()*width + y.z()*width*height] <= threshold && segmentation[y.x() + y.y()*width + y.z()*width*height] == 0) {
				segmentation[y.x() + y.y()*width + y.z()*width*height] = 1;
                voxels->push_back(y);
                stack.push(y);
            }
        }
    }

    return voxels->size();
}

void regionGrowing(Image::pointer volume, Segmentation::pointer segmentation, Vector3i seed) {
    int width = volume->getWidth();
    int height = volume->getHeight();
    int depth = volume->getDepth();
	segmentation->createFromImage(volume);
	ImageAccess::pointer access = volume->getImageAccess(ACCESS_READ);
	short* data = (short*)access->get();
	ImageAccess::pointer access2 = segmentation->getImageAccess(ACCESS_READ_WRITE);
	uchar* segmentationData = (uchar*)access2->get();
	memset(segmentationData, 0, width*height*depth);
    std::vector<Vector3i> voxels;
    segmentationData[seed.x() + seed.y()*width + seed.z()*width*height] = 1;
    voxels.push_back(seed);
    float threshold = data[seed.x() + seed.y()*width + seed.z()*width*height];
    float volumeIncreaseLimit = 20000.0f;
    float volumeMinimum = 100000.0f;
    float VT = 0.0f; // volume with given threshold
    float deltaT = 2.0f;
    float spacing = 1.0f;

    // Create neighbor list
    std::vector<Vector3i> neighbors;
	for(int a = -1; a < 2; a++) {
	for(int b = -1; b < 2; b++) {
	for(int c = -1; c < 2; c++) {
		if(a == 0 && b == 0 && c == 0)
			continue;
		neighbors.push_back(Vector3i(a,b,c));
	}}}

    float Vnew = spacing*grow(segmentationData, neighbors, &voxels, data, threshold, width, height, depth);
    // Loop until explosion is detected
    do {
        VT = Vnew;
        threshold += deltaT;
		Vnew = spacing*grow(segmentationData, neighbors, &voxels, data, threshold, width, height, depth);
        Reporter::info() << "using threshold: " << threshold << Reporter::end;
        Reporter::info() << "gives volume size: " << Vnew << Reporter::end;
    } while(Vnew-VT < volumeIncreaseLimit || Vnew < volumeMinimum);

    float explosionVolume = Vnew;
	Reporter::info() << "Ungrowing.." << Vnew << Reporter::end;
    threshold -= deltaT;
    VT = Vnew;

    // Ungrow until the volume is less than 95% of V
    while(VT >= 0.95f*explosionVolume) {
        voxels.clear();
        voxels.push_back(seed);
		memset(segmentationData, 0, width*height*depth);
		segmentationData[seed.x() + seed.y()*width + seed.z()*width*height] = 1;
        VT = spacing*grow(segmentationData, neighbors, &voxels, data, threshold, width, height, depth);
        Reporter::info() << "using threshold: " << threshold << Reporter::end;
        Reporter::info() << "gives volume size: " << VT << Reporter::end;
        threshold -= deltaT;
    }
}

Image::pointer AirwaySegmentation::convertToHU(Image::pointer image) {
	// TODO need support for no 3d write
	OpenCLDevice::pointer device = getMainDevice();
	cl::Program program = getOpenCLProgram(device);

	OpenCLImageAccess::pointer input = image->getOpenCLImageAccess(ACCESS_READ, device);
	Image::pointer newImage = Image::New();
	newImage->create(image->getSize(), TYPE_INT16, 1);
	newImage->setSpacing(image->getSpacing());
	SceneGraph::setParentNode(newImage, image);

	cl::Kernel kernel(program, "convertToHU");

	kernel.setArg(0, *input->get3DImage());
	if(device->isWritingTo3DTexturesSupported()) {
		OpenCLImageAccess::pointer output = newImage->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		kernel.setArg(1, *output->get3DImage());
	} else {
		OpenCLBufferAccess::pointer output = newImage->getOpenCLBufferAccess(ACCESS_READ_WRITE, device);
		kernel.setArg(1, *output->get());
	}

	device->getCommandQueue().enqueueNDRangeKernel(
			kernel,
			cl::NullRange,
			cl::NDRange(image->getWidth(), image->getHeight(), image->getDepth()),
			cl::NullRange
    );

	return newImage;
}

void AirwaySegmentation::morphologicalClosing(Segmentation::pointer segmentation) {
	int width = segmentation->getWidth();
	int height = segmentation->getHeight();
	int depth = segmentation->getDepth();

	// TODO need support for no 3d write
	OpenCLDevice::pointer device = getMainDevice();
	cl::Program program = getOpenCLProgram(device);

	Segmentation::pointer segmentation2 = Segmentation::New();
	segmentation2->create(segmentation->getSize(), TYPE_UINT8, 1);
	ImageAccess::pointer access = segmentation2->getImageAccess(ACCESS_READ_WRITE);
	uchar* data = (uchar*)access->get();
	memset(data, 0, width*height*depth);
	access->release();

	cl::Kernel dilateKernel(program, "dilate");
	cl::Kernel erodeKernel(program, "erode");

	if(device->isWritingTo3DTexturesSupported()) {
		OpenCLImageAccess::pointer input = segmentation->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		OpenCLImageAccess::pointer input2 = segmentation2->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		dilateKernel.setArg(0, *input->get3DImage());
		dilateKernel.setArg(1, *input2->get3DImage());
	} else {
		OpenCLImageAccess::pointer input = segmentation->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		OpenCLBufferAccess::pointer input2 = segmentation2->getOpenCLBufferAccess(ACCESS_READ_WRITE, device);
		dilateKernel.setArg(0, *input->get3DImage());
		dilateKernel.setArg(1, *input2->get());
	}

	device->getCommandQueue().enqueueNDRangeKernel(
			dilateKernel,
			cl::NullRange,
			cl::NDRange(width, height, depth),
			cl::NullRange
	);

	if(device->isWritingTo3DTexturesSupported()) {
		OpenCLImageAccess::pointer input = segmentation->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		OpenCLImageAccess::pointer input2 = segmentation2->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		erodeKernel.setArg(0, *input2->get3DImage());
		erodeKernel.setArg(1, *input->get3DImage());
	} else {
		OpenCLBufferAccess::pointer input = segmentation->getOpenCLBufferAccess(ACCESS_READ_WRITE, device);
		OpenCLImageAccess::pointer input2 = segmentation2->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
		erodeKernel.setArg(0, *input2->get3DImage());
		erodeKernel.setArg(1, *input->get());
	}

	device->getCommandQueue().enqueueNDRangeKernel(
			erodeKernel,
			cl::NullRange,
			cl::NDRange(width, height, depth),
			cl::NullRange
	);

}

void AirwaySegmentation::execute() {
	Image::pointer image = getStaticInputData<Image>();

	// Convert to signed HU if unsigned
	if(image->getDataType() == TYPE_UINT16) {
		image = convertToHU(image);
	}

	// Smooth image
	GaussianSmoothingFilter::pointer filter = GaussianSmoothingFilter::New();
	filter->setInputData(image);
	filter->setStandardDeviation(0.5);
	filter->update();
	image = filter->getOutputData<Image>();

	// Find seed voxel
	Vector3i seed = findSeedVoxel(image);

	if(seed == Vector3i::Zero()) {
		throw Exception("No seed found.");
	}

	reportInfo() << "Seed found at " << seed.transpose() << reportEnd();

	// Do the region growing
	Segmentation::pointer segmentation = getStaticOutputData<Segmentation>();
	regionGrowing(image, segmentation, seed);

	// Do morphological closing to remove holes in segmentation
	morphologicalClosing(segmentation);

}

}
<|endoftext|>


<commit_before>//******************************************************************
//
// Copyright 2017 Intel Corporation All Rights Reserved.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#include "Interfaces.h"

#include "DeviceConfigurationResource.h"
#include "PlatformConfigurationResource.h"
#include "octypes.h"
#include <string.h>

namespace ajn {
    namespace org {
        namespace alljoyn {
            namespace Config {
                const char *InterfaceXml =
                        "<interface name='org.alljoyn.Config'>"
                        "  <method name='FactoryReset'>"
                        "    <annotation name='org.freedesktop.DBus.Method.NoReply' value='true'/>"
                        "  </method>"
                        "  <method name='GetConfigurations'>"
                        "    <arg name='languageTag' type='s' direction='in'/>"
                        "    <arg name='languages' type='a{sv}' direction='out'/>"
                        "  </method>"
                        "  <method name='ResetConfigurations'>"
                        "    <arg name='languageTag' type='s' direction='in'/>"
                        "    <arg name='fieldList' type='as' direction='in'/>"
                        "  </method>"
                        "  <method name='Restart'>"
                        "    <annotation name='org.freedesktop.DBus.Method.NoReply' value='true'/>"
                        "  </method>"
                        "  <method name='SetPasscode'>"
                        "    <arg name='DaemonRealm' type='s' direction='in'/>"
                        "    <arg name='newPasscode' type='ay' direction='in'/>"
                        "  </method>"
                        "  <method name='UpdateConfigurations'>"
                        "    <arg name='languageTag' type='s' direction='in'/>"
                        "    <arg name='configMap' type='a{sv}' direction='in'/>"
                        "  </method>"
                        "  <property name='Version' type='q' access='read'/>"
                        // TODO "  <annotation name='org.alljoyn.Bus.Secure' value='true'/>"
                        "</interface>";
            }
        }
    }
}

bool IsInterfaceInWellDefinedSet(const char *name)
{
    const char *wellDefined[] = {
        /* OCF ASA Mapping */
        "Environment.CurrentAirQuality", "Environment.CurrentAirQualityLevel",
        "Environment.CurrentHumidity", "Environment.CurrentTemperature",
        "Environment.TargetHumidity", "Environment.TargetTemperature",
        "Environment.TargetTemperatureLevel", "Environment.WaterLevel", "Environment.WindDirection",
        "Operation.AirRecirculationMode", "Operation.Alerts", "Operation.AudioVideoInput",
        "Operation.AudioVolume", "Operation.BatteryStatus", "Operation.Channel",
        "Operation.ClimateControlMode", "Operation.ClosedStatus", "Operation.CurrentPower",
        "Operation.CycleControl", "Operation.DishWashingCyclePhase", "Operation.EnergyUsage",
        "Operation.FanSpeedLevel", "Operation.FilterStatus", "Operation.HeatingZone",
        "Operation.HvacFanMode", "Operation.LaundryCyclePhase", "Operation.MoistureOutputLevel",
        "Operation.OffControl", "Operation.OnControl", "Operation.OnOffStatus",
        "Operation.OvenCyclePhase", "Operation.PlugInUnits", "Operation.RapidMode",
        "Operation.RemoteControllability", "Operation.RepeatMode", "Operation.ResourceSaving",
        "Operation.RobotCleaningCyclePhase", "Operation.SoilLevel", "Operation.SpinSpeedLevel",
        "Operation.Timer"
    };
    for (size_t i = 0; i < sizeof(wellDefined) / sizeof(wellDefined[0]); ++i)
    {
        if (!strcmp(wellDefined[i], name))
        {
            return true;
        }
    }
    return false;
}

bool IsResourceTypeInWellDefinedSet(const char *name)
{
    const char *wellDefined[] = {
        /* OCF ASA Mapping */
        "oic.r.airflow", "oic.r.airqualitycollection", "oic.r.audio", "oic.r.door", "oic.r.ecomode",
        "oic.r.energy.battery", "oic.r.energy.usage", "oic.r.heatingzonecollection",
        "oic.r.humidity", "oic.r.humidity", "oic.r.icemaker", "oic.r.media.input", "oic.r.mode",
        "oic.r.operational.state", "oic.r.operationalstate", "oic.r.refrigeration", "oic.r.scanner",
        "oic.r.selectablelevels", "oic.r.switch.binary", "oic.r.temperature", "oic.r.time.period"
    };
    for (size_t i = 0; i < sizeof(wellDefined) / sizeof(wellDefined[0]); ++i)
    {
        if (!strcmp(wellDefined[i], name))
        {
            return true;
        }
    }
    return false;
}

bool TranslateInterface(const char *name)
{
    const char *doNotTranslatePrefix[] = {
        "org.alljoyn.Bus", "org.freedesktop.DBus"
    };
    for (size_t i = 0; i < sizeof(doNotTranslatePrefix) / sizeof(doNotTranslatePrefix[0]); ++i)
    {
        if (!strncmp(doNotTranslatePrefix[i], name, strlen(doNotTranslatePrefix[i])))
        {
            return false;
        }
    }
    const char *doNotTranslate[] = {
        "org.alljoyn.About", "org.alljoyn.Daemon", "org.alljoyn.Debug", "org.alljoyn.Icon",
        "org.allseen.Introspectable"
    };
    for (size_t i = 0; i < sizeof(doNotTranslate) / sizeof(doNotTranslate[0]); ++i)
    {
        if (!strcmp(doNotTranslate[i], name))
        {
            return false;
        }
    }
    const char *doDeepTranslation[] = {
        "org.alljoyn.Config"
    };
    for (size_t i = 0; i < sizeof(doDeepTranslation) / sizeof(doDeepTranslation[0]); ++i)
    {
        if (!strcmp(doDeepTranslation[i], name))
        {
            return true;
        }
    }
    return !IsInterfaceInWellDefinedSet(name);
}

bool TranslateResourceType(const char *name)
{
    const char *doNotTranslate[] = {
        "oic.d.bridge",
        OC_RSRVD_RESOURCE_TYPE_COLLECTION, OC_RSRVD_RESOURCE_TYPE_DEVICE,
        OC_RSRVD_RESOURCE_TYPE_INTROSPECTION, OC_RSRVD_RESOURCE_TYPE_PLATFORM,
        OC_RSRVD_RESOURCE_TYPE_RD, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH, OC_RSRVD_RESOURCE_TYPE_RES,
        "oic.r.alljoynobject", "oic.r.acl", "oic.r.acl2", "oic.r.amacl", "oic.r.cred", "oic.r.crl",
        "oic.r.csr", "oic.r.doxm", "oic.r.pstat", "oic.r.roles", "oic.r.securemode"
    };
    for (size_t i = 0; i < sizeof(doNotTranslate) / sizeof(doNotTranslate[0]); ++i)
    {
        if (!strcmp(doNotTranslate[i], name))
        {
            return false;
        }
    }
    const char *doDeepTranslation[] = {
        OC_RSRVD_RESOURCE_TYPE_DEVICE_CONFIGURATION, OC_RSRVD_RESOURCE_TYPE_MAINTENANCE,
        OC_RSRVD_RESOURCE_TYPE_PLATFORM_CONFIGURATION
    };
    for (size_t i = 0; i < sizeof(doDeepTranslation) / sizeof(doDeepTranslation[0]); ++i)
    {
        if (!strcmp(doDeepTranslation[i], name))
        {
            return true;
        }
    }
    return !IsResourceTypeInWellDefinedSet(name);
}
<commit_msg>Translate devices that only include /oic/{d,p}.<commit_after>//******************************************************************
//
// Copyright 2017 Intel Corporation All Rights Reserved.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#include "Interfaces.h"

#include "DeviceConfigurationResource.h"
#include "PlatformConfigurationResource.h"
#include "octypes.h"
#include <string.h>

namespace ajn {
    namespace org {
        namespace alljoyn {
            namespace Config {
                const char *InterfaceXml =
                        "<interface name='org.alljoyn.Config'>"
                        "  <method name='FactoryReset'>"
                        "    <annotation name='org.freedesktop.DBus.Method.NoReply' value='true'/>"
                        "  </method>"
                        "  <method name='GetConfigurations'>"
                        "    <arg name='languageTag' type='s' direction='in'/>"
                        "    <arg name='languages' type='a{sv}' direction='out'/>"
                        "  </method>"
                        "  <method name='ResetConfigurations'>"
                        "    <arg name='languageTag' type='s' direction='in'/>"
                        "    <arg name='fieldList' type='as' direction='in'/>"
                        "  </method>"
                        "  <method name='Restart'>"
                        "    <annotation name='org.freedesktop.DBus.Method.NoReply' value='true'/>"
                        "  </method>"
                        "  <method name='SetPasscode'>"
                        "    <arg name='DaemonRealm' type='s' direction='in'/>"
                        "    <arg name='newPasscode' type='ay' direction='in'/>"
                        "  </method>"
                        "  <method name='UpdateConfigurations'>"
                        "    <arg name='languageTag' type='s' direction='in'/>"
                        "    <arg name='configMap' type='a{sv}' direction='in'/>"
                        "  </method>"
                        "  <property name='Version' type='q' access='read'/>"
                        // TODO "  <annotation name='org.alljoyn.Bus.Secure' value='true'/>"
                        "</interface>";
            }
        }
    }
}

bool IsInterfaceInWellDefinedSet(const char *name)
{
    const char *wellDefined[] = {
        /* OCF ASA Mapping */
        "Environment.CurrentAirQuality", "Environment.CurrentAirQualityLevel",
        "Environment.CurrentHumidity", "Environment.CurrentTemperature",
        "Environment.TargetHumidity", "Environment.TargetTemperature",
        "Environment.TargetTemperatureLevel", "Environment.WaterLevel", "Environment.WindDirection",
        "Operation.AirRecirculationMode", "Operation.Alerts", "Operation.AudioVideoInput",
        "Operation.AudioVolume", "Operation.BatteryStatus", "Operation.Channel",
        "Operation.ClimateControlMode", "Operation.ClosedStatus", "Operation.CurrentPower",
        "Operation.CycleControl", "Operation.DishWashingCyclePhase", "Operation.EnergyUsage",
        "Operation.FanSpeedLevel", "Operation.FilterStatus", "Operation.HeatingZone",
        "Operation.HvacFanMode", "Operation.LaundryCyclePhase", "Operation.MoistureOutputLevel",
        "Operation.OffControl", "Operation.OnControl", "Operation.OnOffStatus",
        "Operation.OvenCyclePhase", "Operation.PlugInUnits", "Operation.RapidMode",
        "Operation.RemoteControllability", "Operation.RepeatMode", "Operation.ResourceSaving",
        "Operation.RobotCleaningCyclePhase", "Operation.SoilLevel", "Operation.SpinSpeedLevel",
        "Operation.Timer"
    };
    for (size_t i = 0; i < sizeof(wellDefined) / sizeof(wellDefined[0]); ++i)
    {
        if (!strcmp(wellDefined[i], name))
        {
            return true;
        }
    }
    return false;
}

bool IsResourceTypeInWellDefinedSet(const char *name)
{
    const char *wellDefined[] = {
        /* OCF ASA Mapping */
        "oic.r.airflow", "oic.r.airqualitycollection", "oic.r.audio", "oic.r.door", "oic.r.ecomode",
        "oic.r.energy.battery", "oic.r.energy.usage", "oic.r.heatingzonecollection",
        "oic.r.humidity", "oic.r.humidity", "oic.r.icemaker", "oic.r.media.input", "oic.r.mode",
        "oic.r.operational.state", "oic.r.operationalstate", "oic.r.refrigeration", "oic.r.scanner",
        "oic.r.selectablelevels", "oic.r.switch.binary", "oic.r.temperature", "oic.r.time.period"
    };
    for (size_t i = 0; i < sizeof(wellDefined) / sizeof(wellDefined[0]); ++i)
    {
        if (!strcmp(wellDefined[i], name))
        {
            return true;
        }
    }
    return false;
}

bool TranslateInterface(const char *name)
{
    const char *doNotTranslatePrefix[] = {
        "org.alljoyn.Bus", "org.freedesktop.DBus"
    };
    for (size_t i = 0; i < sizeof(doNotTranslatePrefix) / sizeof(doNotTranslatePrefix[0]); ++i)
    {
        if (!strncmp(doNotTranslatePrefix[i], name, strlen(doNotTranslatePrefix[i])))
        {
            return false;
        }
    }
    const char *doNotTranslate[] = {
        "org.alljoyn.About", "org.alljoyn.Daemon", "org.alljoyn.Debug", "org.alljoyn.Icon",
        "org.allseen.Introspectable"
    };
    for (size_t i = 0; i < sizeof(doNotTranslate) / sizeof(doNotTranslate[0]); ++i)
    {
        if (!strcmp(doNotTranslate[i], name))
        {
            return false;
        }
    }
    const char *doDeepTranslation[] = {
        "org.alljoyn.Config"
    };
    for (size_t i = 0; i < sizeof(doDeepTranslation) / sizeof(doDeepTranslation[0]); ++i)
    {
        if (!strcmp(doDeepTranslation[i], name))
        {
            return true;
        }
    }
    return !IsInterfaceInWellDefinedSet(name);
}

bool TranslateResourceType(const char *name)
{
    const char *doNotTranslate[] = {
        "oic.d.bridge",
        OC_RSRVD_RESOURCE_TYPE_COLLECTION, OC_RSRVD_RESOURCE_TYPE_INTROSPECTION,
        OC_RSRVD_RESOURCE_TYPE_RD, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH, OC_RSRVD_RESOURCE_TYPE_RES,
        "oic.r.alljoynobject", "oic.r.acl", "oic.r.acl2", "oic.r.amacl", "oic.r.cred", "oic.r.crl",
        "oic.r.csr", "oic.r.doxm", "oic.r.pstat", "oic.r.roles", "oic.r.securemode"
    };
    for (size_t i = 0; i < sizeof(doNotTranslate) / sizeof(doNotTranslate[0]); ++i)
    {
        if (!strcmp(doNotTranslate[i], name))
        {
            return false;
        }
    }
    const char *doDeepTranslation[] = {
        OC_RSRVD_RESOURCE_TYPE_DEVICE, OC_RSRVD_RESOURCE_TYPE_DEVICE_CONFIGURATION,
        OC_RSRVD_RESOURCE_TYPE_MAINTENANCE, OC_RSRVD_RESOURCE_TYPE_PLATFORM,
        OC_RSRVD_RESOURCE_TYPE_PLATFORM_CONFIGURATION
    };
    for (size_t i = 0; i < sizeof(doDeepTranslation) / sizeof(doDeepTranslation[0]); ++i)
    {
        if (!strcmp(doDeepTranslation[i], name))
        {
            return true;
        }
    }
    return !IsResourceTypeInWellDefinedSet(name);
}
<|endoftext|>