<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/base_traits.hpp"
#include "dll/recurrent_neural_layer.hpp"

#include "dll/util/timers.hpp" // for auto_timer

namespace dll {

/*!
 * \brief Standard dense layer of neural network.
 */
template <typename Desc>
struct recurrent_layer_impl final : recurrent_neural_layer<recurrent_layer_impl<Desc>, Desc> {
    using desc        = Desc;                                    ///< The descriptor of the layer
    using weight      = typename desc::weight;                   ///< The data type for this layer
    using this_type   = recurrent_layer_impl<desc>;              ///< The type of this layer
    using base_type   = recurrent_neural_layer<this_type, desc>; ///< The base type
    using layer_t     = this_type;                               ///< This layer's type
    using dyn_layer_t = typename desc::dyn_layer_t;              ///< The dynamic version of this layer

    static constexpr size_t time_steps      = desc::time_steps;      ///< The number of time steps
    static constexpr size_t sequence_length = desc::sequence_length; ///< The length of the sequences
    static constexpr size_t hidden_units    = desc::hidden_units;    ///< The number of hidden units

    static constexpr auto activation_function = desc::activation_function; ///< The layer's activation function

    using w_initializer = typename desc::w_initializer; ///< The initializer for the weights

    using input_one_t  = etl::fast_dyn_matrix<weight, time_steps, sequence_length>; ///< The type of one input
    using output_one_t = etl::fast_dyn_matrix<weight, time_steps, hidden_units>;    ///< The type of one output
    using input_t      = std::vector<input_one_t>;                                  ///< The type of the input
    using output_t     = std::vector<output_one_t>;                                 ///< The type of the output

    using w_type = etl::fast_matrix<weight, hidden_units, hidden_units>;    ///< The type of the W weights
    using u_type = etl::fast_matrix<weight, hidden_units, sequence_length>; ///< The type of the U weights

    //Weights and biases
    w_type w; ///< Weights W
    u_type u; ///< Weights U

    //Backup Weights and biases
    std::unique_ptr<w_type> bak_w; ///< Backup Weights W
    std::unique_ptr<u_type> bak_u; ///< Backup Weights U

    /*!
     * \brief Initialize a recurrent layer with basic weights.
     *
     * The weights are initialized from a normal distribution of
     * zero-mean and unit variance.
     */
    recurrent_layer_impl() : base_type() {
        w_initializer::initialize(w, input_size(), output_size());
        w_initializer::initialize(u, input_size(), output_size());
    }

    /*!
     * \brief Returns the input size of this layer
     */
    static constexpr size_t input_size() noexcept {
        return time_steps * sequence_length;
    }

    /*!
     * \brief Returns the output size of this layer
     */
    static constexpr size_t output_size() noexcept {
        return time_steps * hidden_units;
    }

    /*!
     * \brief Returns the number of parameters of this layer
     */
    static constexpr size_t parameters() noexcept {
        return hidden_units * hidden_units + hidden_units * sequence_length;
    }

    /*!
     * \brief Returns a short description of the layer
     * \return an std::string containing a short description of the layer
     */
    static std::string to_short_string(std::string pre = "") {
        cpp_unused(pre);

        char buffer[512];

        if /*constexpr*/ (activation_function == function::IDENTITY) {
            snprintf(buffer, 512, "RNN: %lux%lu -> %lux%lu", time_steps, sequence_length, time_steps, hidden_units);
        } else {
            snprintf(buffer, 512, "RNN: %lux%lu -> %s -> %lux%lu", time_steps, sequence_length, to_string(activation_function).c_str(), time_steps, hidden_units);
        }

        return {buffer};
    }

    /*!
     * \brief Apply the layer to the given batch of input.
     *
     * \param x A batch of input
     * \param output A batch of output that will be filled
     */
    template <typename H, typename V>
    void forward_batch(H&& output, const V& x) const {
        dll::auto_timer timer("recurrent:forward_batch");

        const auto Batch = etl::dim<0>(x);

        cpp_assert(etl::dim<0>(output) == Batch, "The number of samples must be consistent");

        output = 0;

        // TODO: Efficient way: Rearrange input / output

        // t == 0

        for (size_t b = 0; b < Batch; ++b) {
            output(b)(0) = etl::sigmoid(u * x(b)(0));
        }

        for(size_t t = 1; t < time_steps; ++t){
            for(size_t b = 0; b < Batch; ++b){
                output(b)(t) = etl::sigmoid(u * x(b)(t) + w * output(b)(t-1));
            }
        }
    }

    /*!
     * \brief Prepare one empty output for this layer
     * \return an empty ETL matrix suitable to store one output of this layer
     *
     * \tparam Input The type of one Input
     */
    template <typename Input>
    output_one_t prepare_one_output() const {
        return {};
    }

    /*!
     * \brief Prepare a set of empty outputs for this layer
     * \param samples The number of samples to prepare the output for
     * \return a container containing empty ETL matrices suitable to store samples output of this layer
     * \tparam Input The type of one input
     */
    template <typename Input>
    static output_t prepare_output(size_t samples) {
        return output_t{samples};
    }

    /*!
     * \brief Initialize the dynamic version of the layer from the
     * fast version of the layer
     * \param dyn Reference to the dynamic version of the layer that
     * needs to be initialized
     */
    template<typename DLayer>
    static void dyn_init(DLayer& dyn){
        cpp_unused(dyn);
        //TODO dyn.init_layer(num_visible, num_hidden);
    }

    /*!
     * \brief Adapt the errors, called before backpropagation of the errors.
     *
     * This must be used by layers that have both an activation fnction and a non-linearity.
     *
     * \param context the training context
     */
    template<typename C>
    void adapt_errors(C& context) const {
        dll::auto_timer timer("recurrent:adapt_errors");

        if /*constexpr*/ (activation_function != function::IDENTITY){
            context.errors = f_derivative<activation_function>(context.output) >> context.errors;
        }
    }

    /*!
     * \brief Backpropagate the errors to the previous layers
     * \param output The ETL expression into which write the output
     * \param context The training context
     */
    template<typename H, typename C>
    void backward_batch(H&& output, C& context) const {
        dll::auto_timer timer("recurrent:backward_batch");

        cpp_unused(output);
        cpp_unused(context);

        //TODO

        // The reshape has no overhead, so better than SFINAE for nothing
        //constexpr auto Batch = etl::decay_traits<decltype(context.errors)>::template dim<0>();
        //etl::reshape<Batch, num_visible>(output) = context.errors * etl::transpose(w);
    }

    /*!
     * \brief Compute the gradients for this layer, if any
     * \param context The trainng context
     */
    template<typename C>
    void compute_gradients(C& context) const {
        dll::auto_timer timer("recurrent:compute_gradients");

        cpp_unused(context);

        //std::get<0>(context.up.context)->grad = batch_outer(context.input, context.errors);
    }
};

//Allow odr-use of the constexpr static members

template <typename Desc>
const size_t recurrent_layer_impl<Desc>::time_steps;

template <typename Desc>
const size_t recurrent_layer_impl<Desc>::sequence_length;

template <typename Desc>
const size_t recurrent_layer_impl<Desc>::hidden_units;

// Declare the traits for the Layer

template<typename Desc>
struct layer_base_traits<recurrent_layer_impl<Desc>> {
    static constexpr bool is_neural     = true;  ///< Indicates if the layer is a neural layer
    static constexpr bool is_dense      = false;  ///< Indicates if the layer is dense
    static constexpr bool is_conv       = false; ///< Indicates if the layer is convolutional
    static constexpr bool is_deconv     = false; ///< Indicates if the layer is deconvolutional
    static constexpr bool is_standard   = true;  ///< Indicates if the layer is standard
    static constexpr bool is_rbm        = false;  ///< Indicates if the layer is RBM
    static constexpr bool is_pooling    = false; ///< Indicates if the layer is a pooling layer
    static constexpr bool is_unpooling  = false; ///< Indicates if the layer is an unpooling laye
    static constexpr bool is_transform  = false; ///< Indicates if the layer is a transform layer
    static constexpr bool is_dynamic    = false; ///< Indicates if the layer is dynamic
    static constexpr bool pretrain_last = false; ///< Indicates if the layer is dynamic
    static constexpr bool sgd_supported = true;  ///< Indicates if the layer is supported by SGD
};

/*!
 * \brief specialization of sgd_context for recurrent_layer_impl
 */
template <typename DBN, typename Desc, size_t L>
struct sgd_context<DBN, recurrent_layer_impl<Desc>, L> {
    using layer_t = recurrent_layer_impl<Desc>;
    using weight  = typename layer_t::weight; ///< The data type for this layer

    static constexpr size_t time_steps      = layer_t::time_steps;      ///< The number of time steps
    static constexpr size_t sequence_length = layer_t::sequence_length; ///< The length of the sequences
    static constexpr size_t hidden_units    = layer_t::hidden_units;    ///< The number of hidden units

    static constexpr auto batch_size = DBN::batch_size;

    etl::fast_matrix<weight, batch_size, time_steps, sequence_length> input;
    etl::fast_matrix<weight, batch_size, time_steps, hidden_units> output;
    etl::fast_matrix<weight, batch_size, time_steps, hidden_units> errors;

    sgd_context(const recurrent_layer_impl<Desc>& /* layer */)
            : output(0.0), errors(0.0) {}
};

} //end of dll namespace
<commit_msg>First prototype of BPTT<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/base_traits.hpp"
#include "dll/recurrent_neural_layer.hpp"

#include "dll/util/timers.hpp" // for auto_timer

namespace dll {

/*!
 * \brief Standard dense layer of neural network.
 */
template <typename Desc>
struct recurrent_layer_impl final : recurrent_neural_layer<recurrent_layer_impl<Desc>, Desc> {
    using desc        = Desc;                                    ///< The descriptor of the layer
    using weight      = typename desc::weight;                   ///< The data type for this layer
    using this_type   = recurrent_layer_impl<desc>;              ///< The type of this layer
    using base_type   = recurrent_neural_layer<this_type, desc>; ///< The base type
    using layer_t     = this_type;                               ///< This layer's type
    using dyn_layer_t = typename desc::dyn_layer_t;              ///< The dynamic version of this layer

    static constexpr size_t time_steps      = desc::time_steps;      ///< The number of time steps
    static constexpr size_t sequence_length = desc::sequence_length; ///< The length of the sequences
    static constexpr size_t hidden_units    = desc::hidden_units;    ///< The number of hidden units

    static constexpr auto activation_function = desc::activation_function; ///< The layer's activation function

    using w_initializer = typename desc::w_initializer; ///< The initializer for the weights

    using input_one_t  = etl::fast_dyn_matrix<weight, time_steps, sequence_length>; ///< The type of one input
    using output_one_t = etl::fast_dyn_matrix<weight, time_steps, hidden_units>;    ///< The type of one output
    using input_t      = std::vector<input_one_t>;                                  ///< The type of the input
    using output_t     = std::vector<output_one_t>;                                 ///< The type of the output

    using w_type = etl::fast_matrix<weight, hidden_units, hidden_units>;    ///< The type of the W weights
    using u_type = etl::fast_matrix<weight, hidden_units, sequence_length>; ///< The type of the U weights

    //Weights and biases
    w_type w; ///< Weights W
    u_type u; ///< Weights U

    //Backup Weights and biases
    std::unique_ptr<w_type> bak_w; ///< Backup Weights W
    std::unique_ptr<u_type> bak_u; ///< Backup Weights U

    /*!
     * \brief Initialize a recurrent layer with basic weights.
     *
     * The weights are initialized from a normal distribution of
     * zero-mean and unit variance.
     */
    recurrent_layer_impl() : base_type() {
        w_initializer::initialize(w, input_size(), output_size());
        w_initializer::initialize(u, input_size(), output_size());
    }

    /*!
     * \brief Returns the input size of this layer
     */
    static constexpr size_t input_size() noexcept {
        return time_steps * sequence_length;
    }

    /*!
     * \brief Returns the output size of this layer
     */
    static constexpr size_t output_size() noexcept {
        return time_steps * hidden_units;
    }

    /*!
     * \brief Returns the number of parameters of this layer
     */
    static constexpr size_t parameters() noexcept {
        return hidden_units * hidden_units + hidden_units * sequence_length;
    }

    /*!
     * \brief Returns a short description of the layer
     * \return an std::string containing a short description of the layer
     */
    static std::string to_short_string(std::string pre = "") {
        cpp_unused(pre);

        char buffer[512];

        if /*constexpr*/ (activation_function == function::IDENTITY) {
            snprintf(buffer, 512, "RNN: %lux%lu -> %lux%lu", time_steps, sequence_length, time_steps, hidden_units);
        } else {
            snprintf(buffer, 512, "RNN: %lux%lu -> %s -> %lux%lu", time_steps, sequence_length, to_string(activation_function).c_str(), time_steps, hidden_units);
        }

        return {buffer};
    }

    /*!
     * \brief Apply the layer to the given batch of input.
     *
     * \param x A batch of input
     * \param output A batch of output that will be filled
     */
    template <typename H, typename V>
    void forward_batch(H&& output, const V& x) const {
        dll::auto_timer timer("recurrent:forward_batch");

        const auto Batch = etl::dim<0>(x);

        cpp_assert(etl::dim<0>(output) == Batch, "The number of samples must be consistent");

        output = 0;

        // TODO: Efficient way: Rearrange input / output

        // t == 0

        for (size_t b = 0; b < Batch; ++b) {
            output(b)(0) = f_activate<activation_function>(u * x(b)(0));
        }

        for (size_t b = 0; b < Batch; ++b) {
            for (size_t t = 1; t < time_steps; ++t) {
                output(b)(t) = f_activate<activation_function>(u * x(b)(t) + w * output(b)(t - 1));
            }
        }
    }

    /*!
     * \brief Prepare one empty output for this layer
     * \return an empty ETL matrix suitable to store one output of this layer
     *
     * \tparam Input The type of one Input
     */
    template <typename Input>
    output_one_t prepare_one_output() const {
        return {};
    }

    /*!
     * \brief Prepare a set of empty outputs for this layer
     * \param samples The number of samples to prepare the output for
     * \return a container containing empty ETL matrices suitable to store samples output of this layer
     * \tparam Input The type of one input
     */
    template <typename Input>
    static output_t prepare_output(size_t samples) {
        return output_t{samples};
    }

    /*!
     * \brief Initialize the dynamic version of the layer from the
     * fast version of the layer
     * \param dyn Reference to the dynamic version of the layer that
     * needs to be initialized
     */
    template<typename DLayer>
    static void dyn_init(DLayer& dyn){
        cpp_unused(dyn);
        //TODO dyn.init_layer(num_visible, num_hidden);
    }

    /*!
     * \brief Adapt the errors, called before backpropagation of the errors.
     *
     * This must be used by layers that have both an activation fnction and a non-linearity.
     *
     * \param context the training context
     */
    template<typename C>
    void adapt_errors(C& context) const {
        // Nothing to do here (done in BPTT)
        cpp_unused(context);
    }

    /*!
     * \brief Backpropagate the errors to the previous layers
     * \param output The ETL expression into which write the output
     * \param context The training context
     */
    template<typename H, typename C>
    void backward_batch(H&& output, C& context) const {
        dll::auto_timer timer("recurrent:backward_batch");

        cpp_unused(output);
        cpp_unused(context);

        //TODO

        // The reshape has no overhead, so better than SFINAE for nothing
        //constexpr auto Batch = etl::decay_traits<decltype(context.errors)>::template dim<0>();
        //etl::reshape<Batch, num_visible>(output) = context.errors * etl::transpose(w);
    }

    /*!
     * \brief Compute the gradients for this layer, if any
     * \param context The trainng context
     */
    template<typename C>
    void compute_gradients(C& context) const {
        dll::auto_timer timer("recurrent:compute_gradients");

        const size_t Batch = etl::dim<0>(context.errors);

        auto& w_grad = std::get<0>(context.up.context)->grad;
        auto& u_grad = std::get<1>(context.up.context)->grad;

        w_grad = 0;
        u_grad = 0;

        //size_t t = time_steps - 1;

        //do {
            for (size_t b = 0; b < Batch; ++b) {
                size_t step            = time_steps - 1;
                const size_t truncate  = time_steps; //TODO Truncate ?
                const size_t last_step = std::max(int(time_steps) - int(truncate), 0);

                auto delta_t = etl::force_temporary(context.errors(b)(step) >> f_derivative<activation_function>(context.output(b)(step)));

                do {
                    w_grad += etl::outer(delta_t, context.output(b)(step - 1));
                    u_grad += etl::outer(delta_t, context.input(b)(step - 1));

                    delta_t = trans(w) * delta_t >> f_derivative<activation_function>(context.output(b)(step -1));

                    --step;
                } while (step > last_step);
            }

            //--t;
        //} while(t != 0);
    }
};

//Allow odr-use of the constexpr static members

template <typename Desc>
const size_t recurrent_layer_impl<Desc>::time_steps;

template <typename Desc>
const size_t recurrent_layer_impl<Desc>::sequence_length;

template <typename Desc>
const size_t recurrent_layer_impl<Desc>::hidden_units;

// Declare the traits for the Layer

template<typename Desc>
struct layer_base_traits<recurrent_layer_impl<Desc>> {
    static constexpr bool is_neural     = true;  ///< Indicates if the layer is a neural layer
    static constexpr bool is_dense      = false;  ///< Indicates if the layer is dense
    static constexpr bool is_conv       = false; ///< Indicates if the layer is convolutional
    static constexpr bool is_deconv     = false; ///< Indicates if the layer is deconvolutional
    static constexpr bool is_standard   = true;  ///< Indicates if the layer is standard
    static constexpr bool is_rbm        = false;  ///< Indicates if the layer is RBM
    static constexpr bool is_pooling    = false; ///< Indicates if the layer is a pooling layer
    static constexpr bool is_unpooling  = false; ///< Indicates if the layer is an unpooling laye
    static constexpr bool is_transform  = false; ///< Indicates if the layer is a transform layer
    static constexpr bool is_dynamic    = false; ///< Indicates if the layer is dynamic
    static constexpr bool pretrain_last = false; ///< Indicates if the layer is dynamic
    static constexpr bool sgd_supported = true;  ///< Indicates if the layer is supported by SGD
};

/*!
 * \brief specialization of sgd_context for recurrent_layer_impl
 */
template <typename DBN, typename Desc, size_t L>
struct sgd_context<DBN, recurrent_layer_impl<Desc>, L> {
    using layer_t = recurrent_layer_impl<Desc>;
    using weight  = typename layer_t::weight; ///< The data type for this layer

    static constexpr size_t time_steps      = layer_t::time_steps;      ///< The number of time steps
    static constexpr size_t sequence_length = layer_t::sequence_length; ///< The length of the sequences
    static constexpr size_t hidden_units    = layer_t::hidden_units;    ///< The number of hidden units

    static constexpr auto batch_size = DBN::batch_size;

    etl::fast_matrix<weight, batch_size, time_steps, sequence_length> input;
    etl::fast_matrix<weight, batch_size, time_steps, hidden_units> output;
    etl::fast_matrix<weight, batch_size, time_steps, hidden_units> errors;

    sgd_context(const recurrent_layer_impl<Desc>& /* layer */)
            : output(0.0), errors(0.0) {}
};

} //end of dll namespace
<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2011 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "ft-receiver-handler.h"
#include "_gen/ft-receiver-handler.moc.hpp"

#include "ft-receive-op.h"

#include <TelepathyQt4/Channel>
#include <TelepathyQt4/ChannelClassSpec>
#include <TelepathyQt4/ChannelClassSpecList>
#include <TelepathyQt4/ChannelRequest>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4/MethodInvocationContext>
#include <TelepathyQt4/IncomingFileTransferChannel>

#include <QDateTime>
#include <QDebug>

FTReceiverHandler::FTReceiverHandler()
    : QObject(),
      AbstractClientHandler(ChannelClassSpecList() << ChannelClassSpec::incomingFileTransfer(),
              AbstractClientHandler::Capabilities(), false)
{
}

FTReceiverHandler::~FTReceiverHandler()
{
}

bool FTReceiverHandler::bypassApproval() const
{
    return false;
}

void FTReceiverHandler::handleChannels(const MethodInvocationContextPtr<> &context,
        const AccountPtr &account,
        const ConnectionPtr &connection,
        const QList<ChannelPtr> &channels,
        const QList<ChannelRequestPtr> &requestsSatisfied,
        const QDateTime &userActionTime,
        const HandlerInfo &handlerInfo)
{
    Q_ASSERT(channels.size() == 1);
    ChannelPtr chan = channels.first();

    context->setFinished();

    if (!chan->isValid()) {
        qWarning() << "Channel received to handle is invalid, ignoring channel";
        chan->requestClose();
    }

    if (chan->channelType() != TP_QT4_IFACE_CHANNEL_TYPE_FILE_TRANSFER) {
        qWarning() << "Channel received to handle is not of type FileTransfer, service confused. "
            "Ignoring channel";
        chan->requestClose();
        return;
    }

    if (chan->isRequested()) {
        qWarning() << "Channel received to handle is not an incoming file transfer channel, "
            "service confused. Ignoring channel";
        chan->requestClose();
        return;
    }

    IncomingFileTransferChannelPtr iftChan = IncomingFileTransferChannelPtr::qObjectCast(chan);
    if (!iftChan) {
        qWarning() << "Channel received to handle is not a subclass of IncomingFileTransferChannel. "
            "ChannelFactory set on this handler's account must construct IncomingFileTransferChannel "
            "subclasses for incoming channels of type FileTransfer. Ignoring channel";
        chan->requestClose();
        return;
    }

    FTReceiveOp *rop = new FTReceiveOp(iftChan,
            SharedPtr<RefCounted>::dynamicCast(AbstractClientPtr(this)));
    connect(rop,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onReceiveFinished(Tp::PendingOperation*)));
}

void FTReceiverHandler::onReceiveFinished(PendingOperation *op)
{
    FTReceiveOp *rop = qobject_cast<FTReceiveOp*>(op);
    qDebug() << "Closing channel";
    rop->channel()->requestClose();
}
<commit_msg>file-transfer example: Do not try to close invalid channels, and raise an error when an invalid channel is received on receiver handler.<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2011 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "ft-receiver-handler.h"
#include "_gen/ft-receiver-handler.moc.hpp"

#include "ft-receive-op.h"

#include <TelepathyQt4/Channel>
#include <TelepathyQt4/ChannelClassSpec>
#include <TelepathyQt4/ChannelClassSpecList>
#include <TelepathyQt4/ChannelRequest>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4/MethodInvocationContext>
#include <TelepathyQt4/IncomingFileTransferChannel>

#include <QDateTime>
#include <QDebug>

FTReceiverHandler::FTReceiverHandler()
    : QObject(),
      AbstractClientHandler(ChannelClassSpecList() << ChannelClassSpec::incomingFileTransfer(),
              AbstractClientHandler::Capabilities(), false)
{
}

FTReceiverHandler::~FTReceiverHandler()
{
}

bool FTReceiverHandler::bypassApproval() const
{
    return false;
}

void FTReceiverHandler::handleChannels(const MethodInvocationContextPtr<> &context,
        const AccountPtr &account,
        const ConnectionPtr &connection,
        const QList<ChannelPtr> &channels,
        const QList<ChannelRequestPtr> &requestsSatisfied,
        const QDateTime &userActionTime,
        const HandlerInfo &handlerInfo)
{
    Q_ASSERT(channels.size() == 1);
    ChannelPtr chan = channels.first();

    if (!chan->isValid()) {
        qWarning() << "Channel received to handle is invalid, ignoring channel";
        context->setFinishedWithError(TP_QT4_ERROR_INVALID_ARGUMENT,
                QLatin1String("Channel received to handle is invalid"));
        return;
    }

    context->setFinished();

    if (chan->channelType() != TP_QT4_IFACE_CHANNEL_TYPE_FILE_TRANSFER) {
        qWarning() << "Channel received to handle is not of type FileTransfer, service confused. "
            "Ignoring channel";
        chan->requestClose();
        return;
    }

    if (chan->isRequested()) {
        qWarning() << "Channel received to handle is not an incoming file transfer channel, "
            "service confused. Ignoring channel";
        chan->requestClose();
        return;
    }

    IncomingFileTransferChannelPtr iftChan = IncomingFileTransferChannelPtr::qObjectCast(chan);
    if (!iftChan) {
        qWarning() << "Channel received to handle is not a subclass of IncomingFileTransferChannel. "
            "ChannelFactory set on this handler's account must construct IncomingFileTransferChannel "
            "subclasses for incoming channels of type FileTransfer. Ignoring channel";
        chan->requestClose();
        return;
    }

    FTReceiveOp *rop = new FTReceiveOp(iftChan,
            SharedPtr<RefCounted>::dynamicCast(AbstractClientPtr(this)));
    connect(rop,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onReceiveFinished(Tp::PendingOperation*)));
}

void FTReceiverHandler::onReceiveFinished(PendingOperation *op)
{
    FTReceiveOp *rop = qobject_cast<FTReceiveOp*>(op);
    qDebug() << "Closing channel";
    rop->channel()->requestClose();
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * 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.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  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.
 */

/** \author Bastian Steder */

#include <iostream>
using std::cout;
using std::cerr;

#include <pcl/range_image/range_image_planar.h>

namespace pcl
{
  /////////////////////////////////////////////////////////////////////////
  RangeImagePlanar::RangeImagePlanar () : RangeImage(), focal_length_x_(0.0f), focal_length_y_(0.0f),
                                          focal_length_x_reciprocal_(0.0f), focal_length_y_reciprocal_(0.0f),
                                          center_x_(0.0f), center_y_(0.0f)
  {
  }

  /////////////////////////////////////////////////////////////////////////
  RangeImagePlanar::~RangeImagePlanar ()
  {
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::setDisparityImage (const float* disparity_image, int di_width, int di_height,
                                       float focal_length, float base_line, float desired_angular_resolution)
  {
    //MEASURE_FUNCTION_TIME;
    reset ();

    float original_angular_resolution = asinf (0.5f*float(di_width)/float(focal_length)) / (0.5f*float(di_width));
    int skip = 1;
    if (desired_angular_resolution >= 2.0f*original_angular_resolution)
    {
      skip = pcl_lrint (floor (desired_angular_resolution/original_angular_resolution));
    }
    //std::cout << PVARN (skip);
    setAngularResolution (original_angular_resolution * skip);
    width  = di_width / skip;
    height = di_height / skip;
    focal_length_x_ = focal_length_y_ = focal_length / skip;
    focal_length_x_reciprocal_ = focal_length_y_reciprocal_ = 1.0f / focal_length_x_;
    center_x_ = float(di_width)  / float(2*skip);
    center_y_ = float(di_height) / float(2*skip);
    points.resize(width*height);

    //cout << PVARN (*this);

    float normalization_factor = skip*focal_length_x_*base_line;
    for (int y=0; y<(int)height; ++y)
    {
      for (int x=0; x<(int)width; ++x)
      {
        PointWithRange& point = getPointNoCheck(x,y);
        float disparity = disparity_image[(y*skip)*di_width + x*skip];
        if (disparity <= 0.0f)
        {
          //std::cout << disparity << ", "<<std::flush;
          point = unobserved_point;
          continue;
        }
        point.z = normalization_factor / disparity;
        point.x = (x-center_x_)*point.z * focal_length_x_reciprocal_;
        point.y = (y-center_y_)*point.z * focal_length_y_reciprocal_;
        point.range = point.getVector3fMap().norm();
        //cout << point<<std::flush;

        //// Just a test:
        //PointWithRange test_point1;
        //calculate3DPoint (float (x), float (y), point.range, test_point1);
        //if ((point.getVector3fMap ()-test_point1.getVector3fMap ()).norm () > 1e-5)
          //cerr << "Something's wrong here...\n";

        //float image_x, image_y;
        //getImagePoint(point.getVector3fMap (), image_x, image_y);
        //if (fabsf (image_x-x)+fabsf (image_y-y)>1e-4)
          //cerr << PVARC (x)<<PVARC (y)<<PVARC (image_x)<<PVARN (image_y);
      }
    }
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::setDepthImage (const float* depth_image, int di_width, int di_height,
                                   float di_center_x, float di_center_y,
                                   float di_focal_length_x, float di_focal_length_y,
                                   float desired_angular_resolution)
  {
    //MEASURE_FUNCTION_TIME;
    reset ();

    float original_angular_resolution = asinf (0.5f*float(di_width)/float(di_focal_length_x)) / (0.5f*float(di_width));
    int skip = 1;
    if (desired_angular_resolution >= 2.0f*original_angular_resolution)
    {
      skip = pcl_lrint (floor (desired_angular_resolution/original_angular_resolution));
    }
    //std::cout << PVARN (skip);
    setAngularResolution (original_angular_resolution * skip);
    width  = di_width / skip;
    height = di_height / skip;
    focal_length_x_ = di_focal_length_x / skip;
    focal_length_x_reciprocal_ = 1.0f / focal_length_x_;
    focal_length_y_ = di_focal_length_y / skip;
    focal_length_y_reciprocal_ = 1.0f / focal_length_y_;
    center_x_ = float(di_center_x) / float(skip);
    center_y_ = float(di_center_y) / float(skip);
    points.resize(width*height);

    //cout << PVARN (*this);

    for (int y=0; y<(int)height; ++y)
    {
      for (int x=0; x<(int)width; ++x)
      {
        PointWithRange& point = getPointNoCheck(x,y);
        float depth = depth_image[(y*skip)*di_width + x*skip];
        if (depth <= 0.0f || !pcl_isfinite(depth))
        {
          //std::cout << depth << ", "<<std::flush;
          point = unobserved_point;
          continue;
        }
        point.z = depth;
        point.x = (x-center_x_)*point.z * focal_length_x_reciprocal_;
        point.y = (y-center_y_)*point.z * focal_length_y_reciprocal_;
        point.range = point.getVector3fMap().norm();
      }
    }
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::setDepthImage (const unsigned short* depth_image, int di_width, int di_height,
                                   float di_center_x, float di_center_y,
                                   float di_focal_length_x, float di_focal_length_y,
                                   float desired_angular_resolution)
  {
    //MEASURE_FUNCTION_TIME;
    reset ();

    float original_angular_resolution = asinf (0.5f*float(di_width)/float(di_focal_length_x)) / (0.5f*float(di_width));
    int skip = 1;
    if (desired_angular_resolution >= 2.0f*original_angular_resolution)
    {
      skip = pcl_lrint (floor (desired_angular_resolution/original_angular_resolution));
    }
    //std::cout << PVARN (skip);
    setAngularResolution (original_angular_resolution * skip);
    width  = di_width / skip;
    height = di_height / skip;
    focal_length_x_ = di_focal_length_x / skip;
    focal_length_x_reciprocal_ = 1.0f / focal_length_x_;
    focal_length_y_ = di_focal_length_y / skip;
    focal_length_y_reciprocal_ = 1.0f / focal_length_y_;
    center_x_ = float(di_center_x) / float(skip);
    center_y_ = float(di_center_y) / float(skip);
    points.resize(width*height);

    //cout << PVARN (*this);

    for (int y=0; y<(int)height; ++y)
    {
      for (int x=0; x<(int)width; ++x)
      {
        PointWithRange& point = getPointNoCheck(x,y);
        float depth = depth_image[(y*skip)*di_width + x*skip] * 0.001f;
        if (depth <= 0.0f || !pcl_isfinite(depth))
        {
          //std::cout << depth << ", "<<std::flush;
          point = unobserved_point;
          continue;
        }
        point.z = depth;
        point.x = (x-center_x_)*point.z * focal_length_x_reciprocal_;
        point.y = (y-center_y_)*point.z * focal_length_y_reciprocal_;
        point.range = point.getVector3fMap().norm();
      }
    }
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::getHalfImage(RangeImage& half_image) const
  {
    //std::cout << __PRETTY_FUNCTION__ << " called.\n";
    if (typeid(*this) != typeid(half_image))
    {
      std::cerr << __PRETTY_FUNCTION__<<": Given range image is not a RangeImagePlanar!\n";
      return;
    }
    RangeImagePlanar& ret = *((RangeImagePlanar*)&half_image);

    ret.focal_length_x_ = focal_length_x_/2;
    ret.focal_length_x_reciprocal_ = 1.0f/ret.focal_length_x_;
    ret.focal_length_y_ = focal_length_y_/2;
    ret.focal_length_y_reciprocal_ = 1.0f/ret.focal_length_y_;
    ret.center_x_ = center_x_/2;
    ret.center_y_ = center_y_/2;
    BaseClass::getHalfImage(ret);
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::getSubImage(int sub_image_image_offset_x, int sub_image_image_offset_y, int sub_image_width,
                          int sub_image_height, int combine_pixels, RangeImage& sub_image) const
  {
    std::cerr << __PRETTY_FUNCTION__ << ": Warning, not tested properly!\n";

    if (typeid(*this) != typeid(sub_image))
    {
      std::cerr << __PRETTY_FUNCTION__<<": Given range image is not a RangeImagePlanar!\n";
      return;
    }
    RangeImagePlanar& ret = *((RangeImagePlanar*)&sub_image);

    ret.focal_length_x_ = focal_length_x_ / combine_pixels;
    ret.focal_length_x_reciprocal_ = 1.0f/ret.focal_length_x_;
    ret.focal_length_y_ = focal_length_x_ / combine_pixels;
    ret.focal_length_y_reciprocal_ = 1.0f/ret.focal_length_y_;
    ret.center_x_ = center_x_/2 - sub_image_image_offset_x;
    ret.center_y_ = center_y_/2 - sub_image_image_offset_y;
    BaseClass::getSubImage(sub_image_image_offset_x, sub_image_image_offset_y, sub_image_width,
                           sub_image_height, combine_pixels, ret);
    ret.image_offset_x_ = ret.image_offset_y_ = 0;
  }

}  // namespace end

<commit_msg>Minor math fix.<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * 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.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  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.
 */

/** \author Bastian Steder */

#include <iostream>
using std::cout;
using std::cerr;

#include <pcl/range_image/range_image_planar.h>

namespace pcl
{
  /////////////////////////////////////////////////////////////////////////
  RangeImagePlanar::RangeImagePlanar () : RangeImage(), focal_length_x_(0.0f), focal_length_y_(0.0f),
                                          focal_length_x_reciprocal_(0.0f), focal_length_y_reciprocal_(0.0f),
                                          center_x_(0.0f), center_y_(0.0f)
  {
  }

  /////////////////////////////////////////////////////////////////////////
  RangeImagePlanar::~RangeImagePlanar ()
  {
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::setDisparityImage (const float* disparity_image, int di_width, int di_height,
                                       float focal_length, float base_line, float desired_angular_resolution)
  {
    //MEASURE_FUNCTION_TIME;
    reset ();

    float original_angular_resolution = atanf (0.5f*float(di_width)/float(focal_length)) / (0.5f*float(di_width));
    int skip = 1;
    if (desired_angular_resolution >= 2.0f*original_angular_resolution)
    {
      skip = pcl_lrint (floor (desired_angular_resolution/original_angular_resolution));
    }
    //std::cout << PVARN (skip);
    setAngularResolution (original_angular_resolution * skip);
    width  = di_width / skip;
    height = di_height / skip;
    focal_length_x_ = focal_length_y_ = focal_length / skip;
    focal_length_x_reciprocal_ = focal_length_y_reciprocal_ = 1.0f / focal_length_x_;
    center_x_ = float(di_width)  / float(2*skip);
    center_y_ = float(di_height) / float(2*skip);
    points.resize(width*height);

    //cout << PVARN (*this);

    float normalization_factor = skip*focal_length_x_*base_line;
    for (int y=0; y<(int)height; ++y)
    {
      for (int x=0; x<(int)width; ++x)
      {
        PointWithRange& point = getPointNoCheck(x,y);
        float disparity = disparity_image[(y*skip)*di_width + x*skip];
        if (disparity <= 0.0f)
        {
          //std::cout << disparity << ", "<<std::flush;
          point = unobserved_point;
          continue;
        }
        point.z = normalization_factor / disparity;
        point.x = (x-center_x_)*point.z * focal_length_x_reciprocal_;
        point.y = (y-center_y_)*point.z * focal_length_y_reciprocal_;
        point.range = point.getVector3fMap().norm();
        //cout << point<<std::flush;

        //// Just a test:
        //PointWithRange test_point1;
        //calculate3DPoint (float (x), float (y), point.range, test_point1);
        //if ((point.getVector3fMap ()-test_point1.getVector3fMap ()).norm () > 1e-5)
          //cerr << "Something's wrong here...\n";

        //float image_x, image_y;
        //getImagePoint(point.getVector3fMap (), image_x, image_y);
        //if (fabsf (image_x-x)+fabsf (image_y-y)>1e-4)
          //cerr << PVARC (x)<<PVARC (y)<<PVARC (image_x)<<PVARN (image_y);
      }
    }
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::setDepthImage (const float* depth_image, int di_width, int di_height,
                                   float di_center_x, float di_center_y,
                                   float di_focal_length_x, float di_focal_length_y,
                                   float desired_angular_resolution)
  {
    //MEASURE_FUNCTION_TIME;
    reset ();

    float original_angular_resolution = asinf (0.5f*float(di_width)/float(di_focal_length_x)) / (0.5f*float(di_width));
    int skip = 1;
    if (desired_angular_resolution >= 2.0f*original_angular_resolution)
    {
      skip = pcl_lrint (floor (desired_angular_resolution/original_angular_resolution));
    }
    //std::cout << PVARN (skip);
    setAngularResolution (original_angular_resolution * skip);
    width  = di_width / skip;
    height = di_height / skip;
    focal_length_x_ = di_focal_length_x / skip;
    focal_length_x_reciprocal_ = 1.0f / focal_length_x_;
    focal_length_y_ = di_focal_length_y / skip;
    focal_length_y_reciprocal_ = 1.0f / focal_length_y_;
    center_x_ = float(di_center_x) / float(skip);
    center_y_ = float(di_center_y) / float(skip);
    points.resize(width*height);

    //cout << PVARN (*this);

    for (int y=0; y<(int)height; ++y)
    {
      for (int x=0; x<(int)width; ++x)
      {
        PointWithRange& point = getPointNoCheck(x,y);
        float depth = depth_image[(y*skip)*di_width + x*skip];
        if (depth <= 0.0f || !pcl_isfinite(depth))
        {
          //std::cout << depth << ", "<<std::flush;
          point = unobserved_point;
          continue;
        }
        point.z = depth;
        point.x = (x-center_x_)*point.z * focal_length_x_reciprocal_;
        point.y = (y-center_y_)*point.z * focal_length_y_reciprocal_;
        point.range = point.getVector3fMap().norm();
      }
    }
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::setDepthImage (const unsigned short* depth_image, int di_width, int di_height,
                                   float di_center_x, float di_center_y,
                                   float di_focal_length_x, float di_focal_length_y,
                                   float desired_angular_resolution)
  {
    //MEASURE_FUNCTION_TIME;
    reset ();

    float original_angular_resolution = asinf (0.5f*float(di_width)/float(di_focal_length_x)) / (0.5f*float(di_width));
    int skip = 1;
    if (desired_angular_resolution >= 2.0f*original_angular_resolution)
    {
      skip = pcl_lrint (floor (desired_angular_resolution/original_angular_resolution));
    }
    //std::cout << PVARN (skip);
    setAngularResolution (original_angular_resolution * skip);
    width  = di_width / skip;
    height = di_height / skip;
    focal_length_x_ = di_focal_length_x / skip;
    focal_length_x_reciprocal_ = 1.0f / focal_length_x_;
    focal_length_y_ = di_focal_length_y / skip;
    focal_length_y_reciprocal_ = 1.0f / focal_length_y_;
    center_x_ = float(di_center_x) / float(skip);
    center_y_ = float(di_center_y) / float(skip);
    points.resize(width*height);

    //cout << PVARN (*this);

    for (int y=0; y<(int)height; ++y)
    {
      for (int x=0; x<(int)width; ++x)
      {
        PointWithRange& point = getPointNoCheck(x,y);
        float depth = depth_image[(y*skip)*di_width + x*skip] * 0.001f;
        if (depth <= 0.0f || !pcl_isfinite(depth))
        {
          //std::cout << depth << ", "<<std::flush;
          point = unobserved_point;
          continue;
        }
        point.z = depth;
        point.x = (x-center_x_)*point.z * focal_length_x_reciprocal_;
        point.y = (y-center_y_)*point.z * focal_length_y_reciprocal_;
        point.range = point.getVector3fMap().norm();
      }
    }
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::getHalfImage(RangeImage& half_image) const
  {
    //std::cout << __PRETTY_FUNCTION__ << " called.\n";
    if (typeid(*this) != typeid(half_image))
    {
      std::cerr << __PRETTY_FUNCTION__<<": Given range image is not a RangeImagePlanar!\n";
      return;
    }
    RangeImagePlanar& ret = *((RangeImagePlanar*)&half_image);

    ret.focal_length_x_ = focal_length_x_/2;
    ret.focal_length_x_reciprocal_ = 1.0f/ret.focal_length_x_;
    ret.focal_length_y_ = focal_length_y_/2;
    ret.focal_length_y_reciprocal_ = 1.0f/ret.focal_length_y_;
    ret.center_x_ = center_x_/2;
    ret.center_y_ = center_y_/2;
    BaseClass::getHalfImage(ret);
  }

  /////////////////////////////////////////////////////////////////////////
  void
  RangeImagePlanar::getSubImage(int sub_image_image_offset_x, int sub_image_image_offset_y, int sub_image_width,
                          int sub_image_height, int combine_pixels, RangeImage& sub_image) const
  {
    std::cerr << __PRETTY_FUNCTION__ << ": Warning, not tested properly!\n";

    if (typeid(*this) != typeid(sub_image))
    {
      std::cerr << __PRETTY_FUNCTION__<<": Given range image is not a RangeImagePlanar!\n";
      return;
    }
    RangeImagePlanar& ret = *((RangeImagePlanar*)&sub_image);

    ret.focal_length_x_ = focal_length_x_ / combine_pixels;
    ret.focal_length_x_reciprocal_ = 1.0f/ret.focal_length_x_;
    ret.focal_length_y_ = focal_length_x_ / combine_pixels;
    ret.focal_length_y_reciprocal_ = 1.0f/ret.focal_length_y_;
    ret.center_x_ = center_x_/2 - sub_image_image_offset_x;
    ret.center_y_ = center_y_/2 - sub_image_image_offset_y;
    BaseClass::getSubImage(sub_image_image_offset_x, sub_image_image_offset_y, sub_image_width,
                           sub_image_height, combine_pixels, ret);
    ret.image_offset_x_ = ret.image_offset_y_ = 0;
  }

}  // namespace end

<|endoftext|>


<commit_before>#pragma once

#include <memory_resource>

#include "nova_renderer/memory/bytes.hpp"
#include "nova_renderer/memory/host_memory_resource.hpp"

namespace nova::mem {
    template <typename AllocatedType = std::byte>
    class AllocatorHandle : public std::pmr::polymorphic_allocator<AllocatedType> {
    public:
        AllocatorHandle() = default;

        explicit AllocatorHandle(std::pmr::memory_resource* memory);

        AllocatorHandle(const AllocatorHandle& other) = delete;
        AllocatorHandle& operator=(const AllocatorHandle& other) = delete;

        AllocatorHandle(AllocatorHandle&& old) noexcept = default;
        AllocatorHandle& operator=(AllocatorHandle&& old) noexcept = default;

        virtual ~AllocatorHandle() = default;

        /*!
         * \brief Allocates and constructs an object of the specified type
         *
         * Would be nice if C++ came with this method, but nope not yet
         */
        template <typename... Args>
        AllocatedType* new_object(Args&&... args);

        /*!
         * \brief Allocates an object of a different type than what this allocator normally created
         *
         * Intended use case is that you have a byte allocator that you allocate a few different object types from
         */
        template <typename ObjectType, typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        ObjectType* allocate_object();

        /*!
         * \brief Allocates a shared pointer that uses this allocator to allocate its internal memory
         *
         * \param deleter A functor that you want to use to delete the object
         * \param args Any arguments to forward to the new object's constructor
         *
         * \return A shared pointer to the new object
         */
        template <typename ObjectType,
                  typename DeleterType,
                  typename... Args,
                  typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        std::shared_ptr<ObjectType> allocate_shared(DeleterType deleter, Args&&... args);

        /*!
         * \brief Allocates and constructs an object of a different type
         *
         * Intended use case is that you have a byte allocator that you use to create objects of different types
         */
        template <typename ObjectType, typename... Args, typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        ObjectType* new_other_object(Args&&... args);

        /*!
         * \brief Creates a new allocator which will allocate from this allocator's memory resource
         */
        template <typename ObjectType = AllocatedType, typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        AllocatorHandle<ObjectType>* create_suballocator();
    };

    template <typename AllocatedType = std::byte>
    AllocatorHandle<AllocatedType> get_malloc_allocator() {
        return AllocatorHandle<AllocatedType>(std::pmr::new_delete_resource());
    }

    template <typename AllocatedType>
    AllocatorHandle<AllocatedType>::AllocatorHandle(std::pmr::memory_resource* memory)
        : std::pmr::polymorphic_allocator<AllocatedType>(memory) {}

    template <typename AllocatedType>
    template <typename... Args>
    AllocatedType* AllocatorHandle<AllocatedType>::new_object(Args&&... args) {
        auto* mem = this->allocate(1);
        this->construct(mem, args...);
        return mem;
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename>
    ObjectType* AllocatorHandle<AllocatedType>::allocate_object() {
        auto* mem = this->allocate(sizeof(ObjectType));
        return reinterpret_cast<ObjectType*>(mem);
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename DeleterType, typename... Args, typename>
    std::shared_ptr<ObjectType> AllocatorHandle<AllocatedType>::allocate_shared(DeleterType deleter, Args&&... args) {
        const auto ptr = allocate_object<ObjectType>(std::forward(args)...);
        return std::shared_ptr<ObjectType>(ptr, deleter, std::pmr::polymorphic_allocator<std::byte>(this->resource()));
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename... Args, typename>
    ObjectType* AllocatorHandle<AllocatedType>::new_other_object(Args&&... args) {
        auto* mem = this->allocate(sizeof(ObjectType));
        return new(mem) ObjectType(std::forward<Args>(args)...);
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename>
    AllocatorHandle<ObjectType>* AllocatorHandle<AllocatedType>::create_suballocator() {
        return this->template new_other_object<AllocatorHandle<ObjectType>>(this->resource());
    }
} // namespace nova::mem
<commit_msg>[memory] GCC template bullshit<commit_after>#pragma once

#include <memory_resource>

#include "nova_renderer/memory/bytes.hpp"
#include "nova_renderer/memory/host_memory_resource.hpp"

namespace nova::mem {
    template <typename AllocatedType = std::byte>
    class AllocatorHandle : public std::pmr::polymorphic_allocator<AllocatedType> {
    public:
        AllocatorHandle() = default;

        explicit AllocatorHandle(std::pmr::memory_resource* memory);

        AllocatorHandle(const AllocatorHandle& other) = delete;
        AllocatorHandle& operator=(const AllocatorHandle& other) = delete;

        AllocatorHandle(AllocatorHandle&& old) noexcept = default;
        AllocatorHandle& operator=(AllocatorHandle&& old) noexcept = default;

        virtual ~AllocatorHandle() = default;

        /*!
         * \brief Allocates and constructs an object of the specified type
         *
         * Would be nice if C++ came with this method, but nope not yet
         */
        template <typename... Args>
        AllocatedType* new_object(Args&&... args);

        /*!
         * \brief Allocates an object of a different type than what this allocator normally created
         *
         * Intended use case is that you have a byte allocator that you allocate a few different object types from
         */
        template <typename ObjectType>
        auto allocate_object() -> std::enable_if_t<std::conjunction_v<std::is_same<AllocatedType, std::byte>, std::is_pointer<ObjectType>>>;

        /*!
         * \brief Allocates a shared pointer that uses this allocator to allocate its internal memory
         *
         * \param deleter A functor that you want to use to delete the object
         * \param args Any arguments to forward to the new object's constructor
         *
         * \return A shared pointer to the new object
         */
        template <typename ObjectType,
                  typename DeleterType,
                  typename... Args,
                  typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        std::shared_ptr<ObjectType> allocate_shared(DeleterType deleter, Args&&... args);

        /*!
         * \brief Allocates and constructs an object of a different type
         *
         * Intended use case is that you have a byte allocator that you use to create objects of different types
         */
        template <typename ObjectType, typename... Args, typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        ObjectType* new_other_object(Args&&... args);

        /*!
         * \brief Creates a new allocator which will allocate from this allocator's memory resource
         */
        template <typename ObjectType = AllocatedType, typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        AllocatorHandle<ObjectType>* create_suballocator();
    };

    template <typename AllocatedType = std::byte>
    AllocatorHandle<AllocatedType> get_malloc_allocator() {
        return AllocatorHandle<AllocatedType>(std::pmr::new_delete_resource());
    }

    template <typename AllocatedType>
    AllocatorHandle<AllocatedType>::AllocatorHandle(std::pmr::memory_resource* memory)
        : std::pmr::polymorphic_allocator<AllocatedType>(memory) {}

    template <typename AllocatedType>
    template <typename... Args>
    AllocatedType* AllocatorHandle<AllocatedType>::new_object(Args&&... args) {
        auto* mem = this->allocate(1);
        this->construct(mem, args...);
        return mem;
    }

    template <typename AllocatedType>
    template <typename ObjectType>
    auto AllocatorHandle<AllocatedType>::allocate_object()
        -> std::enable_if_t<std::conjunction_v<std::is_same<AllocatedType, std::byte>, std::is_pointer<ObjectType>>> {
        auto* mem = this->allocate(sizeof(ObjectType));
        return reinterpret_cast<ObjectType*>(mem);
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename DeleterType, typename... Args, typename>
    std::shared_ptr<ObjectType> AllocatorHandle<AllocatedType>::allocate_shared(DeleterType deleter, Args&&... args) {
        const auto ptr = allocate_object<ObjectType>(std::forward(args)...);
        return std::shared_ptr<ObjectType>(ptr, deleter, std::pmr::polymorphic_allocator<std::byte>(this->resource()));
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename... Args, typename>
    ObjectType* AllocatorHandle<AllocatedType>::new_other_object(Args&&... args) {
        auto* mem = this->allocate(sizeof(ObjectType));
        return new(mem) ObjectType(std::forward<Args>(args)...);
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename>
    AllocatorHandle<ObjectType>* AllocatorHandle<AllocatedType>::create_suballocator() {
        return this->template new_other_object<AllocatorHandle<ObjectType>>(this->resource());
    }
} // namespace nova::mem
<|endoftext|>


<commit_before>#include "kernel.h"
#include "errmessages.h"
#include "ilwisconfiguration.h"

using namespace Ilwis;

IlwisConfiguration::IlwisConfiguration()
{
}

bool IlwisConfiguration::prepare(const QString &configlocation)
{
    try{
    std::ifstream inputfile;
    inputfile.open(configlocation.toStdString().c_str(),std::ifstream::in);
    if (!inputfile.is_open()) {
        std::cerr << TR("warning : Could not load configuration file").toStdString(); // dont follow logger here as this might be before the logger is initialized
    }

    boost::property_tree::json_parser::read_json(inputfile,_configuration);
    _configLocation = configlocation;

    return true;
    } catch(const boost::property_tree::json_parser::json_parser_error& err){
        //QString message = QString::fromStdString(err.message());
        std::cerr << TR("warning : invalid json file for configuration").toStdString();
    }
    return false;
}

void IlwisConfiguration::eraseChildren(const QString &key)
{
    QString tempkey = key;
    tempkey.replace("/",".");
    auto ptree = _configuration.get_child(tempkey.toStdString());
    for(auto it = ptree.begin();it != ptree.end();){
        it = ptree.erase(it);
    }

//    auto assoc_iter = _configuration.find(tempkey.toStdString());
//    if ( assoc_iter == _configuration.not_found())
//        return;
//    auto iter = _configuration.to_iterator(assoc_iter);
//    _configuration.erase(iter);

    _modified = true;
}

void IlwisConfiguration::addValue(const QString &key, const QString& value){
    QString tempkey = key;
    tempkey.replace("/",".");

    _configuration.put(tempkey.toStdString(), value.toStdString());
    _modified = true;
}

void IlwisConfiguration::putValue(const QString &key, const QString &value)
{
    QString tempkey = key;
    tempkey.replace("/",".");

    //TODO bit unclear if put also replaces values
    _configuration.put(tempkey.toStdString(), value.toStdString());

    _modified = true;
}

void IlwisConfiguration::store(const QString &location)
{
    if ( _modified) {
        std::string loc = location == sUNDEF ? _configLocation.toStdString() : location.toStdString();
        boost::property_tree::json_parser::write_json(loc,_configuration);
    }
}

<commit_msg>missing config was correctly checked but it didnt abort the process than but went on using the non existing file which lead to anothe r error<commit_after>#include <QDesktopServices>
#include "kernel.h"
#include "errmessages.h"
#include "ilwisconfiguration.h"

using namespace Ilwis;

IlwisConfiguration::IlwisConfiguration()
{
}

bool IlwisConfiguration::prepare(const QString &configlocation)
{
    try{
    std::ifstream inputfile;
    inputfile.open(configlocation.toStdString().c_str(),std::ifstream::in);
    if (!inputfile.is_open()) {
        std::cerr << TR("warning : Could not load configuration file").toStdString(); // dont follow logger here as this might be before the logger is initialized
        return false;
    }
    _configLocation = configlocation;
    boost::property_tree::json_parser::read_json(inputfile,_configuration);

    return true;
    } catch(const boost::property_tree::json_parser::json_parser_error& err){
        //QString message = QString::fromStdString(err.message());
        std::cerr << TR("warning : invalid json file for configuration").toStdString();
    }
    return false;
}

void IlwisConfiguration::eraseChildren(const QString &key)
{
    QString tempkey = key;
    tempkey.replace("/",".");
    auto ptree = _configuration.get_child(tempkey.toStdString());
    for(auto it = ptree.begin();it != ptree.end();){
        it = ptree.erase(it);
    }

//    auto assoc_iter = _configuration.find(tempkey.toStdString());
//    if ( assoc_iter == _configuration.not_found())
//        return;
//    auto iter = _configuration.to_iterator(assoc_iter);
//    _configuration.erase(iter);

    _modified = true;
}

void IlwisConfiguration::addValue(const QString &key, const QString& value){
    QString tempkey = key;
    tempkey.replace("/",".");

    _configuration.put(tempkey.toStdString(), value.toStdString());
    _modified = true;
}

void IlwisConfiguration::putValue(const QString &key, const QString &value)
{
    QString tempkey = key;
    tempkey.replace("/",".");

    //TODO bit unclear if put also replaces values
    _configuration.put(tempkey.toStdString(), value.toStdString());

    _modified = true;
}

void IlwisConfiguration::store(const QString &location)
{
    if ( _modified) {
        std::string loc = location == sUNDEF ? _configLocation.toStdString() : location.toStdString();
        if ( loc == ""){
            loc = QString(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/ilwis.config").toStdString();

        }
        boost::property_tree::json_parser::write_json(loc,_configuration);
    }
}

<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
///
/// \file main.cpp
/// \brief Main file for testing different system classes
///        and functionality.
/// Author: Andrew Watson
/// Created: 1/22/13
/// Email: watsontandrew@gmail.com
///
////////////////////////////////////////////////////////////////////////////////
#include <hokuyo.hpp>
#include <time.h>

//#define TESTHOKUYO
#ifdef TESTHOKUYO
class ExampleLaserCallback : public Laser::Callback
{
public:
    ExampleLaserCallback(){}
    ~ExampleLaserCallback(){}
    virtual void ProcessLaserData(const std::vector<CvPoint3D64f>& scan,
                                  const time_t& timestamp)
    {
        mLaserScan = scan;
        mTimeStamp = timestamp;
    }
    std::vector<CvPoint3D64f> mLaserScan;
    time_t mTimeStamp;
};

double MiddleScanDistanceInches (const std::vector<CvPoint3D64f>& scan)
{
    if(scan.size() > 0)
        return scan.at(scan.size() / 2.).x * 1000. / 25.4;
    else
        return 0;
}

int main()
{
    Laser::Hokuyo* laser = new Laser::Hokuyo();
    ExampleLaserCallback callback;
    laser->RegisterCallback(&callback);
    if(laser->Initialize())
    {
        if(laser->StartCaptureThread())
        {
            while (1)
            {
                std::cout << MiddleScanDistanceInches(callback.mLaserScan)
                          << std::endl;
                boost::this_thread::sleep(boost::posix_time::millisec(10));
            }
            laser->Shutdown();
            delete laser;
        }
    }

    return 0;
}
#endif

//#define TESTDYNAMIXEL
#ifdef TESTDYNAMIXEL
int main()
{
    return 0;
}
#endif

#define TESTTIMING
#ifdef TESTTIMING
timespec diff(timespec start, timespec end);
int main()
{
//    clockid_t types[] = {CLOCK_REALTIME, CLOCK_MONOTONIC,
//                         CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID,
//                         (clockid_t) - 1};
//    struct timespec spec;
//    for (int i = 0; types[i] != (clockid_t) - 1; i++)
//    {
//        if(clock_getres(types[i], &spec) != 0)
//        {
//            std::cout << "Timer " << types[i] << " not supported" << std::endl;
//        }
//        else
//        {
//            std::cout << "Timer: " << i << " Seconds: " << spec.tv_sec
//                      << " Nanos: " << spec.tv_nsec << std::endl;
//        }
//    }
    timespec t1, t2;
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t1);
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t2);
    while(1)
    {
        if(diff(t1, t2).tv_nsec > 2000000)
        {
            std::cout << "1 Sec Elapsed" << std::endl;
            clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t1);
            clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t2);
        }
        else
        {
            clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t2);
        }
        std::cout << diff(t1, t2).tv_nsec << std::endl;
        nanosleep((struct timespec[]){{0, 100000000}}, NULL);
    }
    return 0;
}
timespec diff(timespec start, timespec end)
{
    timespec temp;
    if((end.tv_nsec-start.tv_nsec)<0)
    {
        temp.tv_sec = end.tv_sec - start.tv_sec - 1;
        temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
    }
    else
    {
        temp.tv_sec = end.tv_sec - start.tv_sec;
        temp.tv_nsec = end.tv_nsec - start.tv_nsec;
    }
    return temp;
}

#endif

//#define TESTSERVER
#ifdef TESTSERVER
int main()
{
    return 0;
}

#endif
/** End of File */
<commit_msg>Added Wiring Pi Example. Will need to be developed on the pi due to hardware constraints<commit_after>////////////////////////////////////////////////////////////////////////////////
///
/// \file main.cpp
/// \brief Main file for testing different system classes
///        and functionality.
/// Author: Andrew Watson
/// Created: 1/22/13
/// Email: watsontandrew@gmail.com
///
////////////////////////////////////////////////////////////////////////////////
#include <hokuyo.hpp>
#include <time.h>
#include <wiringPi.h>

//#define TESTHOKUYO
#ifdef TESTHOKUYO
class ExampleLaserCallback : public Laser::Callback
{
public:
    ExampleLaserCallback(){}
    ~ExampleLaserCallback(){}
    virtual void ProcessLaserData(const std::vector<CvPoint3D64f>& scan,
                                  const time_t& timestamp)
    {
        mLaserScan = scan;
        mTimeStamp = timestamp;
    }
    std::vector<CvPoint3D64f> mLaserScan;
    time_t mTimeStamp;
};

double MiddleScanDistanceInches (const std::vector<CvPoint3D64f>& scan)
{
    if(scan.size() > 0)
        return scan.at(scan.size() / 2.).x * 1000. / 25.4;
    else
        return 0;
}

int main()
{
    Laser::Hokuyo* laser = new Laser::Hokuyo();
    ExampleLaserCallback callback;
    laser->RegisterCallback(&callback);
    if(laser->Initialize())
    {
        if(laser->StartCaptureThread())
        {
            while (1)
            {
                std::cout << MiddleScanDistanceInches(callback.mLaserScan)
                          << std::endl;
                boost::this_thread::sleep(boost::posix_time::millisec(10));
            }
            laser->Shutdown();
            delete laser;
        }
    }

    return 0;
}
#endif

//#define TESTDYNAMIXEL
#ifdef TESTDYNAMIXEL
int main()
{
    int x = 1234;

    char bytes[sizeof x];
    std::copy(static_cast<const char*>(static_cast<const void*>(&x)),
              static_cast<const char*>(static_cast<const void*>(&x)) + sizeof x,
              bytes);

    char a = bytes[0];
    char b = bytes[1];

   return 0;
}
#endif

//#define TESTTIMING
#ifdef TESTTIMING
timespec diff(timespec start, timespec end);
int main()
{
//    clockid_t types[] = {CLOCK_REALTIME, CLOCK_MONOTONIC,
//                         CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID,
//                         (clockid_t) - 1};
//    struct timespec spec;
//    for (int i = 0; types[i] != (clockid_t) - 1; i++)
//    {
//        if(clock_getres(types[i], &spec) != 0)
//        {
//            std::cout << "Timer " << types[i] << " not supported" << std::endl;
//        }
//        else
//        {
//            std::cout << "Timer: " << i << " Seconds: " << spec.tv_sec
//                      << " Nanos: " << spec.tv_nsec << std::endl;
//        }
//    }
    timespec t1, t2;
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t1);
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t2);
    while(1)
    {
        if(diff(t1, t2).tv_nsec > 2000000)
        {
            std::cout << "1 Sec Elapsed" << std::endl;
            clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t1);
            clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t2);
        }
        else
        {
            clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t2);
        }
        std::cout << diff(t1, t2).tv_nsec << std::endl;
        nanosleep((struct timespec[]){{0, 100000000}}, NULL);
    }
    return 0;
}
timespec diff(timespec start, timespec end)
{
    timespec temp;
    if((end.tv_nsec-start.tv_nsec)<0)
    {
        temp.tv_sec = end.tv_sec - start.tv_sec - 1;
        temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
    }
    else
    {
        temp.tv_sec = end.tv_sec - start.tv_sec;
        temp.tv_nsec = end.tv_nsec - start.tv_nsec;
    }
    return temp;
}

#endif

//#define TESTSERVER
#ifdef TESTSERVER
int main()
{
    return 0;
}

#endif

#define TESTISR
#ifdef TESTISR

#define BUTTON_PIN 0
volatile int eventCounter = 0;
void myInterrupt(void) {eventCounter++;}

int main()
{

    if (wiringPiSetup () < 0) {
          fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno));
          return 1;
      }

      // set Pin 17/0 generate an interrupt on high-to-low transitions
      // and attach myInterrupt() to the interrupt
      if ( wiringPiISR (BUTTON_PIN, INT_EDGE_FALLING, &myInterrupt) < 0 ) {
          fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno));
          return 1;
      }

      // display counter value every second.
      while ( 1 ) {
        printf( "%d\n", eventCounter );
        eventCounter = 0;
        delay( 1000 ); // wait 1 second
      }

      return 0;
}

#endif
/** End of File */
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "ApplicationFeatures/LanguageFeature.h"
#include "Basics/ArangoGlobalContext.h"

#include "Basics/Utf8Helper.h"
#include "Basics/files.h"
#include "Basics/FileUtils.h"
#include "Basics/directories.h"
#include "Logger/Logger.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"

using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::options;

LanguageFeature::LanguageFeature(
    application_features::ApplicationServer* server)
  :
    ApplicationFeature(server, "Language"),
    _binaryPath(server->getBinaryPath()),
    _icuDataPtr(nullptr) {
  setOptional(false);
  requiresElevatedPrivileges(false);
  startsAfter("Logger");
}

LanguageFeature::~LanguageFeature() {
  if (_icuDataPtr != nullptr) {
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, _icuDataPtr);
  }
}

void LanguageFeature::collectOptions(
    std::shared_ptr<options::ProgramOptions> options) {
  options->addHiddenOption("--default-language", "ISO-639 language code",
                           new StringParameter(&_language));
}

void* LanguageFeature::prepareIcu(std::string const& binaryPath, std::string const& binaryExecutionPath, std::string& path, std::string const& binaryName) {
  char const* icuDataEnv = getenv("ICU_DATA");

  std::string fn("icudtl.dat");
  if (icuDataEnv != nullptr) {
    path = icuDataEnv + fn;
  }

  if (path.empty() || !TRI_IsRegularFile(path.c_str())) {
    if (!path.empty()) {
      LOG_TOPIC(WARN, arangodb::Logger::STARTUP) << "failed to locate '" << fn << "' at '"<< path << "'";
    }
    std::string bpfn = binaryExecutionPath + TRI_DIR_SEPARATOR_STR  + fn;

    if (TRI_IsRegularFile(fn.c_str())) {
      path = fn;
    }
    else if (TRI_IsRegularFile(bpfn.c_str())) {
      path = bpfn;
    }
    else {
      std::string argv_0 = binaryExecutionPath + TRI_DIR_SEPARATOR_STR + binaryName;
      path = TRI_LocateInstallDirectory(argv_0.c_str(), binaryPath.c_str());
      path += ICU_DESTINATION_DIRECTORY TRI_DIR_SEPARATOR_STR + fn;
    }
    if (!TRI_IsRegularFile(path.c_str())) {
      std::string msg =
        std::string("cannot locate '") + path + "'; please make sure it is available; "
        "the variable ICU_DATA='";
      if (getenv("ICU_DATA") != nullptr) {
        msg += getenv("ICU_DATA");
      }
      msg += "' should point to the directory containing '" + fn + "'";

      LOG_TOPIC(FATAL, arangodb::Logger::STARTUP) << msg;
      FATAL_ERROR_EXIT();
    }
    else {
      std::string icu_path = path.substr(0, path.length() - fn.length());
      FileUtils::makePathAbsolute(icu_path);
      FileUtils::normalizePath(icu_path);
#ifndef _WIN32
      setenv("ICU_DATA", icu_path.c_str(), 1);
#else
      SetEnvironmentVariable("ICU_DATA", icu_path.c_str());
#endif
    }
  }

  void* icuDataPtr = TRI_SlurpFile(TRI_UNKNOWN_MEM_ZONE, path.c_str(), nullptr);

  if (icuDataPtr == nullptr) {
    LOG_TOPIC(FATAL, arangodb::Logger::STARTUP) << "failed to load '" << fn << "' at '" << path << "' - " << TRI_last_error();
    FATAL_ERROR_EXIT();
  }
  return icuDataPtr;
}

void LanguageFeature::prepare() {
  std::string p;
  auto context = ArangoGlobalContext::CONTEXT;
  std::string binaryExecutionPath = context->getBinaryPath();
  std::string binaryName = context->binaryName();
  _icuDataPtr = LanguageFeature::prepareIcu(_binaryPath, binaryExecutionPath, p, binaryName);

  if (!Utf8Helper::DefaultUtf8Helper.setCollatorLanguage(_language, _icuDataPtr)) {
    LOG_TOPIC(FATAL, arangodb::Logger::STARTUP) << "error initializing ICU with the contents of '" << p << "'";
    FATAL_ERROR_EXIT();
  }
}

void LanguageFeature::start() {
  std::string languageName;

  if (Utf8Helper::DefaultUtf8Helper.getCollatorCountry() != "") {
    languageName =
        std::string(Utf8Helper::DefaultUtf8Helper.getCollatorLanguage() + "_" +
                    Utf8Helper::DefaultUtf8Helper.getCollatorCountry());
  } else {
    languageName = Utf8Helper::DefaultUtf8Helper.getCollatorLanguage();
  }

  LOG_TOPIC(DEBUG, arangodb::Logger::STARTUP) << "using default language '" << languageName << "'";
}
<commit_msg>also try to detect the icu database in its absolute install directory<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "ApplicationFeatures/LanguageFeature.h"
#include "Basics/ArangoGlobalContext.h"

#include "Basics/Utf8Helper.h"
#include "Basics/files.h"
#include "Basics/FileUtils.h"
#include "Basics/directories.h"
#include "Logger/Logger.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"

using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::options;

LanguageFeature::LanguageFeature(
    application_features::ApplicationServer* server)
  :
    ApplicationFeature(server, "Language"),
    _binaryPath(server->getBinaryPath()),
    _icuDataPtr(nullptr) {
  setOptional(false);
  requiresElevatedPrivileges(false);
  startsAfter("Logger");
}

LanguageFeature::~LanguageFeature() {
  if (_icuDataPtr != nullptr) {
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, _icuDataPtr);
  }
}

void LanguageFeature::collectOptions(
    std::shared_ptr<options::ProgramOptions> options) {
  options->addHiddenOption("--default-language", "ISO-639 language code",
                           new StringParameter(&_language));
}

void* LanguageFeature::prepareIcu(std::string const& binaryPath, std::string const& binaryExecutionPath, std::string& path, std::string const& binaryName) {
  char const* icuDataEnv = getenv("ICU_DATA");

  std::string fn("icudtl.dat");
  if (icuDataEnv != nullptr) {
    path = icuDataEnv + fn;
  }

  if (path.empty() || !TRI_IsRegularFile(path.c_str())) {
    if (!path.empty()) {
      LOG_TOPIC(WARN, arangodb::Logger::STARTUP)
        << "failed to locate '" << fn
        << "' at '"<< path << "'";
    }
    std::string bpfn = binaryExecutionPath + TRI_DIR_SEPARATOR_STR  + fn;

    if (TRI_IsRegularFile(fn.c_str())) {
      path = fn;
    }
    else if (TRI_IsRegularFile(bpfn.c_str())) {
      path = bpfn;
    }
    else {
      std::string argv_0 = binaryExecutionPath + TRI_DIR_SEPARATOR_STR + binaryName;
      path = TRI_LocateInstallDirectory(argv_0.c_str(), binaryPath.c_str());
      path += ICU_DESTINATION_DIRECTORY TRI_DIR_SEPARATOR_STR + fn;
      if (!TRI_IsRegularFile(path.c_str())) {
        // Try whether we have an absolute install prefix:
        path = ICU_DESTINATION_DIRECTORY TRI_DIR_SEPARATOR_STR + fn;
      }
    }
    if (!TRI_IsRegularFile(path.c_str())) {
      std::string msg =
        std::string("cannot locate '") + path + "'; please make sure it is available; "
        "the variable ICU_DATA='";
      if (getenv("ICU_DATA") != nullptr) {
        msg += getenv("ICU_DATA");
      }
      msg += "' should point to the directory containing '" + fn + "'";

      LOG_TOPIC(FATAL, arangodb::Logger::STARTUP) << msg;
      FATAL_ERROR_EXIT();
    }
    else {
      std::string icu_path = path.substr(0, path.length() - fn.length());
      FileUtils::makePathAbsolute(icu_path);
      FileUtils::normalizePath(icu_path);
#ifndef _WIN32
      setenv("ICU_DATA", icu_path.c_str(), 1);
#else
      SetEnvironmentVariable("ICU_DATA", icu_path.c_str());
#endif
    }
  }

  void* icuDataPtr = TRI_SlurpFile(TRI_UNKNOWN_MEM_ZONE, path.c_str(), nullptr);

  if (icuDataPtr == nullptr) {
    LOG_TOPIC(FATAL, arangodb::Logger::STARTUP) << "failed to load '" << fn << "' at '" << path << "' - " << TRI_last_error();
    FATAL_ERROR_EXIT();
  }
  return icuDataPtr;
}

void LanguageFeature::prepare() {
  std::string p;
  auto context = ArangoGlobalContext::CONTEXT;
  std::string binaryExecutionPath = context->getBinaryPath();
  std::string binaryName = context->binaryName();
  _icuDataPtr = LanguageFeature::prepareIcu(_binaryPath, binaryExecutionPath, p, binaryName);

  if (!Utf8Helper::DefaultUtf8Helper.setCollatorLanguage(_language, _icuDataPtr)) {
    LOG_TOPIC(FATAL, arangodb::Logger::STARTUP) << "error initializing ICU with the contents of '" << p << "'";
    FATAL_ERROR_EXIT();
  }
}

void LanguageFeature::start() {
  std::string languageName;

  if (Utf8Helper::DefaultUtf8Helper.getCollatorCountry() != "") {
    languageName =
        std::string(Utf8Helper::DefaultUtf8Helper.getCollatorLanguage() + "_" +
                    Utf8Helper::DefaultUtf8Helper.getCollatorCountry());
  } else {
    languageName = Utf8Helper::DefaultUtf8Helper.getCollatorLanguage();
  }

  LOG_TOPIC(DEBUG, arangodb::Logger::STARTUP) << "using default language '" << languageName << "'";
}
<|endoftext|>