<commit_before>#include "xchainer/native/native_device.h"

#include <algorithm>
#include <cstdint>
#include <memory>
#include <numeric>

#include "xchainer/array.h"
#include "xchainer/constant.h"
#include "xchainer/dtype.h"
#include "xchainer/native/col2im.h"
#include "xchainer/native/elementwise.h"
#include "xchainer/native/im2col.h"
#include "xchainer/native/tensor_dot.h"
#include "xchainer/numeric_limits.h"
#include "xchainer/routines/connection.h"
#include "xchainer/routines/creation.h"
#include "xchainer/routines/indexing.h"
#include "xchainer/routines/math.h"
#include "xchainer/scalar.h"
#include "xchainer/shape.h"
#include "xchainer/stack_vector.h"

namespace xchainer {
namespace native {
namespace {

Scalar GetLowestOrInf(Dtype dtype) {
    return VisitDtype(dtype, [](auto pt) {
        using T = typename decltype(pt)::type;
        return Scalar{NumericLimits<T>::LowestOrInf()};
    });
}

// Returns axes that does the following transpose.
// (batch_size, channel, a_1, a_2, ...., a_n, b_1, b_2, ..., b_n) -> (batch_size, channel, b_1, b_2, ...., b_n, a_1, a_2, ..., a_n).
Axes GetSwapSpatialDimensionsAxes(size_t n) {
    Axes axes;
    axes.resize(2 + 2 * n);  // E.g. (batch_size, channel, out_1, out_2, ..., out_n, k_1, k_2, ..., k_n).
    axes[0] = 0;  // Batch dimension kept as is.
    axes[1] = 1;  // Channel dimension kept as is.
    for (size_t i = 2; i < n + 2; ++i) {  // Output and kernel spatial dimensions to be swapped.
        axes[i] = n + i;
        axes[n + i] = i;
    }
    return axes;
}

class NativeMaxPoolForwardBackward : public xchainer::MaxPoolForwardBackward {
public:
    Array Forward(
            const Array& x,
            const StackVector<int64_t, kMaxNdim>& kernel_size,
            const StackVector<int64_t, kMaxNdim>& stride,
            const StackVector<int64_t, kMaxNdim>& pad,
            bool cover_all) override {
        // Convert to column representation of shape (batch_size, channel, k_1, k_2, ..., k_n, out_1, out_2, ..., out_n).
        col_ = internal::Im2Col(x.AsConstant(), kernel_size, stride, pad, cover_all, GetLowestOrInf(x.dtype()));
        axes_.resize(kernel_size.size());
        std::iota(axes_.begin(), axes_.end(), 2);
        return col_.Max(axes_);
    }

    Array Backward(
            const Array& x,
            const StackVector<int64_t, kMaxNdim>& kernel_size,
            const StackVector<int64_t, kMaxNdim>& stride,
            const StackVector<int64_t, kMaxNdim>& pad,
            bool /*cover_all*/,
            const Array& gout) override {
        indices_ = col_.ArgMax(axes_);
        assert(indices_.shape() == gout.shape());

        // Compute flattened col gradients.
        int64_t kernel_total_size = std::accumulate(kernel_size.begin(), kernel_size.end(), int64_t{1}, std::multiplies<>());
        int64_t out_total_size = indices_.GetTotalSize();
        Shape out_flat{out_total_size};
        Device& device = x.device();
        Array gcol = Zeros({out_total_size * kernel_total_size}, x.dtype(), device);
        offset_ = Arange(0, out_total_size * kernel_total_size, kernel_total_size, indices_.dtype(), device);
        device.AddAt(gcol, indices_.Reshape(out_flat) + offset_, {0}, gout.AsConstant().Reshape(out_flat), gcol);

        // Reshape col gradients to (batch_size, channel, out_1, out_2, ..., out_n, k_1, k_2, ..., k_n).
        Shape out_shape_with_kernel = gout.shape();
        std::copy(kernel_size.begin(), kernel_size.end(), std::back_inserter(out_shape_with_kernel));

        // Transform col gradients to input shape.
        return internal::Col2Im(
                gcol.Reshape(out_shape_with_kernel).Transpose(GetSwapSpatialDimensionsAxes(kernel_size.size())),
                stride,
                pad,
                {x.shape().begin() + 2, x.shape().end()});
    }

    Array DoubleBackward(
            const Array& x,
            const StackVector<int64_t, kMaxNdim>& kernel_size,
            const StackVector<int64_t, kMaxNdim>& stride,
            const StackVector<int64_t, kMaxNdim>& pad,
            bool cover_all,
            const Array& /*gout*/,
            const Array& ggx) override {
        Array col = internal::Im2Col(ggx.AsConstant(), kernel_size, stride, pad, cover_all, GetLowestOrInf(x.dtype()));
        return Take(
                col.Transpose(GetSwapSpatialDimensionsAxes(kernel_size.size())).Reshape({col.GetTotalSize()}),
                indices_ + offset_.Reshape(indices_.shape()),
                0);
    }

private:
    Array col_{};
    Axes axes_{};
    Array indices_{};
    Array offset_{};
};

}  // namespace

std::unique_ptr<MaxPoolForwardBackward> NativeDevice::GetMaxPoolForwardBackward() {
    return std::make_unique<NativeMaxPoolForwardBackward>();
}

namespace {

void Mean(const Array& a, const Axes& axis, const Array& out) {
    Device& device = a.device();
    device.Sum(a, axis, out);
    device.DivideAS(out, xchainer::internal::CountItemsAlongAxes(a.shape(), axis), out);
}

void Minimum(const Array& x1, Scalar x2, const Array& out) {
    VisitDtype(out.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        struct Impl {
            void operator()(int64_t /*i*/, T x1, T& out) { out = x1 < x2 ? x1 : x2; }
            T x2;
        };
        Elementwise<const T, T>(Impl{static_cast<T>(x2)}, x1, out);
    });
}

Array GetPoolingWidth(
        const Shape& shape,
        const StackVector<int64_t, kMaxNdim>& kernel_size,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all,
        bool count_include_pad,
        Dtype dtype) {
    int8_t n = shape.ndim() - 2;
    assert(n == static_cast<int8_t>(kernel_size.size()));
    assert(n == static_cast<int8_t>(stride.size()));
    assert(n == static_cast<int8_t>(pad.size()));

    Array width;
    for (int64_t i = 0; i < n; ++i) {
        int64_t d = shape[2 + i];
        int64_t k = kernel_size[i];
        int64_t s = stride[i];
        int64_t p = pad[i];

        int64_t dim = xchainer::internal::GetConvOutDim(d, k, s, p, cover_all);
        Array starts = Arange(dim, dtype) * s - p;
        Array ends = starts + k;

        if (!count_include_pad) {
            starts = Maximum(0, starts);
            Minimum(ends, d, ends);
        }
        assert(starts.shape() == ends.shape());
        if (i == 0) {
            width = ends - starts;
        } else {
            Shape width_expanded = width.shape();
            width_expanded.emplace_back(1);
            Shape w_expanded{1};
            std::copy(starts.shape().begin(), starts.shape().end(), std::back_inserter(w_expanded));
            width = TensorDot(width.Reshape(width_expanded), (ends - starts).Reshape(w_expanded), {static_cast<int8_t>(width.ndim())}, {0});
        }
    }
    return width;
}

}  // namespace

Array NativeDevice::AveragePool(
        const Array& x,
        const StackVector<int64_t, kMaxNdim>& kernel_size,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all,
        bool count_include_pad) {
    // TODO(hvy): Support cover_all.
    if (cover_all) {
        throw NotImplementedError{"Native average pooling does not yet support cover_all."};
    }

    Array col = internal::Im2Col(x.AsConstant(), kernel_size, stride, pad, cover_all, 0);

    // Average along the kernel dimensions of col with shape (batch_size, channel, k_1, k_2, ..., k_n, out_1, out_2, ..., out_n).
    Axes kernel_axes;
    kernel_axes.resize(kernel_size.size());
    std::iota(kernel_axes.begin(), kernel_axes.end(), 2);  // From k_1, up to k_n.

    Array out = xchainer::internal::EmptyReduced(col.shape(), col.dtype(), kernel_axes, false, col.device());

    if (count_include_pad) {
        Mean(col, kernel_axes, out);
    } else {
        Device& device = x.device();
        device.Sum(col, kernel_axes, out);
        device.Divide(
                out,
                GetPoolingWidth(x.shape(), kernel_size, stride, pad, cover_all, count_include_pad, x.dtype()).BroadcastTo(out.shape()),
                out);
    }
    return out;
}

}  // namespace native
}  // namespace xchainer
<commit_msg>Prefer elementwise GetPoolingWidths<commit_after>#include "xchainer/native/native_device.h"

#include <algorithm>
#include <cstdint>
#include <memory>
#include <numeric>

#include "xchainer/array.h"
#include "xchainer/constant.h"
#include "xchainer/dtype.h"
#include "xchainer/native/col2im.h"
#include "xchainer/native/elementwise.h"
#include "xchainer/native/im2col.h"
#include "xchainer/native/tensor_dot.h"
#include "xchainer/numeric_limits.h"
#include "xchainer/routines/connection.h"
#include "xchainer/routines/creation.h"
#include "xchainer/routines/indexing.h"
#include "xchainer/routines/math.h"
#include "xchainer/scalar.h"
#include "xchainer/shape.h"
#include "xchainer/stack_vector.h"

namespace xchainer {
namespace native {
namespace {

Scalar GetLowestOrInf(Dtype dtype) {
    return VisitDtype(dtype, [](auto pt) {
        using T = typename decltype(pt)::type;
        return Scalar{NumericLimits<T>::LowestOrInf()};
    });
}

// Returns axes that does the following transpose.
// (batch_size, channel, a_1, a_2, ...., a_n, b_1, b_2, ..., b_n) -> (batch_size, channel, b_1, b_2, ...., b_n, a_1, a_2, ..., a_n).
Axes GetSwapSpatialDimensionsAxes(size_t n) {
    Axes axes;
    axes.resize(2 + 2 * n);  // E.g. (batch_size, channel, out_1, out_2, ..., out_n, k_1, k_2, ..., k_n).
    axes[0] = 0;  // Batch dimension kept as is.
    axes[1] = 1;  // Channel dimension kept as is.
    for (size_t i = 2; i < n + 2; ++i) {  // Output and kernel spatial dimensions to be swapped.
        axes[i] = n + i;
        axes[n + i] = i;
    }
    return axes;
}

class NativeMaxPoolForwardBackward : public xchainer::MaxPoolForwardBackward {
public:
    Array Forward(
            const Array& x,
            const StackVector<int64_t, kMaxNdim>& kernel_size,
            const StackVector<int64_t, kMaxNdim>& stride,
            const StackVector<int64_t, kMaxNdim>& pad,
            bool cover_all) override {
        // Convert to column representation of shape (batch_size, channel, k_1, k_2, ..., k_n, out_1, out_2, ..., out_n).
        col_ = internal::Im2Col(x.AsConstant(), kernel_size, stride, pad, cover_all, GetLowestOrInf(x.dtype()));
        axes_.resize(kernel_size.size());
        std::iota(axes_.begin(), axes_.end(), 2);
        return col_.Max(axes_);
    }

    Array Backward(
            const Array& x,
            const StackVector<int64_t, kMaxNdim>& kernel_size,
            const StackVector<int64_t, kMaxNdim>& stride,
            const StackVector<int64_t, kMaxNdim>& pad,
            bool /*cover_all*/,
            const Array& gout) override {
        indices_ = col_.ArgMax(axes_);
        assert(indices_.shape() == gout.shape());

        // Compute flattened col gradients.
        int64_t kernel_total_size = std::accumulate(kernel_size.begin(), kernel_size.end(), int64_t{1}, std::multiplies<>());
        int64_t out_total_size = indices_.GetTotalSize();
        Shape out_flat{out_total_size};
        Device& device = x.device();
        Array gcol = Zeros({out_total_size * kernel_total_size}, x.dtype(), device);
        offset_ = Arange(0, out_total_size * kernel_total_size, kernel_total_size, indices_.dtype(), device);
        device.AddAt(gcol, indices_.Reshape(out_flat) + offset_, {0}, gout.AsConstant().Reshape(out_flat), gcol);

        // Reshape col gradients to (batch_size, channel, out_1, out_2, ..., out_n, k_1, k_2, ..., k_n).
        Shape out_shape_with_kernel = gout.shape();
        std::copy(kernel_size.begin(), kernel_size.end(), std::back_inserter(out_shape_with_kernel));

        // Transform col gradients to input shape.
        return internal::Col2Im(
                gcol.Reshape(out_shape_with_kernel).Transpose(GetSwapSpatialDimensionsAxes(kernel_size.size())),
                stride,
                pad,
                {x.shape().begin() + 2, x.shape().end()});
    }

    Array DoubleBackward(
            const Array& x,
            const StackVector<int64_t, kMaxNdim>& kernel_size,
            const StackVector<int64_t, kMaxNdim>& stride,
            const StackVector<int64_t, kMaxNdim>& pad,
            bool cover_all,
            const Array& /*gout*/,
            const Array& ggx) override {
        Array col = internal::Im2Col(ggx.AsConstant(), kernel_size, stride, pad, cover_all, GetLowestOrInf(x.dtype()));
        return Take(
                col.Transpose(GetSwapSpatialDimensionsAxes(kernel_size.size())).Reshape({col.GetTotalSize()}),
                indices_ + offset_.Reshape(indices_.shape()),
                0);
    }

private:
    Array col_{};
    Axes axes_{};
    Array indices_{};
    Array offset_{};
};

}  // namespace

std::unique_ptr<MaxPoolForwardBackward> NativeDevice::GetMaxPoolForwardBackward() {
    return std::make_unique<NativeMaxPoolForwardBackward>();
}

namespace {

void Mean(const Array& a, const Axes& axis, const Array& out) {
    Device& device = a.device();
    device.Sum(a, axis, out);
    device.DivideAS(out, xchainer::internal::CountItemsAlongAxes(a.shape(), axis), out);
}

Array GetPoolingWidths(
        const Shape& shape,
        const StackVector<int64_t, kMaxNdim>& kernel_size,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all,
        bool count_include_pad,
        Dtype dtype) {
    int8_t n = shape.ndim() - 2;
    assert(n == static_cast<int8_t>(kernel_size.size()));
    assert(n == static_cast<int8_t>(stride.size()));
    assert(n == static_cast<int8_t>(pad.size()));

    Array widths;
    for (int64_t i = 0; i < n; ++i) {
        int64_t dim = shape[2 + i];
        int64_t k = kernel_size[i];
        int64_t s = stride[i];
        int64_t p = pad[i];

        Array width = Empty({xchainer::internal::GetConvOutDim(dim, k, s, p, cover_all)}, dtype);
        VisitDtype(dtype, [&](auto pt) {
            using T = typename decltype(pt)::type;
            struct Impl {
                void operator()(int64_t i, T& width) {
                    T start = i * stride - pad;
                    T end = start + kernel_size;
                    if (!count_include_pad) {
                        if (start < 0) {
                            start = 0;
                        }
                        if (end > dim) {
                            end = dim;
                        }
                    }
                    width = end - start;
                }
                T dim;
                T kernel_size;
                T stride;
                T pad;
                bool count_include_pad;
            };
            Elementwise<T>(Impl{static_cast<T>(dim), static_cast<T>(k), static_cast<T>(s), static_cast<T>(p), count_include_pad}, width);
        });

        if (i == 0) {
            widths = width;
        } else {
            Shape widths_expanded = widths.shape();
            widths_expanded.emplace_back(1);

            Shape width_expanded{1};
            std::copy(width.shape().begin(), width.shape().end(), std::back_inserter(width_expanded));

            widths = TensorDot(widths.Reshape(widths_expanded), width.Reshape(width_expanded), {static_cast<int8_t>(widths.ndim())}, {0});
        }
    }
    return widths;
}

}  // namespace

Array NativeDevice::AveragePool(
        const Array& x,
        const StackVector<int64_t, kMaxNdim>& kernel_size,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all,
        bool count_include_pad) {
    // TODO(hvy): Support cover_all.
    if (cover_all) {
        throw NotImplementedError{"Native average pooling does not yet support cover_all."};
    }

    Array col = internal::Im2Col(x.AsConstant(), kernel_size, stride, pad, cover_all, 0);

    // Average along the kernel dimensions of col with shape (batch_size, channel, k_1, k_2, ..., k_n, out_1, out_2, ..., out_n).
    Axes kernel_axes;
    kernel_axes.resize(kernel_size.size());
    std::iota(kernel_axes.begin(), kernel_axes.end(), 2);  // From k_1, up to k_n.

    Array out = xchainer::internal::EmptyReduced(col.shape(), col.dtype(), kernel_axes, false, col.device());

    if (count_include_pad) {
        Mean(col, kernel_axes, out);
    } else {
        Device& device = x.device();
        device.Sum(col, kernel_axes, out);
        device.Divide(
                out,
                GetPoolingWidths(x.shape(), kernel_size, stride, pad, cover_all, count_include_pad, x.dtype()).BroadcastTo(out.shape()),
                out);
    }
    return out;
}

}  // namespace native
}  // namespace xchainer
<|endoftext|>


<commit_before>#include "table_view.h"
#include <utils.h>

#include <rapidjson/rapidjson.h>
#include <rapidjson/document.h>

#include <QHeaderView>
#include <QDebug>

#include <vector>

namespace fpgui {
namespace ui {

static void balance_size_percentages(std::vector<settings::Tab_Configuration>& config, double total = 0)
{
    int invisible = 0;

    for (auto& tab : config)
        if (!tab.show)
            invisible++;

    double min_tab_size = 100 / (config.size() - invisible);

    if (min_tab_size > 5)
        min_tab_size = 5;

    if (total < 0)
        total = 0;

    if (total < 0.1)
    {
        for (auto& tab : config)
        {
            if (!tab.show)
                continue;

            if (tab.size < min_tab_size)
                tab.size = min_tab_size;
            total += tab.size;
        }

        if ((total < 101) && (total > 99))
            return;

        balance_size_percentages(config, total);
        return;
    }

    while (total > 101)
    {
        double temp = 0;

        for (auto& tab : config)
        {
            if (!tab.show)
                continue;

            tab.size -= 0.1;

            if (tab.size < min_tab_size)
                tab.size = min_tab_size;

            temp += tab.size;
        }

        total = temp;
    }

    while (total < 99)
    {
        double temp = 0;

        for (auto& tab : config)
        {
            if (!tab.show)
                continue;

            tab.size += 0.1;

            if (tab.size < min_tab_size)
                tab.size = min_tab_size;

            temp += tab.size;
        }

        total = temp;
    }
}

static void percentage_to_absolute_width(std::vector<settings::Tab_Configuration> &config, double widget_width)
{
    if (widget_width < 1)
        return;

    for (auto& tab : config)
    {
        if (!tab.show)
            continue;

        tab.size *= (widget_width / 100);
    }
}

static void absolute_width_to_percentage(std::vector<settings::Tab_Configuration> &config, QTableWidget &widget)
{
    double widget_width(widget.geometry().width());

    int col = 0;

    for (auto& tab : config)
    {
        if (!tab.show)
            continue;

        double width = widget.columnWidth(col++);
        tab.size = width / widget_width * 100;
    }
}

static bool suppress_resize_signals = false;

void Table_View::setup_view(const std::vector<settings::Tab_Configuration> &config, QTableWidget &widget, bool resize_only)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    generic_utils::Variable_Reset <bool> reset(suppress_resize_signals, true, false);

    double widget_width(widget.geometry().width());
    std::vector<settings::Tab_Configuration> config_copy(config);

    if (!resize_only)
    {
        balance_size_percentages(config_copy);

        config_ = config_copy;
        widget_ = &widget;

        int invisible = 0;

        for (auto& tab : config)
            if (!tab.show)
                invisible++;

        widget.setColumnCount(config_copy.size() - invisible);
        widget.setRowCount(1);

        disconnect(widget_->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this,
                   SLOT(col_size_changed(int, int, int)));

        connect(widget_->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this,
                SLOT(col_size_changed(int, int, int)), Qt::DirectConnection);

        int col = 0;
        for (auto& tab : config_copy)
        {
            if (!tab.show)
                continue;

            widget.setHorizontalHeaderItem(col++, new QTableWidgetItem(tab.name.c_str()));
        }
    }
    else
    {
        absolute_width_to_percentage(config_copy, widget);
        balance_size_percentages(config_copy);
        config_ = config_copy;
    }

    percentage_to_absolute_width(config_copy, widget_width);

    int col = 0;
    for (auto& tab : config_copy)
    {
        if (!tab.show)
            continue;

        widget.setColumnWidth(col++, tab.size);
    }
}

void Table_View::do_resize()
{
    setup_view(config_, *widget_, true);
}

void Table_View::close_view()
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    emit closing();
}

std::vector<settings::Tab_Configuration> Table_View::get_view_configuration()
{
    return config_;
}

void Table_View::col_size_changed(int, int, int)
{
    if (!suppress_resize_signals)
        do_resize();
}

static void trim_data(std::vector<std::string>& data, settings::App_Configuration& config)
{
    while (data.size() > (size_t)config.view_max_messages)
        data.erase(data.begin());
}

void Table_View::refresh_view(std::vector<std::string>& data_batch, bool)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);

    data_.reserve(data_.size() + data_batch.size());
    std::copy(data_batch.begin(), data_batch.end(), std::inserter(data_, data_.end()));

    display_strings(data_batch);
    trim_data(data_, app_config_);
}

void Table_View::display_strings(std::vector<std::string> &json_strings)
{
    for (const auto& js: json_strings)
    {
        rapidjson::GenericDocument<rapidjson::UTF8<>> js_from;
        std::unique_ptr<char[]> to_parse(new char[js.size() + 1]);

        memcpy(to_parse.get(), js.c_str(), js.size());
        to_parse.get()[js.size()] = 0;

        js_from.ParseInsitu(to_parse.get());

        if (js_from.IsNull())
        {
            qCritical() << "JSON document is invalid!";
            return;
        }

        std::map<std::string, int> col_name_to_number;
        for (int i = 0; i < widget_->horizontalHeader()->count(); ++i)
        {
            std::pair<std::string, int> pair(widget_->horizontalHeaderItem(i)->text().toStdString(), i);
            col_name_to_number.insert(pair);
        }

        if (js_from.IsObject())
        {
            rapidjson::Value::Object jsobj(js_from.GetObject());

            for (rapidjson::Value::Object::MemberIterator it = jsobj.MemberBegin(); it != jsobj.MemberEnd(); ++it)
            {
                auto item(col_name_to_number.find(it->name.GetString()));
                if (item == col_name_to_number.end())
                    continue;

                widget_->setItem(widget_->rowCount() - 1, item->second, new QTableWidgetItem(it->value.GetString()));
                //TODO: add to table widget here
            }

            widget_->insertRow(widget_->rowCount());
        }
    }

}

}}
<commit_msg>Fixed #15.<commit_after>#include "table_view.h"
#include <utils.h>

#include <rapidjson/rapidjson.h>
#include <rapidjson/document.h>

#include <QHeaderView>
#include <QDebug>

#include <vector>

namespace fpgui {
namespace ui {

static void balance_size_percentages(std::vector<settings::Tab_Configuration>& config, double total = 0)
{
    int invisible = 0;

    for (auto& tab : config)
        if (!tab.show)
            invisible++;

    double min_tab_size = 100 / (config.size() - invisible);

    if (min_tab_size > 5)
        min_tab_size = 5;

    if (total < 0)
        total = 0;

    if (total < 0.1)
    {
        for (auto& tab : config)
        {
            if (!tab.show)
                continue;

            if (tab.size < min_tab_size)
                tab.size = min_tab_size;
            total += tab.size;
        }

        if ((total < 101) && (total > 99))
            return;

        balance_size_percentages(config, total);
        return;
    }

    while (total > 101)
    {
        double temp = 0;

        for (auto& tab : config)
        {
            if (!tab.show)
                continue;

            tab.size -= 0.1;

            if (tab.size < min_tab_size)
                tab.size = min_tab_size;

            temp += tab.size;
        }

        total = temp;
    }

    while (total < 99)
    {
        double temp = 0;

        for (auto& tab : config)
        {
            if (!tab.show)
                continue;

            tab.size += 0.1;

            if (tab.size < min_tab_size)
                tab.size = min_tab_size;

            temp += tab.size;
        }

        total = temp;
    }
}

static void percentage_to_absolute_width(std::vector<settings::Tab_Configuration> &config, double widget_width)
{
    if (widget_width < 1)
        return;

    for (auto& tab : config)
    {
        if (!tab.show)
            continue;

        tab.size *= (widget_width / 100);
    }
}

static void absolute_width_to_percentage(std::vector<settings::Tab_Configuration> &config, QTableWidget &widget)
{
    double widget_width(widget.geometry().width());

    int col = 0;

    for (auto& tab : config)
    {
        if (!tab.show)
            continue;

        double width = widget.columnWidth(col++);
        tab.size = width / widget_width * 100;
    }
}

static bool suppress_resize_signals = false;

void Table_View::setup_view(const std::vector<settings::Tab_Configuration> &config, QTableWidget &widget, bool resize_only)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    generic_utils::Variable_Reset <bool> reset(suppress_resize_signals, true, false);

    double widget_width(widget.geometry().width());
    std::vector<settings::Tab_Configuration> config_copy(config);

    if (!resize_only)
    {
        balance_size_percentages(config_copy);

        config_ = config_copy;
        widget_ = &widget;

        int invisible = 0;

        for (auto& tab : config)
            if (!tab.show)
                invisible++;

        widget.setColumnCount(config_copy.size() - invisible);
        widget.setRowCount(1);

        disconnect(widget_->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this,
                   SLOT(col_size_changed(int, int, int)));

        connect(widget_->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this,
                SLOT(col_size_changed(int, int, int)), Qt::DirectConnection);

        int col = 0;
        for (auto& tab : config_copy)
        {
            if (!tab.show)
                continue;

            widget.setHorizontalHeaderItem(col++, new QTableWidgetItem(tab.name.c_str()));
        }
    }
    else
    {
        absolute_width_to_percentage(config_copy, widget);
        balance_size_percentages(config_copy);
        config_ = config_copy;
    }

    percentage_to_absolute_width(config_copy, widget_width);

    int col = 0;
    for (auto& tab : config_copy)
    {
        if (!tab.show)
            continue;

        widget.setColumnWidth(col++, tab.size);
    }
}

void Table_View::do_resize()
{
    setup_view(config_, *widget_, true);
}

void Table_View::close_view()
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    emit closing();
}

std::vector<settings::Tab_Configuration> Table_View::get_view_configuration()
{
    return config_;
}

void Table_View::col_size_changed(int, int, int)
{
    if (!suppress_resize_signals)
        do_resize();
}

static void trim_data(std::vector<std::string>& data, settings::App_Configuration& config, QTableWidget* widget = 0)
{
    while (data.size() > (size_t)config.view_max_messages)
    {
        data.erase(data.begin());
        if (widget)
            widget->removeRow(0);
    }
}

void Table_View::refresh_view(std::vector<std::string>& data_batch, bool)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);

    data_.reserve(data_.size() + data_batch.size());
    std::copy(data_batch.begin(), data_batch.end(), std::inserter(data_, data_.end()));

    #ifndef _UNIT_TEST
        display_strings(data_batch);
        trim_data(data_, app_config_, widget_);
    #else
        trim_data(data_, app_config_, 0);
    #endif
}

void Table_View::display_strings(std::vector<std::string> &json_strings)
{
    for (const auto& js: json_strings)
    {
        rapidjson::GenericDocument<rapidjson::UTF8<>> js_from;
        std::unique_ptr<char[]> to_parse(new char[js.size() + 1]);

        memcpy(to_parse.get(), js.c_str(), js.size());
        to_parse.get()[js.size()] = 0;

        js_from.ParseInsitu(to_parse.get());

        if (js_from.IsNull())
        {
            qCritical() << "JSON document is invalid!";
            return;
        }

        std::map<std::string, int> col_name_to_number;
        for (int i = 0; i < widget_->horizontalHeader()->count(); ++i)
        {
            std::pair<std::string, int> pair(widget_->horizontalHeaderItem(i)->text().toStdString(), i);
            col_name_to_number.insert(pair);
        }

        if (js_from.IsObject())
        {
            rapidjson::Value::Object jsobj(js_from.GetObject());

            for (rapidjson::Value::Object::MemberIterator it = jsobj.MemberBegin(); it != jsobj.MemberEnd(); ++it)
            {
                auto item(col_name_to_number.find(it->name.GetString()));
                if (item == col_name_to_number.end())
                    continue;

                widget_->setItem(widget_->rowCount() - 1, item->second, new QTableWidgetItem(it->value.GetString()));
            }

            widget_->insertRow(widget_->rowCount());
        }
    }

}

}}
<|endoftext|>


<commit_before>#include "o2gft.h"
#include "o2google.h"

static const char *GftScope = "https://www.googleapis.com/auth/fusiontables";
static const char *GftEndpoint = "https://accounts.google.com/o/oauth2/auth";
static const char *GftTokenUrl = "https://accounts.google.com/o/oauth2/token";
static const char *GftRefreshUrl = "https://accounts.google.com/o/oauth2/token";

O2Gft::O2Gft(QObject *parent): O2Google(parent) {
    setScope(GftScope);
}
<commit_msg>Remove unused constants causing warnings<commit_after>#include "o2gft.h"
#include "o2google.h"

static const char *GftScope = "https://www.googleapis.com/auth/fusiontables";

O2Gft::O2Gft(QObject *parent): O2Google(parent) {
    setScope(GftScope);
}
<|endoftext|>


<commit_before>#include <fstream>
#include "object.h"
#include "component.h"
#include "engine.h"
#include "log.h"
#include "yaml-cpp/yaml.h"

#include <exception>
#include <algorithm>

namespace gear2d {
  object::object(object::signature & sig)
   : destroyed(false)
   , sig(sig) {
  }

  object::~object() {
    // delete all components
    for (componentcontainer::iterator i = components.begin(); i != components.end(); i++) {
      component::base * c = i->second;
      c->owner == 0;
      engine::remove(c);
      // lets the engine delete c;
    }

    // delete all properties
    for (parameterbase::table::iterator i = parameters.begin(); i != parameters.end(); i++) {
      parameterbase * p = i->second;
      if (p != 0) {
        parameters[p->pid] = 0;
        if (p->dodestroy)  {
          delete p;
        }
      }
    }
  }

  object::id object::oid() { return this; }
  std::string object::name() { return sig["name"]; }

  void object::attach(component::base * newc) throw (evil) {
    logverb;
    if (newc == 0) return;

    trace("Attaching", newc->family(), newc->type());

    /* sees that dependencies are met */
    std::string depends = newc->depends();
    bool passed = true;
    std::string d;
    if (depends != "") {
      std::list<std::string> dependencies;
      split(dependencies, depends, ' ');
      while (!dependencies.empty()) {
        component::selector dependency = dependencies.front();

        /* se if family is here */
        component::base * requiredcom = components[dependency.family];
        if (requiredcom == 0) {
          passed = false;
          d = dependency;
          break;
        }

        /* check if dependency has a type. if not, passed. if yes, check */
        if (dependency.type != "") {
          if (requiredcom->type() != dependency.type) {
            passed = false;
            d = dependency;
            break;
          }
        }
        dependencies.pop_front();
      }
    }

    if (passed == false) {
      std::string s;
      s = s + "Component " + newc->family() + "/" + newc->type() + " have unmet dependencies: " + d;
      throw (evil(s));
    }

    /* ok... dependency check has passed! */
    component::base * oldc = deattach(newc->family());
    if (oldc != 0) { delete oldc; }
    newc->owner = this;
    components[newc->family()] = newc;

    newc->setup(sig);
    engine::add(newc);
  }

  component::base * object::deattach(component::family family) {
    component::base * oldc = components[family];
    if (oldc == 0) return 0;
    components.erase(family);
    engine::remove(oldc);
    return oldc;
  }

  parameterbase::value object::get(parameterbase::id pid) {
    return parameters[pid];
  }

  void object::set(parameterbase::id pid, parameterbase::value v) {
    parameters[pid] = v;
    if (v != 0) {
      v->owner = this;
      v->pid = pid;
    }
  }

  component::base * object::component(gear2d::component::family f) {
    return components[f];
  }

  void object::copy(object::id other) {
    if (other == 0) return;
    for (parameterbase::table::iterator it = parameters.begin(); it != parameters.end(); it++) {
      parameterbase::id pid = it->first;
      parameterbase::value pval = it->second;

      parameterbase::value otherval = other->get(pid);
      pval->set(otherval);
    }
  }

  void object::destroy() {
    destroyed = true;
    engine::destroy(this);
    ofactory->loadedobjs[sig["name"]].remove(this);
  }

  /* -- factory methods */
  object::factory::factory(component::factory & cfactory) : cfactory(cfactory) {

  }

  void object::factory::load(object::type objtype, std::string filename) {
    /* open the file */
    if (filename == "") filename = commonsig["objpath"] + objtype + ".yaml";
//     cout << "debug: Loading " << filename << endl;
    std::ifstream fin(filename.c_str());
    if (!fin.is_open()) {
//       cout << "debug: Could not find " << filename << " to load!" << endl;
      return;
    }

    /* initialize yaml parser */
    YAML::Parser parser(fin);
    YAML::Node node;

    signature & sig = signatures[objtype];
    while (parser.GetNextDocument(node)) node >> sig;
    sig["name"] = objtype;

    // add the global signature
    sig.insert(commonsig.begin(), commonsig.end());
    fin.close();
  }

  object::id object::factory::locate(object::type objtype) {
    if (loadedobjs[objtype].size() == 0) return 0;
    else return loadedobjs[objtype].front();
  }

  void object::factory::set(object::type objtype, object::signature sig) {
    signatures[objtype] = sig;
    return;
  }

  void object::factory::innerbuild(object * o, std::string depends) {
    logtrace(log::info);
    trace("Object:", o->name(), "Depends:", depends);
    std::set<std::string> comlist;
    split(comlist, depends, ' ');
    while(comlist.begin() != comlist.end()) {
      component::selector s = *(comlist.begin());

      /* maybe the object already has these loaded */
      component::base * samecom = o->components[s.family];
      if (samecom != 0) {
        if ((s.type == "")) {
          comlist.erase(comlist.begin());
          continue;
        }
        else if ((samecom->type() == s.type)) {
          comlist.erase(comlist.begin());
          continue;
        }
      }

      /* samecom not found, continue normal attach proccess */
      component::base * c = cfactory.build(s);
      if (c == 0) {
        cfactory.load(s);
        c = cfactory.build(s);
      }

      if (c == 0) continue;

      /* first try to attach the component.
       * if something went wrong, try to load
       * its dependencies. if still going wrong, give up
       * and let it fail */
      try {
        o->attach(c);
      } catch (evil & e) {
//         cout << "debug: handling dependencies for " << c->type() << endl;
        /* build dependencies... */
        trace(e.what());
        innerbuild(o, c->depends());

        /* if that build did'nt fixed, fuck it. */
        o->attach(c);
      }

      comlist.erase(comlist.begin());
     }
     trace("Finished", o->name(), depends);
  }

  object::id object::factory::build(gear2d::object::type objtype) {
//     cout << "debug: building " << objtype << endl;
    /* first determine if this object type is loaded... */
    if (signatures.find(objtype) == signatures.end()) {
//       std::cerr << "(Object factory) Object type " << objtype << " not found." << std::endl;
      return 0;
    }

    /* now get the signature of this type */
    object::signature & signature = signatures[objtype];

    /* instantiate the object */
    object * obj = new object(signature);
    obj->ofactory = this;

    /* now get the attach string */
    std::string attachstring = signature["attach"];

    /* if nothing to attach, return the object */
    if (attachstring == "") return obj;

    /* recursive build method that takes care of dependency loading */
    innerbuild(obj, attachstring);
    loadedobjs[objtype].push_back(obj);
    return obj;
  }
}<commit_msg>Setting log level to verbose<commit_after>#include <fstream>
#include "object.h"
#include "component.h"
#include "engine.h"
#include "log.h"
#include "yaml-cpp/yaml.h"

#include <exception>
#include <algorithm>

namespace gear2d {
  object::object(object::signature & sig)
   : destroyed(false)
   , sig(sig) {
  }

  object::~object() {
    // delete all components
    for (componentcontainer::iterator i = components.begin(); i != components.end(); i++) {
      component::base * c = i->second;
      c->owner == 0;
      engine::remove(c);
      // lets the engine delete c;
    }

    // delete all properties
    for (parameterbase::table::iterator i = parameters.begin(); i != parameters.end(); i++) {
      parameterbase * p = i->second;
      if (p != 0) {
        parameters[p->pid] = 0;
        if (p->dodestroy)  {
          delete p;
        }
      }
    }
  }

  object::id object::oid() { return this; }
  std::string object::name() { return sig["name"]; }

  void object::attach(component::base * newc) throw (evil) {
    logverb;
    if (newc == 0) return;

    trace("Attaching", newc->family(), newc->type());

    /* sees that dependencies are met */
    std::string depends = newc->depends();
    bool passed = true;
    std::string d;
    if (depends != "") {
      std::list<std::string> dependencies;
      split(dependencies, depends, ' ');
      while (!dependencies.empty()) {
        component::selector dependency = dependencies.front();

        /* se if family is here */
        component::base * requiredcom = components[dependency.family];
        if (requiredcom == 0) {
          passed = false;
          d = dependency;
          break;
        }

        /* check if dependency has a type. if not, passed. if yes, check */
        if (dependency.type != "") {
          if (requiredcom->type() != dependency.type) {
            passed = false;
            d = dependency;
            break;
          }
        }
        dependencies.pop_front();
      }
    }

    if (passed == false) {
      std::string s;
      s = s + "Component " + newc->family() + "/" + newc->type() + " have unmet dependencies: " + d;
      throw (evil(s));
    }

    /* ok... dependency check has passed! */
    component::base * oldc = deattach(newc->family());
    if (oldc != 0) { delete oldc; }
    newc->owner = this;
    components[newc->family()] = newc;

    newc->setup(sig);
    engine::add(newc);
  }

  component::base * object::deattach(component::family family) {
    component::base * oldc = components[family];
    if (oldc == 0) return 0;
    components.erase(family);
    engine::remove(oldc);
    return oldc;
  }

  parameterbase::value object::get(parameterbase::id pid) {
    return parameters[pid];
  }

  void object::set(parameterbase::id pid, parameterbase::value v) {
    parameters[pid] = v;
    if (v != 0) {
      v->owner = this;
      v->pid = pid;
    }
  }

  component::base * object::component(gear2d::component::family f) {
    return components[f];
  }

  void object::copy(object::id other) {
    if (other == 0) return;
    for (parameterbase::table::iterator it = parameters.begin(); it != parameters.end(); it++) {
      parameterbase::id pid = it->first;
      parameterbase::value pval = it->second;

      parameterbase::value otherval = other->get(pid);
      pval->set(otherval);
    }
  }

  void object::destroy() {
    destroyed = true;
    engine::destroy(this);
    ofactory->loadedobjs[sig["name"]].remove(this);
  }

  /* -- factory methods */
  object::factory::factory(component::factory & cfactory) : cfactory(cfactory) {

  }

  void object::factory::load(object::type objtype, std::string filename) {
    /* open the file */
    if (filename == "") filename = commonsig["objpath"] + objtype + ".yaml";
//     cout << "debug: Loading " << filename << endl;
    std::ifstream fin(filename.c_str());
    if (!fin.is_open()) {
//       cout << "debug: Could not find " << filename << " to load!" << endl;
      return;
    }

    /* initialize yaml parser */
    YAML::Parser parser(fin);
    YAML::Node node;

    signature & sig = signatures[objtype];
    while (parser.GetNextDocument(node)) node >> sig;
    sig["name"] = objtype;

    // add the global signature
    sig.insert(commonsig.begin(), commonsig.end());
    fin.close();
  }

  object::id object::factory::locate(object::type objtype) {
    if (loadedobjs[objtype].size() == 0) return 0;
    else return loadedobjs[objtype].front();
  }

  void object::factory::set(object::type objtype, object::signature sig) {
    signatures[objtype] = sig;
    return;
  }

  void object::factory::innerbuild(object * o, std::string depends) {
    logverb;
    trace("Object:", o->name(), "Depends:", depends);
    std::set<std::string> comlist;
    split(comlist, depends, ' ');
    while(comlist.begin() != comlist.end()) {
      component::selector s = *(comlist.begin());

      /* maybe the object already has these loaded */
      component::base * samecom = o->components[s.family];
      if (samecom != 0) {
        if ((s.type == "")) {
          comlist.erase(comlist.begin());
          continue;
        }
        else if ((samecom->type() == s.type)) {
          comlist.erase(comlist.begin());
          continue;
        }
      }

      /* samecom not found, continue normal attach proccess */
      component::base * c = cfactory.build(s);
      if (c == 0) {
        cfactory.load(s);
        c = cfactory.build(s);
      }

      if (c == 0) continue;

      /* first try to attach the component.
       * if something went wrong, try to load
       * its dependencies. if still going wrong, give up
       * and let it fail */
      try {
        o->attach(c);
      } catch (evil & e) {
//         cout << "debug: handling dependencies for " << c->type() << endl;
        /* build dependencies... */
        trace(e.what());
        innerbuild(o, c->depends());

        /* if that build did'nt fixed, fuck it. */
        o->attach(c);
      }

      comlist.erase(comlist.begin());
     }
     trace("Finished", o->name(), depends);
  }

  object::id object::factory::build(gear2d::object::type objtype) {
//     cout << "debug: building " << objtype << endl;
    /* first determine if this object type is loaded... */
    if (signatures.find(objtype) == signatures.end()) {
//       std::cerr << "(Object factory) Object type " << objtype << " not found." << std::endl;
      return 0;
    }

    /* now get the signature of this type */
    object::signature & signature = signatures[objtype];

    /* instantiate the object */
    object * obj = new object(signature);
    obj->ofactory = this;

    /* now get the attach string */
    std::string attachstring = signature["attach"];

    /* if nothing to attach, return the object */
    if (attachstring == "") return obj;

    /* recursive build method that takes care of dependency loading */
    innerbuild(obj, attachstring);
    loadedobjs[objtype].push_back(obj);
    return obj;
  }
}<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/
#include <qitype/genericvalue.hpp>
#include <qitype/genericobject.hpp>

namespace qi
{

  std::pair<GenericValue, bool> GenericValue::convert(Type* targetType) const
  {
    /* Can have false-negative (same effective type, different Type instances
   * but we do not care, correct check (by comparing info() result
   * is more expensive than the dummy conversion that will happen.
  */
    if (type == targetType)
    {
      return std::make_pair(*this, false);
    }

    GenericValue result;
    Type::Kind skind = type->kind();
    Type::Kind dkind = targetType->kind();
    if (skind == dkind)
    {
      switch(skind)
      {
        case Type::Float:
          result.type = targetType;
          result.value = targetType->initializeStorage();
          static_cast<TypeFloat*>(targetType)->set(&result.value,
                                                   static_cast<TypeFloat*>(type)->get(value));
          return std::make_pair(result, true);
        case Type::Int:
          result.type = targetType;
          result.value = targetType->initializeStorage();
          static_cast<TypeInt*>(targetType)->set(&result.value,
                                                 static_cast<TypeInt*>(type)->get(value));
          return std::make_pair(result, true);
        case Type::String:
          result.type = targetType;
          result.value = targetType->initializeStorage();
          static_cast<TypeString*>(targetType)->set(&result.value,
                                                    static_cast<TypeString*>(type)->getString(value));
          return std::make_pair(result, true);
        case Type::List:
        {
          result.type = targetType;
          GenericList lsrc = asList();
          TypeList* targetListType = static_cast<TypeList*>(targetType);
          Type* srcElemType = lsrc.elementType();
          void* storage = targetType->initializeStorage();
          Type* dstElemType = targetListType->elementType(storage);
          bool needConvert = (srcElemType->info() != dstElemType->info());
          GenericList lresult;
          lresult.type = targetListType;
          lresult.value = storage;
          GenericListIterator i = lsrc.begin();
          GenericListIterator iend = lsrc.end();
          for (; i!= iend; ++i)
          {
            GenericValue val = *i;
            if (!needConvert)
              lresult.pushBack(val);
            else
            {
              std::pair<GenericValue,bool> c = val.convert(dstElemType);
              lresult.pushBack(c.first);
              if (c.second)
                c.first.destroy();
            }
          }
          return std::make_pair(lresult, true);
        }
          break;
        case Type::Map:
        {
          result.type = targetType;
          GenericMap msrc = asMap();

          TypeMap* targetMapType = static_cast<TypeMap*>(targetType);
          TypeMap* srcMapType = static_cast<TypeMap*>(type);

          Type* srcKeyType = srcMapType->keyType(value);
          Type* srcElementType = srcMapType->elementType(value);

          GenericMap mresult;
          mresult.type = targetType;
          mresult.value = targetMapType->initializeStorage();
          Type* targetKeyType = targetMapType->keyType(mresult.value);
          Type* targetElementType = targetMapType->elementType(mresult.value);

          bool sameKey = srcKeyType->info() == targetKeyType->info();
          bool sameElem = srcElementType->info() == targetElementType->info();

          GenericMapIterator i = msrc.begin();
          GenericMapIterator iend = msrc.end();
          for (; i != iend; ++i)
          {
            std::pair<GenericValue, GenericValue> kv = *i;
            std::pair<GenericValue, bool> ck, cv;
            if (!sameKey)
            {
              ck = kv.first.convert(targetKeyType);
              if (!ck.first.type)
                return std::make_pair(GenericValue(), false);
            }
            if (!sameElem)
            {
              cv = kv.second.convert(targetElementType);
              if (!cv.first.type)
                return std::make_pair(GenericValue(), false);
            }
            mresult.insert(sameKey?kv.first:ck.first, sameElem?kv.second:cv.first);
            if (!sameKey && ck.second)
              ck.first.destroy();
            if (!sameElem && cv.second)
              cv.first.destroy();
          }
          return std::make_pair(mresult, true);
        }
          break;
        case Type::Pointer:
        {
          Type* srcPointedType = static_cast<TypePointer*>(type)->pointedType();
          Type* dstPointedType = static_cast<TypePointer*>(targetType)->pointedType();
          // We only try to handle conversion for pointer to objects
          if (srcPointedType->kind() != Type::Object || dstPointedType->kind() != Type::Object)
          {
            // However, we need the full check for exact match here
            if (type->info() == targetType->info())
              return std::make_pair(*this, false);
            else
              return std::make_pair(GenericValue(), false);
          }
          GenericValue pointedSrc = static_cast<TypePointer*>(type)->dereference(value);
          std::pair<GenericValue, bool> pointedDstPair = pointedSrc.convert(dstPointedType);
          if (!pointedDstPair.first.type)
            return std::make_pair(GenericValue(), false);
          if (pointedDstPair.second)
            qiLogError("qi.meta") << "assertion error, allocated converted reference";
          // We must re-reference
          GenericValue pointedDst = pointedDstPair.first;
          void* ptr = pointedDst.type->ptrFromStorage(&pointedDst.value);
          result.type = targetType;
          result.value = targetType->initializeStorage(&ptr);
          return std::make_pair(result, false);
        }
          break;
        case Type::Tuple:
        {
          TypeTuple* tsrc = static_cast<TypeTuple*>(type);
          TypeTuple* tdst = static_cast<TypeTuple*>(targetType);
          std::vector<void*> sourceData = tsrc->get(value);
          std::vector<Type*> srcTypes = tsrc->memberTypes(value);
          std::vector<Type*> dstTypes = tdst->memberTypes(0);
          if (dstTypes.size() != sourceData.size())
          {
            qiLogWarning("qi.meta") << "Conversion failure: tuple size mismatch";
            return std::make_pair(GenericValue(), false);
          }

          std::vector<void*> targetData;
          std::vector<bool> mustDestroy;
          for (unsigned i=0; i<dstTypes.size(); ++i)
          {
            std::pair<GenericValue, bool> conv = GenericValue(srcTypes[i], sourceData[i]).convert(dstTypes[i]);
            if (!conv.first.type)
            {
              qiLogWarning("qi.meta") << "Conversion failure in tuple member between "
                                      << srcTypes[i]->infoString() << " and " << dstTypes[i]->infoString();
              return std::make_pair(GenericValue(), false);
            }
            targetData.push_back(conv.first.value);
            mustDestroy.push_back(conv.second);
          }
          void* dst = tdst->initializeStorage();
          tdst->set(&dst, targetData);
          for (unsigned i=0; i<mustDestroy.size(); ++i)
          {
            if (mustDestroy[i])
              dstTypes[i]->destroy(targetData[i]);
          }
          result.type = targetType;
          result.value = dst;
          return std::make_pair(result, true);
        }
        case Type::Dynamic: {
          result.type  = targetType;
          result.value = targetType->initializeStorage();
          static_cast<TypeDynamic*>(targetType)->set(&result.value, *this);
          return std::make_pair(result, true);
        }
        case Type::Raw: {
          result.type = targetType;
          result.value = targetType->initializeStorage();
          qi::Buffer buf = static_cast<TypeRaw*>(type)->get(value);
          static_cast<TypeRaw*>(targetType)->set(&result.value, buf);
          return std::make_pair(result, true);
        }
        default:
          break;
      } // switch
    } // skind == dkind
    if (skind == Type::Float && dkind == Type::Int)
    {
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeInt*>(targetType)->set(&result.value,
                                             static_cast<TypeFloat*>(type)->get(value));
      return std::make_pair(result, true);
    }
    else if (skind == Type::Int && dkind == Type::Float)
    {
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeFloat*>(targetType)->set(&result.value,
                                               static_cast<TypeInt*>(type)->get(value));
      return std::make_pair(result, true);
    }
    else if (skind == Type::String && dkind == Type::Raw)
    {
      qi::Buffer buf;
      std::pair<char*, size_t> data = static_cast<TypeString*>(type)->get(value);
      memcpy(buf.reserve(data.second), data.first, data.second);
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeRaw*>(result.type)->set(&result.value, buf);
      return std::make_pair(result, true);
    }
    else if (skind == Type::Raw && dkind == Type::String)
    {
      qiLogWarning("qi.meta") << "Conversion attempt from raw to string";
      return std::make_pair(GenericValue(), false);
    }
    static Type* genericValueType = typeOf<GenericValue>();
    static Type* genericObjectType = typeOf<GenericObject>();
    if (targetType->info() == genericValueType->info())
    {
      // Target is metavalue: special case
      GenericValue res;
      res.type = targetType;
      res.value = new GenericValue(*this);
      return std::make_pair(res, false);
    }
    if (type->info() == genericValueType->info())
    { // Source is metavalue: special case
      GenericValue* metaval = (GenericValue*)value;
      return metaval->convert(targetType);
    }
    if (type->info() == genericObjectType->info())
    {
      GenericObject* obj = (GenericObject*)value;
      GenericValue v;
      v.type = obj->type;
      v.value = obj->value;
      return v.convert(targetType);
    }
    if (skind == Type::Object)
    {
      // Try inheritance
      ObjectType* osrc = static_cast<ObjectType*>(type);
      qiLogDebug("qi.meta") << "inheritance check "
                            << osrc <<" " << (osrc?osrc->inherits(targetType):false);
      int inheritOffset = 0;
      if (osrc && (inheritOffset =  osrc->inherits(targetType)) != -1)
      {
        // We return a Value that point to the same data as this.
        result.type = targetType;
        result.value = (void*)((long)value + inheritOffset);
        return std::make_pair(result, false);
      }
    }
    if (type->info() == targetType->info())
    {
      return std::make_pair(*this, false);
    }

    return std::make_pair(GenericValue(), false);
  }

  GenericValue GenericValue::convertCopy(Type* targetType) const
  {
    std::pair<GenericValue, bool> res = convert(targetType);
    if (res.second)
      return res.first;
    else
      return res.first.clone();
  }

}

QI_TYPE_REGISTER(qi::GenericValue);
<commit_msg>GenericValue::convert: Handle target of kind Dynamic.<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/
#include <qitype/genericvalue.hpp>
#include <qitype/genericobject.hpp>

namespace qi
{

  std::pair<GenericValue, bool> GenericValue::convert(Type* targetType) const
  {
    /* Can have false-negative (same effective type, different Type instances
   * but we do not care, correct check (by comparing info() result
   * is more expensive than the dummy conversion that will happen.
  */
    if (type == targetType)
    {
      return std::make_pair(*this, false);
    }

    GenericValue result;
    Type::Kind skind = type->kind();
    Type::Kind dkind = targetType->kind();
    if (skind == dkind)
    {
      switch(skind)
      {
        case Type::Float:
          result.type = targetType;
          result.value = targetType->initializeStorage();
          static_cast<TypeFloat*>(targetType)->set(&result.value,
                                                   static_cast<TypeFloat*>(type)->get(value));
          return std::make_pair(result, true);
        case Type::Int:
          result.type = targetType;
          result.value = targetType->initializeStorage();
          static_cast<TypeInt*>(targetType)->set(&result.value,
                                                 static_cast<TypeInt*>(type)->get(value));
          return std::make_pair(result, true);
        case Type::String:
          result.type = targetType;
          result.value = targetType->initializeStorage();
          static_cast<TypeString*>(targetType)->set(&result.value,
                                                    static_cast<TypeString*>(type)->getString(value));
          return std::make_pair(result, true);
        case Type::List:
        {
          result.type = targetType;
          GenericList lsrc = asList();
          TypeList* targetListType = static_cast<TypeList*>(targetType);
          Type* srcElemType = lsrc.elementType();
          void* storage = targetType->initializeStorage();
          Type* dstElemType = targetListType->elementType(storage);
          bool needConvert = (srcElemType->info() != dstElemType->info());
          GenericList lresult;
          lresult.type = targetListType;
          lresult.value = storage;
          GenericListIterator i = lsrc.begin();
          GenericListIterator iend = lsrc.end();
          for (; i!= iend; ++i)
          {
            GenericValue val = *i;
            if (!needConvert)
              lresult.pushBack(val);
            else
            {
              std::pair<GenericValue,bool> c = val.convert(dstElemType);
              lresult.pushBack(c.first);
              if (c.second)
                c.first.destroy();
            }
          }
          return std::make_pair(lresult, true);
        }
          break;
        case Type::Map:
        {
          result.type = targetType;
          GenericMap msrc = asMap();

          TypeMap* targetMapType = static_cast<TypeMap*>(targetType);
          TypeMap* srcMapType = static_cast<TypeMap*>(type);

          Type* srcKeyType = srcMapType->keyType(value);
          Type* srcElementType = srcMapType->elementType(value);

          GenericMap mresult;
          mresult.type = targetType;
          mresult.value = targetMapType->initializeStorage();
          Type* targetKeyType = targetMapType->keyType(mresult.value);
          Type* targetElementType = targetMapType->elementType(mresult.value);

          bool sameKey = srcKeyType->info() == targetKeyType->info();
          bool sameElem = srcElementType->info() == targetElementType->info();

          GenericMapIterator i = msrc.begin();
          GenericMapIterator iend = msrc.end();
          for (; i != iend; ++i)
          {
            std::pair<GenericValue, GenericValue> kv = *i;
            std::pair<GenericValue, bool> ck, cv;
            if (!sameKey)
            {
              ck = kv.first.convert(targetKeyType);
              if (!ck.first.type)
                return std::make_pair(GenericValue(), false);
            }
            if (!sameElem)
            {
              cv = kv.second.convert(targetElementType);
              if (!cv.first.type)
                return std::make_pair(GenericValue(), false);
            }
            mresult.insert(sameKey?kv.first:ck.first, sameElem?kv.second:cv.first);
            if (!sameKey && ck.second)
              ck.first.destroy();
            if (!sameElem && cv.second)
              cv.first.destroy();
          }
          return std::make_pair(mresult, true);
        }
          break;
        case Type::Pointer:
        {
          Type* srcPointedType = static_cast<TypePointer*>(type)->pointedType();
          Type* dstPointedType = static_cast<TypePointer*>(targetType)->pointedType();
          // We only try to handle conversion for pointer to objects
          if (srcPointedType->kind() != Type::Object || dstPointedType->kind() != Type::Object)
          {
            // However, we need the full check for exact match here
            if (type->info() == targetType->info())
              return std::make_pair(*this, false);
            else
              return std::make_pair(GenericValue(), false);
          }
          GenericValue pointedSrc = static_cast<TypePointer*>(type)->dereference(value);
          std::pair<GenericValue, bool> pointedDstPair = pointedSrc.convert(dstPointedType);
          if (!pointedDstPair.first.type)
            return std::make_pair(GenericValue(), false);
          if (pointedDstPair.second)
            qiLogError("qi.meta") << "assertion error, allocated converted reference";
          // We must re-reference
          GenericValue pointedDst = pointedDstPair.first;
          void* ptr = pointedDst.type->ptrFromStorage(&pointedDst.value);
          result.type = targetType;
          result.value = targetType->initializeStorage(&ptr);
          return std::make_pair(result, false);
        }
          break;
        case Type::Tuple:
        {
          TypeTuple* tsrc = static_cast<TypeTuple*>(type);
          TypeTuple* tdst = static_cast<TypeTuple*>(targetType);
          std::vector<void*> sourceData = tsrc->get(value);
          std::vector<Type*> srcTypes = tsrc->memberTypes(value);
          std::vector<Type*> dstTypes = tdst->memberTypes(0);
          if (dstTypes.size() != sourceData.size())
          {
            qiLogWarning("qi.meta") << "Conversion failure: tuple size mismatch";
            return std::make_pair(GenericValue(), false);
          }

          std::vector<void*> targetData;
          std::vector<bool> mustDestroy;
          for (unsigned i=0; i<dstTypes.size(); ++i)
          {
            std::pair<GenericValue, bool> conv = GenericValue(srcTypes[i], sourceData[i]).convert(dstTypes[i]);
            if (!conv.first.type)
            {
              qiLogWarning("qi.meta") << "Conversion failure in tuple member between "
                                      << srcTypes[i]->infoString() << " and " << dstTypes[i]->infoString();
              return std::make_pair(GenericValue(), false);
            }
            targetData.push_back(conv.first.value);
            mustDestroy.push_back(conv.second);
          }
          void* dst = tdst->initializeStorage();
          tdst->set(&dst, targetData);
          for (unsigned i=0; i<mustDestroy.size(); ++i)
          {
            if (mustDestroy[i])
              dstTypes[i]->destroy(targetData[i]);
          }
          result.type = targetType;
          result.value = dst;
          return std::make_pair(result, true);
        }
        case Type::Dynamic: {
          result.type  = targetType;
          result.value = targetType->initializeStorage();
          static_cast<TypeDynamic*>(targetType)->set(&result.value, *this);
          return std::make_pair(result, true);
        }
        case Type::Raw: {
          result.type = targetType;
          result.value = targetType->initializeStorage();
          qi::Buffer buf = static_cast<TypeRaw*>(type)->get(value);
          static_cast<TypeRaw*>(targetType)->set(&result.value, buf);
          return std::make_pair(result, true);
        }
        default:
          break;
      } // switch
    } // skind == dkind
    if (skind == Type::Float && dkind == Type::Int)
    {
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeInt*>(targetType)->set(&result.value,
                                             static_cast<TypeFloat*>(type)->get(value));
      return std::make_pair(result, true);
    }
    else if (skind == Type::Int && dkind == Type::Float)
    {
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeFloat*>(targetType)->set(&result.value,
                                               static_cast<TypeInt*>(type)->get(value));
      return std::make_pair(result, true);
    }
    else if (skind == Type::String && dkind == Type::Raw)
    {
      qi::Buffer buf;
      std::pair<char*, size_t> data = static_cast<TypeString*>(type)->get(value);
      memcpy(buf.reserve(data.second), data.first, data.second);
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeRaw*>(result.type)->set(&result.value, buf);
      return std::make_pair(result, true);
    }
    else if (skind == Type::Raw && dkind == Type::String)
    {
      qiLogWarning("qi.meta") << "Conversion attempt from raw to string";
      return std::make_pair(GenericValue(), false);
    }
    if (targetType->kind() == Type::Dynamic)
    {
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeDynamic*>(targetType)->set(&result.value, *this);
      return std::make_pair(result, true);
    }
    static Type* genericValueType = typeOf<GenericValue>();
    static Type* genericObjectType = typeOf<GenericObject>();

    if (type->info() == genericValueType->info())
    { // Source is metavalue: special case
      GenericValue* metaval = (GenericValue*)value;
      return metaval->convert(targetType);
    }
    if (type->info() == genericObjectType->info())
    {
      GenericObject* obj = (GenericObject*)value;
      GenericValue v;
      v.type = obj->type;
      v.value = obj->value;
      return v.convert(targetType);
    }
    if (skind == Type::Object)
    {
      // Try inheritance
      ObjectType* osrc = static_cast<ObjectType*>(type);
      qiLogDebug("qi.meta") << "inheritance check "
                            << osrc <<" " << (osrc?osrc->inherits(targetType):false);
      int inheritOffset = 0;
      if (osrc && (inheritOffset =  osrc->inherits(targetType)) != -1)
      {
        // We return a Value that point to the same data as this.
        result.type = targetType;
        result.value = (void*)((long)value + inheritOffset);
        return std::make_pair(result, false);
      }
    }
    if (type->info() == targetType->info())
    {
      return std::make_pair(*this, false);
    }

    return std::make_pair(GenericValue(), false);
  }

  GenericValue GenericValue::convertCopy(Type* targetType) const
  {
    std::pair<GenericValue, bool> res = convert(targetType);
    if (res.second)
      return res.first;
    else
      return res.first.clone();
  }

}

QI_TYPE_REGISTER(qi::GenericValue);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 ScyllaDB
 */

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

#include "init.hh"
#include "supervisor.hh"
#include "directories.hh"
#include "distributed_loader.hh"
#include "disk-error-handler.hh"

namespace utils {

static future<> disk_sanity(sstring path, bool developer_mode) {
    return check_direct_io_support(path).then([] {
        return make_ready_future<>();
    }).handle_exception([path](auto ep) {
        startlog.error("Could not access {}: {}", path, ep);
        return make_exception_future<>(ep);
    });
};

future<> directories::touch_and_lock(sstring path) {
    return io_check([path] { return recursive_touch_directory(path); }).then_wrapped([this, path] (future<> f) {
        try {
            f.get();
            return file_lock::acquire(fs::path(path) / ".lock").then([this](file_lock lock) {
               _locks.emplace_back(std::move(lock));
            }).handle_exception([path](auto ep) {
                // only do this because "normal" unhandled exception exit in seastar
                // _drops_ system_error message ("what()") and thus does not quite deliver
                // the relevant info to the user
                try {
                    std::rethrow_exception(ep);
                } catch (std::exception& e) {
                    startlog.error("Could not initialize {}: {}", path, e.what());
                    throw;
                } catch (...) {
                    throw;
                }
            });
        } catch (...) {
            startlog.error("Directory '{}' cannot be initialized. Tried to do it but failed with: {}", path, std::current_exception());
            throw;
        }
    });
}

future<> directories::init(db::config& cfg, bool hinted_handoff_enabled) {
  // XXX -- this indentation is temporary, wil go away with next patches
  return seastar::async([&] {
    std::unordered_set<sstring> directories;
    directories.insert(cfg.data_file_directories().cbegin(),
            cfg.data_file_directories().cend());
    directories.insert(cfg.commitlog_directory());

    if (hinted_handoff_enabled) {
        fs::path hints_base_dir(cfg.hints_directory());
        directories.insert(cfg.hints_directory());
        for (unsigned i = 0; i < smp::count; ++i) {
            sstring shard_dir((hints_base_dir / seastar::to_sstring(i).c_str()).native());
            directories.insert(std::move(shard_dir));
        }
    }
    fs::path view_pending_updates_base_dir = fs::path(cfg.view_hints_directory());
    sstring view_pending_updates_base_dir_str = view_pending_updates_base_dir.native();
    directories.insert(view_pending_updates_base_dir_str);
    for (unsigned i = 0; i < smp::count; ++i) {
        sstring shard_dir((view_pending_updates_base_dir / seastar::to_sstring(i).c_str()).native());
        directories.insert(std::move(shard_dir));
    }

    supervisor::notify("creating and verifying directories");
    parallel_for_each(directories, [this, &cfg] (sstring path) {
        return touch_and_lock(path).then([path = std::move(path), &cfg] {
            return disk_sanity(path, cfg.developer_mode()).then([path = std::move(path)] {
                return distributed_loader::verify_owner_and_mode(fs::path(path)).handle_exception([](auto ep) {
                    startlog.error("Failed owner and mode verification: {}", ep);
                    return make_exception_future<>(ep);
                });
            });
        });
    }).get();
  });
}

} // namespace utils
<commit_msg>directories: Drop seastar::async usage<commit_after>/*
 * Copyright (C) 2019 ScyllaDB
 */

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

#include "init.hh"
#include "supervisor.hh"
#include "directories.hh"
#include "distributed_loader.hh"
#include "disk-error-handler.hh"

namespace utils {

static future<> disk_sanity(sstring path, bool developer_mode) {
    return check_direct_io_support(path).then([] {
        return make_ready_future<>();
    }).handle_exception([path](auto ep) {
        startlog.error("Could not access {}: {}", path, ep);
        return make_exception_future<>(ep);
    });
};

future<> directories::touch_and_lock(sstring path) {
    return io_check([path] { return recursive_touch_directory(path); }).then_wrapped([this, path] (future<> f) {
        try {
            f.get();
            return file_lock::acquire(fs::path(path) / ".lock").then([this](file_lock lock) {
               _locks.emplace_back(std::move(lock));
            }).handle_exception([path](auto ep) {
                // only do this because "normal" unhandled exception exit in seastar
                // _drops_ system_error message ("what()") and thus does not quite deliver
                // the relevant info to the user
                try {
                    std::rethrow_exception(ep);
                } catch (std::exception& e) {
                    startlog.error("Could not initialize {}: {}", path, e.what());
                    throw;
                } catch (...) {
                    throw;
                }
            });
        } catch (...) {
            startlog.error("Directory '{}' cannot be initialized. Tried to do it but failed with: {}", path, std::current_exception());
            throw;
        }
    });
}

future<> directories::init(db::config& cfg, bool hinted_handoff_enabled) {
    std::unordered_set<sstring> directories;
    directories.insert(cfg.data_file_directories().cbegin(),
            cfg.data_file_directories().cend());
    directories.insert(cfg.commitlog_directory());

    if (hinted_handoff_enabled) {
        fs::path hints_base_dir(cfg.hints_directory());
        directories.insert(cfg.hints_directory());
        for (unsigned i = 0; i < smp::count; ++i) {
            sstring shard_dir((hints_base_dir / seastar::to_sstring(i).c_str()).native());
            directories.insert(std::move(shard_dir));
        }
    }
    fs::path view_pending_updates_base_dir = fs::path(cfg.view_hints_directory());
    sstring view_pending_updates_base_dir_str = view_pending_updates_base_dir.native();
    directories.insert(view_pending_updates_base_dir_str);
    for (unsigned i = 0; i < smp::count; ++i) {
        sstring shard_dir((view_pending_updates_base_dir / seastar::to_sstring(i).c_str()).native());
        directories.insert(std::move(shard_dir));
    }

    supervisor::notify("creating and verifying directories");
    return parallel_for_each(directories, [this, &cfg] (sstring path) {
        return touch_and_lock(path).then([path = std::move(path), &cfg] {
            return disk_sanity(path, cfg.developer_mode()).then([path = std::move(path)] {
                return distributed_loader::verify_owner_and_mode(fs::path(path)).handle_exception([](auto ep) {
                    startlog.error("Failed owner and mode verification: {}", ep);
                    return make_exception_future<>(ep);
                });
            });
        });
    });
}

} // namespace utils
<|endoftext|>