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

#ifndef DLL_CONV_DBN_INL
#define DLL_CONV_DBN_INL

#include <tuple>

#include "etl/dyn_vector.hpp"
#include "etl/dyn_matrix.hpp"

#include "conv_rbm.hpp"
#include "tuple_utils.hpp"
#include "dbn_trainer.hpp"
#include "conjugate_gradient.hpp"
#include "dbn_common.hpp"

//SVM Support is optional cause it requires libsvm

#ifdef DLL_SVM_SUPPORT
#include "nice_svm.hpp"
#endif

namespace dll {

/*!
 * \brief A Deep Belief Network implementation
 */
template<typename Desc>
struct conv_dbn {
    using desc = Desc;
    using this_type = conv_dbn<desc>;

    using tuple_type = typename desc::layers::tuple_type;
    tuple_type tuples;

    static constexpr const std::size_t layers = desc::layers::layers;

    template <std::size_t N>
    using rbm_type = typename std::tuple_element<N, tuple_type>::type;

    using weight = typename rbm_type<0>::weight;

#ifdef DLL_SVM_SUPPORT
    svm::model svm_model;               ///< The learned model
    svm::problem problem;               ///< libsvm is stupid, therefore, you cannot destroy the problem if you want to use the model...
    bool svm_loaded = false;            ///< Indicates if a SVM model has been loaded (and therefore must be saved)
#endif //DLL_SVM_SUPPORT

    //No arguments by default
    conv_dbn(){};

    //No copying
    conv_dbn(const conv_dbn& dbn) = delete;
    conv_dbn& operator=(const conv_dbn& dbn) = delete;

    //No moving
    conv_dbn(conv_dbn&& dbn) = delete;
    conv_dbn& operator=(conv_dbn&& dbn) = delete;

    void display() const {
        std::size_t parameters = 0;

        detail::for_each(tuples, [&parameters](auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;

            constexpr const auto NV = rbm_t::NV;
            constexpr const auto NH = rbm_t::NH;
            constexpr const auto K = rbm_t::K;

            printf("RBM: %lux%lu -> %lux%lu (%lu)\n", NV, NV, NH, NH, K);
        });
    }

    void store(std::ostream& os) const {
        detail::for_each(tuples, [&os](auto& rbm){
            rbm.store(os);
        });
    }

    void load(std::istream& is){
        detail::for_each(tuples, [&is](auto& rbm){
            rbm.load(is);
        });
    }

    template<std::size_t N>
    auto layer() -> typename std::add_lvalue_reference<rbm_type<N>>::type {
        return std::get<N>(tuples);
    }

    template<std::size_t N>
    constexpr auto layer() const -> typename std::add_lvalue_reference<typename std::add_const<rbm_type<N>>::type>::type {
        return std::get<N>(tuples);
    }

    template<std::size_t N>
    static constexpr std::size_t rbm_nv(){
        return rbm_type<N>::NV;
    }

    template<std::size_t N>
    static constexpr std::size_t rbm_nh(){
        return rbm_type<N>::NH;
    }

    template<std::size_t N>
    static constexpr std::size_t rbm_k(){
        return rbm_type<N>::K;
    }

    /*{{{ Pretrain */

    /*!
     * \brief Pretrain the network by training all layers in an unsupervised
     * manner.
     */
    template<typename Samples>
    void pretrain(const Samples& training_data, std::size_t max_epochs){
        using visible_t = std::vector<etl::dyn_vector<typename Samples::value_type::value_type>>;
        using hidden_t = std::vector<etl::dyn_vector<etl::dyn_matrix<weight>>>;

        using watcher_t = typename desc::template watcher_t<this_type>;

        watcher_t watcher;

        watcher.pretraining_begin(*this);

        //Convert data to an useful form
        visible_t data;
        data.reserve(training_data.size());

        for(auto& sample : training_data){
            data.emplace_back(sample);
        }

        hidden_t next_a;
        hidden_t next_s;
        visible_t next;

        auto input = std::ref(data);

        detail::for_each_i(tuples, [&watcher, this, &input, &next, &next_a, &next_s, max_epochs](std::size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto NH = rbm_t::NH;
            constexpr const auto K = rbm_t::K;

            auto input_size = static_cast<const visible_t&>(input).size();

            watcher.template pretrain_layer<rbm_t>(*this, I, input_size);

            rbm.template train<
                    visible_t,
                    !watcher_t::ignore_sub,                                 //Enable the RBM Watcher or not
                    typename dbn_detail::rbm_watcher_t<watcher_t>::type>    //Replace the RBM watcher if not void
                (static_cast<const visible_t&>(input), max_epochs);

            //Get the activation probabilities for the next level
            if(I < layers - 1){
                next_a.clear();
                next_a.reserve(input_size);
                next_s.clear();
                next_s.reserve(input_size);

                //TODO Review that
                for(std::size_t i = 0; i < input_size; ++i){
                    next_a.emplace_back(K, etl::dyn_matrix<weight>(NH, NH));
                    next_s.emplace_back(K, etl::dyn_matrix<weight>(NH, NH));
                }

                for(std::size_t i = 0; i < input_size; ++i){
                    rbm.v1 = static_cast<const visible_t&>(input)[i];
                    rbm.activate_hidden(next_a[i], next_s[i], rbm.v1, rbm.v1);
                }

                next.clear();
                next.reserve(input_size);

                //TODO Check the order of the output

                for(std::size_t i = 0; i < input_size; ++i){
                    next.emplace_back(NH * NH * K);

                    for(std::size_t j = 0; j < NH; ++j){
                        for(std::size_t k = 0; k < NH; ++k){
                            for(std::size_t l = 0; l < K; ++l){
                                next[i][j * NH * NH + k * NH + l] = next_a[i](k)(j,k);
                            }
                        }
                    }
                }

                input = std::ref(next);
            }
        });

        watcher.pretraining_end(*this);
    }

    /*}}}*/

    /*{{{ Predict */

    template<typename Sample, typename Output>
    void activation_probabilities(const Sample& item_data, Output& result){
        using visible_t = etl::dyn_vector<typename Sample::value_type>;
        using hidden_t = etl::dyn_vector<etl::dyn_matrix<weight>>;

        visible_t item(item_data);

        auto input = std::cref(item);

        detail::for_each_i(tuples, [&item, &input, &result](std::size_t I, auto& rbm){
            if(I != layers - 1){
                typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
                constexpr const auto NH = rbm_t::NH;
                constexpr const auto K = rbm_t::K;

                static visible_t next(K * NH * NH);
                static hidden_t next_a(K, etl::dyn_matrix<weight>(NH, NH));
                static hidden_t next_s(K, etl::dyn_matrix<weight>(NH, NH));

                rbm.v1 = static_cast<const Sample&>(input);
                rbm.activate_hidden(next_a, next_s, rbm.v1, rbm.v1);

                //TODO Check the order of the output

                for(std::size_t j = 0; j < NH; ++j){
                    for(std::size_t k = 0; k < NH; ++k){
                        for(std::size_t l = 0; l < K; ++l){
                            next[j * NH * NH + k * NH + l] = next_a(k)(j,k);
                        }
                    }
                }

                input = std::cref(next);
            }
        });

        constexpr const auto K = rbm_k<layers - 1>();
        constexpr const auto NH = rbm_nh<layers - 1>();

        static hidden_t next_a(K, etl::dyn_matrix<weight>(NH, NH));
        static hidden_t next_s(K, etl::dyn_matrix<weight>(NH, NH));

        auto& last_rbm = layer<layers - 1>();

        last_rbm.v1 = static_cast<const Sample&>(input);
        last_rbm.activate_hidden(next_a, next_s, last_rbm.v1, last_rbm.v1);

        //TODO Check the order of the output

        for(std::size_t j = 0; j < NH; ++j){
            for(std::size_t k = 0; k < NH; ++k){
                for(std::size_t l = 0; l < K; ++l){
                    result[j * NH * NH + k * NH + l] = next_a(k)(j,k);
                }
            }
        }
    }

    template<typename Sample>
    etl::dyn_vector<weight> activation_probabilities(const Sample& item_data){
        etl::dyn_vector<weight> result(rbm_nh<layers - 1>() * rbm_nh<layers - 1>() * rbm_k<layers - 1>());

        activation_probabilities(item_data, result);

        return result;
    }

    template<typename Weights>
    size_t predict_label(const Weights& result){
        size_t label = 0;
        weight max = 0;
        for(size_t l = 0; l < result.size(); ++l){
            auto value = result[l];

            if(value > max){
                max = value;
                label = l;
            }
        }

        return label;
    }

    template<typename Sample>
    size_t predict(const Sample& item){
        auto result = activation_probabilities(item);
        return predict_label(result);;
    }

    /*}}}*/

#ifdef DLL_SVM_SUPPORT

    /*{{{ SVM Training and prediction */

    /*}}}*/

#endif //DLL_SVM_SUPPORT

};

} //end of namespace dll

#endif
<commit_msg>Add load/store support for SVM<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DLL_CONV_DBN_INL
#define DLL_CONV_DBN_INL

#include <tuple>

#include "etl/dyn_vector.hpp"
#include "etl/dyn_matrix.hpp"

#include "conv_rbm.hpp"
#include "tuple_utils.hpp"
#include "dbn_trainer.hpp"
#include "conjugate_gradient.hpp"
#include "dbn_common.hpp"
#include "svm_common.hpp"

namespace dll {

/*!
 * \brief A Deep Belief Network implementation
 */
template<typename Desc>
struct conv_dbn {
    using desc = Desc;
    using this_type = conv_dbn<desc>;

    using tuple_type = typename desc::layers::tuple_type;
    tuple_type tuples;

    static constexpr const std::size_t layers = desc::layers::layers;

    template <std::size_t N>
    using rbm_type = typename std::tuple_element<N, tuple_type>::type;

    using weight = typename rbm_type<0>::weight;

#ifdef DLL_SVM_SUPPORT
    svm::model svm_model;               ///< The learned model
    svm::problem problem;               ///< libsvm is stupid, therefore, you cannot destroy the problem if you want to use the model...
    bool svm_loaded = false;            ///< Indicates if a SVM model has been loaded (and therefore must be saved)
#endif //DLL_SVM_SUPPORT

    //No arguments by default
    conv_dbn(){};

    //No copying
    conv_dbn(const conv_dbn& dbn) = delete;
    conv_dbn& operator=(const conv_dbn& dbn) = delete;

    //No moving
    conv_dbn(conv_dbn&& dbn) = delete;
    conv_dbn& operator=(conv_dbn&& dbn) = delete;

    void display() const {
        std::size_t parameters = 0;

        detail::for_each(tuples, [&parameters](auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;

            constexpr const auto NV = rbm_t::NV;
            constexpr const auto NH = rbm_t::NH;
            constexpr const auto K = rbm_t::K;

            printf("RBM: %lux%lu -> %lux%lu (%lu)\n", NV, NV, NH, NH, K);
        });
    }

    void store(std::ostream& os) const {
        detail::for_each(tuples, [&os](auto& rbm){
            rbm.store(os);
        });

#ifdef DLL_SVM_SUPPORT
        svm_store(*this, os);
#endif //DLL_SVM_SUPPORT
    }

    void load(std::istream& is){
        detail::for_each(tuples, [&is](auto& rbm){
            rbm.load(is);
        });

#ifdef DLL_SVM_SUPPORT
        svm_load(*this, is);
#endif //DLL_SVM_SUPPORT
    }

    template<std::size_t N>
    auto layer() -> typename std::add_lvalue_reference<rbm_type<N>>::type {
        return std::get<N>(tuples);
    }

    template<std::size_t N>
    constexpr auto layer() const -> typename std::add_lvalue_reference<typename std::add_const<rbm_type<N>>::type>::type {
        return std::get<N>(tuples);
    }

    template<std::size_t N>
    static constexpr std::size_t rbm_nv(){
        return rbm_type<N>::NV;
    }

    template<std::size_t N>
    static constexpr std::size_t rbm_nh(){
        return rbm_type<N>::NH;
    }

    template<std::size_t N>
    static constexpr std::size_t rbm_k(){
        return rbm_type<N>::K;
    }

    /*{{{ Pretrain */

    /*!
     * \brief Pretrain the network by training all layers in an unsupervised
     * manner.
     */
    template<typename Samples>
    void pretrain(const Samples& training_data, std::size_t max_epochs){
        using visible_t = std::vector<etl::dyn_vector<typename Samples::value_type::value_type>>;
        using hidden_t = std::vector<etl::dyn_vector<etl::dyn_matrix<weight>>>;

        using watcher_t = typename desc::template watcher_t<this_type>;

        watcher_t watcher;

        watcher.pretraining_begin(*this);

        //Convert data to an useful form
        visible_t data;
        data.reserve(training_data.size());

        for(auto& sample : training_data){
            data.emplace_back(sample);
        }

        hidden_t next_a;
        hidden_t next_s;
        visible_t next;

        auto input = std::ref(data);

        detail::for_each_i(tuples, [&watcher, this, &input, &next, &next_a, &next_s, max_epochs](std::size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto NH = rbm_t::NH;
            constexpr const auto K = rbm_t::K;

            auto input_size = static_cast<const visible_t&>(input).size();

            watcher.template pretrain_layer<rbm_t>(*this, I, input_size);

            rbm.template train<
                    visible_t,
                    !watcher_t::ignore_sub,                                 //Enable the RBM Watcher or not
                    typename dbn_detail::rbm_watcher_t<watcher_t>::type>    //Replace the RBM watcher if not void
                (static_cast<const visible_t&>(input), max_epochs);

            //Get the activation probabilities for the next level
            if(I < layers - 1){
                next_a.clear();
                next_a.reserve(input_size);
                next_s.clear();
                next_s.reserve(input_size);

                //TODO Review that
                for(std::size_t i = 0; i < input_size; ++i){
                    next_a.emplace_back(K, etl::dyn_matrix<weight>(NH, NH));
                    next_s.emplace_back(K, etl::dyn_matrix<weight>(NH, NH));
                }

                for(std::size_t i = 0; i < input_size; ++i){
                    rbm.v1 = static_cast<const visible_t&>(input)[i];
                    rbm.activate_hidden(next_a[i], next_s[i], rbm.v1, rbm.v1);
                }

                next.clear();
                next.reserve(input_size);

                //TODO Check the order of the output

                for(std::size_t i = 0; i < input_size; ++i){
                    next.emplace_back(NH * NH * K);

                    for(std::size_t j = 0; j < NH; ++j){
                        for(std::size_t k = 0; k < NH; ++k){
                            for(std::size_t l = 0; l < K; ++l){
                                next[i][j * NH * NH + k * NH + l] = next_a[i](k)(j,k);
                            }
                        }
                    }
                }

                input = std::ref(next);
            }
        });

        watcher.pretraining_end(*this);
    }

    /*}}}*/

    /*{{{ Predict */

    template<typename Sample, typename Output>
    void activation_probabilities(const Sample& item_data, Output& result){
        using visible_t = etl::dyn_vector<typename Sample::value_type>;
        using hidden_t = etl::dyn_vector<etl::dyn_matrix<weight>>;

        visible_t item(item_data);

        auto input = std::cref(item);

        detail::for_each_i(tuples, [&item, &input, &result](std::size_t I, auto& rbm){
            if(I != layers - 1){
                typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
                constexpr const auto NH = rbm_t::NH;
                constexpr const auto K = rbm_t::K;

                static visible_t next(K * NH * NH);
                static hidden_t next_a(K, etl::dyn_matrix<weight>(NH, NH));
                static hidden_t next_s(K, etl::dyn_matrix<weight>(NH, NH));

                rbm.v1 = static_cast<const Sample&>(input);
                rbm.activate_hidden(next_a, next_s, rbm.v1, rbm.v1);

                //TODO Check the order of the output

                for(std::size_t j = 0; j < NH; ++j){
                    for(std::size_t k = 0; k < NH; ++k){
                        for(std::size_t l = 0; l < K; ++l){
                            next[j * NH * NH + k * NH + l] = next_a(k)(j,k);
                        }
                    }
                }

                input = std::cref(next);
            }
        });

        constexpr const auto K = rbm_k<layers - 1>();
        constexpr const auto NH = rbm_nh<layers - 1>();

        static hidden_t next_a(K, etl::dyn_matrix<weight>(NH, NH));
        static hidden_t next_s(K, etl::dyn_matrix<weight>(NH, NH));

        auto& last_rbm = layer<layers - 1>();

        last_rbm.v1 = static_cast<const Sample&>(input);
        last_rbm.activate_hidden(next_a, next_s, last_rbm.v1, last_rbm.v1);

        //TODO Check the order of the output

        for(std::size_t j = 0; j < NH; ++j){
            for(std::size_t k = 0; k < NH; ++k){
                for(std::size_t l = 0; l < K; ++l){
                    result[j * NH * NH + k * NH + l] = next_a(k)(j,k);
                }
            }
        }
    }

    template<typename Sample>
    etl::dyn_vector<weight> activation_probabilities(const Sample& item_data){
        etl::dyn_vector<weight> result(rbm_nh<layers - 1>() * rbm_nh<layers - 1>() * rbm_k<layers - 1>());

        activation_probabilities(item_data, result);

        return result;
    }

    template<typename Weights>
    size_t predict_label(const Weights& result){
        size_t label = 0;
        weight max = 0;
        for(size_t l = 0; l < result.size(); ++l){
            auto value = result[l];

            if(value > max){
                max = value;
                label = l;
            }
        }

        return label;
    }

    template<typename Sample>
    size_t predict(const Sample& item){
        auto result = activation_probabilities(item);
        return predict_label(result);;
    }

    /*}}}*/

#ifdef DLL_SVM_SUPPORT

    /*{{{ SVM Training and prediction */

    /*}}}*/

#endif //DLL_SVM_SUPPORT

};

} //end of namespace dll

#endif
<|endoftext|>


<commit_before>#ifndef QRW_BOARD_HPP
#define QRW_BOARD_HPP

#include <SFML/System/Vector2.hpp>

namespace qrw
{
	class AbstractAlgorithm;
	class Path;
	class Coordinates;
	class Square;

	class Board
	{
		public:
			Board(int _width, int _height);
			~Board();

			Square* getSquare(int x, int y);
			Square* getSquare(sf::Vector2i pos);
			Square* getSquare(const Coordinates& coordinates);

			int getWidth();
			int getHeight();

			/**
			 * @brief Call pathfinding algorithm to find path from start to end.
			 * @param start Coordinates of the start.
			 * @param end Coordinates of the end.
			 * @return Pointer to found path or nullptr if no path could be found.
			 */
			Path* findPath(const Coordinates& start, const Coordinates& end);

		private:
			Square** _squares;

			int _width;
			int _height;

			AbstractAlgorithm* _pathfinder;
	};
}

#endif
<commit_msg>Fixed signature of Board constructor.<commit_after>#ifndef QRW_BOARD_HPP
#define QRW_BOARD_HPP

#include <SFML/System/Vector2.hpp>

namespace qrw
{
	class AbstractAlgorithm;
	class Path;
	class Coordinates;
	class Square;

	class Board
	{
		public:
			Board(int width, int height);
			~Board();

			Square* getSquare(int x, int y);
			Square* getSquare(sf::Vector2i pos);
			Square* getSquare(const Coordinates& coordinates);

			int getWidth();
			int getHeight();

			/**
			 * @brief Call pathfinding algorithm to find path from start to end.
			 * @param start Coordinates of the start.
			 * @param end Coordinates of the end.
			 * @return Pointer to found path or nullptr if no path could be found.
			 */
			Path* findPath(const Coordinates& start, const Coordinates& end);

		private:
			Square** _squares;

			int _width;
			int _height;

			AbstractAlgorithm* _pathfinder;
	};
}

#endif
<|endoftext|>


<commit_before>/* The MIT License (MIT)

Copyright (c) 2016 jonathan poelen

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

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

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

/**
* \author    Jonathan Poelen <jonathan.poelen+falcon@gmail.com>
* \version   0.1
* \brief     Compile time selection statements
*/

#pragma once

#include <initializer_list>
#include <type_traits>
#include <utility>

namespace falcon { namespace cexpr {

template<class T>
constexpr
std::integral_constant<bool, bool(T::value)>
cbool(T const &) noexcept
{ return {}; }

// TODO falcon.cxx project
#ifdef IN_IDE_PARSER

# define FALCON_CEXPR_DECLTYPE_AUTO_RETURN(a) \
  -> decltype(a)                              \
  { return (a); }                             \

# define FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(a) \
  noexcept(noexcept(decltype(a)(a))) ->                \
  decltype(a)                                          \
  { return (a); }                                      \

#else

# define FALCON_CEXPR_DECLTYPE_AUTO_RETURN(...) \
  -> decltype(__VA_ARGS__)                      \
  { return (__VA_ARGS__); }                     \

# define FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(...)    \
  noexcept(noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))) -> \
  decltype(__VA_ARGS__)                                     \
  { return (__VA_ARGS__); }                                 \

#endif

namespace detail
{
  template<class True, class False>
  constexpr True select_(std::true_type, True && yes, False &&)
  { return std::forward<True>(yes); }

  template<class True, class False>
  constexpr False select_(std::false_type, True &&, False && no)
  { return std::forward<False>(no); }
}

/// \return \p yes if \p cond is a \c true constant expression, otherwise \p no
template<class B, class True, class False>
constexpr auto select(B cond, True && yes, False && no)
FALCON_CEXPR_DECLTYPE_AUTO_RETURN(
  detail::select_(cbool(cond), std::forward<True>(yes), std::forward<False>(no))
)

namespace detail
{
  template<class True, class False>
  constexpr auto cif_(std::true_type, True && yes, False &&)
  FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
    std::forward<True>(yes)()
  )

  template<class True, class False>
  constexpr auto cif_(std::false_type, True &&, False && no)
  FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
    std::forward<False>(no)()
  )

  template<class True>
  constexpr
  auto cif_(std::true_type, True && yes)
  FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
    std::forward<True>(yes)()
  )

  template<class True>
  constexpr
  void cif_(std::false_type, True &&)
  {}
}

/// \return \p yes() if \p cond is a \c true constant expression, otherwise \p no()
template<class B, class True, class False>
constexpr auto cif(B cond, True && yes, False && no)
FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
  detail::cif_(cbool(cond), std::forward<True>(yes), std::forward<False>(no))
)

/// \return \p yes() if \p cond is a \c true constant expression, otherwise \c void
template<class B, class True>
constexpr
auto cif(B cond, True && yes)
FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
  detail::cif_(cbool(cond), std::forward<True>(yes))
)

struct nodefault_t {
  constexpr nodefault_t() noexcept {}
};
constexpr nodefault_t nodefault;

namespace detail
{
  template<class Int, Int... ints>
  class check_unique_int : std::integral_constant<Int, ints>... {};
}

/// \brief run \p func(\c ints) if \p i equal \c ints
template<class Int, Int... ints, class I, class Func>
constexpr
void cswitch(std::integer_sequence<Int, ints...>, I i, Func && func, nodefault_t)
{
  detail::check_unique_int<Int, ints...>{};

  (void)std::initializer_list<int>{(void(
    i == ints
    ? void(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))
    : void()
  ), 1)...};
}

/// \brief run \p func(\c ints) if \p i equal \c ints, otherwise \p default_func(\p i)
template<class Int, Int... ints, class I, class Func, class Default>
constexpr
void cswitch(std::integer_sequence<Int, ints...>, I i, Func && func, Default && default_func)
{
  detail::check_unique_int<Int, ints...>{};

  bool has_ints = false;
  (void)std::initializer_list<int>{(void(
    i == ints
    ? void((std::forward<Func>(func)(std::integral_constant<Int, ints>{}), void(has_ints = true)))
    : void()
  ), 1)...};
  if (!has_ints) {
    std::forward<Default>(default_func)(i);
  }
}

/// \brief shortcut for \c cswitch(\p ints, \p i, \p func, \p func)
template<class Ints, class I, class Func>
constexpr
void cswitch(Ints ints, I i, Func && func)
{ cswitch(ints, i, std::forward<Func>(func), std::forward<Func>(func)); }

/// \brief run \p default_value = \p func(\c ints) if \p i equal \c ints
/// \return \p default_value
template<class T, class Int, Int... ints, class I, class Func>
T rswitch(T default_value, std::integer_sequence<Int, ints...> intseq, I i, Func && func, nodefault_t)
{
  cswitch(
    intseq, i,
    [&](auto ic) { default_value = std::forward<Func>(func)(ic); },
    nodefault_t{}
  );
  return default_value;
}

/// \brief run \p default_value = \p func(\c ints) if \p i equal \c ints, otherwise \p default_value = \p default_func(\p i)
/// \return \p default_value
template<class T, class Int, Int... ints, class I, class Func, class Default>
constexpr
T rswitch(T default_value, std::integer_sequence<Int, ints...> intseq, I i, Func && func, Default && default_func)
{
  cswitch(
    intseq, i,
    [&](auto ic) { default_value = std::forward<Func>(func)(ic); },
    [&](auto i_) { default_value = std::forward<Default>(default_func)(i_); }
  );
  return default_value;
}

/// \brief shortcut for \c rswitch(\p default_value, \p intseq, \p i, \p func, \p func)
template<class T, class Int, Int... ints, class I, class Func>
constexpr
T rswitch(T default_value, std::integer_sequence<Int, ints...> intseq, I i, Func && func)
{ return rswitch(std::forward<T>(default_value), intseq, i, std::forward<Func>(func), std::forward<Func>(func)); }

/// \return \p func(\p ints) if \p i equal \c ints, otherwise \p default_func(\p i)
template<class Int, Int... ints, class I, class Func, class Default>
constexpr
auto rswitch(std::integer_sequence<Int, ints...>, I i, Func && func, Default && default_func)
-> std::common_type_t<
  decltype(std::forward<Default>(default_func)(i)),
  decltype(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))...
>
{
  return [](auto recursive, auto... iic) {
    return recursive(recursive, iic...);
  }([&](auto recf, auto ic, auto ... ics){
    return i == ic
      ? std::forward<Func>(func)(ic)
      : select(
          std::integral_constant<bool, bool(sizeof...(ics))>{},
          recf,
          [&](auto){ return std::forward<Default>(default_func)(i); }
      )(recf, ics...);
  }, std::integral_constant<Int, ints>{}...);
}

/// \return \p func(\p ints) if \p i equal \c ints, otherwise \a result_type{}
template<class Int, Int... ints, class I, class Func>
constexpr
auto rswitch(std::integer_sequence<Int, ints...> intseq, I i, Func && func, nodefault_t)
-> std::common_type_t<
  decltype(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))...
>
{
  return rswitch(intseq, i, std::forward<Func>(func), [](I const &){
    return std::common_type_t<
      decltype(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))...
    >{};
  });
}

/// \brief shortcut for \c rswitch(\c intseq, \p i, \p func, \p func)
template<class Int, Int... ints, class I, class Func>
constexpr
auto rswitch(std::integer_sequence<Int, ints...> intseq, I i, Func && func)
-> std::common_type_t<
  decltype(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))...
>
{ return rswitch(intseq, i, std::forward<Func>(func), std::forward<Func>(func)); }

} }
<commit_msg>fixes cswitch to msvc<commit_after>/* The MIT License (MIT)

Copyright (c) 2016 jonathan poelen

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

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

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

/**
* \author    Jonathan Poelen <jonathan.poelen+falcon@gmail.com>
* \version   0.1
* \brief     Compile time selection statements
*/

#pragma once

#include <initializer_list>
#include <type_traits>
#include <utility>

namespace falcon { namespace cexpr {

template<class T>
constexpr
std::integral_constant<bool, bool(T::value)>
cbool(T const &) noexcept
{ return {}; }

// TODO falcon.cxx project
#ifdef IN_IDE_PARSER

# define FALCON_CEXPR_DECLTYPE_AUTO_RETURN(a) \
  -> decltype(a)                              \
  { return (a); }                             \

# define FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(a) \
  noexcept(noexcept(decltype(a)(a))) ->                \
  decltype(a)                                          \
  { return (a); }                                      \

#else

# define FALCON_CEXPR_DECLTYPE_AUTO_RETURN(...) \
  -> decltype(__VA_ARGS__)                      \
  { return (__VA_ARGS__); }                     \

# define FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(...)    \
  noexcept(noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))) -> \
  decltype(__VA_ARGS__)                                     \
  { return (__VA_ARGS__); }                                 \

#endif

namespace detail
{
  template<class True, class False>
  constexpr True select_(std::true_type, True && yes, False &&)
  { return std::forward<True>(yes); }

  template<class True, class False>
  constexpr False select_(std::false_type, True &&, False && no)
  { return std::forward<False>(no); }
}

/// \return \p yes if \p cond is a \c true constant expression, otherwise \p no
template<class B, class True, class False>
constexpr auto select(B cond, True && yes, False && no)
FALCON_CEXPR_DECLTYPE_AUTO_RETURN(
  detail::select_(cbool(cond), std::forward<True>(yes), std::forward<False>(no))
)

namespace detail
{
  template<class True, class False>
  constexpr auto cif_(std::true_type, True && yes, False &&)
  FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
    std::forward<True>(yes)()
  )

  template<class True, class False>
  constexpr auto cif_(std::false_type, True &&, False && no)
  FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
    std::forward<False>(no)()
  )

  template<class True>
  constexpr
  auto cif_(std::true_type, True && yes)
  FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
    std::forward<True>(yes)()
  )

  template<class True>
  constexpr
  void cif_(std::false_type, True &&)
  {}
}

/// \return \p yes() if \p cond is a \c true constant expression, otherwise \p no()
template<class B, class True, class False>
constexpr auto cif(B cond, True && yes, False && no)
FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
  detail::cif_(cbool(cond), std::forward<True>(yes), std::forward<False>(no))
)

/// \return \p yes() if \p cond is a \c true constant expression, otherwise \c void
template<class B, class True>
constexpr
auto cif(B cond, True && yes)
FALCON_CEXPR_DECLTYPE_AUTO_RETURN_NOEXCEPT(
  detail::cif_(cbool(cond), std::forward<True>(yes))
)

struct nodefault_t {
  constexpr nodefault_t() noexcept {}
};
constexpr nodefault_t nodefault;

namespace detail
{
  template<class Int, Int... ints>
  class check_unique_int : std::integral_constant<Int, ints>... {};
}

/// \brief run \p func(\c ints) if \p i equal \c ints
template<class Int, Int... ints, class I, class Func>
constexpr
void cswitch(std::integer_sequence<Int, ints...>, I i, Func && func, nodefault_t)
{
  detail::check_unique_int<Int, ints...>{};

  (void)std::initializer_list<int>{(void(
    i == ints
    ? void(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))
    : void()
  ), 1)...};
}

/// \brief run \p func(\c ints) if \p i equal \c ints, otherwise \p default_func(\p i)
template<class Int, Int... ints, class I, class Func, class Default>
constexpr
void cswitch(std::integer_sequence<Int, ints...>, I i, Func && func, Default && default_func)
{
  detail::check_unique_int<Int, ints...>{};
  [&]{ // msvc...
    bool has_int = false;
    (void)std::initializer_list<int>{(void(
      i == ints
      ? void((std::forward<Func>(func)(std::integral_constant<Int, ints>{}), void(has_int = true)))
      : void()
    ), 1)...};
    if (!has_int) {
      std::forward<Default>(default_func)(i);
    }
  }();
}

/// \brief shortcut for \c cswitch(\p ints, \p i, \p func, \p func)
template<class Ints, class I, class Func>
constexpr
void cswitch(Ints ints, I i, Func && func)
{ cswitch(ints, i, std::forward<Func>(func), std::forward<Func>(func)); }

/// \brief run \p default_value = \p func(\c ints) if \p i equal \c ints
/// \return \p default_value
template<class T, class Int, Int... ints, class I, class Func>
T rswitch(T default_value, std::integer_sequence<Int, ints...> intseq, I i, Func && func, nodefault_t)
{
  cswitch(
    intseq, i,
    [&](auto ic) { default_value = std::forward<Func>(func)(ic); },
    nodefault_t{}
  );
  return default_value;
}

/// \brief run \p default_value = \p func(\c ints) if \p i equal \c ints, otherwise \p default_value = \p default_func(\p i)
/// \return \p default_value
template<class T, class Int, Int... ints, class I, class Func, class Default>
constexpr
T rswitch(T default_value, std::integer_sequence<Int, ints...> intseq, I i, Func && func, Default && default_func)
{
  cswitch(
    intseq, i,
    [&](auto ic) { default_value = std::forward<Func>(func)(ic); },
    [&](auto i_) { default_value = std::forward<Default>(default_func)(i_); }
  );
  return default_value;
}

/// \brief shortcut for \c rswitch(\p default_value, \p intseq, \p i, \p func, \p func)
template<class T, class Int, Int... ints, class I, class Func>
constexpr
T rswitch(T default_value, std::integer_sequence<Int, ints...> intseq, I i, Func && func)
{ return rswitch(std::forward<T>(default_value), intseq, i, std::forward<Func>(func), std::forward<Func>(func)); }

/// \return \p func(\p ints) if \p i equal \c ints, otherwise \p default_func(\p i)
template<class Int, Int... ints, class I, class Func, class Default>
constexpr
auto rswitch(std::integer_sequence<Int, ints...>, I i, Func && func, Default && default_func)
-> std::common_type_t<
  decltype(std::forward<Default>(default_func)(i)),
  decltype(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))...
>
{
  return [](auto recursive, auto... iic) {
    return recursive(recursive, iic...);
  }([&](auto recf, auto ic, auto ... ics){
    return i == ic
      ? std::forward<Func>(func)(ic)
      : select(
          std::integral_constant<bool, bool(sizeof...(ics))>{},
          recf,
          [&](auto){ return std::forward<Default>(default_func)(i); }
      )(recf, ics...);
  }, std::integral_constant<Int, ints>{}...);
}

/// \return \p func(\p ints) if \p i equal \c ints, otherwise \a result_type{}
template<class Int, Int... ints, class I, class Func>
constexpr
auto rswitch(std::integer_sequence<Int, ints...> intseq, I i, Func && func, nodefault_t)
-> std::common_type_t<
  decltype(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))...
>
{
  return rswitch(intseq, i, std::forward<Func>(func), [](I const &){
    return std::common_type_t<
      decltype(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))...
    >{};
  });
}

/// \brief shortcut for \c rswitch(\c intseq, \p i, \p func, \p func)
template<class Int, Int... ints, class I, class Func>
constexpr
auto rswitch(std::integer_sequence<Int, ints...> intseq, I i, Func && func)
-> std::common_type_t<
  decltype(std::forward<Func>(func)(std::integral_constant<Int, ints>{}))...
>
{ return rswitch(intseq, i, std::forward<Func>(func), std::forward<Func>(func)); }

} }
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * 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
 *
 *****************************************************************************/

#ifndef MAPNIK_UTILS_HPP
#define MAPNIK_UTILS_HPP

// boost
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif

// stl
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <limits>
#include <ctime>
#include <algorithm>
#include <cmath>

namespace mapnik
{

#ifdef MAPNIK_THREADSAFE
using boost::mutex;
#endif

template <typename T>
class CreateUsingNew
{
public:
    static T* create()
    {
        return new T;
    }
    static void destroy(T* obj)
    {
        delete obj;
    }
};

template <typename T>
class CreateStatic
{
private:
    union MaxAlign
    {
        char t_[sizeof(T)];
        short int shortInt_;
        int int_;
        long int longInt_;
        float float_;
        double double_;
        long double longDouble_;
        struct Test;
        int Test::* pMember_;
        int (Test::*pMemberFn_)(int);
    };

public:

    static T* create()
    {
        static MaxAlign staticMemory;
        return new(&staticMemory) T;
    }

    static void destroy(volatile T* obj)
    {
        obj->~T();
    }
};

#ifdef __GNUC__
    template <typename T,
              template <typename U> class CreatePolicy=CreateStatic> class MAPNIK_DECL singleton
    {
#else
    template <typename T,
              template <typename U> class CreatePolicy=CreateStatic> class singleton
    {
#endif
        friend class CreatePolicy<T>;
        static T* pInstance_;
        static bool destroyed_;
        singleton(const singleton &rhs);
        singleton& operator=(const singleton&);

        static void onDeadReference()
        {
            throw std::runtime_error("dead reference!");
        }

        static void DestroySingleton()
        {
            CreatePolicy<T>::destroy(pInstance_);
            pInstance_ = 0;
            destroyed_ = true;
        }

    protected:
#ifdef MAPNIK_THREADSAFE
        static mutex mutex_;
#endif
        singleton() {}
    public:
        static T& instance()
        {
            if (! pInstance_)
            {
#ifdef MAPNIK_THREADSAFE
                mutex::scoped_lock lock(mutex_);
#endif
                if (! pInstance_)
                {
                    if (destroyed_)
                    {
                        destroyed_ = false;
                        onDeadReference();
                    }
                    else
                    {
                        pInstance_ = CreatePolicy<T>::create();

                        // register destruction
                        std::atexit(&DestroySingleton);
                    }
                }
            }
            return *pInstance_;
        }
    };
#ifdef MAPNIK_THREADSAFE
    template <typename T,
              template <typename U> class CreatePolicy> mutex singleton<T,CreatePolicy>::mutex_;
#endif

    template <typename T,
              template <typename U> class CreatePolicy> T* singleton<T,CreatePolicy>::pInstance_=0;
    template <typename T,
              template <typename U> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;

#ifdef _WINDOWS

#include <windows.h>

    // UTF8 <--> UTF16 conversion routines

    std::string utf16_to_utf8(std::wstring const& wstr)
    {
        std::string str;
        int size = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, 0, 0, 0, 0);
        if(size > 0)
        {
            std::vector<char> buffer(size);
            WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &buffer[0], size, 0, 0);
            str.assign(buffer.begin(), buffer.end() - 1);
        }
        return str;
    }

    std::wstring utf8_to_utf16 (std::string const& str)
    {
        std::wstring wstr;
        int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, 0, 0);
        if (size > 0)
        {
            std::vector<wchar_t> buffer(size);
            MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &buffer[0], size);
            wstr.assign(buffer.begin(), buffer.end() - 1);
        }
        return wstr;
    }

#endif  // _WINDOWS

}

#endif // MAPNIK_UTILS_HPP
<commit_msg>+ add accidentally removed config.hpp<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * 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
 *
 *****************************************************************************/

#ifndef MAPNIK_UTILS_HPP
#define MAPNIK_UTILS_HPP

#include <mapnik/config.hpp>

// boost
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif

// stl
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <limits>
#include <ctime>
#include <algorithm>
#include <cmath>

namespace mapnik
{

#ifdef MAPNIK_THREADSAFE
using boost::mutex;
#endif

template <typename T>
class CreateUsingNew
{
public:
    static T* create()
    {
        return new T;
    }
    static void destroy(T* obj)
    {
        delete obj;
    }
};

template <typename T>
class CreateStatic
{
private:
    union MaxAlign
    {
        char t_[sizeof(T)];
        short int shortInt_;
        int int_;
        long int longInt_;
        float float_;
        double double_;
        long double longDouble_;
        struct Test;
        int Test::* pMember_;
        int (Test::*pMemberFn_)(int);
    };

public:

    static T* create()
    {
        static MaxAlign staticMemory;
        return new(&staticMemory) T;
    }

    static void destroy(volatile T* obj)
    {
        obj->~T();
    }
};

#ifdef __GNUC__
template <typename T,
          template <typename U> class CreatePolicy=CreateStatic> class MAPNIK_DECL singleton
{
#else

template <typename T,
          template <typename U> class CreatePolicy=CreateStatic> class singleton
{
#endif
    friend class CreatePolicy<T>;
    static T* pInstance_;
    static bool destroyed_;
    singleton(const singleton &rhs);
    singleton& operator=(const singleton&);

    static void onDeadReference()
    {
        throw std::runtime_error("dead reference!");
    }

    static void DestroySingleton()
    {
        CreatePolicy<T>::destroy(pInstance_);
        pInstance_ = 0;
        destroyed_ = true;
    }

protected:
#ifdef MAPNIK_THREADSAFE
    static mutex mutex_;
#endif
    singleton() {}
public:
    static T& instance()
    {
        if (! pInstance_)
        {
#ifdef MAPNIK_THREADSAFE
            mutex::scoped_lock lock(mutex_);
#endif
            if (! pInstance_)
            {
                if (destroyed_)
                {
                    destroyed_ = false;
                    onDeadReference();
                }
                else
                {
                    pInstance_ = CreatePolicy<T>::create();

                    // register destruction
                    std::atexit(&DestroySingleton);
                }
            }
        }
        return *pInstance_;
    }
};

#ifdef MAPNIK_THREADSAFE
template <typename T,
          template <typename U> class CreatePolicy> mutex singleton<T,CreatePolicy>::mutex_;
#endif

template <typename T,
          template <typename U> class CreatePolicy> T* singleton<T,CreatePolicy>::pInstance_=0;
template <typename T,
          template <typename U> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;

#ifdef _WINDOWS

#include <windows.h>

// UTF8 <--> UTF16 conversion routines

std::string utf16_to_utf8(std::wstring const& wstr)
{
    std::string str;
    int size = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, 0, 0, 0, 0);
    if(size > 0)
    {
        std::vector<char> buffer(size);
        WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &buffer[0], size, 0, 0);
        str.assign(buffer.begin(), buffer.end() - 1);
    }
    return str;
}

std::wstring utf8_to_utf16 (std::string const& str)
{
    std::wstring wstr;
    int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, 0, 0);
    if (size > 0)
    {
        std::vector<wchar_t> buffer(size);
        MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &buffer[0], size);
        wstr.assign(buffer.begin(), buffer.end() - 1);
    }
    return wstr;
}

#endif  // _WINDOWS

}

#endif // MAPNIK_UTILS_HPP
<|endoftext|>


<commit_before>#pragma once

#include <type_traits>
#include <vector>
#include <initializer_list>
#include <cstddef>
#include <algorithm>
#include <iterator>

namespace helene
{

template <class T, std::size_t StackBufferSize = sizeof(std::vector<T>)>
class small_vector
{
    static_assert(std::is_trivial<T>::value,
                  "small_vector is only compatible with trivial types");

public:
    typedef typename std::vector<T>::size_type size_type;
    typedef typename std::vector<T>::difference_type difference_type;
    typedef T* iterator;
    typedef const T* const_iterator;

private:
    static constexpr size_type at_least_size =
        std::max(StackBufferSize, sizeof(std::vector<T>));
    static constexpr size_type max_stack_size_ = at_least_size / sizeof(T);

public:
    small_vector() : size_()
    {
        new(&storage_) T[max_stack_size_];
    }

    small_vector(std::initializer_list<T> init) : size_(init.size())
    {
        if(size_ > max_stack_size_)
        {
            new(&storage_) std::vector<T>(init);
        }
        else
        {
            new(&storage_) T[max_stack_size_];
            std::copy(
                init.begin(), init.end(), reinterpret_cast<T*>(&storage_));
        }
    }

    small_vector(size_type count) : size_(count)
    {
        if(size_ > max_stack_size_)
        {
            new(&storage_) std::vector<T>(count);
        }
        else
        {
            new(&storage_) T[max_stack_size_];
            std::fill_n(reinterpret_cast<T*>(&storage_), size_, T{});
        }
    }

    small_vector(size_type count, const T& value)
    {
        if(size_ > max_stack_size_)
        {
            new(&storage_) std::vector<T>(count, value);
        }
        else
        {
            new(&storage_) T[max_stack_size_];
            std::fill_n(reinterpret_cast<T*>(&storage_), size_, value);
        }
    }

    ~small_vector()
    {
        if(size_ > max_stack_size_)
        {
            reinterpret_cast<std::vector<T>*>(&storage_)->~vector();
        }
    }

public:
    void
    push_back(const T& value)
    {
        if(size_ > max_stack_size_)
        {
            reinterpret_cast<std::vector<T>*>(&storage_)->push_back(value);
        }
        else if(size_ == max_stack_size_)
        {
            T* buff = reinterpret_cast<T*>(&storage_);
            T temp[max_stack_size_];
            std::copy(buff, buff + size_, std::begin(temp));

            new(&storage_) std::vector<T>(std::begin(temp), std::end(temp));
            reinterpret_cast<std::vector<T>*>(&storage_)->push_back(value);
        }
        else
        {
            reinterpret_cast<T*>(&storage_)[size_] = value;
        }

        ++size_;
    }

    void
    pop_back()
    {
        if(size_ > max_stack_size_ + 1) // remain on heap
        {
            reinterpret_cast<std::vector<T>*>(&storage_)->pop_back();
            --size_;
        }
        else if(size_ == max_stack_size_ + 1) // transition to stack
        {
            // reinterpret_cast<std::vector<T>*>(&storage_)->pop_back();
            // not necessary, trivially destructible

            std::vector<T> temp(
                std::move(*(reinterpret_cast<std::vector<T>*>(&storage_))));
            reinterpret_cast<std::vector<T>*>(&storage_)->~vector();

            new(&storage_) T[max_stack_size_];
            std::copy(
                temp.begin(), temp.end() - 1, reinterpret_cast<T*>(&storage_));
            --size_;
        }
        else // remain on stack
        {
            --size_;
        }
    }

    T& operator[](size_type n)
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->operator[](n);
        }
        else
        {
            return reinterpret_cast<T*>(&storage_)[n];
        }
    }

    const T& operator[](size_type n) const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->
            operator[](n);
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_)[n];
        }
    }

    T&
    front()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->front();
        }
        else
        {
            return reinterpret_cast<T*>(&storage_)[0];
        }
    }

    const T&
    front() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->front();
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_)[0];
        }
    }

    T&
    back()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->back();
        }
        else
        {
            return reinterpret_cast<T*>(&storage_)[size_ - 1];
        }
    }

    const T&
    back() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->back();
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_)[size_ - 1];
        }
    }

    iterator
    erase(iterator pos)
    {
        if(size_ > max_stack_size_ + 1)
        {
            std::vector<T>* ref = reinterpret_cast<std::vector<T>*>(&storage_);

            // convert to std::vector<T>::iterator
            typename std::vector<T>::iterator iter_pos =
                ref->begin() + (pos - ref->data());

            auto iter_out = ref->erase(iter_pos);
            --size_;

            // convert std::vector<T>::iterator to pointer
            difference_type diff = iter_out - ref->begin();

            return ref->data() + diff;
        }
        else if(size_ == max_stack_size_ + 1)
        {
            std::vector<T>* ref = reinterpret_cast<std::vector<T>*>(&storage_);

            // convert to std::vector<T>::iterator
            const auto diff = pos - ref->data();
            typename std::vector<T>::iterator iter_pos =
                ref->begin() + (pos - ref->data());

            auto iter_out = ref->erase(iter_pos);

            std::vector<T> temp(std::move(*ref));
            ref->~vector();

            new(&storage_) T[max_stack_size_];
            std::copy(
                temp.begin(), temp.end(), reinterpret_cast<T*>(&storage_));
            --size_;

            return reinterpret_cast<T*>(&storage_) + diff;
        }
        else
        {
            T* beg = reinterpret_cast<T*>(&storage_);
            std::copy(pos + 1, end(), pos);

            --size_;
            return pos;
        }
    }

    iterator
    erase(iterator first, iterator last)
    {
        const auto erase_size = std::distance(first, last);

        if(size_ > max_stack_size_ + erase_size)
        {
            std::vector<T>* ref = reinterpret_cast<std::vector<T>*>(&storage_);

            // convert to std::vector<T>::iterator
            auto first_iter = ref->begin() + (first - begin());
            auto last_iter = ref->begin() + (last - begin());

            auto iter_out = ref->erase(first_iter, last_iter);
            size_ -= erase_size;

            // convert back to simple pointer
            return begin() + (iter_out - ref->begin());
        }
        else if(size_ <= max_stack_size_)
        {
            T* buff_beg = reinterpret_cast<T*>(&storage_);
            if(last < end()) // if anything left past end of range to erase
            {
                std::copy(last, end(), first);
            }
            size_ -= erase_size;
            return first;
        }
        else
        {
            std::vector<T>* ref = reinterpret_cast<std::vector<T>*>(&storage_);

            // convert to std::vector<T>::iterator
            auto first_iter = ref->begin() + (first - begin());
            auto last_iter = ref->begin() + (last - begin());

            // carry out erase on vector
            auto iter_out = ref->erase(first_iter, last_iter);
            const auto out_diff = iter_out - ref->begin();

            std::vector<T> temp(std::move(*ref));
            ref->~vector();

            new(&storage_) T[max_stack_size_];

            std::copy(
                temp.begin(), temp.end(), reinterpret_cast<T*>(&storage_));

            size_ -= erase_size;

            return begin() + out_diff;
        }
    }

    T*
    data()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->data();
        }
        else
        {
            return reinterpret_cast<T*>(&storage_);
        }
    }

    const T*
    data() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->data();
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_);
        }
    }

    iterator
    begin()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->data();
        }
        else
        {
            return reinterpret_cast<T*>(&storage_);
        }
    }

    iterator
    end()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->data() + size_;
        }
        else
        {
            return reinterpret_cast<T*>(&storage_) + size_;
        }
    }

    const_iterator
    cbegin() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->data();
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_);
        }
    }

    const_iterator
    cend() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->data() +
                   size_;
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_) + size_;
        }
    }

    size_type
    size() const
    {
        return size_;
    }

    bool
    empty() const
    {
        return size_ == 0;
    }

    static constexpr size_type
    max_stack_size()
    {
        return max_stack_size_;
    }

    bool
    on_stack() const
    {
        return size_ <= max_stack_size_;
    }

private:
    std::aligned_storage_t<at_least_size> storage_;
    size_type size_;
};

} // namespace helene
<commit_msg>Add public typedefs. 	modified:   include/small_vector.hpp<commit_after>#pragma once

#include <type_traits>
#include <vector>
#include <initializer_list>
#include <cstddef>
#include <algorithm>
#include <iterator>

namespace helene
{

template <class T, std::size_t StackBufferSize = sizeof(std::vector<T>)>
class small_vector
{
    static_assert(std::is_trivial<T>::value,
                  "small_vector is only compatible with trivial types");

public:
    typedef T value_type;
    typedef typename std::vector<T>::size_type size_type;
    typedef typename std::vector<T>::difference_type difference_type;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T* iterator;
    typedef const T* const_iterator;

private:
    static constexpr size_type at_least_size =
        std::max(StackBufferSize, sizeof(std::vector<T>));
    static constexpr size_type max_stack_size_ = at_least_size / sizeof(T);

public:
    small_vector() : size_()
    {
        new(&storage_) T[max_stack_size_];
    }

    small_vector(std::initializer_list<T> init) : size_(init.size())
    {
        if(size_ > max_stack_size_)
        {
            new(&storage_) std::vector<T>(init);
        }
        else
        {
            new(&storage_) T[max_stack_size_];
            std::copy(
                init.begin(), init.end(), reinterpret_cast<T*>(&storage_));
        }
    }

    small_vector(size_type count) : size_(count)
    {
        if(size_ > max_stack_size_)
        {
            new(&storage_) std::vector<T>(count);
        }
        else
        {
            new(&storage_) T[max_stack_size_];
            std::fill_n(reinterpret_cast<T*>(&storage_), size_, T{});
        }
    }

    small_vector(size_type count, const T& value)
    {
        if(size_ > max_stack_size_)
        {
            new(&storage_) std::vector<T>(count, value);
        }
        else
        {
            new(&storage_) T[max_stack_size_];
            std::fill_n(reinterpret_cast<T*>(&storage_), size_, value);
        }
    }

    ~small_vector()
    {
        if(size_ > max_stack_size_)
        {
            reinterpret_cast<std::vector<T>*>(&storage_)->~vector();
        }
    }

public:
    void
    push_back(const T& value)
    {
        if(size_ > max_stack_size_)
        {
            reinterpret_cast<std::vector<T>*>(&storage_)->push_back(value);
        }
        else if(size_ == max_stack_size_)
        {
            T* buff = reinterpret_cast<T*>(&storage_);
            T temp[max_stack_size_];
            std::copy(buff, buff + size_, std::begin(temp));

            new(&storage_) std::vector<T>(std::begin(temp), std::end(temp));
            reinterpret_cast<std::vector<T>*>(&storage_)->push_back(value);
        }
        else
        {
            reinterpret_cast<T*>(&storage_)[size_] = value;
        }

        ++size_;
    }

    void
    pop_back()
    {
        if(size_ > max_stack_size_ + 1) // remain on heap
        {
            reinterpret_cast<std::vector<T>*>(&storage_)->pop_back();
            --size_;
        }
        else if(size_ == max_stack_size_ + 1) // transition to stack
        {
            // reinterpret_cast<std::vector<T>*>(&storage_)->pop_back();
            // not necessary, trivially destructible

            std::vector<T> temp(
                std::move(*(reinterpret_cast<std::vector<T>*>(&storage_))));
            reinterpret_cast<std::vector<T>*>(&storage_)->~vector();

            new(&storage_) T[max_stack_size_];
            std::copy(
                temp.begin(), temp.end() - 1, reinterpret_cast<T*>(&storage_));
            --size_;
        }
        else // remain on stack
        {
            --size_;
        }
    }

    T& operator[](size_type n)
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->operator[](n);
        }
        else
        {
            return reinterpret_cast<T*>(&storage_)[n];
        }
    }

    const T& operator[](size_type n) const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->
            operator[](n);
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_)[n];
        }
    }

    T&
    front()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->front();
        }
        else
        {
            return reinterpret_cast<T*>(&storage_)[0];
        }
    }

    const T&
    front() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->front();
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_)[0];
        }
    }

    T&
    back()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->back();
        }
        else
        {
            return reinterpret_cast<T*>(&storage_)[size_ - 1];
        }
    }

    const T&
    back() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->back();
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_)[size_ - 1];
        }
    }

    iterator
    erase(iterator pos)
    {
        if(size_ > max_stack_size_ + 1)
        {
            std::vector<T>* ref = reinterpret_cast<std::vector<T>*>(&storage_);

            // convert to std::vector<T>::iterator
            typename std::vector<T>::iterator iter_pos =
                ref->begin() + (pos - ref->data());

            auto iter_out = ref->erase(iter_pos);
            --size_;

            // convert std::vector<T>::iterator to pointer
            difference_type diff = iter_out - ref->begin();

            return ref->data() + diff;
        }
        else if(size_ == max_stack_size_ + 1)
        {
            std::vector<T>* ref = reinterpret_cast<std::vector<T>*>(&storage_);

            // convert to std::vector<T>::iterator
            const auto diff = pos - ref->data();
            typename std::vector<T>::iterator iter_pos =
                ref->begin() + (pos - ref->data());

            auto iter_out = ref->erase(iter_pos);

            std::vector<T> temp(std::move(*ref));
            ref->~vector();

            new(&storage_) T[max_stack_size_];
            std::copy(
                temp.begin(), temp.end(), reinterpret_cast<T*>(&storage_));
            --size_;

            return reinterpret_cast<T*>(&storage_) + diff;
        }
        else
        {
            T* beg = reinterpret_cast<T*>(&storage_);
            std::copy(pos + 1, end(), pos);

            --size_;
            return pos;
        }
    }

    iterator
    erase(iterator first, iterator last)
    {
        const auto erase_size = std::distance(first, last);

        if(size_ > max_stack_size_ + erase_size)
        {
            std::vector<T>* ref = reinterpret_cast<std::vector<T>*>(&storage_);

            // convert to std::vector<T>::iterator
            auto first_iter = ref->begin() + (first - begin());
            auto last_iter = ref->begin() + (last - begin());

            auto iter_out = ref->erase(first_iter, last_iter);
            size_ -= erase_size;

            // convert back to simple pointer
            return begin() + (iter_out - ref->begin());
        }
        else if(size_ <= max_stack_size_)
        {
            T* buff_beg = reinterpret_cast<T*>(&storage_);
            if(last < end()) // if anything left past end of range to erase
            {
                std::copy(last, end(), first);
            }
            size_ -= erase_size;
            return first;
        }
        else
        {
            std::vector<T>* ref = reinterpret_cast<std::vector<T>*>(&storage_);

            // convert to std::vector<T>::iterator
            auto first_iter = ref->begin() + (first - begin());
            auto last_iter = ref->begin() + (last - begin());

            // carry out erase on vector
            auto iter_out = ref->erase(first_iter, last_iter);
            const auto out_diff = iter_out - ref->begin();

            std::vector<T> temp(std::move(*ref));
            ref->~vector();

            new(&storage_) T[max_stack_size_];

            std::copy(
                temp.begin(), temp.end(), reinterpret_cast<T*>(&storage_));

            size_ -= erase_size;

            return begin() + out_diff;
        }
    }

    T*
    data()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->data();
        }
        else
        {
            return reinterpret_cast<T*>(&storage_);
        }
    }

    const T*
    data() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->data();
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_);
        }
    }

    iterator
    begin()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->data();
        }
        else
        {
            return reinterpret_cast<T*>(&storage_);
        }
    }

    iterator
    end()
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<std::vector<T>*>(&storage_)->data() + size_;
        }
        else
        {
            return reinterpret_cast<T*>(&storage_) + size_;
        }
    }

    const_iterator
    cbegin() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->data();
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_);
        }
    }

    const_iterator
    cend() const
    {
        if(size_ > max_stack_size_)
        {
            return reinterpret_cast<const std::vector<T>*>(&storage_)->data() +
                   size_;
        }
        else
        {
            return reinterpret_cast<const T*>(&storage_) + size_;
        }
    }

    size_type
    size() const
    {
        return size_;
    }

    bool
    empty() const
    {
        return size_ == 0;
    }

    static constexpr size_type
    max_stack_size()
    {
        return max_stack_size_;
    }

    bool
    on_stack() const
    {
        return size_ <= max_stack_size_;
    }

private:
    std::aligned_storage_t<at_least_size> storage_;
    size_type size_;
};

} // namespace helene
<|endoftext|>


<commit_before>#ifndef FILTER_FALSE__HPP__
#define FILTER_FALSE__HPP__

#include <iterbase.hpp>
#include <filter.hpp>

namespace iter {

    namespace detail {

        // Callable object that reverses the boolean result of another
        // callable, taking the object in a Container's iterator
        template <typename FilterFunc, typename Container>
        class PredicateFlipper {
            private:
                FilterFunc filter_func;

                using contained_iter_ret =
                    typename IterBase<Container>::contained_iter_ret;

            public:
                PredicateFlipper(FilterFunc filter_func) :
                    filter_func(filter_func)
                { }

                PredicateFlipper() = delete;
                PredicateFlipper(const PredicateFlipper &) = default;

                // Calls the filter_func
                bool operator() (const contained_iter_ret item) const {
                    return !bool(filter_func(item));
                }
        };

        // Reverses the bool() conversion result of anything that supports a
        // bool conversion
        template <typename Container>
        class BoolFlipper : public BoolTester<Container> {
            private:
                using contained_iter_ret =
                    typename BoolTester<Container>::contained_iter_ret;

            public:
                bool operator() (const contained_iter_ret item) const {
                    return !bool(item);
                }
        };

    }

    // Creates a PredicateFlipper for the predicate function, which reverses
    // the bool result of the function.  The PredicateFlipper is then passed
    // to the normal filter() function
    template <typename FilterFunc, typename Container>
    auto filterfalse(FilterFunc filter_func, Container & container) ->
            decltype(filter(detail::PredicateFlipper<FilterFunc, Container>(
                            filter_func), container)) {
        return filter(
                detail::PredicateFlipper<FilterFunc, Container>(filter_func),
                container);
    }

    // Single argument version, uses a BoolFlipper to reverse the truthiness
    // of an object
    template <typename Container>
    auto filterfalse(Container & container) ->
            decltype(filter(detail::BoolFlipper<Container>(), container)) {
        return filter(detail::BoolFlipper<Container>(), container);
    }

}

#endif //#ifndef FILTER_FALSE__HPP__
<commit_msg>Adds support for temporaries<commit_after>#ifndef FILTER_FALSE__HPP__
#define FILTER_FALSE__HPP__

#include <iterbase.hpp>
#include <filter.hpp>

#include <utility>

namespace iter {

    namespace detail {

        // Callable object that reverses the boolean result of another
        // callable, taking the object in a Container's iterator
        template <typename FilterFunc, typename Container>
        class PredicateFlipper {
            private:
                FilterFunc filter_func;

                using contained_iter_ret =
                    typename IterBase<Container>::contained_iter_ret;

            public:
                PredicateFlipper(FilterFunc filter_func) :
                    filter_func(filter_func)
                { }

                PredicateFlipper() = delete;
                PredicateFlipper(const PredicateFlipper &) = default;

                // Calls the filter_func
                bool operator() (const contained_iter_ret item) const {
                    return !bool(filter_func(item));
                }
        };

        // Reverses the bool() conversion result of anything that supports a
        // bool conversion
        template <typename Container>
        class BoolFlipper : public BoolTester<Container> {
            private:
                using contained_iter_ret =
                    typename BoolTester<Container>::contained_iter_ret;

            public:
                bool operator() (const contained_iter_ret item) const {
                    return !bool(item);
                }
        };

    }

    // Creates a PredicateFlipper for the predicate function, which reverses
    // the bool result of the function.  The PredicateFlipper is then passed
    // to the normal filter() function
    template <typename FilterFunc, typename Container>
    auto filterfalse(FilterFunc filter_func, Container && container) ->
            decltype(filter(
                        detail::PredicateFlipper<FilterFunc, Container>(
                            filter_func),
                        std::forward<Container>(container))) {
        return filter(
                detail::PredicateFlipper<FilterFunc, Container>(filter_func),
                std::forward<Container>(container));
    }

    // Single argument version, uses a BoolFlipper to reverse the truthiness
    // of an object
    template <typename Container>
    auto filterfalse(Container && container) ->
            decltype(filter(
                        detail::BoolFlipper<Container>(),
                        std::forward<Container>(container))) {
        return filter(
                detail::BoolFlipper<Container>(),
                std::forward<Container>(container));
    }

}

#endif //#ifndef FILTER_FALSE__HPP__
<|endoftext|>


<commit_before>/***************************************************************************
 * installable external renderer
 ***************************************************************************/

#include "external_renderer_shader.h"

#include "objects/material.h"
#include "objects/mesh.h"
#include "objects/components/render_data.h"
#include "objects/textures/texture.h"
#include "objects/textures/external_renderer_texture.h"
#include "util/gvr_log.h"

static GVRF_ExternalRenderer externalRenderer = NULL;

void GVRF_installExternalRenderer(GVRF_ExternalRenderer fct) {
    externalRenderer = fct;
}

namespace gvr {

void ExternalRendererShader::render(const glm::mat4& mvp_matrix, RenderData* render_data) {
    if (externalRenderer == NULL) {
        LOGE("External renderer not installed");
        return;
    }

    Texture* texture = render_data->material()->getTexture("main_texture");
    if (texture->getTarget() != ExternalRendererTexture::TARGET) {
        LOGE("External renderer only takes external renderer textures");
        return;
    }

    externalRenderer(reinterpret_cast<ExternalRendererTexture*>(texture)->getData(),
                     render_data->mesh()->getBoundingBoxInfo(), 6,
                     glm::value_ptr(mvp_matrix), 16);

    checkGlError("ExternalRendererShader::render");
}

}

<commit_msg>Fixed compile error<commit_after>/***************************************************************************
 * installable external renderer
 ***************************************************************************/

#include "external_renderer_shader.h"

#include "objects/material.h"
#include "objects/mesh.h"
#include "objects/components/render_data.h"
#include "objects/textures/texture.h"
#include "objects/textures/external_renderer_texture.h"
#include "util/gvr_log.h"

static GVRF_ExternalRenderer externalRenderer = NULL;

void GVRF_installExternalRenderer(GVRF_ExternalRenderer fct) {
    externalRenderer = fct;
}

namespace gvr {

void ExternalRendererShader::render(const glm::mat4& mvp_matrix, RenderData* render_data) {
    if (externalRenderer == NULL) {
        LOGE("External renderer not installed");
        return;
    }

    Texture* texture = render_data->pass(0)->material()->getTexture("main_texture");
    if (texture->getTarget() != ExternalRendererTexture::TARGET) {
        LOGE("External renderer only takes external renderer textures");
        return;
    }

    externalRenderer(reinterpret_cast<ExternalRendererTexture*>(texture)->getData(),
                     render_data->mesh()->getBoundingBoxInfo(), 6,
                     glm::value_ptr(mvp_matrix), 16);

    checkGlError("ExternalRendererShader::render");
}

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008 Sebastian Sauer <mail@dipe.org>
 *
 * This file is part of SuperKaramba.
 *
 * SuperKaramba is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * SuperKaramba 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 SuperKaramba; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "skpackage.h"

#include "themefile.h"

#include <kconfiggroup.h>
#include <kstandarddirs.h>

K_EXPORT_PLASMA_PACKAGESTRUCTURE(superkaramba, SkPackage)

SkPackage::SkPackage(QObject *parent, const QVariantList &args)
    : Plasma::PackageStructure(parent)
{
    Q_UNUSED(args);
    setDefaultMimetypes( QStringList() << "application/zip" << "application/x-superkaramba" );
}

SkPackage::~SkPackage()
{
}

bool SkPackage::installPackage(const QString &archivePath, const QString &packageRoot)
{
    kDebug()<<"archivePath="<<archivePath<<"packageRoot="<<packageRoot;

    ThemeFile theme(archivePath);

    QDir root(packageRoot);
    const QString name = QString("sk_%1").arg(theme.id());
    if( !root.cd(name) && ( !root.mkdir(name) || !root.cd(name) ) ) {
        return false;
    }

    const QString path = root.path();
    //if( ! theme.extractArchiveTo(path) ) {
    if( ! theme.copyArchiveTo(path) ) {
        kWarning()<<"Failed to copy archive="<<archivePath<<" to path="<<path;
        return false;
    }

    setPath(path);

    Plasma::PackageMetadata data;
    data.setPluginName(name);
    data.setImplementationApi("superkaramba");
    data.setType("SuperKaramba");
    //data.setServiceType(const QString &);
    data.setName(theme.name());
    data.setDescription(i18n("SuperKaramba Theme"));
    data.setAuthor(theme.author());
    data.setEmail(theme.authorEmail());
    data.setVersion(theme.version());
    data.setWebsite(theme.homepage());
    data.setLicense(theme.license());
    //data.setApplication("superkaramba");
    //data.setRequiredVersion(const QString &);

    QString iconfile = "superkaramba";
    if( ! theme.iconName().isEmpty() ) {
        theme.extractArchiveFileTo(theme.iconName(), path);
        QFileInfo fi(path, theme.iconName());
        if( fi.exists() )
            iconfile = fi.absoluteFilePath();
    }

    Plasma::Package::registerPackage(data, iconfile);

#if 0
    // write a desktop-file that is used by Plasma to know about our new applet.
    const QString desktopfile = KStandardDirs::locateLocal("services", QString("plasma-scriptengine-%1.desktop").arg(name));
    KDesktopFile desktop(desktopfile);
    KConfigGroup group = desktop.desktopGroup();

    group.writeEntry("Name", theme.name());
    group.writeEntry("Comment", i18n("SuperKaramba Theme"));
    group.writeEntry("Type", "Service");
    group.writeEntry("ServiceTypes", "Plasma/Applet");

    QString iconfile = "superkaramba";
    if( ! theme.iconName().isEmpty() ) {
        QFileInfo fi(path, theme.iconName());
        if( fi.exists() )
            iconfile = fi.absoluteFilePath();
    }
    group.writeEntry("Icon", iconfile);

    group.writeEntry("X-KDE-PluginInfo-Name", name);
    group.writeEntry("X-KDE-PluginInfo-Version", theme.version());
    group.writeEntry("X-KDE-PluginInfo-Author", theme.author());
    group.writeEntry("X-KDE-PluginInfo-Email", theme.authorEmail());
    group.writeEntry("X-KDE-PluginInfo-Website", theme.homepage());
    group.writeEntry("X-KDE-PluginInfo-License", theme.license());
    group.writeEntry("X-KDE-PluginInfo-Category", "SuperKaramba");
    group.writeEntry("X-KDE-PluginInfo-EnabledByDefault", "true");

    // the SkAppletScript ScriptEngine implementation is responsible for our new applet.
    group.writeEntry("X-Plasma-API", "superkaramba");
    // its an applet.
    group.writeEntry("X-Plasma-ComponentTypes", "Applet");
    // the SkPackage PackageStructure implementation is responsible for the applets package format.
    group.writeEntry("X-Plasma-PackageFormat", "superkaramba");

    group.sync();

    // rebuild the cache to let e.g. Plasma know about our new desktop-file.
    //FIXME would be better if we just let plasma know about the new desktop-file and let it add on the fly without using the sycoca
    QDBusMessage msg = QDBusMessage::createSignal("/", "org.kde.KSycoca", "notifyDatabaseChanged" );
    msg << QStringList();
    if( QDBusConnection::sessionBus().isConnected() )
        QDBusConnection::sessionBus().send(msg);
#endif
    return true;
}

#include "skpackage.moc"
<commit_msg>use category, not type<commit_after>/*
 * Copyright (C) 2008 Sebastian Sauer <mail@dipe.org>
 *
 * This file is part of SuperKaramba.
 *
 * SuperKaramba is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * SuperKaramba 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 SuperKaramba; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "skpackage.h"

#include "themefile.h"

#include <kconfiggroup.h>
#include <kstandarddirs.h>

K_EXPORT_PLASMA_PACKAGESTRUCTURE(superkaramba, SkPackage)

SkPackage::SkPackage(QObject *parent, const QVariantList &args)
    : Plasma::PackageStructure(parent)
{
    Q_UNUSED(args);
    setDefaultMimetypes( QStringList() << "application/zip" << "application/x-superkaramba" );
}

SkPackage::~SkPackage()
{
}

bool SkPackage::installPackage(const QString &archivePath, const QString &packageRoot)
{
    kDebug()<<"archivePath="<<archivePath<<"packageRoot="<<packageRoot;

    ThemeFile theme(archivePath);

    QDir root(packageRoot);
    const QString name = QString("sk_%1").arg(theme.id());
    if( !root.cd(name) && ( !root.mkdir(name) || !root.cd(name) ) ) {
        return false;
    }

    const QString path = root.path();
    //if( ! theme.extractArchiveTo(path) ) {
    if( ! theme.copyArchiveTo(path) ) {
        kWarning()<<"Failed to copy archive="<<archivePath<<" to path="<<path;
        return false;
    }

    setPath(path);

    Plasma::PackageMetadata data;
    data.setPluginName(name);
    data.setImplementationApi("superkaramba");
    data.setCategory("SuperKaramba");
    //data.setServiceType(const QString &);
    data.setName(theme.name());
    data.setDescription(i18n("SuperKaramba Theme"));
    data.setAuthor(theme.author());
    data.setEmail(theme.authorEmail());
    data.setVersion(theme.version());
    data.setWebsite(theme.homepage());
    data.setLicense(theme.license());
    //data.setApplication("superkaramba");
    //data.setRequiredVersion(const QString &);

    QString iconfile = "superkaramba";
    if( ! theme.iconName().isEmpty() ) {
        theme.extractArchiveFileTo(theme.iconName(), path);
        QFileInfo fi(path, theme.iconName());
        if( fi.exists() )
            iconfile = fi.absoluteFilePath();
    }

    Plasma::Package::registerPackage(data, iconfile);

#if 0
    // write a desktop-file that is used by Plasma to know about our new applet.
    const QString desktopfile = KStandardDirs::locateLocal("services", QString("plasma-scriptengine-%1.desktop").arg(name));
    KDesktopFile desktop(desktopfile);
    KConfigGroup group = desktop.desktopGroup();

    group.writeEntry("Name", theme.name());
    group.writeEntry("Comment", i18n("SuperKaramba Theme"));
    group.writeEntry("Type", "Service");
    group.writeEntry("ServiceTypes", "Plasma/Applet");

    QString iconfile = "superkaramba";
    if( ! theme.iconName().isEmpty() ) {
        QFileInfo fi(path, theme.iconName());
        if( fi.exists() )
            iconfile = fi.absoluteFilePath();
    }
    group.writeEntry("Icon", iconfile);

    group.writeEntry("X-KDE-PluginInfo-Name", name);
    group.writeEntry("X-KDE-PluginInfo-Version", theme.version());
    group.writeEntry("X-KDE-PluginInfo-Author", theme.author());
    group.writeEntry("X-KDE-PluginInfo-Email", theme.authorEmail());
    group.writeEntry("X-KDE-PluginInfo-Website", theme.homepage());
    group.writeEntry("X-KDE-PluginInfo-License", theme.license());
    group.writeEntry("X-KDE-PluginInfo-Category", "SuperKaramba");
    group.writeEntry("X-KDE-PluginInfo-EnabledByDefault", "true");

    // the SkAppletScript ScriptEngine implementation is responsible for our new applet.
    group.writeEntry("X-Plasma-API", "superkaramba");
    // its an applet.
    group.writeEntry("X-Plasma-ComponentTypes", "Applet");
    // the SkPackage PackageStructure implementation is responsible for the applets package format.
    group.writeEntry("X-Plasma-PackageFormat", "superkaramba");

    group.sync();

    // rebuild the cache to let e.g. Plasma know about our new desktop-file.
    //FIXME would be better if we just let plasma know about the new desktop-file and let it add on the fly without using the sycoca
    QDBusMessage msg = QDBusMessage::createSignal("/", "org.kde.KSycoca", "notifyDatabaseChanged" );
    msg << QStringList();
    if( QDBusConnection::sessionBus().isConnected() )
        QDBusConnection::sessionBus().send(msg);
#endif
    return true;
}

#include "skpackage.moc"
<|endoftext|>