<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2019-2020 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <ivwdataframe/pydataframe.h>

#include <warn/push>
#include <warn/ignore/shadow>
#include <pybind11/functional.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <warn/pop>

#include <inviwo/dataframe/datastructures/column.h>
#include <inviwo/dataframe/datastructures/dataframe.h>
#include <inviwo/dataframe/datastructures/datapoint.h>

#include <inviwo/core/util/defaultvalues.h>
#include <inviwo/core/datastructures/buffer/buffer.h>
#include <modules/python3/pyportutils.h>

#include <fmt/format.h>

namespace py = pybind11;

namespace inviwo {

namespace {

struct DataFrameAddColumnReg {
    template <typename T>
    auto operator()(py::class_<DataFrame, std::shared_ptr<DataFrame>>& d) {
        auto classname = Defaultvalues<T>::getName();

        d.def(fmt::format("add{}Column", classname).c_str(),
              [](DataFrame& d, const std::string& header, const size_t size = 0) {
                  return d.addColumn<T>(header, size);
              },
              py::arg("header"), py::arg("size") = 0);

        d.def(fmt::format("add{}Column", classname).c_str(),
              [](DataFrame& d, std::string header, std::vector<T> data) {
                  return d.addColumn(std::move(header), std::move(data));
              },
              py::arg("header"), py::arg("data"));
    }
};

struct DataPointReg {
    template <typename T>
    auto operator()(pybind11::module& m) {
        using D = DataPoint<T>;
        auto classname = Defaultvalues<T>::getName() + "DataPoint";

        py::class_<D, DataPointBase, std::shared_ptr<D>> data(m, classname.c_str());
        data.def_property_readonly("data", &D::getData)
            .def_property_readonly("str", &D::toString)
            .def("__repr__",
                 [classname](D& p) { return fmt::format("<{}: '{}'>", classname, p.toString()); });
    }
};

struct TemplateColumnReg {
    template <typename T>
    auto operator()(pybind11::module& m) {
        using C = TemplateColumn<T>;
        auto classname = Defaultvalues<T>::getName() + "Column";

        py::class_<C, Column, std::shared_ptr<C>> col(m, classname.c_str());
        col.def_property_readonly("buffer", [](C& c) { return c.getTypedBuffer(); })
            .def(py::init<const std::string&>())
            .def("add", py::overload_cast<const T&>(&C::add))
            .def("add", py::overload_cast<const std::string&>(&C::add))
            .def("append", [](C& c, C& src) { c.append(src); })
            .def("set", &C::set)
            .def("get",
                 [](const C& c, size_t i) {
                     if (i >= c.getSize()) throw py::index_error();
                     return c.get(i);
                 },
                 py::arg("i"))
            .def("get",
                 [](const C& c, size_t i, bool asString) {
                     if (i >= c.getSize()) throw py::index_error();
                     return c.get(i, asString);
                 },
                 py::arg("i"), py::arg("asString"))
            .def("__repr__", [classname](C& c) {
                return fmt::format("<{}: '{}', {}, {}>", classname, c.getHeader(), c.getSize(),
                                   c.getBuffer()->getDataFormat()->getString());
            });
    }
};

}  // namespace

void exposeDataFrame(pybind11::module& m) {
    py::class_<DataPointBase, std::shared_ptr<DataPointBase>>(m, "DataPointBase")
        .def("__repr__",
             [](DataPointBase& p) { return fmt::format("<DataPoint: '{}'>", p.toString()); });

    py::class_<Column, std::shared_ptr<Column>>(m, "Column")
        .def_property("header", &Column::getHeader, &Column::setHeader)
        .def_property_readonly("buffer", [](Column& self) { return self.getBuffer(); })
        .def_property_readonly("size", &Column::getSize)
        .def("__repr__", [](Column& c) {
            return fmt::format("<Column: '{}', {}, {}>", c.getHeader(), c.getSize(),
                               c.getBuffer()->getDataFormat()->getString());
        });

    using Scalars = std::tuple<float, double, int, glm::i64, size_t, std::uint32_t>;
    util::for_each_type<Scalars>{}(DataPointReg{}, m);
    util::for_each_type<Scalars>{}(TemplateColumnReg{}, m);

    py::class_<CategoricalColumn, TemplateColumn<std::uint32_t>,
               std::shared_ptr<CategoricalColumn>>(m, "CategoricalColumn")
        .def(py::init<const std::string&>())
        .def_property_readonly("categories", &CategoricalColumn::getCategories,
                               py::return_value_policy::copy)
        .def("add", [](CategoricalColumn& c, const std::string& str) { c.add(str); })
        .def("append", [](CategoricalColumn& c, CategoricalColumn& src) { c.append(src); })
        .def("set", [](CategoricalColumn& c, size_t idx, const std::uint32_t& v) { c.set(idx, v); })
        .def("set", py::overload_cast<size_t, const std::string&>(&CategoricalColumn::set))
        .def("get",
             [](const CategoricalColumn& c, size_t i, bool asString) {
                 if (i >= c.getSize()) throw py::index_error();
                 return c.get(i, asString);
             },
             py::arg("i"), py::arg("asString") = true)
        .def("__repr__", [](CategoricalColumn& c) {
            return fmt::format("<CategoricalColumn: '{}', {}, {} categories>", c.getHeader(),
                               c.getSize(), c.getCategories().size());
        });

    py::class_<DataFrame, std::shared_ptr<DataFrame>> dataframe(m, "DataFrame");
    dataframe.def(py::init<std::uint32_t>(), py::arg("size") = 0)
        .def_property_readonly("cols", &DataFrame::getNumberOfColumns)
        .def_property_readonly("rows", &DataFrame::getNumberOfRows)
        .def("indexcol", [](DataFrame& d) { return d.getIndexColumn(); })
        .def("column", [](DataFrame& self, size_t index) { return self.getColumn(index); })
        .def("addColumnFromBuffer", &DataFrame::addColumnFromBuffer)
        .def("addCategoricalColumn", &DataFrame::addCategoricalColumn, py::arg("header"),
             py::arg("size") = 0)
        .def("getRow", &DataFrame::getDataItem, py::arg("index"), py::arg("asString") = false)

        .def("updateIndex", [](DataFrame& d) { d.updateIndexBuffer(); })

        // interface for operator[]
        .def("__getitem__",
             [](const DataFrame& d, size_t i) {
                 if (i >= d.getNumberOfColumns()) throw py::index_error();
                 return *(d.begin() + i);
             },
             py::return_value_policy::reference_internal)
        // sequence protocol operations
        .def("__iter__", [](const DataFrame& d) { return py::make_iterator(d.begin(), d.end()); },
             py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */)

        .def("__repr__", [](const DataFrame& d) {
            std::string str = fmt::format("<DataFrame: {} column(s), {} rows",
                                          d.getNumberOfColumns(), d.getNumberOfRows());
            size_t i = 0;
            for (auto c : d) {
                ++i;
                str += fmt::format("\n   {:>3}: '{}', {}, {}", i, c->getHeader(), c->getSize(),
                                   c->getBuffer()->getDataFormat()->getString());
            }
            return str + ">";
        });

    util::for_each_type<Scalars>{}(DataFrameAddColumnReg{}, dataframe);

    m.def("createDataFrame", createDataFrame, py::arg("exampleRows"),
          py::arg("colheaders") = std::vector<std::string>{},
          R"delim(
            Create a new DataFrame by guessing the column types from a number of rows.

            Parameters
            ----------
            exampleRows     Rows for guessing data type of each column.
            colHeaders      Name of each column. If none are given, "Column 1", "Column 2", ... is used
        )delim");

    exposeStandardDataPorts<DataFrame>(m, "DataFrame");
}

}  // namespace inviwo
<commit_msg>DataFramePython: exposed DataFrame joins<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2019-2020 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <ivwdataframe/pydataframe.h>

#include <warn/push>
#include <warn/ignore/shadow>
#include <pybind11/functional.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <warn/pop>

#include <inviwo/dataframe/datastructures/column.h>
#include <inviwo/dataframe/datastructures/dataframe.h>
#include <inviwo/dataframe/datastructures/datapoint.h>
#include <inviwo/dataframe/util/dataframeutils.h>

#include <inviwo/core/util/defaultvalues.h>
#include <inviwo/core/datastructures/buffer/buffer.h>
#include <modules/python3/pyportutils.h>

#include <fmt/format.h>

namespace py = pybind11;

namespace inviwo {

namespace {

struct DataFrameAddColumnReg {
    template <typename T>
    auto operator()(py::class_<DataFrame, std::shared_ptr<DataFrame>>& d) {
        auto classname = Defaultvalues<T>::getName();

        d.def(
            fmt::format("add{}Column", classname).c_str(),
            [](DataFrame& d, const std::string& header, const size_t size = 0) {
                return d.addColumn<T>(header, size);
            },
            py::arg("header"), py::arg("size") = 0);

        d.def(
            fmt::format("add{}Column", classname).c_str(),
            [](DataFrame& d, std::string header, std::vector<T> data) {
                return d.addColumn(std::move(header), std::move(data));
            },
            py::arg("header"), py::arg("data"));
    }
};

struct DataPointReg {
    template <typename T>
    auto operator()(pybind11::module& m) {
        using D = DataPoint<T>;
        auto classname = Defaultvalues<T>::getName() + "DataPoint";

        py::class_<D, DataPointBase, std::shared_ptr<D>> data(m, classname.c_str());
        data.def_property_readonly("data", &D::getData)
            .def_property_readonly("str", &D::toString)
            .def("__repr__",
                 [classname](D& p) { return fmt::format("<{}: '{}'>", classname, p.toString()); });
    }
};

struct TemplateColumnReg {
    template <typename T>
    auto operator()(pybind11::module& m) {
        using C = TemplateColumn<T>;
        auto classname = Defaultvalues<T>::getName() + "Column";

        py::class_<C, Column, std::shared_ptr<C>> col(m, classname.c_str());
        col.def_property_readonly("buffer", [](C& c) { return c.getTypedBuffer(); })
            .def(py::init<const std::string&>())
            .def("add", py::overload_cast<const T&>(&C::add))
            .def("add", py::overload_cast<const std::string&>(&C::add))
            .def("append", [](C& c, C& src) { c.append(src); })
            .def("set", &C::set)
            .def(
                "get",
                [](const C& c, size_t i) {
                    if (i >= c.getSize()) throw py::index_error();
                    return c.get(i);
                },
                py::arg("i"))
            .def(
                "get",
                [](const C& c, size_t i, bool asString) {
                    if (i >= c.getSize()) throw py::index_error();
                    return c.get(i, asString);
                },
                py::arg("i"), py::arg("asString"))
            .def("__repr__", [classname](C& c) {
                return fmt::format("<{}: '{}', {}, {}>", classname, c.getHeader(), c.getSize(),
                                   c.getBuffer()->getDataFormat()->getString());
            });
    }
};

}  // namespace

void exposeDataFrame(pybind11::module& m) {
    py::class_<DataPointBase, std::shared_ptr<DataPointBase>>(m, "DataPointBase")
        .def("__repr__",
             [](DataPointBase& p) { return fmt::format("<DataPoint: '{}'>", p.toString()); });

    py::class_<Column, std::shared_ptr<Column>>(m, "Column")
        .def_property("header", &Column::getHeader, &Column::setHeader)
        .def_property_readonly("buffer", [](Column& self) { return self.getBuffer(); })
        .def_property_readonly("size", &Column::getSize)
        .def("__repr__", [](Column& c) {
            return fmt::format("<Column: '{}', {}, {}>", c.getHeader(), c.getSize(),
                               c.getBuffer()->getDataFormat()->getString());
        });

    using Scalars = std::tuple<float, double, int, glm::i64, size_t, std::uint32_t>;
    util::for_each_type<Scalars>{}(DataPointReg{}, m);
    util::for_each_type<Scalars>{}(TemplateColumnReg{}, m);

    py::class_<CategoricalColumn, TemplateColumn<std::uint32_t>,
               std::shared_ptr<CategoricalColumn>>(m, "CategoricalColumn")
        .def(py::init<const std::string&>())
        .def_property_readonly("categories", &CategoricalColumn::getCategories,
                               py::return_value_policy::copy)
        .def("add", [](CategoricalColumn& c, const std::string& str) { c.add(str); })
        .def("append", [](CategoricalColumn& c, CategoricalColumn& src) { c.append(src); })
        .def("set", [](CategoricalColumn& c, size_t idx, const std::uint32_t& v) { c.set(idx, v); })
        .def("set", py::overload_cast<size_t, const std::string&>(&CategoricalColumn::set))
        .def(
            "get",
            [](const CategoricalColumn& c, size_t i, bool asString) {
                if (i >= c.getSize()) throw py::index_error();
                return c.get(i, asString);
            },
            py::arg("i"), py::arg("asString") = true)
        .def("__repr__", [](CategoricalColumn& c) {
            return fmt::format("<CategoricalColumn: '{}', {}, {} categories>", c.getHeader(),
                               c.getSize(), c.getCategories().size());
        });

    py::class_<DataFrame, std::shared_ptr<DataFrame>> dataframe(m, "DataFrame");
    dataframe.def(py::init<std::uint32_t>(), py::arg("size") = 0)
        .def_property_readonly("cols", &DataFrame::getNumberOfColumns)
        .def_property_readonly("rows", &DataFrame::getNumberOfRows)
        .def("indexcol", [](DataFrame& d) { return d.getIndexColumn(); })
        .def("column", [](DataFrame& self, size_t index) { return self.getColumn(index); })
        .def("addColumnFromBuffer", &DataFrame::addColumnFromBuffer)
        .def("addCategoricalColumn", &DataFrame::addCategoricalColumn, py::arg("header"),
             py::arg("size") = 0)
        .def("getRow", &DataFrame::getDataItem, py::arg("index"), py::arg("asString") = false)

        .def("updateIndex", [](DataFrame& d) { d.updateIndexBuffer(); })

        // interface for operator[]
        .def(
            "__getitem__",
            [](const DataFrame& d, size_t i) {
                if (i >= d.getNumberOfColumns()) throw py::index_error();
                return *(d.begin() + i);
            },
            py::return_value_policy::reference_internal)
        // sequence protocol operations
        .def(
            "__iter__", [](const DataFrame& d) { return py::make_iterator(d.begin(), d.end()); },
            py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */)

        .def("__repr__", [](const DataFrame& d) {
            std::string str = fmt::format("<DataFrame: {} column(s), {} rows",
                                          d.getNumberOfColumns(), d.getNumberOfRows());
            size_t i = 0;
            for (auto c : d) {
                ++i;
                str += fmt::format("\n   {:>3}: '{}', {}, {}", i, c->getHeader(), c->getSize(),
                                   c->getBuffer()->getDataFormat()->getString());
            }
            return str + ">";
        });

    util::for_each_type<Scalars>{}(DataFrameAddColumnReg{}, dataframe);

    m.def("createDataFrame", createDataFrame, py::arg("exampleRows"),
          py::arg("colheaders") = std::vector<std::string>{},
          R"delim(
Create a new DataFrame by guessing the column types from a number of rows.

Parameters
----------
exampleRows     Rows for guessing data type of each column.
colHeaders      Name of each column. If none are given, "Column 1", "Column 2", ... is used
)delim")
        .def("appendColumns", dataframeutils::appendColumns, py::arg("left"), py::arg("right"),
             py::arg("ignoreduplicates") = false, py::arg("fillmissingrows") = false,
             R"delim(
Create a new DataFrame by appending the columns of DataFrame right to DataFrame left

Parameters
----------
ignoreduplicates   duplicate columns, i.e. same column header, are ignored if true
fillmissingrows    if true, missing rows in either DataFrame are filled with 0 or
                   "undefined" (for categorical columns)
)delim")
        .def("appendRows", dataframeutils::appendRows, py::arg("top"), py::arg("bottom"),
             py::arg("matchbyname") = false,
             R"delim(
Create a new DataFrame by appending the rows of DataFrame bottom to DataFrame top

Parameters
----------
matchByName    if true, column headers are used for matching columns. Otherwise columns
               are matched by order (default)
)delim")
        .def("innerJoin", dataframeutils::innerJoin, py::arg("left"), py::arg("right"),
             py::arg("keycolumn") = "index",
             R"delim(
Create a new DataFrame by using an inner join of DataFrame left and DataFrame right.
That is only rows with matching keys are kept.

It is assumed that the entries in the key columns are unique. Otherwise results are undefined.

Parameters
----------
keycolumn    header of the column used as key for the join operation (default: index column)
)delim");

    exposeStandardDataPorts<DataFrame>(m, "DataFrame");
}

}  // namespace inviwo
<|endoftext|>


<commit_before>#include <wayfire/singleton-plugin.hpp>
#include <wayfire/view.hpp>
#include <wayfire/matcher.hpp>
#include <wayfire/workspace-manager.hpp>
#include <wayfire/output.hpp>
#include <wayfire/signal-definitions.hpp>

#include "deco-subsurface.hpp"

struct wayfire_decoration_global_cleanup_t
{
    ~wayfire_decoration_global_cleanup_t()
    {
        for (auto view : wf::get_core().get_all_views())
        {
            deinit_view(view);
        }
    }
};

class wayfire_decoration :
    public wf::singleton_plugin_t<wayfire_decoration_global_cleanup_t, true>
{
    wf::view_matcher_t ignore_views{"decoration/ignore_views"};

    wf::signal_connection_t view_updated{
        [=] (wf::signal_data_t *data)
        {
            update_view_decoration(get_signaled_view(data));
        }
    };

  public:
    void init() override
    {
        singleton_plugin_t::init();
        grab_interface->name = "simple-decoration";
        grab_interface->capabilities = wf::CAPABILITY_VIEW_DECORATOR;

        output->connect_signal("view-mapped", &view_updated);
        output->connect_signal("view-decoration-state-updated", &view_updated);
    }

    /**
     * Uses view_matcher_t to match whether the given view needs to be
     * ignored for decoration
     *
     * @param view The view to match
     * @return Whether the given view should be decorated?
     */
    bool ignore_decoration_of_view(wayfire_view view)
    {
        return ignore_views.matches(view);
    }

    wf::wl_idle_call idle_deactivate;
    void update_view_decoration(wayfire_view view)
    {
        if (view->should_be_decorated() && !ignore_decoration_of_view(view))
        {
            if (output->activate_plugin(grab_interface))
            {
                init_view(view);
                idle_deactivate.run_once([this] ()
                {
                    output->deactivate_plugin(grab_interface);
                });
            }
        } else
        {
            deinit_view(view);
        }
    }

    void fini() override
    {
        for (auto& view : output->workspace->get_views_in_layer(wf::ALL_LAYERS))
        {
            deinit_view(view);
        }

        singleton_plugin_t::fini();
    }
};

DECLARE_WAYFIRE_PLUGIN(wayfire_decoration);
<commit_msg>decoration: Add decorations to views on init<commit_after>#include <wayfire/singleton-plugin.hpp>
#include <wayfire/view.hpp>
#include <wayfire/matcher.hpp>
#include <wayfire/workspace-manager.hpp>
#include <wayfire/output.hpp>
#include <wayfire/signal-definitions.hpp>

#include "deco-subsurface.hpp"

struct wayfire_decoration_global_cleanup_t
{
    ~wayfire_decoration_global_cleanup_t()
    {
        for (auto view : wf::get_core().get_all_views())
        {
            deinit_view(view);
        }
    }
};

class wayfire_decoration :
    public wf::singleton_plugin_t<wayfire_decoration_global_cleanup_t, true>
{
    wf::view_matcher_t ignore_views{"decoration/ignore_views"};

    wf::signal_connection_t view_updated{
        [=] (wf::signal_data_t *data)
        {
            update_view_decoration(get_signaled_view(data));
        }
    };

  public:
    void init() override
    {
        singleton_plugin_t::init();
        grab_interface->name = "simple-decoration";
        grab_interface->capabilities = wf::CAPABILITY_VIEW_DECORATOR;

        output->connect_signal("view-mapped", &view_updated);
        output->connect_signal("view-decoration-state-updated", &view_updated);
        for (auto& view :
             output->workspace->get_views_in_layer(wf::ALL_LAYERS))
        {
            update_view_decoration(view);
        }
    }

    /**
     * Uses view_matcher_t to match whether the given view needs to be
     * ignored for decoration
     *
     * @param view The view to match
     * @return Whether the given view should be decorated?
     */
    bool ignore_decoration_of_view(wayfire_view view)
    {
        return ignore_views.matches(view);
    }

    wf::wl_idle_call idle_deactivate;
    void update_view_decoration(wayfire_view view)
    {
        if (view->should_be_decorated() && !ignore_decoration_of_view(view))
        {
            if (output->activate_plugin(grab_interface))
            {
                init_view(view);
                idle_deactivate.run_once([this] ()
                {
                    output->deactivate_plugin(grab_interface);
                });
            }
        } else
        {
            deinit_view(view);
        }
    }

    void fini() override
    {
        for (auto& view : output->workspace->get_views_in_layer(wf::ALL_LAYERS))
        {
            deinit_view(view);
        }

        singleton_plugin_t::fini();
    }
};

DECLARE_WAYFIRE_PLUGIN(wayfire_decoration);
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/objects/hexdump.h>
#include <vespa/vespalib/test/insertion_operators.h>
#include <ostream>

using vespalib::nbostream;
using ExpBuffer = std::vector<uint8_t>;

namespace std
{

bool operator==(const std::vector<uint8_t> &exp, const nbostream &stream)
{
    return ((exp.size() == stream.size()) &&
            (memcmp(&exp[0], stream.peek(), exp.size()) == 0));
}

std::ostream &operator<<(std::ostream &out, const std::vector<uint8_t> &rhs)
{
    out << vespalib::HexDump(&rhs[0], rhs.size());
    return out;
}

template <typename T, typename U>
std::ostream &operator<<(std::ostream &out, const std::pair<T, U> &rhs)
{
    out << "{ " << rhs.first << ", " << rhs.second << " }";
    return out;
}

template <typename T>
std::ostream &
operator<<(std::ostream &os, const vespalib::Array<T> &set)
{
    os << "{";
    bool first = true;
    for (const auto &entry : set) {
        if (!first) {
            os << ",";
        }
        os << entry;
        first = false;
    }
    os << "}";
    return os;
}

} // namespace std

struct Fixture
{
    nbostream _stream;

    template <typename T>
    void
    assertSerialize(const ExpBuffer &exp, const T &val)
    {
        _stream << val;
        EXPECT_EQUAL(exp, _stream);
        T checkVal = T();
        _stream >> checkVal;
        EXPECT_EQUAL(val, checkVal);
    }
};

TEST_F("test serializing 64-bit signed integers", Fixture)
{
    int64_t val = 0x0123456789ABCDEF;
    f.assertSerialize({ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, val);
}

TEST_F("test serializing 64-bit unsigned integers", Fixture)
{
    uint64_t val = 0x0123456789ABCDEF;
    f.assertSerialize({ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, val);
}

TEST_F("test serializing 32-bit signed integers", Fixture)
{
    int32_t val = 0x01234567;
    f.assertSerialize({ 0x01, 0x23, 0x45, 0x67 }, val);
}

TEST_F("test serializing 32-bit unsigned integers", Fixture)
{
    uint32_t val = 0x01234567;
    f.assertSerialize({ 0x01, 0x23, 0x45, 0x67 }, val);
}

TEST_F("test serializing 16-bit signed integers", Fixture)
{
    int16_t val = 0x0123;
    f.assertSerialize({ 0x01, 0x23 }, val);
}

TEST_F("test serializing 16-bit unsigned integers", Fixture)
{
    uint16_t val = 0x0123;
    f.assertSerialize({ 0x01, 0x23 }, val);
}

TEST_F("test serializing 8-bit signed integers", Fixture)
{
    int8_t val = 0x23;
    f.assertSerialize({ 0x23 }, val);
}

TEST_F("test serializing 8-bit unsigned integers", Fixture)
{
    uint8_t val = 0x23;
    f.assertSerialize({ 0x23 }, val);
}

TEST_F("test serializing char", Fixture)
{
    char val('A');
    f.assertSerialize({ 0x41 }, val);
}

TEST_F("test serializing bool", Fixture)
{
    bool myfalse = false;
    bool mytrue = true;
    ExpBuffer exp({ 0x00, 0x01 });
    f._stream << myfalse << mytrue;
    EXPECT_EQUAL(exp, f._stream);
    bool checkFalse = true;
    bool checkTrue = false;
    f._stream >> checkFalse >> checkTrue;
    EXPECT_FALSE(checkFalse);
    EXPECT_TRUE(checkTrue);
}

TEST_F("test serializing double", Fixture)
{
    double val = 1.5;
    f.assertSerialize({ 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, val);
}

TEST_F("test serializing float", Fixture)
{
    float val = -1.5;
    f.assertSerialize({ 0xBF, 0xC0, 0x00, 0x00 }, val);
}

TEST_F("Test serializing c string", Fixture)
{
    const char *cstr = "Hello";
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    f._stream << cstr;
    EXPECT_EQUAL(exp, f._stream);
}

TEST_F("Test serializing stringref", Fixture)
{
    vespalib::stringref val("Hello");
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    f._stream << val;
    EXPECT_EQUAL(exp, f._stream);
}

TEST_F("Test serializing std::string", Fixture)
{
    std::string val("Hello");
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    f.assertSerialize(exp, val);
}

TEST_F("Test serializing vespalib::string", Fixture)
{
    vespalib::string val("Hello");
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    f.assertSerialize(exp, val);
}

TEST_F("Test serializing vespalib::Array", Fixture)
{
    vespalib::Array<int16_t> val;
    val.resize(2);
    val[0] = 0x0123;
    val[1] = 0x4567;
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x02, 0x01, 0x23, 0x45, 0x67 });
    f.assertSerialize(exp, val);
}

TEST_F("Test serializing std::vector", Fixture)
{
    std::vector<int16_t> val({ 0x0123, 0x4567 });
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x02, 0x01, 0x23, 0x45, 0x67 });
    f.assertSerialize(exp, val);
}

TEST_F("Test serializing std::pair", Fixture)
{
    std::pair<int16_t, int16_t> val({ 0x0123, 0x4567 });
    ExpBuffer exp({ 0x01, 0x23, 0x45, 0x67 });
    f.assertSerialize(exp, val);
}

TEST_F("Test saveVector", Fixture)
{
    std::vector<int16_t> val({ 0x0123, 0x4567 });
    val.reserve(16);
    ExpBuffer exp({        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
                           0x01, 0x23, 0x45, 0x67 });
    f._stream.saveVector(val);
    EXPECT_EQUAL(exp, f._stream);
    std::vector<int16_t> checkVal;
    f._stream.restoreVector(checkVal);
    EXPECT_EQUAL(val, checkVal);
    EXPECT_EQUAL(val.capacity(), checkVal.capacity());
}

TEST_F("Test write", Fixture)
{
    f._stream.write("Hello", 5);
    ExpBuffer exp({ 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    EXPECT_EQUAL(exp, f._stream);
    EXPECT_EQUAL(5u, f._stream.size());
    ExpBuffer rval(5);
    f._stream.read(&rval[0], 5);
    EXPECT_EQUAL(exp, rval);
}

TEST_F("Test putInt1_4", Fixture)
{
    f._stream.putInt1_4Bytes(5);
    EXPECT_EQUAL(ExpBuffer({ 0x05 }), f._stream);
    uint32_t checkInt = f._stream.getInt1_4Bytes();
    EXPECT_EQUAL(5u, checkInt);
    EXPECT_EQUAL(0u, f._stream.size());
    f._stream.clear();
    f._stream.putInt1_4Bytes(1000);
    EXPECT_EQUAL(ExpBuffer({ 0x80, 0x00, 0x03, 0xe8 }), f._stream);
    checkInt = f._stream.getInt1_4Bytes();
    EXPECT_EQUAL(1000u, checkInt);
    EXPECT_EQUAL(0u, f._stream.size());
}

TEST_F("Test writeSmallString", Fixture)
{
    f._stream.writeSmallString("Hello");
    ExpBuffer exp({ 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    EXPECT_EQUAL(exp, f._stream);
    vespalib::string checkString;
    f._stream.readSmallString(checkString);
    EXPECT_EQUAL("Hello", checkString);
    EXPECT_EQUAL(0u, f._stream.size());
}

TEST_MAIN() { TEST_RUN_ALL(); }
<commit_msg>Unbreak factory (vespalib)<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/objects/hexdump.h>
#include <vespa/vespalib/test/insertion_operators.h>
#include <ostream>

using vespalib::nbostream;
using ExpBuffer = std::vector<uint8_t>;

namespace std
{

bool operator==(const std::vector<uint8_t> &exp, const nbostream &stream)
{
    return ((exp.size() == stream.size()) &&
            (memcmp(&exp[0], stream.peek(), exp.size()) == 0));
}

std::ostream &operator<<(std::ostream &out, const std::vector<uint8_t> &rhs)
{
    out << vespalib::HexDump(&rhs[0], rhs.size());
    return out;
}

template <typename T>
std::ostream &
operator<<(std::ostream &os, const vespalib::Array<T> &set)
{
    os << "{";
    bool first = true;
    for (const auto &entry : set) {
        if (!first) {
            os << ",";
        }
        os << entry;
        first = false;
    }
    os << "}";
    return os;
}

} // namespace std

struct Fixture
{
    nbostream _stream;

    template <typename T>
    void
    assertSerialize(const ExpBuffer &exp, const T &val)
    {
        _stream << val;
        EXPECT_EQUAL(exp, _stream);
        T checkVal = T();
        _stream >> checkVal;
        EXPECT_EQUAL(val, checkVal);
    }
};

TEST_F("test serializing 64-bit signed integers", Fixture)
{
    int64_t val = 0x0123456789ABCDEF;
    f.assertSerialize({ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, val);
}

TEST_F("test serializing 64-bit unsigned integers", Fixture)
{
    uint64_t val = 0x0123456789ABCDEF;
    f.assertSerialize({ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, val);
}

TEST_F("test serializing 32-bit signed integers", Fixture)
{
    int32_t val = 0x01234567;
    f.assertSerialize({ 0x01, 0x23, 0x45, 0x67 }, val);
}

TEST_F("test serializing 32-bit unsigned integers", Fixture)
{
    uint32_t val = 0x01234567;
    f.assertSerialize({ 0x01, 0x23, 0x45, 0x67 }, val);
}

TEST_F("test serializing 16-bit signed integers", Fixture)
{
    int16_t val = 0x0123;
    f.assertSerialize({ 0x01, 0x23 }, val);
}

TEST_F("test serializing 16-bit unsigned integers", Fixture)
{
    uint16_t val = 0x0123;
    f.assertSerialize({ 0x01, 0x23 }, val);
}

TEST_F("test serializing 8-bit signed integers", Fixture)
{
    int8_t val = 0x23;
    f.assertSerialize({ 0x23 }, val);
}

TEST_F("test serializing 8-bit unsigned integers", Fixture)
{
    uint8_t val = 0x23;
    f.assertSerialize({ 0x23 }, val);
}

TEST_F("test serializing char", Fixture)
{
    char val('A');
    f.assertSerialize({ 0x41 }, val);
}

TEST_F("test serializing bool", Fixture)
{
    bool myfalse = false;
    bool mytrue = true;
    ExpBuffer exp({ 0x00, 0x01 });
    f._stream << myfalse << mytrue;
    EXPECT_EQUAL(exp, f._stream);
    bool checkFalse = true;
    bool checkTrue = false;
    f._stream >> checkFalse >> checkTrue;
    EXPECT_FALSE(checkFalse);
    EXPECT_TRUE(checkTrue);
}

TEST_F("test serializing double", Fixture)
{
    double val = 1.5;
    f.assertSerialize({ 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, val);
}

TEST_F("test serializing float", Fixture)
{
    float val = -1.5;
    f.assertSerialize({ 0xBF, 0xC0, 0x00, 0x00 }, val);
}

TEST_F("Test serializing c string", Fixture)
{
    const char *cstr = "Hello";
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    f._stream << cstr;
    EXPECT_EQUAL(exp, f._stream);
}

TEST_F("Test serializing stringref", Fixture)
{
    vespalib::stringref val("Hello");
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    f._stream << val;
    EXPECT_EQUAL(exp, f._stream);
}

TEST_F("Test serializing std::string", Fixture)
{
    std::string val("Hello");
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    f.assertSerialize(exp, val);
}

TEST_F("Test serializing vespalib::string", Fixture)
{
    vespalib::string val("Hello");
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    f.assertSerialize(exp, val);
}

TEST_F("Test serializing vespalib::Array", Fixture)
{
    vespalib::Array<int16_t> val;
    val.resize(2);
    val[0] = 0x0123;
    val[1] = 0x4567;
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x02, 0x01, 0x23, 0x45, 0x67 });
    f.assertSerialize(exp, val);
}

TEST_F("Test serializing std::vector", Fixture)
{
    std::vector<int16_t> val({ 0x0123, 0x4567 });
    ExpBuffer exp({ 0x00, 0x00, 0x00, 0x02, 0x01, 0x23, 0x45, 0x67 });
    f.assertSerialize(exp, val);
}

TEST_F("Test serializing std::pair", Fixture)
{
    std::pair<int16_t, int16_t> val({ 0x0123, 0x4567 });
    ExpBuffer exp({ 0x01, 0x23, 0x45, 0x67 });
    f.assertSerialize(exp, val);
}

TEST_F("Test saveVector", Fixture)
{
    std::vector<int16_t> val({ 0x0123, 0x4567 });
    val.reserve(16);
    ExpBuffer exp({        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
                           0x01, 0x23, 0x45, 0x67 });
    f._stream.saveVector(val);
    EXPECT_EQUAL(exp, f._stream);
    std::vector<int16_t> checkVal;
    f._stream.restoreVector(checkVal);
    EXPECT_EQUAL(val, checkVal);
    EXPECT_EQUAL(val.capacity(), checkVal.capacity());
}

TEST_F("Test write", Fixture)
{
    f._stream.write("Hello", 5);
    ExpBuffer exp({ 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    EXPECT_EQUAL(exp, f._stream);
    EXPECT_EQUAL(5u, f._stream.size());
    ExpBuffer rval(5);
    f._stream.read(&rval[0], 5);
    EXPECT_EQUAL(exp, rval);
}

TEST_F("Test putInt1_4", Fixture)
{
    f._stream.putInt1_4Bytes(5);
    EXPECT_EQUAL(ExpBuffer({ 0x05 }), f._stream);
    uint32_t checkInt = f._stream.getInt1_4Bytes();
    EXPECT_EQUAL(5u, checkInt);
    EXPECT_EQUAL(0u, f._stream.size());
    f._stream.clear();
    f._stream.putInt1_4Bytes(1000);
    EXPECT_EQUAL(ExpBuffer({ 0x80, 0x00, 0x03, 0xe8 }), f._stream);
    checkInt = f._stream.getInt1_4Bytes();
    EXPECT_EQUAL(1000u, checkInt);
    EXPECT_EQUAL(0u, f._stream.size());
}

TEST_F("Test writeSmallString", Fixture)
{
    f._stream.writeSmallString("Hello");
    ExpBuffer exp({ 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f });
    EXPECT_EQUAL(exp, f._stream);
    vespalib::string checkString;
    f._stream.readSmallString(checkString);
    EXPECT_EQUAL("Hello", checkString);
    EXPECT_EQUAL(0u, f._stream.size());
}

TEST_MAIN() { TEST_RUN_ALL(); }
<|endoftext|>


<commit_before>#include <errno.h>
#include <stdlib.h>
#include <getopt.h>
#include <boost/foreach.hpp>
#include <boost/asio/ip/address.hpp>

#include <libwatcher/connectivityMessage.h>
#include "logger.h"
#include "client.h"
#include "sendMessageHandler.h"

using namespace std;
using namespace watcher;
using namespace watcher::event;

void usage(const char *progName)
{
    fprintf(stderr, "Usage: %s -s|--servername server [-l|--logProps log.propertiesFile] [-f|--fromNode fromNodeAddr] nbr1 nbr2 ... nbrN\n", basename(progName));
    fprintf(stderr, "Where:\n");
    fprintf(stderr, "\tnbr1 nbr2 ... nbrN is a list of ip addresses that the node is connected to.\n");
    fprintf(stderr, "\tserver is the server address or hostname\n");
    fprintf(stderr, "\tfromNodeAddr is the address of the node the neighbors are attached to.\n");

    exit(1);
}

int main(int argc, char **argv)
{
    int c;
    char *serverName=NULL;
    char *logProps=NULL;
    boost::asio::ip::address_v4 fromNodeAddr;

    while (true)
    {
        int option_index = 0;
        static struct option long_options[] = {
            {"logProps", required_argument, 0, 'l'},
            {"servername", required_argument, 0, 's'},
            {"fromNode", required_argument, 0, 'f'},
            {0, 0, 0, 0}
        };

        c = getopt_long(argc, argv, "l:s:f:hH?", long_options, &option_index);

        if (c == -1)
            break;

        switch(c)
        {
            case 'l':
                logProps = strdup(optarg); // buffer overflow here. :)
                break;
            case 's':
                serverName = strdup(optarg);  // buffer overflow here :)
                break;
            case 'f':
                fromNodeAddr=boost::asio::ip::address_v4::from_string(optarg);
                break;
            case 'h':
            case 'H':
            case '?':
            default:
                usage(argv[0]);
                break;
        }
    }

    if (!serverName)
    {
        usage(argv[0]);
        if (serverName)
            free(serverName);
        if (logProps)
            free(logProps);
        exit(1);
    }

    //
    // Now do some actual work.
    //
    printf("Initializing logging system\n");
    LOAD_LOG_PROPS(logProps ? logProps : "sendMessage.log.properties");

    LOG_DEBUG("Args: server: " << serverName << " fromAddr: " << fromNodeAddr << " logProps: " << logProps);

    watcher::Client client(serverName);
    client.addMessageHandler(SendMessageHandler::create());
    printf("Connecting to %s and sending message.\n", serverName);

    ConnectivityMessagePtr cm(new ConnectivityMessage);
    if(fromNodeAddr!=boost::asio::ip::address_v4())
    {
        LOG_DEBUG("Setting from address on message to " << fromNodeAddr);
        cm->fromNodeID=fromNodeAddr;
    }

    for(int i=optind; i<argc; i++)
    {
        boost::system::error_code ec;
        NodeIdentifier addr=NodeIdentifier::from_string(argv[i], ec);
        if(!ec)
            cm->neighbors.push_back(addr);
        else
            LOG_ERROR("Ignoring non address arguement: " << argv[i]);
    }

    LOG_DEBUG("Sending Message: " << *cm);

    if(!client.sendMessage(cm))
    {
        LOG_ERROR("Error sending gps message: " << *cm);
        free(serverName);
        if (logProps)
            free(logProps);
        TRACE_EXIT_RET(EXIT_FAILURE);
        return EXIT_FAILURE;
    }

    client.wait();

    free(serverName);
    if (logProps)
        free(logProps);

    TRACE_EXIT_RET(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

<commit_msg>Allow layer to be specified on the command line for sendConnectivityMesssage.<commit_after>#include <errno.h>
#include <stdlib.h>
#include <getopt.h>
#include <boost/foreach.hpp>
#include <boost/asio/ip/address.hpp>

#include <libwatcher/connectivityMessage.h>
#include "logger.h"
#include "client.h"
#include "sendMessageHandler.h"

using namespace std;
using namespace watcher;
using namespace watcher::event;

void usage(const char *progName)
{
    fprintf(stderr, "Usage: %s -s|--servername server [-l|--logProps log.propertiesFile] [-f|--fromNode fromNodeAddr] nbr1 nbr2 ... nbrN\n", basename(progName));
    fprintf(stderr, "Where:\n");
    fprintf(stderr, "\tnbr1 nbr2 ... nbrN is a list of ip addresses that the node is connected to.\n");
    fprintf(stderr, "\tserver is the server address or hostname\n");
    fprintf(stderr, "\tfromNodeAddr is the address of the node the neighbors are attached to.\n");

    exit(1);
}

int main(int argc, char **argv)
{
    int c;
    char *serverName=NULL;
    char *logProps=NULL;
    GUILayer layer(PHYSICAL_LAYER);
    boost::asio::ip::address_v4 fromNodeAddr;

    while (true)
    {
        int option_index = 0;
        static struct option long_options[] = {
            {"logProps", required_argument, 0, 'p'},
            {"servername", required_argument, 0, 's'},
            {"fromNode", required_argument, 0, 'f'},
            {"layer", required_argument, 0, 'l'},
            {0, 0, 0, 0}
        };

        c = getopt_long(argc, argv, "p:s:f:l:hH?", long_options, &option_index);

        if (c == -1)
            break;

        switch(c)
        {
            case 'p':
                logProps = strdup(optarg); // buffer overflow here. :)
                break;
            case 's':
                serverName = strdup(optarg);  // buffer overflow here :)
                break;
            case 'f':
                fromNodeAddr=boost::asio::ip::address_v4::from_string(optarg);
                break;
            case 'l':
                layer = strdup(optarg);
                break;
            case 'h':
            case 'H':
            case '?':
            default:
                usage(argv[0]);
                break;
        }
    }

    if (!serverName)
    {
        usage(argv[0]);
        if (serverName)
            free(serverName);
        if (logProps)
            free(logProps);
        exit(1);
    }

    //
    // Now do some actual work.
    //
    printf("Initializing logging system\n");
    LOAD_LOG_PROPS(logProps ? logProps : "sendMessage.log.properties");

    LOG_DEBUG("Args: server: " << serverName << " fromAddr: " << fromNodeAddr << " logProps: " << logProps);

    watcher::Client client(serverName);
    client.addMessageHandler(SendMessageHandler::create());
    printf("Connecting to %s and sending message.\n", serverName);

    ConnectivityMessagePtr cm(new ConnectivityMessage);
    if(fromNodeAddr!=boost::asio::ip::address_v4())
    {
        LOG_DEBUG("Setting from address on message to " << fromNodeAddr);
        cm->fromNodeID=fromNodeAddr;
    }
    cm->layer=layer;

    for(int i=optind; i<argc; i++)
    {
        boost::system::error_code ec;
        NodeIdentifier addr=NodeIdentifier::from_string(argv[i], ec);
        if(!ec)
            cm->neighbors.push_back(addr);
        else
            LOG_ERROR("Ignoring non address arguement: " << argv[i]);
    }

    LOG_DEBUG("Sending Message: " << *cm);

    if(!client.sendMessage(cm))
    {
        LOG_ERROR("Error sending gps message: " << *cm);
        free(serverName);
        if (logProps)
            free(logProps);
        TRACE_EXIT_RET(EXIT_FAILURE);
        return EXIT_FAILURE;
    }

    client.wait();

    free(serverName);
    if (logProps)
        free(logProps);

    TRACE_EXIT_RET(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "vie_autotest.h"

#include "base_primitives.h"
#include "general_primitives.h"
#include "tb_interfaces.h"
#include "vie_autotest_defines.h"
#include "video_capture_factory.h"

class BaseObserver : public webrtc::ViEBaseObserver {
 public:
  BaseObserver()
      : cpu_load_(0) {}

  virtual void PerformanceAlarm(const unsigned int cpu_load) {
    cpu_load_ = cpu_load;
  }
  unsigned int cpu_load_;
};

void ViEAutoTest::ViEBaseStandardTest() {
  // ***************************************************************
  // Begin create/initialize WebRTC Video Engine for testing
  // ***************************************************************

  TbInterfaces interfaces("ViEBaseStandardTest");

  // ***************************************************************
  // Engine ready. Set up the test case:
  // ***************************************************************
  int video_channel = -1;
  EXPECT_EQ(0, interfaces.base->CreateChannel(video_channel));

  webrtc::VideoCaptureModule* video_capture_module(NULL);
  const unsigned int kMaxDeviceNameLength = 128;
  char device_name[kMaxDeviceNameLength];
  memset(device_name, 0, kMaxDeviceNameLength);
  int capture_id;

  webrtc::ViEBase *base_interface = interfaces.base;
  webrtc::ViERender *render_interface = interfaces.render;
  webrtc::ViECapture *capture_interface = interfaces.capture;

  FindCaptureDeviceOnSystem(capture_interface,
                            device_name,
                            kMaxDeviceNameLength,
                            &capture_id,
                            &video_capture_module);

  EXPECT_EQ(0, capture_interface->ConnectCaptureDevice(capture_id,
                                                       video_channel));
  EXPECT_EQ(0, capture_interface->StartCapture(capture_id));

  ConfigureRtpRtcp(interfaces.rtp_rtcp, video_channel);

  EXPECT_EQ(0, render_interface->RegisterVideoRenderModule(*_vrm1));
  EXPECT_EQ(0, render_interface->RegisterVideoRenderModule(*_vrm2));

  RenderInWindow(render_interface, capture_id, _window1, 0);
  RenderInWindow(render_interface, video_channel, _window2, 1);

  // ***************************************************************
  // Run the actual test:
  // ***************************************************************
  ViETest::Log("You should shortly see a local preview from camera %s"
      " in window 1 and the remote video in window 2.", device_name);
  ::TestI420CallSetup(interfaces.codec, interfaces.video_engine,
                      base_interface, interfaces.network, video_channel,
                      device_name);

  // ***************************************************************
  // Testing finished. Tear down Video Engine
  // ***************************************************************
  EXPECT_EQ(0, capture_interface->StopCapture(capture_id));
  EXPECT_EQ(0, base_interface->StopReceive(video_channel));

  StopAndRemoveRenderers(base_interface, render_interface, video_channel,
                         capture_id);

  EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm1));
  EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm2));

  EXPECT_EQ(0, capture_interface->ReleaseCaptureDevice(capture_id));

  video_capture_module->Release();
  video_capture_module = NULL;

  EXPECT_EQ(0, base_interface->DeleteChannel(video_channel));
}

void ViEAutoTest::ViEBaseExtendedTest() {
  // Start with standard test
  ViEBaseAPITest();
  ViEBaseStandardTest();

    // ***************************************************************
    // Test BaseObserver
    // ***************************************************************
    // TODO(mflodman) Add test for base observer. Cpu load must be over 75%.
//    BaseObserver base_observer;
//    EXPECT_EQ(ptrViEBase->RegisterObserver(base_observer), 0);
//
//    AutoTestSleep(KAutoTestSleepTimeMs);
//
//    EXPECT_EQ(ptrViEBase->DeregisterObserver(), 0);
//    EXPECT_GT(base_observer.cpu_load, 0);
}

void ViEAutoTest::ViEBaseAPITest() {
  // ***************************************************************
  // Begin create/initialize WebRTC Video Engine for testing
  // ***************************************************************
  // Get the ViEBase API
  webrtc::ViEBase* ptrViEBase = webrtc::ViEBase::GetInterface(NULL);
  EXPECT_EQ(NULL, ptrViEBase) << "Should return null for a bad ViE pointer";

  webrtc::VideoEngine* ptrViE = webrtc::VideoEngine::Create();
  EXPECT_TRUE(NULL != ptrViE);

  std::string trace_file_path =
      ViETest::GetResultOutputPath() + "ViEBaseAPI_trace.txt";
  EXPECT_EQ(0, ptrViE->SetTraceFile(trace_file_path.c_str()));

  ptrViEBase = webrtc::ViEBase::GetInterface(ptrViE);
  EXPECT_TRUE(NULL != ptrViEBase);

  // ***************************************************************
  // Engine ready. Begin testing class
  // ***************************************************************
  char version[1024] = "";
  EXPECT_EQ(0, ptrViEBase->GetVersion(version));
  EXPECT_EQ(0, ptrViEBase->LastError());

  // Create without init
  int videoChannel = -1;
  EXPECT_NE(0, ptrViEBase->CreateChannel(videoChannel)) <<
      "Should fail since Init has not been called yet";
  EXPECT_EQ(0, ptrViEBase->Init());
  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel));

  int videoChannel2 = -1;
  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2));
  EXPECT_NE(videoChannel, videoChannel2) <<
      "Should allocate new number for independent channel";

  EXPECT_EQ(0, ptrViEBase->DeleteChannel(videoChannel2));

  EXPECT_EQ(-1, ptrViEBase->CreateChannel(videoChannel2, videoChannel + 1)) <<
      "Should fail since neither channel exists (the second must)";

  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2, videoChannel));

  // Test Voice Engine integration with Video Engine.
  webrtc::VoiceEngine* ptrVoE = NULL;
  webrtc::VoEBase* ptrVoEBase = NULL;
  int audioChannel = -1;

  ptrVoE = webrtc::VoiceEngine::Create();
  EXPECT_TRUE(NULL != ptrVoE);

  ptrVoEBase = webrtc::VoEBase::GetInterface(ptrVoE);
  EXPECT_TRUE(NULL != ptrVoEBase);
  EXPECT_EQ(0, ptrVoEBase->Init());

  audioChannel = ptrVoEBase->CreateChannel();
  EXPECT_NE(-1, audioChannel);

  // Connect before setting VoE.
  EXPECT_NE(0, ptrViEBase->ConnectAudioChannel(videoChannel, audioChannel)) <<
      "Should fail since Voice Engine is not set yet.";

  // Then do it right.
  EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(ptrVoE));
  EXPECT_EQ(0, ptrViEBase->ConnectAudioChannel(videoChannel, audioChannel));

  // ***************************************************************
  // Testing finished. Tear down Video Engine
  // ***************************************************************
  EXPECT_NE(0, ptrViEBase->DisconnectAudioChannel(videoChannel + 5)) <<
      "Should fail: disconnecting bogus channel";

  EXPECT_EQ(0, ptrViEBase->DisconnectAudioChannel(videoChannel));

  // Clean up voice engine
  EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(NULL));
  EXPECT_EQ(0, ptrVoEBase->Release());
  EXPECT_TRUE(webrtc::VoiceEngine::Delete(ptrVoE));

  webrtc::ViEBase* ptrViEBase2 = webrtc::ViEBase::GetInterface(ptrViE);
  EXPECT_TRUE(NULL != ptrViEBase2);

  EXPECT_EQ(1, ptrViEBase->Release()) << "There should be one interface left.";

  EXPECT_FALSE(webrtc::VideoEngine::Delete(ptrViE)) <<
      "Should fail since there are interfaces left.";

  EXPECT_EQ(0, ptrViEBase->Release());
  EXPECT_TRUE(webrtc::VideoEngine::Delete(ptrViE));
}
<commit_msg>nits<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "vie_autotest.h"

#include "base_primitives.h"
#include "general_primitives.h"
#include "tb_interfaces.h"
#include "vie_autotest_defines.h"
#include "video_capture_factory.h"

class BaseObserver : public webrtc::ViEBaseObserver {
 public:
  BaseObserver()
      : cpu_load_(0) {}

  virtual void PerformanceAlarm(const unsigned int cpu_load) {
    cpu_load_ = cpu_load;
  }
  unsigned int cpu_load_;
};

void ViEAutoTest::ViEBaseStandardTest() {
  // ***************************************************************
  // Begin create/initialize WebRTC Video Engine for testing
  // ***************************************************************

  TbInterfaces interfaces("ViEBaseStandardTest");

  // ***************************************************************
  // Engine ready. Set up the test case:
  // ***************************************************************
  int video_channel = -1;
  EXPECT_EQ(0, interfaces.base->CreateChannel(video_channel));

  webrtc::VideoCaptureModule* video_capture_module(NULL);
  const unsigned int kMaxDeviceNameLength = 128;
  char device_name[kMaxDeviceNameLength];
  memset(device_name, 0, kMaxDeviceNameLength);
  int capture_id;

  webrtc::ViEBase *base_interface = interfaces.base;
  webrtc::ViERender *render_interface = interfaces.render;
  webrtc::ViECapture *capture_interface = interfaces.capture;

  FindCaptureDeviceOnSystem(capture_interface,
                            device_name,
                            kMaxDeviceNameLength,
                            &capture_id,
                            &video_capture_module);

  EXPECT_EQ(0, capture_interface->ConnectCaptureDevice(capture_id,
                                                       video_channel));
  EXPECT_EQ(0, capture_interface->StartCapture(capture_id));

  ConfigureRtpRtcp(interfaces.rtp_rtcp, video_channel);

  EXPECT_EQ(0, render_interface->RegisterVideoRenderModule(*_vrm1));
  EXPECT_EQ(0, render_interface->RegisterVideoRenderModule(*_vrm2));

  RenderInWindow(render_interface, capture_id, _window1, 0);
  RenderInWindow(render_interface, video_channel, _window2, 1);

  // ***************************************************************
  // Run the actual test:
  // ***************************************************************
  ViETest::Log("You should shortly see a local preview from camera %s"
      " in window 1 and the remote video in window 2.", device_name);
  ::TestI420CallSetup(interfaces.codec, interfaces.video_engine,
                      base_interface, interfaces.network, video_channel,
                      device_name);

  // ***************************************************************
  // Testing finished. Tear down Video Engine
  // ***************************************************************
  EXPECT_EQ(0, capture_interface->StopCapture(capture_id));
  EXPECT_EQ(0, base_interface->StopReceive(video_channel));

  StopAndRemoveRenderers(base_interface, render_interface, video_channel,
                         capture_id);

  EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm1));
  EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm2));

  EXPECT_EQ(0, capture_interface->ReleaseCaptureDevice(capture_id));

  video_capture_module->Release();
  video_capture_module = NULL;

  EXPECT_EQ(0, base_interface->DeleteChannel(video_channel));
}

void ViEAutoTest::ViEBaseExtendedTest() {
  // Start with standard test
  ViEBaseAPITest();
  ViEBaseStandardTest();

    // ***************************************************************
    // Test BaseObserver
    // ***************************************************************
    // TODO(mflodman) Add test for base observer. Cpu load must be over 75%.
//    BaseObserver base_observer;
//    EXPECT_EQ(ptrViEBase->RegisterObserver(base_observer), 0);
//
//    AutoTestSleep(KAutoTestSleepTimeMs);
//
//    EXPECT_EQ(ptrViEBase->DeregisterObserver(), 0);
//    EXPECT_GT(base_observer.cpu_load, 0);
}

void ViEAutoTest::ViEBaseAPITest() {
  // ***************************************************************
  // Begin create/initialize WebRTC Video Engine for testing
  // ***************************************************************
  // Get the ViEBase API
  webrtc::ViEBase* ptrViEBase = webrtc::ViEBase::GetInterface(NULL);
  EXPECT_EQ(NULL, ptrViEBase) << "Should return null for a bad ViE pointer";

  webrtc::VideoEngine* ptrViE = webrtc::VideoEngine::Create();
  EXPECT_TRUE(NULL != ptrViE);

  std::string trace_file_path =
      ViETest::GetResultOutputPath() + "ViEBaseAPI_trace.txt";
  EXPECT_EQ(0, ptrViE->SetTraceFile(trace_file_path.c_str()));

  ptrViEBase = webrtc::ViEBase::GetInterface(ptrViE);
  EXPECT_TRUE(NULL != ptrViEBase);

  // ***************************************************************
  // Engine ready. Begin testing class
  // ***************************************************************
  char version[1024] = "";
  EXPECT_EQ(0, ptrViEBase->GetVersion(version));
  EXPECT_EQ(0, ptrViEBase->LastError());

  // Create without init
  int videoChannel = -1;
  EXPECT_NE(0, ptrViEBase->CreateChannel(videoChannel)) <<
      "Should fail since Init has not been called yet";
  EXPECT_EQ(0, ptrViEBase->Init());
  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel));

  int videoChannel2 = -1;
  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2));
  EXPECT_NE(videoChannel, videoChannel2) <<
      "Should allocate new number for independent channel";

  EXPECT_EQ(0, ptrViEBase->DeleteChannel(videoChannel2));

  EXPECT_EQ(-1, ptrViEBase->CreateChannel(videoChannel2, videoChannel + 1)) <<
      "Should fail since neither channel exists (the second must)";

  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2, videoChannel));

  // Test Voice Engine integration with Video Engine.
  webrtc::VoiceEngine* ptrVoE = NULL;
  webrtc::VoEBase* ptrVoEBase = NULL;
  int audioChannel = -1;

  ptrVoE = webrtc::VoiceEngine::Create();
  EXPECT_TRUE(NULL != ptrVoE);

  ptrVoEBase = webrtc::VoEBase::GetInterface(ptrVoE);
  EXPECT_TRUE(NULL != ptrVoEBase);
  EXPECT_EQ(0, ptrVoEBase->Init());

  audioChannel = ptrVoEBase->CreateChannel();
  EXPECT_NE(-1, audioChannel);

  // Connect before setting VoE.
  EXPECT_NE(0, ptrViEBase->ConnectAudioChannel(videoChannel, audioChannel)) <<
      "Should fail since Voice Engine is not set yet.";

  // Then do it right.
  EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(ptrVoE));
  EXPECT_EQ(0, ptrViEBase->ConnectAudioChannel(videoChannel, audioChannel));

  // ***************************************************************
  // Testing finished. Tear down Video Engine
  // ***************************************************************
  EXPECT_NE(0, ptrViEBase->DisconnectAudioChannel(videoChannel + 5)) <<
      "Should fail: disconnecting bogus channel";

  EXPECT_EQ(0, ptrViEBase->DisconnectAudioChannel(videoChannel));

  // Clean up voice engine
  EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(NULL));
  EXPECT_EQ(0, ptrVoEBase->Release());
  EXPECT_TRUE(webrtc::VoiceEngine::Delete(ptrVoE));

  webrtc::ViEBase* ptrViEBase2 = webrtc::ViEBase::GetInterface(ptrViE);
  EXPECT_TRUE(NULL != ptrViEBase2);

  EXPECT_EQ(1, ptrViEBase->Release()) << "There should be one interface left.";

  EXPECT_FALSE(webrtc::VideoEngine::Delete(ptrViE)) <<
      "Should fail since there are interfaces left.";

  EXPECT_EQ(0, ptrViEBase->Release());
  EXPECT_TRUE(webrtc::VideoEngine::Delete(ptrViE));
}
<|endoftext|>


<commit_before><commit_msg>loplugin:stringconstant: handle OUString+=OUString(literal)<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "PlatformWheelEvent.h"

#include <wx/defs.h>
#include <wx/event.h>

namespace WebCore {

PlatformWheelEvent::PlatformWheelEvent(const wxMouseEvent& event, const wxPoint& globalPoint)
    : m_position(event.GetPosition())
    , m_globalPosition(globalPoint)
    , m_shiftKey(event.ShiftDown())
    , m_ctrlKey(event.ControlDown())
    , m_altKey(event.AltDown())
    , m_metaKey(event.MetaDown()) // FIXME: We'll have to test other browsers
    , m_deltaX(0) // wx doesn't support horizontal mouse wheel scrolling
    , m_deltaY(event.GetWheelRotation() / event.GetWheelDelta())
    , m_isAccepted(false)
    , m_isContinuous(false)
    , m_continuousDeltaX(0)
    , m_continuousDeltaY(0)
{
    // FIXME: retrieve the user setting for the number of lines to scroll on each wheel event
    m_charsToScrollPerDelta = 1;
    m_linesToScrollPerDelta = 1;
    m_pageXScrollMode = false;
    m_pageYScrollMode = false;
}

}
<commit_msg>Fix wx bustage.<commit_after>/*
 * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "PlatformWheelEvent.h"

#include <wx/defs.h>
#include <wx/event.h>

namespace WebCore {

PlatformWheelEvent::PlatformWheelEvent(const wxMouseEvent& event, const wxPoint& globalPoint)
    : m_position(event.GetPosition())
    , m_globalPosition(globalPoint)
    , m_granularity(ScrollByLineWheelEvent)
    , m_shiftKey(event.ShiftDown())
    , m_ctrlKey(event.ControlDown())
    , m_altKey(event.AltDown())
    , m_metaKey(event.MetaDown()) // FIXME: We'll have to test other browsers
    , m_deltaX(0) // wx doesn't support horizontal mouse wheel scrolling
    , m_deltaY(event.GetWheelRotation() / event.GetWheelDelta())
    , m_isAccepted(false)
{
    // FIXME: retrieve the user setting for the number of lines to scroll on each wheel event
    m_deltaY *= horizontalLineMultiplier();
}

}
<|endoftext|>


<commit_before>/*
 * TableFlagFilter.cpp
 *
 * Copyright (C) 2020 by VISUS (University of Stuttgart)
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "TableFlagFilter.h"

#include "mmcore/param/EnumParam.h"
#include "mmcore/utility/log/Log.h"

using namespace megamol::stdplugin::datatools;
using namespace megamol::stdplugin::datatools::table;
using namespace megamol;

TableFlagFilter::TableFlagFilter()
    : core::Module()
    , tableInSlot("getDataIn", "Float table input")
    , flagStorageInSlot("readFlagStorage", "Flag storage read input")
    , tableOutSlot("getDataOut", "Float table output")
    , filterModeParam("filterMode", "filter mode")
    , tableInFrameCount(0)
    , tableInDataHash(0)
    , tableInColCount(0)
    , dataHash(0)
    , rowCount(0) {

    this->tableInSlot.SetCompatibleCall<TableDataCallDescription>();
    this->MakeSlotAvailable(&this->tableInSlot);

    this->flagStorageInSlot.SetCompatibleCall<core::FlagCallRead_GLDescription>();
    this->MakeSlotAvailable(&this->flagStorageInSlot);

    this->tableOutSlot.SetCallback(TableDataCall::ClassName(),
        TableDataCall::FunctionName(0),
        &TableFlagFilter::getData);
    this->tableOutSlot.SetCallback(TableDataCall::ClassName(),
        TableDataCall::FunctionName(1),
        &TableFlagFilter::getHash);
    this->MakeSlotAvailable(&this->tableOutSlot);

    auto* fmp = new core::param::EnumParam(FilterMode::FILTERED);
    fmp->SetTypePair(FilterMode::FILTERED, "Filtered");
    fmp->SetTypePair(FilterMode::SELECTED, "Selected");
    this->filterModeParam << fmp;
    this->MakeSlotAvailable(&this->filterModeParam);
}

TableFlagFilter::~TableFlagFilter() {
    this->Release();
}

bool TableFlagFilter::create() {
    return true;
}

void TableFlagFilter::release() {
}

bool TableFlagFilter::getData(core::Call &call) {
    if (!this->handleCall(call)) {
        return false;
    }

    auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
    tableOutCall->SetFrameCount(this->tableInFrameCount);
    tableOutCall->SetDataHash(this->dataHash);
    tableOutCall->Set(this->tableInColCount, this->rowCount, this->colInfos.data(), this->data.data());

    return true;
}

bool TableFlagFilter::getHash(core::Call &call) {
    if (!this->handleCall(call)) {
        return false;
    }

    auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
    tableOutCall->SetFrameCount(this->tableInFrameCount);
    tableOutCall->SetDataHash(this->dataHash);

    return true;
}

bool TableFlagFilter::handleCall(core::Call &call) {
    auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
    auto *tableInCall = this->tableInSlot.CallAs<TableDataCall>();
    auto *flagsInCall = this->flagStorageInSlot.CallAs<core::FlagCallRead_GL>();

    if (tableOutCall == nullptr) {
        return false;
    }

    if (tableInCall == nullptr) {
        megamol::core::utility::log::Log::DefaultLog.WriteMsg(
            megamol::core::utility::log::Log::LEVEL_ERROR, "TableFlagFilter requires a table!");
        return false;
    }

    if (flagsInCall == nullptr) {
        megamol::core::utility::log::Log::DefaultLog.WriteMsg(
            megamol::core::utility::log::Log::LEVEL_ERROR, "TableFlagFilter requires a flag storage!");
        return false;
    }

    tableInCall->SetFrameID(tableOutCall->GetFrameID());
    (*tableInCall)(1);
    (*tableInCall)(0);
    (*flagsInCall)(core::FlagCallRead_GL::CallGetData);

    if (this->tableInFrameCount != tableInCall->GetFrameCount() || this->tableInDataHash != tableInCall->DataHash() || flagsInCall->hasUpdate()) {
        megamol::core::utility::log::Log::DefaultLog.WriteMsg(megamol::core::utility::log::Log::LEVEL_INFO, "TableFlagFilter: Filter table.");

        this->dataHash++;

        this->tableInFrameCount = tableInCall->GetFrameCount();
        this->tableInDataHash = tableInCall->DataHash();
        this->tableInColCount = tableInCall->GetColumnsCount();
        size_t tableInRowCount = tableInCall->GetRowsCount();

        // download flags
        flagsInCall->getData()->validateFlagCount(tableInRowCount);
        auto flags = flagsInCall->getData()->flags;
        uint32_t *flagsData = new uint32_t[flags->getByteSize() / sizeof(uint32_t)];
        flags->bind();
        glGetBufferSubData(flags->getTarget(), 0, flags->getByteSize(), flagsData);

        // copy column infos
        this->colInfos.resize(this->tableInColCount);
        for (size_t i = 0; i < this->tableInColCount; ++i) {
            this->colInfos[i] = tableInCall->GetColumnsInfos()[i];
            this->colInfos[i].SetMinimumValue(std::numeric_limits<float>::max());
            this->colInfos[i].SetMaximumValue(std::numeric_limits<float>::lowest());
        }

        core::FlagStorage::FlagItemType testMask = core::FlagStorage::ENABLED | core::FlagStorage::FILTERED;
        core::FlagStorage::FlagItemType passMask = core::FlagStorage::ENABLED;;
        if (static_cast<FilterMode>(this->filterModeParam.Param<core::param::EnumParam>()->Value()) == FilterMode::SELECTED) {
            testMask = core::FlagStorage::ENABLED | core::FlagStorage::SELECTED | core::FlagStorage::FILTERED;
            passMask = core::FlagStorage::ENABLED | core::FlagStorage::SELECTED;
        }

        // Resize data to size of input table. With this we only need to allocate memory once.
        this->data.resize(this->tableInColCount * tableInRowCount);
        this->rowCount = 0;

        const float *tableInData = tableInCall->GetData();
        for (size_t r = 0; r < tableInRowCount; ++r) {
            if ((flagsData[r] & testMask) == passMask) {
                for (size_t c = 0; c < this->tableInColCount; ++c) {
                    float val = tableInData[this->tableInColCount * r + c];
                    this->data[this->tableInColCount * this->rowCount + c] = val;
                    if (val < this->colInfos[c].MinimumValue()) {
                        this->colInfos[c].SetMinimumValue(val);
                    }
                    if (val > this->colInfos[c].MaximumValue()) {
                        this->colInfos[c].SetMaximumValue(val);
                    }
                }
                this->rowCount++;
            }
        }

        // delete memory of filtered rows
        this->data.resize(this->tableInColCount * this->rowCount);

        delete[] flagsData;

        // nicer output
        if (this->rowCount == 0) {
            for (size_t i = 0; i < this->tableInColCount; ++i) {
                this->colInfos[i].SetMinimumValue(0.0);
                this->colInfos[i].SetMaximumValue(0.0);
            }
        }
    }

    return true;
}
<commit_msg>less verbose table flag filter<commit_after>/*
 * TableFlagFilter.cpp
 *
 * Copyright (C) 2020 by VISUS (University of Stuttgart)
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "TableFlagFilter.h"

#include "mmcore/param/EnumParam.h"
#include "mmcore/utility/log/Log.h"

using namespace megamol::stdplugin::datatools;
using namespace megamol::stdplugin::datatools::table;
using namespace megamol;

TableFlagFilter::TableFlagFilter()
    : core::Module()
    , tableInSlot("getDataIn", "Float table input")
    , flagStorageInSlot("readFlagStorage", "Flag storage read input")
    , tableOutSlot("getDataOut", "Float table output")
    , filterModeParam("filterMode", "filter mode")
    , tableInFrameCount(0)
    , tableInDataHash(0)
    , tableInColCount(0)
    , dataHash(0)
    , rowCount(0) {

    this->tableInSlot.SetCompatibleCall<TableDataCallDescription>();
    this->MakeSlotAvailable(&this->tableInSlot);

    this->flagStorageInSlot.SetCompatibleCall<core::FlagCallRead_GLDescription>();
    this->MakeSlotAvailable(&this->flagStorageInSlot);

    this->tableOutSlot.SetCallback(TableDataCall::ClassName(),
        TableDataCall::FunctionName(0),
        &TableFlagFilter::getData);
    this->tableOutSlot.SetCallback(TableDataCall::ClassName(),
        TableDataCall::FunctionName(1),
        &TableFlagFilter::getHash);
    this->MakeSlotAvailable(&this->tableOutSlot);

    auto* fmp = new core::param::EnumParam(FilterMode::FILTERED);
    fmp->SetTypePair(FilterMode::FILTERED, "Filtered");
    fmp->SetTypePair(FilterMode::SELECTED, "Selected");
    this->filterModeParam << fmp;
    this->MakeSlotAvailable(&this->filterModeParam);
}

TableFlagFilter::~TableFlagFilter() {
    this->Release();
}

bool TableFlagFilter::create() {
    return true;
}

void TableFlagFilter::release() {
}

bool TableFlagFilter::getData(core::Call &call) {
    if (!this->handleCall(call)) {
        return false;
    }

    auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
    tableOutCall->SetFrameCount(this->tableInFrameCount);
    tableOutCall->SetDataHash(this->dataHash);
    tableOutCall->Set(this->tableInColCount, this->rowCount, this->colInfos.data(), this->data.data());

    return true;
}

bool TableFlagFilter::getHash(core::Call &call) {
    if (!this->handleCall(call)) {
        return false;
    }

    auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
    tableOutCall->SetFrameCount(this->tableInFrameCount);
    tableOutCall->SetDataHash(this->dataHash);

    return true;
}

bool TableFlagFilter::handleCall(core::Call &call) {
    auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
    auto *tableInCall = this->tableInSlot.CallAs<TableDataCall>();
    auto *flagsInCall = this->flagStorageInSlot.CallAs<core::FlagCallRead_GL>();

    if (tableOutCall == nullptr) {
        return false;
    }

    if (tableInCall == nullptr) {
        megamol::core::utility::log::Log::DefaultLog.WriteMsg(
            megamol::core::utility::log::Log::LEVEL_ERROR, "TableFlagFilter requires a table!");
        return false;
    }

    if (flagsInCall == nullptr) {
        megamol::core::utility::log::Log::DefaultLog.WriteMsg(
            megamol::core::utility::log::Log::LEVEL_ERROR, "TableFlagFilter requires a flag storage!");
        return false;
    }

    tableInCall->SetFrameID(tableOutCall->GetFrameID());
    (*tableInCall)(1);
    (*tableInCall)(0);
    (*flagsInCall)(core::FlagCallRead_GL::CallGetData);

    if (this->tableInFrameCount != tableInCall->GetFrameCount() || this->tableInDataHash != tableInCall->DataHash() || flagsInCall->hasUpdate()) {
        // megamol::core::utility::log::Log::DefaultLog.WriteMsg(megamol::core::utility::log::Log::LEVEL_INFO, "TableFlagFilter: Filter table.");

        this->dataHash++;

        this->tableInFrameCount = tableInCall->GetFrameCount();
        this->tableInDataHash = tableInCall->DataHash();
        this->tableInColCount = tableInCall->GetColumnsCount();
        size_t tableInRowCount = tableInCall->GetRowsCount();

        // download flags
        flagsInCall->getData()->validateFlagCount(tableInRowCount);
        auto flags = flagsInCall->getData()->flags;
        uint32_t *flagsData = new uint32_t[flags->getByteSize() / sizeof(uint32_t)];
        flags->bind();
        glGetBufferSubData(flags->getTarget(), 0, flags->getByteSize(), flagsData);

        // copy column infos
        this->colInfos.resize(this->tableInColCount);
        for (size_t i = 0; i < this->tableInColCount; ++i) {
            this->colInfos[i] = tableInCall->GetColumnsInfos()[i];
            this->colInfos[i].SetMinimumValue(std::numeric_limits<float>::max());
            this->colInfos[i].SetMaximumValue(std::numeric_limits<float>::lowest());
        }

        core::FlagStorage::FlagItemType testMask = core::FlagStorage::ENABLED | core::FlagStorage::FILTERED;
        core::FlagStorage::FlagItemType passMask = core::FlagStorage::ENABLED;;
        if (static_cast<FilterMode>(this->filterModeParam.Param<core::param::EnumParam>()->Value()) == FilterMode::SELECTED) {
            testMask = core::FlagStorage::ENABLED | core::FlagStorage::SELECTED | core::FlagStorage::FILTERED;
            passMask = core::FlagStorage::ENABLED | core::FlagStorage::SELECTED;
        }

        // Resize data to size of input table. With this we only need to allocate memory once.
        this->data.resize(this->tableInColCount * tableInRowCount);
        this->rowCount = 0;

        const float *tableInData = tableInCall->GetData();
        for (size_t r = 0; r < tableInRowCount; ++r) {
            if ((flagsData[r] & testMask) == passMask) {
                for (size_t c = 0; c < this->tableInColCount; ++c) {
                    float val = tableInData[this->tableInColCount * r + c];
                    this->data[this->tableInColCount * this->rowCount + c] = val;
                    if (val < this->colInfos[c].MinimumValue()) {
                        this->colInfos[c].SetMinimumValue(val);
                    }
                    if (val > this->colInfos[c].MaximumValue()) {
                        this->colInfos[c].SetMaximumValue(val);
                    }
                }
                this->rowCount++;
            }
        }

        // delete memory of filtered rows
        this->data.resize(this->tableInColCount * this->rowCount);

        delete[] flagsData;

        // nicer output
        if (this->rowCount == 0) {
            for (size_t i = 0; i < this->tableInColCount; ++i) {
                this->colInfos[i].SetMinimumValue(0.0);
                this->colInfos[i].SetMaximumValue(0.0);
            }
        }
    }

    return true;
}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/client/lib/slicing.h"

#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/util.h"

namespace xla {

XlaOp SliceInMinorDims(XlaOp x, absl::Span<const int64> start,
                       absl::Span<const int64> end) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_RET_CHECK(start.size() == end.size());
    int64 n_minor_dims = start.size();

    TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));

    const int64 n_dims = shape.rank();
    TF_RET_CHECK(n_minor_dims <= n_dims);
    auto major_dims = AsInt64Slice(shape.dimensions())
                          .subspan(
                              /*pos=*/0,
                              /*len=*/n_dims - n_minor_dims);

    // Prepends 0s in the major dim
    std::vector<int64> padded_start(n_dims, 0);
    std::copy(start.begin(), start.end(),
              padded_start.begin() + major_dims.size());

    // Prepends the shape of the major dims.
    std::vector<int64> padded_end(n_dims);
    std::copy(major_dims.begin(), major_dims.end(), padded_end.begin());
    std::copy(end.begin(), end.end(), padded_end.begin() + major_dims.size());

    std::vector<int64> strides(n_dims, 1);
    return Slice(x, padded_start, padded_end, strides);
  });
}

XlaOp UpdateSlice(XlaOp x, XlaOp update, absl::Span<const int64> start) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));
    const int64 n_dims = shape.rank();
    TF_RET_CHECK(start.size() == n_dims);

    // TODO(phawkins): make int64 work on all backends, remove the int32 cast.
    std::vector<int32> start_as_int32(start.begin(), start.end());
    std::vector<XlaOp> start_ops(start.size());
    for (int i = 0; i < start.size(); ++i) {
      start_ops[i] = ConstantR0(builder, start_as_int32[i]);
    }
    return DynamicUpdateSlice(x, update, start_ops);
  });
}

XlaOp UpdateSliceInMinorDims(XlaOp x, XlaOp update,
                             absl::Span<const int64> start) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));
    const int64 n_dims = shape.rank();
    const int64 n_minor_dims = start.size();
    TF_RET_CHECK(n_minor_dims <= n_dims);
    std::vector<int64> padded_start(n_dims, 0);
    std::copy(start.begin(), start.end(),
              padded_start.begin() + (n_dims - n_minor_dims));
    return UpdateSlice(x, update, padded_start);
  });
}

namespace {

std::vector<int64> ConcatVectors(absl::Span<const int64> xs,
                                 absl::Span<const int64> ys) {
  std::vector<int64> output(xs.size() + ys.size());
  std::copy(xs.begin(), xs.end(), output.begin());
  std::copy(ys.begin(), ys.end(), output.begin() + xs.size());
  return output;
}

StatusOr<std::vector<XlaOp>> PrependZerosInMajorDims(
    XlaOp x, absl::Span<const XlaOp> starts) {
  XlaBuilder* builder = x.builder();
  TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));
  const int64 n_dims = shape.rank();
  auto zero = ConstantR0<int32>(builder, 0);
  std::vector<XlaOp> padded_starts(n_dims, zero);
  for (int i = 0; i < starts.size(); ++i) {
    padded_starts[n_dims - starts.size() + i] = starts[i];
  }
  return padded_starts;
}

}  // namespace

XlaOp DynamicSliceInMinorDims(XlaOp x, absl::Span<const XlaOp> starts,
                              absl::Span<const int64> sizes) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));
    const int64 n_dims = shape.rank();
    int64 n_minor_dims = starts.size();
    TF_RET_CHECK(n_minor_dims == sizes.size());
    TF_RET_CHECK(n_minor_dims <= n_dims);
    auto major_dims = AsInt64Slice(shape.dimensions())
                          .subspan(
                              /*pos=*/0,
                              /*len=*/n_dims - sizes.size());
    TF_ASSIGN_OR_RETURN(auto padded_starts, PrependZerosInMajorDims(x, starts));
    auto padded_sizes = ConcatVectors(major_dims, sizes);
    return DynamicSlice(x, padded_starts, padded_sizes);
  });
}

XlaOp DynamicUpdateSliceInMinorDims(XlaOp x, XlaOp update,
                                    absl::Span<const XlaOp> starts) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(auto padded_starts, PrependZerosInMajorDims(x, starts));
    return DynamicUpdateSlice(x, update, padded_starts);
  });
}

XlaOp TorchGather(XlaOp input, XlaOp index, int64 dim) {
  XlaBuilder* builder = input.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape index_shape, builder->GetShape(index));
    ShapeUtil::AppendMajorDimension(1, &index_shape);
    std::vector<XlaOp> to_concat;
    TF_ASSIGN_OR_RETURN(Shape input_shape, builder->GetShape(input));
    to_concat.reserve(input_shape.rank());
    for (int64 i = 0; i < input_shape.rank(); ++i) {
      if (i == dim) {
        to_concat.push_back(Reshape(index, index_shape.dimensions()));
      } else {
        to_concat.push_back(Iota(builder, index_shape, i));
      }
    }
    XlaOp gather_indices = ConcatInDim(builder, to_concat, input_shape.rank());
    std::vector<int64> slice_sizes(input_shape.rank(), 1);
    GatherDimensionNumbers gather_dnums;
    gather_dnums.set_index_vector_dim(input_shape.rank());
    for (int64 i = 0; i < input_shape.rank(); ++i) {
      gather_dnums.add_collapsed_slice_dims(i);
      gather_dnums.add_start_index_map(i);
    }
    return Gather(input, gather_indices, gather_dnums, slice_sizes);
  });
}

XlaOp TorchIndexSelect(XlaOp input, XlaOp index, int64 dim, int64 batch_dims) {
  XlaBuilder* builder = input.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape input_shape, builder->GetShape(input));
    TF_ASSIGN_OR_RETURN(Shape index_shape, builder->GetShape(index));
    if (dim < batch_dims) {
      return InvalidArgument(
          "Gather dim must be greater than or equal to the number of batch "
          "dims");
    }
    std::vector<int64> slice_sizes = input_shape.dimensions();
    GatherDimensionNumbers gather_dnums;
    gather_dnums.set_index_vector_dim(index_shape.rank());
    if (batch_dims > 0) {
      ShapeUtil::AppendMajorDimension(1, &index_shape);
      std::vector<XlaOp> to_concat;
      to_concat.reserve(batch_dims + 1);
      for (int64 batch_dim = 0; batch_dim < batch_dims; ++batch_dim) {
        to_concat.push_back(Iota(builder, index_shape, batch_dim));
      }
      to_concat.push_back(Reshape(index, index_shape.dimensions()));
      index = ConcatInDim(builder, to_concat, gather_dnums.index_vector_dim());
    }
    for (int64 i = 0; i < input_shape.rank(); ++i) {
      if (i < batch_dims || i == dim) {
        if (slice_sizes[i] != 0) {
          slice_sizes[i] = 1;
          gather_dnums.add_collapsed_slice_dims(i);
        }
        gather_dnums.add_start_index_map(i);
      } else {
        if (i < dim) {
          gather_dnums.add_offset_dims(i);
        } else {
          gather_dnums.add_offset_dims(i + gather_dnums.index_vector_dim() -
                                       (1 + batch_dims));
        }
      }
    }
    return Gather(input, index, gather_dnums, slice_sizes);
  });
}

}  // namespace xla
<commit_msg>[XLA:CLIENT] Use U32 instead of 64 bit types for gathers against dimensions smaller than 2^32.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/client/lib/slicing.h"

#include <limits>

#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/util.h"

namespace xla {

XlaOp SliceInMinorDims(XlaOp x, absl::Span<const int64> start,
                       absl::Span<const int64> end) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_RET_CHECK(start.size() == end.size());
    int64 n_minor_dims = start.size();

    TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));

    const int64 n_dims = shape.rank();
    TF_RET_CHECK(n_minor_dims <= n_dims);
    auto major_dims = AsInt64Slice(shape.dimensions())
                          .subspan(
                              /*pos=*/0,
                              /*len=*/n_dims - n_minor_dims);

    // Prepends 0s in the major dim
    std::vector<int64> padded_start(n_dims, 0);
    std::copy(start.begin(), start.end(),
              padded_start.begin() + major_dims.size());

    // Prepends the shape of the major dims.
    std::vector<int64> padded_end(n_dims);
    std::copy(major_dims.begin(), major_dims.end(), padded_end.begin());
    std::copy(end.begin(), end.end(), padded_end.begin() + major_dims.size());

    std::vector<int64> strides(n_dims, 1);
    return Slice(x, padded_start, padded_end, strides);
  });
}

XlaOp UpdateSlice(XlaOp x, XlaOp update, absl::Span<const int64> start) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));
    const int64 n_dims = shape.rank();
    TF_RET_CHECK(start.size() == n_dims);

    // TODO(phawkins): make int64 work on all backends, remove the int32 cast.
    std::vector<int32> start_as_int32(start.begin(), start.end());
    std::vector<XlaOp> start_ops(start.size());
    for (int i = 0; i < start.size(); ++i) {
      start_ops[i] = ConstantR0(builder, start_as_int32[i]);
    }
    return DynamicUpdateSlice(x, update, start_ops);
  });
}

XlaOp UpdateSliceInMinorDims(XlaOp x, XlaOp update,
                             absl::Span<const int64> start) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));
    const int64 n_dims = shape.rank();
    const int64 n_minor_dims = start.size();
    TF_RET_CHECK(n_minor_dims <= n_dims);
    std::vector<int64> padded_start(n_dims, 0);
    std::copy(start.begin(), start.end(),
              padded_start.begin() + (n_dims - n_minor_dims));
    return UpdateSlice(x, update, padded_start);
  });
}

namespace {

std::vector<int64> ConcatVectors(absl::Span<const int64> xs,
                                 absl::Span<const int64> ys) {
  std::vector<int64> output(xs.size() + ys.size());
  std::copy(xs.begin(), xs.end(), output.begin());
  std::copy(ys.begin(), ys.end(), output.begin() + xs.size());
  return output;
}

StatusOr<std::vector<XlaOp>> PrependZerosInMajorDims(
    XlaOp x, absl::Span<const XlaOp> starts) {
  XlaBuilder* builder = x.builder();
  TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));
  const int64 n_dims = shape.rank();
  auto zero = ConstantR0<int32>(builder, 0);
  std::vector<XlaOp> padded_starts(n_dims, zero);
  for (int i = 0; i < starts.size(); ++i) {
    padded_starts[n_dims - starts.size() + i] = starts[i];
  }
  return padded_starts;
}

}  // namespace

XlaOp DynamicSliceInMinorDims(XlaOp x, absl::Span<const XlaOp> starts,
                              absl::Span<const int64> sizes) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x));
    const int64 n_dims = shape.rank();
    int64 n_minor_dims = starts.size();
    TF_RET_CHECK(n_minor_dims == sizes.size());
    TF_RET_CHECK(n_minor_dims <= n_dims);
    auto major_dims = AsInt64Slice(shape.dimensions())
                          .subspan(
                              /*pos=*/0,
                              /*len=*/n_dims - sizes.size());
    TF_ASSIGN_OR_RETURN(auto padded_starts, PrependZerosInMajorDims(x, starts));
    auto padded_sizes = ConcatVectors(major_dims, sizes);
    return DynamicSlice(x, padded_starts, padded_sizes);
  });
}

XlaOp DynamicUpdateSliceInMinorDims(XlaOp x, XlaOp update,
                                    absl::Span<const XlaOp> starts) {
  XlaBuilder* builder = x.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(auto padded_starts, PrependZerosInMajorDims(x, starts));
    return DynamicUpdateSlice(x, update, padded_starts);
  });
}

XlaOp TorchGather(XlaOp input, XlaOp index, int64 dim) {
  XlaBuilder* builder = input.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape index_shape, builder->GetShape(index));
    ShapeUtil::AppendMajorDimension(1, &index_shape);
    std::vector<XlaOp> to_concat;
    TF_ASSIGN_OR_RETURN(Shape input_shape, builder->GetShape(input));
    if (ShapeUtil::ElementHasBitWidth(index_shape, 64) &&
        input_shape.dimensions(dim) < std::numeric_limits<uint32>::max()) {
      index = ConvertElementType(index, U32);
      index_shape.set_element_type(U32);
    }
    to_concat.reserve(input_shape.rank());
    for (int64 i = 0; i < input_shape.rank(); ++i) {
      if (i == dim) {
        to_concat.push_back(Reshape(index, index_shape.dimensions()));
      } else {
        to_concat.push_back(Iota(builder, index_shape, i));
      }
    }
    XlaOp gather_indices = ConcatInDim(builder, to_concat, input_shape.rank());
    std::vector<int64> slice_sizes(input_shape.rank(), 1);
    GatherDimensionNumbers gather_dnums;
    gather_dnums.set_index_vector_dim(input_shape.rank());
    for (int64 i = 0; i < input_shape.rank(); ++i) {
      gather_dnums.add_collapsed_slice_dims(i);
      gather_dnums.add_start_index_map(i);
    }
    return Gather(input, gather_indices, gather_dnums, slice_sizes);
  });
}

XlaOp TorchIndexSelect(XlaOp input, XlaOp index, int64 dim, int64 batch_dims) {
  XlaBuilder* builder = input.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape input_shape, builder->GetShape(input));
    TF_ASSIGN_OR_RETURN(Shape index_shape, builder->GetShape(index));
    if (dim < batch_dims) {
      return InvalidArgument(
          "Gather dim must be greater than or equal to the number of batch "
          "dims");
    }
    if (ShapeUtil::ElementHasBitWidth(index_shape, 64) &&
        input_shape.dimensions(dim) < std::numeric_limits<uint32>::max()) {
      index = ConvertElementType(index, U32);
      index_shape.set_element_type(U32);
    }
    std::vector<int64> slice_sizes = input_shape.dimensions();
    GatherDimensionNumbers gather_dnums;
    gather_dnums.set_index_vector_dim(index_shape.rank());
    if (batch_dims > 0) {
      ShapeUtil::AppendMajorDimension(1, &index_shape);
      std::vector<XlaOp> to_concat;
      to_concat.reserve(batch_dims + 1);
      for (int64 batch_dim = 0; batch_dim < batch_dims; ++batch_dim) {
        to_concat.push_back(Iota(builder, index_shape, batch_dim));
      }
      to_concat.push_back(Reshape(index, index_shape.dimensions()));
      index = ConcatInDim(builder, to_concat, gather_dnums.index_vector_dim());
    }
    for (int64 i = 0; i < input_shape.rank(); ++i) {
      if (i < batch_dims || i == dim) {
        if (slice_sizes[i] != 0) {
          slice_sizes[i] = 1;
          gather_dnums.add_collapsed_slice_dims(i);
        }
        gather_dnums.add_start_index_map(i);
      } else {
        if (i < dim) {
          gather_dnums.add_offset_dims(i);
        } else {
          gather_dnums.add_offset_dims(i + gather_dnums.index_vector_dim() -
                                       (1 + batch_dims));
        }
      }
    }
    return Gather(input, index, gather_dnums, slice_sizes);
  });
}

}  // namespace xla
<|endoftext|>