<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_pm_ocb_indir_setup_linear.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/// @file p9_pm_ocb_indir_setup_linear.C
/// @brief  Configure OCB Channel for Linear Streaming or Non-streaming mode

// *HWP HWP Owner       : Amit Kumar <akumar3@us.ibm.com>
// *HWP Backup HWP Owner: Greg Still <stillgs@us.ibm.com>
// *HWP FW Owner        : Sangeetha T S <sangeet2@in.ibm.com>
// *HWP Team            : PM
// *HWP Level           : 2
// *HWP Consumed by     : HS

#ifndef _P9_PM_OCB_INDIR_SETUP_LINEAR_H_
#define _P9_PM_OCB_INDIR_SETUP_LINEAR_H_

#include <fapi2.H>
#include <p9_pm_ocb_init.H>

typedef fapi2::ReturnCode (*p9_pm_ocb_indir_setup_linear_FP_t)
(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&,
 const p9ocb::PM_OCB_CHAN_NUM,
 const p9ocb::PM_OCB_CHAN_TYPE,
 const uint32_t);

extern "C"
{

//------------------------------------------------------------------------------
// Function prototype
//------------------------------------------------------------------------------
/// @brief  Configure OCB Channel for Linear Streaming or Non-streaming mode
/// @param[in]  i_target   Chip Target
/// @param[in]  i_ocb_chan select channel 0-3 to set up      (see p8_ocb_init.H)
/// @param[in]  i_ocb_type linear streaming or non-streaming (see p8_ocb_init.H)
/// @param[in]  i_ocb_bar  32-bit channel base address (29 bits + "000")
/// @return FAPI2_RC_SUCCESS on success, else error.

    fapi2::ReturnCode p9_pm_ocb_indir_setup_linear(
        const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
        const p9ocb::PM_OCB_CHAN_NUM  i_ocb_chan,
        const p9ocb::PM_OCB_CHAN_TYPE i_ocb_type,
        const uint32_t      i_ocb_bar);

} // extern "C"

#endif
<commit_msg>PM: P10 OCB Hardware Procedures (with new OCI headers)<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_pm_ocb_indir_setup_linear.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/// @file p9_pm_ocb_indir_setup_linear.C
/// @brief  Configure OCB Channel for Linear Streaming or Non-streaming mode

// *HWP HW Owner        : Greg Still <stillgs@us.ibm.com>
// *HWP FW Owner        : Amit Tendolkar <amit.tendolkar@in.ibm.com>
// *HWP Team            : PM
// *HWP Level           : 2
// *HWP Consumed by     : HS

#ifndef _P9_PM_OCB_INDIR_SETUP_LINEAR_H_
#define _P9_PM_OCB_INDIR_SETUP_LINEAR_H_

#include <fapi2.H>
#include <p9_pm_ocb_init.H>

typedef fapi2::ReturnCode (*p9_pm_ocb_indir_setup_linear_FP_t)
(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&,
 const p9ocb::PM_OCB_CHAN_NUM,
 const p9ocb::PM_OCB_CHAN_TYPE,
 const uint32_t);

extern "C"
{

//------------------------------------------------------------------------------
// Function prototype
//------------------------------------------------------------------------------
/// @brief  Configure OCB Channel for Linear Streaming or Non-streaming mode
/// @param[in]  i_target   Chip Target
/// @param[in]  i_ocb_chan select channel 0-3 to set up      (see p8_ocb_init.H)
/// @param[in]  i_ocb_type linear streaming or non-streaming (see p8_ocb_init.H)
/// @param[in]  i_ocb_bar  32-bit channel base address (29 bits + "000")
/// @return FAPI2_RC_SUCCESS on success, else error.

    fapi2::ReturnCode p9_pm_ocb_indir_setup_linear(
        const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
        const p9ocb::PM_OCB_CHAN_NUM  i_ocb_chan,
        const p9ocb::PM_OCB_CHAN_TYPE i_ocb_type,
        const uint32_t      i_ocb_bar);

} // extern "C"

#endif
<|endoftext|>


<commit_before>#include "spotLight.h"
#include "glm/gtx/string_cast.hpp"

std::string SpotLight::s_classBlock;
std::string SpotLight::s_typeName;

SpotLight::SpotLight(const std::string& _name, bool _dynamic) :
    PointLight(_name, _dynamic),
    m_direction(1.0,0.0,0.0),
    m_spotExponent(0.0),
    m_spotCutoff(0.0),
    m_spotCosCutoff(0.0) {

    m_type = LightType::SPOT;

}

SpotLight::~SpotLight() {

}

void SpotLight::setDirection(const glm::vec3 &_dir) {
    m_direction = _dir;
}

void SpotLight::setCutOff(float _cutoffAngle, float _exponent) {
    m_spotCutoff = _cutoffAngle;
    m_spotCosCutoff = cos(_cutoffAngle * 3.14159 / 180.0);
    m_spotExponent = _exponent;
}

void SpotLight::setupProgram( std::shared_ptr<ShaderProgram> _shader ) {
    if (m_dynamic) {
        PointLight::setupProgram(_shader);
        _shader->setUniformf(getUniformName()+".direction", m_direction);
        _shader->setUniformf(getUniformName()+".spotCosCutoff", m_spotCosCutoff);
        _shader->setUniformf(getUniformName()+".spotExponent", m_spotExponent);
    }
}

std::string SpotLight::getClassBlock() {
    if (s_classBlock.empty()) {
        s_classBlock = stringFromResource("spotLight.glsl")+"\n";
    }
    return s_classBlock;
}

std::string SpotLight::getInstanceAssignBlock() {
    std::string block = Light::getInstanceAssignBlock();

    if (!m_dynamic) {
        block += ", " + glm::to_string(m_position);
        if (m_attenuation!=0.0) {
            block += ", " + std::to_string(m_attenuation);
        }
        if (m_innerRadius!=0.0) {
            block += ", " + std::to_string(m_innerRadius);
        }
        if (m_outerRadius!=0.0) {
            block += ", " + std::to_string(m_outerRadius);
        }

        block += ", " + glm::to_string(m_direction);
        block += ", " + std::to_string(m_spotCosCutoff);
        block += ", " + std::to_string(m_spotExponent);

        block += ")";
    }
    return block;
}

const std::string& SpotLight::getTypeName() {

    return s_typeName;

}
<commit_msg>Forgot to initialize spot light type string<commit_after>#include "spotLight.h"
#include "glm/gtx/string_cast.hpp"

std::string SpotLight::s_classBlock;
std::string SpotLight::s_typeName = "SpotLight";

SpotLight::SpotLight(const std::string& _name, bool _dynamic) :
    PointLight(_name, _dynamic),
    m_direction(1.0,0.0,0.0),
    m_spotExponent(0.0),
    m_spotCutoff(0.0),
    m_spotCosCutoff(0.0) {

    m_type = LightType::SPOT;

}

SpotLight::~SpotLight() {

}

void SpotLight::setDirection(const glm::vec3 &_dir) {
    m_direction = _dir;
}

void SpotLight::setCutOff(float _cutoffAngle, float _exponent) {
    m_spotCutoff = _cutoffAngle;
    m_spotCosCutoff = cos(_cutoffAngle * 3.14159 / 180.0);
    m_spotExponent = _exponent;
}

void SpotLight::setupProgram( std::shared_ptr<ShaderProgram> _shader ) {
    if (m_dynamic) {
        PointLight::setupProgram(_shader);
        _shader->setUniformf(getUniformName()+".direction", m_direction);
        _shader->setUniformf(getUniformName()+".spotCosCutoff", m_spotCosCutoff);
        _shader->setUniformf(getUniformName()+".spotExponent", m_spotExponent);
    }
}

std::string SpotLight::getClassBlock() {
    if (s_classBlock.empty()) {
        s_classBlock = stringFromResource("spotLight.glsl")+"\n";
    }
    return s_classBlock;
}

std::string SpotLight::getInstanceAssignBlock() {
    std::string block = Light::getInstanceAssignBlock();

    if (!m_dynamic) {
        block += ", " + glm::to_string(m_position);
        if (m_attenuation!=0.0) {
            block += ", " + std::to_string(m_attenuation);
        }
        if (m_innerRadius!=0.0) {
            block += ", " + std::to_string(m_innerRadius);
        }
        if (m_outerRadius!=0.0) {
            block += ", " + std::to_string(m_outerRadius);
        }

        block += ", " + glm::to_string(m_direction);
        block += ", " + std::to_string(m_spotCosCutoff);
        block += ", " + std::to_string(m_spotExponent);

        block += ")";
    }
    return block;
}

const std::string& SpotLight::getTypeName() {

    return s_typeName;

}
<|endoftext|>


<commit_before>/** \file    Elasticsearch.cc
 *  \brief   Implementation of the Elasticsearch class.
 *  \author  Dr. Johannes Ruscheinski
 *  \author  Mario Trojan
 *
 *  \copyright 2018,2019 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "Elasticsearch.h"
#include "FileUtil.h"
#include "IniFile.h"
#include "UBTools.h"
#include "Url.h"

const std::string DEFAULT_CONFIG_FILE_PATH(UBTools::GetTuelibPath() + "Elasticsearch.conf");

static void LoadIniParameters(const std::string &config_file_path, std::string * const host, std::string * const username,
                              std::string * const password, bool * const ignore_ssl_certificates)
{
    if (not FileUtil::Exists(config_file_path))
        LOG_ERROR("Elasticsearch config file missing: " + config_file_path);

    const IniFile ini_file(config_file_path);

    *host                    = ini_file.getString("Elasticsearch", "host");
    *username                = ini_file.getString("Elasticsearch", "username", "");
    *password                = ini_file.getString("Elasticsearch", "password", "");
    *ignore_ssl_certificates = ini_file.getBool("Elasticsearch", "ignore_ssl_certificates", false);
}

Elasticsearch::Elasticsearch(const std::string &index, const std::string &type): index_(index), type_(type) {
    LoadIniParameters(DEFAULT_CONFIG_FILE_PATH, &host_, &username_, &password_, &ignore_ssl_certificates_);
}

size_t Elasticsearch::size() const {
    return JSON::LookupInteger("/_all/primaries/docs/count", query("_stats", REST::GET, JSON::ObjectNode()));
}

void Elasticsearch::simpleInsert(const std::map<std::string, std::string> &fields_and_values) {
    query("", REST::POST, JSON::ObjectNode(fields_and_values));
}

// A general comment as to the strategy we use in this function:
//
//    We know that there is an _update API endpoint, but as we insert a bunch of chunks, the number of which can change,
//    we have to use a "wildcard" strategy to first delete possibly existing chunks as the number of new chunks may be greater or
//    fewer than what may already be stored.
void Elasticsearch::insertOrUpdateDocument(const std::string &document_id, const std::string &document) {
    deleteDocument(document_id);
    simpleInsert({ { "id", document_id }, { "document", document } });
}

bool Elasticsearch::deleteDocument(const std::string &document_id) {
    const JSON::ObjectNode match_node("{ \"query\":"
                                      "    { \"match\":"
                                      "        { \"id\": \"" + JSON::EscapeString(document_id) + "\" }"
                                      "    }"
                                      "}");
    const auto result_node(query("_delete_by_query", REST::POST, match_node));
    return result_node->getIntegerNode("deleted")->getValue() > 0;
}

std::unordered_set<std::string> Elasticsearch::selectAll(const std::string &field) const {
    const std::vector<std::map<std::string, std::string>> result(simpleSelect({ field }));
    std::unordered_set<std::string> unique_values;
    for (const auto &map : result) {
        const auto key_and_value(map.find(field));
        if (key_and_value != map.cend())
            unique_values.emplace(key_and_value->second);
    }

    return unique_values;
}

std::vector<std::map<std::string, std::string>> Elasticsearch::simpleSelect(const std::set<std::string> &fields,
                                                                            const std::map<std::string, std::string> &filter,
                                                                            const int max_count) const
{
    std::string query_string("{\n");

    if (not fields.empty()) {
        query_string += "    \"_source\": [";
        for (const auto &field : fields)
            query_string += "\"" + field + "\", ";
        query_string.resize(query_string.size() - 2); // Remove trailing comma and space.
        query_string += "],\n";
    }

    query_string += "    \"query\": {";

    if (filter.empty())
        query_string += " \"match_all\" {}";
    else {
        query_string += "\"bool\" : { \"filter\": [\n";
        for (const auto &field_and_value : filter)
            query_string += "       { \"term\": { \"" + field_and_value.first + "\": \"" + field_and_value.second + "\"} },\n";
        query_string.resize(query_string.size() - 2); // Remove the last comma and newline.
        query_string += "\n    ] }";
    }

    query_string += "    },\n";
    query_string += "    \"size\": " + std::to_string(max_count) + "\n";
    query_string += "}\n";

    const auto result_node(query("_search", REST::POST, JSON::ObjectNode(query_string)));
    const auto hits_object_node(result_node->getObjectNode("hits"));
    if (unlikely(hits_object_node == nullptr))
        LOG_ERROR("missing \"hits\" object node in Elasticsearch result node!");
    const auto hits_array_node(hits_object_node->getArrayNode("hits"));
    if (unlikely(hits_array_node == nullptr))
        LOG_ERROR("missing \"hits\" array node in Elasticsearch result node!");

    std::vector<std::map<std::string, std::string>> search_results;
    search_results.reserve(hits_array_node->size());
    for (const auto entry_node : *hits_array_node) {
        std::map<std::string, std::string> new_map;
        const auto entry_object_node(JSON::JSONNode::CastToObjectNodeOrDie("entry_object_node", entry_node));
        for (const auto &entry : *entry_object_node) {
            if (fields.empty() or fields.find(entry.first) != fields.cend())
                new_map[entry.first] = JSON::JSONNode::CastToStringNodeOrDie("new_map[entry.first]", entry.second)->getValue();
        }

        search_results.resize(search_results.size() + 1);
        std::swap(search_results.back(), new_map);
    }

    return search_results;
}

static std::string ToString(const Elasticsearch::RangeOperator op) {
    switch (op) {
    case Elasticsearch::RO_GT:  return "gt";
    case Elasticsearch::RO_GTE: return "gte";
    case Elasticsearch::RO_LT:  return "lt";
    case Elasticsearch::RO_LTE: return "lte";
    default:
        LOG_ERROR("we should *never* get here!");
    }
}

bool Elasticsearch::deleteRange(const std::string &field, const RangeOperator operator1, const std::string &operand1,
                                const RangeOperator operator2, const std::string &operand2)
{
    const std::string range_node((operator2 == RO_NOOP or operand2.empty()) ?
                                    "{ \"query\":"
                                    "    { \"range\":"
                                    "        \"" + field + "\": {"
                                    "            \"" + ToString(operator1) + "\"" + operand1 + "\""
                                        + ((operator2 == RO_NOOP or operand2.empty())
                                               ? std::string()
                                               : "      ,\"" + ToString(operator2) + "\"" + operand2 + "\"") +
                                    "        }"
                                    "    }"
                                    "}"
                                                                            :
                                    "");
    const auto result_node(query("_delete", REST::POST, range_node));
    return result_node->getIntegerNode("deleted")->getValue() > 0;
}

bool Elasticsearch::fieldWithValueExists(const std::string &field, const std::string &value) {

   const auto result_node(
         query("_search", REST::GET,
              "{"
              "    \"query\": {"
              "        \"match\" : { \"" + field + "\" : \"" + value + "\" }"
              "    }"
              "}"
         ));

   const auto hits_node(result_node->getObjectNode("hits"));
   if (hits_node == nullptr)
       LOG_ERROR("No \"hits\" node in results");

   const auto total_node = hits_node->getIntegerNode("total");
   if (total_node == nullptr)
       LOG_ERROR("No \"total\" node found");
   return total_node->getValue() == 0 ? false : true;
}

std::shared_ptr<JSON::ObjectNode> Elasticsearch::query(const std::string &action, const REST::QueryType query_type,
                                                       const JSON::ObjectNode &data) const
{
    Downloader::Params downloader_params;
    downloader_params.authentication_username_ = username_;
    downloader_params.authentication_password_ = password_;
    downloader_params.ignore_ssl_certificates_ = ignore_ssl_certificates_;
    downloader_params.additional_headers_.push_back("Content-Type: application/json");
    const Url url(host_ + "/" + index_ + "/" + type_ + (action.empty() ? "" : "/" + action));
    std::shared_ptr<JSON::JSONNode> result(REST::QueryJSON(url, query_type, &data, downloader_params));
    std::shared_ptr<JSON::ObjectNode> result_object(JSON::JSONNode::CastToObjectNodeOrDie("Elasticsearch result", result));
    if (result_object->hasNode("error"))
        LOG_ERROR("Elasticsearch " + action + " query failed: " + result_object->getNode("error")->toString());

    return result_object;
}
<commit_msg>Execute as POST query<commit_after>/** \file    Elasticsearch.cc
 *  \brief   Implementation of the Elasticsearch class.
 *  \author  Dr. Johannes Ruscheinski
 *  \author  Mario Trojan
 *
 *  \copyright 2018,2019 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "Elasticsearch.h"
#include "FileUtil.h"
#include "IniFile.h"
#include "UBTools.h"
#include "Url.h"

const std::string DEFAULT_CONFIG_FILE_PATH(UBTools::GetTuelibPath() + "Elasticsearch.conf");

static void LoadIniParameters(const std::string &config_file_path, std::string * const host, std::string * const username,
                              std::string * const password, bool * const ignore_ssl_certificates)
{
    if (not FileUtil::Exists(config_file_path))
        LOG_ERROR("Elasticsearch config file missing: " + config_file_path);

    const IniFile ini_file(config_file_path);

    *host                    = ini_file.getString("Elasticsearch", "host");
    *username                = ini_file.getString("Elasticsearch", "username", "");
    *password                = ini_file.getString("Elasticsearch", "password", "");
    *ignore_ssl_certificates = ini_file.getBool("Elasticsearch", "ignore_ssl_certificates", false);
}

Elasticsearch::Elasticsearch(const std::string &index, const std::string &type): index_(index), type_(type) {
    LoadIniParameters(DEFAULT_CONFIG_FILE_PATH, &host_, &username_, &password_, &ignore_ssl_certificates_);
}

size_t Elasticsearch::size() const {
    return JSON::LookupInteger("/_all/primaries/docs/count", query("_stats", REST::GET, JSON::ObjectNode()));
}

void Elasticsearch::simpleInsert(const std::map<std::string, std::string> &fields_and_values) {
    query("", REST::POST, JSON::ObjectNode(fields_and_values));
}

// A general comment as to the strategy we use in this function:
//
//    We know that there is an _update API endpoint, but as we insert a bunch of chunks, the number of which can change,
//    we have to use a "wildcard" strategy to first delete possibly existing chunks as the number of new chunks may be greater or
//    fewer than what may already be stored.
void Elasticsearch::insertOrUpdateDocument(const std::string &document_id, const std::string &document) {
    deleteDocument(document_id);
    simpleInsert({ { "id", document_id }, { "document", document } });
}

bool Elasticsearch::deleteDocument(const std::string &document_id) {
    const JSON::ObjectNode match_node("{ \"query\":"
                                      "    { \"match\":"
                                      "        { \"id\": \"" + JSON::EscapeString(document_id) + "\" }"
                                      "    }"
                                      "}");
    const auto result_node(query("_delete_by_query", REST::POST, match_node));
    return result_node->getIntegerNode("deleted")->getValue() > 0;
}

std::unordered_set<std::string> Elasticsearch::selectAll(const std::string &field) const {
    const std::vector<std::map<std::string, std::string>> result(simpleSelect({ field }));
    std::unordered_set<std::string> unique_values;
    for (const auto &map : result) {
        const auto key_and_value(map.find(field));
        if (key_and_value != map.cend())
            unique_values.emplace(key_and_value->second);
    }

    return unique_values;
}

std::vector<std::map<std::string, std::string>> Elasticsearch::simpleSelect(const std::set<std::string> &fields,
                                                                            const std::map<std::string, std::string> &filter,
                                                                            const int max_count) const
{
    std::string query_string("{\n");

    if (not fields.empty()) {
        query_string += "    \"_source\": [";
        for (const auto &field : fields)
            query_string += "\"" + field + "\", ";
        query_string.resize(query_string.size() - 2); // Remove trailing comma and space.
        query_string += "],\n";
    }

    query_string += "    \"query\": {";

    if (filter.empty())
        query_string += " \"match_all\" {}";
    else {
        query_string += "\"bool\" : { \"filter\": [\n";
        for (const auto &field_and_value : filter)
            query_string += "       { \"term\": { \"" + field_and_value.first + "\": \"" + field_and_value.second + "\"} },\n";
        query_string.resize(query_string.size() - 2); // Remove the last comma and newline.
        query_string += "\n    ] }";
    }

    query_string += "    },\n";
    query_string += "    \"size\": " + std::to_string(max_count) + "\n";
    query_string += "}\n";

    const auto result_node(query("_search", REST::POST, JSON::ObjectNode(query_string)));
    const auto hits_object_node(result_node->getObjectNode("hits"));
    if (unlikely(hits_object_node == nullptr))
        LOG_ERROR("missing \"hits\" object node in Elasticsearch result node!");
    const auto hits_array_node(hits_object_node->getArrayNode("hits"));
    if (unlikely(hits_array_node == nullptr))
        LOG_ERROR("missing \"hits\" array node in Elasticsearch result node!");

    std::vector<std::map<std::string, std::string>> search_results;
    search_results.reserve(hits_array_node->size());
    for (const auto entry_node : *hits_array_node) {
        std::map<std::string, std::string> new_map;
        const auto entry_object_node(JSON::JSONNode::CastToObjectNodeOrDie("entry_object_node", entry_node));
        for (const auto &entry : *entry_object_node) {
            if (fields.empty() or fields.find(entry.first) != fields.cend())
                new_map[entry.first] = JSON::JSONNode::CastToStringNodeOrDie("new_map[entry.first]", entry.second)->getValue();
        }

        search_results.resize(search_results.size() + 1);
        std::swap(search_results.back(), new_map);
    }

    return search_results;
}

static std::string ToString(const Elasticsearch::RangeOperator op) {
    switch (op) {
    case Elasticsearch::RO_GT:  return "gt";
    case Elasticsearch::RO_GTE: return "gte";
    case Elasticsearch::RO_LT:  return "lt";
    case Elasticsearch::RO_LTE: return "lte";
    default:
        LOG_ERROR("we should *never* get here!");
    }
}

bool Elasticsearch::deleteRange(const std::string &field, const RangeOperator operator1, const std::string &operand1,
                                const RangeOperator operator2, const std::string &operand2)
{
    const std::string range_node((operator2 == RO_NOOP or operand2.empty()) ?
                                    "{ \"query\":"
                                    "    { \"range\":"
                                    "        \"" + field + "\": {"
                                    "            \"" + ToString(operator1) + "\"" + operand1 + "\""
                                        + ((operator2 == RO_NOOP or operand2.empty())
                                               ? std::string()
                                               : "      ,\"" + ToString(operator2) + "\"" + operand2 + "\"") +
                                    "        }"
                                    "    }"
                                    "}"
                                                                            :
                                    "");
    const auto result_node(query("_delete", REST::POST, range_node));
    return result_node->getIntegerNode("deleted")->getValue() > 0;
}

bool Elasticsearch::fieldWithValueExists(const std::string &field, const std::string &value) {

   const auto result_node(
         query("_search", REST::POST,
              "{"
              "    \"query\": {"
              "        \"match\" : { \"" + field + "\" : \"" + value + "\" }"
              "    }"
              "}"
         ));

   const auto hits_node(result_node->getObjectNode("hits"));
   if (hits_node == nullptr)
       LOG_ERROR("No \"hits\" node in results");

   const auto total_node = hits_node->getIntegerNode("total");
   if (total_node == nullptr)
       LOG_ERROR("No \"total\" node found");
   return total_node->getValue() == 0 ? false : true;
}

std::shared_ptr<JSON::ObjectNode> Elasticsearch::query(const std::string &action, const REST::QueryType query_type,
                                                       const JSON::ObjectNode &data) const
{
    Downloader::Params downloader_params;
    downloader_params.authentication_username_ = username_;
    downloader_params.authentication_password_ = password_;
    downloader_params.ignore_ssl_certificates_ = ignore_ssl_certificates_;
    downloader_params.additional_headers_.push_back("Content-Type: application/json");
    const Url url(host_ + "/" + index_ + "/" + type_ + (action.empty() ? "" : "/" + action));
    std::shared_ptr<JSON::JSONNode> result(REST::QueryJSON(url, query_type, &data, downloader_params));
    std::shared_ptr<JSON::ObjectNode> result_object(JSON::JSONNode::CastToObjectNodeOrDie("Elasticsearch result", result));
    if (result_object->hasNode("error"))
        LOG_ERROR("Elasticsearch " + action + " query failed: " + result_object->getNode("error")->toString());

    return result_object;
}
<|endoftext|>


<commit_before>#include <cassert>
#include <string>

#include "builtin.hh"
#include "cons.hh"
#include "cons_util.hh"
#include "procedure.hh"
#include "s_closure.hh"
#include "s_rules.hh"
#include "zs_error.hh"

using namespace proc_flag;

std::pair<int, Variadic> parse_func_arg(Lisp_ptr args){
  if(identifierp(args)){
    return {0, Variadic::t};
  }

  int argc = 0;

  auto i = begin(args);
  for(; i; ++i){
    if(!identifierp(*i)){
      throw_zs_error(args, "eval error: informal lambda list!");
    }
    ++argc;
  }

  if(nullp(i.base())){
    return {argc, Variadic::f};
  }else{
    if(!identifierp(i.base())){
      throw_zs_error(args, "eval error: informal lambda list!");
    }
    return {argc, Variadic::t};
  }
}

  // Continuation class

constexpr ProcInfo Continuation::cont_procinfo;

Continuation::Continuation(const VM& v)
  : vm_(v), name_(){}

Continuation::~Continuation() = default;

const ProcInfo* get_procinfo(Lisp_ptr p){
  if(!is_procedure(p.tag())) return nullptr;

  if(p.tag() == Ptr_tag::i_procedure){
    auto iproc = p.get<IProcedure*>();
    assert(iproc);
    return iproc->info();
  }else if(p.tag() == Ptr_tag::n_procedure){
    auto nproc = p.get<const NProcedure*>();
    assert(nproc);
    return nproc->info();
  }else if(p.tag() == Ptr_tag::continuation){
    auto cont = p.get<Continuation*>();
    assert(cont);
    return cont->info();
  }else if(p.tag() == Ptr_tag::syntax_rules){
    auto srule = p.get<SyntaxRules*>();
    assert(srule);
    return srule->info();
  }else{
    UNEXP_DEFAULT();
  }
}

Lisp_ptr get_procname(Lisp_ptr p){
  if(p.tag() == Ptr_tag::i_procedure){
    auto iproc = p.get<IProcedure*>();
    assert(iproc);
    return iproc->name();
  }else if(p.tag() == Ptr_tag::n_procedure){
    auto nproc = p.get<const NProcedure*>();
    assert(nproc);
    return zs_new<String>(find_builtin_nproc_name(nproc));
  }else if(p.tag() == Ptr_tag::continuation){
    auto cont = p.get<Continuation*>();
    assert(cont);
    return cont->name();
  }else if(p.tag() == Ptr_tag::syntax_rules){
    auto srule = p.get<SyntaxRules*>();
    assert(srule);
    return srule->name();
  }else{
    UNEXP_DEFAULT();
  }
}

void set_procname(Lisp_ptr p, Lisp_ptr n){
  if(p.tag() == Ptr_tag::i_procedure){
    auto iproc = p.get<IProcedure*>();
    assert(iproc);
    iproc->set_name(n);
  }else if(p.tag() == Ptr_tag::n_procedure){
    return;
  }else if(p.tag() == Ptr_tag::continuation){
    auto cont = p.get<Continuation*>();
    assert(cont);
    cont->set_name(n);
  }else if(p.tag() == Ptr_tag::syntax_rules){
    auto srule = p.get<SyntaxRules*>();
    assert(srule);
    srule->set_name(n);
  }else{
    UNEXP_DEFAULT();
  }
}
<commit_msg>cleanup procedure.cc (because of cons_util::begin cleanup<commit_after>#include <cassert>
#include <string>

#include "builtin.hh"
#include "cons.hh"
#include "cons_util.hh"
#include "procedure.hh"
#include "s_closure.hh"
#include "s_rules.hh"
#include "zs_error.hh"

using namespace proc_flag;

std::pair<int, Variadic> parse_func_arg(Lisp_ptr args){
  int argc = 0;

  auto i = begin(args);
  for(; i; ++i){
    if(!identifierp(*i)){
      throw_zs_error(args, "eval error: informal lambda list!");
    }
    ++argc;
  }

  if(nullp(i.base())){
    return {argc, Variadic::f};
  }else{
    if(!identifierp(i.base())){
      throw_zs_error(args, "eval error: informal lambda list!");
    }
    return {argc, Variadic::t};
  }
}

  // Continuation class

constexpr ProcInfo Continuation::cont_procinfo;

Continuation::Continuation(const VM& v)
  : vm_(v), name_(){}

Continuation::~Continuation() = default;

const ProcInfo* get_procinfo(Lisp_ptr p){
  if(!is_procedure(p.tag())) return nullptr;

  if(p.tag() == Ptr_tag::i_procedure){
    auto iproc = p.get<IProcedure*>();
    assert(iproc);
    return iproc->info();
  }else if(p.tag() == Ptr_tag::n_procedure){
    auto nproc = p.get<const NProcedure*>();
    assert(nproc);
    return nproc->info();
  }else if(p.tag() == Ptr_tag::continuation){
    auto cont = p.get<Continuation*>();
    assert(cont);
    return cont->info();
  }else if(p.tag() == Ptr_tag::syntax_rules){
    auto srule = p.get<SyntaxRules*>();
    assert(srule);
    return srule->info();
  }else{
    UNEXP_DEFAULT();
  }
}

Lisp_ptr get_procname(Lisp_ptr p){
  if(p.tag() == Ptr_tag::i_procedure){
    auto iproc = p.get<IProcedure*>();
    assert(iproc);
    return iproc->name();
  }else if(p.tag() == Ptr_tag::n_procedure){
    auto nproc = p.get<const NProcedure*>();
    assert(nproc);
    return zs_new<String>(find_builtin_nproc_name(nproc));
  }else if(p.tag() == Ptr_tag::continuation){
    auto cont = p.get<Continuation*>();
    assert(cont);
    return cont->name();
  }else if(p.tag() == Ptr_tag::syntax_rules){
    auto srule = p.get<SyntaxRules*>();
    assert(srule);
    return srule->name();
  }else{
    UNEXP_DEFAULT();
  }
}

void set_procname(Lisp_ptr p, Lisp_ptr n){
  if(p.tag() == Ptr_tag::i_procedure){
    auto iproc = p.get<IProcedure*>();
    assert(iproc);
    iproc->set_name(n);
  }else if(p.tag() == Ptr_tag::n_procedure){
    return;
  }else if(p.tag() == Ptr_tag::continuation){
    auto cont = p.get<Continuation*>();
    assert(cont);
    cont->set_name(n);
  }else if(p.tag() == Ptr_tag::syntax_rules){
    auto srule = p.get<SyntaxRules*>();
    assert(srule);
    srule->set_name(n);
  }else{
    UNEXP_DEFAULT();
  }
}
<|endoftext|>


<commit_before>/***********************************************************************
    created:    28/9/2014
    author:     David Reepmeyer
*************************************************************************/
/***************************************************************************

    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.
***************************************************************************/
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
# include <unistd.h>
#endif

#include "CEGUISamplesConfig.h"
#include "CEGuiEGLBaseApplication.h"
#include "SampleBrowserBase.h"
#include "CEGUI/CEGUI.h"

#include <stdexcept>
#include <sstream>

#include <CEGUI/RendererModules/OpenGL/GLES2Renderer.h>

//----------------------------------------------------------------------------//
CEGuiEGLBaseApplication* CEGuiEGLBaseApplication::d_appInstance = 0;

//----------------------------------------------------------------------------//
CEGuiEGLBaseApplication::CEGuiEGLBaseApplication() :
    d_display(EGL_NO_DISPLAY),
    d_surface(EGL_NO_SURFACE),
    d_context(EGL_NO_CONTEXT),
    d_width(0),
    d_height(0),
    d_contextInitialised(false),
    d_contextValid(false),
    d_glesVersion(0)
{
    if(d_appInstance)
        throw CEGUI::InvalidRequestException("CEGuiEGLBaseApplication instance already exists!");

    d_appInstance = this;
    AndroidAppHelper::createWindow();
    d_renderer = &CEGUI::GLES2Renderer::create();
}

//----------------------------------------------------------------------------//
CEGuiEGLBaseApplication::~CEGuiEGLBaseApplication()
{
    terminate();
}

CEGuiEGLBaseApplication& CEGuiEGLBaseApplication::getSingleton()
{
    return (*d_appInstance);
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::run()
{

    d_sampleApp->initialise();

    d_windowSized = false; //The resize callback is being called immediately after setting it in this version of glfw
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    clock_gettime(CLOCK_MONOTONIC, &start_timespec);

    while(!d_sampleApp->isQuitting())
    {
        drawFrame();

#ifdef __ANDROID__

        if(!AndroidAppHelper::processEvents())
        {
            d_sampleApp->setQuitting(true);
            terminate();
        }

#endif

        if(d_windowSized)
        {
            d_windowSized = false;
            //CEGUI::System::getSingleton().notifyDisplaySizeChanged(
            //CEGUI::Sizef(static_cast<float>(d_newWindowWidth),
            //static_cast<float>(d_newWindowHeight)));
        }

    }

    d_sampleApp->deinitialise();
}

//----------------------------------------------------------------------------//
SampleBrowserBase* CEGuiEGLBaseApplication::getSampleApp()
{
    return d_sampleApp;
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::initialiseResourceGroupDirectories()
{
    // initialise the required dirs for the DefaultResourceProvider
    CEGUI::DefaultResourceProvider* rp =
        static_cast<CEGUI::DefaultResourceProvider*>
        (CEGUI::System::getSingleton().getResourceProvider());
#ifdef __ANDROID__
    const char* dataPathPrefix = "datafiles";
#else
    const char* dataPathPrefix = getDataPathPrefix();
#endif
    char resourcePath[PATH_MAX];

    // for each resource type, set a resource group directory
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "schemes");
    rp->setResourceGroupDirectory("schemes", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "imagesets");
    rp->setResourceGroupDirectory("imagesets", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "fonts");
    rp->setResourceGroupDirectory("fonts", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "layouts");
    rp->setResourceGroupDirectory("layouts", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "looknfeel");
    rp->setResourceGroupDirectory("looknfeels", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "lua_scripts");
    rp->setResourceGroupDirectory("lua_scripts", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "xml_schemas");
    rp->setResourceGroupDirectory("schemas", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "animations");
    rp->setResourceGroupDirectory("animations", resourcePath);
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::destroyWindow()
{
    terminate();
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::beginRendering(const float /*elapsed*/)
{
    clearFrame();
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, d_width, d_height);
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::endRendering()
{
    swap();
}
//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::clearFrame()
{
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::drawFrame()
{
    d_appInstance->renderSingleFrame(static_cast<float>(getElapsedTime()));
}

double CEGuiEGLBaseApplication::getElapsedTime()
{
    timespec now_timespec;
    clock_gettime(CLOCK_MONOTONIC, &now_timespec);
    double elapsed = (now_timespec.tv_sec - start_timespec.tv_sec);
    elapsed += ((double)(now_timespec.tv_nsec - start_timespec.tv_nsec)) / ((double) 1000000000L);
    start_timespec = now_timespec;
    return elapsed;
}

//----------------------------------------------------------------------------//
bool CEGuiEGLBaseApplication::init(ANativeWindow* window, int openglesVersion = 2)
{
    d_glesVersion = openglesVersion;

    if(d_contextInitialised)
        return true;

    window_ = window;
    initEGLSurface();
    initEGLContext();

    d_contextInitialised = true;

    return true;
}

//----------------------------------------------------------------------------//
bool CEGuiEGLBaseApplication::initEGLSurface()
{
    d_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(d_display, 0, 0);

    const EGLint attribs[] = { EGL_RENDERABLE_TYPE,
                               EGL_OPENGL_ES2_BIT, //Request opengl ES2.0
                               EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
                               EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_NONE
                             };
    int32_t color_size_ = 8;
    int32_t depth_size_ = 24;

    EGLint num_configs;
    eglChooseConfig(d_display, attribs, &d_config, 1, &num_configs);

    if(!num_configs)
    {
        //Fall back to 16bit depth buffer
        const EGLint attribs[] = { EGL_RENDERABLE_TYPE,
                                   EGL_OPENGL_ES2_BIT, //Request opengl ES2.0
                                   EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
                                   EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_NONE
                                 };
        eglChooseConfig(d_display, attribs, &d_config, 1, &num_configs);
        depth_size_ = 16;
    }

    if(!num_configs)
    {
        CEGUI::Logger::getSingleton().logEvent("Unable to retrieve EGL config");
        return false;
    }

    d_surface = eglCreateWindowSurface(d_display, d_config, window_, NULL);
    eglQuerySurface(d_display, d_surface, EGL_WIDTH, &d_width);
    eglQuerySurface(d_display, d_surface, EGL_HEIGHT, &d_height);
    EGLint format;
    eglGetConfigAttrib(d_display, d_config, EGL_NATIVE_VISUAL_ID, &format);
    ANativeWindow_setBuffersGeometry(window_, 0, 0, format);
    return true;
}

//----------------------------------------------------------------------------//
bool CEGuiEGLBaseApplication::initEGLContext()
{
    const EGLint d_contextattribs[] =
    {
        EGL_CONTEXT_CLIENT_VERSION, d_glesVersion, //Request opengl es version (2/3)
        EGL_NONE
    };

    d_context = eglCreateContext(d_display, d_config, NULL, d_contextattribs);

    if(eglMakeCurrent(d_display, d_surface, d_surface, d_context) == EGL_FALSE)
    {
        CEGUI::Logger::getSingleton().logEvent("Unable to eglMakeCurrent");
        return false;
    }

    d_contextValid = true;
    return true;
}

//----------------------------------------------------------------------------//
EGLint CEGuiEGLBaseApplication::swap()
{
    bool b = eglSwapBuffers(d_display, d_surface);

    if(!b)
    {
        CEGUI::Logger::getSingleton().logEvent("eglSwapBuffers failed");
        EGLint err = eglGetError();

        if(err == EGL_BAD_SURFACE)
        {
            //Recreate surface
            initEGLSurface();
            return EGL_SUCCESS; //Still consider glContext is valid
        }
        else if(err == EGL_CONTEXT_LOST || err == EGL_BAD_CONTEXT)
        {
            //Context has been lost!!
            d_contextValid = false;
            terminate();
            initEGLContext();
        }

        return err;
    }

    return EGL_SUCCESS;
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::terminate()
{
    if(d_display != EGL_NO_DISPLAY)
    {
        eglMakeCurrent(d_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

        if(d_context != EGL_NO_CONTEXT)
        {
            eglDestroyContext(d_display, d_context);
        }

        if(d_surface != EGL_NO_SURFACE)
        {
            eglDestroySurface(d_display, d_surface);
        }

        eglTerminate(d_display);
    }

    d_display = EGL_NO_DISPLAY;
    d_context = EGL_NO_CONTEXT;
    d_surface = EGL_NO_SURFACE;
    d_contextValid = false;

}

//----------------------------------------------------------------------------//
EGLint CEGuiEGLBaseApplication::resume(ANativeWindow* window)
{
    if(d_contextInitialised == false)
    {
        init(window);
        return EGL_SUCCESS;
    }

    int32_t original_widhth = d_width;
    int32_t original_height = d_height;

    //Create surface
    window_ = window;
    d_surface = eglCreateWindowSurface(d_display, d_config, window_, NULL);
    eglQuerySurface(d_display, d_surface, EGL_WIDTH, &d_width);
    eglQuerySurface(d_display, d_surface, EGL_HEIGHT, &d_height);

    if(d_width != original_widhth || d_height != original_height)
    {
        CEGUI::Logger::getSingleton().logEvent("Screen Resized");
    }

    if(eglMakeCurrent(d_display, d_surface, d_surface, d_context) == EGL_TRUE)
        return EGL_SUCCESS;

    EGLint err = eglGetError();
    CEGUI::Logger::getSingleton().logEvent("Unable to eglMakeCurrent");

    if(err == EGL_CONTEXT_LOST)
    {
        //Recreate context
        CEGUI::Logger::getSingleton().logEvent("Recreating EGL context");
        initEGLContext();
    }
    else
    {
        //Recreate surface
        terminate();
        initEGLSurface();
        initEGLContext();
    }

    return err;
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::suspend()
{
    if(d_surface != EGL_NO_SURFACE)
    {
        eglDestroySurface(d_display, d_surface);
        d_surface = EGL_NO_SURFACE;
    }
}

//----------------------------------------------------------------------------//
bool CEGuiEGLBaseApplication::invalidate()
{
    terminate();

    d_contextInitialised = false;
    return true;
}

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

<commit_msg>separating opengl texture classes for GLES/GL/GL3 differences<commit_after>/***********************************************************************
    created:    28/9/2014
    author:     David Reepmeyer
*************************************************************************/
/***************************************************************************

    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.
***************************************************************************/
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
# include <unistd.h>
#endif

#include "CEGUISamplesConfig.h"
#include "CEGuiEGLBaseApplication.h"
#include "SampleBrowserBase.h"
#include "CEGUI/CEGUI.h"

#include <stdexcept>
#include <sstream>

#include <CEGUI/RendererModules/OpenGL/GLES2Renderer.h>

//----------------------------------------------------------------------------//
CEGuiEGLBaseApplication* CEGuiEGLBaseApplication::d_appInstance = 0;

//----------------------------------------------------------------------------//
CEGuiEGLBaseApplication::CEGuiEGLBaseApplication() :
    d_display(EGL_NO_DISPLAY),
    d_surface(EGL_NO_SURFACE),
    d_context(EGL_NO_CONTEXT),
    d_width(0),
    d_height(0),
    d_contextInitialised(false),
    d_contextValid(false),
    d_glesVersion(0)
{
    if(d_appInstance)
        throw CEGUI::InvalidRequestException("CEGuiEGLBaseApplication instance already exists!");

    d_appInstance = this;
    AndroidAppHelper::createWindow();
    d_renderer = &CEGUI::GLES2Renderer::create();
}

//----------------------------------------------------------------------------//
CEGuiEGLBaseApplication::~CEGuiEGLBaseApplication()
{
    terminate();
}

CEGuiEGLBaseApplication& CEGuiEGLBaseApplication::getSingleton()
{
    return (*d_appInstance);
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::run()
{

    d_sampleApp->initialise();

    d_windowSized = false; //The resize callback is being called immediately after setting it in this version of glfw
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    clock_gettime(CLOCK_MONOTONIC, &start_timespec);

    while(!d_sampleApp->isQuitting())
    {
        drawFrame();

#ifdef __ANDROID__

        if(!AndroidAppHelper::processEvents())
        {
            d_sampleApp->setQuitting(true);
            terminate();
        }

#endif
        if(d_windowSized)
        {
            d_windowSized = false;
            //CEGUI::System::getSingleton().notifyDisplaySizeChanged(
            //CEGUI::Sizef(static_cast<float>(d_newWindowWidth),
            //static_cast<float>(d_newWindowHeight)));
        }

    }

    d_sampleApp->deinitialise();
}

//----------------------------------------------------------------------------//
SampleBrowserBase* CEGuiEGLBaseApplication::getSampleApp()
{
    return d_sampleApp;
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::initialiseResourceGroupDirectories()
{
    // initialise the required dirs for the DefaultResourceProvider
    CEGUI::DefaultResourceProvider* rp =
        static_cast<CEGUI::DefaultResourceProvider*>
        (CEGUI::System::getSingleton().getResourceProvider());
#ifdef __ANDROID__
    const char* dataPathPrefix = "datafiles";
#else
    const char* dataPathPrefix = getDataPathPrefix();
#endif
    char resourcePath[PATH_MAX];

    // for each resource type, set a resource group directory
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "schemes");
    rp->setResourceGroupDirectory("schemes", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "imagesets");
    rp->setResourceGroupDirectory("imagesets", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "fonts");
    rp->setResourceGroupDirectory("fonts", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "layouts");
    rp->setResourceGroupDirectory("layouts", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "looknfeel");
    rp->setResourceGroupDirectory("looknfeels", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "lua_scripts");
    rp->setResourceGroupDirectory("lua_scripts", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "xml_schemas");
    rp->setResourceGroupDirectory("schemas", resourcePath);
    sprintf(resourcePath, "%s/%s", dataPathPrefix, "animations");
    rp->setResourceGroupDirectory("animations", resourcePath);
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::destroyWindow()
{
    terminate();
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::beginRendering(const float /*elapsed*/)
{
    clearFrame();
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, d_width, d_height);
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::endRendering()
{
    swap();
}
//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::clearFrame()
{
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::drawFrame()
{
    d_appInstance->renderSingleFrame(static_cast<float>(getElapsedTime()));
}

double CEGuiEGLBaseApplication::getElapsedTime()
{
    timespec now_timespec;
    clock_gettime(CLOCK_MONOTONIC, &now_timespec);
    double elapsed = (now_timespec.tv_sec - start_timespec.tv_sec);
    elapsed += ((double)(now_timespec.tv_nsec - start_timespec.tv_nsec)) / ((double) 1000000000L);
    start_timespec = now_timespec;
    return elapsed;
}

//----------------------------------------------------------------------------//
bool CEGuiEGLBaseApplication::init(ANativeWindow* window, int openglesVersion = 2)
{
    d_glesVersion = openglesVersion;

    if(d_contextInitialised)
        return true;

    window_ = window;
    initEGLSurface();
    initEGLContext();

    d_contextInitialised = true;

    return true;
}

//----------------------------------------------------------------------------//
bool CEGuiEGLBaseApplication::initEGLSurface()
{
    d_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(d_display, 0, 0);

    const EGLint attribs[] = { EGL_RENDERABLE_TYPE,
                               EGL_OPENGL_ES2_BIT, //Request opengl ES2.0
                               EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
                               EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_NONE
                             };
    int32_t color_size_ = 8;
    int32_t depth_size_ = 24;

    EGLint num_configs;
    eglChooseConfig(d_display, attribs, &d_config, 1, &num_configs);

    if(!num_configs)
    {
        //Fall back to 16bit depth buffer
        const EGLint attribs[] = { EGL_RENDERABLE_TYPE,
                                   EGL_OPENGL_ES2_BIT, //Request opengl ES2.0
                                   EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
                                   EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_NONE
                                 };
        eglChooseConfig(d_display, attribs, &d_config, 1, &num_configs);
        depth_size_ = 16;
    }

    if(!num_configs)
    {
        return false;
    }

    d_surface = eglCreateWindowSurface(d_display, d_config, window_, NULL);
    eglQuerySurface(d_display, d_surface, EGL_WIDTH, &d_width);
    eglQuerySurface(d_display, d_surface, EGL_HEIGHT, &d_height);
    EGLint format;
    eglGetConfigAttrib(d_display, d_config, EGL_NATIVE_VISUAL_ID, &format);
    ANativeWindow_setBuffersGeometry(window_, 0, 0, format);
    return true;
}

//----------------------------------------------------------------------------//
bool CEGuiEGLBaseApplication::initEGLContext()
{
    const EGLint d_contextattribs[] =
    {
        EGL_CONTEXT_CLIENT_VERSION, d_glesVersion, //Request opengl es version (2/3)
        EGL_NONE
    };

    d_context = eglCreateContext(d_display, d_config, NULL, d_contextattribs);

    if(eglMakeCurrent(d_display, d_surface, d_surface, d_context) == EGL_FALSE)
    {
        return false;
    }

    d_contextValid = true;
    return true;
}

//----------------------------------------------------------------------------//
EGLint CEGuiEGLBaseApplication::swap()
{
    bool b = eglSwapBuffers(d_display, d_surface);

    if(!b)
    {
        EGLint err = eglGetError();

        if(err == EGL_BAD_SURFACE)
        {
            //Recreate surface
            initEGLSurface();
            return EGL_SUCCESS; //Still consider glContext is valid
        }
        else if(err == EGL_CONTEXT_LOST || err == EGL_BAD_CONTEXT)
        {
            //Context has been lost!!
            d_contextValid = false;
            terminate();
            initEGLContext();
        }

        return err;
    }

    return EGL_SUCCESS;
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::terminate()
{
    if(d_display != EGL_NO_DISPLAY)
    {
        eglMakeCurrent(d_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

        if(d_context != EGL_NO_CONTEXT)
        {
            eglDestroyContext(d_display, d_context);
        }

        if(d_surface != EGL_NO_SURFACE)
        {
            eglDestroySurface(d_display, d_surface);
        }

        eglTerminate(d_display);
    }

    d_display = EGL_NO_DISPLAY;
    d_context = EGL_NO_CONTEXT;
    d_surface = EGL_NO_SURFACE;
    d_contextValid = false;

}

//----------------------------------------------------------------------------//
EGLint CEGuiEGLBaseApplication::resume(ANativeWindow* window)
{
    if(d_contextInitialised == false)
    {
        init(window);
        return EGL_SUCCESS;
    }

    int32_t original_widhth = d_width;
    int32_t original_height = d_height;

    //Create surface
    window_ = window;
    d_surface = eglCreateWindowSurface(d_display, d_config, window_, NULL);
    eglQuerySurface(d_display, d_surface, EGL_WIDTH, &d_width);
    eglQuerySurface(d_display, d_surface, EGL_HEIGHT, &d_height);

    if(eglMakeCurrent(d_display, d_surface, d_surface, d_context) == EGL_TRUE)
        return EGL_SUCCESS;

    EGLint err = eglGetError();

    if(err == EGL_CONTEXT_LOST)
    {
        //Recreate context
        initEGLContext();
    }
    else
    {
        //Recreate surface
        terminate();
        initEGLSurface();
        initEGLContext();
    }

    return err;
}

//----------------------------------------------------------------------------//
void CEGuiEGLBaseApplication::suspend()
{
    if(d_surface != EGL_NO_SURFACE)
    {
        eglDestroySurface(d_display, d_surface);
        d_surface = EGL_NO_SURFACE;
    }
}

//----------------------------------------------------------------------------//
bool CEGuiEGLBaseApplication::invalidate()
{
    terminate();

    d_contextInitialised = false;
    return true;
}

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

<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "formeditorscene.h"
#include "formeditorview.h"
#include "formeditorwidget.h"
#include "formeditoritem.h"
#include "movemanipulator.h"
#include <metainfo.h>
#include <QGraphicsSceneDragDropEvent>

#include <QEvent>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsView>

#include <QApplication>
#include <QDebug>
#include <QList>

#include "formeditornodeinstanceview.h"

#include "resizehandleitem.h"
#include <QtDebug>

namespace QmlDesigner {

FormEditorScene::FormEditorScene(FormEditorWidget *view, FormEditorView *editorView)
        : QGraphicsScene(),
        m_editorView(editorView),
        m_formLayerItem(new LayerItem(this)),
        m_manipulatorLayerItem(new LayerItem(this)),
        m_paintMode(NormalMode),
        m_showBoundingRects(true)
{
    setSceneRect(0, 0, 1, 1); // prevent automatic calculation (causing a recursion), right size will be set later

    m_manipulatorLayerItem->setZValue(1.0);
    m_formLayerItem->setZValue(0.0);
    m_formLayerItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
    view->setScene(this);
    setItemIndexMethod(QGraphicsScene::NoIndex);

//    setItemIndexMethod(QGraphicsScene::NoIndex);
}

FormEditorScene::~FormEditorScene()
{
    clear();  //FormEditorItems have to be cleared before destruction
              //Reason: FormEditorItems accesses FormEditorScene in destructor
}

FormEditorItem* FormEditorScene::itemForQmlItemNode(const QmlItemNode &qmlItemNode) const
{
    Q_ASSERT(hasItemForQmlItemNode(qmlItemNode));
    return m_qmlItemNodeItemHash.value(qmlItemNode);
}

QList<FormEditorItem*> FormEditorScene::itemsForQmlItemNodes(const QList<QmlItemNode> &nodeList) const
{
    QList<FormEditorItem*> itemList;
    foreach (const QmlItemNode &node, nodeList) {
        if (hasItemForQmlItemNode(node))
            itemList += itemForQmlItemNode(node);
    }

    return itemList;
}

QList<FormEditorItem*> FormEditorScene::allFormEditorItems() const
{
    return m_qmlItemNodeItemHash.values();
}

void FormEditorScene::updateAllFormEditorItems()
{
    foreach (FormEditorItem *item, allFormEditorItems()) {
        item->update();
    }
}

bool FormEditorScene::hasItemForQmlItemNode(const QmlItemNode &qmlItemNode) const
{
    return m_qmlItemNodeItemHash.contains(qmlItemNode);
}

void FormEditorScene::removeItemFromHash(FormEditorItem *item)
{
   m_qmlItemNodeItemHash.remove(item->qmlItemNode());
}

AbstractFormEditorTool* FormEditorScene::currentTool() const
{
    return m_editorView->currentTool();
}

//This method calculates the possible parent for reparent
FormEditorItem* FormEditorScene::calulateNewParent(FormEditorItem *formEditorItem)
{
    QList<QGraphicsItem *> list = items(formEditorItem->qmlItemNode().instanceBoundingRect().center());
    foreach (QGraphicsItem *graphicsItem, list) {
        if (qgraphicsitem_cast<FormEditorItem*>(graphicsItem) &&
            graphicsItem->collidesWithItem(formEditorItem, Qt::ContainsItemShape))
            return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
    }
    return 0;
}

void FormEditorScene::synchronizeTransformation(const QmlItemNode &qmlItemNode)
{
    FormEditorItem *item = itemForQmlItemNode(qmlItemNode);
    item->updateGeometry();
    item->update();

    if (qmlItemNode.isRootNode()) {
        QRectF sceneRect(qmlItemNode.instanceBoundingRect());

        setSceneRect(sceneRect);
        formLayerItem()->update();
        manipulatorLayerItem()->update();
    }
}

void FormEditorScene::synchronizeParent(const QmlItemNode &qmlItemNode)
{
    QmlItemNode parentNode = qmlItemNode.instanceParent().toQmlItemNode();
    reparentItem(qmlItemNode, parentNode);
}

void FormEditorScene::synchronizeOtherProperty(const QmlItemNode &qmlItemNode, const QString &propertyName)
{
    if (hasItemForQmlItemNode(qmlItemNode)) {
        FormEditorItem *item = itemForQmlItemNode(qmlItemNode);

        if (propertyName == "opacity")
            item->setOpacity(qmlItemNode.instanceValue("opacity").toDouble());

        if (propertyName == "clip")
            item->setFlag(QGraphicsItem::ItemClipsChildrenToShape, qmlItemNode.instanceValue("clip").toBool());

        if (propertyName == "visible")
            item->setContentVisible(qmlItemNode.instanceValue("visible").toBool());

        if (item)
            item->update();
    }
}

void FormEditorScene::synchronizeState(const QmlItemNode &qmlItemNode)
{
    if (hasItemForQmlItemNode(qmlItemNode)) {
        FormEditorItem *item = itemForQmlItemNode(qmlItemNode);
        if (item)
            item->update();
    }
}

FormEditorItem *FormEditorScene::addFormEditorItem(const QmlItemNode &qmlItemNode)
{
    FormEditorItem *formEditorItem = new FormEditorItem(qmlItemNode, this);
    Q_ASSERT(!m_qmlItemNodeItemHash.contains(qmlItemNode));

    m_qmlItemNodeItemHash.insert(qmlItemNode, formEditorItem);
    if (qmlItemNode.isRootNode()) {
        QRectF sceneRect(qmlItemNode.instanceBoundingRect());

        setSceneRect(sceneRect);
       formLayerItem()->update();
       manipulatorLayerItem()->update();
    }

    return formEditorItem;
}

void FormEditorScene::dropEvent(QGraphicsSceneDragDropEvent * event)
{
    currentTool()->dropEvent(event);

    if (views().first())
        views().first()->setFocus();
}

void FormEditorScene::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
{
    currentTool()->dragEnterEvent(event);
}

void FormEditorScene::dragLeaveEvent(QGraphicsSceneDragDropEvent * event)
{
    currentTool()->dragLeaveEvent(event);

    return;
}

void FormEditorScene::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
{
    currentTool()->dragMoveEvent(event);
}

QList<QGraphicsItem *> FormEditorScene::removeLayerItems(const QList<QGraphicsItem *> &itemList)
{
    QList<QGraphicsItem *> itemListWithoutLayerItems;

    foreach (QGraphicsItem *item, itemList)
        if (item != manipulatorLayerItem() && item != formLayerItem())
            itemListWithoutLayerItems.append(item);

    return itemListWithoutLayerItems;
}

void FormEditorScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    currentTool()->mousePressEvent(removeLayerItems(items(event->scenePos())), event);
}

void FormEditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->buttons())
        currentTool()->mouseMoveEvent(removeLayerItems(items(event->scenePos())), event);
    else
        currentTool()->hoverMoveEvent(removeLayerItems(items(event->scenePos())), event);

    event->accept();
}

void FormEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    currentTool()->mouseReleaseEvent(removeLayerItems(items(event->scenePos())), event);

    event->accept();
 }

void FormEditorScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
    currentTool()->mouseDoubleClickEvent(removeLayerItems(items(event->scenePos())), event);

    event->accept();
}

void FormEditorScene::keyPressEvent(QKeyEvent *keyEvent)
{
    currentTool()->keyPressEvent(keyEvent);
}

void FormEditorScene::keyReleaseEvent(QKeyEvent *keyEvent)
{
    currentTool()->keyReleaseEvent(keyEvent);
}

FormEditorView *FormEditorScene::editorView() const
{
   return m_editorView;
}

LayerItem* FormEditorScene::manipulatorLayerItem() const
{
    return m_manipulatorLayerItem.data();
}

LayerItem* FormEditorScene::formLayerItem() const
{
    return m_formLayerItem.data();
}

bool FormEditorScene::event(QEvent * event)
{
    switch(event->type())
    {
        case QEvent::GraphicsSceneHoverEnter :
            hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
            return true;
        case QEvent::GraphicsSceneHoverMove :
            hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
            return true;
        case QEvent::GraphicsSceneHoverLeave :
            hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
            return true;
        default: return QGraphicsScene::event(event);
    }

}

void FormEditorScene::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
{
    qDebug() << __FUNCTION__;
}

void FormEditorScene::hoverMoveEvent(QGraphicsSceneHoverEvent * /*event*/)
{
    qDebug() << __FUNCTION__;
}

void FormEditorScene::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
{
    qDebug() << __FUNCTION__;
}

void FormEditorScene::reparentItem(const QmlItemNode &node, const QmlItemNode &newParent)
{
    Q_ASSERT(hasItemForQmlItemNode(node));
    FormEditorItem *item = itemForQmlItemNode(node);
    FormEditorItem *parentItem = 0;
    if (newParent.isValid() && hasItemForQmlItemNode(newParent))
        parentItem = itemForQmlItemNode(newParent);

    if (item->parentItem() != parentItem) {
        item->setParentItem(parentItem);
        item->update();
    }
}

FormEditorItem* FormEditorScene::rootFormEditorItem() const
{
    QList<QGraphicsItem*> childItemList(m_formLayerItem->childItems());
    if (!childItemList.isEmpty())
        return FormEditorItem::fromQGraphicsItem(childItemList.first());

    return 0;
}

FormEditorScene::PaintMode FormEditorScene::paintMode() const
{
    return m_paintMode;
}

void FormEditorScene::setPaintMode(PaintMode paintMode)
{
    m_paintMode = paintMode;
}

void FormEditorScene::clearFormEditorItems()
{
    QList<QGraphicsItem*> itemList(items());

    foreach (QGraphicsItem *item, itemList) {
        if (qgraphicsitem_cast<FormEditorItem* >(item))
            item->setParentItem(0);
    }

    foreach (QGraphicsItem *item, itemList) {
        if (qgraphicsitem_cast<FormEditorItem* >(item))
            delete item;
    }
}

void FormEditorScene::highlightBoundingRect(FormEditorItem *highlighItem)
{
    foreach(FormEditorItem *item, allFormEditorItems()) {
        if (item == highlighItem)
            item->setHighlightBoundingRect(true);
        else
            item->setHighlightBoundingRect(false);
    }
}

void FormEditorScene::setShowBoundingRects(bool show)
{
    m_showBoundingRects = show;
    updateAllFormEditorItems();
}

bool FormEditorScene::showBoundingRects() const
{
    return m_showBoundingRects;
}

}

<commit_msg>Fix crash when loading any Qml file in QuickDesigner<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "formeditorscene.h"
#include "formeditorview.h"
#include "formeditorwidget.h"
#include "formeditoritem.h"
#include "movemanipulator.h"
#include <metainfo.h>
#include <QGraphicsSceneDragDropEvent>

#include <QEvent>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsView>

#include <QApplication>
#include <QDebug>
#include <QList>

#include "formeditornodeinstanceview.h"

#include "resizehandleitem.h"
#include <QtDebug>

namespace QmlDesigner {

FormEditorScene::FormEditorScene(FormEditorWidget *view, FormEditorView *editorView)
        : QGraphicsScene(),
        m_editorView(editorView),
        m_formLayerItem(new LayerItem(this)),
        m_manipulatorLayerItem(new LayerItem(this)),
        m_paintMode(NormalMode),
        m_showBoundingRects(true)
{
    setSceneRect(0, 0, 1, 1); // prevent automatic calculation (causing a recursion), right size will be set later

    m_manipulatorLayerItem->setZValue(1.0);
    m_formLayerItem->setZValue(0.0);
    m_formLayerItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
    view->setScene(this);
    setItemIndexMethod(QGraphicsScene::NoIndex);

//    setItemIndexMethod(QGraphicsScene::NoIndex);
}

FormEditorScene::~FormEditorScene()
{
    clear();  //FormEditorItems have to be cleared before destruction
              //Reason: FormEditorItems accesses FormEditorScene in destructor
}

FormEditorItem* FormEditorScene::itemForQmlItemNode(const QmlItemNode &qmlItemNode) const
{
    Q_ASSERT(hasItemForQmlItemNode(qmlItemNode));
    return m_qmlItemNodeItemHash.value(qmlItemNode);
}

QList<FormEditorItem*> FormEditorScene::itemsForQmlItemNodes(const QList<QmlItemNode> &nodeList) const
{
    QList<FormEditorItem*> itemList;
    foreach (const QmlItemNode &node, nodeList) {
        if (hasItemForQmlItemNode(node))
            itemList += itemForQmlItemNode(node);
    }

    return itemList;
}

QList<FormEditorItem*> FormEditorScene::allFormEditorItems() const
{
    return m_qmlItemNodeItemHash.values();
}

void FormEditorScene::updateAllFormEditorItems()
{
    foreach (FormEditorItem *item, allFormEditorItems()) {
        item->update();
    }
}

bool FormEditorScene::hasItemForQmlItemNode(const QmlItemNode &qmlItemNode) const
{
    return m_qmlItemNodeItemHash.contains(qmlItemNode);
}

void FormEditorScene::removeItemFromHash(FormEditorItem *item)
{
   m_qmlItemNodeItemHash.remove(item->qmlItemNode());
}

AbstractFormEditorTool* FormEditorScene::currentTool() const
{
    return m_editorView->currentTool();
}

//This method calculates the possible parent for reparent
FormEditorItem* FormEditorScene::calulateNewParent(FormEditorItem *formEditorItem)
{
    QList<QGraphicsItem *> list = items(formEditorItem->qmlItemNode().instanceBoundingRect().center());
    foreach (QGraphicsItem *graphicsItem, list) {
        if (qgraphicsitem_cast<FormEditorItem*>(graphicsItem) &&
            graphicsItem->collidesWithItem(formEditorItem, Qt::ContainsItemShape))
            return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
    }
    return 0;
}

void FormEditorScene::synchronizeTransformation(const QmlItemNode &qmlItemNode)
{
    FormEditorItem *item = itemForQmlItemNode(qmlItemNode);
    item->updateGeometry();
    item->update();

    if (qmlItemNode.isRootNode()) {
        QRectF sceneRect(qmlItemNode.instanceBoundingRect());

        setSceneRect(sceneRect);
        formLayerItem()->update();
        manipulatorLayerItem()->update();
    }
}

void FormEditorScene::synchronizeParent(const QmlItemNode &qmlItemNode)
{
    QmlItemNode parentNode = qmlItemNode.instanceParent().toQmlItemNode();
    reparentItem(qmlItemNode, parentNode);
}

void FormEditorScene::synchronizeOtherProperty(const QmlItemNode &qmlItemNode, const QString &propertyName)
{
    if (hasItemForQmlItemNode(qmlItemNode)) {
        FormEditorItem *item = itemForQmlItemNode(qmlItemNode);

        if (propertyName == "opacity")
            item->setOpacity(qmlItemNode.instanceValue("opacity").toDouble());

        if (propertyName == "clip")
            item->setFlag(QGraphicsItem::ItemClipsChildrenToShape, qmlItemNode.instanceValue("clip").toBool());

        if (propertyName == "visible")
            item->setContentVisible(qmlItemNode.instanceValue("visible").toBool());

        if (item)
            item->update();
    }
}

void FormEditorScene::synchronizeState(const QmlItemNode &qmlItemNode)
{
    if (hasItemForQmlItemNode(qmlItemNode)) {
        FormEditorItem *item = itemForQmlItemNode(qmlItemNode);
        if (item)
            item->update();
    }
}

FormEditorItem *FormEditorScene::addFormEditorItem(const QmlItemNode &qmlItemNode)
{
    FormEditorItem *formEditorItem = new FormEditorItem(qmlItemNode, this);
    Q_ASSERT(!m_qmlItemNodeItemHash.contains(qmlItemNode));

    m_qmlItemNodeItemHash.insert(qmlItemNode, formEditorItem);
    if (qmlItemNode.isRootNode()) {
        QRectF sceneRect(qmlItemNode.instanceBoundingRect());

        setSceneRect(sceneRect);
       formLayerItem()->update();
       manipulatorLayerItem()->update();
    }

    return formEditorItem;
}

void FormEditorScene::dropEvent(QGraphicsSceneDragDropEvent * event)
{
    currentTool()->dropEvent(event);

    if (views().first())
        views().first()->setFocus();
}

void FormEditorScene::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
{
    currentTool()->dragEnterEvent(event);
}

void FormEditorScene::dragLeaveEvent(QGraphicsSceneDragDropEvent * event)
{
    currentTool()->dragLeaveEvent(event);

    return;
}

void FormEditorScene::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
{
    currentTool()->dragMoveEvent(event);
}

QList<QGraphicsItem *> FormEditorScene::removeLayerItems(const QList<QGraphicsItem *> &itemList)
{
    QList<QGraphicsItem *> itemListWithoutLayerItems;

    foreach (QGraphicsItem *item, itemList)
        if (item != manipulatorLayerItem() && item != formLayerItem())
            itemListWithoutLayerItems.append(item);

    return itemListWithoutLayerItems;
}

void FormEditorScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    currentTool()->mousePressEvent(removeLayerItems(items(event->scenePos())), event);
}

void FormEditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->buttons())
        currentTool()->mouseMoveEvent(removeLayerItems(items(event->scenePos())), event);
    else
        currentTool()->hoverMoveEvent(removeLayerItems(items(event->scenePos())), event);

    event->accept();
}

void FormEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    currentTool()->mouseReleaseEvent(removeLayerItems(items(event->scenePos())), event);

    event->accept();
 }

void FormEditorScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
    currentTool()->mouseDoubleClickEvent(removeLayerItems(items(event->scenePos())), event);

    event->accept();
}

void FormEditorScene::keyPressEvent(QKeyEvent *keyEvent)
{
    currentTool()->keyPressEvent(keyEvent);
}

void FormEditorScene::keyReleaseEvent(QKeyEvent *keyEvent)
{
    currentTool()->keyReleaseEvent(keyEvent);
}

FormEditorView *FormEditorScene::editorView() const
{
   return m_editorView;
}

LayerItem* FormEditorScene::manipulatorLayerItem() const
{
    return m_manipulatorLayerItem.data();
}

LayerItem* FormEditorScene::formLayerItem() const
{
    return m_formLayerItem.data();
}

bool FormEditorScene::event(QEvent * event)
{
    switch(event->type())
    {
        case QEvent::GraphicsSceneHoverEnter :
            hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
            return true;
        case QEvent::GraphicsSceneHoverMove :
            hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
            return true;
        case QEvent::GraphicsSceneHoverLeave :
            hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
            return true;
        default: return QGraphicsScene::event(event);
    }

}

void FormEditorScene::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
{
    qDebug() << __FUNCTION__;
}

void FormEditorScene::hoverMoveEvent(QGraphicsSceneHoverEvent * /*event*/)
{
    qDebug() << __FUNCTION__;
}

void FormEditorScene::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
{
    qDebug() << __FUNCTION__;
}

void FormEditorScene::reparentItem(const QmlItemNode &node, const QmlItemNode &newParent)
{
    Q_ASSERT(hasItemForQmlItemNode(node));
    FormEditorItem *item = itemForQmlItemNode(node);
    FormEditorItem *parentItem = 0;
    if (newParent.isValid() && hasItemForQmlItemNode(newParent))
        parentItem = itemForQmlItemNode(newParent);

    if (item->parentItem() != parentItem) {
        item->setParentItem(parentItem);
        item->update();
    }
}

FormEditorItem* FormEditorScene::rootFormEditorItem() const
{
    QList<QGraphicsItem*> childItemList(m_formLayerItem->childItems());
    if (!childItemList.isEmpty())
        return FormEditorItem::fromQGraphicsItem(childItemList.first());

    return 0;
}

FormEditorScene::PaintMode FormEditorScene::paintMode() const
{
    return m_paintMode;
}

void FormEditorScene::setPaintMode(PaintMode paintMode)
{
    m_paintMode = paintMode;
}

void FormEditorScene::clearFormEditorItems()
{
    QList<QGraphicsItem*> itemList(items());

    foreach (QGraphicsItem *item, itemList) {
        if (qgraphicsitem_cast<FormEditorItem* >(item))
            item->setParentItem(0);
    }

    foreach (QGraphicsItem *item, itemList) {
        if (qgraphicsitem_cast<FormEditorItem* >(item))
            delete item;
    }
}

void FormEditorScene::highlightBoundingRect(FormEditorItem *highlighItem)
{
    foreach(FormEditorItem *item, allFormEditorItems()) {
        if (item == highlighItem)
            item->setHighlightBoundingRect(true);
        else
            item->setHighlightBoundingRect(false);
    }
}

void FormEditorScene::setShowBoundingRects(bool show)
{
    m_showBoundingRects = show;
    updateAllFormEditorItems();
}

bool FormEditorScene::showBoundingRects() const
{
    return m_showBoundingRects;
}

}

<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2014 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_CORE_BURST_INPUT_WINDOW_HPP_
#define JUBATUS_CORE_BURST_INPUT_WINDOW_HPP_

#include <stdint.h>
#include <cmath>
#include <vector>
#include <msgpack.hpp>
#include "../common/assert.hpp"
#include "../common/exception.hpp"

#include "window_fwd.hpp"

namespace jubatus {
namespace core {
namespace burst {

template<class Batch>
class basic_window {
 public:
  typedef Batch batch_type;

  explicit basic_window(double batch_length = 1)
      : batches_(), start_pos_(0), batch_length_(batch_length) {
    if (batch_length <= 0) {
      throw JUBATUS_EXCEPTION(common::invalid_parameter(
          "window: batch_length should be > 0"));
    }
  }

  basic_window(double start_pos, double batch_length, int32_t batch_size)
      : batches_(), start_pos_(start_pos), batch_length_(batch_length) {
    if (batch_length <= 0) {
      throw JUBATUS_EXCEPTION(common::invalid_parameter(
          "window: batch_length should be > 0"));
    }
    if (batch_size < 0) {
      throw JUBATUS_EXCEPTION(common::invalid_parameter(
          "window: batch_size should be >= 0"));
    }
    batches_.resize(batch_size);
  }

  // get index for pos; return -1 if out of range
  int get_index(double pos) const {
    int n = get_batch_size();
    int i = get_index_(pos);

    if (i < 0 || n <= i) {
      JUBATUS_ASSERT(!contains(pos));
      return -1;
    }

    JUBATUS_ASSERT(contains(pos));
    return i;
  }

  double get_start_pos() const {
    return start_pos_;
  }
  double get_end_pos() const {
    return start_pos_ + get_all_length();
  }
  bool contains(double pos) const {
    return get_start_pos() <= pos && pos < get_end_pos();
  }
  double get_all_length() const {
    return batch_length_ * get_batch_size();
  }

  const std::vector<batch_type>& get_batches() const {
    return batches_;
  }
  int32_t get_batch_size() const {
    return batches_.size();
  }
  double get_batch_length() const {
    return batch_length_;
  }

 protected:
  std::vector<batch_type> batches_;
  double start_pos_;
  double batch_length_;

  // get index for pos; no out of range, return as if extended
  int get_index_(double pos) const {
    return static_cast<int>(
        std::floor((pos - start_pos_) / get_batch_length()));
  }
};

class input_window : private basic_window<batch_input> {
  typedef basic_window<batch_input> base_;

 public:
  explicit input_window(double start_pos = 0,
                        double batch_interval = 1,
                        int32_t batch_size = 0)
      : base_(start_pos, batch_interval, batch_size) {
  }

  bool add_document(uint32_t d, uint32_t r, double pos) {
    int i = base_::get_index(pos);

    if (i < 0) {
      return false;
    }

    batches_[i].d += d;
    batches_[i].r += r;
    return true;
  }

  using base_::get_start_pos;
  using base_::get_end_pos;
  using base_::contains;
  using base_::get_all_length;

  using base_::get_batches;
  using base_::get_batch_size;
  using base_::get_batch_length;
};

}  // namespace burst
}  // namespace core
}  // namespace jubatus

#endif  // JUBATUS_CORE_BURST_INPUT_WINDOW_HPP_
<commit_msg>Add swap to input_window<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2014 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_CORE_BURST_INPUT_WINDOW_HPP_
#define JUBATUS_CORE_BURST_INPUT_WINDOW_HPP_

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <msgpack.hpp>
#include "../common/assert.hpp"
#include "../common/exception.hpp"

#include "window_fwd.hpp"

namespace jubatus {
namespace core {
namespace burst {

template<class Batch>
class basic_window {
 public:
  typedef Batch batch_type;

  explicit basic_window(double batch_length = 1)
      : batches_(), start_pos_(0), batch_length_(batch_length) {
    if (batch_length <= 0) {
      throw JUBATUS_EXCEPTION(common::invalid_parameter(
          "window: batch_length should be > 0"));
    }
  }

  basic_window(double start_pos, double batch_length, int32_t batch_size)
      : batches_(), start_pos_(start_pos), batch_length_(batch_length) {
    if (batch_length <= 0) {
      throw JUBATUS_EXCEPTION(common::invalid_parameter(
          "window: batch_length should be > 0"));
    }
    if (batch_size < 0) {
      throw JUBATUS_EXCEPTION(common::invalid_parameter(
          "window: batch_size should be >= 0"));
    }
    batches_.resize(batch_size);
  }

  // get index for pos; return -1 if out of range
  int get_index(double pos) const {
    int n = get_batch_size();
    int i = get_index_(pos);

    if (i < 0 || n <= i) {
      JUBATUS_ASSERT(!contains(pos));
      return -1;
    }

    JUBATUS_ASSERT(contains(pos));
    return i;
  }

  double get_start_pos() const {
    return start_pos_;
  }
  double get_end_pos() const {
    return start_pos_ + get_all_length();
  }
  bool contains(double pos) const {
    return get_start_pos() <= pos && pos < get_end_pos();
  }
  double get_all_length() const {
    return batch_length_ * get_batch_size();
  }

  const std::vector<batch_type>& get_batches() const {
    return batches_;
  }
  int32_t get_batch_size() const {
    return batches_.size();
  }
  double get_batch_length() const {
    return batch_length_;
  }

  void swap(basic_window& x) {
    using std::swap;
    swap(batches_, x.batches_);
    swap(start_pos_, x.start_pos_);
    swap(batch_length_, x.batch_length_);
  }
  friend void swap(basic_window& x, basic_window& y) {
    x.swap(y);
  }

 protected:
  std::vector<batch_type> batches_;
  double start_pos_;
  double batch_length_;

  // get index for pos; no out of range, return as if extended
  int get_index_(double pos) const {
    return static_cast<int>(
        std::floor((pos - start_pos_) / get_batch_length()));
  }
};

class input_window : private basic_window<batch_input> {
  typedef basic_window<batch_input> base_;

 public:
  explicit input_window(double start_pos = 0,
                        double batch_interval = 1,
                        int32_t batch_size = 0)
      : base_(start_pos, batch_interval, batch_size) {
  }

  bool add_document(uint32_t d, uint32_t r, double pos) {
    int i = base_::get_index(pos);

    if (i < 0) {
      return false;
    }

    batches_[i].d += d;
    batches_[i].r += r;
    return true;
  }

  using base_::get_start_pos;
  using base_::get_end_pos;
  using base_::contains;
  using base_::get_all_length;

  using base_::get_batches;
  using base_::get_batch_size;
  using base_::get_batch_length;

  void swap(input_window& x) {
    base_::swap(static_cast<base_&>(x));
  }
  friend void swap(input_window& x, input_window& y) {
    x.swap(y);
  }
};

}  // namespace burst
}  // namespace core
}  // namespace jubatus

#endif  // JUBATUS_CORE_BURST_INPUT_WINDOW_HPP_
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_CORE_COMMON_BYTE_BUFFER_HPP_
#define JUBATUS_CORE_COMMON_BYTE_BUFFER_HPP_

#include <stdint.h>
#include <vector>
#include <cstring>
#include <msgpack.hpp>
#include <pficommon/lang/shared_ptr.h>

namespace jubatus {
namespace core {
namespace common {

class byte_buffer {
 public:
  byte_buffer() {
  }

  explicit byte_buffer(size_t size)
      : buf_(new std::vector<char>(size)) {
  }

  byte_buffer(const void* ptr, size_t size)
      : buf_(new std::vector<char>()) {
    buf_->resize(size);
    std::memcpy(&(*buf_)[0], ptr, size);
  }

  byte_buffer(const byte_buffer& b)
      : buf_(b.buf_) {
  }

  byte_buffer& operator=(const byte_buffer& b) {
    this->buf_ = b.buf_;
    return *this;
  }

  ~byte_buffer() {
  }

  void assign(const void* ptr, size_t size) {
    if (!buf_) {
      buf_.reset(new std::vector<char>());
    }
    buf_->resize(size);
    std::memcpy(&(*buf_)[0], ptr, size);
  }

  const char* ptr() const {
    if (buf_) {
      return &(*buf_)[0];
    } else {
      return NULL;
    }
  }

  char* ptr() {
    return const_cast<char*>(
      const_cast<const byte_buffer*>(this)->ptr());
  }

  size_t size() const {
    if (buf_) {
      return buf_->size();
    } else {
      return 0;
    }
  }

 private:
  pfi::lang::shared_ptr<std::vector<char> > buf_;
};
}  // namespace common
}  // namespace core
}  // namespace jubatus

namespace msgpack {

inline jubatus::core::common::byte_buffer& operator>>(
    object o,
    jubatus::core::common::byte_buffer& b) {
  if (o.type != type::RAW) {
    throw type_error();
  }

  b.assign(o.via.raw.ptr, o.via.raw.size);
  return b;
}

template<typename Stream>
inline packer<Stream>& operator<<(
    packer<Stream>& o,
    const jubatus::core::common::byte_buffer& b) {
  o.pack_raw(b.size());
  o.pack_raw_body(b.ptr(), b.size());
  return o;
}

inline void operator<<(
    object::with_zone& o,
    const jubatus::core::common::byte_buffer& b) {
  o.type = type::RAW;
  char* ptr = static_cast<char*>(o.zone->malloc(b.size()));
  o.via.raw.ptr = ptr;
  o.via.raw.size = static_cast<uint32_t>(b.size());
  std::memcpy(ptr, b.ptr(), b.size());
}

inline void operator<<(
    object& o,
    const jubatus::core::common::byte_buffer& b) {
  o.type = type::RAW;
  o.via.raw.ptr = b.ptr();
  o.via.raw.size = static_cast<uint32_t>(b.size());
}

}  // namespace msgpack

#endif  // JUBATUS_CORE_COMMON_BYTE_BUFFER_HPP_
<commit_msg>Add swap to byte_buffer<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_CORE_COMMON_BYTE_BUFFER_HPP_
#define JUBATUS_CORE_COMMON_BYTE_BUFFER_HPP_

#include <stdint.h>
#include <vector>
#include <cstring>
#include <msgpack.hpp>
#include <pficommon/lang/shared_ptr.h>

namespace jubatus {
namespace core {
namespace common {

class byte_buffer {
 public:
  byte_buffer() {
  }

  explicit byte_buffer(size_t size)
      : buf_(new std::vector<char>(size)) {
  }

  byte_buffer(const void* ptr, size_t size)
      : buf_(new std::vector<char>()) {
    buf_->resize(size);
    std::memcpy(&(*buf_)[0], ptr, size);
  }

  byte_buffer(const byte_buffer& b)
      : buf_(b.buf_) {
  }

  byte_buffer& operator=(const byte_buffer& b) {
    this->buf_ = b.buf_;
    return *this;
  }

  ~byte_buffer() {
  }

  void swap(byte_buffer& other) {
    this->buf_.swap(other.buf_);
    // pfi::lang::shared_ptr provides no non-member swap;
    // `swap(this->buf_, other.buf_);' may be inefficient.
    // when pfi::lang::shared_ptr provide non-member swap,
    // this function should be rewritten with it
    // because if new data members are added to
    // pfi::lang::shared_ptr, member function swap
    // (currently derived from base) may cause object slicing.
  }

  void assign(const void* ptr, size_t size) {
    if (!buf_) {
      buf_.reset(new std::vector<char>());
    }
    buf_->resize(size);
    std::memcpy(&(*buf_)[0], ptr, size);
  }

  const char* ptr() const {
    if (buf_) {
      return &(*buf_)[0];
    } else {
      return NULL;
    }
  }

  char* ptr() {
    return const_cast<char*>(
      const_cast<const byte_buffer*>(this)->ptr());
  }

  size_t size() const {
    if (buf_) {
      return buf_->size();
    } else {
      return 0;
    }
  }

 private:
  pfi::lang::shared_ptr<std::vector<char> > buf_;
};

inline void swap(byte_buffer& one, byte_buffer& another) {
  one.swap(another);
}

}  // namespace common
}  // namespace core
}  // namespace jubatus

namespace msgpack {

inline jubatus::core::common::byte_buffer& operator>>(
    object o,
    jubatus::core::common::byte_buffer& b) {
  if (o.type != type::RAW) {
    throw type_error();
  }

  b.assign(o.via.raw.ptr, o.via.raw.size);
  return b;
}

template<typename Stream>
inline packer<Stream>& operator<<(
    packer<Stream>& o,
    const jubatus::core::common::byte_buffer& b) {
  o.pack_raw(b.size());
  o.pack_raw_body(b.ptr(), b.size());
  return o;
}

inline void operator<<(
    object::with_zone& o,
    const jubatus::core::common::byte_buffer& b) {
  o.type = type::RAW;
  char* ptr = static_cast<char*>(o.zone->malloc(b.size()));
  o.via.raw.ptr = ptr;
  o.via.raw.size = static_cast<uint32_t>(b.size());
  std::memcpy(ptr, b.ptr(), b.size());
}

inline void operator<<(
    object& o,
    const jubatus::core::common::byte_buffer& b) {
  o.type = type::RAW;
  o.via.raw.ptr = b.ptr();
  o.via.raw.size = static_cast<uint32_t>(b.size());
}

}  // namespace msgpack

#endif  // JUBATUS_CORE_COMMON_BYTE_BUFFER_HPP_
<|endoftext|>