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

#include <algorithm>
#include <cassert>
#include <cstring>
#include <ostream>
#include <string>
#include <unordered_map>

#include <gsl/gsl>

#include "xchainer/array_body.h"
#include "xchainer/array_node.h"
#include "xchainer/array_repr.h"
#include "xchainer/backend.h"
#include "xchainer/device.h"
#include "xchainer/error.h"
#include "xchainer/op_node.h"
#include "xchainer/scalar.h"

namespace xchainer {
namespace internal {

void SetUpOpNodes(const std::string& name, const std::vector<ConstArrayRef>& inputs, Array& out,
                  const std::vector<std::function<Array(const Array&, const std::vector<GraphId>&)>>& backward_functions,
                  const std::vector<GraphId>& graph_ids_to_stop_gradients) {
    if (inputs.size() != backward_functions.size()) {
        throw XchainerError("Cannot construct a graph where numbers of input Arrays and backward functions do not match.");
    }

    std::unordered_map<GraphId, std::shared_ptr<OpNode>> graph_edges;

    // Helper function to create an edge in the graph
    auto create_edge = [&name, &graph_edges](const std::shared_ptr<ArrayNode>& next_node, auto& backward_function) {
        std::shared_ptr<OpNode>& op_node = graph_edges[next_node->graph_id()];  // Create if not exists
        if (!op_node) {
            op_node = std::make_shared<OpNode>(name);
        }
        op_node->set_rank(std::max(op_node->rank(), next_node->rank()));
        op_node->RegisterNextNode(next_node, backward_function);
    };

    for (size_t i = 0; i < inputs.size(); ++i) {                                  // For each input
        for (const std::shared_ptr<ArrayNode>& node : inputs[i].get().nodes()) {  // For each graph, create an edge
            if (find(graph_ids_to_stop_gradients.begin(), graph_ids_to_stop_gradients.end(), node->graph_id()) ==
                graph_ids_to_stop_gradients.end()) {
                create_edge(node, backward_functions[i]);
            }
        }
    }

    if (!graph_edges.empty() && std::any_of(inputs.begin(), inputs.end(), [&out](const Array& input) { return &out == &input; })) {
        throw XchainerError("In-place operation (" + name + ") is not supported for an array that require gradients.");
    }

    // Bind edges to output
    for (const auto& edge : graph_edges) {
        const GraphId& graph_id = edge.first;
        const std::shared_ptr<OpNode>& op_node = edge.second;

        const std::shared_ptr<ArrayNode>& out_node = CreateArrayNode(out, graph_id);
        out_node->set_next_node(op_node);
        out_node->set_rank(op_node->rank() + 1);
    }
}

bool HasArrayNode(const Array& array, const GraphId& graph_id) {
    return std::find_if(array.nodes().begin(), array.nodes().end(),
                        [&graph_id](const auto& node) { return graph_id == node->graph_id(); }) != array.nodes().end();
}

const std::shared_ptr<ArrayNode>& CreateArrayNode(Array& array, const GraphId& graph_id) {
    if (HasArrayNode(array, graph_id)) {
        throw XchainerError("Duplicate graph registration: '" + graph_id + "'.");
    }
    array.nodes().emplace_back(std::make_shared<ArrayNode>(graph_id));
    return array.nodes().back();
}

std::shared_ptr<const ArrayNode> GetArrayNode(const Array& array, const GraphId& graph_id) { return GetMutableArrayNode(array, graph_id); }

const std::shared_ptr<ArrayNode>& GetMutableArrayNode(const Array& array, const GraphId& graph_id) {
    auto it =
        std::find_if(array.nodes().begin(), array.nodes().end(), [&graph_id](const auto& node) { return graph_id == node->graph_id(); });
    if (it == array.nodes().end()) {
        throw XchainerError("Array does not belong to the graph: '" + graph_id + "'.");
    }
    return *it;
}

}  // namespace internal

Array Array::FromBuffer(const Shape& shape, Dtype dtype, std::shared_ptr<void> data, Device& device) {
    auto bytesize = static_cast<size_t>(shape.GetTotalSize() * GetElementSize(dtype));
    std::shared_ptr<void> device_data = device.FromBuffer(data, bytesize);
    return {shape, Strides{shape, dtype}, dtype, device, device_data};
}

Array Array::Empty(const Shape& shape, Dtype dtype, Device& device) {
    auto bytesize = static_cast<size_t>(shape.GetTotalSize() * GetElementSize(dtype));
    std::shared_ptr<void> data = device.Allocate(bytesize);
    return {shape, Strides{shape, dtype}, dtype, device, data};
}

Array Array::Full(const Shape& shape, Scalar scalar, Dtype dtype, Device& device) {
    Array array = Empty(shape, dtype, device);
    array.Fill(scalar);
    return array;
}

Array Array::Full(const Shape& shape, Scalar scalar, Device& device) { return Full(shape, scalar, scalar.dtype(), device); }

Array Array::Zeros(const Shape& shape, Dtype dtype, Device& device) { return Full(shape, 0, dtype, device); }

Array Array::Ones(const Shape& shape, Dtype dtype, Device& device) { return Full(shape, 1, dtype, device); }

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

Array Array::FullLike(const Array& array, Scalar scalar, Device& device) { return Full(array.shape(), scalar, array.dtype(), device); }

Array Array::ZerosLike(const Array& array, Device& device) { return Zeros(array.shape(), array.dtype(), device); }

Array Array::OnesLike(const Array& array, Device& device) { return Ones(array.shape(), array.dtype(), device); }

Array::Array(const Shape& shape, const Strides& strides, Dtype dtype, Device& device, std::shared_ptr<void> data, int64_t offset)
    : body_(std::make_shared<internal::ArrayBody>(shape, strides, dtype, device, std::move(data), offset)) {}

Array::Array(const Array& other)
    : body_(std::make_shared<internal::ArrayBody>(other.shape(), other.strides(), other.dtype(), other.device(), other.body_->data_,
                                                  other.offset(), other.body_->nodes_)) {}

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

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

Array Array::operator+(const Array& rhs) const {
    Array out = Array::EmptyLike(*this, device());
    Add(rhs, out);
    return out;
}

Array Array::operator*(const Array& rhs) const {
    Array out = Array::EmptyLike(*this, device());
    Mul(rhs, out);
    return out;
}

Array Array::Transpose() const {
    Shape out_shape{shape().span().rbegin(), shape().span().rend()};
    Strides out_strides{strides().span().rbegin(), strides().span().rend()};
    return Array{out_shape, out_strides, dtype(), device(), body_->data_, offset()};
}

Array Array::Copy() const {
    // No graph will be disconnected.
    return AsConstant({}, CopyKind::kCopy);
}

Array Array::ToDevice(Device& dst_device) const {
    Device& src_device = body_->device_;

    // TODO(niboshi): Offset is assumed to be 0. It should be taken into account.
    std::shared_ptr<void> data;
    int64_t offset = 0;
    size_t bytesize = GetTotalBytes();

    if (&src_device == &dst_device) {
        // Devices are identical. Return an alias.
        data = body_->data_;
        offset = body_->offset_;
    } else if (src_device.backend().SupportsTransfer(src_device, dst_device)) {
        // Use src backend for transfer
        std::tuple<std::shared_ptr<void>, size_t> data_tuple = src_device.TransferDataTo(dst_device, body_->data_, 0, bytesize);
        data = std::move(std::get<0>(data_tuple));
        offset = static_cast<int64_t>(std::get<1>(data_tuple));
    } else if (dst_device.backend().SupportsTransfer(src_device, dst_device)) {
        // Use dst backend for transfer
        std::tuple<std::shared_ptr<void>, size_t> data_tuple = dst_device.TransferDataFrom(src_device, body_->data_, 0, bytesize);
        data = std::move(std::get<0>(data_tuple));
        offset = static_cast<int64_t>(std::get<1>(data_tuple));
    } else {
        // Neither backends support transfer
        throw XchainerError("Transfer between devices is not supported: src='" + src_device.name() + "' dst='" + dst_device.name() + "'.");
    }

    // Create contiguous output array.
    Array out{body_->shape_, Strides{body_->shape_, body_->dtype_}, body_->dtype_, dst_device, std::move(data), offset};

    // Connect the graph.
    // Backward operation is implemented as backward-transfer.
    internal::SetUpOpNodes("transfer", {*this}, out,
                           {[&src_device](const Array& gout, const std::vector<GraphId>&) -> Array { return gout.ToDevice(src_device); }},
                           {});
    return out;
}

Array Array::AsConstant(CopyKind kind) const {
    switch (kind) {
        case CopyKind::kCopy: {
            Array out = Array::EmptyLike(*this, device());
            // TODO(takagi): When non-C-contiguous orders are supported, we cannot blindly copy all elements but need to take
            // is_contiguous_ and offset_ into account
            device().MemoryCopyFrom(out.data().get(), body_->data_.get(), GetTotalBytes(), device());
            return std::move(out);
        }
        case CopyKind::kView:
            return Array{shape(), strides(), dtype(), device(), body_->data_, offset()};
        default:
            assert(false);  // should never be reached
    }
}

Array Array::AsConstant(const std::vector<GraphId>& graph_ids, CopyKind kind) const {
    switch (kind) {
        case CopyKind::kCopy: {
            Array out = Array::EmptyLike(*this, device());
            internal::SetUpOpNodes("copy", {*this}, out, {[](const Array& gout, const std::vector<GraphId>&) { return gout; }}, graph_ids);
            // TODO(takagi): When non-C-contiguous orders are supported, we cannot blindly copy all elements but need to take
            // is_contiguous_ and offset_ into account
            device().MemoryCopyFrom(out.data().get(), body_->data_.get(), GetTotalBytes(), device());
            return std::move(out);
        }
        case CopyKind::kView: {
            Array out{shape(), strides(), dtype(), device(), body_->data_, offset()};

            // Duplicate the array nodes only when graph IDs are not found in specified graph_ids.
            for (const std::shared_ptr<ArrayNode>& node : nodes()) {
                if (std::find(graph_ids.begin(), graph_ids.end(), node->graph_id()) == graph_ids.end()) {
                    // extend the graph
                    out.body_->nodes_.emplace_back(node);
                }
            }
            return std::move(out);
        }
        default:
            assert(false);  // should never be reached
    }
}

void Array::Fill(Scalar value) { device().Fill(*this, value); }

const nonstd::optional<Array>& Array::GetGrad(const GraphId& graph_id) const { return internal::GetArrayNode(*this, graph_id)->grad(); }

void Array::SetGrad(Array grad, const GraphId& graph_id) { internal::GetMutableArrayNode(*this, graph_id)->set_grad(std::move(grad)); }

void Array::ClearGrad(const GraphId& graph_id) { internal::GetMutableArrayNode(*this, graph_id)->ClearGrad(); }

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

void Array::Add(const Array& rhs, Array& out) const {
    // TODO(sonots): dtype conversion
    CheckEqual(dtype(), rhs.dtype());
    // TODO(sonots): broadcasting
    CheckEqual(shape(), rhs.shape());

    auto lhs_backward_function = [](const Array& gout, const std::vector<GraphId>&) -> Array { return gout; };
    auto rhs_backward_function = lhs_backward_function;
    internal::SetUpOpNodes("add", {*this, rhs}, out, {lhs_backward_function, rhs_backward_function});

    device().Add(*this, rhs, out);
}

void Array::Mul(const Array& rhs, Array& out) const {
    // TODO(sonots): dtype conversion
    CheckEqual(dtype(), rhs.dtype());
    // TODO(sonots): broadcasting
    CheckEqual(shape(), rhs.shape());

    auto lhs_backward_function = [other = rhs](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) {
        return gout * other.AsConstant(graph_ids_to_stop_gradient);
    };
    auto rhs_backward_function = [other = *this](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) {
        return gout * other.AsConstant(graph_ids_to_stop_gradient);
    };
    internal::SetUpOpNodes("mul", {*this, rhs}, out, {lhs_backward_function, rhs_backward_function});

    device().Mul(*this, rhs, out);
}

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() << "," << op.get() << ">" << 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

Array Transpose(const Array& a) {
    return a.Transpose();
}

void DebugDumpComputationalGraph(std::ostream& os, const Array& array, const GraphId& graph_id, int indent) {
    DebugDumpComputationalGraph(os, *internal::GetArrayNode(array, graph_id), indent);
}

}  // namespace xchainer
<commit_msg>clang-format<commit_after>#include "xchainer/array.h"

#include <algorithm>
#include <cassert>
#include <cstring>
#include <ostream>
#include <string>
#include <unordered_map>

#include <gsl/gsl>

#include "xchainer/array_body.h"
#include "xchainer/array_node.h"
#include "xchainer/array_repr.h"
#include "xchainer/backend.h"
#include "xchainer/device.h"
#include "xchainer/error.h"
#include "xchainer/op_node.h"
#include "xchainer/scalar.h"

namespace xchainer {
namespace internal {

void SetUpOpNodes(const std::string& name, const std::vector<ConstArrayRef>& inputs, Array& out,
                  const std::vector<std::function<Array(const Array&, const std::vector<GraphId>&)>>& backward_functions,
                  const std::vector<GraphId>& graph_ids_to_stop_gradients) {
    if (inputs.size() != backward_functions.size()) {
        throw XchainerError("Cannot construct a graph where numbers of input Arrays and backward functions do not match.");
    }

    std::unordered_map<GraphId, std::shared_ptr<OpNode>> graph_edges;

    // Helper function to create an edge in the graph
    auto create_edge = [&name, &graph_edges](const std::shared_ptr<ArrayNode>& next_node, auto& backward_function) {
        std::shared_ptr<OpNode>& op_node = graph_edges[next_node->graph_id()];  // Create if not exists
        if (!op_node) {
            op_node = std::make_shared<OpNode>(name);
        }
        op_node->set_rank(std::max(op_node->rank(), next_node->rank()));
        op_node->RegisterNextNode(next_node, backward_function);
    };

    for (size_t i = 0; i < inputs.size(); ++i) {                                  // For each input
        for (const std::shared_ptr<ArrayNode>& node : inputs[i].get().nodes()) {  // For each graph, create an edge
            if (find(graph_ids_to_stop_gradients.begin(), graph_ids_to_stop_gradients.end(), node->graph_id()) ==
                graph_ids_to_stop_gradients.end()) {
                create_edge(node, backward_functions[i]);
            }
        }
    }

    if (!graph_edges.empty() && std::any_of(inputs.begin(), inputs.end(), [&out](const Array& input) { return &out == &input; })) {
        throw XchainerError("In-place operation (" + name + ") is not supported for an array that require gradients.");
    }

    // Bind edges to output
    for (const auto& edge : graph_edges) {
        const GraphId& graph_id = edge.first;
        const std::shared_ptr<OpNode>& op_node = edge.second;

        const std::shared_ptr<ArrayNode>& out_node = CreateArrayNode(out, graph_id);
        out_node->set_next_node(op_node);
        out_node->set_rank(op_node->rank() + 1);
    }
}

bool HasArrayNode(const Array& array, const GraphId& graph_id) {
    return std::find_if(array.nodes().begin(), array.nodes().end(),
                        [&graph_id](const auto& node) { return graph_id == node->graph_id(); }) != array.nodes().end();
}

const std::shared_ptr<ArrayNode>& CreateArrayNode(Array& array, const GraphId& graph_id) {
    if (HasArrayNode(array, graph_id)) {
        throw XchainerError("Duplicate graph registration: '" + graph_id + "'.");
    }
    array.nodes().emplace_back(std::make_shared<ArrayNode>(graph_id));
    return array.nodes().back();
}

std::shared_ptr<const ArrayNode> GetArrayNode(const Array& array, const GraphId& graph_id) { return GetMutableArrayNode(array, graph_id); }

const std::shared_ptr<ArrayNode>& GetMutableArrayNode(const Array& array, const GraphId& graph_id) {
    auto it =
        std::find_if(array.nodes().begin(), array.nodes().end(), [&graph_id](const auto& node) { return graph_id == node->graph_id(); });
    if (it == array.nodes().end()) {
        throw XchainerError("Array does not belong to the graph: '" + graph_id + "'.");
    }
    return *it;
}

}  // namespace internal

Array Array::FromBuffer(const Shape& shape, Dtype dtype, std::shared_ptr<void> data, Device& device) {
    auto bytesize = static_cast<size_t>(shape.GetTotalSize() * GetElementSize(dtype));
    std::shared_ptr<void> device_data = device.FromBuffer(data, bytesize);
    return {shape, Strides{shape, dtype}, dtype, device, device_data};
}

Array Array::Empty(const Shape& shape, Dtype dtype, Device& device) {
    auto bytesize = static_cast<size_t>(shape.GetTotalSize() * GetElementSize(dtype));
    std::shared_ptr<void> data = device.Allocate(bytesize);
    return {shape, Strides{shape, dtype}, dtype, device, data};
}

Array Array::Full(const Shape& shape, Scalar scalar, Dtype dtype, Device& device) {
    Array array = Empty(shape, dtype, device);
    array.Fill(scalar);
    return array;
}

Array Array::Full(const Shape& shape, Scalar scalar, Device& device) { return Full(shape, scalar, scalar.dtype(), device); }

Array Array::Zeros(const Shape& shape, Dtype dtype, Device& device) { return Full(shape, 0, dtype, device); }

Array Array::Ones(const Shape& shape, Dtype dtype, Device& device) { return Full(shape, 1, dtype, device); }

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

Array Array::FullLike(const Array& array, Scalar scalar, Device& device) { return Full(array.shape(), scalar, array.dtype(), device); }

Array Array::ZerosLike(const Array& array, Device& device) { return Zeros(array.shape(), array.dtype(), device); }

Array Array::OnesLike(const Array& array, Device& device) { return Ones(array.shape(), array.dtype(), device); }

Array::Array(const Shape& shape, const Strides& strides, Dtype dtype, Device& device, std::shared_ptr<void> data, int64_t offset)
    : body_(std::make_shared<internal::ArrayBody>(shape, strides, dtype, device, std::move(data), offset)) {}

Array::Array(const Array& other)
    : body_(std::make_shared<internal::ArrayBody>(other.shape(), other.strides(), other.dtype(), other.device(), other.body_->data_,
                                                  other.offset(), other.body_->nodes_)) {}

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

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

Array Array::operator+(const Array& rhs) const {
    Array out = Array::EmptyLike(*this, device());
    Add(rhs, out);
    return out;
}

Array Array::operator*(const Array& rhs) const {
    Array out = Array::EmptyLike(*this, device());
    Mul(rhs, out);
    return out;
}

Array Array::Transpose() const {
    Shape out_shape{shape().span().rbegin(), shape().span().rend()};
    Strides out_strides{strides().span().rbegin(), strides().span().rend()};
    return Array{out_shape, out_strides, dtype(), device(), body_->data_, offset()};
}

Array Array::Copy() const {
    // No graph will be disconnected.
    return AsConstant({}, CopyKind::kCopy);
}

Array Array::ToDevice(Device& dst_device) const {
    Device& src_device = body_->device_;

    // TODO(niboshi): Offset is assumed to be 0. It should be taken into account.
    std::shared_ptr<void> data;
    int64_t offset = 0;
    size_t bytesize = GetTotalBytes();

    if (&src_device == &dst_device) {
        // Devices are identical. Return an alias.
        data = body_->data_;
        offset = body_->offset_;
    } else if (src_device.backend().SupportsTransfer(src_device, dst_device)) {
        // Use src backend for transfer
        std::tuple<std::shared_ptr<void>, size_t> data_tuple = src_device.TransferDataTo(dst_device, body_->data_, 0, bytesize);
        data = std::move(std::get<0>(data_tuple));
        offset = static_cast<int64_t>(std::get<1>(data_tuple));
    } else if (dst_device.backend().SupportsTransfer(src_device, dst_device)) {
        // Use dst backend for transfer
        std::tuple<std::shared_ptr<void>, size_t> data_tuple = dst_device.TransferDataFrom(src_device, body_->data_, 0, bytesize);
        data = std::move(std::get<0>(data_tuple));
        offset = static_cast<int64_t>(std::get<1>(data_tuple));
    } else {
        // Neither backends support transfer
        throw XchainerError("Transfer between devices is not supported: src='" + src_device.name() + "' dst='" + dst_device.name() + "'.");
    }

    // Create contiguous output array.
    Array out{body_->shape_, Strides{body_->shape_, body_->dtype_}, body_->dtype_, dst_device, std::move(data), offset};

    // Connect the graph.
    // Backward operation is implemented as backward-transfer.
    internal::SetUpOpNodes("transfer", {*this}, out,
                           {[&src_device](const Array& gout, const std::vector<GraphId>&) -> Array { return gout.ToDevice(src_device); }},
                           {});
    return out;
}

Array Array::AsConstant(CopyKind kind) const {
    switch (kind) {
        case CopyKind::kCopy: {
            Array out = Array::EmptyLike(*this, device());
            // TODO(takagi): When non-C-contiguous orders are supported, we cannot blindly copy all elements but need to take
            // is_contiguous_ and offset_ into account
            device().MemoryCopyFrom(out.data().get(), body_->data_.get(), GetTotalBytes(), device());
            return std::move(out);
        }
        case CopyKind::kView:
            return Array{shape(), strides(), dtype(), device(), body_->data_, offset()};
        default:
            assert(false);  // should never be reached
    }
}

Array Array::AsConstant(const std::vector<GraphId>& graph_ids, CopyKind kind) const {
    switch (kind) {
        case CopyKind::kCopy: {
            Array out = Array::EmptyLike(*this, device());
            internal::SetUpOpNodes("copy", {*this}, out, {[](const Array& gout, const std::vector<GraphId>&) { return gout; }}, graph_ids);
            // TODO(takagi): When non-C-contiguous orders are supported, we cannot blindly copy all elements but need to take
            // is_contiguous_ and offset_ into account
            device().MemoryCopyFrom(out.data().get(), body_->data_.get(), GetTotalBytes(), device());
            return std::move(out);
        }
        case CopyKind::kView: {
            Array out{shape(), strides(), dtype(), device(), body_->data_, offset()};

            // Duplicate the array nodes only when graph IDs are not found in specified graph_ids.
            for (const std::shared_ptr<ArrayNode>& node : nodes()) {
                if (std::find(graph_ids.begin(), graph_ids.end(), node->graph_id()) == graph_ids.end()) {
                    // extend the graph
                    out.body_->nodes_.emplace_back(node);
                }
            }
            return std::move(out);
        }
        default:
            assert(false);  // should never be reached
    }
}

void Array::Fill(Scalar value) { device().Fill(*this, value); }

const nonstd::optional<Array>& Array::GetGrad(const GraphId& graph_id) const { return internal::GetArrayNode(*this, graph_id)->grad(); }

void Array::SetGrad(Array grad, const GraphId& graph_id) { internal::GetMutableArrayNode(*this, graph_id)->set_grad(std::move(grad)); }

void Array::ClearGrad(const GraphId& graph_id) { internal::GetMutableArrayNode(*this, graph_id)->ClearGrad(); }

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

void Array::Add(const Array& rhs, Array& out) const {
    // TODO(sonots): dtype conversion
    CheckEqual(dtype(), rhs.dtype());
    // TODO(sonots): broadcasting
    CheckEqual(shape(), rhs.shape());

    auto lhs_backward_function = [](const Array& gout, const std::vector<GraphId>&) -> Array { return gout; };
    auto rhs_backward_function = lhs_backward_function;
    internal::SetUpOpNodes("add", {*this, rhs}, out, {lhs_backward_function, rhs_backward_function});

    device().Add(*this, rhs, out);
}

void Array::Mul(const Array& rhs, Array& out) const {
    // TODO(sonots): dtype conversion
    CheckEqual(dtype(), rhs.dtype());
    // TODO(sonots): broadcasting
    CheckEqual(shape(), rhs.shape());

    auto lhs_backward_function = [other = rhs](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) {
        return gout * other.AsConstant(graph_ids_to_stop_gradient);
    };
    auto rhs_backward_function = [other = *this](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) {
        return gout * other.AsConstant(graph_ids_to_stop_gradient);
    };
    internal::SetUpOpNodes("mul", {*this, rhs}, out, {lhs_backward_function, rhs_backward_function});

    device().Mul(*this, rhs, out);
}

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() << "," << op.get() << ">" << 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

Array Transpose(const Array& a) { return a.Transpose(); }

void DebugDumpComputationalGraph(std::ostream& os, const Array& array, const GraphId& graph_id, int indent) {
    DebugDumpComputationalGraph(os, *internal::GetArrayNode(array, graph_id), indent);
}

}  // namespace xchainer
<|endoftext|>


<commit_before>#include <algorithm>
#include <cpr/cpr.h>
#include <tw/oauth.h>
#include <utils.h>
#include "command.h"
#include "../CmdHandler.h"
#include "../option.h"

#define MAX_URL 128

/* full name of the command */
CMDNAME("status");
/* description of the command */
CMDDESCR("set channel status");
/* command usage synopsis */
CMDUSAGE("status [-a] [STATUS]");

static const char *TWITCH_API = "https://api.twitch.tv/kraken/channels/";

static int curr_status(char *buf, const char *channel, const cpr::Header *head);
static int set_status(char *out, const char *channel, const char *status,
		const cpr::Header *head);

/* status: set channel status */
int CmdHandler::status(char *out, struct command *c)
{
	const cpr::Header head{{ "Accept", "application/vnd.twitchtv.v3+json" },
		{ "Authorization", "OAuth " + std::string(m_token) }};

	char buf[MAX_MSG];
	int append, status;

	int opt;
	static struct l_option long_opts[] = {
		{ "append", NO_ARG, 'a' },
		{ "help", NO_ARG, 'h' },
		{ 0, 0, 0 }
	};

	if (!P_ALMOD(c->privileges)) {
		PERM_DENIED(out, c->nick, c->argv[0]);
		return EXIT_FAILURE;
	}

	opt_init();
	append = 0;
	buf[0] = '\0';
	status = EXIT_SUCCESS;
	while ((opt = l_getopt_long(c->argc, c->argv, "a", long_opts)) != EOF) {
		switch (opt) {
		case 'a':
			append = 1;
			break;
		case 'h':
			HELPMSG(out, CMDNAME, CMDUSAGE, CMDDESCR);
			return EXIT_SUCCESS;
		case '?':
			_sprintf(out, MAX_MSG, "%s", l_opterr());
			return EXIT_FAILURE;
		default:
			return EXIT_FAILURE;
		}
	}

	/* get the current status if no arg provided or if appending */
	if (l_optind == c->argc || append) {
		if (!curr_status(buf, m_channel, &head)) {
			_sprintf(out, MAX_MSG, "%s: %s", c->argv[0], buf);
			return EXIT_FAILURE;
		}
	}

	if (l_optind == c->argc) {
		if (append) {
			_sprintf(out, MAX_MSG, "%s: no text to append",
					c->argv[0]);
			status = EXIT_FAILURE;
		} else {
			_sprintf(out, MAX_MSG, "[STATUS] Current status for %s "
					"is \"%s\".", m_channel, buf);
		}
		return status;
	}

	if (append)
		strcat(buf, " ");
	argvcat(buf + strlen(buf), c->argc, c->argv, l_optind, 1);

	return set_status(out, m_channel, buf, &head);
}

/* curr_status: get current status of channel */
static int curr_status(char *buf, const char *channel, const cpr::Header *head)
{
	cpr::Response resp;
	Json::Reader reader;
	Json::Value response;
	char url[MAX_URL];
	char *s;

	_sprintf(url, MAX_URL, "%s%s", TWITCH_API, channel);
	resp = cpr::Get(cpr::Url(url), *head);

	if (reader.parse(resp.text, response)) {
		if (response.isMember("error")) {
			_sprintf(buf, MAX_MSG, "%s",
					response["error"].asCString());
			for (s = buf; *s; ++s)
				*s = tolower(*s);
			return 0;
		}
		_sprintf(buf, MAX_MSG, "%s", response["status"].asCString());
		return 1;
	}
	_sprintf(buf, MAX_MSG, "could not parse channel data");
	return 0;
}

/* curr_status: set new status of channel */
static int set_status(char *out, const char *channel, const char *status,
		const cpr::Header *head)
{
	cpr::Response resp;
	Json::Reader reader;
	Json::Value response;
	char body[MAX_MSG];
	char url[MAX_URL];
	char *s;

	_sprintf(body, MAX_MSG, "channel[status]=%s",
			tw::pencode(status, " ").c_str());
	for (s = body; *s; ++s) {
		if (*s == ' ')
			*s = '+';
	}

	_sprintf(url, MAX_URL, "%s%s", TWITCH_API, channel);
	resp = cpr::Put(cpr::Url(url), cpr::Body(body), *head);

	if (reader.parse(resp.text, response)) {
		if (response.isMember("error")) {
			_sprintf(out, MAX_MSG, "%s: %s", CMDNAME,
					response["error"].asCString());
			for (s = out; *s; ++s)
				*s = tolower(*s);
			return EXIT_FAILURE;
		}
		_sprintf(out, MAX_MSG, "[STATUS] Channel status changed to "
				"\"%s\".", response["status"].asCString());
		return EXIT_SUCCESS;
	}
	_sprintf(out, MAX_MSG, "could not parse channel data");
	return EXIT_FAILURE;
}
<commit_msg>status: add sed functionality<commit_after>#include <algorithm>
#include <cpr/cpr.h>
#include <tw/oauth.h>
#include <utils.h>
#include "command.h"
#include "../CmdHandler.h"
#include "../option.h"
#include "../sed.h"

#define MAX_URL 128

/* full name of the command */
CMDNAME("status");
/* description of the command */
CMDDESCR("set channel status");
/* command usage synopsis */
CMDUSAGE("status [-a] [-s SEDCMD] [STATUS]");

static const char *TWITCH_API = "https://api.twitch.tv/kraken/channels/";

static int curr_status(char *buf, const char *channel, const cpr::Header *head);
static int set_status(char *out, const char *channel, const char *status,
		const cpr::Header *head);

/* status: set channel status */
int CmdHandler::status(char *out, struct command *c)
{
	const cpr::Header head{{ "Accept", "application/vnd.twitchtv.v3+json" },
		{ "Authorization", "OAuth " + std::string(m_token) }};

	char buf[MAX_MSG];
	char sedcmd[MAX_MSG];
	int append, sedflag;

	int opt;
	static struct l_option long_opts[] = {
		{ "append", NO_ARG, 'a' },
		{ "help", NO_ARG, 'h' },
		{ "sed", REQ_ARG, 's' },
		{ 0, 0, 0 }
	};

	if (!P_ALMOD(c->privileges)) {
		PERM_DENIED(out, c->nick, c->argv[0]);
		return EXIT_FAILURE;
	}

	opt_init();
	append = sedflag = 0;
	buf[0] = '\0';
	while ((opt = l_getopt_long(c->argc, c->argv, "as:", long_opts)) != EOF) {
		switch (opt) {
		case 'a':
			append = 1;
			break;
		case 'h':
			HELPMSG(out, CMDNAME, CMDUSAGE, CMDDESCR);
			return EXIT_SUCCESS;
		case 's':
			sedflag = 1;
			strcpy(sedcmd, l_optarg);
			break;
		case '?':
			_sprintf(out, MAX_MSG, "%s", l_opterr());
			return EXIT_FAILURE;
		default:
			return EXIT_FAILURE;
		}
	}

	if (append && sedflag) {
		_sprintf(out, MAX_MSG, "%s: cannot combine -s and -a",
				c->argv[0]);
		return EXIT_FAILURE;
	}

	/* get the current status if no arg provided, appending or sed */
	if (l_optind == c->argc || append || sedflag) {
		if (!curr_status(buf, m_channel, &head)) {
			_sprintf(out, MAX_MSG, "%s: %s", c->argv[0], buf);
			return EXIT_FAILURE;
		}
	}

	if (l_optind == c->argc) {
		if (append) {
			_sprintf(out, MAX_MSG, "%s: no text to append",
					c->argv[0]);
			return EXIT_FAILURE;
		} else if (sedflag) {
			if (!sed(buf, MAX_MSG, buf, sedcmd)) {
				_sprintf(out, MAX_MSG, "%s: %s",
						c->argv[0], buf);
				return EXIT_FAILURE;
			}
		} else {
			_sprintf(out, MAX_MSG, "[STATUS] Current status for %s "
					"is \"%s\".", m_channel, buf);
			return EXIT_SUCCESS;
		}
	} else if (sedflag) {
		_sprintf(out, MAX_MSG, "%s: cannot provide status with -s",
				c->argv[0]);
		return EXIT_FAILURE;
	}

	if (append)
		strcat(buf, " ");
	argvcat(buf + strlen(buf), c->argc, c->argv, l_optind, 1);

	return set_status(out, m_channel, buf, &head);
}

/* curr_status: get current status of channel */
static int curr_status(char *buf, const char *channel, const cpr::Header *head)
{
	cpr::Response resp;
	Json::Reader reader;
	Json::Value response;
	char url[MAX_URL];
	char *s;

	_sprintf(url, MAX_URL, "%s%s", TWITCH_API, channel);
	resp = cpr::Get(cpr::Url(url), *head);

	if (reader.parse(resp.text, response)) {
		if (response.isMember("error")) {
			_sprintf(buf, MAX_MSG, "%s",
					response["error"].asCString());
			for (s = buf; *s; ++s)
				*s = tolower(*s);
			return 0;
		}
		_sprintf(buf, MAX_MSG, "%s", response["status"].asCString());
		return 1;
	}
	_sprintf(buf, MAX_MSG, "could not parse channel data");
	return 0;
}

/* curr_status: set new status of channel */
static int set_status(char *out, const char *channel, const char *status,
		const cpr::Header *head)
{
	cpr::Response resp;
	Json::Reader reader;
	Json::Value response;
	char body[MAX_MSG];
	char url[MAX_URL];
	char *s;

	_sprintf(body, MAX_MSG, "channel[status]=%s",
			tw::pencode(status, " ").c_str());
	for (s = body; *s; ++s) {
		if (*s == ' ')
			*s = '+';
	}

	_sprintf(url, MAX_URL, "%s%s", TWITCH_API, channel);
	resp = cpr::Put(cpr::Url(url), cpr::Body(body), *head);

	if (reader.parse(resp.text, response)) {
		if (response.isMember("error")) {
			_sprintf(out, MAX_MSG, "%s: %s", CMDNAME,
					response["error"].asCString());
			for (s = out; *s; ++s)
				*s = tolower(*s);
			return EXIT_FAILURE;
		}
		_sprintf(out, MAX_MSG, "[STATUS] Channel status changed to "
				"\"%s\".", response["status"].asCString());
		return EXIT_SUCCESS;
	}
	_sprintf(out, MAX_MSG, "could not parse channel data");
	return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define USAGE "Usage:\r\nc \r\n[tux machine number] \r\n[probability of packet corruption in int form] \r\n[probability of packet loss in int form] \r\n[probability of packet delay] \r\n[length of delay in ms] \r\n"
#define PORT 10038
#define PAKSIZE 128
#define ACK 0
#define NAK 1
#define BUFSIZE 121
#define FILENAME "Testfile"
#define TIMEOUT 100 //in ms

using namespace std;

bool isvpack(unsigned char * p);
bool init(int argc, char** argv);
bool loadFile();
bool getFile();
bool sendFile();
bool isAck();
void handleAck();
void handleNak(int& x);
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb);
Packet createPacket(int index);
bool sendPacket();

bool seqNum = true;
struct sockaddr_in a;
struct sockaddr_in ca;
socklen_t calen;
int rlen;
int s;
bool ack;
string fstr;
char * file;
int probCorrupt;
int probLoss;
int probDelay;
int delayT;
Packet p;
int length;
bool dropPck;
bool delayPck;
unsigned char b[BUFSIZE];

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  calen = sizeof(ca);

  unsigned char packet[PAKSIZE + 1];
  rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);

  sendFile();

  return 0;
}

bool init(int argc, char** argv){

  if(argc != 6) {
    cout << USAGE << endl;
    return false;
  }

  char * probCorruptStr = argv[2];
  probCorrupt = boost::lexical_cast<int>(probCorruptStr);
  char * probLossStr = argv[3];
  probLoss = boost::lexical_cast<int>(probLossStr);
  char * probDelayStr = argv[4];
  probDelay = boost::lexical_cast<int>(probDelayStr);
  char* delayTStr = argv[5];
  delayT = boost::lexical_cast<int>(delayTStr);

  static int timeout = TIMEOUT;

  /* Create our socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return 0;
  }

  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

  /*
   * Bind our socket to an IP (whatever the computer decides)
   * and a specified port.
   *
   */

  if (!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY);
  a.sin_port = htons(PORT);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return 0;
  }

  fstr = string(file);
  cout << "File: " << endl << fstr << endl;

  seqNum = true;
  dropPck = false;

  return true;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[7];
  memcpy(css, &p[1], 6);
  css[6] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[2], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == seqNum) return false;
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){

  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  bool isSeqNumSet = false;
  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);
    if(!isSeqNumSet) {
      isSeqNumSet = true;
      char * str = new char[1];
      memcpy(str, &packet[0], 1);
      seqNum = boost::lexical_cast<int>(str);
    }
    for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      cout << "Sent response: ";
      if(isvpack(packet)) {
        ack = ACK;
        seqNum = (seqNum) ? false : true;
        file << dataPull;
      } else {
        ack = NAK;
      }
      cout << ((ack == ACK) ? "ACK" : "NAK") << endl;
      Packet p ((seqNum) ? false : true, reinterpret_cast<const char *>(dataPull));
      p.setCheckSum(boost::lexical_cast<int>(css));
      p.setAckNack(ack);

      if(sendto(s, p.str(), PAKSIZE, 0, (struct sockaddr *)&ca, calen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

bool sendFile() {

  for(int x = 0; x <= (length / BUFSIZE) + 1; x++) {
    p = createPacket(x);
    if(!sendPacket()) continue;

    while(recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&ca, &calen) < 0) {
		cout << "Timed out. Resending..." << endl;
		sendPacket();
	}

    if(isAck()) {
      handleAck();
    } else {
      handleNak(x);
    }

    memset(b, 0, BUFSIZE);
  }
  return true;
}

Packet createPacket(int index){
    cout << endl;
    cout << "=== TRANSMISSION START" << endl;
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);

	if(mstr.length() < BUFSIZE) {
      mstr[length - (index * BUFSIZE)] = '\0';
    }
    return Packet (seqNum, mstr.c_str());
}

bool sendPacket(){
    int pc = probCorrupt; int pl = probLoss; int pd = probDelay;
	bool* pckStatus = gremlin(&p, pc, pl, pd);

	if ((dropPck = pckStatus[0]) == true) return false;
	if ((delayPck = pckStatus[1]) == true) sleep(delayT);
    if(sendto(s, p.str(), BUFSIZE + 7, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
    }
    return true;
}

bool isAck() {
    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {

}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}

bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb){
  bool dropPacket = false;
  bool delayPacket = false;
  bool* packStatus = new bool[2];
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  if(r <= (lossProb)){
    dropPacket = true;
	packStatus[0] = dropPacket;
    cout << "Dropped!" << endl;
  }
  else if(r <= (delayProb)){
	  delayPacket = true;
	  packStatus[1] = delayPacket;
	  cout << "Delayed!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  else seqNum = (seqNum) ? false : true;
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  cout << "Message: "  << pack->getDataBuffer() << endl;

  return packStatus;
}<commit_msg>Fix the fix's fix<commit_after>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define USAGE "Usage:\r\nc \r\n[tux machine number] \r\n[probability of packet corruption in int form] \r\n[probability of packet loss in int form] \r\n[probability of packet delay] \r\n[length of delay in ms] \r\n"
#define PORT 10038
#define PAKSIZE 128
#define ACK 0
#define NAK 1
#define BUFSIZE 121
#define FILENAME "Testfile"
#define TIMEOUT 100 //in ms

using namespace std;

bool isvpack(unsigned char * p);
bool init(int argc, char** argv);
bool loadFile();
bool getFile();
bool sendFile();
bool isAck();
void handleAck();
void handleNak(int& x);
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb);
Packet createPacket(int index);
bool sendPacket();

bool seqNum = true;
struct sockaddr_in a;
struct sockaddr_in ca;
socklen_t calen;
int rlen;
int s;
bool ack;
string fstr;
char * file;
int probCorrupt;
int probLoss;
int probDelay;
int delayT;
Packet p;
int length;
bool dropPck;
bool delayPck;
unsigned char b[BUFSIZE];

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  calen = sizeof(ca);

  unsigned char packet[PAKSIZE + 1];
  rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);

  sendFile();

  return 0;
}

bool init(int argc, char** argv){

  if(argc != 6) {
    cout << USAGE << endl;
    return false;
  }

  char * probCorruptStr = argv[2];
  probCorrupt = boost::lexical_cast<int>(probCorruptStr);
  char * probLossStr = argv[3];
  probLoss = boost::lexical_cast<int>(probLossStr);
  char * probDelayStr = argv[4];
  probDelay = boost::lexical_cast<int>(probDelayStr);
  char* delayTStr = argv[5];
  delayT = boost::lexical_cast<int>(delayTStr);

  static int timeout = TIMEOUT;

  /* Create our socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return 0;
  }

  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

  /*
   * Bind our socket to an IP (whatever the computer decides)
   * and a specified port.
   *
   */

  if (!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY);
  a.sin_port = htons(PORT);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return 0;
  }

  fstr = string(file);
  cout << "File: " << endl << fstr << endl;

  seqNum = true;
  dropPck = false;

  return true;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[7];
  memcpy(css, &p[1], 6);
  css[6] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[2], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == seqNum) return false;
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){

  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  bool isSeqNumSet = false;
  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);
    if(!isSeqNumSet) {
      isSeqNumSet = true;
      char * str = new char[1];
      memcpy(str, &packet[0], 1);
      seqNum = boost::lexical_cast<int>(str);
    }
    for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      cout << "Sent response: ";
      if(isvpack(packet)) {
        ack = ACK;
        seqNum = (seqNum) ? false : true;
        file << dataPull;
      } else {
        ack = NAK;
      }
      cout << ((ack == ACK) ? "ACK" : "NAK") << endl;
      Packet p ((seqNum) ? false : true, reinterpret_cast<const char *>(dataPull));
      p.setCheckSum(boost::lexical_cast<int>(css));
      p.setAckNack(ack);

      if(sendto(s, p.str(), PAKSIZE, 0, (struct sockaddr *)&ca, calen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

bool sendFile() {

  for(int x = 0; x <= (length / BUFSIZE) + 1; x++) {
    p = createPacket(x);
    if(!sendPacket()) continue;

    while(recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&ca, &calen) < 0) {
		cout << "Timed out. Resending..." << endl;
		sendPacket();
	}

    if(isAck()) {
      handleAck();
    } else {
      handleNak(x);
    }

    memset(b, 0, BUFSIZE);
  }
  return true;
}

Packet createPacket(int index){
    cout << endl;
    cout << "=== TRANSMISSION START" << endl;
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);

	if(mstr.length() < BUFSIZE) {
      mstr[length - (index * BUFSIZE)] = '\0';
    }
    return Packet (seqNum, mstr.c_str());
}

bool sendPacket(){
    int pc = probCorrupt; int pl = probLoss; int pd = probDelay;
	bool* pckStatus = gremlin(&p, pc, pl, pd);

	dropPck = pckStatus[0];
	delayPck = pckStatus[1];

	if (dropPck) return false;
	if (delayPck) sleep(delayT);
    if(sendto(s, p.str(), BUFSIZE + 7, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
    }
    return true;
}

bool isAck() {
    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {

}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}

bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb){
  bool dropPacket = false;
  bool delayPacket = false;
  bool* packStatus = new bool[2];
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  if(r <= (lossProb)){
    dropPacket = true;
	packStatus[0] = dropPacket;
    cout << "Dropped!" << endl;
  }
  else if(r <= (delayProb)){
	  delayPacket = true;
	  packStatus[1] = delayPacket;
	  cout << "Delayed!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  else seqNum = (seqNum) ? false : true;
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  cout << "Message: "  << pack->getDataBuffer() << endl;

  return packStatus;
}<|endoftext|>


<commit_before>/*
** Copyright 2011-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <cstdlib>
#include <memory>
#include <QCoreApplication>
#include <QMutex>
#include <QMutexLocker>
#include "com/centreon/broker/config/applier/endpoint.hh"
#include "com/centreon/broker/config/applier/logger.hh"
#include "com/centreon/broker/config/applier/modules.hh"
#include "com/centreon/broker/config/applier/state.hh"
#include "com/centreon/broker/logging/file.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/multiplexing/engine.hh"
#include "com/centreon/broker/multiplexing/subscriber.hh"

using namespace com::centreon::broker::config::applier;

// Class instance.
static state* gl_state = NULL;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Destructor.
 */
state::~state() {}

/**
 *  Apply a configuration state.
 *
 *  @param[in] s       State to apply.
 *  @param[in] run_mux Set to true if multiplexing must be run.
 */
void state::apply(
              com::centreon::broker::config::state const& s,
              bool run_mux) {
  // Apply logging configuration.
  logger::instance().apply(s.loggers());

  // Flush logs or not.
  com::centreon::broker::logging::file::with_flush(
    s.flush_logs());

  // Enable or not thread ID logging.
  com::centreon::broker::logging::file::with_thread_id(
    s.log_thread_id());

  // Enable or not timestamp logging.
  com::centreon::broker::logging::file::with_timestamp(
    s.log_timestamp());

  // Apply modules configuration.
  modules::instance().apply(
                        s.module_list(),
                        s.module_directory(),
                        &s);
  {
    unsigned int module_count(0);
    for (modules::iterator
           it(modules::instance().begin()),
           end(modules::instance().end());
         it != end;
         ++it)
      ++module_count;
    if (module_count)
      logging::config(logging::high) << "applier: " << module_count
        << " modules loaded";
    else
      logging::config(logging::high) << "applier: no module loaded, "
        "you might want to check the 'module_directory' directive";
  }

  com::centreon::broker::multiplexing::subscriber::event_queue_max_size(s.event_queue_max_size());

  // Apply input, output and temporary configuration.
  endpoint::instance().apply(s.inputs(), s.outputs(), s.temporary());

  // Enable multiplexing loop.
  if (run_mux)
    com::centreon::broker::multiplexing::engine::instance().start();

  return ;
}

/**
 *  Get the instance of this object.
 *
 *  @return Class instance.
 */
state& state::instance() {
  return (*gl_state);
}

/**
 *  Load singleton.
 */
void state::load() {
  if (!gl_state)
    gl_state = new state;
  return ;
}

/**
 *  Unload singleton.
 */
void state::unload() {
  delete gl_state;
  gl_state = NULL;
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  Default constructor.
 */
state::state() {}

/**
 *  @brief Copy constructor.
 *
 *  Any call to this constructor will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 */
state::state(state const& s) {
  (void)s;
  _internal_copy(s);
}

/**
 *  @brief Assignment operator.
 *
 *  Any call to this method will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 *
 *  @return This object.
 */
state& state::operator=(state const& s) {
  (void)s;
  _internal_copy(s);
  return (*this);
}

/**
 *  Calls abort().
 *
 *  @param[in] s Unused.
 */
void state::_internal_copy(state const& s) {
  (void)s;
  assert(!"state configuration applier is not copyable");
  abort();
  return ;
}
<commit_msg>Only print information about loaded modules after the default configuration has been loaded. This fixes #4002.<commit_after>/*
** Copyright 2011-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <cstdlib>
#include <memory>
#include <QCoreApplication>
#include <QMutex>
#include <QMutexLocker>
#include "com/centreon/broker/config/applier/endpoint.hh"
#include "com/centreon/broker/config/applier/logger.hh"
#include "com/centreon/broker/config/applier/modules.hh"
#include "com/centreon/broker/config/applier/state.hh"
#include "com/centreon/broker/logging/file.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/multiplexing/engine.hh"
#include "com/centreon/broker/multiplexing/subscriber.hh"

using namespace com::centreon::broker::config::applier;

// Class instance.
static state* gl_state = NULL;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Destructor.
 */
state::~state() {}

/**
 *  Apply a configuration state.
 *
 *  @param[in] s       State to apply.
 *  @param[in] run_mux Set to true if multiplexing must be run.
 */
void state::apply(
              com::centreon::broker::config::state const& s,
              bool run_mux) {
  // Apply logging configuration.
  logger::instance().apply(s.loggers());

  // Flush logs or not.
  com::centreon::broker::logging::file::with_flush(
    s.flush_logs());

  // Enable or not thread ID logging.
  com::centreon::broker::logging::file::with_thread_id(
    s.log_thread_id());

  // Enable or not timestamp logging.
  com::centreon::broker::logging::file::with_timestamp(
    s.log_timestamp());

  // Apply modules configuration.
  modules::instance().apply(
                        s.module_list(),
                        s.module_directory(),
                        &s);
  static bool first_application(true);
  if (first_application)
    first_application = false;
  else {
    unsigned int module_count(0);
    for (modules::iterator
           it(modules::instance().begin()),
           end(modules::instance().end());
         it != end;
         ++it)
      ++module_count;
    if (module_count)
      logging::config(logging::high) << "applier: " << module_count
        << " modules loaded";
    else
      logging::config(logging::high) << "applier: no module loaded, "
        "you might want to check the 'module_directory' directive";
  }

  com::centreon::broker::multiplexing::subscriber::event_queue_max_size(s.event_queue_max_size());

  // Apply input, output and temporary configuration.
  endpoint::instance().apply(s.inputs(), s.outputs(), s.temporary());

  // Enable multiplexing loop.
  if (run_mux)
    com::centreon::broker::multiplexing::engine::instance().start();

  return ;
}

/**
 *  Get the instance of this object.
 *
 *  @return Class instance.
 */
state& state::instance() {
  return (*gl_state);
}

/**
 *  Load singleton.
 */
void state::load() {
  if (!gl_state)
    gl_state = new state;
  return ;
}

/**
 *  Unload singleton.
 */
void state::unload() {
  delete gl_state;
  gl_state = NULL;
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  Default constructor.
 */
state::state() {}

/**
 *  @brief Copy constructor.
 *
 *  Any call to this constructor will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 */
state::state(state const& s) {
  (void)s;
  _internal_copy(s);
}

/**
 *  @brief Assignment operator.
 *
 *  Any call to this method will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 *
 *  @return This object.
 */
state& state::operator=(state const& s) {
  (void)s;
  _internal_copy(s);
  return (*this);
}

/**
 *  Calls abort().
 *
 *  @param[in] s Unused.
 */
void state::_internal_copy(state const& s) {
  (void)s;
  assert(!"state configuration applier is not copyable");
  abort();
  return ;
}
<|endoftext|>


<commit_before>#include "polylineStyle.h"
#include "util/builders.h"
#include "roadLayers.h"
#include <ctime>

PolylineStyle::PolylineStyle(std::string _name, GLenum _drawMode) : Style(_name, _drawMode) {
    m_material.setEmissionEnabled(false);
    m_material.setAmbientEnabled(true);
    m_material.setDiffuse(glm::vec4(1.0));
    m_material.setSpecularEnabled(true);

    constructVertexLayout();
    constructShaderProgram();
}

void PolylineStyle::constructVertexLayout() {

    // TODO: Ideally this would be in the same location as the struct that it basically describes
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 3, GL_FLOAT, false, 0},
        {"a_texcoord", 2, GL_FLOAT, false, 0},
        {"a_extrudeNormal", 2, GL_FLOAT, false, 0},
        {"a_extrudeWidth", 1, GL_FLOAT, false, 0},
        {"a_color", 4, GL_UNSIGNED_BYTE, true, 0},
        {"a_layer", 1, GL_FLOAT, false, 0}
    }));

}

void PolylineStyle::constructShaderProgram() {

    std::string vertShaderSrcStr = stringFromResource("polyline.vs");
    std::string fragShaderSrcStr = stringFromResource("polyline.fs");

    m_shaderProgram = std::make_shared<ShaderProgram>();
    m_shaderProgram->setSourceStrings(fragShaderSrcStr, vertShaderSrcStr);

    m_material.injectOnProgram(m_shaderProgram);
}

void PolylineStyle::buildPoint(Point& _point, std::string& _layer, Properties& _props, VboMesh& _mesh) const {
    // No-op
}

void PolylineStyle::buildLine(Line& _line, std::string& _layer, Properties& _props, VboMesh& _mesh) const {
    std::vector<PosNormEnormColVertex> vertices;
    std::vector<int> indices;
    std::vector<glm::vec3> points;
    std::vector<glm::vec2> texcoords;
    std::vector<glm::vec2> scalingVecs;

    GLuint abgr = 0xff686868; // Default road color
    GLuint abgrOutline = 0xff777777;
    GLfloat layer = sortKeyToLayer(_props.numericProps["sort_key"]) + 3;

    float halfWidth = 0.02;

    const std::string& kind = _props.stringProps["kind"];

    if (kind == "highway") {
        halfWidth = 0.02;
    } else if (kind == "major_road") {
        halfWidth = 0.015;
    } else if (kind == "minor_road") {
        halfWidth = 0.01;
    } else if (kind == "rail") {
        halfWidth = 0.002;
    } else if (kind == "path") {
        halfWidth = 0.005;
    }

    PolyLineOutput lineOutput = { points, indices, scalingVecs, texcoords };
    PolyLineOptions lineOptions = { CapTypes::ROUND, JoinTypes::MITER, halfWidth };
    Builders::buildPolyLine(_line, lineOptions, lineOutput);

    for (size_t i = 0; i < points.size(); i++) {
        const glm::vec3& p = points[i];
        const glm::vec2& uv = texcoords[i];
        const glm::vec2& en = scalingVecs[i];
        vertices.push_back({ p.x, p.y, p.z, uv.x, uv.y, en.x, en.y, 0.6f * halfWidth, abgr, layer });
    }

    size_t outlineStart = points.size();

    Builders::buildOutline(_line, lineOptions, lineOutput);

    for (size_t i = outlineStart; i < points.size(); i++) {
        const glm::vec3& p = points[i];
        const glm::vec2& uv = texcoords[i];
        const glm::vec2& en = scalingVecs[i];
        vertices.push_back({ p.x, p.y, p.z, uv.x, uv.y, en.x, en.y, halfWidth, abgrOutline, layer - 1.f });
    }

    // Make sure indices get correctly offset
    int vertOffset = _mesh.numVertices();
    for (auto& ind : indices) {
        ind += vertOffset;
    }

    _mesh.addVertices((GLbyte*)vertices.data(), (int)vertices.size());
    _mesh.addIndices(indices.data(), (int)indices.size());
}

void PolylineStyle::buildPolygon(Polygon& _polygon, std::string& _layer, Properties& _props, VboMesh& _mesh) const {
    // No-op
}
<commit_msg>Outlining roads can be done with just BuildPolyLine<commit_after>#include "polylineStyle.h"
#include "util/builders.h"
#include "roadLayers.h"
#include <ctime>

PolylineStyle::PolylineStyle(std::string _name, GLenum _drawMode) : Style(_name, _drawMode) {
    m_material.setEmissionEnabled(false);
    m_material.setAmbientEnabled(true);
    m_material.setDiffuse(glm::vec4(1.0));
    m_material.setSpecularEnabled(true);

    constructVertexLayout();
    constructShaderProgram();
}

void PolylineStyle::constructVertexLayout() {

    // TODO: Ideally this would be in the same location as the struct that it basically describes
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 3, GL_FLOAT, false, 0},
        {"a_texcoord", 2, GL_FLOAT, false, 0},
        {"a_extrudeNormal", 2, GL_FLOAT, false, 0},
        {"a_extrudeWidth", 1, GL_FLOAT, false, 0},
        {"a_color", 4, GL_UNSIGNED_BYTE, true, 0},
        {"a_layer", 1, GL_FLOAT, false, 0}
    }));

}

void PolylineStyle::constructShaderProgram() {

    std::string vertShaderSrcStr = stringFromResource("polyline.vs");
    std::string fragShaderSrcStr = stringFromResource("polyline.fs");

    m_shaderProgram = std::make_shared<ShaderProgram>();
    m_shaderProgram->setSourceStrings(fragShaderSrcStr, vertShaderSrcStr);

    m_material.injectOnProgram(m_shaderProgram);
}

void PolylineStyle::buildPoint(Point& _point, std::string& _layer, Properties& _props, VboMesh& _mesh) const {
    // No-op
}

void PolylineStyle::buildLine(Line& _line, std::string& _layer, Properties& _props, VboMesh& _mesh) const {
    std::vector<PosNormEnormColVertex> vertices;
    std::vector<int> indices;
    std::vector<glm::vec3> points;
    std::vector<glm::vec2> texcoords;
    std::vector<glm::vec2> scalingVecs;

    GLuint abgr = 0xff686868; // Default road color
    GLuint abgrOutline = 0xff777777;
    GLfloat layer = sortKeyToLayer(_props.numericProps["sort_key"]) + 3;

    float halfWidth = 0.02;

    const std::string& kind = _props.stringProps["kind"];

    if (kind == "highway") {
        halfWidth = 0.02;
    } else if (kind == "major_road") {
        halfWidth = 0.015;
    } else if (kind == "minor_road") {
        halfWidth = 0.01;
    } else if (kind == "rail") {
        halfWidth = 0.002;
    } else if (kind == "path") {
        halfWidth = 0.005;
    }

    PolyLineOutput lineOutput = { points, indices, scalingVecs, texcoords };
    PolyLineOptions lineOptions = { CapTypes::ROUND, JoinTypes::MITER, halfWidth };
    Builders::buildPolyLine(_line, lineOptions, lineOutput);

    for (size_t i = 0; i < points.size(); i++) {
        const glm::vec3& p = points[i];
        const glm::vec2& uv = texcoords[i];
        const glm::vec2& en = scalingVecs[i];
        vertices.push_back({ p.x, p.y, p.z, uv.x, uv.y, en.x, en.y, 0.6f * halfWidth, abgr, layer });
    }

    size_t outlineStart = points.size();

    Builders::buildPolyLine(_line, lineOptions, lineOutput);

    for (size_t i = outlineStart; i < points.size(); i++) {
        const glm::vec3& p = points[i];
        const glm::vec2& uv = texcoords[i];
        const glm::vec2& en = scalingVecs[i];
        vertices.push_back({ p.x, p.y, p.z, uv.x, uv.y, en.x, en.y, halfWidth, abgrOutline, layer - 1.f });
    }

    // Make sure indices get correctly offset
    int vertOffset = _mesh.numVertices();
    for (auto& ind : indices) {
        ind += vertOffset;
    }

    _mesh.addVertices((GLbyte*)vertices.data(), (int)vertices.size());
    _mesh.addIndices(indices.data(), (int)indices.size());
}

void PolylineStyle::buildPolygon(Polygon& _polygon, std::string& _layer, Properties& _props, VboMesh& _mesh) const {
    // No-op
}
<|endoftext|>


<commit_before>#include <thenet/message_queue.hpp>

namespace the
{

namespace net
{

MessageQueue::MessageQueue( LowLevelSendCallback low_level_send_callback )
  : m_low_level_send( low_level_send_callback )
{
}

bool
MessageQueue::send( Data&& data )
{
  return m_out_buffer.push( data );
}

bool
MessageQueue::receive( Data& data )
{
  return m_in_buffer.pop( data );
}

void
MessageQueue::wake_up()
{
  Data data;
  while ( m_out_buffer.pop( data ) )
  {
    m_low_level_send( std::move( data ) );
  }
}

void
MessageQueue::message_from_network( Data&& data )
{
  m_in_buffer.push( data );
}

}

}

<commit_msg>making sure data is moved instead of being copied<commit_after>#include <thenet/message_queue.hpp>

namespace the
{

namespace net
{

MessageQueue::MessageQueue( LowLevelSendCallback low_level_send_callback )
  : m_low_level_send( low_level_send_callback )
{
}

bool
MessageQueue::send( Data&& data )
{
  return m_out_buffer.push( data );
}

bool
MessageQueue::receive( Data& data )
{
  return m_in_buffer.pop( data );
}

void
MessageQueue::wake_up()
{
  Data data;
  while ( m_out_buffer.pop( data ) )
  {
    m_low_level_send( std::move( data ) );
  }
}

void
MessageQueue::message_from_network( Data&& data )
{
  m_in_buffer.push( std::move( data ) );
}

}

}

<|endoftext|>


<commit_before>#include "connection.hpp"
#include <boost/thread.hpp>
#include <thread>
#include <chrono>

using boost::asio::ip::tcp;

namespace libircppclient {

void connection::connect(const std::string &addr, const std::string &port)
{
    /* Perfect place to implement check of valid data */
    addr_ = addr;
    port_ = port;

    connect();
}

void connection::connect()
{
    /*
     * Resolve the host and generate a list of endpoints.
     * An endpoint is the information used to connect to an address.
     * An address may have more than one endpoint.
     */
    tcp::resolver r(io_service_);
    tcp::resolver::query query(addr_, port_);
    tcp::resolver::iterator endpt_it = r.resolve(query);

    /* Denotes the end of the list of generated endpoints. */
    decltype(endpt_it) end;

    /* Default error */
    boost::system::error_code error = boost::asio::error::host_not_found;

    /* Iterate until we've reached the end of the list. */
    while (endpt_it != end) {
        if (!error)
            break;

        socket_.close();
        socket_.connect(*endpt_it++, error);
    }

    if (error)
        throw error;
}

void connection::run()
{
    std::thread ping_handler_thread(ping_handler);

    /*
     * Start an asynchronous read thread going through connection::read().
     * Pass the arguments (this, _1, _2) to the handler.
     */
    socket_.async_read_some(boost::asio::buffer(buffer_),
                            boost::bind(&connection::read,
                                        this, boost::asio::placeholders::error,
                                        boost::asio::placeholders::bytes_transferred()));

    io_service_.run();

    /* Remain at this point until we do not need the connection any more. */
    ping_handler_thread.join();
}

void connection::ping()
{
    using namespace std::literals;

    while (do_ping) {
        /*
         * Interval decided by mimicing WeeChat.
         * The standard does not seem to explicitly
         * state a ping inverval. Is it the server's
         * decision?
         */
        std::this_thread::sleep_for(1min + 30s);

        /* For debugging */
        std::cout << "[info] Pinging " << addr_ << '.' << std::endl;
        write("PING " + addr_);
    }
}

void connection::pong()
{
    write("PONG :" + addr_);
}

void connection::write(const std::string &content)
{
    /*
     * The IRC protocol specifies that all messages sent to the server
     * must be terminated with CR-LF (Carriage Return - Line Feed)
     */
    boost::asio::write(socket_, boost::asio::buffer(content + "\r\n"));
    //reset_timer();
}

void connection::read(const boost::system::error_code &error, std::size_t length)
{
    if (error) {
        /* Unable to read from server. */
        throw error;
    } else {
        /*
         * Works in synergy with socket::async_read_some().
         *
         * Copy the data within the buffer and the length of it
         * and pass it to the class' read_handler.
         */
        read_handler(std::string(buffer_.data(), length));

        /*
         * Start an asynchronous recursive read thread.
         *
         * Read data from the IRC server into the buffer, and
         * call this function again.
         *
         * Pass the eventual error and the message length.
         */
        socket_.async_read_some(boost::asio::buffer(buffer_),
                                boost::bind(&connection::read,
                                            this, boost::asio::placeholders::error,
                                            boost::asio::placeholders::bytes_transferred));
    }
}

void connection::read_handler(const std::string &content)
{
    std::stringstream iss(content);
    std::string command;

    iss >> command;

    if (command == "PING")
        pong();
    else
        ext_read_handler_(content);
}

void connection::stop()
{
    socket_.close();
    io_service_.stop();
}

/* ns libircppclient */
}
<commit_msg>Add empty line under statements which are followed by block comments<commit_after>#include "connection.hpp"
#include <boost/thread.hpp>
#include <thread>
#include <chrono>

using boost::asio::ip::tcp;

namespace libircppclient {

void connection::connect(const std::string &addr, const std::string &port)
{
    /* Perfect place to implement check of valid data */
    addr_ = addr;
    port_ = port;

    connect();
}

void connection::connect()
{
    /*
     * Resolve the host and generate a list of endpoints.
     * An endpoint is the information used to connect to an address.
     * An address may have more than one endpoint.
     */
    tcp::resolver r(io_service_);
    tcp::resolver::query query(addr_, port_);
    tcp::resolver::iterator endpt_it = r.resolve(query);

    /* Denotes the end of the list of generated endpoints. */
    decltype(endpt_it) end;

    /* Default error */
    boost::system::error_code error = boost::asio::error::host_not_found;

    /* Iterate until we've reached the end of the list. */
    while (endpt_it != end) {
        if (!error)
            break;

        socket_.close();
        socket_.connect(*endpt_it++, error);
    }

    if (error)
        throw error;
}

void connection::run()
{
    std::thread ping_handler_thread(ping_handler);

    /*
     * Start an asynchronous read thread going through connection::read().
     * Pass the arguments (this, _1, _2) to the handler.
     */
    socket_.async_read_some(boost::asio::buffer(buffer_),
                            boost::bind(&connection::read,
                                        this, boost::asio::placeholders::error,
                                        boost::asio::placeholders::bytes_transferred()));

    io_service_.run();

    /* Remain at this point until we do not need the connection any more. */
    ping_handler_thread.join();
}

void connection::ping()
{
    using namespace std::literals;

    while (do_ping) {

        /*
         * Interval decided by mimicing WeeChat.
         * The standard does not seem to explicitly
         * state a ping inverval. Is it the server's
         * decision?
         */
        std::this_thread::sleep_for(1min + 30s);

        /* For debugging */
        std::cout << "[info] Pinging " << addr_ << '.' << std::endl;
        write("PING " + addr_);
    }
}

void connection::pong()
{
    write("PONG :" + addr_);
}

void connection::write(const std::string &content)
{
    /*
     * The IRC protocol specifies that all messages sent to the server
     * must be terminated with CR-LF (Carriage Return - Line Feed)
     */
    boost::asio::write(socket_, boost::asio::buffer(content + "\r\n"));
    //reset_timer();
}

void connection::read(const boost::system::error_code &error, std::size_t length)
{
    if (error) {
        /* Unable to read from server. */
        throw error;
    } else {

        /*
         * Works in synergy with socket::async_read_some().
         *
         * Copy the data within the buffer and the length of it
         * and pass it to the class' read_handler.
         */
        read_handler(std::string(buffer_.data(), length));

        /*
         * Start an asynchronous recursive read thread.
         *
         * Read data from the IRC server into the buffer, and
         * call this function again.
         *
         * Pass the eventual error and the message length.
         */
        socket_.async_read_some(boost::asio::buffer(buffer_),
                                boost::bind(&connection::read,
                                            this, boost::asio::placeholders::error,
                                            boost::asio::placeholders::bytes_transferred));
    }
}

void connection::read_handler(const std::string &content)
{
    std::stringstream iss(content);
    std::string command;

    iss >> command;

    if (command == "PING")
        pong();
    else
        ext_read_handler_(content);
}

void connection::stop()
{
    socket_.close();
    io_service_.stop();
}

/* ns libircppclient */
}
<|endoftext|>


<commit_before>#include "modinclude.h"
#include "cap.h"

class Cap : public CapModule {
	public:
		Cap();
		int botAPIversion();
		void onModuleChange();
		void onOtherData(std::string server, std::vector<std::string> parsedLine);
		void onConnect(std::string server);
		void capRegister(std::string moduleName, std::string capCommand);
		void blockCap(std::string server, std::string moduleName);
		void continueCap(std::string server, std::string moduleName);
	private:
		void endCap();
		std::tr1::unordered_map<std::string, std::vector<std::string> > capCommands;
		std::tr1::unordered_map<std::string, std::vector<std::string> > blockingModules;
};

Cap::Cap() {
	std::vector<std::string> theCore;
	theCore.push_back("");
	capCommands.insert(std::pair<std::string, std::vector<std::string> > ("multi-prefix", theCore));
}

int Cap::botAPIversion() {
	return 1100;
}

void Cap::onModuleChange() {
	std::tr1::unordered_map<std::string, Module*> modulesList = getModules();
	for (std::tr1::unordered_map<std::string, std::vector<std::string> >::iterator capIter = capCommands.begin(); capIter != capCommands.end(); ++capIter) {
		for (unsigned int i = 0; i < capIter->second.size(); i++) {
			if (modulesList.find(capIter->second[i]) == modulesList.end()) {
				capIter->second.erase(capIter->second.begin() + i);
				i--;
			}
		}
	}
	for (std::tr1::unordered_map<std::string, std::vector<std::string> >::iterator blockIter = blockingModules.begin(); blockIter != blockingModules.end(); ++blockIter) {
		for (unsigned int i = 0; i < blockIter->second.size(); i++) {
			if (modulesList.find(blockIter->second[i]) == modulesList.end()) {
				blockIter->second.erase(blockIter->second.begin() + i);
				i--;
			}
		}
		endCap(blockIter->first);
	}
}

void Cap::onOtherData(std::string server, std::vector<std::string> parsedLine) {
	if (parsedLine[1] == "CAP") {
		if (parsedLine[3] == "LS") {
			std::string capReq = "";
			std::vector<std::string> serverCapab = splitBySpace(parsedLine[4]);
			for (unsigned int i = 0; i < serverCapab.size(); i++) {
				if (serverCapab[i][0] == '=' || serverCapab[i][0] == '~')
					serverCapab[i] = serverCapab[i].substr(1);
				std::tr1::unordered_map<std::string, std::vector<std::string> >::iterator capIter = capCommands.find(serverCapab[i]);
				if (capIter != capCommands.end()) {
					capReq += " " + serverCapab[i];
					for (unsigned int j = 0; j < capIter->second.size(); j++) {
						CapClient* lsMod = (CapClient*) getModules().find(capIter->second[j])->second;
						lsMod->onCapExists(server, serverCapab[i]);
					}
				}
			}
			sendOtherCommand(server, "CAP", "REQ :" + capReq.substr(1));
		} else if (parsedLine[3] == "ACK") {
			std::vector<std::string> capAcknowledge = splitBySpace(parsedLine[4]);
			std::string ackReply = "";
			for (unsigned int i = 0; i < capAcknowledge.size(); i++) {
				char capModifier = ' ';
				if (capAcknowledge[i][0] == '=' || capAcknowledge[i][0] == '~') {
					capModifier = capAcknowledge[i][0];
					capAcknowledge[i] = capAcknowledge[i].substr(1);
				}
				std::tr1::unordered_map<std::string, std::vector<std::string> >::iterator capAck = capCommands.find(capAcknowledge);
				if (capAck != capCommands.end()) {
					for (unsigned int j = 0; j < capAck->second.size(); j++) {
						if (capAck->second[j] == "")
							continue;
						CapClient* ackMod = (CapClient*) getModules().find(capAck->second[j])->second;
						ackMod->onCapAccept(server, capAck->first);
					}
				}
				if (capModifier == '~')
					ackReply += " " + capAcknowledge[i];
			}
			if (ackReply != "")
				sendOtherCommand(server, "CAP", "ACK :" + ackReply.substr(1));
		} else if (parsedLine[3] == "NAK")
			endCap(server);
	}
}

void Cap::onConnect(std::string server) {
	sendOtherCommand(server, "CAP", "LS");
	blockingModules[server].clear();
}

void Cap::capRegister(std::string moduleName, std::string capCommand) {
	capCommands[capCommand].push_back(moduleName);
}

void Cap::blockCap(std::string server, std::string moduleName) {
	blockingModules[server].push_back(moduleName);
}

void Cap::continueCap(std::string server, std::string moduleName) {
	for (unsigned int i = 0; i < blockingModules[server].size(); i++) {
		if (blockingModules[server][i] == moduleName) {
			blockingModules[server].erase(blockingModules[server].begin() + i);
			i--;
		}
	}
	endCap(server);
}

void Cap::endCap(std::string server) {
	if (blockingModules[server].empty()) {
		sendOtherCommand(server, "CAP", "END");
		blockingModules[server].push_back(""); // insert dummy to force CAP END to not be sent again
	}
}

extern "C" Module* spawn() {
	return new Cap;
}<commit_msg>Fix an unupdated part of m_cap<commit_after>#include "modinclude.h"
#include "cap.h"

class Cap : public CapModule {
	public:
		Cap();
		int botAPIversion();
		void onModuleChange();
		void onOtherData(std::string server, std::vector<std::string> parsedLine);
		void onConnect(std::string server);
		void capRegister(std::string moduleName, std::string capCommand);
		void blockCap(std::string server, std::string moduleName);
		void continueCap(std::string server, std::string moduleName);
	private:
		void endCap(std::string server);
		std::tr1::unordered_map<std::string, std::vector<std::string> > capCommands;
		std::tr1::unordered_map<std::string, std::vector<std::string> > blockingModules;
};

Cap::Cap() {
	std::vector<std::string> theCore;
	theCore.push_back("");
	capCommands.insert(std::pair<std::string, std::vector<std::string> > ("multi-prefix", theCore));
}

int Cap::botAPIversion() {
	return 1100;
}

void Cap::onModuleChange() {
	std::tr1::unordered_map<std::string, Module*> modulesList = getModules();
	for (std::tr1::unordered_map<std::string, std::vector<std::string> >::iterator capIter = capCommands.begin(); capIter != capCommands.end(); ++capIter) {
		for (unsigned int i = 0; i < capIter->second.size(); i++) {
			if (modulesList.find(capIter->second[i]) == modulesList.end()) {
				capIter->second.erase(capIter->second.begin() + i);
				i--;
			}
		}
	}
	for (std::tr1::unordered_map<std::string, std::vector<std::string> >::iterator blockIter = blockingModules.begin(); blockIter != blockingModules.end(); ++blockIter) {
		for (unsigned int i = 0; i < blockIter->second.size(); i++) {
			if (modulesList.find(blockIter->second[i]) == modulesList.end()) {
				blockIter->second.erase(blockIter->second.begin() + i);
				i--;
			}
		}
		endCap(blockIter->first);
	}
}

void Cap::onOtherData(std::string server, std::vector<std::string> parsedLine) {
	if (parsedLine[1] == "CAP") {
		if (parsedLine[3] == "LS") {
			std::string capReq = "";
			std::vector<std::string> serverCapab = splitBySpace(parsedLine[4]);
			for (unsigned int i = 0; i < serverCapab.size(); i++) {
				if (serverCapab[i][0] == '=' || serverCapab[i][0] == '~')
					serverCapab[i] = serverCapab[i].substr(1);
				std::tr1::unordered_map<std::string, std::vector<std::string> >::iterator capIter = capCommands.find(serverCapab[i]);
				if (capIter != capCommands.end()) {
					capReq += " " + serverCapab[i];
					for (unsigned int j = 0; j < capIter->second.size(); j++) {
						CapClient* lsMod = (CapClient*) getModules().find(capIter->second[j])->second;
						lsMod->onCapExists(server, serverCapab[i]);
					}
				}
			}
			sendOtherCommand(server, "CAP", "REQ :" + capReq.substr(1));
		} else if (parsedLine[3] == "ACK") {
			std::vector<std::string> capAcknowledge = splitBySpace(parsedLine[4]);
			std::string ackReply = "";
			for (unsigned int i = 0; i < capAcknowledge.size(); i++) {
				char capModifier = ' ';
				if (capAcknowledge[i][0] == '=' || capAcknowledge[i][0] == '~') {
					capModifier = capAcknowledge[i][0];
					capAcknowledge[i] = capAcknowledge[i].substr(1);
				}
				std::tr1::unordered_map<std::string, std::vector<std::string> >::iterator capAck = capCommands.find(capAcknowledge);
				if (capAck != capCommands.end()) {
					for (unsigned int j = 0; j < capAck->second.size(); j++) {
						if (capAck->second[j] == "")
							continue;
						CapClient* ackMod = (CapClient*) getModules().find(capAck->second[j])->second;
						ackMod->onCapAccept(server, capAck->first);
					}
				}
				if (capModifier == '~')
					ackReply += " " + capAcknowledge[i];
			}
			if (ackReply != "")
				sendOtherCommand(server, "CAP", "ACK :" + ackReply.substr(1));
		} else if (parsedLine[3] == "NAK")
			endCap(server);
	}
}

void Cap::onConnect(std::string server) {
	sendOtherCommand(server, "CAP", "LS");
	blockingModules[server].clear();
}

void Cap::capRegister(std::string moduleName, std::string capCommand) {
	capCommands[capCommand].push_back(moduleName);
}

void Cap::blockCap(std::string server, std::string moduleName) {
	blockingModules[server].push_back(moduleName);
}

void Cap::continueCap(std::string server, std::string moduleName) {
	for (unsigned int i = 0; i < blockingModules[server].size(); i++) {
		if (blockingModules[server][i] == moduleName) {
			blockingModules[server].erase(blockingModules[server].begin() + i);
			i--;
		}
	}
	endCap(server);
}

void Cap::endCap(std::string server) {
	if (blockingModules[server].empty()) {
		sendOtherCommand(server, "CAP", "END");
		blockingModules[server].push_back(""); // insert dummy to force CAP END to not be sent again
	}
}

extern "C" Module* spawn() {
	return new Cap;
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013, George Makrydakis <irrequietus@gmail.com>
 *
 * This file is part of odreex.
 *
 * odreex is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * odreex is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * odreex. If not, see http://www.gnu.org/licenses/.
 *
 */

#ifndef _ODREEX_AMPLE_BASIC_NUMBER_HH_
#define _ODREEX_AMPLE_BASIC_NUMBER_HH_

#include <cinttypes>

namespace odreex {
namespace ample {

template<typename Type_T, Type_T N = 0>
struct basic_number {
    typedef basic_number type;
    static Type_T const value = N;

    template<typename Number_T>
    struct oprt_add {
        typedef basic_number< Type_T
                            , N + static_cast<Type_T>(Number_T::value)> type;
    };

    template<typename Number_T>
    struct oprt_sub {
        typedef basic_number< Type_T
                            , N - static_cast<Type_T>(Number_T::value)> type;
    };

    template<typename Number_T>
    struct oprt_mul {
        typedef basic_number< Type_T
                            , N * static_cast<Type_T>(Number_T::value)> type;
    };

    template<typename Number_T>
    struct oprt_div {
        static_assert(Number_T::value, "cannot divide by zero");
        typedef basic_number< Number_T
                            , N / static_cast<Type_T>(Number_T::value)> type;
    };

    template<typename Number_T>
    struct oprt_mod {
        typedef basic_number< Type_T
                            , N % static_cast<Type_T>(Number_T::value)> type;
    };

    struct oprt_next
         : oprt_add<basic_number<Type_T, 1>>
    {};

    struct oprt_prev
         : oprt_sub<basic_number<Type_T, 1>>
    {};
};

template<uint64_t N>
using num64u_t = basic_number<uint64_t, N>;

template<uint32_t N>
using num32u_t = basic_number<uint32_t, N>;

template<int64_t N>
using num64_t = basic_number<int64_t, N>;

template<int32_t N>
using num32_t = basic_number<int32_t, N>;

template<uint64_t N>
using natural = basic_number<uint64_t, N>;

} /* ample */
} /* odreex */

#endif /* _ODREEX_AMPLE_BASIC_NUMBER_HH_ */
<commit_msg>Canonical header #ifndef fix for odreex/ample/base/basic_number.hh.<commit_after>/*
 * Copyright (C) 2013, George Makrydakis <irrequietus@gmail.com>
 *
 * This file is part of odreex.
 *
 * odreex is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * odreex is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * odreex. If not, see http://www.gnu.org/licenses/.
 *
 */

#ifndef _ODREEX_AMPLE_BASE_BASIC_NUMBER_HH_
#define _ODREEX_AMPLE_BASE_BASIC_NUMBER_HH_

#include <cinttypes>

namespace odreex {
namespace ample {

template<typename Type_T, Type_T N = 0>
struct basic_number {
    typedef basic_number type;
    static Type_T const value = N;

    template<typename Number_T>
    struct oprt_add {
        typedef basic_number< Type_T
                            , N + static_cast<Type_T>(Number_T::value)> type;
    };

    template<typename Number_T>
    struct oprt_sub {
        typedef basic_number< Type_T
                            , N - static_cast<Type_T>(Number_T::value)> type;
    };

    template<typename Number_T>
    struct oprt_mul {
        typedef basic_number< Type_T
                            , N * static_cast<Type_T>(Number_T::value)> type;
    };

    template<typename Number_T>
    struct oprt_div {
        static_assert(Number_T::value, "cannot divide by zero");
        typedef basic_number< Number_T
                            , N / static_cast<Type_T>(Number_T::value)> type;
    };

    template<typename Number_T>
    struct oprt_mod {
        typedef basic_number< Type_T
                            , N % static_cast<Type_T>(Number_T::value)> type;
    };

    struct oprt_next
         : oprt_add<basic_number<Type_T, 1>>
    {};

    struct oprt_prev
         : oprt_sub<basic_number<Type_T, 1>>
    {};
};

template<uint64_t N>
using num64u_t = basic_number<uint64_t, N>;

template<uint32_t N>
using num32u_t = basic_number<uint32_t, N>;

template<int64_t N>
using num64_t = basic_number<int64_t, N>;

template<int32_t N>
using num32_t = basic_number<int32_t, N>;

template<uint64_t N>
using natural = basic_number<uint64_t, N>;

} /* ample */
} /* odreex */

#endif /* _ODREEX_AMPLE_BASE_BASIC_NUMBER_HH_ */
<|endoftext|>


<commit_before>/// HEADER
#include "morphological.h"

/// PROJECT
#include <csapex_vision/cv_mat_message.h>

/// PROJECT
#include <csapex/model/connector_out.h>
#include <csapex/model/connector_in.h>

/// SYSTEM
#include <csapex/utility/register_apex_plugin.h>

CSAPEX_REGISTER_CLASS(csapex::Morpholocial, csapex::Node)

using namespace csapex;

Morpholocial::Morpholocial()
{
    addTag(Tag::get("Vision"));

    addParameter(param::Parameter::declare<int>("size", 1, 20, 2, 1));
    addParameter(param::Parameter::declare<int>("iterations", 1, 10, 1, 1));
}

void Morpholocial::allConnectorsArrived()
{
    connection_types::CvMatMessage::Ptr a = input_->getMessage<connection_types::CvMatMessage>();

    connection_types::CvMatMessage::Ptr msg(new connection_types::CvMatMessage);
    int op = cv::MORPH_OPEN;//, MORPH_CLOSE, MORPH_GRADIENT, MORPH_TOPHAT, MORPH_BLACKHAT;
    int morph_elem = cv::MORPH_RECT;
    int morph_size = param<int>("size");
    cv::Mat kernel = cv::getStructuringElement(morph_elem, cv::Size(2*morph_size+1, 2*morph_size+1), cv::Point(morph_size, morph_size));
    cv::Point anchor(-1,-1);
    int iterations = param<int>("iterations");
    int border_type = cv::BORDER_CONSTANT;
    const cv::Scalar& border_value = cv::morphologyDefaultBorderValue();

    cv::morphologyEx(a->value, msg->value, op, kernel, anchor, iterations, border_type, border_value);

    output_->publish(msg);
}

void Morpholocial::setup()
{
    setSynchronizedInputs(true);

    input_ = addInput<connection_types::CvMatMessage>("A");

    output_ = addOutput<connection_types::CvMatMessage>("morph(A)");
}
<commit_msg>migration to new utils_param<commit_after>/// HEADER
#include "morphological.h"

/// PROJECT
#include <csapex_vision/cv_mat_message.h>

/// PROJECT
#include <csapex/model/connector_out.h>
#include <csapex/model/connector_in.h>
#include <utils_param/parameter_factory.h>

/// SYSTEM
#include <csapex/utility/register_apex_plugin.h>

CSAPEX_REGISTER_CLASS(csapex::Morpholocial, csapex::Node)

using namespace csapex;

Morpholocial::Morpholocial()
{
    addTag(Tag::get("Vision"));

    addParameter(param::ParameterFactory::declare<int>("size", 1, 20, 2, 1));
    addParameter(param::ParameterFactory::declare<int>("iterations", 1, 10, 1, 1));
}

void Morpholocial::allConnectorsArrived()
{
    connection_types::CvMatMessage::Ptr a = input_->getMessage<connection_types::CvMatMessage>();

    connection_types::CvMatMessage::Ptr msg(new connection_types::CvMatMessage);
    int op = cv::MORPH_OPEN;//, MORPH_CLOSE, MORPH_GRADIENT, MORPH_TOPHAT, MORPH_BLACKHAT;
    int morph_elem = cv::MORPH_RECT;
    int morph_size = param<int>("size");
    cv::Mat kernel = cv::getStructuringElement(morph_elem, cv::Size(2*morph_size+1, 2*morph_size+1), cv::Point(morph_size, morph_size));
    cv::Point anchor(-1,-1);
    int iterations = param<int>("iterations");
    int border_type = cv::BORDER_CONSTANT;
    const cv::Scalar& border_value = cv::morphologyDefaultBorderValue();

    cv::morphologyEx(a->value, msg->value, op, kernel, anchor, iterations, border_type, border_value);

    output_->publish(msg);
}

void Morpholocial::setup()
{
    setSynchronizedInputs(true);

    input_ = addInput<connection_types::CvMatMessage>("A");

    output_ = addOutput<connection_types::CvMatMessage>("morph(A)");
}
<|endoftext|>


<commit_before><commit_msg>Fix build warnings with VS 2022 (#9967)<commit_after><|endoftext|>