<commit_before>#include "xchainer/array.h"

#include <cassert>
#include <cstring>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA

#include "xchainer/array_fill.h"
#include "xchainer/array_math.h"
#include "xchainer/array_repr.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/array_fill.h"
#include "xchainer/cuda/array_math.h"
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/op_node.h"
#include "xchainer/scalar.h"

namespace xchainer {

namespace {

#ifdef XCHAINER_ENABLE_CUDA
std::shared_ptr<void> AllocateCudaManaged(size_t size) {
    std::shared_ptr<void> ptr{};
    {
        void* raw_ptr = nullptr;
        auto raw_ptr_scope = gsl::finally([&]() {
            if (raw_ptr && !ptr) {
                cudaFree(raw_ptr);
            }
        });
        cuda::CheckError(cudaMallocManaged(&raw_ptr, size, cudaMemAttachGlobal));
        ptr.reset(raw_ptr, cudaFree);
    }
    return ptr;
}
#endif  // XCHAINER_ENABLE_CUDA

std::shared_ptr<void> Allocate(const Device& device, size_t size) {
    if (device == MakeDevice("cpu")) {
        return std::make_unique<uint8_t[]>(size);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        return AllocateCudaManaged(size);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void MemoryCopy(const Device& device, void* dst_ptr, const void* src_ptr, size_t size) {
    if (device == MakeDevice("cpu")) {
        std::memcpy(dst_ptr, src_ptr, size);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, size, cudaMemcpyHostToDevice));
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

}  // namespace

Array::Array(const Shape& shape, Dtype dtype, std::shared_ptr<void> data, bool requires_grad, int64_t offset)
    : shape_(shape),
      is_contiguous_(true),
      dtype_(dtype),
      data_(nullptr),
      requires_grad_(requires_grad),
      offset_(offset),
      node_(std::make_shared<ArrayNode>()) {
    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        data_ = std::move(data);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        size_t size = static_cast<size_t>(shape_.total_size() * GetElementSize(dtype));
        data_ = AllocateCudaManaged(size);
        MemoryCopy(device, data_.get(), data.get(), size);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

Array Array::Empty(const Shape& shape, Dtype dtype) {
    size_t size = static_cast<size_t>(shape.total_size() * GetElementSize(dtype));
    std::shared_ptr<void> data = Allocate(GetCurrentDevice(), size);
    return {shape, dtype, data};
}

Array Array::EmptyLike(const Array& array) { return Empty(array.shape(), array.dtype()); }

Array Array::DeepCopy() const {
    auto bytes = total_bytes();
    if (GetCurrentDevice() == MakeDevice("cpu")) {
        std::shared_ptr<void> ret_data = std::make_unique<uint8_t[]>(bytes);
        std::memcpy(ret_data.get(), data_.get(), bytes);
        return {shape_, dtype_, ret_data, requires_grad_, offset_};
#ifdef XCHAINER_ENABLE_CUDA
    } else if (GetCurrentDevice() == MakeDevice("cuda")) {
        // TODO(sonots): Better to use abstraction layer such as Allocate or MemoryCopy,
        // but they do not support all cases such as device to device, yet. We need refactoring.
        void* ret_ptr = nullptr;
        cuda::CheckError(cudaMallocManaged(&ret_ptr, bytes, cudaMemAttachGlobal));
        std::shared_ptr<void> ret_data(ret_ptr, ::cudaFree);
        cuda::CheckError(cudaMemcpy(ret_ptr, data_.get(), bytes, cudaMemcpyDeviceToDevice));
        return {shape_, dtype_, ret_data, requires_grad_, offset_};
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

Array& Array::operator+=(const Array& rhs) {
    Add(rhs, *this);
    requires_grad_ |= rhs.requires_grad();
    return *this;
}

Array& Array::operator*=(const Array& rhs) {
    Mul(rhs, *this);
    requires_grad_ |= rhs.requires_grad();
    return *this;
}

Array Array::operator+(const Array& rhs) const {
    bool requires_grad = (requires_grad_ || rhs.requires_grad());
    Array out = {shape_, dtype_, std::make_unique<uint8_t[]>(total_bytes()), requires_grad, 0};
    Add(rhs, out);
    return out;
}

Array Array::operator*(const Array& rhs) const {
    bool requires_grad = (requires_grad_ || rhs.requires_grad());
    Array out = {shape_, dtype_, std::make_unique<uint8_t[]>(total_bytes()), requires_grad, 0};
    Mul(rhs, out);
    return out;
}

void Array::Add(const Array& rhs, Array& out) const {
    if ((&out == this || &out == &rhs) && out.requires_grad_) {
        throw XchainerError("In-place operation (Add) is not supported for an array with requires_grad=true.");
    }

    // TODO: dtype conversion
    CheckEqual(dtype_, rhs.dtype());
    // TODO: broadcasting
    CheckEqual(shape_, rhs.shape());

    if (requires_grad_ || rhs.requires_grad()) {
        const Array& lhs = *this;
        std::shared_ptr<const ArrayNode> lhs_node = node();
        std::shared_ptr<const ArrayNode> rhs_node = rhs.node();
        std::shared_ptr<ArrayNode> out_node = out.RenewNode();
        std::function<Array(const Array&)> empty_func;
        auto lhs_func = lhs.requires_grad() ? [](const Array& gout) { return gout; } : empty_func;
        auto rhs_func = rhs.requires_grad() ? [](const Array& gout) { return gout; } : empty_func;
        auto backward_functions = std::vector<std::function<Array(const Array&)>>{lhs_func, rhs_func};
        std::shared_ptr<OpNode> op_node =
            std::make_shared<OpNode>("add", std::vector<std::shared_ptr<const ArrayNode>>{lhs_node, rhs_node}, backward_functions);
        out_node->set_next_node(op_node);
    }

    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Add(*this, rhs, out);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Add(*this, rhs, out);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void Array::Mul(const Array& rhs, Array& out) const {
    if ((&out == this || &out == &rhs) && out.requires_grad_) {
        throw XchainerError("In-place operation (Mul) is not supported for an array with requires_grad=true.");
    }

    // TODO: dtype conversion
    CheckEqual(dtype_, rhs.dtype());
    // TODO: broadcasting
    CheckEqual(shape_, rhs.shape());

    if (requires_grad_ || rhs.requires_grad()) {
        // deep copy for in-place operation to keep original input
        const Array& lhs = (this == &out) ? DeepCopy() : *this;
        std::shared_ptr<const ArrayNode> lhs_node = node();
        std::shared_ptr<const ArrayNode> rhs_node = rhs.node();
        std::shared_ptr<ArrayNode> out_node = out.RenewNode();
        std::function<Array(const Array&)> empty_func;
        // TODO(sonots): turn off constructing graph (requires_grad) in backward (but, turn on for double backprop)
        auto lhs_func = lhs.requires_grad() ? [rhs](const Array& gout) { return gout * rhs; } : empty_func;
        auto rhs_func = rhs.requires_grad() ? [lhs](const Array& gout) { return gout * lhs; } : empty_func;
        auto backward_functions = std::vector<std::function<Array(const Array&)>>{lhs_func, rhs_func};
        std::shared_ptr<OpNode> op_node =
            std::make_shared<OpNode>("mul", std::vector<std::shared_ptr<const ArrayNode>>{lhs_node, rhs_node}, backward_functions);
        out_node->set_next_node(op_node);
    }

    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Mul(*this, rhs, out);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Mul(*this, rhs, out);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void Array::Fill(Scalar value) {
    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Fill(*this, value);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Fill(*this, value);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

std::string Array::ToString() const { return ArrayRepr(*this); }

namespace {

void DebugDumpComputationalGraph(std::ostream& os, const ArrayNode& array_node, int indent) {
    static const char kIndentChar = ' ';

    os << std::string(static_cast<size_t>(indent * 2), kIndentChar) << "ArrayNode<" << &array_node << ">" << std::endl;

    std::shared_ptr<const OpNode> op = array_node.next_node();
    if (op) {
        os << std::string(static_cast<size_t>((indent + 1) * 2), kIndentChar) << "Op<" << op->name() << ">" << std::endl;
        for (const std::shared_ptr<const ArrayNode>& next_node : op->next_nodes()) {
            DebugDumpComputationalGraph(os, *next_node, static_cast<size_t>(indent + 2));
        }
    }
}

}  // namespace

void DebugDumpComputationalGraph(std::ostream& os, const Array& array, int indent) {
    DebugDumpComputationalGraph(os, *array.node(), indent);
}

}  // namespace xchainer
<commit_msg>Remove deep copy for in-place operation<commit_after>#include "xchainer/array.h"

#include <cassert>
#include <cstring>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA

#include "xchainer/array_fill.h"
#include "xchainer/array_math.h"
#include "xchainer/array_repr.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/array_fill.h"
#include "xchainer/cuda/array_math.h"
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/op_node.h"
#include "xchainer/scalar.h"

namespace xchainer {

namespace {

#ifdef XCHAINER_ENABLE_CUDA
std::shared_ptr<void> AllocateCudaManaged(size_t size) {
    std::shared_ptr<void> ptr{};
    {
        void* raw_ptr = nullptr;
        auto raw_ptr_scope = gsl::finally([&]() {
            if (raw_ptr && !ptr) {
                cudaFree(raw_ptr);
            }
        });
        cuda::CheckError(cudaMallocManaged(&raw_ptr, size, cudaMemAttachGlobal));
        ptr.reset(raw_ptr, cudaFree);
    }
    return ptr;
}
#endif  // XCHAINER_ENABLE_CUDA

std::shared_ptr<void> Allocate(const Device& device, size_t size) {
    if (device == MakeDevice("cpu")) {
        return std::make_unique<uint8_t[]>(size);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        return AllocateCudaManaged(size);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void MemoryCopy(const Device& device, void* dst_ptr, const void* src_ptr, size_t size) {
    if (device == MakeDevice("cpu")) {
        std::memcpy(dst_ptr, src_ptr, size);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, size, cudaMemcpyHostToDevice));
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

}  // namespace

Array::Array(const Shape& shape, Dtype dtype, std::shared_ptr<void> data, bool requires_grad, int64_t offset)
    : shape_(shape),
      is_contiguous_(true),
      dtype_(dtype),
      data_(nullptr),
      requires_grad_(requires_grad),
      offset_(offset),
      node_(std::make_shared<ArrayNode>()) {
    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        data_ = std::move(data);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        size_t size = static_cast<size_t>(shape_.total_size() * GetElementSize(dtype));
        data_ = AllocateCudaManaged(size);
        MemoryCopy(device, data_.get(), data.get(), size);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

Array Array::Empty(const Shape& shape, Dtype dtype) {
    size_t size = static_cast<size_t>(shape.total_size() * GetElementSize(dtype));
    std::shared_ptr<void> data = Allocate(GetCurrentDevice(), size);
    return {shape, dtype, data};
}

Array Array::EmptyLike(const Array& array) { return Empty(array.shape(), array.dtype()); }

Array Array::DeepCopy() const {
    auto bytes = total_bytes();
    if (GetCurrentDevice() == MakeDevice("cpu")) {
        std::shared_ptr<void> ret_data = std::make_unique<uint8_t[]>(bytes);
        std::memcpy(ret_data.get(), data_.get(), bytes);
        return {shape_, dtype_, ret_data, requires_grad_, offset_};
#ifdef XCHAINER_ENABLE_CUDA
    } else if (GetCurrentDevice() == MakeDevice("cuda")) {
        // TODO(sonots): Better to use abstraction layer such as Allocate or MemoryCopy,
        // but they do not support all cases such as device to device, yet. We need refactoring.
        void* ret_ptr = nullptr;
        cuda::CheckError(cudaMallocManaged(&ret_ptr, bytes, cudaMemAttachGlobal));
        std::shared_ptr<void> ret_data(ret_ptr, ::cudaFree);
        cuda::CheckError(cudaMemcpy(ret_ptr, data_.get(), bytes, cudaMemcpyDeviceToDevice));
        return {shape_, dtype_, ret_data, requires_grad_, offset_};
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

Array& Array::operator+=(const Array& rhs) {
    Add(rhs, *this);
    requires_grad_ |= rhs.requires_grad();
    return *this;
}

Array& Array::operator*=(const Array& rhs) {
    Mul(rhs, *this);
    requires_grad_ |= rhs.requires_grad();
    return *this;
}

Array Array::operator+(const Array& rhs) const {
    bool requires_grad = (requires_grad_ || rhs.requires_grad());
    Array out = {shape_, dtype_, std::make_unique<uint8_t[]>(total_bytes()), requires_grad, 0};
    Add(rhs, out);
    return out;
}

Array Array::operator*(const Array& rhs) const {
    bool requires_grad = (requires_grad_ || rhs.requires_grad());
    Array out = {shape_, dtype_, std::make_unique<uint8_t[]>(total_bytes()), requires_grad, 0};
    Mul(rhs, out);
    return out;
}

void Array::Add(const Array& rhs, Array& out) const {
    if ((&out == this || &out == &rhs) && out.requires_grad_) {
        throw XchainerError("In-place operation (Add) is not supported for an array with requires_grad=true.");
    }

    // TODO: dtype conversion
    CheckEqual(dtype_, rhs.dtype());
    // TODO: broadcasting
    CheckEqual(shape_, rhs.shape());

    if (requires_grad_ || rhs.requires_grad()) {
        const Array& lhs = *this;
        std::shared_ptr<const ArrayNode> lhs_node = node();
        std::shared_ptr<const ArrayNode> rhs_node = rhs.node();
        std::shared_ptr<ArrayNode> out_node = out.RenewNode();
        std::function<Array(const Array&)> empty_func;
        auto lhs_func = lhs.requires_grad() ? [](const Array& gout) { return gout; } : empty_func;
        auto rhs_func = rhs.requires_grad() ? [](const Array& gout) { return gout; } : empty_func;
        auto backward_functions = std::vector<std::function<Array(const Array&)>>{lhs_func, rhs_func};
        std::shared_ptr<OpNode> op_node =
            std::make_shared<OpNode>("add", std::vector<std::shared_ptr<const ArrayNode>>{lhs_node, rhs_node}, backward_functions);
        out_node->set_next_node(op_node);
    }

    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Add(*this, rhs, out);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Add(*this, rhs, out);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void Array::Mul(const Array& rhs, Array& out) const {
    if ((&out == this || &out == &rhs) && out.requires_grad_) {
        throw XchainerError("In-place operation (Mul) is not supported for an array with requires_grad=true.");
    }

    // TODO: dtype conversion
    CheckEqual(dtype_, rhs.dtype());
    // TODO: broadcasting
    CheckEqual(shape_, rhs.shape());

    if (requires_grad_ || rhs.requires_grad()) {
        const Array& lhs = *this;
        std::shared_ptr<const ArrayNode> lhs_node = node();
        std::shared_ptr<const ArrayNode> rhs_node = rhs.node();
        std::shared_ptr<ArrayNode> out_node = out.RenewNode();
        std::function<Array(const Array&)> empty_func;
        // TODO(sonots): turn off constructing graph (requires_grad) in backward (but, turn on for double backprop)
        auto lhs_func = lhs.requires_grad() ? [rhs](const Array& gout) { return gout * rhs; } : empty_func;
        auto rhs_func = rhs.requires_grad() ? [lhs](const Array& gout) { return gout * lhs; } : empty_func;
        auto backward_functions = std::vector<std::function<Array(const Array&)>>{lhs_func, rhs_func};
        std::shared_ptr<OpNode> op_node =
            std::make_shared<OpNode>("mul", std::vector<std::shared_ptr<const ArrayNode>>{lhs_node, rhs_node}, backward_functions);
        out_node->set_next_node(op_node);
    }

    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Mul(*this, rhs, out);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Mul(*this, rhs, out);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void Array::Fill(Scalar value) {
    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Fill(*this, value);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Fill(*this, value);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

std::string Array::ToString() const { return ArrayRepr(*this); }

namespace {

void DebugDumpComputationalGraph(std::ostream& os, const ArrayNode& array_node, int indent) {
    static const char kIndentChar = ' ';

    os << std::string(static_cast<size_t>(indent * 2), kIndentChar) << "ArrayNode<" << &array_node << ">" << std::endl;

    std::shared_ptr<const OpNode> op = array_node.next_node();
    if (op) {
        os << std::string(static_cast<size_t>((indent + 1) * 2), kIndentChar) << "Op<" << op->name() << ">" << std::endl;
        for (const std::shared_ptr<const ArrayNode>& next_node : op->next_nodes()) {
            DebugDumpComputationalGraph(os, *next_node, static_cast<size_t>(indent + 2));
        }
    }
}

}  // namespace

void DebugDumpComputationalGraph(std::ostream& os, const Array& array, int indent) {
    DebugDumpComputationalGraph(os, *array.node(), indent);
}

}  // namespace xchainer
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors

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

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

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_FUNCTION_TYPES_HPP
#define SOL_FUNCTION_TYPES_HPP

#include "function_types_core.hpp"
#include "function_types_templated.hpp"
#include "function_types_basic.hpp"
#include "function_types_allocator.hpp"
#include "function_types_member.hpp"
#include "function_types_usertype.hpp"
#include "function_types_overload.hpp"
#include "function_types_allocator.hpp"
#include "resolve.hpp"

namespace sol {

template <typename Sig, typename... Ps>
struct function_arguments {
    std::tuple<Ps...> params;
    template <typename... Args>
    function_arguments(Args&&... args) : params(std::forward<Args>(args)...) {}
};

template <typename Sig = function_sig<>, typename... Args>
function_arguments<Sig, Args...> function_args( Args&&... args ) {
    return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
}

namespace stack {
template<typename... Sigs>
struct pusher<function_sig<Sigs...>> {
    template <typename... Sig, typename Fx, typename... Args>
    static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::functor_function<clean_fx>>(std::forward<Fx>(fx), std::forward<Args>(args)...);
        set_fx(L, std::move(sptr));
    }

    template <typename R, typename... A, typename Fx, typename... Args>
    static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
        using fx_ptr_t = R(*)(A...);
        fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
        select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...);
    }

    template <typename R, typename... A, typename Fx, typename... Args>
    static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
        typedef std::decay_t<meta::Unwrapped<meta::Unqualified<Fx>>> raw_fx_t;
        typedef R(* fx_ptr_t)(A...);
        typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible;
        select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
        typedef meta::function_signature_t<meta::Unwrapped<meta::Unqualified<Fx>>> Sig;
        select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_variable<meta::Unqualified<T>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
        set_fx(L, std::move(sptr));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::decay_t<Fx> dFx;
        dFx memfxptr(std::forward<Fx>(fx));
        auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
        lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::Unqualified<Fx>>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
        upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
        select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
        typedef typename meta::bind_traits<meta::Unqualified<Fx>>::object_type C;
        lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
        int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_function<meta::Unwrapped<meta::Unqualified<T>>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
        set_fx(L, std::move(sptr));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::decay_t<Fx> dFx;
        dFx memfxptr(std::forward<Fx>(fx));
        auto userptr = detail::ptr(std::forward<T>(obj));
        lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::Unqualified<Fx>>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
        upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_member_variable(std::is_member_object_pointer<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
        select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
        typedef typename meta::bind_traits<meta::Unqualified<Fx>>::object_type C;
        lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
        int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_member_function(std::is_member_function_pointer<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
        std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
        lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, target);
        stack::push(L, freefunc, upvalues);
    }

    static void select_function(std::true_type, lua_State* L, lua_CFunction f) {
        stack::push(L, f);
    }

    template <typename Fx, typename... Args>
    static void select(lua_State* L, Fx&& fx, Args&&... args) {
        select_function(std::is_function<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    static void set_fx(lua_State* L, std::unique_ptr<function_detail::base_function> luafunc) {
        function_detail::base_function* target = luafunc.release();
        void* targetdata = static_cast<void*>(target);
        lua_CFunction freefunc = function_detail::call;

        stack::push(L, userdata_value(targetdata));
        function_detail::free_function_cleanup(L);
        lua_setmetatable(L, -2);
        stack::push(L, freefunc, 1);
    }

    template<typename... Args>
    static int push(lua_State* L, Args&&... args) {
        // Set will always place one thing (function) on the stack
        select(L, std::forward<Args>(args)...);
        return 1;
    }
};

template<typename T, typename... Args>
struct pusher<function_arguments<T, Args...>> {
    template <std::size_t... I, typename FP>
    static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
        return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
    }

    template <typename FP>
    static int push(lua_State* L, FP&& fp) {
        return push_func(std::index_sequence_for<Args...>(), L, std::forward<FP>(fp));
    }
};

template<typename Signature>
struct pusher<std::function<Signature>> {
    static int push(lua_State* L, std::function<Signature> fx) {
        return pusher<function_sig<>>{}.push(L, std::move(fx));
    }
};

template<typename... Functions>
struct pusher<overload_set<Functions...>> {
    static int push(lua_State* L, overload_set<Functions...>&& set) {
        pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(std::move(set.set)));
        return 1;
    }

    static int push(lua_State* L, const overload_set<Functions...>& set) {
        pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(set.set));
        return 1;
    }
};

} // stack
} // sol

#endif // SOL_FUNCTION_TYPES_HPP
<commit_msg>unused q_q<commit_after>// The MIT License (MIT)

// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors

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

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

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_FUNCTION_TYPES_HPP
#define SOL_FUNCTION_TYPES_HPP

#include "function_types_core.hpp"
#include "function_types_templated.hpp"
#include "function_types_basic.hpp"
#include "function_types_allocator.hpp"
#include "function_types_member.hpp"
#include "function_types_usertype.hpp"
#include "function_types_overload.hpp"
#include "function_types_allocator.hpp"
#include "resolve.hpp"

namespace sol {

template <typename Sig, typename... Ps>
struct function_arguments {
    std::tuple<Ps...> params;
    template <typename... Args>
    function_arguments(Args&&... args) : params(std::forward<Args>(args)...) {}
};

template <typename Sig = function_sig<>, typename... Args>
function_arguments<Sig, Args...> function_args( Args&&... args ) {
    return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
}

namespace stack {
template<typename... Sigs>
struct pusher<function_sig<Sigs...>> {
    template <typename... Sig, typename Fx, typename... Args>
    static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::functor_function<clean_fx>>(std::forward<Fx>(fx), std::forward<Args>(args)...);
        set_fx(L, std::move(sptr));
    }

    template <typename R, typename... A, typename Fx, typename... Args>
    static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
        using fx_ptr_t = R(*)(A...);
        fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
        select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...);
    }

    template <typename R, typename... A, typename Fx, typename... Args>
    static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
        typedef std::decay_t<meta::Unwrapped<meta::Unqualified<Fx>>> raw_fx_t;
        typedef R(* fx_ptr_t)(A...);
        typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible;
        select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
        typedef meta::function_signature_t<meta::Unwrapped<meta::Unqualified<Fx>>> Sig;
        select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_variable<meta::Unqualified<T>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
        set_fx(L, std::move(sptr));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::decay_t<Fx> dFx;
        dFx memfxptr(std::forward<Fx>(fx));
        auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
        lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::Unqualified<Fx>>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
        upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
        select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
        typedef typename meta::bind_traits<meta::Unqualified<Fx>>::object_type C;
        lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
        int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_function<meta::Unwrapped<meta::Unqualified<T>>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
        set_fx(L, std::move(sptr));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::decay_t<Fx> dFx;
        dFx memfxptr(std::forward<Fx>(fx));
        auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
        lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::Unqualified<Fx>>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
        upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_member_variable(std::is_member_object_pointer<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
        select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
        typedef typename meta::bind_traits<meta::Unqualified<Fx>>::object_type C;
        lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
        int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_member_function(std::is_member_function_pointer<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
        std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
        lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, target);
        stack::push(L, freefunc, upvalues);
    }

    static void select_function(std::true_type, lua_State* L, lua_CFunction f) {
        stack::push(L, f);
    }

    template <typename Fx, typename... Args>
    static void select(lua_State* L, Fx&& fx, Args&&... args) {
        select_function(std::is_function<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    static void set_fx(lua_State* L, std::unique_ptr<function_detail::base_function> luafunc) {
        function_detail::base_function* target = luafunc.release();
        void* targetdata = static_cast<void*>(target);
        lua_CFunction freefunc = function_detail::call;

        stack::push(L, userdata_value(targetdata));
        function_detail::free_function_cleanup(L);
        lua_setmetatable(L, -2);
        stack::push(L, freefunc, 1);
    }

    template<typename... Args>
    static int push(lua_State* L, Args&&... args) {
        // Set will always place one thing (function) on the stack
        select(L, std::forward<Args>(args)...);
        return 1;
    }
};

template<typename T, typename... Args>
struct pusher<function_arguments<T, Args...>> {
    template <std::size_t... I, typename FP>
    static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
        return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
    }

    template <typename FP>
    static int push(lua_State* L, FP&& fp) {
        return push_func(std::index_sequence_for<Args...>(), L, std::forward<FP>(fp));
    }
};

template<typename Signature>
struct pusher<std::function<Signature>> {
    static int push(lua_State* L, std::function<Signature> fx) {
        return pusher<function_sig<>>{}.push(L, std::move(fx));
    }
};

template<typename... Functions>
struct pusher<overload_set<Functions...>> {
    static int push(lua_State* L, overload_set<Functions...>&& set) {
        pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(std::move(set.set)));
        return 1;
    }

    static int push(lua_State* L, const overload_set<Functions...>& set) {
        pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(set.set));
        return 1;
    }
};

} // stack
} // sol

#endif // SOL_FUNCTION_TYPES_HPP
<|endoftext|>


<commit_before>#include "components/WebGUIComponent.h"

namespace Sigma {
	void WebGUIView::InjectKeyboardEvent(const unsigned int key, const Sigma::event::KEY_STATE state) {
		if (this->hasFocus) {
			CefKeyEvent key_event;
			memset(&key_event, 0, sizeof(CefKeyEvent));

			key_event.native_key_code = key;

			if (state == Sigma::event::KS_UP) {
				key_event.type = KEYEVENT_KEYUP;
				this->browserHost->SendKeyEvent(key_event);
			}
			else {
				key_event.type = KEYEVENT_KEYDOWN;
				this->browserHost->SendKeyEvent(key_event);
			}
		}
	}

	bool WebGUIView::InjectMouseMove(float x, float y) {
		CefMouseEvent mouse_event;
		mouse_event.x = (x - this->x) * this->windowWidth;
		mouse_event.y = (y - this->y) * this->windowHeight;

		if(this->mouseDown == 0) {
			if ((x > this->x) && (x < (this->x + this->width))) {
				if ((y > this->y) && (y < (this->y + this->height))) {
					this->browserHost->SendFocusEvent(true);
					this->hasFocus = true;
					this->browserHost->SendMouseMoveEvent(mouse_event, false);
					return true;
				}
			}
			this->browserHost->SendFocusEvent(false);
			this->hasFocus = false;
		}
		else {
			this->browserHost->SendMouseMoveEvent(mouse_event, false);
			return true;
		}
		return false;
	}

	bool WebGUIView::InjectMouseDown(const Sigma::event::BUTTON btn, float x, float y) {
		if (btn != Sigma::event::BUTTON::LEFT) { return false; }
		if ((x > this->x) && (x < (this->x + this->width))) {
			if ((y > this->y) && (y < (this->y + this->height))) {
				CefMouseEvent mouse_event;
				mouse_event.x = (x - this->x) * this->windowWidth;
				mouse_event.y = (y - this->y) * this->windowHeight;

				this->browserHost->SendFocusEvent(true);
				this->hasFocus = true;
				this->browserHost->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
				this->mouseDown = 1;
				//this->browserHost->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
				return true; // Early return to prevent focus loss.
			}
		}
		this->browserHost->SendFocusEvent(false);
		this->hasFocus = false;
		return false;
	}

	bool WebGUIView::InjectMouseUp(const Sigma::event::BUTTON btn, float x, float y) {
		if (this->hasFocus) {
			CefMouseEvent mouse_event;
			mouse_event.x = (x - this->x) * this->windowWidth;
			mouse_event.y = (y - this->y) * this->windowHeight;
			this->browserHost->SendMouseClickEvent(mouse_event, btn == Sigma::event::BUTTON::LEFT ? MBT_LEFT : (btn == Sigma::event::BUTTON::MIDDLE ? MBT_MIDDLE : MBT_RIGHT), true, 1);
			this->mouseDown = 0;
			return true;
		}
		this->browserHost->SendFocusEvent(false);
		this->hasFocus = false;
		return false;
	}

	void WebGUIView::InjectCharDown(const unsigned int c) {
		if (this->hasFocus) {
			CefKeyEvent key_event;
			memset(&key_event, 0, sizeof(CefKeyEvent));

			key_event.native_key_code = c;

			if (c >= 32) {
				key_event.type = KEYEVENT_CHAR;

				key_event.character = c;
				key_event.unmodified_character = c;

				this->browserHost->SendKeyEvent(key_event);
				key_event.type = KEYEVENT_KEYUP;
				this->browserHost->SendKeyEvent(key_event);
			}
		}
	}
}
<commit_msg>Added a catch in InjectMouseMove to prevent a crash if an event is sent before browsetHost is initialized<commit_after>#include "components/WebGUIComponent.h"

namespace Sigma {
	void WebGUIView::InjectKeyboardEvent(const unsigned int key, const Sigma::event::KEY_STATE state) {
		if (this->hasFocus) {
			CefKeyEvent key_event;
			memset(&key_event, 0, sizeof(CefKeyEvent));

			key_event.native_key_code = key;

			if (state == Sigma::event::KS_UP) {
				key_event.type = KEYEVENT_KEYUP;
				this->browserHost->SendKeyEvent(key_event);
			}
			else {
				key_event.type = KEYEVENT_KEYDOWN;
				this->browserHost->SendKeyEvent(key_event);
			}
		}
	}

	bool WebGUIView::InjectMouseMove(float x, float y) {
		if (!this->browserHost) {
			return false;
		}
		CefMouseEvent mouse_event;
		mouse_event.x = (x - this->x) * this->windowWidth;
		mouse_event.y = (y - this->y) * this->windowHeight;

		if(this->mouseDown == 0) {
			if ((x > this->x) && (x < (this->x + this->width))) {
				if ((y > this->y) && (y < (this->y + this->height))) {
					this->browserHost->SendFocusEvent(true);
					this->hasFocus = true;
					this->browserHost->SendMouseMoveEvent(mouse_event, false);
					return true;
				}
			}
			this->browserHost->SendFocusEvent(false);
			this->hasFocus = false;
		}
		else {
			this->browserHost->SendMouseMoveEvent(mouse_event, false);
			return true;
		}
		return false;
	}

	bool WebGUIView::InjectMouseDown(const Sigma::event::BUTTON btn, float x, float y) {
		if (btn != Sigma::event::BUTTON::LEFT) { return false; }
		if ((x > this->x) && (x < (this->x + this->width))) {
			if ((y > this->y) && (y < (this->y + this->height))) {
				CefMouseEvent mouse_event;
				mouse_event.x = (x - this->x) * this->windowWidth;
				mouse_event.y = (y - this->y) * this->windowHeight;

				this->browserHost->SendFocusEvent(true);
				this->hasFocus = true;
				this->browserHost->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
				this->mouseDown = 1;
				//this->browserHost->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
				return true; // Early return to prevent focus loss.
			}
		}
		this->browserHost->SendFocusEvent(false);
		this->hasFocus = false;
		return false;
	}

	bool WebGUIView::InjectMouseUp(const Sigma::event::BUTTON btn, float x, float y) {
		if (this->hasFocus) {
			CefMouseEvent mouse_event;
			mouse_event.x = (x - this->x) * this->windowWidth;
			mouse_event.y = (y - this->y) * this->windowHeight;
			this->browserHost->SendMouseClickEvent(mouse_event, btn == Sigma::event::BUTTON::LEFT ? MBT_LEFT : (btn == Sigma::event::BUTTON::MIDDLE ? MBT_MIDDLE : MBT_RIGHT), true, 1);
			this->mouseDown = 0;
			return true;
		}
		this->browserHost->SendFocusEvent(false);
		this->hasFocus = false;
		return false;
	}

	void WebGUIView::InjectCharDown(const unsigned int c) {
		if (this->hasFocus) {
			CefKeyEvent key_event;
			memset(&key_event, 0, sizeof(CefKeyEvent));

			key_event.native_key_code = c;

			if (c >= 32) {
				key_event.type = KEYEVENT_CHAR;

				key_event.character = c;
				key_event.unmodified_character = c;

				this->browserHost->SendKeyEvent(key_event);
				key_event.type = KEYEVENT_KEYUP;
				this->browserHost->SendKeyEvent(key_event);
			}
		}
	}
}
<|endoftext|>


<commit_before>
// ChunkSender.cpp

// Interfaces to the cChunkSender class representing the thread that waits for chunks becoming ready (loaded / generated) and sends them to clients

#include "Globals.h"
#include "ChunkSender.h"
#include "cWorld.h"
#include "packets/cPacket_MapChunk.h"
#include "packets/cPacket_PreChunk.h"
#include "cBlockEntity.h"

cChunkSender::cChunkSender(void) :
	super("ChunkSender"),
	m_World(NULL)
{
}

cChunkSender::~cChunkSender()
{
	mShouldTerminate = true;
	m_Event.Set();
}

bool cChunkSender::Start(cWorld * a_World)
{
	m_World = a_World;
	return super::Start();
}

void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
	// This is probably never gonna be called twice for the same chunk, and if it is, we don't mind, so we don't check
	{
		cCSLock Lock(m_CS);
		m_ChunksReady.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
	}
	m_Event.Set();
}

void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
{
	ASSERT(a_Client != NULL);
	{
		cCSLock Lock(m_CS);
		m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client));
	}
	m_Event.Set();
}

void cChunkSender::RemoveClient(cClientHandle * a_Client)
{
	cCSLock Lock(m_CS);
	for (sSendChunkList::iterator itr = m_SendChunks.begin(); itr != m_SendChunks.end();)
	{
		if (itr->m_Client == a_Client)
		{
			itr = m_SendChunks.erase(itr);
			continue;
		}
		++itr;
	}  // for itr - m_SendChunks[]
}

void cChunkSender::Execute(void)
{
	while (!mShouldTerminate)
	{
		cCSLock Lock(m_CS);
		while (m_ChunksReady.empty() && m_SendChunks.empty())
		{
			cCSUnlock Unlock(Lock);
			m_Event.Wait();
			if (mShouldTerminate)
			{
				return;
			}
		}  // while (empty)

		if (!m_ChunksReady.empty())
		{
			// Take one from the queue:
			cChunkCoords Coords(m_ChunksReady.front());
			m_ChunksReady.pop_front();
			Lock.Unlock();

			SendChunk(Coords.m_ChunkX, Coords.m_ChunkY, Coords.m_ChunkZ, NULL);
		}
		else
		{
			// Take one from the queue:
			sSendChunk Chunk(m_SendChunks.front());
			m_SendChunks.pop_front();
			Lock.Unlock();

			SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkY, Chunk.m_ChunkZ, Chunk.m_Client);
		}
	}  // while (!mShouldTerminate)
}

void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
{
	ASSERT(m_World != NULL);

	// Prepare MapChunk packets:
	m_World->GetChunkData(a_ChunkX, a_ChunkY, a_ChunkZ, this);
	cPacket_PreChunk PreChunk(a_ChunkX, a_ChunkZ, true);
	cPacket_MapChunk MapChunk(a_ChunkX, a_ChunkY, a_ChunkZ, m_BlockData);

	// Send:
	if (a_Client == NULL)
	{
		m_World->BroadcastToChunk(a_ChunkX, a_ChunkY, a_ChunkZ, PreChunk);
		m_World->BroadcastToChunk(a_ChunkX, a_ChunkY, a_ChunkZ, MapChunk);
	}
	else
	{
		a_Client->Send(PreChunk);
		a_Client->Send(MapChunk);
	}

	// Send entity creation packets:
	for (PacketList::iterator itr = m_Packets.begin(); itr != m_Packets.end(); ++itr)
	{
		if (a_Client == NULL)
		{
			m_World->BroadcastToChunk(a_ChunkX, a_ChunkY, a_ChunkZ, **itr);
		}
		else
		{
			a_Client->Send(**itr);
		}
		delete *itr;
	}  // for itr - m_Packets[]
	m_Packets.clear();
}

void cChunkSender::BlockData(const char * a_Data)
{
	memcpy(m_BlockData, a_Data, cChunk::c_BlockDataSize);
}

void cChunkSender::BlockEntity(cBlockEntity * a_Entity)
{
	m_Packets.push_back(a_Entity->GetPacket());
}

void cChunkSender::Entity(cEntity * a_Entity)
{
	// Nothing needed yet, perhaps in the future when we save entities into chunks we'd like to send them upon load, too ;)
}

<commit_msg>ChunkSender won't send NULL packets anymore<commit_after>
// ChunkSender.cpp

// Interfaces to the cChunkSender class representing the thread that waits for chunks becoming ready (loaded / generated) and sends them to clients

#include "Globals.h"
#include "ChunkSender.h"
#include "cWorld.h"
#include "packets/cPacket_MapChunk.h"
#include "packets/cPacket_PreChunk.h"
#include "cBlockEntity.h"

cChunkSender::cChunkSender(void) :
	super("ChunkSender"),
	m_World(NULL)
{
}

cChunkSender::~cChunkSender()
{
	mShouldTerminate = true;
	m_Event.Set();
}

bool cChunkSender::Start(cWorld * a_World)
{
	m_World = a_World;
	return super::Start();
}

void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
	// This is probably never gonna be called twice for the same chunk, and if it is, we don't mind, so we don't check
	{
		cCSLock Lock(m_CS);
		m_ChunksReady.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
	}
	m_Event.Set();
}

void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
{
	ASSERT(a_Client != NULL);
	{
		cCSLock Lock(m_CS);
		m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client));
	}
	m_Event.Set();
}

void cChunkSender::RemoveClient(cClientHandle * a_Client)
{
	cCSLock Lock(m_CS);
	for (sSendChunkList::iterator itr = m_SendChunks.begin(); itr != m_SendChunks.end();)
	{
		if (itr->m_Client == a_Client)
		{
			itr = m_SendChunks.erase(itr);
			continue;
		}
		++itr;
	}  // for itr - m_SendChunks[]
}

void cChunkSender::Execute(void)
{
	while (!mShouldTerminate)
	{
		cCSLock Lock(m_CS);
		while (m_ChunksReady.empty() && m_SendChunks.empty())
		{
			cCSUnlock Unlock(Lock);
			m_Event.Wait();
			if (mShouldTerminate)
			{
				return;
			}
		}  // while (empty)

		if (!m_ChunksReady.empty())
		{
			// Take one from the queue:
			cChunkCoords Coords(m_ChunksReady.front());
			m_ChunksReady.pop_front();
			Lock.Unlock();

			SendChunk(Coords.m_ChunkX, Coords.m_ChunkY, Coords.m_ChunkZ, NULL);
		}
		else
		{
			// Take one from the queue:
			sSendChunk Chunk(m_SendChunks.front());
			m_SendChunks.pop_front();
			Lock.Unlock();

			SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkY, Chunk.m_ChunkZ, Chunk.m_Client);
		}
	}  // while (!mShouldTerminate)
}

void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
{
	ASSERT(m_World != NULL);

	// Prepare MapChunk packets:
	m_World->GetChunkData(a_ChunkX, a_ChunkY, a_ChunkZ, this);
	cPacket_PreChunk PreChunk(a_ChunkX, a_ChunkZ, true);
	cPacket_MapChunk MapChunk(a_ChunkX, a_ChunkY, a_ChunkZ, m_BlockData);

	// Send:
	if (a_Client == NULL)
	{
		m_World->BroadcastToChunk(a_ChunkX, a_ChunkY, a_ChunkZ, PreChunk);
		m_World->BroadcastToChunk(a_ChunkX, a_ChunkY, a_ChunkZ, MapChunk);
	}
	else
	{
		a_Client->Send(PreChunk);
		a_Client->Send(MapChunk);
	}

	// Send entity creation packets:
	for (PacketList::iterator itr = m_Packets.begin(); itr != m_Packets.end(); ++itr)
	{
		if (a_Client == NULL)
		{
			m_World->BroadcastToChunk(a_ChunkX, a_ChunkY, a_ChunkZ, **itr);
		}
		else
		{
			a_Client->Send(**itr);
		}
		delete *itr;
	}  // for itr - m_Packets[]
	m_Packets.clear();
}

void cChunkSender::BlockData(const char * a_Data)
{
	memcpy(m_BlockData, a_Data, cChunk::c_BlockDataSize);
}

void cChunkSender::BlockEntity(cBlockEntity * a_Entity)
{
	cPacket * Packet = a_Entity->GetPacket();
	if (Packet != NULL)
	{
		m_Packets.push_back(Packet);
	}
}

void cChunkSender::Entity(cEntity * a_Entity)
{
	// Nothing needed yet, perhaps in the future when we save entities into chunks we'd like to send them upon load, too ;)
}

<|endoftext|>


<commit_before>#include "Config.hpp"
#include "Exception.hpp"
#include "Utility.hpp"
#include <fstream>

// Includes needed to get path of dynamic library
#ifdef _WIN32
#include <windows.h>
#else
#define __USE_GNU 1
#include <dlfcn.h>
#endif

namespace fast {

	namespace Config {
		namespace {
			// Initialize global variables, put in anonymous namespace to hide them
			bool mConfigurationLoaded = false;
			std::string mConfigFilename = "";
			std::string mBasePath = "";
			std::string mTestDataPath;
			std::string mKernelSourcePath;
			std::string mKernelBinaryPath;
			std::string mDocumentationPath;
			std::string mPipelinePath;
			std::string mLibraryPath;
			std::string mQtPluginsPath;
			StreamingMode m_streamingMode = STREAMING_MODE_PROCESS_ALL_FRAMES;
		}

		std::string getPath() {
			if (mBasePath != "")
				return mBasePath;
			std::string path = "";
			std::string slash = "/";
			// Find path of the FAST dynamic library
			// The fast_configuration.txt file should lie in the folder below
#ifdef _WIN32
			// http://stackoverflow.com/questions/6924195/get-dll-path-at-runtime
			HMODULE hm = NULL;

			if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
				GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
				(LPCSTR)&getPath,
				&hm)) {
				int ret = GetLastError();
				throw Exception("Error reading dyanmic library address in getPath()");
			}
			char dlpath[MAX_PATH];
			GetModuleFileNameA(hm, dlpath, sizeof(dlpath));
			path = std::string(dlpath);
			path = replace(path, "\\", "/"); // Replace windows \ with /
			path = replace(path, "/FAST.dll", "");
#else
			// http://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded
			Dl_info dl_info;
			int ret = dladdr((void *)&getPath, &dl_info);
			if (ret == 0)
				throw Exception("Error reading dynamic library address in getPath()");
			const char* dlpath = dl_info.dli_fname;
			path = std::string(dlpath);
			// Remove lib name and lib folder
			int libPos = path.rfind(slash + "lib" + slash);
			path = path.substr(0, libPos) + slash + "bin";
#endif

			path = path + slash; // Make sure there is a slash at the end
			return path;
		}

		void loadConfiguration() {
			if (mConfigurationLoaded)
				return;

			// Set default paths
			mTestDataPath = getPath() + "../../data/";
			mKernelSourcePath = getPath() + "../../source/FAST/";
			mKernelBinaryPath = getPath() + "../kernel_binaries/";
			mDocumentationPath = getPath() + "../../doc/";
			mPipelinePath = getPath() + "../../pipelines/";
			mQtPluginsPath = getPath() + "../plugins/";
#ifdef WIN32
			mLibraryPath = getPath();
#else
			mLibraryPath = getPath() + "/../lib/";
#endif

			// Read and parse configuration file
			// It should reside in the build folder when compiling, and in the root folder when using release
			std::string filename;
			if(mConfigFilename == "") {
				filename = getPath() + "fast_configuration.txt";
			}
			else {
				filename = mConfigFilename;
			}
			std::ifstream file(filename);
			if (!file.is_open()) {
				Reporter::warning() << "Unable to open the configuration file " << filename << ". Using defaults instead." << Reporter::end();
				mConfigurationLoaded = true;
				return;
			}
			Reporter::info() << "Loaded configuration file: " << filename << Reporter::end();

			do {
				std::string line;
				std::getline(file, line);
				trim(line);
				if (line[0] == '#' || line.size() == 0) {
					// Comment or empty line, skip
					continue;
				}
				std::vector<std::string> list = split(line, "=");
				if (list.size() != 2) {
					throw Exception("Error parsing configuration file. Expected key = value pair, got: " + line);
				}

				std::string key = list[0];
				std::string value = list[1];
				trim(key);
				trim(value);
				value = replace(value, "@ROOT@", getPath() + "/../");

				if (key == "TestDataPath") {
					mTestDataPath = value;
				}
				else if (key == "KernelSourcePath") {
					mKernelSourcePath = value;
				}
				else if (key == "KernelBinaryPath") {
					mKernelBinaryPath = value;
				}
				else if (key == "DocumentationPath") {
					mDocumentationPath = value;
				}
				else if (key == "PipelinePath") {
					mPipelinePath = value;
				}
				else if (key == "QtPluginsPath") {
					mQtPluginsPath = value;
				}
				else if (key == "LibraryPath") {
					mLibraryPath = value;
				}
				else {
					throw Exception("Error parsing configuration file. Unrecognized key: " + key);
				}
			} while (!file.eof());
			file.close();

			Reporter::info() << "Test data path: " << mTestDataPath << Reporter::end();
			Reporter::info() << "Kernel source path: " << mKernelSourcePath << Reporter::end();
			Reporter::info() << "Kernel binary path: " << mKernelBinaryPath << Reporter::end();
			Reporter::info() << "Documentation path: " << mDocumentationPath << Reporter::end();
			Reporter::info() << "Pipeline path: " << mPipelinePath << Reporter::end();
			Reporter::info() << "Qt plugins path: " << mQtPluginsPath << Reporter::end();
            Reporter::info() << "Library path: " << mLibraryPath << Reporter::end();

			mConfigurationLoaded = true;
		}

		std::string getTestDataPath() {
			loadConfiguration();
			return mTestDataPath;
		}

		std::string getKernelSourcePath() {
			loadConfiguration();
			return mKernelSourcePath;
		}

		std::string getKernelBinaryPath() {
			loadConfiguration();
			return mKernelBinaryPath;
		}

		std::string getDocumentationPath() {
			loadConfiguration();
			return mDocumentationPath;
		}

		std::string getPipelinePath() {
			loadConfiguration();
			return mPipelinePath;
		}

		std::string getLibraryPath() {
		    loadConfiguration();
		    return mLibraryPath;
		}

		std::string getQtPluginsPath() {
			loadConfiguration();
			return mQtPluginsPath;
		}

		void setConfigFilename(std::string filename) {
			mConfigFilename = filename;
			loadConfiguration();
		}

		void setBasePath(std::string path) {
			mBasePath = path;
			if (mBasePath[mBasePath.size() - 1] != '/')
				mBasePath += "/";
			mTestDataPath = getPath() + "../data/";
			mKernelSourcePath = getPath() + "../source/FAST/";
			mKernelBinaryPath = getPath() + "kernel_binaries/";
			mDocumentationPath = getPath() + "../doc/";
			mPipelinePath = getPath() + "../pipelines/";
#ifdef WIN32
            mLibraryPath = getPath() + "../bin/";
#else
            mLibraryPath = getPath() + "../lib/";
#endif
			loadConfiguration();
		}

		void setTestDataPath(std::string path) {
			mTestDataPath = path;
		}

		void setKernelSourcePath(std::string path) {
			mKernelSourcePath = path;
		}

		void setKernelBinaryPath(std::string path) {
			mKernelBinaryPath = path;
		}

		void setDocumentationPath(std::string path) {
			mDocumentationPath = path;
		}

		void setPipelinePath(std::string path) {
			mPipelinePath = path;
		}

		void setStreamingMode(StreamingMode mode) {
		    m_streamingMode = mode;
		}

		StreamingMode getStreamingMode() {
		    return m_streamingMode;
		}

	} // end namespace Config

}; // end namespace fast
<commit_msg>added execption to config class on windows, if FAST is installed in Program Files it will not be able to write to this folder and need to use ProgramData folder instead<commit_after>#include "Config.hpp"
#include "Exception.hpp"
#include "Utility.hpp"
#include <fstream>

// Includes needed to get path of dynamic library
#ifdef _WIN32
#include <windows.h>
#else
#define __USE_GNU 1
#include <dlfcn.h>
#endif

namespace fast {

	namespace Config {
		namespace {
			// Initialize global variables, put in anonymous namespace to hide them
			bool mConfigurationLoaded = false;
			std::string mConfigFilename = "";
			std::string mBasePath = "";
			std::string mTestDataPath;
			std::string mKernelSourcePath;
			std::string mKernelBinaryPath;
			std::string mDocumentationPath;
			std::string mPipelinePath;
			std::string mLibraryPath;
			std::string mQtPluginsPath;
			StreamingMode m_streamingMode = STREAMING_MODE_PROCESS_ALL_FRAMES;
		}

		std::string getPath() {
			if (mBasePath != "")
				return mBasePath;
			std::string path = "";
			std::string slash = "/";
			// Find path of the FAST dynamic library
			// The fast_configuration.txt file should lie in the folder below
#ifdef _WIN32
			// http://stackoverflow.com/questions/6924195/get-dll-path-at-runtime
			HMODULE hm = NULL;

			if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
				GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
				(LPCSTR)&getPath,
				&hm)) {
				int ret = GetLastError();
				throw Exception("Error reading dyanmic library address in getPath()");
			}
			char dlpath[MAX_PATH];
			GetModuleFileNameA(hm, dlpath, sizeof(dlpath));
			path = std::string(dlpath);
			path = replace(path, "\\", "/"); // Replace windows \ with /
			path = replace(path, "/FAST.dll", "");
#else
			// http://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded
			Dl_info dl_info;
			int ret = dladdr((void *)&getPath, &dl_info);
			if (ret == 0)
				throw Exception("Error reading dynamic library address in getPath()");
			const char* dlpath = dl_info.dli_fname;
			path = std::string(dlpath);
			// Remove lib name and lib folder
			int libPos = path.rfind(slash + "lib" + slash);
			path = path.substr(0, libPos) + slash + "bin";
#endif

			path = path + slash; // Make sure there is a slash at the end
			return path;
		}

		void loadConfiguration() {
			if (mConfigurationLoaded)
				return;

			// Set default paths
			mTestDataPath = getPath() + "../../data/";
			mKernelSourcePath = getPath() + "../../source/FAST/";
			mKernelBinaryPath = getPath() + "../kernel_binaries/";
			mDocumentationPath = getPath() + "../../doc/";
			mPipelinePath = getPath() + "../../pipelines/";
			mQtPluginsPath = getPath() + "../plugins/";

			std::string writeablePath = getPath();
#ifdef WIN32
			mLibraryPath = getPath();
			if(getPath().find("Program Files") != std::string::npos) {
				// Special case for windows: default install dir: program files is not writeable.
				// Use ProgramData folder instead.
				writeablePath = "C:/ProgramData/FAST/";
				// Copy pipelines (first time only)
				for(auto&& pipeline : getDirectoryList(mPipelinePath)) {
					if(!fileExists(writeablePath + "pipelines/" + pipeline)) {
						// Copy file from source folder
						std::ifstream  src(mPipelinePath + pipeline, std::ios::binary);
						std::ofstream  dst(writeablePath + "pipelines/" + pipeline, std::ios::binary);

						dst << src.rdbuf();
					}
				}
			}
#else
			mLibraryPath = getPath() + "/../lib/";
#endif

			// Read and parse configuration file
			// It should reside in the build folder when compiling, and in the root folder when using release
			std::string filename;
			if(mConfigFilename == "") {
				filename = getPath() + "fast_configuration.txt";
			}
			else {
				filename = mConfigFilename;
			}
			std::ifstream file(filename);
			if (!file.is_open()) {
				Reporter::warning() << "Unable to open the configuration file " << filename << ". Using defaults instead." << Reporter::end();
				mConfigurationLoaded = true;
				return;
			}
			Reporter::info() << "Loaded configuration file: " << filename << Reporter::end();

			do {
				std::string line;
				std::getline(file, line);
				trim(line);
				if (line[0] == '#' || line.size() == 0) {
					// Comment or empty line, skip
					continue;
				}
				std::vector<std::string> list = split(line, "=");
				if (list.size() != 2) {
					throw Exception("Error parsing configuration file. Expected key = value pair, got: " + line);
				}

				std::string key = list[0];
				std::string value = list[1];
				trim(key);
				trim(value);

				if (key == "TestDataPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mTestDataPath = value;
				}
				else if (key == "KernelSourcePath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mKernelSourcePath = value;
				}
				else if (key == "KernelBinaryPath") {
					value = replace(value, "@ROOT@", writeablePath);
					mKernelBinaryPath = value;
				}
				else if (key == "DocumentationPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mDocumentationPath = value;
				}
				else if (key == "PipelinePath") {
					value = replace(value, "@ROOT@", writeablePath);
					mPipelinePath = value;
				}
				else if (key == "QtPluginsPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mQtPluginsPath = value;
				}
				else if (key == "LibraryPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mLibraryPath = value;
				}
				else {
					throw Exception("Error parsing configuration file. Unrecognized key: " + key);
				}
			} while (!file.eof());
			file.close();

			Reporter::info() << "Test data path: " << mTestDataPath << Reporter::end();
			Reporter::info() << "Kernel source path: " << mKernelSourcePath << Reporter::end();
			Reporter::info() << "Kernel binary path: " << mKernelBinaryPath << Reporter::end();
			Reporter::info() << "Documentation path: " << mDocumentationPath << Reporter::end();
			Reporter::info() << "Pipeline path: " << mPipelinePath << Reporter::end();
			Reporter::info() << "Qt plugins path: " << mQtPluginsPath << Reporter::end();
            Reporter::info() << "Library path: " << mLibraryPath << Reporter::end();

			mConfigurationLoaded = true;
		}

		std::string getTestDataPath() {
			loadConfiguration();
			return mTestDataPath;
		}

		std::string getKernelSourcePath() {
			loadConfiguration();
			return mKernelSourcePath;
		}

		std::string getKernelBinaryPath() {
			loadConfiguration();
			return mKernelBinaryPath;
		}

		std::string getDocumentationPath() {
			loadConfiguration();
			return mDocumentationPath;
		}

		std::string getPipelinePath() {
			loadConfiguration();
			return mPipelinePath;
		}

		std::string getLibraryPath() {
		    loadConfiguration();
		    return mLibraryPath;
		}

		std::string getQtPluginsPath() {
			loadConfiguration();
			return mQtPluginsPath;
		}

		void setConfigFilename(std::string filename) {
			mConfigFilename = filename;
			loadConfiguration();
		}

		void setBasePath(std::string path) {
			mBasePath = path;
			if (mBasePath[mBasePath.size() - 1] != '/')
				mBasePath += "/";
			mTestDataPath = getPath() + "../data/";
			mKernelSourcePath = getPath() + "../source/FAST/";
			mKernelBinaryPath = getPath() + "kernel_binaries/";
			mDocumentationPath = getPath() + "../doc/";
			mPipelinePath = getPath() + "../pipelines/";
#ifdef WIN32
            mLibraryPath = getPath() + "../bin/";
#else
            mLibraryPath = getPath() + "../lib/";
#endif
			loadConfiguration();
		}

		void setTestDataPath(std::string path) {
			mTestDataPath = path;
		}

		void setKernelSourcePath(std::string path) {
			mKernelSourcePath = path;
		}

		void setKernelBinaryPath(std::string path) {
			mKernelBinaryPath = path;
		}

		void setDocumentationPath(std::string path) {
			mDocumentationPath = path;
		}

		void setPipelinePath(std::string path) {
			mPipelinePath = path;
		}

		void setStreamingMode(StreamingMode mode) {
		    m_streamingMode = mode;
		}

		StreamingMode getStreamingMode() {
		    return m_streamingMode;
		}

	} // end namespace Config

}; // end namespace fast
<|endoftext|>


<commit_before>// Copyright (c) 2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "winshutdownmonitor.h"

#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
#include "init.h"
#include "util.h"

#include <windows.h>

#include <QDebug>

#include <openssl/rand.h>

// If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
{
       Q_UNUSED(eventType);

       MSG *pMsg = static_cast<MSG *>(pMessage);

       // Seed OpenSSL PRNG with Windows event data (e.g.  mouse movements and other user interactions)
       if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
            // Warn only once as this is performance-critical
            static bool warned = false;
            if (!warned) {
                LogPrint("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
                warned = true;
            }
       }

       switch(pMsg->message)
       {
           case WM_QUERYENDSESSION:
           {
               // Initiate a client shutdown after receiving a WM_QUERYENDSESSION and block
               // Windows session end until we have finished client shutdown.
               StartShutdown();
               *pnResult = FALSE;
               return true;
           }

           case WM_ENDSESSION:
           {
               *pnResult = FALSE;
               return true;
           }
       }

       return false;
}

void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId)
{
    typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR);
    PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate");
    if (shutdownBRCreate == NULL) {
        qWarning() << "registerShutdownBlockReason: GetProcAddress for ShutdownBlockReasonCreate failed";
        return;
    }

    if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str()))
        qWarning() << "registerShutdownBlockReason: Successfully registered: " + strReason;
    else
        qWarning() << "registerShutdownBlockReason: Failed to register: " + strReason;
}
#endif
<commit_msg>Fix LogPrint to LogPrintf<commit_after>// Copyright (c) 2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "winshutdownmonitor.h"

#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
#include "init.h"
#include "util.h"

#include <windows.h>

#include <QDebug>

#include <openssl/rand.h>

// If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
{
       Q_UNUSED(eventType);

       MSG *pMsg = static_cast<MSG *>(pMessage);

       // Seed OpenSSL PRNG with Windows event data (e.g.  mouse movements and other user interactions)
       if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
            // Warn only once as this is performance-critical
            static bool warned = false;
            if (!warned) {
                LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
                warned = true;
            }
       }

       switch(pMsg->message)
       {
           case WM_QUERYENDSESSION:
           {
               // Initiate a client shutdown after receiving a WM_QUERYENDSESSION and block
               // Windows session end until we have finished client shutdown.
               StartShutdown();
               *pnResult = FALSE;
               return true;
           }

           case WM_ENDSESSION:
           {
               *pnResult = FALSE;
               return true;
           }
       }

       return false;
}

void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId)
{
    typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR);
    PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate");
    if (shutdownBRCreate == NULL) {
        qWarning() << "registerShutdownBlockReason: GetProcAddress for ShutdownBlockReasonCreate failed";
        return;
    }

    if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str()))
        qWarning() << "registerShutdownBlockReason: Successfully registered: " + strReason;
    else
        qWarning() << "registerShutdownBlockReason: Failed to register: " + strReason;
}
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/winshutdownmonitor.h>

#if defined(Q_OS_WIN)
#include <shutdown.h>
#include <util/system.h>

#include <windows.h>

#include <QDebug>

#include <openssl/rand.h>

// If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
{
       Q_UNUSED(eventType);

       MSG *pMsg = static_cast<MSG *>(pMessage);

       // Seed OpenSSL PRNG with Windows event data (e.g.  mouse movements and other user interactions)
       if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
            // Warn only once as this is performance-critical
            static bool warned = false;
            if (!warned) {
                LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
                warned = true;
            }
       }

       switch(pMsg->message)
       {
           case WM_QUERYENDSESSION:
           {
               // Initiate a client shutdown after receiving a WM_QUERYENDSESSION and block
               // Windows session end until we have finished client shutdown.
               StartShutdown();
               *pnResult = FALSE;
               return true;
           }

           case WM_ENDSESSION:
           {
               *pnResult = FALSE;
               return true;
           }
       }

       return false;
}

void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId)
{
    typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR);
    PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate");
    if (shutdownBRCreate == nullptr) {
        qWarning() << "registerShutdownBlockReason: GetProcAddress for ShutdownBlockReasonCreate failed";
        return;
    }

    if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str()))
        qInfo() << "registerShutdownBlockReason: Successfully registered: " + strReason;
    else
        qWarning() << "registerShutdownBlockReason: Failed to register: " + strReason;
}
#endif
<commit_msg>gui: remove OpenSSL PRNG seeding (Windows, Qt only)<commit_after>// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/winshutdownmonitor.h>

#if defined(Q_OS_WIN)
#include <shutdown.h>

#include <windows.h>

#include <QDebug>

// If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
{
       Q_UNUSED(eventType);

       MSG *pMsg = static_cast<MSG *>(pMessage);

       switch(pMsg->message)
       {
           case WM_QUERYENDSESSION:
           {
               // Initiate a client shutdown after receiving a WM_QUERYENDSESSION and block
               // Windows session end until we have finished client shutdown.
               StartShutdown();
               *pnResult = FALSE;
               return true;
           }

           case WM_ENDSESSION:
           {
               *pnResult = FALSE;
               return true;
           }
       }

       return false;
}

void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId)
{
    typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR);
    PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate");
    if (shutdownBRCreate == nullptr) {
        qWarning() << "registerShutdownBlockReason: GetProcAddress for ShutdownBlockReasonCreate failed";
        return;
    }

    if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str()))
        qInfo() << "registerShutdownBlockReason: Successfully registered: " + strReason;
    else
        qWarning() << "registerShutdownBlockReason: Failed to register: " + strReason;
}
#endif
<|endoftext|>


<commit_before>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include "TestSupport.h"

#include <support/ScopedBuffer.h>
#include <support/TestUtils.h>

#include <nlunit-test.h>

namespace {

class TestCounterMemoryManagement
{
public:
    static int Counter() { return mAllocCount; }

    static void MemoryFree(void * p)
    {
        mAllocCount--;
        chip::Platform::MemoryFree(p);
    }
    static void * MemoryAlloc(size_t size)
    {
        mAllocCount++;
        return chip::Platform::MemoryAlloc(size);
    }
    static void * MemoryAlloc(size_t size, bool longTerm)
    {

        mAllocCount++;
        return chip::Platform::MemoryAlloc(size, longTerm);
    }
    static void * MemoryCalloc(size_t num, size_t size)
    {

        mAllocCount++;
        return chip::Platform::MemoryCalloc(num, size);
    }

private:
    static int mAllocCount;
};
int TestCounterMemoryManagement::mAllocCount = 0;

using TestCounterScopedBuffer = chip::Platform::ScopedMemoryBuffer<char, TestCounterMemoryManagement>;

void TestAutoFree(nlTestSuite * inSuite, void * inContext)
{
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);

    {
        TestCounterScopedBuffer buffer;

        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
        NL_TEST_ASSERT(inSuite, buffer.Alloc(128));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
    }
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
}

void TestFreeDuringAllocs(nlTestSuite * inSuite, void * inContext)
{
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);

    {
        TestCounterScopedBuffer buffer;

        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
        NL_TEST_ASSERT(inSuite, buffer.Alloc(128));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
        NL_TEST_ASSERT(inSuite, buffer.Alloc(64));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
        NL_TEST_ASSERT(inSuite, buffer.LongTermAlloc(256));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
        NL_TEST_ASSERT(inSuite, buffer.Calloc(10));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
    }
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
}

void TestRelease(nlTestSuite * inSuite, void * inContext)
{
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
    void * ptr = nullptr;

    {
        TestCounterScopedBuffer buffer;

        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
        NL_TEST_ASSERT(inSuite, buffer.Alloc(128));
        NL_TEST_ASSERT(inSuite, buffer.Ptr() != nullptr);

        ptr = buffer.Release();
        NL_TEST_ASSERT(inSuite, ptr != nullptr);
        NL_TEST_ASSERT(inSuite, buffer.Ptr() == nullptr);
    }

    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);

    {
        TestCounterScopedBuffer buffer;
        NL_TEST_ASSERT(inSuite, buffer.Alloc(128));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 2);
        TestCounterMemoryManagement::MemoryFree(ptr);
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
    }

    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
}

} // namespace

#define NL_TEST_DEF_FN(fn) NL_TEST_DEF("Test " #fn, fn)
/**
 *   Test Suite. It lists all the test functions.
 */
static const nlTest sTests[] = {
    NL_TEST_DEF_FN(TestAutoFree),         //
    NL_TEST_DEF_FN(TestFreeDuringAllocs), //
    NL_TEST_DEF_FN(TestRelease),          //
    NL_TEST_SENTINEL()                    //
};

int TestScopedBuffer(void)
{
    nlTestSuite theSuite = { "CHIP ScopedBuffer tests", &sTests[0], nullptr, nullptr };

    // Run test suit againt one context.
    nlTestRunner(&theSuite, nullptr);
    return nlTestRunnerStats(&theSuite);
}

CHIP_REGISTER_TEST_SUITE(TestBufBound)
<commit_msg>Make sure scoped buffer test test calls Platform::MemoryInit (#3050)<commit_after>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include "TestSupport.h"

#include <support/ScopedBuffer.h>
#include <support/TestUtils.h>

#include <nlunit-test.h>

namespace {

class TestCounterMemoryManagement
{
public:
    static int Counter() { return mAllocCount; }

    static void MemoryFree(void * p)
    {
        mAllocCount--;
        chip::Platform::MemoryFree(p);
    }
    static void * MemoryAlloc(size_t size)
    {
        mAllocCount++;
        return chip::Platform::MemoryAlloc(size);
    }
    static void * MemoryAlloc(size_t size, bool longTerm)
    {

        mAllocCount++;
        return chip::Platform::MemoryAlloc(size, longTerm);
    }
    static void * MemoryCalloc(size_t num, size_t size)
    {

        mAllocCount++;
        return chip::Platform::MemoryCalloc(num, size);
    }

private:
    static int mAllocCount;
};
int TestCounterMemoryManagement::mAllocCount = 0;

using TestCounterScopedBuffer = chip::Platform::ScopedMemoryBuffer<char, TestCounterMemoryManagement>;

void TestAutoFree(nlTestSuite * inSuite, void * inContext)
{
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);

    {
        TestCounterScopedBuffer buffer;

        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
        NL_TEST_ASSERT(inSuite, buffer.Alloc(128));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
    }
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
}

void TestFreeDuringAllocs(nlTestSuite * inSuite, void * inContext)
{
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);

    {
        TestCounterScopedBuffer buffer;

        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
        NL_TEST_ASSERT(inSuite, buffer.Alloc(128));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
        NL_TEST_ASSERT(inSuite, buffer.Alloc(64));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
        NL_TEST_ASSERT(inSuite, buffer.LongTermAlloc(256));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
        NL_TEST_ASSERT(inSuite, buffer.Calloc(10));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
    }
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
}

void TestRelease(nlTestSuite * inSuite, void * inContext)
{
    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
    void * ptr = nullptr;

    {
        TestCounterScopedBuffer buffer;

        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
        NL_TEST_ASSERT(inSuite, buffer.Alloc(128));
        NL_TEST_ASSERT(inSuite, buffer.Ptr() != nullptr);

        ptr = buffer.Release();
        NL_TEST_ASSERT(inSuite, ptr != nullptr);
        NL_TEST_ASSERT(inSuite, buffer.Ptr() == nullptr);
    }

    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);

    {
        TestCounterScopedBuffer buffer;
        NL_TEST_ASSERT(inSuite, buffer.Alloc(128));
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 2);
        TestCounterMemoryManagement::MemoryFree(ptr);
        NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 1);
    }

    NL_TEST_ASSERT(inSuite, TestCounterMemoryManagement::Counter() == 0);
}

int Setup(void * inContext)
{
    CHIP_ERROR error = chip::Platform::MemoryInit();
    if (error != CHIP_NO_ERROR)
        return FAILURE;
    return SUCCESS;
}

int Teardown(void * inContext)
{
    chip::Platform::MemoryShutdown();
    return SUCCESS;
}

} // namespace

#define NL_TEST_DEF_FN(fn) NL_TEST_DEF("Test " #fn, fn)
/**
 *   Test Suite. It lists all the test functions.
 */
static const nlTest sTests[] = {
    NL_TEST_DEF_FN(TestAutoFree),         //
    NL_TEST_DEF_FN(TestFreeDuringAllocs), //
    NL_TEST_DEF_FN(TestRelease),          //
    NL_TEST_SENTINEL()                    //
};

int TestScopedBuffer(void)
{
    nlTestSuite theSuite = { "CHIP ScopedBuffer tests", &sTests[0], Setup, Teardown };

    // Run test suit againt one context.
    nlTestRunner(&theSuite, nullptr);
    return nlTestRunnerStats(&theSuite);
}

CHIP_REGISTER_TEST_SUITE(TestBufBound)
<|endoftext|>


<commit_before>#include "macwebcam_info.h"

#include <assert.h>
#include <iostream>
#include <QProcess>
#include <QCoreApplication>

typedef struct{
  int x, y;
} resolution_t;

QList<resolution_t> resolutions;

resolution_t makeRes(int x, int y)
{
  resolution_t res;
  res.x = x;
  res.y = y;
  return res;
}

MacWebcamInfo::MacWebcamInfo(const QString &id)
{
  webcam_id = id;
  resolutions.clear();
  res_list.clear();
  resolutions.push_back(makeRes(160, 120));
  resolutions.push_back(makeRes(320, 240));
  resolutions.push_back(makeRes(352, 288));
  resolutions.push_back(makeRes(640, 480));

  QList<resolution_t>::iterator i;
  QString str;
  for(i = resolutions.begin(); i != resolutions.end(); ++i){
    str = QString("%1 x %2").arg(i->x).arg(i->y);
    res_list.push_back(str);
  }
}

const QStringList& MacWebcamInfo::getResolutions()
{
  return res_list;
}

bool MacWebcamInfo::decodeRes(const QString &res, int &res_x, int &res_y)
{
  const QRegExp &res_rexp = QRegExp("^\\s*(\\d+)\\s*[xX]\\s*(\\d+)\\s*$");
  if(res_rexp.indexIn(res) == -1){
    return false;
  }
  res_x = res_rexp.cap(1).toInt();
  res_y = res_rexp.cap(2).toInt();
  return true;
}

int MacWebcamInfo::findRes(const int &res_x, const int &res_y)
{
  QList<resolution_t>::const_iterator i;
  int counter = 0;
  for(i = resolutions.begin(); i != resolutions.end(); ++i, ++counter){
    if((i->x == res_x) && (i->y == res_y)){
      return counter;
    }
  }
  return 0;
}

MacWebcamInfo::~MacWebcamInfo()
{
}

QStringList& MacWebcamInfo::EnumerateWebcams()
{
  QStringList *res = new QStringList();
  QProcess *enum_proc = new QProcess();
  enum_proc->start(QCoreApplication::applicationDirPath() + "/../helper/qt_cam -e");
  enum_proc->waitForStarted(10000);
  enum_proc->waitForFinished(10000);
  QString str(enum_proc->readAllStandardOutput());
  *res = str.split("\n", QString::SkipEmptyParts);
  return *res;
}
<commit_msg>Fixed problem causing no webcam being found when ltr_gui was   in path containing spaces.<commit_after>#include "macwebcam_info.h"

#include <assert.h>
#include <iostream>
#include <QProcess>
#include <QCoreApplication>

typedef struct{
  int x, y;
} resolution_t;

QList<resolution_t> resolutions;

resolution_t makeRes(int x, int y)
{
  resolution_t res;
  res.x = x;
  res.y = y;
  return res;
}

MacWebcamInfo::MacWebcamInfo(const QString &id)
{
  webcam_id = id;
  resolutions.clear();
  res_list.clear();
  resolutions.push_back(makeRes(160, 120));
  resolutions.push_back(makeRes(320, 240));
  resolutions.push_back(makeRes(352, 288));
  resolutions.push_back(makeRes(640, 480));

  QList<resolution_t>::iterator i;
  QString str;
  for(i = resolutions.begin(); i != resolutions.end(); ++i){
    str = QString("%1 x %2").arg(i->x).arg(i->y);
    res_list.push_back(str);
  }
}

const QStringList& MacWebcamInfo::getResolutions()
{
  return res_list;
}

bool MacWebcamInfo::decodeRes(const QString &res, int &res_x, int &res_y)
{
  const QRegExp &res_rexp = QRegExp("^\\s*(\\d+)\\s*[xX]\\s*(\\d+)\\s*$");
  if(res_rexp.indexIn(res) == -1){
    return false;
  }
  res_x = res_rexp.cap(1).toInt();
  res_y = res_rexp.cap(2).toInt();
  return true;
}

int MacWebcamInfo::findRes(const int &res_x, const int &res_y)
{
  QList<resolution_t>::const_iterator i;
  int counter = 0;
  for(i = resolutions.begin(); i != resolutions.end(); ++i, ++counter){
    if((i->x == res_x) && (i->y == res_y)){
      return counter;
    }
  }
  return 0;
}

MacWebcamInfo::~MacWebcamInfo()
{
}

QStringList& MacWebcamInfo::EnumerateWebcams()
{
  QStringList *res = new QStringList();
  QProcess *enum_proc = new QProcess();
  enum_proc->start(QCoreApplication::applicationDirPath() + "/../helper/qt_cam", QStringList() << "-e");
  enum_proc->waitForStarted(10000);
  enum_proc->waitForFinished(10000);
  QString str(enum_proc->readAllStandardOutput());
  *res = str.split("\n", QString::SkipEmptyParts);
  return *res;
}
<|endoftext|>