<commit_before>#include "mjolnir/graphtilebuilder.h"

#include <boost/filesystem/operations.hpp>

using namespace valhalla::baldr;

namespace valhalla {
namespace mjolnir {

GraphTileBuilder::GraphTileBuilder() {

}

// Output the tile to file. Stores as binary data.

bool GraphTileBuilder::StoreTileData(const std::string& basedirectory,
                                     const GraphId& graphid) {
  // Get the name of the file
  boost::filesystem::path filename = Filename(basedirectory, graphid);
  // Make sure the directory exists on the system
  if (!boost::filesystem::exists(filename.parent_path()))
    boost::filesystem::create_directories(filename.parent_path());

  // Open to the end of the file so we can immediately get size;
  std::ofstream file(filename.c_str(),
                     std::ios::out | std::ios::binary | std::ios::ate);
  if (file.is_open()) {
    // Write the header. TODO - add edge info offset and name list offset
    header_builder_.set_nodecount(nodes_builder_.size());
    header_builder_.set_directededgecount(directededges_builder_.size());
    file.write(reinterpret_cast<const char*>(&header_builder_),
               sizeof header_builder_);

    // Write the nodes
    file.write(reinterpret_cast<const char*>(&nodes_builder_[0]),
               nodes_builder_.size() * sizeof(NodeInfoBuilder));

    // Write the directed edges
    file.write(reinterpret_cast<const char*>(&directededges_builder_[0]),
               directededges_builder_.size() * sizeof(DirectedEdgeBuilder));

    // Write the edge data
    file.write(reinterpret_cast<const char*>(&edgeinfo_builder_[0]),
               edgeinfo_size_);

    // Write the names
    file.write(reinterpret_cast<const char*>(&textlist_builder_[0]),
               textlist_size_);

    std::cout << "Write: " << filename << " nodes = " << nodes_builder_.size()
              << " directededges = " << directededges_builder_.size()
              << " edges = " << edgeinfo_builder_.size() << " textlist = "
              << textlist_builder_.size() << std::endl;

    file.close();
    return true;
  } else {
    std::cout << "Failed to open file " << filename << std::endl;
  }
  return false;
}

void GraphTileBuilder::AddNodeAndDirectedEdges(
    const NodeInfoBuilder& node,
    const std::vector<DirectedEdgeBuilder>& directededges) {
  // Add the node to the list
  nodes_builder_.push_back(node);

  // For each directed edge need to set its common edge offset
  for (const auto& directededge : directededges) {
    // Add the directed edge to the list
    directededges_builder_.push_back(directededge);
  }

}

void GraphTileBuilder::SetEdgeInfoAndSize(
    const std::vector<EdgeInfoBuilder>& edges,
    const std::size_t edgeinfo_size) {

  // TODO - change to move?
  if (!edges.empty()) {
    edgeinfo_builder_.insert(edgeinfo_builder_.end(), edges.begin(),
                             edges.end());
  }

  // Set edgeinfo data size
  edgeinfo_size_ = edgeinfo_size;
}

void GraphTileBuilder::SetTextListAndSize(const std::vector<std::string>& textlist,
                        const std::size_t textlist_size) {
  // TODO move
  if (!textlist.empty()) {
    textlist_builder_.insert(textlist_builder_.end(), textlist.begin(),
                             textlist.end());
  // Set textlist data size
    textlist_size_ = textlist_size;
  }
}

}
}

<commit_msg>header assignment updates temp debug<commit_after>#include "mjolnir/graphtilebuilder.h"

#include <boost/filesystem/operations.hpp>

using namespace valhalla::baldr;

namespace valhalla {
namespace mjolnir {

GraphTileBuilder::GraphTileBuilder() {

}

// Output the tile to file. Stores as binary data.

bool GraphTileBuilder::StoreTileData(const std::string& basedirectory,
                                     const GraphId& graphid) {
  // Get the name of the file
  boost::filesystem::path filename = Filename(basedirectory, graphid);
  // Make sure the directory exists on the system
  if (!boost::filesystem::exists(filename.parent_path()))
    boost::filesystem::create_directories(filename.parent_path());

  // Open to the end of the file so we can immediately get size;
  std::ofstream file(filename.c_str(),
                     std::ios::out | std::ios::binary | std::ios::ate);
  if (file.is_open()) {
    // Configure the header
    header_builder_.set_nodecount(nodes_builder_.size());
    header_builder_.set_directededgecount(directededges_builder_.size());
    header_builder_.set_edgeinfo_offset(
        (sizeof(GraphTileHeaderBuilder))
            + (nodes_builder_.size() * sizeof(NodeInfoBuilder))
            + (directededges_builder_.size() * sizeof(DirectedEdgeBuilder)));
    header_builder_.set_textlist_offset(
        header_builder_.edgeinfo_offset() + edgeinfo_size_);

    // Write the header.
    file.write(reinterpret_cast<const char*>(&header_builder_),
               sizeof(GraphTileHeaderBuilder));

    // Write the nodes
    file.write(reinterpret_cast<const char*>(&nodes_builder_[0]),
               nodes_builder_.size() * sizeof(NodeInfoBuilder));

    // Write the directed edges
    file.write(reinterpret_cast<const char*>(&directededges_builder_[0]),
               directededges_builder_.size() * sizeof(DirectedEdgeBuilder));

    // Write the edge data
    file.write(reinterpret_cast<const char*>(&edgeinfo_builder_[0]),
               edgeinfo_size_);

    // Write the names
    file.write(reinterpret_cast<const char*>(&textlist_builder_[0]),
               textlist_size_);

    std::cout << "Write: " << filename << " nodes = " << nodes_builder_.size()
              << " directededges = " << directededges_builder_.size()
              << " edgeinfo size = " << edgeinfo_size_ << " textlist size = "
              << textlist_size_ << std::endl;

    file.close();
    return true;
  } else {
    std::cout << "Failed to open file " << filename << std::endl;
  }
  return false;
}

void GraphTileBuilder::AddNodeAndDirectedEdges(
    const NodeInfoBuilder& node,
    const std::vector<DirectedEdgeBuilder>& directededges) {
  // Add the node to the list
  nodes_builder_.push_back(node);

  // For each directed edge need to set its common edge offset
  for (const auto& directededge : directededges) {
    // Add the directed edge to the list
    directededges_builder_.push_back(directededge);
  }

}

void GraphTileBuilder::SetEdgeInfoAndSize(
    const std::vector<EdgeInfoBuilder>& edges,
    const std::size_t edgeinfo_size) {

  // TODO - change to move?
  if (!edges.empty()) {
    edgeinfo_builder_.insert(edgeinfo_builder_.end(), edges.begin(),
                             edges.end());
  }

  // Set edgeinfo data size
  edgeinfo_size_ = edgeinfo_size;
}

void GraphTileBuilder::SetTextListAndSize(
    const std::vector<std::string>& textlist, const std::size_t textlist_size) {
  // TODO move
  if (!textlist.empty()) {
    textlist_builder_.insert(textlist_builder_.end(), textlist.begin(),
                             textlist.end());
  }

  // Set textlist data size
  textlist_size_ = textlist_size;

  // TODO rm later
  size_t computed_size = 0;
  for (const auto& name : textlist_builder_) {
    if (name.empty())
      continue;
    computed_size += name.length() + 1;
  }
  std::cout << ">>>>> TEXTLIST computed_size = " << computed_size
            << "  textlist_size_ = " << textlist_size_ << std::endl;
}

}
}

<|endoftext|>


<commit_before>//******************************************************************
//
// Copyright 2014 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 <random>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <map>
#include <sstream>
#include <string>

#include <InProcServerWrapper.h>
#include <InitializeException.h>
#include <OCReflect.h>
#include <OCResourceRequest.h>
#include <OCResourceResponse.h>
#include <ocstack.h>
#include <OCApi.h>
#include <OCUtilities.h>

using namespace OC::OCReflect;

using namespace std;

std::map <OCResourceHandle, std::function<void(const OC::OCResourceRequest::Ptr, const OC::OCResourceResponse::Ptr)>> entityHandlerMap;

void defaultEntityHandler(const OC::OCResourceRequest::Ptr request, const OC::OCResourceResponse::Ptr response)
{
    cout << "\nSomething wrong: We are in default entity handler: " << endl;
}

OCStackResult entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest ) {

    // TODO @SASHI we need to have a better way of logging (with various levels of logging)
    cout << "\nIn C entity handler: " << endl;

    // TODO @SASHI dow we need shared pointer?
    auto pRequest = std::make_shared<OC::OCResourceRequest>();
    auto pResponse = std::make_shared<OC::OCResourceResponse>();

    // TODO @ SASHI Utility to convert from C to C++ (every).
    switch (flag) {
        case OC_INIT_FLAG:
            // TODO @SASHI We can fill the common data (resource Handle, etc.. )
            // init time.
            pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
            break;
        case OC_REQUEST_FLAG:
            pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);

            if(entityHandlerRequest)
            {
                if(entityHandlerRequest->query)
                {
                    std::string querystr(reinterpret_cast<char*>(entityHandlerRequest->query));
                    OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(querystr);
                    if(qp.size() > 0)
                        pRequest->setQueryParams(qp);
                }
                if(OC_REST_GET == entityHandlerRequest->method)
                {
                    // TODO @SASHI Why strings : "GET"??
                    pRequest->setRequestType("GET");
                }

                if(OC_REST_PUT == entityHandlerRequest->method)
                {
                    pRequest->setRequestType("PUT");
                    pRequest->setPayload(std::string(reinterpret_cast<const char*>(entityHandlerRequest->reqJSONPayload)));
                }
            }
            break;
        case OC_OBSERVE_FLAG:
            pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::ObserverFlag);
            break;
    }

    // Finding the corresponding CPP Application entityHandler for a given resource
    auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource);

    if(entityHandlerEntry != entityHandlerMap.end()) {
        // Call CPP Application Entity Handler
        entityHandlerEntry->second(pRequest, pResponse);
    }
    else {
        std::cout << "No eintity handler found."  << endl;
        return OC_STACK_ERROR;
    }

    if(flag == OC_REQUEST_FLAG)
    {
        // TODO @SASHI we could use const reference
        std::string payLoad = pResponse->getPayload();

        if(OC_REST_GET == entityHandlerRequest->method)
        {
            cout << "\t\t\tGoing from stack for GET: " << payLoad << endl;
        }
        else if (OC_REST_PUT == entityHandlerRequest->method)
        {
            cout << "\t\t\tGoing from stack for PUT: " << payLoad << endl;
        }

        else
        {
            cout << "\t\t\t Unknown method...!!!" << endl;
        }
        // TODO @SASHI Now there is memory that needs to be freed.
        entityHandlerRequest->resJSONPayload = reinterpret_cast<unsigned char *>(OC::OCReflect::OCStack::strdup(payLoad.c_str()));

        if(nullptr == entityHandlerRequest->resJSONPayload)
        {
            // TODO @SASHI throw std::runtime_error("out of memory");
            cout << "Out of memory in copying to resJSONPayload" << endl;
        }
    }

    return OC_STACK_OK;
}

namespace OC
{
    InProcServerWrapper::InProcServerWrapper(std::weak_ptr<std::mutex> csdkLock, PlatformConfig cfg)
                            :m_csdkLock(csdkLock)
    {
        OCMode initType;

        if(cfg.mode == ModeType::Server)
        {
            initType = OC_SERVER;
        }
        else if (cfg.mode == ModeType::Both)
        {
            initType = OC_CLIENT_SERVER;
        }
        else
        {
            throw InitializeException("Cannot construct a Server when configured as a client", OC_STACK_INVALID_PARAM);
        }

        OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);

        // Setting default entity Handler
        entityHandlerMap[(OCResourceHandle) 0] = defaultEntityHandler;

        if(OC_STACK_OK != result)
        {
            throw InitializeException("Error Initializing Stack", result);
        }

        m_threadRun = true;
        m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
    }

    void InProcServerWrapper::processFunc()
    {
        auto cLock = m_csdkLock.lock();
        while(cLock && m_threadRun)
        {
            OCStackResult result;
            {
                std::lock_guard<std::mutex> lock(*cLock);
                result = OCProcess();
            }

            if(result != OC_STACK_OK)
            {
                cout << "Something wrong in OCProcess" << endl;
                // TODO: SASHI
            }

            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            // To minimize CPU utilization we may wish to do this with sleep
            //std::this_thread::sleep_for(std::chrono::milliseconds(1));
        }
    }

    OCStackResult InProcServerWrapper::registerResource(
                    OCResourceHandle& resourceHandle,
                    std::string& resourceURI,
                    const std::string& resourceTypeName,
                    const std::string& resourceInterface,
                    std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> eHandler,
                    uint8_t resourceProperties)

    {
        OCStackResult  result;

        cout << "Registering Resource: \n";
        cout << "\tResource URI: " << resourceURI << endl;
        cout << "\tResource TypeName: " << resourceTypeName  << endl;
        cout << "\tResource Interface: " << resourceInterface << endl;

        auto cLock = m_csdkLock.lock();

        if(cLock)
        {
            std::lock_guard<std::mutex> lock(*cLock);

            result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
                            resourceTypeName.c_str(), // const char * resourceTypeName
                            resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
                            resourceURI.c_str(), // const char * uri
                            entityHandler, // OCEntityHandler entityHandler
                            resourceProperties // uint8_t resourceProperties
                            );

            if(result != OC_STACK_OK)
            {
                cout << "\tSomething wrong in creating the resource" << endl;
                resourceHandle = (OCResourceHandle) 0;
                // TODO: SASHI
            }
            else
            {
                cout << "\tResource creation is successful with resource handle:  " << resourceHandle << endl;
                entityHandlerMap[resourceHandle] = eHandler;
            }
        }
        else
        {
            result = OC_STACK_ERROR;
        }

        return result;
    }

    OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
                     const std::string& resourceTypeName)
    {
        cout << "Binding Type to Resource: \n";
        cout << "\tTypeName: " << resourceTypeName  << endl;

        auto cLock = m_csdkLock.lock();
        OCStackResult result;
        if(cLock)
        {
            std::lock_guard<std::mutex> lock(*cLock);
            result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
        }
        else
        {
            result = OC_STACK_ERROR;
        }

        if (result != OC_STACK_OK)
        {
            throw OCException("Bind Type to resource failed", result);
        }
        return result;
    }

    OCStackResult InProcServerWrapper::bindInterfaceToResource(const OCResourceHandle& resourceHandle,
                     const std::string& resourceInterfaceName)
    {
        cout << "Binding Interface to Resource: \n";
        cout << "\tInterfaceName: " << resourceInterfaceName  << endl;

        auto cLock = m_csdkLock.lock();
        OCStackResult result;
        if(cLock)
        {
            std::lock_guard<std::mutex> lock(*cLock);
            result = OCBindResourceInterfaceToResource(resourceHandle, resourceInterfaceName.c_str());
        }
        else
        {
            result = OC_STACK_ERROR;
        }

        if (result != OC_STACK_OK)
        {
            throw OCException("Bind Interface to resource failed", result);
        }
        return result;
    }

    InProcServerWrapper::~InProcServerWrapper()
    {
        if(m_processThread.joinable())
        {
            m_threadRun = false;
            m_processThread.join();
        }

        OCStop();
    }
}
<commit_msg>Fix build error. Now the entityHandler has its own return type<commit_after>//******************************************************************
//
// Copyright 2014 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 <random>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <map>
#include <sstream>
#include <string>

#include <InProcServerWrapper.h>
#include <InitializeException.h>
#include <OCReflect.h>
#include <OCResourceRequest.h>
#include <OCResourceResponse.h>
#include <ocstack.h>
#include <OCApi.h>
#include <OCUtilities.h>

using namespace OC::OCReflect;

using namespace std;

std::map <OCResourceHandle, std::function<void(const OC::OCResourceRequest::Ptr, const OC::OCResourceResponse::Ptr)>> entityHandlerMap;

void defaultEntityHandler(const OC::OCResourceRequest::Ptr request, const OC::OCResourceResponse::Ptr response)
{
    cout << "\nSomething wrong: We are in default entity handler: " << endl;
}

OCEntityHandlerResult entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest ) {

    // TODO @SASHI we need to have a better way of logging (with various levels of logging)
    cout << "\nIn C entity handler: " << endl;

    // TODO @SASHI dow we need shared pointer?
    auto pRequest = std::make_shared<OC::OCResourceRequest>();
    auto pResponse = std::make_shared<OC::OCResourceResponse>();

    // TODO @ SASHI Utility to convert from C to C++ (every).
    switch (flag) {
        case OC_INIT_FLAG:
            // TODO @SASHI We can fill the common data (resource Handle, etc.. )
            // init time.
            pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
            break;
        case OC_REQUEST_FLAG:
            pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);

            if(entityHandlerRequest)
            {
                if(entityHandlerRequest->query)
                {
                    std::string querystr(reinterpret_cast<char*>(entityHandlerRequest->query));
                    OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(querystr);
                    if(qp.size() > 0)
                        pRequest->setQueryParams(qp);
                }
                if(OC_REST_GET == entityHandlerRequest->method)
                {
                    // TODO @SASHI Why strings : "GET"??
                    pRequest->setRequestType("GET");
                }

                if(OC_REST_PUT == entityHandlerRequest->method)
                {
                    pRequest->setRequestType("PUT");
                    pRequest->setPayload(std::string(reinterpret_cast<const char*>(entityHandlerRequest->reqJSONPayload)));
                }
            }
            break;
        case OC_OBSERVE_FLAG:
            pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::ObserverFlag);
            break;
    }

    // Finding the corresponding CPP Application entityHandler for a given resource
    auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource);

    if(entityHandlerEntry != entityHandlerMap.end()) {
        // Call CPP Application Entity Handler
        entityHandlerEntry->second(pRequest, pResponse);
    }
    else {
        std::cout << "No eintity handler found."  << endl;
        return OC_EH_ERROR;
    }

    if(flag == OC_REQUEST_FLAG)
    {
        // TODO @SASHI we could use const reference
        std::string payLoad = pResponse->getPayload();

        if(OC_REST_GET == entityHandlerRequest->method)
        {
            cout << "\t\t\tGoing from stack for GET: " << payLoad << endl;
        }
        else if (OC_REST_PUT == entityHandlerRequest->method)
        {
            cout << "\t\t\tGoing from stack for PUT: " << payLoad << endl;
        }

        else
        {
            cout << "\t\t\t Unknown method...!!!" << endl;
        }
        // TODO @SASHI Now there is memory that needs to be freed.
        entityHandlerRequest->resJSONPayload = reinterpret_cast<unsigned char *>(OC::OCReflect::OCStack::strdup(payLoad.c_str()));

        if(nullptr == entityHandlerRequest->resJSONPayload)
        {
            // TODO @SASHI throw std::runtime_error("out of memory");
            cout << "Out of memory in copying to resJSONPayload" << endl;
        }
    }

    return OC_EH_OK;
}

namespace OC
{
    InProcServerWrapper::InProcServerWrapper(std::weak_ptr<std::mutex> csdkLock, PlatformConfig cfg)
                            :m_csdkLock(csdkLock)
    {
        OCMode initType;

        if(cfg.mode == ModeType::Server)
        {
            initType = OC_SERVER;
        }
        else if (cfg.mode == ModeType::Both)
        {
            initType = OC_CLIENT_SERVER;
        }
        else
        {
            throw InitializeException("Cannot construct a Server when configured as a client", OC_STACK_INVALID_PARAM);
        }

        OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);

        // Setting default entity Handler
        entityHandlerMap[(OCResourceHandle) 0] = defaultEntityHandler;

        if(OC_STACK_OK != result)
        {
            throw InitializeException("Error Initializing Stack", result);
        }

        m_threadRun = true;
        m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
    }

    void InProcServerWrapper::processFunc()
    {
        auto cLock = m_csdkLock.lock();
        while(cLock && m_threadRun)
        {
            OCStackResult result;
            {
                std::lock_guard<std::mutex> lock(*cLock);
                result = OCProcess();
            }

            if(result != OC_STACK_OK)
            {
                cout << "Something wrong in OCProcess" << endl;
                // TODO: SASHI
            }

            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            // To minimize CPU utilization we may wish to do this with sleep
            //std::this_thread::sleep_for(std::chrono::milliseconds(1));
        }
    }

    OCStackResult InProcServerWrapper::registerResource(
                    OCResourceHandle& resourceHandle,
                    std::string& resourceURI,
                    const std::string& resourceTypeName,
                    const std::string& resourceInterface,
                    std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> eHandler,
                    uint8_t resourceProperties)

    {
        OCStackResult  result;

        cout << "Registering Resource: \n";
        cout << "\tResource URI: " << resourceURI << endl;
        cout << "\tResource TypeName: " << resourceTypeName  << endl;
        cout << "\tResource Interface: " << resourceInterface << endl;

        auto cLock = m_csdkLock.lock();

        if(cLock)
        {
            std::lock_guard<std::mutex> lock(*cLock);

            result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
                            resourceTypeName.c_str(), // const char * resourceTypeName
                            resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
                            resourceURI.c_str(), // const char * uri
                            entityHandler, // OCEntityHandler entityHandler
                            resourceProperties // uint8_t resourceProperties
                            );

            if(result != OC_STACK_OK)
            {
                cout << "\tSomething wrong in creating the resource" << endl;
                resourceHandle = (OCResourceHandle) 0;
                // TODO: SASHI
            }
            else
            {
                cout << "\tResource creation is successful with resource handle:  " << resourceHandle << endl;
                entityHandlerMap[resourceHandle] = eHandler;
            }
        }
        else
        {
            result = OC_STACK_ERROR;
        }

        return result;
    }

    OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
                     const std::string& resourceTypeName)
    {
        cout << "Binding Type to Resource: \n";
        cout << "\tTypeName: " << resourceTypeName  << endl;

        auto cLock = m_csdkLock.lock();
        OCStackResult result;
        if(cLock)
        {
            std::lock_guard<std::mutex> lock(*cLock);
            result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
        }
        else
        {
            result = OC_STACK_ERROR;
        }

        if (result != OC_STACK_OK)
        {
            throw OCException("Bind Type to resource failed", result);
        }
        return result;
    }

    OCStackResult InProcServerWrapper::bindInterfaceToResource(const OCResourceHandle& resourceHandle,
                     const std::string& resourceInterfaceName)
    {
        cout << "Binding Interface to Resource: \n";
        cout << "\tInterfaceName: " << resourceInterfaceName  << endl;

        auto cLock = m_csdkLock.lock();
        OCStackResult result;
        if(cLock)
        {
            std::lock_guard<std::mutex> lock(*cLock);
            result = OCBindResourceInterfaceToResource(resourceHandle, resourceInterfaceName.c_str());
        }
        else
        {
            result = OC_STACK_ERROR;
        }

        if (result != OC_STACK_OK)
        {
            throw OCException("Bind Interface to resource failed", result);
        }
        return result;
    }

    InProcServerWrapper::~InProcServerWrapper()
    {
        if(m_processThread.joinable())
        {
            m_threadRun = false;
            m_processThread.join();
        }

        OCStop();
    }
}
<|endoftext|>


<commit_before>#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <iostream>
#include <algorithm>

using namespace std;

typedef short id_t;

const id_t INVALID_ID = -1;
const id_t ID_COUNT = (1 << 15) - 1;
const int DECK_SIZE = 60;
const int CARD_NAME_SIZE = 64;
const int PLAYER_NAME_SIZE = 128;

id_t NEXT_PLAYER_ID = 0;
id_t NEXT_CARD_ID = 0;

const char * deck_file_name = "decks.dat";
const char * player_file_name = "players.dat";
const char * card_file_name = "cards.dat";
const char * report_file_name = "report.txt";

enum Color {
	Red, Black, Blue, White, Green, ColorCount, Invalid = -1
};

const char * color_names[ColorCount] = {"Red", "Black", "Blue", "White", "Green"};

struct Player {
	id_t id;
	char name[PLAYER_NAME_SIZE];
};

struct Card {
	id_t id;
	char name[CARD_NAME_SIZE];
	Color color;
};

struct Deck {
	id_t owner;
	Color color;
	id_t cards[DECK_SIZE];
};

Player * players = nullptr;
int player_count = 0;
Card * cards = nullptr;
int card_count = 0;

// returns false only if program can't continue
bool load();
// returns false on any error
bool save();

// commands
void create_deck();
void create_card();
void create_player();
void report();

// helpers
Color name_to_color(const char * color_name);
bool load_players();
bool load_cards();
bool save(const char * file_name, const char * data, int size);

int main() {
	load();

	char cmd[8];
	while (cin >> cmd) {
		if (!strcmp(cmd, "cd")) {
			create_deck();
		} else if (!strcmp(cmd, "cc")) {
			create_card();
		} else if (!strcmp(cmd, "cp")) {
			create_player();
		} else if (!strcmp(cmd, "report")) {
			report();
		} else {
			break;
		}
	}
	cerr.flush();

	if (!save()) {
		cerr << "Failed to save files" << endl;
	}
	return 0;
}

////////////////////////
/// Loading & Saving
////////////////////////

bool load() {
	return load_players() && load_cards();
}

bool save() {
	bool result = save(player_file_name, (const char*)players, player_count) && save(card_file_name, (const char *)cards, card_count);
	delete[] cards;
	delete[] players;
	return result;
}

////////////////////////
/// Commands
////////////////////////

void create_deck() {
	Player owner = {INVALID_ID, ""};
	Card input_cards[DECK_SIZE];
	for (int c = 0; c < 60; ++c) {
		input_cards[c].id = INVALID_ID;
		input_cards[c].color = Invalid;
	}

	Deck deck = {owner.id, Invalid, {0, }};

	// input
	cin.ignore();
	cin.getline(owner.name, PLAYER_NAME_SIZE);
	for (int c = 0; c < DECK_SIZE; ++c) {
		cin.getline(input_cards[c].name, CARD_NAME_SIZE);
	}

	// check owner
	for (int c = 0; c < player_count; ++c) {
		if (!strcmp(owner.name, players[c].name)) {
			owner = players[c];
			break;
		}
	}

	if (owner.id == INVALID_ID) {
		cerr << "Failed to find owner" << endl;
		return;
	}
	deck.owner = owner.id;

	// check cards
	int color_histogram[ColorCount] = {0, };
	for (int c = 0; c < DECK_SIZE; ++c) {
		for (int r = 0; r < card_count; ++r) {
			if (!strcmp(input_cards[c].name, cards[r].name)) {
				input_cards[c] = cards[r]; // get color & id
			}
		}
		if (input_cards[c].id == INVALID_ID) {
			cerr << "Failed to find card " << input_cards[c].name << endl;
			return;
		}

		color_histogram[input_cards[c].color]++;
		deck.cards[c] = input_cards[c].id;
	}

	// find most common color
	deck.color = Red;
	for (int c = 0; c < ColorCount; ++c) {
		if (color_histogram[deck.color] < color_histogram[c]) {
			deck.color = (Color)c;
		}
	}

	// append to file
	ofstream deck_file(deck_file_name, ios::binary | ios::app | ios::ate);
	if (!deck_file.write((const char *)&deck, sizeof(deck))) {
		cerr << "Failed to add new deck" << endl;
		return;
	}
}

void create_card() {
	char color_name[16], card_name[2048];
	Card card = {INVALID_ID, "", Invalid};

	// input
	cin >> color_name;
	cin.ignore();
	cin.getline(card_name, 2048);
	strncpy(card.name, card_name, CARD_NAME_SIZE);
	card.name[CARD_NAME_SIZE - 1] = 0;
	card.color = name_to_color(color_name);

	// check for existence
	for (int c = 0; c < card_count; ++c) {
		if (!strcmp(card.name, cards[c].name)) {
			card.id = cards[c].id;
			break;
		}
	}

	if (card.id != INVALID_ID || card.color == Invalid) {
		cerr << "Failed to create card" << endl;
		return;
	}

	// allocate
	Card * new_cards = new (nothrow)Card[card_count + 1];
	if (!new_cards) {
		cerr << "Failed to create card" << endl;
		return;
	}
	memcpy(new_cards, cards, card_count * sizeof(Card));
	// add new player
	card.id = NEXT_CARD_ID++;
	new_cards[card_count++] = card;

	delete[] cards;
	cards = new_cards;
}

void create_player() {
	Player player = {INVALID_ID, ""};

	// input
	cin.ignore();
	cin.getline(player.name, PLAYER_NAME_SIZE);

	// check for existence
	for (int c = 0; c < player_count; ++c) {
		if (!strcmp(player.name, players[c].name)) {
			player.id = players[c].id;
			break;
		}
	}

	if (player.id != INVALID_ID) {
		cerr << "Failed to create player" << endl;
		return;
	}

	// allocate space
	Player * new_players = new (nothrow)Player[player_count + 1];
	if (!new_players) {
		cerr << "Failed to create player" << endl;
		return;
	}

	memcpy(new_players, players, player_count * sizeof(Player));
	// add new player
	player.id = NEXT_PLAYER_ID++;
	new_players[player_count++] = player;

	delete[] players;
	players = new_players;
}

void report() {
	ifstream deck_file(deck_file_name, ios::binary | ios::ate);

	int deck_count = deck_file.tellg() / sizeof(Deck);
	deck_file.seekg(0, ios::beg);

	Deck * decks = nullptr;
	if (deck_count > 0) {
		decks = new (nothrow)Deck[deck_count];
		if (!decks) {
			deck_count = 0;
		} else {
			deck_file.read((char*)decks, deck_count * sizeof(Deck));
		}
	}

	// will be used to count card occurances in decks card_histogram[CARD_ID]
	int * card_histogram = new (nothrow)int[ID_COUNT];
	if (!card_histogram) {
		delete[] decks;
		return;
	}
	// init with 0's
	memset(card_histogram, 0, ID_COUNT * sizeof(int));

	ofstream report_file(report_file_name, ios::trunc);
	if (!report_file) {
		cerr << "Failed to create report";
		delete[] decks;
		delete[] card_histogram;
		return;
	}

	// for each color output it's decks
	for (Color color = Red; color < ColorCount; color = (Color)(color + 1)) {
		report_file << color_names[color] << endl;
		for (int c = 0; c < deck_count; ++c) {
			const Deck & deck = decks[c];

			if (deck.color != color) {
				continue;
			}

			// find owner
			Player pl = {deck.owner, ""};
			for (int r = 0; r < player_count; ++r) {
				if (players[r].id == pl.id) {
					pl = players[r];
					break;
				}
			}

			// find first card
			Card first_card = {deck.cards[0], "", Invalid};
			for (int r = 0; r < card_count; ++r) {
				if (first_card.id == cards[r].id) {
					first_card = cards[r];
					break;
				}
			}

			// update histogram
			for (int r = 0; r < DECK_SIZE; ++r) {
				card_histogram[deck.cards[r]]++;
			}

			report_file << "    Owner: " << pl.name << " Card: " << first_card.name << " Color: " << color_names[first_card.color] << endl;
		}
	}

	// find max in card_histogram and find the corresponding Card
	Card most_common = {0, "", Invalid};
	for (id_t c = 0; c < ID_COUNT; ++c) {
		if (card_histogram[most_common.id] < card_histogram[c]) {
			most_common.id = c;
		}
	}

	for (int c = 0; c < card_count; ++c) {
		if (most_common.id == cards[c].id) {
			most_common = cards[c];
		}
	}

	if (most_common.id == INVALID_ID) {
		report_file << "Most common card:  Color: Red";
	} else {
		report_file << "Most common card: " << most_common.name << " Color: " << color_names[most_common.color];
	}

	// clean up
	delete[] decks;
	delete[] card_histogram;
}

////////////////////////
/// Helpers
////////////////////////

Color name_to_color(const char * color_name) {
	for (int c = 0; c < ColorCount; ++c) {
		if (!strcmp(color_names[c], color_name)) {
			return (Color)c;
		}
	}
	return Invalid;
}

bool load_players() {
	fstream player_file(player_file_name, ios::in | ios::binary);
	if (!player_file) {
		return true;
	}

	// get count
	player_file.seekg(0, ios::end);
	player_count = player_file.tellg() / sizeof(Player);
	players = new (nothrow) Player[player_count];
	if (!players) {
		return false;
	}

	// read
	player_file.seekg(0, ios::beg);
	if (!player_file.read((char*)players, player_count * sizeof(Player))) {
		return false;
	}

	// init next id
	for (int c = 0; c < card_count; ++c) {
		NEXT_PLAYER_ID = max(NEXT_PLAYER_ID, cards[c].id);
	}
	++NEXT_PLAYER_ID;
}

bool load_cards() {
	fstream cards_file(card_file_name, ios::in | ios::binary);
	if (!cards_file) {
		return true;
	}

	// get count
	cards_file.seekg(0, ios::end);
	card_count = cards_file.tellg() / sizeof(Player);
	cards = new (nothrow) Card[card_count];
	if (!cards) {
		return false;
	}

	// read
	cards_file.seekg(0, ios::beg);
	if (!cards_file.read((char*)cards, card_count * sizeof(Player))) {
		return false;
	}

	// init next id
	for (int c = 0; c < card_count; ++c) {
		NEXT_CARD_ID = max(NEXT_CARD_ID, cards[c].id);
	}
	++NEXT_CARD_ID;
}

bool save(const char * file_name, const char * data, int size) {
	ofstream file(file_name, ios::out | ios::trunc | ios::binary);
	if (!file) {
		return false;
	}

	if (!file.write(data, size)) {
		return false;
	}

	return true;
}<commit_msg>Minor fixes on hw1 solution<commit_after>#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <iostream>
#include <algorithm>

using namespace std;

typedef short id_t;

const id_t INVALID_ID = -1;
const id_t ID_COUNT = (1 << 15) - 1;
const int DECK_SIZE = 60;
const int CARD_NAME_SIZE = 64;
const int PLAYER_NAME_SIZE = 128;

id_t NEXT_PLAYER_ID = 0;
id_t NEXT_CARD_ID = 0;

const char * deck_file_name = "decks.dat";
const char * player_file_name = "players.dat";
const char * card_file_name = "cards.dat";
const char * report_file_name = "report.txt";

enum Color {
	Red, Black, Blue, White, Green, ColorCount, Invalid = -1
};

const char * color_names[ColorCount] = {"Red", "Black", "Blue", "White", "Green"};

struct Player {
	id_t id;
	char name[PLAYER_NAME_SIZE];
};

struct Card {
	id_t id;
	char name[CARD_NAME_SIZE];
	Color color;
};

struct Deck {
	id_t owner;
	Color color;
	id_t cards[DECK_SIZE];
};

Player * players = nullptr;
int player_count = 0;
Card * cards = nullptr;
int card_count = 0;

// returns false only if program can't continue
bool load();
// returns false on any error
bool save();

// commands
void create_deck();
void create_card();
void create_player();
void report();

// helpers
Color name_to_color(const char * color_name);
bool load_players();
bool load_cards();
bool save(const char * file_name, const char * data, int size);

int main() {
	if (load()) {
		cerr << "Failed while loading players & cards" << endl;
	}

	char cmd[8];
	while (cin >> cmd) {
		if (!strcmp(cmd, "cd")) {
			create_deck();
		} else if (!strcmp(cmd, "cc")) {
			create_card();
		} else if (!strcmp(cmd, "cp")) {
			create_player();
		} else if (!strcmp(cmd, "report")) {
			report();
		} else {
			cerr << "Command " << cmd << " not recognised - quitting" << endl;
			break;
		}
	}

	if (!save()) {
		cerr << "Failed to save files" << endl;
	}
	return 0;
}

////////////////////////
/// Loading & Saving
////////////////////////

bool load() {
	return load_players() && load_cards();
}

bool save() {
	bool result = save(player_file_name, (const char*)players, player_count) && save(card_file_name, (const char *)cards, card_count);
	delete[] cards;
	delete[] players;
	return result;
}

////////////////////////
/// Commands
////////////////////////

void create_deck() {
	Player owner = {INVALID_ID, ""};
	Card input_cards[DECK_SIZE];
	for (int c = 0; c < 60; ++c) {
		input_cards[c].id = INVALID_ID;
		input_cards[c].color = Invalid;
	}

	Deck deck = {owner.id, Invalid, {0, }};

	// input
	cin.ignore();
	cin.getline(owner.name, PLAYER_NAME_SIZE);
	for (int c = 0; c < DECK_SIZE; ++c) {
		cin.getline(input_cards[c].name, CARD_NAME_SIZE);
	}

	// check owner
	for (int c = 0; c < player_count; ++c) {
		if (!strcmp(owner.name, players[c].name)) {
			owner = players[c];
			break;
		}
	}

	if (owner.id == INVALID_ID) {
		cerr << "Failed to find owner" << endl;
		return;
	}
	deck.owner = owner.id;

	// check cards
	int color_histogram[ColorCount] = {0, };
	for (int c = 0; c < DECK_SIZE; ++c) {
		for (int r = 0; r < card_count; ++r) {
			if (!strcmp(input_cards[c].name, cards[r].name)) {
				input_cards[c] = cards[r]; // get color & id
			}
		}
		if (input_cards[c].id == INVALID_ID) {
			cerr << "Failed to find card " << input_cards[c].name << endl;
			return;
		}

		color_histogram[input_cards[c].color]++;
		deck.cards[c] = input_cards[c].id;
	}

	// find most common color
	deck.color = Red;
	for (int c = 0; c < ColorCount; ++c) {
		if (color_histogram[deck.color] < color_histogram[c]) {
			deck.color = (Color)c;
		}
	}

	// append to file
	ofstream deck_file(deck_file_name, ios::binary | ios::app | ios::ate);
	if (!deck_file.write((const char *)&deck, sizeof(deck))) {
		cerr << "Failed to add new deck" << endl;
		return;
	}
}

void create_card() {
	char color_name[16], card_name[2048];
	Card card = {INVALID_ID, "", Invalid};

	// input
	cin >> color_name;
	cin.ignore();
	cin.getline(card_name, 2048);
	strncpy(card.name, card_name, CARD_NAME_SIZE);
	card.name[CARD_NAME_SIZE - 1] = 0;
	card.color = name_to_color(color_name);

	// check for existence
	for (int c = 0; c < card_count; ++c) {
		if (!strcmp(card.name, cards[c].name)) {
			card.id = cards[c].id;
			break;
		}
	}

	if (card.id != INVALID_ID || card.color == Invalid) {
		cerr << "Failed to create card" << endl;
		return;
	}

	// allocate
	Card * new_cards = new (nothrow)Card[card_count + 1];
	if (!new_cards) {
		cerr << "Failed to create card" << endl;
		return;
	}
	memcpy(new_cards, cards, card_count * sizeof(Card));
	// add new player
	card.id = NEXT_CARD_ID++;
	new_cards[card_count++] = card;

	delete[] cards;
	cards = new_cards;
}

void create_player() {
	Player player = {INVALID_ID, ""};

	// input
	cin.ignore();
	cin.getline(player.name, PLAYER_NAME_SIZE);

	// check for existence
	for (int c = 0; c < player_count; ++c) {
		if (!strcmp(player.name, players[c].name)) {
			player.id = players[c].id;
			break;
		}
	}

	if (player.id != INVALID_ID) {
		cerr << "Failed to create player" << endl;
		return;
	}

	// allocate space
	Player * new_players = new (nothrow)Player[player_count + 1];
	if (!new_players) {
		cerr << "Failed to create player" << endl;
		return;
	}

	memcpy(new_players, players, player_count * sizeof(Player));
	// add new player
	player.id = NEXT_PLAYER_ID++;
	new_players[player_count++] = player;

	delete[] players;
	players = new_players;
}

void report() {
	ifstream deck_file(deck_file_name, ios::binary | ios::ate);

	int deck_count = deck_file.tellg() / sizeof(Deck);
	deck_file.seekg(0, ios::beg);

	Deck * decks = nullptr;
	if (deck_count > 0) {
		decks = new (nothrow)Deck[deck_count];
		if (!decks) {
			deck_count = 0;
		} else {
			deck_file.read((char*)decks, deck_count * sizeof(Deck));
		}
	}

	// will be used to count card occurances in decks card_histogram[CARD_ID]
	int * card_histogram = new (nothrow)int[ID_COUNT];
	if (!card_histogram) {
		delete[] decks;
		return;
	}
	// init with 0's
	memset(card_histogram, 0, ID_COUNT * sizeof(int));

	ofstream report_file(report_file_name, ios::trunc);
	if (!report_file) {
		cerr << "Failed to create report";
		delete[] decks;
		delete[] card_histogram;
		return;
	}

	// for each color output it's decks
	for (Color color = Red; color < ColorCount; color = (Color)(color + 1)) {
		report_file << color_names[color] << endl;
		for (int c = 0; c < deck_count; ++c) {
			const Deck & deck = decks[c];

			if (deck.color != color) {
				continue;
			}

			// find owner
			Player pl = {deck.owner, ""};
			for (int r = 0; r < player_count; ++r) {
				if (players[r].id == pl.id) {
					pl = players[r];
					break;
				}
			}

			// find first card
			Card first_card = {deck.cards[0], "", Invalid};
			for (int r = 0; r < card_count; ++r) {
				if (first_card.id == cards[r].id) {
					first_card = cards[r];
					break;
				}
			}

			// update histogram
			for (int r = 0; r < DECK_SIZE; ++r) {
				card_histogram[deck.cards[r]]++;
			}

			report_file << "    Owner: " << pl.name << " Card: " << first_card.name << " Color: " << color_names[first_card.color] << endl;
		}
	}

	// find max in card_histogram and find the corresponding Card
	Card most_common = {0, "", Invalid};
	for (id_t c = 0; c < ID_COUNT; ++c) {
		if (card_histogram[most_common.id] < card_histogram[c]) {
			most_common.id = c;
		}
	}

	for (int c = 0; c < card_count; ++c) {
		if (most_common.id == cards[c].id) {
			most_common = cards[c];
		}
	}

	if (most_common.id == INVALID_ID) {
		report_file << "Most common card:  Color: Red";
	} else {
		report_file << "Most common card: " << most_common.name << " Color: " << color_names[most_common.color];
	}

	// clean up
	delete[] decks;
	delete[] card_histogram;
}

////////////////////////
/// Helpers
////////////////////////

Color name_to_color(const char * color_name) {
	for (int c = 0; c < ColorCount; ++c) {
		if (!strcmp(color_names[c], color_name)) {
			return (Color)c;
		}
	}
	return Invalid;
}

bool load_players() {
	fstream player_file(player_file_name, ios::in | ios::binary);
	if (!player_file) {
		return true;
	}

	// get count
	player_file.seekg(0, ios::end);
	player_count = player_file.tellg() / sizeof(Player);
	players = new (nothrow) Player[player_count];
	if (!players) {
		delete[] players;
		player_count = 0;
		return false;
	}

	// read
	player_file.seekg(0, ios::beg);
	if (!player_file.read((char*)players, player_count * sizeof(Player))) {
		delete[] players;
		player_count = 0;
		return false;
	}

	// init next id
	for (int c = 0; c < card_count; ++c) {
		NEXT_PLAYER_ID = max(NEXT_PLAYER_ID, cards[c].id);
	}
	++NEXT_PLAYER_ID;

	return true;
}

bool load_cards() {
	fstream cards_file(card_file_name, ios::in | ios::binary);
	if (!cards_file) {
		return true;
	}

	// get count
	cards_file.seekg(0, ios::end);
	card_count = cards_file.tellg() / sizeof(Player);
	cards = new (nothrow) Card[card_count];
	if (!cards) {
		delete[] cards;
		card_count = 0;
		return false;
	}

	// read
	cards_file.seekg(0, ios::beg);
	if (!cards_file.read((char*)cards, card_count * sizeof(Player))) {
		delete[] cards;
		card_count = 0;
		return false;
	}

	// init next id
	for (int c = 0; c < card_count; ++c) {
		NEXT_CARD_ID = max(NEXT_CARD_ID, cards[c].id);
	}
	++NEXT_CARD_ID;

	return true;
}

bool save(const char * file_name, const char * data, int size) {
	ofstream file(file_name, ios::out | ios::trunc | ios::binary);
	if (!file) {
		return false;
	}

	if (!file.write(data, size)) {
		return false;
	}

	return true;
}<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

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 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., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
// Ogre includes
#include "OgreStableHeaders.h"

#include "OgreResource.h"
#include "OgreResourceManager.h"
#include "OgreResourceBackgroundQueue.h"
#include "OgreLogManager.h"
#include "OgreException.h"

namespace Ogre
{
	//-----------------------------------------------------------------------
	Resource::Resource(ResourceManager* creator, const String& name, ResourceHandle handle,
		const String& group, bool isManual, ManualResourceLoader* loader)
		: mCreator(creator), mName(name), mGroup(group), mHandle(handle),
		mLoadingState(LOADSTATE_UNLOADED), mIsBackgroundLoaded(false),
		mSize(0), mIsManual(isManual), mLoader(loader), mStateCount(0)
	{
	}
	//-----------------------------------------------------------------------
	Resource::~Resource()
	{
	}
	//-----------------------------------------------------------------------
	void Resource::escalateLoading()
	{
		// Just call load as if this is the background thread, locking on
		// load status will prevent race conditions
		load(true);
	}
	//-----------------------------------------------------------------------
	void Resource::prepare()
	{
        // quick check that avoids any synchronisation
        if (mLoadingState.get() != LOADSTATE_UNLOADED) return;

        // atomically do slower check to make absolutely sure,
        // and set the load state to PREPARING
		if (!mLoadingState.cas(LOADSTATE_UNLOADED,LOADSTATE_PREPARING))
			return;

		// Scope lock for actual loading
        try
		{

			OGRE_LOCK_AUTO_MUTEX

			if (mIsManual)
			{
                if (mLoader)
				{
					mLoader->prepareResource(this);
				}
				else
				{
					// Warn that this resource is not reloadable
					LogManager::getSingleton().stream(LML_TRIVIAL)
						<< "WARNING: " << mCreator->getResourceType()
						<< " instance '" << mName << "' was defined as manually "
						<< "loaded, but no manual loader was provided. This Resource "
						<< "will be lost if it has to be reloaded.";
				}
			}
			else
			{
				if (mGroup == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
				{
					// Derive resource group
					changeGroupOwnership(
						ResourceGroupManager::getSingleton()
						.findGroupContainingResource(mName));
				}
				prepareImpl();
			}
		}
        catch (...)
        {
            mLoadingState.set(LOADSTATE_UNLOADED);
            throw;
        }

        mLoadingState.set(LOADSTATE_PREPARED);

		// Since we don't distinguish between GPU and CPU RAM, this
		// seems pointless
		//if(mCreator)
		//	mCreator->_notifyResourcePrepared(this);

		// Fire (deferred) events
		if (mIsBackgroundLoaded)
			queueFireBackgroundPreparingComplete();

	}

    void Resource::load(bool background)
	{
		// Early-out without lock (mitigate perf cost of ensuring loaded)
		// Don't load if:
		// 1. We're already loaded
		// 2. Another thread is loading right now
		// 3. We're marked for background loading and this is not the background
		//    loading thread we're being called by

        if (mIsBackgroundLoaded && !background) return;

        // quick check that avoids any synchronisation
        LoadingState old = mLoadingState.get();
        if (old!=LOADSTATE_UNLOADED && old!=LOADSTATE_PREPARED) return;

        // atomically do slower check to make absolutely sure,
        // and set the load state to LOADING
        if (!mLoadingState.cas(old,LOADSTATE_LOADING)) return;

		// Scope lock for actual loading
        try
		{

			OGRE_LOCK_AUTO_MUTEX

			if (mIsManual)
			{
                preLoadImpl();
				// Load from manual loader
				if (mLoader)
				{
					mLoader->loadResource(this);
				}
				else
				{
					// Warn that this resource is not reloadable
					LogManager::getSingleton().stream(LML_TRIVIAL)
						<< "WARNING: " << mCreator->getResourceType()
						<< " instance '" << mName << "' was defined as manually "
						<< "loaded, but no manual loader was provided. This Resource "
						<< "will be lost if it has to be reloaded.";
				}
                postLoadImpl();
			}
			else
			{

                if (old==LOADSTATE_UNLOADED)
                    prepareImpl();

                preLoadImpl();

                old = LOADSTATE_PREPARED;

				if (mGroup == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
				{
					// Derive resource group
					changeGroupOwnership(
						ResourceGroupManager::getSingleton()
						.findGroupContainingResource(mName));
				}

				loadImpl();

                postLoadImpl();
			}

			// Calculate resource size
			mSize = calculateSize();

		}
        catch (...)
        {
            // Reset loading in-progress flag, in case failed for some reason.
            // We reset it to UNLOADED because the only other case is when
            // old == PREPARED in which case the loadImpl should wipe out
            // any prepared data since it might be invalid.
            mLoadingState.set(LOADSTATE_UNLOADED);
            // Re-throw
            throw;
        }

        mLoadingState.set(LOADSTATE_LOADED);
        _dirtyState();

		// Notify manager
		if(mCreator)
			mCreator->_notifyResourceLoaded(this);

		// Fire (deferred) events
		if (mIsBackgroundLoaded)
			queueFireBackgroundLoadingComplete();

	}
	//---------------------------------------------------------------------
	void Resource::_dirtyState()
	{
		// don't worry about threading here, count only ever increases so
		// doesn't matter if we get a lost increment (one is enough)
		++mStateCount;
	}
	//-----------------------------------------------------------------------
	void Resource::changeGroupOwnership(const String& newGroup)
	{
		if (mGroup != newGroup)
		{
			String oldGroup = mGroup;
			mGroup = newGroup;
			ResourceGroupManager::getSingleton()
				._notifyResourceGroupChanged(oldGroup, this);
		}
	}
	//-----------------------------------------------------------------------
	void Resource::unload(void)
	{
		// Early-out without lock (mitigate perf cost of ensuring unloaded)
        LoadingState old = mLoadingState.get();
        if (old!=LOADSTATE_LOADED && old!=LOADSTATE_PREPARED) return;

        if (!mLoadingState.cas(old,LOADSTATE_UNLOADING)) return;

		// Scope lock for actual unload
		{
			OGRE_LOCK_AUTO_MUTEX
            if (old==LOADSTATE_PREPARED) {
                unprepareImpl();
            } else {
                preUnloadImpl();
                unloadImpl();
                postUnloadImpl();
            }
		}

        mLoadingState.set(LOADSTATE_UNLOADED);

		// Notify manager
		// Note if we have gone from PREPARED to UNLOADED, then we haven't actually
		// unloaded, i.e. there is no memory freed on the GPU.
		if(old==LOADSTATE_LOADED && mCreator)
			mCreator->_notifyResourceUnloaded(this);

	}
	//-----------------------------------------------------------------------
	void Resource::reload(void)
	{
		OGRE_LOCK_AUTO_MUTEX
		if (mLoadingState.get() == LOADSTATE_LOADED)
		{
			unload();
			load();
		}
	}
	//-----------------------------------------------------------------------
	void Resource::touch(void)
	{
        // make sure loaded
        load();

		if(mCreator)
			mCreator->_notifyResourceTouched(this);
	}
	//-----------------------------------------------------------------------
	void Resource::addListener(Resource::Listener* lis)
	{
		OGRE_LOCK_MUTEX(mListenerListMutex)
		mListenerList.push_back(lis);
	}
	//-----------------------------------------------------------------------
	void Resource::removeListener(Resource::Listener* lis)
	{
		// O(n) but not called very often
		OGRE_LOCK_MUTEX(mListenerListMutex)
		mListenerList.remove(lis);
	}
	//-----------------------------------------------------------------------
	void Resource::queueFireBackgroundLoadingComplete(void)
	{
		// Lock the listener list
		OGRE_LOCK_MUTEX(mListenerListMutex)
		if(!mListenerList.empty())
			ResourceBackgroundQueue::getSingleton()._queueFireBackgroundLoadingComplete(this);
	}
	//-----------------------------------------------------------------------
	void Resource::_fireBackgroundLoadingComplete(void)
	{
		// Lock the listener list
		OGRE_LOCK_MUTEX(mListenerListMutex)
		for (ListenerList::iterator i = mListenerList.begin();
			i != mListenerList.end(); ++i)
		{
			(*i)->backgroundLoadingComplete(this);
		}
	}
	//-----------------------------------------------------------------------
	void Resource::queueFireBackgroundPreparingComplete(void)
	{
		// Lock the listener list
		OGRE_LOCK_MUTEX(mListenerListMutex)
		if(!mListenerList.empty())
			ResourceBackgroundQueue::getSingleton()._queueFireBackgroundPreparingComplete(this);
	}
	//-----------------------------------------------------------------------
	void Resource::_fireBackgroundPreparingComplete(void)
	{
		// Lock the listener list
		OGRE_LOCK_MUTEX(mListenerListMutex)
		for (ListenerList::iterator i = mListenerList.begin();
			i != mListenerList.end(); ++i)
		{
			(*i)->backgroundPreparingComplete(this);
		}
	}

}
<commit_msg>Patch 2827710: Resource::load race condition When using ResourceBackgroundQueue, foreground and background thread calls load() same time. In this case, one of those thread should be wait that loading process is complete, otherwise it accesses incomplete resource and crashes.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

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 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., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
// Ogre includes
#include "OgreStableHeaders.h"

#include "OgreResource.h"
#include "OgreResourceManager.h"
#include "OgreResourceBackgroundQueue.h"
#include "OgreLogManager.h"
#include "OgreException.h"

namespace Ogre
{
	//-----------------------------------------------------------------------
	Resource::Resource(ResourceManager* creator, const String& name, ResourceHandle handle,
		const String& group, bool isManual, ManualResourceLoader* loader)
		: mCreator(creator), mName(name), mGroup(group), mHandle(handle),
		mLoadingState(LOADSTATE_UNLOADED), mIsBackgroundLoaded(false),
		mSize(0), mIsManual(isManual), mLoader(loader), mStateCount(0)
	{
	}
	//-----------------------------------------------------------------------
	Resource::~Resource()
	{
	}
	//-----------------------------------------------------------------------
	void Resource::escalateLoading()
	{
		// Just call load as if this is the background thread, locking on
		// load status will prevent race conditions
		load(true);
	}
	//-----------------------------------------------------------------------
	void Resource::prepare()
	{
        // quick check that avoids any synchronisation
        LoadingState old = mLoadingState.get();
        if (old != LOADSTATE_UNLOADED && old != LOADSTATE_PREPARING) return;

        // atomically do slower check to make absolutely sure,
        // and set the load state to PREPARING
		if (!mLoadingState.cas(LOADSTATE_UNLOADED,LOADSTATE_PREPARING))
		{
			while( mLoadingState.get() == LOADSTATE_PREPARING )
			{
				OGRE_LOCK_AUTO_MUTEX
			}
			return;
		}

		// Scope lock for actual loading
        try
		{

			OGRE_LOCK_AUTO_MUTEX

			if (mIsManual)
			{
                if (mLoader)
				{
					mLoader->prepareResource(this);
				}
				else
				{
					// Warn that this resource is not reloadable
					LogManager::getSingleton().stream(LML_TRIVIAL)
						<< "WARNING: " << mCreator->getResourceType()
						<< " instance '" << mName << "' was defined as manually "
						<< "loaded, but no manual loader was provided. This Resource "
						<< "will be lost if it has to be reloaded.";
				}
			}
			else
			{
				if (mGroup == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
				{
					// Derive resource group
					changeGroupOwnership(
						ResourceGroupManager::getSingleton()
						.findGroupContainingResource(mName));
				}
				prepareImpl();
			}
		}
        catch (...)
        {
            mLoadingState.set(LOADSTATE_UNLOADED);
            throw;
        }

        mLoadingState.set(LOADSTATE_PREPARED);

		// Since we don't distinguish between GPU and CPU RAM, this
		// seems pointless
		//if(mCreator)
		//	mCreator->_notifyResourcePrepared(this);

		// Fire (deferred) events
		if (mIsBackgroundLoaded)
			queueFireBackgroundPreparingComplete();

	}

    void Resource::load(bool background)
	{
		// Early-out without lock (mitigate perf cost of ensuring loaded)
		// Don't load if:
		// 1. We're already loaded
		// 2. Another thread is loading right now
		// 3. We're marked for background loading and this is not the background
		//    loading thread we're being called by

        if (mIsBackgroundLoaded && !background) return;

        // quick check that avoids any synchronisation
        LoadingState old = mLoadingState.get();

		if ( old == LOADSTATE_PREPARING )
		{
			while( mLoadingState.get() == LOADSTATE_PREPARING )
			{
				OGRE_LOCK_AUTO_MUTEX
			}
			old = mLoadingState.get();
		}

		if (old!=LOADSTATE_UNLOADED && old!=LOADSTATE_PREPARED && old!=LOADSTATE_LOADING) return;

        // atomically do slower check to make absolutely sure,
        // and set the load state to LOADING
        if (old==LOADSTATE_LOADING || !mLoadingState.cas(old,LOADSTATE_LOADING))
		{
			while( mLoadingState.get() == LOADSTATE_LOADING )
			{
				OGRE_LOCK_AUTO_MUTEX
			}
			return;
		}

		// Scope lock for actual loading
        try
		{

			OGRE_LOCK_AUTO_MUTEX

			if (mIsManual)
			{
                preLoadImpl();
				// Load from manual loader
				if (mLoader)
				{
					mLoader->loadResource(this);
				}
				else
				{
					// Warn that this resource is not reloadable
					LogManager::getSingleton().stream(LML_TRIVIAL)
						<< "WARNING: " << mCreator->getResourceType()
						<< " instance '" << mName << "' was defined as manually "
						<< "loaded, but no manual loader was provided. This Resource "
						<< "will be lost if it has to be reloaded.";
				}
                postLoadImpl();
			}
			else
			{

                if (old==LOADSTATE_UNLOADED)
                    prepareImpl();

                preLoadImpl();

                old = LOADSTATE_PREPARED;

				if (mGroup == ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
				{
					// Derive resource group
					changeGroupOwnership(
						ResourceGroupManager::getSingleton()
						.findGroupContainingResource(mName));
				}

				loadImpl();

                postLoadImpl();
			}

			// Calculate resource size
			mSize = calculateSize();

		}
        catch (...)
        {
            // Reset loading in-progress flag, in case failed for some reason.
            // We reset it to UNLOADED because the only other case is when
            // old == PREPARED in which case the loadImpl should wipe out
            // any prepared data since it might be invalid.
            mLoadingState.set(LOADSTATE_UNLOADED);
            // Re-throw
            throw;
        }

        mLoadingState.set(LOADSTATE_LOADED);
        _dirtyState();

		// Notify manager
		if(mCreator)
			mCreator->_notifyResourceLoaded(this);

		// Fire (deferred) events
		if (mIsBackgroundLoaded)
			queueFireBackgroundLoadingComplete();

	}
	//---------------------------------------------------------------------
	void Resource::_dirtyState()
	{
		// don't worry about threading here, count only ever increases so
		// doesn't matter if we get a lost increment (one is enough)
		++mStateCount;
	}
	//-----------------------------------------------------------------------
	void Resource::changeGroupOwnership(const String& newGroup)
	{
		if (mGroup != newGroup)
		{
			String oldGroup = mGroup;
			mGroup = newGroup;
			ResourceGroupManager::getSingleton()
				._notifyResourceGroupChanged(oldGroup, this);
		}
	}
	//-----------------------------------------------------------------------
	void Resource::unload(void)
	{
		// Early-out without lock (mitigate perf cost of ensuring unloaded)
        LoadingState old = mLoadingState.get();
        if (old!=LOADSTATE_LOADED && old!=LOADSTATE_PREPARED) return;

        if (!mLoadingState.cas(old,LOADSTATE_UNLOADING)) return;

		// Scope lock for actual unload
		{
			OGRE_LOCK_AUTO_MUTEX
            if (old==LOADSTATE_PREPARED) {
                unprepareImpl();
            } else {
                preUnloadImpl();
                unloadImpl();
                postUnloadImpl();
            }
		}

        mLoadingState.set(LOADSTATE_UNLOADED);

		// Notify manager
		// Note if we have gone from PREPARED to UNLOADED, then we haven't actually
		// unloaded, i.e. there is no memory freed on the GPU.
		if(old==LOADSTATE_LOADED && mCreator)
			mCreator->_notifyResourceUnloaded(this);

	}
	//-----------------------------------------------------------------------
	void Resource::reload(void)
	{
		OGRE_LOCK_AUTO_MUTEX
		if (mLoadingState.get() == LOADSTATE_LOADED)
		{
			unload();
			load();
		}
	}
	//-----------------------------------------------------------------------
	void Resource::touch(void)
	{
        // make sure loaded
        load();

		if(mCreator)
			mCreator->_notifyResourceTouched(this);
	}
	//-----------------------------------------------------------------------
	void Resource::addListener(Resource::Listener* lis)
	{
		OGRE_LOCK_MUTEX(mListenerListMutex)
		mListenerList.push_back(lis);
	}
	//-----------------------------------------------------------------------
	void Resource::removeListener(Resource::Listener* lis)
	{
		// O(n) but not called very often
		OGRE_LOCK_MUTEX(mListenerListMutex)
		mListenerList.remove(lis);
	}
	//-----------------------------------------------------------------------
	void Resource::queueFireBackgroundLoadingComplete(void)
	{
		// Lock the listener list
		OGRE_LOCK_MUTEX(mListenerListMutex)
		if(!mListenerList.empty())
			ResourceBackgroundQueue::getSingleton()._queueFireBackgroundLoadingComplete(this);
	}
	//-----------------------------------------------------------------------
	void Resource::_fireBackgroundLoadingComplete(void)
	{
		// Lock the listener list
		OGRE_LOCK_MUTEX(mListenerListMutex)
		for (ListenerList::iterator i = mListenerList.begin();
			i != mListenerList.end(); ++i)
		{
			(*i)->backgroundLoadingComplete(this);
		}
	}
	//-----------------------------------------------------------------------
	void Resource::queueFireBackgroundPreparingComplete(void)
	{
		// Lock the listener list
		OGRE_LOCK_MUTEX(mListenerListMutex)
		if(!mListenerList.empty())
			ResourceBackgroundQueue::getSingleton()._queueFireBackgroundPreparingComplete(this);
	}
	//-----------------------------------------------------------------------
	void Resource::_fireBackgroundPreparingComplete(void)
	{
		// Lock the listener list
		OGRE_LOCK_MUTEX(mListenerListMutex)
		for (ListenerList::iterator i = mListenerList.begin();
			i != mListenerList.end(); ++i)
		{
			(*i)->backgroundPreparingComplete(this);
		}
	}

}
<|endoftext|>


<commit_before>#ifndef __REPLICATION_MASTERSTORE_HPP__
#define __REPLICATION_MASTERSTORE_HPP__

#include "store.hpp"
#include "arch/arch.hpp"
#include "concurrency/mutex.hpp"
#include "containers/thick_list.hpp"
#include "replication/net_structs.hpp"

namespace replication {

class masterstore_exc_t : public std::runtime_error {
public:
    masterstore_exc_t(const char *wat) : std::runtime_error(wat) { }
};

class masterstore_t {

    bool has_slave() { return slave_ != NULL; }
    void add_slave(tcp_conn_t *conn);

    void hello();

    void get_cas(store_key_t *key, castime_t castime);

    void set(store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime);
    void add(store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime);
    void replace(store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime);
    void cas(store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, cas_t unique, castime_t castime);
    void incr(store_key_t *key, uint64_t amount, castime_t castime);
    void decr(store_key_t *key, uint64_t amount, castime_t castime);
    void append(store_key_t *key, data_provider_t *data, castime_t castime);
    void prepend(store_key_t *key, data_provider_t *data, castime_t castime);
    void delete_key(store_key_t *key);

private:
    // Spawns a coroutine.
    void send_data_with_ident(data_provider_t *data, uint32_t ident);

    template <class net_struct_type>
    void setlike(int msgcode, store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime);

    template <class net_struct_type>
    void stereotypical(int msgcode, store_key_t *key, data_provider_t *data, net_struct_type netstruct);

    mutex_t message_contiguity_;
    tcp_conn_t *slave_;
    thick_list<data_provider_t *, uint32_t> sources_;

};

}  // namespace replication

#endif  // __REPLICATION_MASTERSTORE_HPP__
<commit_msg>Added DISABLE_COPYING to masterstore_t.<commit_after>#ifndef __REPLICATION_MASTERSTORE_HPP__
#define __REPLICATION_MASTERSTORE_HPP__

#include "store.hpp"
#include "arch/arch.hpp"
#include "concurrency/mutex.hpp"
#include "containers/thick_list.hpp"
#include "replication/net_structs.hpp"

namespace replication {

class masterstore_exc_t : public std::runtime_error {
public:
    masterstore_exc_t(const char *wat) : std::runtime_error(wat) { }
};

class masterstore_t {
public:
    masterstore_t() { }

    bool has_slave() { return slave_ != NULL; }
    void add_slave(tcp_conn_t *conn);

    void hello();

    void get_cas(store_key_t *key, castime_t castime);

    void set(store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime);
    void add(store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime);
    void replace(store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime);
    void cas(store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, cas_t unique, castime_t castime);
    void incr(store_key_t *key, uint64_t amount, castime_t castime);
    void decr(store_key_t *key, uint64_t amount, castime_t castime);
    void append(store_key_t *key, data_provider_t *data, castime_t castime);
    void prepend(store_key_t *key, data_provider_t *data, castime_t castime);
    void delete_key(store_key_t *key);

private:
    // Spawns a coroutine.
    void send_data_with_ident(data_provider_t *data, uint32_t ident);

    template <class net_struct_type>
    void setlike(int msgcode, store_key_t *key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime);

    template <class net_struct_type>
    void stereotypical(int msgcode, store_key_t *key, data_provider_t *data, net_struct_type netstruct);

    mutex_t message_contiguity_;
    tcp_conn_t *slave_;
    thick_list<data_provider_t *, uint32_t> sources_;

    DISABLE_COPYING(masterstore_t);
};

}  // namespace replication

#endif  // __REPLICATION_MASTERSTORE_HPP__
<|endoftext|>


<commit_before>/*
Copyright libCellML Contributors

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 "libcellml/importsource.h"

namespace libcellml {

/**
 * @brief The ImportSource::ImportSourceImpl struct.
 *
 * The private implementation for the ImportSource class.
 */
struct ImportSource::ImportSourceImpl
{
    std::string mReference;
};

ImportSource::ImportSource()
    : mPimpl(new ImportSourceImpl())
{
}

ImportSource::~ImportSource()
{
    delete mPimpl;
}

ImportSource::ImportSource(const ImportSource& rhs)
    : Entity(rhs)
    , mPimpl(new ImportSourceImpl())
{
    mPimpl->mReference = rhs.mPimpl->mReference;
}

ImportSource::ImportSource(ImportSource &&rhs)
    : Entity(std::move(rhs))
    , mPimpl(rhs.mPimpl)
{
    rhs.mPimpl = nullptr;
}

ImportSource& ImportSource::operator=(ImportSource e)
{
    Entity::operator= (e);
    e.swap(*this);
    return *this;
}

void ImportSource::swap(ImportSource &rhs)
{
    std::swap(this->mPimpl, rhs.mPimpl);
}

void ImportSource::setSource(const std::string &reference)
{
    mPimpl->mReference = reference;
}

std::string ImportSource::getSource() const
{
    return mPimpl->mReference;
}

}
<commit_msg>Update import source to match new documentation.<commit_after>/*
Copyright libCellML Contributors

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 "libcellml/importsource.h"

namespace libcellml {

/**
 * @brief The ImportSource::ImportSourceImpl struct.
 *
 * The private implementation for the ImportSource class.
 */
struct ImportSource::ImportSourceImpl
{
    std::string mSource;
};

ImportSource::ImportSource()
    : mPimpl(new ImportSourceImpl())
{
}

ImportSource::~ImportSource()
{
    delete mPimpl;
}

ImportSource::ImportSource(const ImportSource& rhs)
    : Entity(rhs)
    , mPimpl(new ImportSourceImpl())
{
    mPimpl->mSource = rhs.mPimpl->mSource;
}

ImportSource::ImportSource(ImportSource &&rhs)
    : Entity(std::move(rhs))
    , mPimpl(rhs.mPimpl)
{
    rhs.mPimpl = nullptr;
}

ImportSource& ImportSource::operator=(ImportSource e)
{
    Entity::operator= (e);
    e.swap(*this);
    return *this;
}

void ImportSource::swap(ImportSource &rhs)
{
    std::swap(this->mPimpl, rhs.mPimpl);
}

void ImportSource::setSource(const std::string &source)
{
    mPimpl->mSource = source;
}

std::string ImportSource::getSource() const
{
    return mPimpl->mSource;
}

}
<|endoftext|>


<commit_before>/**
 * @file rodsdateconditionwidget.h
 * @brief Implementation of RodsDateConditionWidget class
 *
 * The RodsDateConditionWidget class extends the class RodsConditionWidget and
 * implements a widget for entering a date/time condition for a GenQuery.
 *
 * Copyright (C) 2014-2015 University of Jyväskylä. All rights reserved.
 * License: The BSD 3-Clause License, see LICENSE file for details.
 *
 * @author Ilari Korhonen
 */

// application class RodsDateConditionWidget header
#include "rodsdateconditionwidget.h"

RodsDateConditionWidget::RodsDateConditionWidget(int rodsAttr, QString label, QWidget *parent)
{
    this->attr = rodsAttr;

    this->layout = new QHBoxLayout(this);
    this->layout->setMargin(4);
    this->layout->setAlignment(Qt::AlignLeft);

    this->labelWidget = new QLabel(label, this);
    this->layout->addWidget(this->labelWidget);

    this->condBox = new QComboBox(this);
    this->condBox->addItem("After", RodsDateConditionWidget::IsNewer);
    this->condBox->addItem("Before", RodsDateConditionWidget::IsOlder);
    this->condBox->addItem("Exactly", RodsDateConditionWidget::Equals);
    this->layout->addWidget(condBox);

    this->dateTime = new QDateTimeEdit();
    this->layout->addWidget(this->dateTime);
}

RodsDateConditionWidget::~RodsDateConditionWidget()
{
    delete (this->dateTime);
    delete (this->condBox);
    delete (this->labelWidget);
    delete (this->layout);
}

void RodsDateConditionWidget::evaluateConds(Kanki::RodsGenQuery *query)
{
    int opr = this->condBox->currentData().toInt();

    // get unix timestamp and pad it with zeros (for string comparison...)
    std::string value = QVariant(this->dateTime->dateTime().toTime_t()).toString().toStdString();
    value.insert(0, 11 - value.length(), '0');

    switch (opr)
    {
        case RodsDateConditionWidget::Equals:
            query->addQueryCondition(this->attr, Kanki::RodsGenQuery::isEqual, value);
        break;

        case RodsDateConditionWidget::IsNewer:
            query->addQueryCondition(this->attr, Kanki::RodsGenQuery::isGreaterOrEqual, value);
        break;

        case RodsDateConditionWidget::IsOlder:
            query->addQueryCondition(this->attr, Kanki::RodsGenQuery::isLessOrEqual, value);
        break;

        default:
        break;
    }
}
<commit_msg>RodsDateConditionWidget forgotten parent widget argument to superclass<commit_after>/**
 * @file rodsdateconditionwidget.h
 * @brief Implementation of RodsDateConditionWidget class
 *
 * The RodsDateConditionWidget class extends the class RodsConditionWidget and
 * implements a widget for entering a date/time condition for a GenQuery.
 *
 * Copyright (C) 2014-2015 University of Jyväskylä. All rights reserved.
 * License: The BSD 3-Clause License, see LICENSE file for details.
 *
 * @author Ilari Korhonen
 */

// application class RodsDateConditionWidget header
#include "rodsdateconditionwidget.h"

RodsDateConditionWidget::RodsDateConditionWidget(int rodsAttr, QString label, QWidget *parent)
    : RodsConditionWidget(parent)
{
    this->attr = rodsAttr;

    this->layout = new QHBoxLayout(this);
    this->layout->setMargin(4);
    this->layout->setAlignment(Qt::AlignLeft);

    this->labelWidget = new QLabel(label, this);
    this->layout->addWidget(this->labelWidget);

    this->condBox = new QComboBox(this);
    this->condBox->addItem("After", RodsDateConditionWidget::IsNewer);
    this->condBox->addItem("Before", RodsDateConditionWidget::IsOlder);
    this->condBox->addItem("Exactly", RodsDateConditionWidget::Equals);
    this->layout->addWidget(condBox);

    this->dateTime = new QDateTimeEdit();
    this->layout->addWidget(this->dateTime);
}

RodsDateConditionWidget::~RodsDateConditionWidget()
{
    delete (this->dateTime);
    delete (this->condBox);
    delete (this->labelWidget);
    delete (this->layout);
}

void RodsDateConditionWidget::evaluateConds(Kanki::RodsGenQuery *query)
{
    int opr = this->condBox->currentData().toInt();

    // get unix timestamp and pad it with zeros (for string comparison...)
    std::string value = QVariant(this->dateTime->dateTime().toTime_t()).toString().toStdString();
    value.insert(0, 11 - value.length(), '0');

    switch (opr)
    {
        case RodsDateConditionWidget::Equals:
            query->addQueryCondition(this->attr, Kanki::RodsGenQuery::isEqual, value);
        break;

        case RodsDateConditionWidget::IsNewer:
            query->addQueryCondition(this->attr, Kanki::RodsGenQuery::isGreaterOrEqual, value);
        break;

        case RodsDateConditionWidget::IsOlder:
            query->addQueryCondition(this->attr, Kanki::RodsGenQuery::isLessOrEqual, value);
        break;

        default:
        break;
    }
}
<|endoftext|>


<commit_before>#include "messages/layouts/messagelayout.hpp"
#include "singletons/emotemanager.hpp"
#include "singletons/settingsmanager.hpp"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QtGlobal>

#define MARGIN_LEFT (int)(8 * this->scale)
#define MARGIN_RIGHT (int)(8 * this->scale)
#define MARGIN_TOP (int)(4 * this->scale)
#define MARGIN_BOTTOM (int)(4 * this->scale)
#define COMPACT_EMOTES_OFFSET 6

namespace chatterino {
namespace messages {
namespace layouts {

MessageLayout::MessageLayout(MessagePtr _message)
    : message(_message)
    , buffer(nullptr)
{
    if (_message->flags & Message::Collapsed) {
        this->flags &= MessageLayout::Collapsed;
    }
}

Message *MessageLayout::getMessage()
{
    return this->message.get();
}

// Height
int MessageLayout::getHeight() const
{
    return container.getHeight();
}

// Layout
// return true if redraw is required
bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags)
{
    auto &emoteManager = singletons::EmoteManager::getInstance();

    bool layoutRequired = false;

    // check if width changed
    bool widthChanged = width != this->currentLayoutWidth;
    layoutRequired |= widthChanged;
    this->currentLayoutWidth = width;

    // check if emotes changed
    bool imagesChanged = this->emoteGeneration != emoteManager.getGeneration();
    layoutRequired |= imagesChanged;
    this->emoteGeneration = emoteManager.getGeneration();

    // check if text changed
    bool textChanged =
        this->fontGeneration != singletons::FontManager::getInstance().getGeneration();
    layoutRequired |= textChanged;
    this->fontGeneration = singletons::FontManager::getInstance().getGeneration();

    // check if work mask changed
    bool wordMaskChanged = this->currentWordFlags !=
                           flags;  // singletons::SettingManager::getInstance().getWordTypeMask();
    layoutRequired |= wordMaskChanged;
    this->currentWordFlags = flags;  // singletons::SettingManager::getInstance().getWordTypeMask();

    // check if timestamp format changed
    bool timestampFormatChanged =
        this->timestampFormat != singletons::SettingManager::getInstance().timestampFormat;

    layoutRequired |= timestampFormatChanged;

    // check if dpi changed
    bool scaleChanged = this->scale != scale;
    layoutRequired |= scaleChanged;
    this->scale = scale;
    imagesChanged |= scaleChanged;
    textChanged |= scaleChanged;

    // update word sizes if needed
    if (imagesChanged) {
        //        this->container.updateImages();
        this->flags &= MessageLayout::RequiresBufferUpdate;
    }
    if (textChanged) {
        //        this->container.updateText();
        this->flags &= MessageLayout::RequiresBufferUpdate;
    }
    if (widthChanged || wordMaskChanged) {
        this->deleteBuffer();
    }

    // return if no layout is required
    if (!layoutRequired) {
        return false;
    }

    this->actuallyLayout(width, flags);
    this->invalidateBuffer();

    return true;
}

void MessageLayout::actuallyLayout(int width, MessageElement::Flags flags)
{
    this->container.begin(width, this->scale, this->message->flags.value);

    for (const std::unique_ptr<MessageElement> &element : this->message->getElements()) {
        element->addToContainer(this->container, flags);
    }

    if (this->height != this->container.getHeight()) {
        this->deleteBuffer();
    }

    this->container.finish();
    this->height = this->container.getHeight();
}

// Painting
void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection,
                          bool isLastReadMessage, bool isWindowFocused)
{
    QPixmap *pixmap = this->buffer.get();
    singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();

    // create new buffer if required
    if (!pixmap) {
#ifdef Q_OS_MACOS
        pixmap =
            new QPixmap((int)(this->container.getWidth() * painter.device()->devicePixelRatioF()),
                        (int)(this->container.getHeight() * painter.device()->devicePixelRatioF()));
        pixmap->setDevicePixelRatio(painter.device()->devicePixelRatioF());
#else
        pixmap = new QPixmap(this->container.getWidth(), std::max(16, this->container.getHeight()));
#endif

        this->buffer = std::shared_ptr<QPixmap>(pixmap);
        this->bufferValid = false;
    }

    if (!this->bufferValid || !selection.isEmpty()) {
        this->updateBuffer(pixmap, messageIndex, selection);
    }

    // draw on buffer
    painter.drawPixmap(0, y, *pixmap);
    //    painter.drawPixmap(0, y, this->container.width, this->container.getHeight(), *pixmap);

    // draw disabled
    if (this->message->flags.HasFlag(Message::Disabled)) {
        painter.fillRect(0, y, pixmap->width(), pixmap->height(), themeManager.messages.disabled);
    }

    // draw gif emotes
    this->container.paintAnimatedElements(painter, y);

    // draw last read message line
    if (isLastReadMessage) {
        QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color()
                                       : themeManager.tabs.selected.backgrounds.unfocused.color();

        QBrush brush(color, Qt::VerPattern);

        painter.fillRect(0, y + this->container.getHeight() - 1, this->container.getWidth(), 1,
                         brush);
    }

    this->bufferValid = true;
}

void MessageLayout::updateBuffer(QPixmap *buffer, int messageIndex, Selection &selection)
{
    singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();

    QPainter painter(buffer);

    painter.setRenderHint(QPainter::SmoothPixmapTransform);

    // draw background
    painter.fillRect(buffer->rect(), this->message->flags & Message::Highlighted
                                         ? themeManager.messages.backgrounds.highlighted
                                         : themeManager.messages.backgrounds.regular);

    // draw selection
    if (!selection.isEmpty()) {
        this->container.paintSelection(painter, messageIndex, selection);
    }

    // draw message
    this->container.paintElements(painter);

#ifdef OHHEYITSFOURTF
    // debug
    painter.setPen(QColor(255, 0, 0));
    painter.drawRect(buffer->rect().x(), buffer->rect().y(), buffer->rect().width() - 1,
                     buffer->rect().height() - 1);

    QTextOption option;
    option.setAlignment(Qt::AlignRight | Qt::AlignTop);

    painter.drawText(QRectF(1, 1, this->container.width - 3, 1000),
                     QString::number(++this->bufferUpdatedCount), option);
#endif
}

void MessageLayout::invalidateBuffer()
{
    this->bufferValid = false;
}

void MessageLayout::deleteBuffer()
{
    this->buffer = nullptr;
}

// Elements
//    assert(QThread::currentThread() == QApplication::instance()->thread());

// returns nullptr if none was found

// fourtf: this should return a MessageLayoutItem
const MessageLayoutElement *MessageLayout::getElementAt(QPoint point)
{
    // go through all words and return the first one that contains the point.
    return this->container.getElementAt(point);
}

int MessageLayout::getLastCharacterIndex() const
{
    return this->container.getLastCharacterIndex();
}

int MessageLayout::getSelectionIndex(QPoint position)
{
    return this->container.getSelectionIndex(position);
}

void MessageLayout::addSelectionText(QString &str, int from, int to)
{
    this->container.addSelectionText(str, from, to);
}
}  // namespace layouts
}  // namespace messages
}  // namespace chatterino
<commit_msg>Fixed an issue where Badges and emotes were not rendered transparently in disabled messages<commit_after>#include "messages/layouts/messagelayout.hpp"
#include "singletons/emotemanager.hpp"
#include "singletons/settingsmanager.hpp"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QtGlobal>

#define MARGIN_LEFT (int)(8 * this->scale)
#define MARGIN_RIGHT (int)(8 * this->scale)
#define MARGIN_TOP (int)(4 * this->scale)
#define MARGIN_BOTTOM (int)(4 * this->scale)
#define COMPACT_EMOTES_OFFSET 6

namespace chatterino {
namespace messages {
namespace layouts {

MessageLayout::MessageLayout(MessagePtr _message)
    : message(_message)
    , buffer(nullptr)
{
    if (_message->flags & Message::Collapsed) {
        this->flags &= MessageLayout::Collapsed;
    }
}

Message *MessageLayout::getMessage()
{
    return this->message.get();
}

// Height
int MessageLayout::getHeight() const
{
    return container.getHeight();
}

// Layout
// return true if redraw is required
bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags)
{
    auto &emoteManager = singletons::EmoteManager::getInstance();

    bool layoutRequired = false;

    // check if width changed
    bool widthChanged = width != this->currentLayoutWidth;
    layoutRequired |= widthChanged;
    this->currentLayoutWidth = width;

    // check if emotes changed
    bool imagesChanged = this->emoteGeneration != emoteManager.getGeneration();
    layoutRequired |= imagesChanged;
    this->emoteGeneration = emoteManager.getGeneration();

    // check if text changed
    bool textChanged =
        this->fontGeneration != singletons::FontManager::getInstance().getGeneration();
    layoutRequired |= textChanged;
    this->fontGeneration = singletons::FontManager::getInstance().getGeneration();

    // check if work mask changed
    bool wordMaskChanged = this->currentWordFlags !=
                           flags;  // singletons::SettingManager::getInstance().getWordTypeMask();
    layoutRequired |= wordMaskChanged;
    this->currentWordFlags = flags;  // singletons::SettingManager::getInstance().getWordTypeMask();

    // check if timestamp format changed
    bool timestampFormatChanged =
        this->timestampFormat != singletons::SettingManager::getInstance().timestampFormat;

    layoutRequired |= timestampFormatChanged;

    // check if dpi changed
    bool scaleChanged = this->scale != scale;
    layoutRequired |= scaleChanged;
    this->scale = scale;
    imagesChanged |= scaleChanged;
    textChanged |= scaleChanged;

    // update word sizes if needed
    if (imagesChanged) {
        //        this->container.updateImages();
        this->flags &= MessageLayout::RequiresBufferUpdate;
    }
    if (textChanged) {
        //        this->container.updateText();
        this->flags &= MessageLayout::RequiresBufferUpdate;
    }
    if (widthChanged || wordMaskChanged) {
        this->deleteBuffer();
    }

    // return if no layout is required
    if (!layoutRequired) {
        return false;
    }

    this->actuallyLayout(width, flags);
    this->invalidateBuffer();

    return true;
}

void MessageLayout::actuallyLayout(int width, MessageElement::Flags flags)
{
    this->container.begin(width, this->scale, this->message->flags.value);

    for (const std::unique_ptr<MessageElement> &element : this->message->getElements()) {
        element->addToContainer(this->container, flags);
    }

    if (this->height != this->container.getHeight()) {
        this->deleteBuffer();
    }

    this->container.finish();
    this->height = this->container.getHeight();
}

// Painting
void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection,
                          bool isLastReadMessage, bool isWindowFocused)
{
    QPixmap *pixmap = this->buffer.get();
    singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();

    // create new buffer if required
    if (!pixmap) {
#ifdef Q_OS_MACOS
        pixmap =
            new QPixmap((int)(this->container.getWidth() * painter.device()->devicePixelRatioF()),
                        (int)(this->container.getHeight() * painter.device()->devicePixelRatioF()));
        pixmap->setDevicePixelRatio(painter.device()->devicePixelRatioF());
#else
        pixmap = new QPixmap(this->container.getWidth(), std::max(16, this->container.getHeight()));
#endif

        this->buffer = std::shared_ptr<QPixmap>(pixmap);
        this->bufferValid = false;
    }

    if (!this->bufferValid || !selection.isEmpty()) {
        this->updateBuffer(pixmap, messageIndex, selection);
    }

    // draw on buffer
    painter.drawPixmap(0, y, *pixmap);
    //    painter.drawPixmap(0, y, this->container.width, this->container.getHeight(), *pixmap);

    // draw gif emotes
    this->container.paintAnimatedElements(painter, y);

    // draw disabled
    if (this->message->flags.HasFlag(Message::Disabled)) {
        painter.fillRect(0, y, pixmap->width(), pixmap->height(), themeManager.messages.disabled);
    }

    // draw last read message line
    if (isLastReadMessage) {
        QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color()
                                       : themeManager.tabs.selected.backgrounds.unfocused.color();

        QBrush brush(color, Qt::VerPattern);

        painter.fillRect(0, y + this->container.getHeight() - 1, this->container.getWidth(), 1,
                         brush);
    }

    this->bufferValid = true;
}

void MessageLayout::updateBuffer(QPixmap *buffer, int messageIndex, Selection &selection)
{
    singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();

    QPainter painter(buffer);

    painter.setRenderHint(QPainter::SmoothPixmapTransform);

    // draw background
    painter.fillRect(buffer->rect(), this->message->flags & Message::Highlighted
                                         ? themeManager.messages.backgrounds.highlighted
                                         : themeManager.messages.backgrounds.regular);

    // draw selection
    if (!selection.isEmpty()) {
        this->container.paintSelection(painter, messageIndex, selection);
    }

    // draw message
    this->container.paintElements(painter);

#ifdef OHHEYITSFOURTF
    // debug
    painter.setPen(QColor(255, 0, 0));
    painter.drawRect(buffer->rect().x(), buffer->rect().y(), buffer->rect().width() - 1,
                     buffer->rect().height() - 1);

    QTextOption option;
    option.setAlignment(Qt::AlignRight | Qt::AlignTop);

    painter.drawText(QRectF(1, 1, this->container.width - 3, 1000),
                     QString::number(++this->bufferUpdatedCount), option);
#endif
}

void MessageLayout::invalidateBuffer()
{
    this->bufferValid = false;
}

void MessageLayout::deleteBuffer()
{
    this->buffer = nullptr;
}

// Elements
//    assert(QThread::currentThread() == QApplication::instance()->thread());

// returns nullptr if none was found

// fourtf: this should return a MessageLayoutItem
const MessageLayoutElement *MessageLayout::getElementAt(QPoint point)
{
    // go through all words and return the first one that contains the point.
    return this->container.getElementAt(point);
}

int MessageLayout::getLastCharacterIndex() const
{
    return this->container.getLastCharacterIndex();
}

int MessageLayout::getSelectionIndex(QPoint position)
{
    return this->container.getSelectionIndex(position);
}

void MessageLayout::addSelectionText(QString &str, int from, int to)
{
    this->container.addSelectionText(str, from, to);
}
}  // namespace layouts
}  // namespace messages
}  // namespace chatterino
<|endoftext|>