<commit_before>#pragma once

#include "defaults.hpp"
#include "tools.hpp"
#include "grid_base.hpp"
#include "grid_tools.hpp"
#include "container.hpp"

namespace gftools {

/** A grid_object_base is a wrapper over container class, that stores data,
 * defined on multiple different grids.
 */
template <typename ContainerType, typename ...GridTypes>
class grid_object_base;

template <typename ValueType, typename ... GridTypes>
using grid_object = grid_object_base<container<ValueType, sizeof...(GridTypes)>, GridTypes...>;

template <typename ValueType, typename ... GridTypes>
using grid_object_ref = grid_object_base<container_ref<ValueType, sizeof...(GridTypes)>, GridTypes...>;

template <typename ContainerType, typename ...GridTypes>
class grid_object_base
{
public:
    /// A typedef for the container.
    typedef ContainerType container_type;
    /// A typedef for the values stored in the container.
    typedef typename ContainerType::value_type value_type;
    /// A typedef for a tuple of grids.
    typedef std::tuple<GridTypes...> grid_tuple;
    /// Tuple of grids traits.
    typedef tools::grid_tuple_traits<grid_tuple> trs;
    /// Total number of grids.
    static constexpr size_t N = sizeof...(GridTypes);

    /// A typedef for a function that gives the analytical value of the object, when it's not stored.
    typedef typename tools::GridArgTypeExtractor<value_type, std::tuple<GridTypes...> >::f_type function_type;
    /// A typedef for a function that gives the analytical value of the object, when it's not stored.
    typedef typename tools::GridPointExtractor<value_type, std::tuple<GridTypes...> >::f_type point_function_type;
    /// A typedef for a tuple of grid points.
    typedef typename trs::point_tuple point_tuple;
    /// A typedef for a tuple of grid point values.
    typedef typename trs::arg_tuple arg_tuple;
    /// A typedef for an array of grid indices.
    typedef typename trs::indices indices_t;

    class exPointMismatch : public std::exception { virtual const char* what() const throw() { return "Index mismatch."; }; };
    class exIOProblem : public std::exception { virtual const char* what() const throw(){return "IO problem.";} };
    class ex_wrong_index : public std::exception { virtual const char* what() const throw(){return "Index out of bounds";}};
public:
    /// Grids on which the data is defined.
    const std::tuple<GridTypes...> grids_;
    /// Cache data dimensions.
    const indices_t dims_;
    /// Actual data - can be a container (data allocated) or a view (proxy to some other data).
    container_type data_;
    /// This function returns the value of the object when the point is not in container.
    function_type tail_;

// Constructors
    /// Constructs a grid object out of a tuple containing various grids.
    grid_object_base( const std::tuple<GridTypes...> &grids);
    //grid_object_base( const std::tuple<GridTypes...> &grids, ContainerType&& in);
    grid_object_base( GridTypes... grids):grid_object_base(std::forward_as_tuple(grids...)){};
    /// Constructor of grids and data.

    template <typename CType>
        grid_object_base( const std::tuple<GridTypes...> &grids, CType& data);
    grid_object_base( const std::tuple<GridTypes...> &grids, ContainerType&& data);

    /// Copy constructor.
    grid_object_base( const grid_object_base<ContainerType, GridTypes...>& rhs);
    template <typename CType>
        grid_object_base( const grid_object_base<CType, GridTypes...>& rhs);
    /// Move constructor.
    grid_object_base( grid_object_base<ContainerType, GridTypes...>&& rhs);
// Assignments
    grid_object_base& operator= (const grid_object_base & rhs);
    template <typename CType>
        grid_object_base& operator= (const grid_object_base<CType,GridTypes...> & rhs);
    grid_object_base& operator= (grid_object_base && rhs);
    grid_object_base& operator= (const value_type & rhs);

// Properties of gridobjects - dimensions, grids, etc
    std::tuple<GridTypes...> const& grids() const { return grids_; }
    /// Returns an Mth grid in grids_.
    template<size_t M = 0>
        auto grid() const -> const typename std::tuple_element<M, std::tuple<GridTypes...>>::type&
           { return std::get<M>(grids_); };
    size_t size() const { return data_.size(); }
    point_tuple points(indices_t in) const { return trs::points(in,grids_); }
    arg_tuple get_args(indices_t in) const { return trs::get_args(in, grids_); }
    arg_tuple get_args(point_tuple in) const { return trs::get_args(in, grids_); }
    indices_t get_indices(point_tuple in) const { return trs::get_indices(in, grids_); }
    /// Returns the data_ container.
    container_type& data(){return data_;}
    container_type const& data() const {return data_;}
    function_type& tail(){return tail_;}

// Global operations - reductions, shifts
    /// Returns the complex conjugate of this object, if it's complex valued.
    grid_object_base<ContainerType, GridTypes...> conj() { return grid_object_base(grids_, data_.conj()); }
    /// Returns a norm of difference between two objects.
    template <typename CT>
        real_type diff (const grid_object_base<CT, GridTypes...> &rhs) const { return data_.diff(rhs.data()); } ;
    /// Returns the sum of all elements in the container.
    value_type sum() { return data_.sum(); };
    /// Returns an object with arguments, shifted by the given values.
    template <typename ...ArgTypes>
        typename std::enable_if<
            (std::is_convertible<std::tuple<typename std::remove_reference<ArgTypes>::type...>, arg_tuple>::value || std::is_convertible<std::tuple<ArgTypes...>, point_tuple>::value),
            grid_object<value_type, GridTypes...>>::type shift(ArgTypes... args) const { return this->shift(std::forward_as_tuple(args...)); }
    template <typename ...ArgTypes>
        typename std::enable_if<
            (std::is_convertible<std::tuple<ArgTypes...>, arg_tuple>::value || std::is_same<std::tuple<ArgTypes...>, point_tuple>::value),
            grid_object<value_type, GridTypes...>>::type shift(const std::tuple<ArgTypes...>& arg_tuple) const ;

// IO
    /// Save the data to the txt file.
    void savetxt(const std::string& fname) const;
    /// Loads the data to the txt file.
    void loadtxt(const std::string& fname, real_type tol = 1e-8);
    /// Dumps the object to the stream.
    template <typename CT, class ...GridTypes2> friend std::ostream& operator<<(std::ostream& lhs, const grid_object_base<CT,GridTypes2...> &in);

// Access operators
    /// Returns element number i, which corresponds to (*_grid)[i].
    auto operator[](size_t i)->decltype(data_[i]) { return data_[i]; };
    //template <size_t M> value_type& operator[](const std::array<size_t,M>& in);
    /// Returns tail_(in).
    value_type tail_eval(const arg_tuple& in) const { return tuple_tools::unfold_tuple(tail_, in); }
    template <typename ... ArgTypes>
        typename std::enable_if<std::is_convertible<std::tuple<ArgTypes...>, arg_tuple>::value, value_type>::type
            tail_eval(ArgTypes...in) { return tail_(in...); };
    /// Return the value by grid values.
    value_type& get(const point_tuple& in) { return data_(get_indices(in)); }

    //value_type& operator()(const point_tuple& in) { return data_(get_indices(in)); }

    const value_type& operator()(const point_tuple& in) const { return data_(get_indices(in)); }

    template <int M=N>
    typename std::enable_if<(M>1 ), value_type>::type  operator()(arg_tuple in) const
    	{
            try { point_tuple x = trs::find_nearest(in, grids_); return (*this)(x); } // FIXME with expression templates
            catch (...) { return this->tail_eval(in); };
        // FIXME # warning grid_object::operator() doesn't provide interpolation for D>=2
        }
    template <int M=N>
    typename std::enable_if<(M==1 ), value_type>::type  operator()(arg_tuple in) const
    	{ try { return std::get<0>(grids_).eval(data_, std::get<0>(in)); } catch (...) { return this->tail_eval(in); } }

    template <typename ...ArgTypes>
    	typename std::enable_if<std::is_convertible<std::tuple<ArgTypes...>, point_tuple>::value
    							, value_type>::type
        operator()(ArgTypes... in) const { return (*this)(point_tuple(std::forward_as_tuple(in...))); }
    template <typename ...ArgTypes>
        	typename std::enable_if<!std::is_convertible<std::tuple<ArgTypes...>, point_tuple>::value &&
        							sizeof...(ArgTypes)!=1 && (sizeof...(ArgTypes)==N)
        							, value_type>::type
            operator()(ArgTypes... in) const { return (*this)(arg_tuple(std::forward_as_tuple(in...))); }

    template <typename ArgType>
    	typename std::enable_if<std::is_same<std::tuple<ArgType>, arg_tuple>::value, value_type>::type
    	 operator()(ArgType in) const { try { return std::get<0>(grids_).eval(data_, in); }
            catch (typename std::tuple_element<0, grid_tuple>::type::ex_wrong_index) { return tail_(in); }; }

    /*template <typename ArgType>
        	typename std::enable_if<std::is_same<std::tuple<ArgType>, arg_tuple>::value, value_type>::type
        	 operator()(ArgType in) { return std::get<0>(grids_).eval(data_, in); }
*/
    /// Return value of grid_object. eval methods of grids are used, so interpolation is done if provided with grids

// Fill values
    /// Fills the container with a provided function.
    void fill(const function_type &in);
    void fill(const point_function_type &in);
    void fill(const std::function<value_type(arg_tuple)>& in) { this->fill(tools::extract_tuple_f(in)); }
    void fill(const std::function<value_type(point_tuple)>& in) { this->fill(tools::extract_tuple_f(in)); }
    /// A shortcut for fill method.
    //template <typename ...ArgTypes> grid_object_base& operator= (const std::function<value_type(ArgTypes...)> &);
    /// Same as operator=, but allows for non-equal grids. Slow. Uses analytic function to provide missing values.
    template <typename CType2>
    grid_object_base& copy_interpolate(const grid_object_base<CType2, GridTypes...> &rhs);

// Math (should be removed to an external algebra class).
    grid_object_base& operator*= (const grid_object_base & rhs);
    grid_object_base& operator*= (const value_type& rhs);
    grid_object_base operator* (const grid_object_base & rhs) const;
    grid_object_base operator* (const value_type & rhs) const;
    grid_object_base& operator+= (const grid_object_base & rhs);
    grid_object_base& operator+= (const value_type& rhs);
    grid_object_base operator+ (const grid_object_base & rhs) const;
    grid_object_base operator+ (const value_type & rhs) const;
    grid_object_base& operator-= (const grid_object_base & rhs);
    grid_object_base& operator-= (const value_type& rhs);
    grid_object_base operator- (const grid_object_base & rhs) const;
    grid_object_base operator- (const value_type & rhs) const;
    grid_object_base& operator/= (const grid_object_base & rhs);
    grid_object_base& operator/= (const value_type& rhs);
    grid_object_base operator/ (const grid_object_base & rhs) const;
    grid_object_base operator/ (const value_type & rhs) const;
    friend grid_object_base operator* (const value_type & lhs, const grid_object_base & rhs) {return rhs*lhs;};
    friend grid_object_base operator+ (const value_type & lhs, const grid_object_base & rhs) {return rhs+lhs;};
    friend grid_object_base operator- (const value_type & lhs, const grid_object_base & rhs) {return rhs*(-1.0)+lhs;};
    friend grid_object_base operator/ (const value_type & lhs, const grid_object_base & rhs) {grid_object_base out(rhs); out=lhs; return out/rhs;};
};

/*
/// A helper recursive template utility to extract and set data from the container.
    template <size_t Nc, typename CT, typename ArgType1, typename ...ArgTypes> struct containerExtractor {
        typedef typename CT::value_type value_type;
        /// Gets the data by values.
        static value_type get(CT &data, const std::tuple<GridTypes...> &grids, const ArgType1& arg1, const ArgTypes&... args);
        static value_type& get_ref(CT &data, const std::tuple<GridTypes...> &grids, const ArgType1& arg1, const ArgTypes&... args);
             };
    /// Specialization of containerExtractor for 1-dim container.
    template <typename CT, typename ArgType1> struct containerExtractor<1,CT,ArgType1> {
        typedef typename CT::value_type value_type;
        static value_type get(CT &data, const std::tuple<GridTypes...> &grids, const ArgType1& arg1);
        static value_type get(CT &data, const std::tuple<GridTypes...> &grids, const std::tuple<ArgType1>& arg1);

        static value_type& get_ref(CT &data, const std::tuple<GridTypes...> &grids, const ArgType1& arg1);
        static value_type& get_ref(CT &data, const std::tuple<GridTypes...> &grids, const std::tuple<ArgType1>& arg1);
        };
*/

} // end of namespace gftools

#include "grid_object.hxx"

<commit_msg>const operator[] for grid_objects<commit_after>#pragma once

#include "defaults.hpp"
#include "tools.hpp"
#include "grid_base.hpp"
#include "grid_tools.hpp"
#include "container.hpp"

namespace gftools {

/** A grid_object_base is a wrapper over container class, that stores data,
 * defined on multiple different grids.
 */
template <typename ContainerType, typename ...GridTypes>
class grid_object_base;

template <typename ValueType, typename ... GridTypes>
using grid_object = grid_object_base<container<ValueType, sizeof...(GridTypes)>, GridTypes...>;

template <typename ValueType, typename ... GridTypes>
using grid_object_ref = grid_object_base<container_ref<ValueType, sizeof...(GridTypes)>, GridTypes...>;

template <typename ContainerType, typename ...GridTypes>
class grid_object_base
{
public:
    /// A typedef for the container.
    typedef ContainerType container_type;
    /// A typedef for the values stored in the container.
    typedef typename ContainerType::value_type value_type;
    /// A typedef for a tuple of grids.
    typedef std::tuple<GridTypes...> grid_tuple;
    /// Tuple of grids traits.
    typedef tools::grid_tuple_traits<grid_tuple> trs;
    /// Total number of grids.
    static constexpr size_t N = sizeof...(GridTypes);

    /// A typedef for a function that gives the analytical value of the object, when it's not stored.
    typedef typename tools::GridArgTypeExtractor<value_type, std::tuple<GridTypes...> >::f_type function_type;
    /// A typedef for a function that gives the analytical value of the object, when it's not stored.
    typedef typename tools::GridPointExtractor<value_type, std::tuple<GridTypes...> >::f_type point_function_type;
    /// A typedef for a tuple of grid points.
    typedef typename trs::point_tuple point_tuple;
    /// A typedef for a tuple of grid point values.
    typedef typename trs::arg_tuple arg_tuple;
    /// A typedef for an array of grid indices.
    typedef typename trs::indices indices_t;

    class exPointMismatch : public std::exception { virtual const char* what() const throw() { return "Index mismatch."; }; };
    class exIOProblem : public std::exception { virtual const char* what() const throw(){return "IO problem.";} };
    class ex_wrong_index : public std::exception { virtual const char* what() const throw(){return "Index out of bounds";}};
public:
    /// Grids on which the data is defined.
    const std::tuple<GridTypes...> grids_;
    /// Cache data dimensions.
    const indices_t dims_;
    /// Actual data - can be a container (data allocated) or a view (proxy to some other data).
    container_type data_;
    /// This function returns the value of the object when the point is not in container.
    function_type tail_;

// Constructors
    /// Constructs a grid object out of a tuple containing various grids.
    grid_object_base( const std::tuple<GridTypes...> &grids);
    //grid_object_base( const std::tuple<GridTypes...> &grids, ContainerType&& in);
    grid_object_base( GridTypes... grids):grid_object_base(std::forward_as_tuple(grids...)){};
    /// Constructor of grids and data.

    template <typename CType>
        grid_object_base( const std::tuple<GridTypes...> &grids, CType& data);
    grid_object_base( const std::tuple<GridTypes...> &grids, ContainerType&& data);

    /// Copy constructor.
    grid_object_base( const grid_object_base<ContainerType, GridTypes...>& rhs);
    template <typename CType>
        grid_object_base( const grid_object_base<CType, GridTypes...>& rhs);
    /// Move constructor.
    grid_object_base( grid_object_base<ContainerType, GridTypes...>&& rhs);
// Assignments
    grid_object_base& operator= (const grid_object_base & rhs);
    template <typename CType>
        grid_object_base& operator= (const grid_object_base<CType,GridTypes...> & rhs);
    grid_object_base& operator= (grid_object_base && rhs);
    grid_object_base& operator= (const value_type & rhs);

// Properties of gridobjects - dimensions, grids, etc
    std::tuple<GridTypes...> const& grids() const { return grids_; }
    /// Returns an Mth grid in grids_.
    template<size_t M = 0>
        auto grid() const -> const typename std::tuple_element<M, std::tuple<GridTypes...>>::type&
           { return std::get<M>(grids_); };
    size_t size() const { return data_.size(); }
    point_tuple points(indices_t in) const { return trs::points(in,grids_); }
    arg_tuple get_args(indices_t in) const { return trs::get_args(in, grids_); }
    arg_tuple get_args(point_tuple in) const { return trs::get_args(in, grids_); }
    indices_t get_indices(point_tuple in) const { return trs::get_indices(in, grids_); }
    /// Returns the data_ container.
    container_type& data(){return data_;}
    container_type const& data() const {return data_;}
    function_type& tail(){return tail_;}

// Global operations - reductions, shifts
    /// Returns the complex conjugate of this object, if it's complex valued.
    grid_object_base<ContainerType, GridTypes...> conj() { return grid_object_base(grids_, data_.conj()); }
    /// Returns a norm of difference between two objects.
    template <typename CT>
        real_type diff (const grid_object_base<CT, GridTypes...> &rhs) const { return data_.diff(rhs.data()); } ;
    /// Returns the sum of all elements in the container.
    value_type sum() { return data_.sum(); };
    /// Returns an object with arguments, shifted by the given values.
    template <typename ...ArgTypes>
        typename std::enable_if<
            (std::is_convertible<std::tuple<typename std::remove_reference<ArgTypes>::type...>, arg_tuple>::value || std::is_convertible<std::tuple<ArgTypes...>, point_tuple>::value),
            grid_object<value_type, GridTypes...>>::type shift(ArgTypes... args) const { return this->shift(std::forward_as_tuple(args...)); }
    template <typename ...ArgTypes>
        typename std::enable_if<
            (std::is_convertible<std::tuple<ArgTypes...>, arg_tuple>::value || std::is_same<std::tuple<ArgTypes...>, point_tuple>::value),
            grid_object<value_type, GridTypes...>>::type shift(const std::tuple<ArgTypes...>& arg_tuple) const ;

// IO
    /// Save the data to the txt file.
    void savetxt(const std::string& fname) const;
    /// Loads the data to the txt file.
    void loadtxt(const std::string& fname, real_type tol = 1e-8);
    /// Dumps the object to the stream.
    template <typename CT, class ...GridTypes2> friend std::ostream& operator<<(std::ostream& lhs, const grid_object_base<CT,GridTypes2...> &in);

// Access operators
    /// Returns element number i, which corresponds to (*_grid)[i].
    auto operator[](size_t i)->decltype(data_[i]) { return data_[i]; };
    auto operator[](size_t i) const -> const decltype(data_[i]) { return data_[i]; };
    //template <size_t M> value_type& operator[](const std::array<size_t,M>& in);
    /// Returns tail_(in).
    value_type tail_eval(const arg_tuple& in) const { return tuple_tools::unfold_tuple(tail_, in); }
    template <typename ... ArgTypes>
        typename std::enable_if<std::is_convertible<std::tuple<ArgTypes...>, arg_tuple>::value, value_type>::type
            tail_eval(ArgTypes...in) { return tail_(in...); };
    /// Return the value by grid values.
    value_type& get(const point_tuple& in) { return data_(get_indices(in)); }

    //value_type& operator()(const point_tuple& in) { return data_(get_indices(in)); }

    const value_type& operator()(const point_tuple& in) const { return data_(get_indices(in)); }

    template <int M=N>
    typename std::enable_if<(M>1 ), value_type>::type  operator()(arg_tuple in) const
    	{
            try { point_tuple x = trs::find_nearest(in, grids_); return (*this)(x); } // FIXME with expression templates
            catch (...) { return this->tail_eval(in); };
        // FIXME # warning grid_object::operator() doesn't provide interpolation for D>=2
        }
    template <int M=N>
    typename std::enable_if<(M==1 ), value_type>::type  operator()(arg_tuple in) const
    	{ try { return std::get<0>(grids_).eval(data_, std::get<0>(in)); } catch (...) { return this->tail_eval(in); } }

    template <typename ...ArgTypes>
    	typename std::enable_if<std::is_convertible<std::tuple<ArgTypes...>, point_tuple>::value
    							, value_type>::type
        operator()(ArgTypes... in) const { return (*this)(point_tuple(std::forward_as_tuple(in...))); }
    template <typename ...ArgTypes>
        	typename std::enable_if<!std::is_convertible<std::tuple<ArgTypes...>, point_tuple>::value &&
        							sizeof...(ArgTypes)!=1 && (sizeof...(ArgTypes)==N)
        							, value_type>::type
            operator()(ArgTypes... in) const { return (*this)(arg_tuple(std::forward_as_tuple(in...))); }

    template <typename ArgType>
    	typename std::enable_if<std::is_same<std::tuple<ArgType>, arg_tuple>::value, value_type>::type
    	 operator()(ArgType in) const { try { return std::get<0>(grids_).eval(data_, in); }
            catch (typename std::tuple_element<0, grid_tuple>::type::ex_wrong_index) { return tail_(in); }; }

    /*template <typename ArgType>
        	typename std::enable_if<std::is_same<std::tuple<ArgType>, arg_tuple>::value, value_type>::type
        	 operator()(ArgType in) { return std::get<0>(grids_).eval(data_, in); }
*/
    /// Return value of grid_object. eval methods of grids are used, so interpolation is done if provided with grids

// Fill values
    /// Fills the container with a provided function.
    void fill(const function_type &in);
    void fill(const point_function_type &in);
    void fill(const std::function<value_type(arg_tuple)>& in) { this->fill(tools::extract_tuple_f(in)); }
    void fill(const std::function<value_type(point_tuple)>& in) { this->fill(tools::extract_tuple_f(in)); }
    /// A shortcut for fill method.
    //template <typename ...ArgTypes> grid_object_base& operator= (const std::function<value_type(ArgTypes...)> &);
    /// Same as operator=, but allows for non-equal grids. Slow. Uses analytic function to provide missing values.
    template <typename CType2>
    grid_object_base& copy_interpolate(const grid_object_base<CType2, GridTypes...> &rhs);

// Math (should be removed to an external algebra class).
    grid_object_base& operator*= (const grid_object_base & rhs);
    grid_object_base& operator*= (const value_type& rhs);
    grid_object_base operator* (const grid_object_base & rhs) const;
    grid_object_base operator* (const value_type & rhs) const;
    grid_object_base& operator+= (const grid_object_base & rhs);
    grid_object_base& operator+= (const value_type& rhs);
    grid_object_base operator+ (const grid_object_base & rhs) const;
    grid_object_base operator+ (const value_type & rhs) const;
    grid_object_base& operator-= (const grid_object_base & rhs);
    grid_object_base& operator-= (const value_type& rhs);
    grid_object_base operator- (const grid_object_base & rhs) const;
    grid_object_base operator- (const value_type & rhs) const;
    grid_object_base& operator/= (const grid_object_base & rhs);
    grid_object_base& operator/= (const value_type& rhs);
    grid_object_base operator/ (const grid_object_base & rhs) const;
    grid_object_base operator/ (const value_type & rhs) const;
    friend grid_object_base operator* (const value_type & lhs, const grid_object_base & rhs) {return rhs*lhs;};
    friend grid_object_base operator+ (const value_type & lhs, const grid_object_base & rhs) {return rhs+lhs;};
    friend grid_object_base operator- (const value_type & lhs, const grid_object_base & rhs) {return rhs*(-1.0)+lhs;};
    friend grid_object_base operator/ (const value_type & lhs, const grid_object_base & rhs) {grid_object_base out(rhs); out=lhs; return out/rhs;};
};

/*
/// A helper recursive template utility to extract and set data from the container.
    template <size_t Nc, typename CT, typename ArgType1, typename ...ArgTypes> struct containerExtractor {
        typedef typename CT::value_type value_type;
        /// Gets the data by values.
        static value_type get(CT &data, const std::tuple<GridTypes...> &grids, const ArgType1& arg1, const ArgTypes&... args);
        static value_type& get_ref(CT &data, const std::tuple<GridTypes...> &grids, const ArgType1& arg1, const ArgTypes&... args);
             };
    /// Specialization of containerExtractor for 1-dim container.
    template <typename CT, typename ArgType1> struct containerExtractor<1,CT,ArgType1> {
        typedef typename CT::value_type value_type;
        static value_type get(CT &data, const std::tuple<GridTypes...> &grids, const ArgType1& arg1);
        static value_type get(CT &data, const std::tuple<GridTypes...> &grids, const std::tuple<ArgType1>& arg1);

        static value_type& get_ref(CT &data, const std::tuple<GridTypes...> &grids, const ArgType1& arg1);
        static value_type& get_ref(CT &data, const std::tuple<GridTypes...> &grids, const std::tuple<ArgType1>& arg1);
        };
*/

} // end of namespace gftools

#include "grid_object.hxx"

<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/planning/common/planning_gflags.h"
DEFINE_int32(planning_loop_rate, 5, "Loop rate for planning node");

DEFINE_string(rtk_trajectory_filename, "modules/planning/data/garage.csv",
              "Loop rate for planning node");

DEFINE_uint64(backward_trajectory_point_num, 10,
              "The number of points to be included in planning trajectory "
              "before the matched point");

DEFINE_uint64(rtk_trajectory_forward, 800,
              "The number of points to be included in RTK trajectory "
              "after the matched point");

DEFINE_double(trajectory_resolution, 0.01,
              "The time resolution of "
              "output trajectory.");

DEFINE_double(
    look_backward_distance, 10,
    "look backward this distance when creating reference line from routing");

DEFINE_double(
    look_forward_distance, 70,
    "look forward this distance when creating reference line from routing");
DEFINE_bool(enable_smooth_reference_line, true,
            "enable smooth the map reference line");

DEFINE_int32(max_history_frame_num, 5, "The maximum history frame number");

DEFINE_double(max_collision_distance, 0.1,
              "considered as collision if distance (meters) is smaller than or "
              "equal to this (meters)");

DEFINE_double(replan_distance_threshold, 5.0,
              "The distance threshold of replan");

DEFINE_bool(enable_reference_line_provider_thread, false,
            "Enable reference line provider thread.");

DEFINE_double(default_reference_line_width, 4.0,
              "Default reference line width");

DEFINE_double(planning_upper_speed_limit, 7.5,
              "Maximum speed (m/s) in planning.");

DEFINE_double(planning_distance, 100, "Planning distance");

DEFINE_double(trajectory_time_length, 8.0, "Trajectory time length");
DEFINE_double(trajectory_time_resolution, 0.1,
              "Trajectory time resolution in planning");
DEFINE_double(output_trajectory_time_resolution, 0.05,
              "Trajectory time resolution when publish");

DEFINE_bool(enable_trajectory_check, false,
            "Enable sanity check for planning trajectory.");

DEFINE_double(speed_lower_bound, -0.02, "The lowest speed allowed.");
DEFINE_double(speed_upper_bound, 40.0, "The highest speed allowed.");

DEFINE_double(longitudinal_acceleration_lower_bound, -4.5,
              "The lowest longitudinal acceleration allowed.");
DEFINE_double(longitudinal_acceleration_upper_bound, 4.0,
              "The highest longitudinal acceleration allowed.");

DEFINE_double(lateral_acceleration_bound, 4.5,
              "Bound of lateral acceleration; symmetric for left and right");
DEFINE_double(lateral_jerk_bound, 4.0,
              "Bound of lateral jerk; symmetric for left and right");

DEFINE_double(longitudinal_jerk_lower_bound, -4.0,
              "The lower bound of longitudinal jerk.");
DEFINE_double(longitudinal_jerk_upper_bound, 4.0,
              "The upper bound of longitudinal jerk.");

DEFINE_double(kappa_bound, 1.00, "The bound for vehicle curvature");

// ST Boundary
DEFINE_double(st_max_s, 80, "the maximum s of st boundary");
DEFINE_double(st_max_t, 10, "the maximum t of st boundary");

// Decision Part
DEFINE_double(static_obstacle_speed_threshold, 1.0,
              "obstacles are considered as static obstacle if its speed is "
              "less than this value (m/s)");
DEFINE_bool(enable_nudge_decision, false, "enable nudge decision");
DEFINE_double(static_decision_ignore_s_range, 3.0,
              "threshold for judging nudge in dp path computing decision");
DEFINE_double(static_decision_nudge_l_buffer, 0.5, "l buffer for nudge");
DEFINE_double(stop_distance_obstacle, 10.0,
              "stop distance from in-lane obstacle (meters)");
DEFINE_double(stop_distance_destination, 3.0,
              "stop distance from destination line");
DEFINE_double(min_driving_width, 2.5,
              "minimum road width(meters) for adc to drive through");
DEFINE_double(nudge_distance_obstacle, 0.3,
              "minimum distance to nudge a obstacle (meters)");
DEFINE_double(follow_min_distance, 10,
              "min follow distance for vehicles/bicycles/moving objects");
DEFINE_double(stop_line_min_distance, 0.0,
              "min distance (meters) to stop line for a valid stop");

DEFINE_string(destination_obstacle_id, "DEST",
              "obstacle id for converting destination to an obstacle");
DEFINE_int32(virtual_obstacle_perception_id, -1,
             "virtual obstacle perception id(a negative int)");
DEFINE_double(virtual_stop_wall_length, 0.1,
              "virtual stop wall length (meters)");
DEFINE_double(virtual_stop_wall_width, 3.7, "virtual stop wall width (meters)");
DEFINE_double(virtual_stop_wall_height, 2.0,
              "virtual stop wall height (meters)");

// Prediction Part
DEFINE_double(prediction_total_time, 5.0, "Total prediction time");
DEFINE_bool(align_prediction_time, true,
            "enable align prediction data based planning time");

// Trajectory
DEFINE_bool(enable_rule_layer, true,
            "enable rule for trajectory before model computation");

// Traffic decision

DEFINE_string(planning_config_file,
              "modules/planning/conf/planning_config.pb.txt",
              "planning config file");

DEFINE_int32(trajectory_point_num_for_debug, 10,
             "number of output trajectory points for debugging");

DEFINE_double(decision_valid_stop_range, 0.5,
              "The valid stop range in decision.");
DEFINE_bool(enable_record_debug, true,
            "True to enable record debug into debug protobuf.");
DEFINE_bool(enable_prediction, true, "True to enable prediction input.");

// QpSt optimizer
DEFINE_bool(enable_slowdown_profile_generator, true,
            "True to enable slowdown speed profile generator.");
DEFINE_double(slowdown_speed_threshold, 8.0,
              "Only generator slowdown profile when adc speed is lower than "
              "this threshold. unit : m/s.");
DEFINE_double(slowdown_profile_deceleration, -1.0,
              "The deceleration to generate slowdown profile. unit: m/s^2.");
<commit_msg>planning: disable align_prediction_time to allow rosbag replay works for planning.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/planning/common/planning_gflags.h"
DEFINE_int32(planning_loop_rate, 5, "Loop rate for planning node");

DEFINE_string(rtk_trajectory_filename, "modules/planning/data/garage.csv",
              "Loop rate for planning node");

DEFINE_uint64(backward_trajectory_point_num, 10,
              "The number of points to be included in planning trajectory "
              "before the matched point");

DEFINE_uint64(rtk_trajectory_forward, 800,
              "The number of points to be included in RTK trajectory "
              "after the matched point");

DEFINE_double(trajectory_resolution, 0.01,
              "The time resolution of "
              "output trajectory.");

DEFINE_double(
    look_backward_distance, 10,
    "look backward this distance when creating reference line from routing");

DEFINE_double(
    look_forward_distance, 70,
    "look forward this distance when creating reference line from routing");
DEFINE_bool(enable_smooth_reference_line, true,
            "enable smooth the map reference line");

DEFINE_int32(max_history_frame_num, 5, "The maximum history frame number");

DEFINE_double(max_collision_distance, 0.1,
              "considered as collision if distance (meters) is smaller than or "
              "equal to this (meters)");

DEFINE_double(replan_distance_threshold, 5.0,
              "The distance threshold of replan");

DEFINE_bool(enable_reference_line_provider_thread, false,
            "Enable reference line provider thread.");

DEFINE_double(default_reference_line_width, 4.0,
              "Default reference line width");

DEFINE_double(planning_upper_speed_limit, 7.5,
              "Maximum speed (m/s) in planning.");

DEFINE_double(planning_distance, 100, "Planning distance");

DEFINE_double(trajectory_time_length, 8.0, "Trajectory time length");
DEFINE_double(trajectory_time_resolution, 0.1,
              "Trajectory time resolution in planning");
DEFINE_double(output_trajectory_time_resolution, 0.05,
              "Trajectory time resolution when publish");

DEFINE_bool(enable_trajectory_check, false,
            "Enable sanity check for planning trajectory.");

DEFINE_double(speed_lower_bound, -0.02, "The lowest speed allowed.");
DEFINE_double(speed_upper_bound, 40.0, "The highest speed allowed.");

DEFINE_double(longitudinal_acceleration_lower_bound, -4.5,
              "The lowest longitudinal acceleration allowed.");
DEFINE_double(longitudinal_acceleration_upper_bound, 4.0,
              "The highest longitudinal acceleration allowed.");

DEFINE_double(lateral_acceleration_bound, 4.5,
              "Bound of lateral acceleration; symmetric for left and right");
DEFINE_double(lateral_jerk_bound, 4.0,
              "Bound of lateral jerk; symmetric for left and right");

DEFINE_double(longitudinal_jerk_lower_bound, -4.0,
              "The lower bound of longitudinal jerk.");
DEFINE_double(longitudinal_jerk_upper_bound, 4.0,
              "The upper bound of longitudinal jerk.");

DEFINE_double(kappa_bound, 1.00, "The bound for vehicle curvature");

// ST Boundary
DEFINE_double(st_max_s, 80, "the maximum s of st boundary");
DEFINE_double(st_max_t, 10, "the maximum t of st boundary");

// Decision Part
DEFINE_double(static_obstacle_speed_threshold, 1.0,
              "obstacles are considered as static obstacle if its speed is "
              "less than this value (m/s)");
DEFINE_bool(enable_nudge_decision, false, "enable nudge decision");
DEFINE_double(static_decision_ignore_s_range, 3.0,
              "threshold for judging nudge in dp path computing decision");
DEFINE_double(static_decision_nudge_l_buffer, 0.5, "l buffer for nudge");
DEFINE_double(stop_distance_obstacle, 10.0,
              "stop distance from in-lane obstacle (meters)");
DEFINE_double(stop_distance_destination, 3.0,
              "stop distance from destination line");
DEFINE_double(min_driving_width, 2.5,
              "minimum road width(meters) for adc to drive through");
DEFINE_double(nudge_distance_obstacle, 0.3,
              "minimum distance to nudge a obstacle (meters)");
DEFINE_double(follow_min_distance, 10,
              "min follow distance for vehicles/bicycles/moving objects");
DEFINE_double(stop_line_min_distance, 0.0,
              "min distance (meters) to stop line for a valid stop");

DEFINE_string(destination_obstacle_id, "DEST",
              "obstacle id for converting destination to an obstacle");
DEFINE_int32(virtual_obstacle_perception_id, -1,
             "virtual obstacle perception id(a negative int)");
DEFINE_double(virtual_stop_wall_length, 0.1,
              "virtual stop wall length (meters)");
DEFINE_double(virtual_stop_wall_width, 3.7, "virtual stop wall width (meters)");
DEFINE_double(virtual_stop_wall_height, 2.0,
              "virtual stop wall height (meters)");

// Prediction Part
DEFINE_double(prediction_total_time, 5.0, "Total prediction time");
DEFINE_bool(align_prediction_time, false,
            "enable align prediction data based planning time");

// Trajectory
DEFINE_bool(enable_rule_layer, true,
            "enable rule for trajectory before model computation");

// Traffic decision

DEFINE_string(planning_config_file,
              "modules/planning/conf/planning_config.pb.txt",
              "planning config file");

DEFINE_int32(trajectory_point_num_for_debug, 10,
             "number of output trajectory points for debugging");

DEFINE_double(decision_valid_stop_range, 0.5,
              "The valid stop range in decision.");
DEFINE_bool(enable_record_debug, true,
            "True to enable record debug into debug protobuf.");
DEFINE_bool(enable_prediction, true, "True to enable prediction input.");

// QpSt optimizer
DEFINE_bool(enable_slowdown_profile_generator, true,
            "True to enable slowdown speed profile generator.");
DEFINE_double(slowdown_speed_threshold, 8.0,
              "Only generator slowdown profile when adc speed is lower than "
              "this threshold. unit : m/s.");
DEFINE_double(slowdown_profile_deceleration, -1.0,
              "The deceleration to generate slowdown profile. unit: m/s^2.");
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;

void addition(int *sum, int x, int y){
	*sum = x + y;
}

int main(){
	int x = 4;
	int y = 5;
	int sum;
	addition(&sum, x, y);

	cout << "The sum is " << sum << endl;

	return 0;
}
<commit_msg>Update S7_Pointer_in_functions.cpp<commit_after>//
//  Program Name - S7_Pointer_in_functions.cpp
//  Series: GetOnToC++ Step: 7
//
//  Purpose: This program illustrates how to and the benefits of pointers in functions
//
//  Compile: g++ S7_Pointer_in_functions.cpp -o S7_Pointer_in_functions
//  Execute: ./S7_Pointer_in_functions
//
//  Created by Narayan Mahadevan on 18/08/13.
//
#include <iostream>
using namespace std;

void addition(int *sum, int x, int y){
	*sum = x + y;
}

int main(){
	int x = 4;
	int y = 5;
	int sum;
	addition(&sum, x, y);

	cout << "The sum is " << sum << endl;

	return 0;
}
<|endoftext|>


<commit_before>/*
 * Segment.cpp
 *****************************************************************************
 * Copyright (C) 2010 - 2011 Klagenfurt University
 *
 * Created on: Aug 10, 2010
 * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
 *          Christian Timmerer  <christian.timmerer@itec.uni-klu.ac.at>
 *
 * This program 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 program 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 program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/
#define __STDC_CONSTANT_MACROS

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "Segment.h"
#include "Representation.h"
#include "MPD.h"
#include "mp4/AtomsReader.hpp"

#include <cassert>

using namespace dash::mpd;
using namespace dash::http;

ISegment::ISegment(const ICanonicalUrl *parent):
    ICanonicalUrl( parent ),
    startByte  (0),
    endByte    (0),
    startTime  (VLC_TS_INVALID),
    duration   (0)
{
    debugName = "Segment";
    classId = CLASSID_ISEGMENT;
}

dash::http::Chunk * ISegment::getChunk(const std::string &url)
{
    return new (std::nothrow) SegmentChunk(this, url);
}

dash::http::Chunk* ISegment::toChunk(size_t index, Representation *ctxrep)
{
    Chunk *chunk;
    try
    {
        chunk = getChunk(getUrlSegment().toString(index, ctxrep));
        if (!chunk)
            return NULL;
    }
    catch (int)
    {
        return NULL;
    }

    if(startByte != endByte)
    {
        chunk->setStartByte(startByte);
        chunk->setEndByte(endByte);
    }

    return chunk;
}

bool ISegment::isSingleShot() const
{
    return true;
}
void ISegment::done()
{
    //Only used for a SegmentTemplate.
}

void ISegment::setByteRange(size_t start, size_t end)
{
    startByte = start;
    endByte   = end;
}

void ISegment::setStartTime(mtime_t ztime)
{
    startTime = ztime;
}

mtime_t ISegment::getStartTime() const
{
    return startTime;
}

mtime_t ISegment::getDuration() const
{
    return duration;
}

void ISegment::setDuration(mtime_t d)
{
    duration = d;
}

size_t ISegment::getOffset() const
{
    return startByte;
}

std::string ISegment::toString(int indent) const
{
    std::stringstream ss;
    ss << std::string(indent, ' ') << debugName << " url=" << getUrlSegment().toString();
    if(startByte!=endByte)
        ss << " @" << startByte << ".." << endByte;
    return ss.str();
}

bool ISegment::contains(size_t byte) const
{
    if (startByte == endByte)
        return false;
    return (byte >= startByte &&
            (!endByte || byte <= endByte) );
}

int ISegment::getClassId() const
{
    return classId;
}

ISegment::SegmentChunk::SegmentChunk(ISegment *segment_, const std::string &url) :
    dash::http::Chunk(url)
{
    segment = segment_;
}

void ISegment::SegmentChunk::onDownload(void *, size_t)
{

}

Segment::Segment(ICanonicalUrl *parent) :
        ISegment(parent)
{
    size = -1;
    classId = CLASSID_SEGMENT;
}

void Segment::addSubSegment(SubSegment *subsegment)
{
    subsegments.push_back(subsegment);
}

Segment::~Segment()
{
    std::vector<SubSegment*>::iterator it;
    for(it=subsegments.begin();it!=subsegments.end();it++)
        delete *it;
}

void                    Segment::setSourceUrl   ( const std::string &url )
{
    if ( url.empty() == false )
        this->sourceUrl = url;
}

std::string Segment::toString(int indent) const
{
    if (subsegments.empty())
    {
        return ISegment::toString(indent);
    }
    else
    {
        std::string ret;
        std::vector<SubSegment *>::const_iterator l;
        for(l = subsegments.begin(); l != subsegments.end(); l++)
        {
            ret.append( (*l)->toString(indent + 1) );
        }
        return ret;
    }
}

Url Segment::getUrlSegment() const
{
    Url ret = getParentUrlSegment();
    if (!sourceUrl.empty())
        ret.append(sourceUrl);
    return ret;
}

dash::http::Chunk* Segment::toChunk(size_t index, Representation *ctxrep)
{
    Chunk *chunk = ISegment::toChunk(index, ctxrep);
    if (chunk && ctxrep)
        chunk->setBitrate(ctxrep->getBandwidth());
    return chunk;
}

std::vector<ISegment*> Segment::subSegments()
{
    std::vector<ISegment*> list;
    if(!subsegments.empty())
    {
        std::vector<SubSegment*>::iterator it;
        for(it=subsegments.begin();it!=subsegments.end();it++)
            list.push_back(*it);
    }
    else
    {
        list.push_back(this);
    }
    return list;
}

InitSegment::InitSegment(ICanonicalUrl *parent) :
    Segment(parent)
{
    debugName = "InitSegment";
    classId = CLASSID_INITSEGMENT;
}

IndexSegment::IndexSegment(ICanonicalUrl *parent) :
    Segment(parent)
{
    debugName = "IndexSegment";
    classId = CLASSID_INDEXSEGMENT;
}

dash::http::Chunk* IndexSegment::toChunk(size_t index, Representation *ctxrep)
{
    IndexSegmentChunk *chunk = dynamic_cast<IndexSegmentChunk *>(Segment::toChunk(index, ctxrep));
    chunk->setIndexRepresentation(ctxrep);
    return chunk;
}

dash::http::Chunk * IndexSegment::getChunk(const std::string &url)
{
    return new IndexSegmentChunk(this, url);
}

IndexSegment::IndexSegmentChunk::IndexSegmentChunk(ISegment *segment, const std::string &url)
    : SegmentChunk(segment, url)
{

}

void IndexSegment::IndexSegmentChunk::setIndexRepresentation(Representation *rep_)
{
    rep = rep_;
}

void IndexSegment::IndexSegmentChunk::onDownload(void *buffer, size_t size)
{
    if(!rep)
        return;

    dash::mp4::AtomsReader br(rep->getMPD()->getVLCObject());
    br.parseBlock(buffer, size, rep);
}

SubSegment::SubSegment(Segment *main, size_t start, size_t end) :
    ISegment(main), parent(main)
{
    setByteRange(start, end);
    debugName = "SubSegment";
    classId = CLASSID_SUBSEGMENT;
}

Url SubSegment::getUrlSegment() const
{
    return getParentUrlSegment();
}

std::vector<ISegment*> SubSegment::subSegments()
{
    std::vector<ISegment*> list;
    list.push_back(this);
    return list;
}
<commit_msg>demux: dash: missing initializer (cid #1260244)<commit_after>/*
 * Segment.cpp
 *****************************************************************************
 * Copyright (C) 2010 - 2011 Klagenfurt University
 *
 * Created on: Aug 10, 2010
 * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
 *          Christian Timmerer  <christian.timmerer@itec.uni-klu.ac.at>
 *
 * This program 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 program 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 program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/
#define __STDC_CONSTANT_MACROS

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "Segment.h"
#include "Representation.h"
#include "MPD.h"
#include "mp4/AtomsReader.hpp"

#include <cassert>

using namespace dash::mpd;
using namespace dash::http;

ISegment::ISegment(const ICanonicalUrl *parent):
    ICanonicalUrl( parent ),
    startByte  (0),
    endByte    (0),
    startTime  (VLC_TS_INVALID),
    duration   (0)
{
    debugName = "Segment";
    classId = CLASSID_ISEGMENT;
}

dash::http::Chunk * ISegment::getChunk(const std::string &url)
{
    return new (std::nothrow) SegmentChunk(this, url);
}

dash::http::Chunk* ISegment::toChunk(size_t index, Representation *ctxrep)
{
    Chunk *chunk;
    try
    {
        chunk = getChunk(getUrlSegment().toString(index, ctxrep));
        if (!chunk)
            return NULL;
    }
    catch (int)
    {
        return NULL;
    }

    if(startByte != endByte)
    {
        chunk->setStartByte(startByte);
        chunk->setEndByte(endByte);
    }

    return chunk;
}

bool ISegment::isSingleShot() const
{
    return true;
}
void ISegment::done()
{
    //Only used for a SegmentTemplate.
}

void ISegment::setByteRange(size_t start, size_t end)
{
    startByte = start;
    endByte   = end;
}

void ISegment::setStartTime(mtime_t ztime)
{
    startTime = ztime;
}

mtime_t ISegment::getStartTime() const
{
    return startTime;
}

mtime_t ISegment::getDuration() const
{
    return duration;
}

void ISegment::setDuration(mtime_t d)
{
    duration = d;
}

size_t ISegment::getOffset() const
{
    return startByte;
}

std::string ISegment::toString(int indent) const
{
    std::stringstream ss;
    ss << std::string(indent, ' ') << debugName << " url=" << getUrlSegment().toString();
    if(startByte!=endByte)
        ss << " @" << startByte << ".." << endByte;
    return ss.str();
}

bool ISegment::contains(size_t byte) const
{
    if (startByte == endByte)
        return false;
    return (byte >= startByte &&
            (!endByte || byte <= endByte) );
}

int ISegment::getClassId() const
{
    return classId;
}

ISegment::SegmentChunk::SegmentChunk(ISegment *segment_, const std::string &url) :
    dash::http::Chunk(url)
{
    segment = segment_;
}

void ISegment::SegmentChunk::onDownload(void *, size_t)
{

}

Segment::Segment(ICanonicalUrl *parent) :
        ISegment(parent)
{
    size = -1;
    classId = CLASSID_SEGMENT;
}

void Segment::addSubSegment(SubSegment *subsegment)
{
    subsegments.push_back(subsegment);
}

Segment::~Segment()
{
    std::vector<SubSegment*>::iterator it;
    for(it=subsegments.begin();it!=subsegments.end();it++)
        delete *it;
}

void                    Segment::setSourceUrl   ( const std::string &url )
{
    if ( url.empty() == false )
        this->sourceUrl = url;
}

std::string Segment::toString(int indent) const
{
    if (subsegments.empty())
    {
        return ISegment::toString(indent);
    }
    else
    {
        std::string ret;
        std::vector<SubSegment *>::const_iterator l;
        for(l = subsegments.begin(); l != subsegments.end(); l++)
        {
            ret.append( (*l)->toString(indent + 1) );
        }
        return ret;
    }
}

Url Segment::getUrlSegment() const
{
    Url ret = getParentUrlSegment();
    if (!sourceUrl.empty())
        ret.append(sourceUrl);
    return ret;
}

dash::http::Chunk* Segment::toChunk(size_t index, Representation *ctxrep)
{
    Chunk *chunk = ISegment::toChunk(index, ctxrep);
    if (chunk && ctxrep)
        chunk->setBitrate(ctxrep->getBandwidth());
    return chunk;
}

std::vector<ISegment*> Segment::subSegments()
{
    std::vector<ISegment*> list;
    if(!subsegments.empty())
    {
        std::vector<SubSegment*>::iterator it;
        for(it=subsegments.begin();it!=subsegments.end();it++)
            list.push_back(*it);
    }
    else
    {
        list.push_back(this);
    }
    return list;
}

InitSegment::InitSegment(ICanonicalUrl *parent) :
    Segment(parent)
{
    debugName = "InitSegment";
    classId = CLASSID_INITSEGMENT;
}

IndexSegment::IndexSegment(ICanonicalUrl *parent) :
    Segment(parent)
{
    debugName = "IndexSegment";
    classId = CLASSID_INDEXSEGMENT;
}

dash::http::Chunk* IndexSegment::toChunk(size_t index, Representation *ctxrep)
{
    IndexSegmentChunk *chunk = dynamic_cast<IndexSegmentChunk *>(Segment::toChunk(index, ctxrep));
    chunk->setIndexRepresentation(ctxrep);
    return chunk;
}

dash::http::Chunk * IndexSegment::getChunk(const std::string &url)
{
    return new IndexSegmentChunk(this, url);
}

IndexSegment::IndexSegmentChunk::IndexSegmentChunk(ISegment *segment, const std::string &url)
    : SegmentChunk(segment, url)
{
    rep = NULL;
}

void IndexSegment::IndexSegmentChunk::setIndexRepresentation(Representation *rep_)
{
    rep = rep_;
}

void IndexSegment::IndexSegmentChunk::onDownload(void *buffer, size_t size)
{
    if(!rep)
        return;

    dash::mp4::AtomsReader br(rep->getMPD()->getVLCObject());
    br.parseBlock(buffer, size, rep);
}

SubSegment::SubSegment(Segment *main, size_t start, size_t end) :
    ISegment(main), parent(main)
{
    setByteRange(start, end);
    debugName = "SubSegment";
    classId = CLASSID_SUBSEGMENT;
}

Url SubSegment::getUrlSegment() const
{
    return getParentUrlSegment();
}

std::vector<ISegment*> SubSegment::subSegments()
{
    std::vector<ISegment*> list;
    list.push_back(this);
    return list;
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2011, Arvid Norberg, Magnus Jonsson
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 the author 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.

*/

#include "libtorrent/rsa.hpp"
#include "libtorrent/hasher.hpp"

#if defined TORRENT_USE_OPENSSL

extern "C"
{
#include <openssl/rsa.h>
#include <openssl/objects.h> // for NID_sha1
}

namespace libtorrent
{

// returns the size of the resulting signature
int sign_rsa(sha1_hash const& digest
	, char const* private_key, int private_len
	, char* signature, int sig_len)
{
	// convert bytestring to internal representation
	// of the private key
	RSA* priv = 0;
	unsigned char const* key = (unsigned char const*)private_key;
	priv = d2i_RSAPrivateKey(&priv, &key, private_len);
	if (priv == 0) return -1;

	if (RSA_size(priv) > sig_len)
	{
		RSA_free(priv);
		return -1;
	}

	RSA_sign(NID_sha1, &digest[0], 20, (unsigned char*)signature, (unsigned int*)&sig_len, priv);

	RSA_free(priv);

	return sig_len;
}

// returns true if the signature is valid
bool verify_rsa(sha1_hash const& digest
	, char const* public_key, int public_len
	, char const* signature, int sig_len)
{
	// convert bytestring to internal representation
	// of the public key
	RSA* pub = 0;
	unsigned char const* key = (unsigned char const*)public_key;
	pub = d2i_RSAPublicKey(&pub, &key, public_len);
	if (pub == 0) return false;

	int ret = RSA_verify(NID_sha1, &digest[0], 20, (unsigned char*)signature, sig_len, pub);

	RSA_free(pub);

	return ret;
}

bool generate_rsa_keys(char* public_key, int* public_len
	, char* private_key, int* private_len, int key_size)
{
	RSA* keypair = RSA_generate_key(key_size, 3, 0, 0);
	if (keypair == 0) return false;

	bool ret = false;
	if (RSA_size(keypair) > *public_len) goto getout;
	if (RSA_size(keypair) > *private_len) goto getout;

	unsigned char* pub = (unsigned char*)public_key;
	unsigned char* priv = (unsigned char*)private_key;
	*public_len = i2d_RSAPublicKey(keypair, &pub);
	*private_len = i2d_RSAPrivateKey(keypair, &priv);

	ret = true;

getout:
	RSA_free(keypair);
	return ret;
}

} // namespace libtorrent

#else

// just stub these out for now, since they're not used anywhere yet
namespace libtorrent
{

// returns the size of the resulting signature
int sign_rsa(sha1_hash const& digest
	, char const* private_key, int private_len
	, char* signature, int sig_len)
{
	return 0;
}

// returns true if the signature is valid
bool verify_rsa(sha1_hash const& digest
	, char const* public_key, int public_len
	, char const* signature, int sig_len)
{
	return false;
}

bool generate_rsa_keys(char* public_key, int* public_len
	, char* private_key, int* private_len, int key_size)
{
	return false;
}

} // namespace libtorrent

#endif

<commit_msg>fixed build issue<commit_after>/*

Copyright (c) 2011, Arvid Norberg, Magnus Jonsson
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 the author 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.

*/

#include "libtorrent/rsa.hpp"
#include "libtorrent/hasher.hpp"

#if defined TORRENT_USE_OPENSSL

extern "C"
{
#include <openssl/rsa.h>
#include <openssl/objects.h> // for NID_sha1
}

namespace libtorrent
{

// returns the size of the resulting signature
int sign_rsa(sha1_hash const& digest
	, char const* private_key, int private_len
	, char* signature, int sig_len)
{
	// convert bytestring to internal representation
	// of the private key
	RSA* priv = 0;
	unsigned char const* key = (unsigned char const*)private_key;
	priv = d2i_RSAPrivateKey(&priv, &key, private_len);
	if (priv == 0) return -1;

	if (RSA_size(priv) > sig_len)
	{
		RSA_free(priv);
		return -1;
	}

	RSA_sign(NID_sha1, &digest[0], 20, (unsigned char*)signature, (unsigned int*)&sig_len, priv);

	RSA_free(priv);

	return sig_len;
}

// returns true if the signature is valid
bool verify_rsa(sha1_hash const& digest
	, char const* public_key, int public_len
	, char const* signature, int sig_len)
{
	// convert bytestring to internal representation
	// of the public key
	RSA* pub = 0;
	unsigned char const* key = (unsigned char const*)public_key;
	pub = d2i_RSAPublicKey(&pub, &key, public_len);
	if (pub == 0) return false;

	int ret = RSA_verify(NID_sha1, &digest[0], 20, (unsigned char*)signature, sig_len, pub);

	RSA_free(pub);

	return ret;
}

bool generate_rsa_keys(char* public_key, int* public_len
	, char* private_key, int* private_len, int key_size)
{
	RSA* keypair = RSA_generate_key(key_size, 3, 0, 0);
	if (keypair == 0) return false;

	bool ret = false;
	unsigned char* pub = (unsigned char*)public_key;
	unsigned char* priv = (unsigned char*)private_key;

	if (RSA_size(keypair) > *public_len) goto getout;
	if (RSA_size(keypair) > *private_len) goto getout;

	*public_len = i2d_RSAPublicKey(keypair, &pub);
	*private_len = i2d_RSAPrivateKey(keypair, &priv);

	ret = true;

getout:
	RSA_free(keypair);
	return ret;
}

} // namespace libtorrent

#else

// just stub these out for now, since they're not used anywhere yet
namespace libtorrent
{

// returns the size of the resulting signature
int sign_rsa(sha1_hash const& digest
	, char const* private_key, int private_len
	, char* signature, int sig_len)
{
	return 0;
}

// returns true if the signature is valid
bool verify_rsa(sha1_hash const& digest
	, char const* public_key, int public_len
	, char const* signature, int sig_len)
{
	return false;
}

bool generate_rsa_keys(char* public_key, int* public_len
	, char* private_key, int* private_len, int key_size)
{
	return false;
}

} // namespace libtorrent

#endif

<|endoftext|>


<commit_before>#include <regex>
#include <string.h>
#include "lynxbot.h"
#include "sed.h"
#include "stringparse.h"

struct sedinfo {
	char *regex;
	char *replace;
	int global;
	int ignore;
	int error;
	int errtok;
};

static int parsecmd(struct sedinfo *s, char *cmd);
static void puterr(char *out, size_t max, struct sedinfo *s);

/* sed: perform a basic sed substitution command on input */
int sed(char *s, size_t max, const char *input, const char *sedcmd)
{
	char cmd[MAX_MSG];
	struct sedinfo sedbuf;
	std::regex pattern;
	std::smatch match;

	strncpy(cmd, sedcmd, MAX_MSG);
	if (!parsecmd(&sedbuf, cmd)) {
		puterr(s, max, &sedbuf);
		return 0;
	}

	try {
		if (sedbuf.ignore)
			pattern = std::regex(sedbuf.regex);
		else
			pattern = std::regex(sedbuf.regex, std::regex::icase);
	} catch (std::regex_error) {
		_sprintf(out, max, "sed: invalid regex");
		return 0;
	}

	printf("%s\n%s\n%s\n", input, sedbuf.regex, sedbuf.replace);
	return 1;
}

#define INVCMD 1
#define UNTERM 2
#define BADOPT 3

/* parsecmd: break up the sed command into its parts */
static int parsecmd(struct sedinfo *s, char *cmd)
{
	char *t;
	int delim;

	s->global = s->ignore = 0;
	if (cmd[0] != 's') {
		s->error = INVCMD;
		s->errtok = cmd[0];
		return 0;
	}
	if (!(delim = cmd[1]) || !*(s->regex = cmd + 2)) {
		s->error = UNTERM;
		return 0;
	}
	t = s->regex;
	while ((t = strchr(t, delim)) && *(t - 1) == '\\')
		shift_l(t - 1);
	if (!t) {
		s->error = UNTERM;
		return 0;
	}
	*t++ = '\0';
	if (!*(s->replace = t)) {
		s->error = UNTERM;
		return 0;
	}
	while ((t = strchr(t, delim)) && *(t - 1) == '\\')
		shift_l(t - 1);
	if (!t) {
		s->error = UNTERM;
		return 0;
	}
	*t++ = '\0';
	for (; *t; ++t) {
		switch (*t) {
		case 'g':
			s->global = 1;
			break;
		case 'i':
			s->ignore = 1;
			break;
		default:
			s->error = BADOPT;
			s->errtok = *t;
			return 0;
		}
	}

	return 1;
}

/* puterr: write error string corresponding to s->error to out */
static void puterr(char *out, size_t max, struct sedinfo *s)
{
	switch (s->error) {
	case INVCMD:
		_sprintf(out, max, "sed: invalid command '%c'", s->errtok);
		break;
	case UNTERM:
		_sprintf(out, max, "sed: unterminated 's' command");
		break;
	case BADOPT:
		_sprintf(out, max, "sed: unkown option to 's' command "
				"-- '%c'", s->errtok);
		break;
	default:
		break;
	}
}
<commit_msg>Changed regex parsing to account for delimeters within brackets<commit_after>#include <regex>
#include <string.h>
#include "lynxbot.h"
#include "sed.h"
#include "stringparse.h"

struct sedinfo {
	char *regex;
	char *replace;
	int global;
	int ignore;
	int error;
	int errtok;
};

static int parsecmd(struct sedinfo *s, char *cmd);
static void puterr(char *out, size_t max, struct sedinfo *s);
static char *readbrackets(char *s);

/* sed: perform a basic sed substitution command on input */
int sed(char *s, size_t max, const char *input, const char *sedcmd)
{
	char cmd[MAX_MSG];
	struct sedinfo sedbuf;
	std::regex pattern;
	std::smatch match;

	strncpy(cmd, sedcmd, MAX_MSG);
	if (!parsecmd(&sedbuf, cmd)) {
		puterr(s, max, &sedbuf);
		return 0;
	}

	try {
		if (sedbuf.ignore)
			pattern = std::regex(sedbuf.regex);
		else
			pattern = std::regex(sedbuf.regex, std::regex::icase);
	} catch (std::regex_error) {
		_sprintf(s, max, "sed: invalid regex");
		return 0;
	}

	printf("%s\n%s\n%s\n", input, sedbuf.regex, sedbuf.replace);
	return 1;
}

#define INVCMD 1
#define UNTERM 2
#define BADOPT 3

/* parsecmd: break up the sed command into its parts */
static int parsecmd(struct sedinfo *s, char *cmd)
{
	char *t;
	int delim, type;

	s->global = s->ignore = 0;
	if (cmd[0] != 's') {
		s->error = INVCMD;
		s->errtok = cmd[0];
		return 0;
	}
	if (!(delim = cmd[1]) || !*(s->regex = cmd + 2)) {
		s->error = UNTERM;
		return 0;
	}
	t = s->regex;
	for (t = s->regex; *t; ++t) {
		if (*t == '\'' || *t == '"') {
			if (!(t = readbrackets(t))) {
				s->error = UNTERM;
				return 0;
			}
		} else if (*t == delim) {
			if (*(t - 1) != '\\')
				break;
			shift_l(t - 1);
			--t;
		}
	}
	if (!t) {
		s->error = UNTERM;
		return 0;
	}
	*t++ = '\0';
	if (!*(s->replace = t)) {
		s->error = UNTERM;
		return 0;
	}
	while ((t = strchr(t, delim)) && *(t - 1) == '\\')
		shift_l(t - 1);
	if (!t) {
		s->error = UNTERM;
		return 0;
	}
	*t++ = '\0';
	for (; *t; ++t) {
		switch (*t) {
		case 'g':
			s->global = 1;
			break;
		case 'i':
			s->ignore = 1;
			break;
		default:
			s->error = BADOPT;
			s->errtok = *t;
			return 0;
		}
	}

	return 1;
}

/* puterr: write error string corresponding to s->error to out */
static void puterr(char *out, size_t max, struct sedinfo *s)
{
	switch (s->error) {
	case INVCMD:
		_sprintf(out, max, "sed: invalid command '%c'", s->errtok);
		break;
	case UNTERM:
		_sprintf(out, max, "sed: unterminated 's' command");
		break;
	case BADOPT:
		_sprintf(out, max, "sed: unkown option to 's' command "
				"-- '%c'", s->errtok);
		break;
	default:
		break;
	}
}

static char *readbrackets(char *s)
{
	return s;
}
<|endoftext|>


<commit_before>#ifndef utf8_hh_INCLUDED
#define utf8_hh_INCLUDED

#include <cstddef>
#include "unicode.hh"

namespace Kakoune
{

namespace utf8
{

// returns an iterator to next character first byte
template<typename Iterator>
Iterator next(Iterator it)
{
    if (*it++ & 0x80)
        while ((*(it) & 0xC0) == 0x80)
            ++it;
    return it;
}

// returns it's parameter if it points to a character first byte,
// or else returns next character first byte
template<typename Iterator>
Iterator finish(Iterator it)
{
    while ((*(it) & 0xC0) == 0x80)
        ++it;
    return it;
}

// returns an iterator to the previous character first byte
template<typename Iterator>
Iterator previous(Iterator it)
{
    while ((*(--it) & 0xC0) == 0x80)
           ;
    return it;
}

// returns an iterator pointing to the first byte of the
// dth character after (or before if d < 0) the character
// pointed by it
template<typename Iterator, typename Distance>
Iterator advance(Iterator it, Distance d)
{
    if (d < 0)
    {
       while (d++)
           it = previous(it);
    }
    else
    {
        while (d--)
           it = next(it);
    }
    return it;
}

// returns the character count between begin and end
template<typename Iterator>
size_t distance(Iterator begin, Iterator end)
{
    size_t dist = 0;
    while (begin != end)
    {
        if ((*begin++ & 0xC0) != 0x80)
            ++dist;
    }
}

// return true if it points to the first byte of a (either single or
// multibyte) character
template<typename Iterator>
bool is_character_start(Iterator it)
{
    return (*it & 0xC0) != 0x80;
}

struct invalid_utf8_sequence{};

// returns the codepoint of the character whose first byte
// is pointed by it
template<typename Iterator>
Codepoint codepoint(Iterator it)
{
    // According to rfc3629, UTF-8 allows only up to 4 bytes.
    // (21 bits codepoint)
    Codepoint cp;
    char byte = *it++;
    if (not (byte & 0x80)) // 0xxxxxxx
        cp = byte;
    else if ((byte & 0xE0) == 0xC0) // 110xxxxx
    {
        cp = ((byte & 0x1F) << 6) | (*it & 0x3F);
    }
    else if ((byte & 0xF0) == 0xE0) // 1110xxxx
    {
        cp = ((byte & 0x0F) << 12) | ((*it++ & 0x3F) << 6);
        cp |= (*it & 0x3F);
    }
    else if ((byte & 0xF8) == 0xF0) // 11110xxx
    {
        cp = ((byte & 0x0F) << 18) | ((*it++ & 0x3F) << 12);
        cp |= (*it++ & 0x3F) << 6;
        cp |= (*it & 0x3F);
    }
    else
        throw invalid_utf8_sequence{};
}

struct invalid_codepoint{};

template<typename OutputIterator>
void dump(OutputIterator& it, Codepoint cp)
{
    if (cp <= 0x7F)
        *it++ = cp;
    else if (cp <= 0x7FF)
    {
        *it++ = 0xC0 | (cp >> 6);
        *it++ = 0x80 | (cp & 0x3F);
    }
    else if (cp <= 0xFFFF)
    {
        *it++ = 0xE0 | (cp >> 12);
        *it++ = 0x80 | ((cp >> 6) & 0x3F);
        *it++ = 0x80 | (cp & 0x3F);
    }
    else if (cp <= 0x10FFFF)
    {
        *it++ = 0xF0 | (cp >> 18);
        *it++ = 0x80 | ((cp >> 12) & 0x3F);
        *it++ = 0x80 | ((cp >> 6)  & 0x3F);
        *it++ = 0x80 | (cp & 0x3F);
    }
    else
        throw invalid_codepoint{};
}

}

}

#endif // utf8_hh_INCLUDED
<commit_msg>Actually return something in utf8::codepoint, thanks gcc for using rax<commit_after>#ifndef utf8_hh_INCLUDED
#define utf8_hh_INCLUDED

#include <cstddef>
#include "unicode.hh"

namespace Kakoune
{

namespace utf8
{

// returns an iterator to next character first byte
template<typename Iterator>
Iterator next(Iterator it)
{
    if (*it++ & 0x80)
        while ((*(it) & 0xC0) == 0x80)
            ++it;
    return it;
}

// returns it's parameter if it points to a character first byte,
// or else returns next character first byte
template<typename Iterator>
Iterator finish(Iterator it)
{
    while ((*(it) & 0xC0) == 0x80)
        ++it;
    return it;
}

// returns an iterator to the previous character first byte
template<typename Iterator>
Iterator previous(Iterator it)
{
    while ((*(--it) & 0xC0) == 0x80)
           ;
    return it;
}

// returns an iterator pointing to the first byte of the
// dth character after (or before if d < 0) the character
// pointed by it
template<typename Iterator, typename Distance>
Iterator advance(Iterator it, Distance d)
{
    if (d < 0)
    {
       while (d++)
           it = previous(it);
    }
    else
    {
        while (d--)
           it = next(it);
    }
    return it;
}

// returns the character count between begin and end
template<typename Iterator>
size_t distance(Iterator begin, Iterator end)
{
    size_t dist = 0;
    while (begin != end)
    {
        if ((*begin++ & 0xC0) != 0x80)
            ++dist;
    }
}

// return true if it points to the first byte of a (either single or
// multibyte) character
template<typename Iterator>
bool is_character_start(Iterator it)
{
    return (*it & 0xC0) != 0x80;
}

struct invalid_utf8_sequence{};

// returns the codepoint of the character whose first byte
// is pointed by it
template<typename Iterator>
Codepoint codepoint(Iterator it)
{
    // According to rfc3629, UTF-8 allows only up to 4 bytes.
    // (21 bits codepoint)
    Codepoint cp;
    char byte = *it++;
    if (not (byte & 0x80)) // 0xxxxxxx
        cp = byte;
    else if ((byte & 0xE0) == 0xC0) // 110xxxxx
    {
        cp = ((byte & 0x1F) << 6) | (*it & 0x3F);
    }
    else if ((byte & 0xF0) == 0xE0) // 1110xxxx
    {
        cp = ((byte & 0x0F) << 12) | ((*it++ & 0x3F) << 6);
        cp |= (*it & 0x3F);
    }
    else if ((byte & 0xF8) == 0xF0) // 11110xxx
    {
        cp = ((byte & 0x0F) << 18) | ((*it++ & 0x3F) << 12);
        cp |= (*it++ & 0x3F) << 6;
        cp |= (*it & 0x3F);
    }
    else
        throw invalid_utf8_sequence{};
    return cp;
}

struct invalid_codepoint{};

template<typename OutputIterator>
void dump(OutputIterator& it, Codepoint cp)
{
    if (cp <= 0x7F)
        *it++ = cp;
    else if (cp <= 0x7FF)
    {
        *it++ = 0xC0 | (cp >> 6);
        *it++ = 0x80 | (cp & 0x3F);
    }
    else if (cp <= 0xFFFF)
    {
        *it++ = 0xE0 | (cp >> 12);
        *it++ = 0x80 | ((cp >> 6) & 0x3F);
        *it++ = 0x80 | (cp & 0x3F);
    }
    else if (cp <= 0x10FFFF)
    {
        *it++ = 0xF0 | (cp >> 18);
        *it++ = 0x80 | ((cp >> 12) & 0x3F);
        *it++ = 0x80 | ((cp >> 6)  & 0x3F);
        *it++ = 0x80 | (cp & 0x3F);
    }
    else
        throw invalid_codepoint{};
}

}

}

#endif // utf8_hh_INCLUDED
<|endoftext|>


<commit_before>/* The MIT License (MIT)
 *
 * Copyright (c) 2014-2017 David Medina and Tim Warburton
 *
 * 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
 */

#include <map>

#include "occa/tools/misc.hpp"
#include "occa/tools/sys.hpp"
#include "occa/base.hpp"
#include "occa/uva.hpp"

namespace occa {
  ptrRangeMap_t uvaMap;
  memoryVector_t uvaStaleMemory;

  ptrRange_t::ptrRange_t() :
    start(NULL),
    end(NULL) {}

  ptrRange_t::ptrRange_t(void *ptr, const udim_t bytes) :
    start((char*) ptr),
    end(((char*) ptr) + bytes) {}

  ptrRange_t::ptrRange_t(const ptrRange_t &r) :
    start(r.start),
    end(r.end) {}

  ptrRange_t& ptrRange_t::operator = (const ptrRange_t &r) {
    start = r.start;
    end   = r.end;

    return *this;
  }

  bool ptrRange_t::operator == (const ptrRange_t &r) const {
    return ((start <= r.start) && (r.start < end));
  }

  bool ptrRange_t::operator != (const ptrRange_t &r) const {
    return ((r.start < start) || (end <= r.start));
  }

  int operator < (const ptrRange_t &a, const ptrRange_t &b) {
    return ((a != b) && (a.start < b.start));
  }

  uvaPtrInfo_t::uvaPtrInfo_t() :
    mem(NULL) {}

  uvaPtrInfo_t::uvaPtrInfo_t(void *ptr) {
    ptrRangeMap_t::iterator it = uvaMap.find(ptr);

    if (it != uvaMap.end()) {
      mem = (it->second);
    } else {
      mem = (occa::memory_v*) ptr; // Defaults to ptr being a memory_v
    }
  }

  uvaPtrInfo_t::uvaPtrInfo_t(occa::memory_v *mem_) :
    mem(mem_) {}

  uvaPtrInfo_t::uvaPtrInfo_t(const uvaPtrInfo_t &upi) :
    mem(upi.mem) {}

  uvaPtrInfo_t& uvaPtrInfo_t::operator = (const uvaPtrInfo_t &upi) {
    mem = upi.mem;
    return *this;
  }

  occa::device uvaPtrInfo_t::getDevice() {
    return occa::device(mem->dHandle);
  }

  occa::memory uvaPtrInfo_t::getMemory() {
    return occa::memory(mem);
  }

  occa::memory_v* uvaToMemory(void *ptr) {
    ptrRangeMap_t::iterator it = uvaMap.find(ptr);
    return (it == uvaMap.end()) ? NULL : it->second;
  }

  void startManaging(void *ptr) {
    occa::memory_v *mem = uvaToMemory(ptr);
    if (mem != NULL) {
      mem->memInfo |= uvaFlag::isManaged;
    }
  }

  void stopManaging(void *ptr) {
    occa::memory_v *mem = uvaToMemory(ptr);
    if (mem != NULL) {
      mem->memInfo &= ~uvaFlag::isManaged;
    }
  }

  void syncToDevice(void *ptr, const udim_t bytes) {
    occa::memory_v *mem = uvaToMemory(ptr);
    if (mem) {
      syncMemToDevice(mem, bytes, ptrDiff(mem->uvaPtr, ptr));
    }
  }

  void syncToHost(void *ptr, const udim_t bytes) {
    occa::memory_v *mem = uvaToMemory(ptr);
    if (mem) {
      syncMemToHost(mem, bytes, ptrDiff(mem->uvaPtr, ptr));
    }
  }

  void syncMemToDevice(occa::memory_v *mem,
                       const udim_t bytes,
                       const udim_t offset) {

    if (mem->dHandle->hasSeparateMemorySpace()) {
      occa::memory(mem).syncToDevice(bytes, offset);
    }
  }

  void syncMemToHost(occa::memory_v *mem,
                     const udim_t bytes,
                     const udim_t offset) {

    if (mem->dHandle->hasSeparateMemorySpace()) {
      occa::memory(mem).syncToHost(bytes, offset);
    }
  }

  bool needsSync(void *ptr) {
    occa::memory_v *mem = uvaToMemory(ptr);
    return (mem == NULL) ? false : mem->isStale();
  }

  void sync(void *ptr) {
    occa::memory_v *mem = uvaToMemory(ptr);

    if (mem != NULL) {
      if (mem->inDevice()) {
        syncMemToHost(mem);
      } else {
        syncMemToDevice(mem);
      }
    }
  }

  void dontSync(void *ptr) {
    removeFromStaleMap(ptr);
  }

  void removeFromStaleMap(void *ptr) {
    ptrRangeMap_t::iterator it = uvaMap.find(ptr);
    if (it == uvaMap.end()) {
      return;
    }

    memory m(it->second);
    if (!m.uvaIsStale()) {
      return;
    }

    removeFromStaleMap(m.getMHandle());
  }

  void removeFromStaleMap(memory_v *mem) {
    occa::memory m(mem);
    const size_t staleEntries = uvaStaleMemory.size();

    for (size_t i = 0; i < staleEntries; ++i) {
      if (uvaStaleMemory[i] == mem) {
        m.uvaMarkFresh();
        uvaStaleMemory.erase(uvaStaleMemory.begin() + i);
        break;
      }
    }
  }

  void free(void *ptr) {
    ptrRangeMap_t::iterator it = uvaMap.find(ptr);

    if ((it != uvaMap.end()) &&
       (((void*) it->first.start) != ((void*) it->second))) {
      occa::memory(it->second).free();
    } else {
      ::free(ptr);
    }
  }
}
<commit_msg>[UVA] Set/unset uvaPtr during start/stop managing calls<commit_after>/* The MIT License (MIT)
 *
 * Copyright (c) 2014-2017 David Medina and Tim Warburton
 *
 * 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
 */

#include <map>

#include "occa/tools/misc.hpp"
#include "occa/tools/sys.hpp"
#include "occa/base.hpp"
#include "occa/uva.hpp"

namespace occa {
  ptrRangeMap_t uvaMap;
  memoryVector_t uvaStaleMemory;

  ptrRange_t::ptrRange_t() :
    start(NULL),
    end(NULL) {}

  ptrRange_t::ptrRange_t(void *ptr, const udim_t bytes) :
    start((char*) ptr),
    end(((char*) ptr) + bytes) {}

  ptrRange_t::ptrRange_t(const ptrRange_t &r) :
    start(r.start),
    end(r.end) {}

  ptrRange_t& ptrRange_t::operator = (const ptrRange_t &r) {
    start = r.start;
    end   = r.end;

    return *this;
  }

  bool ptrRange_t::operator == (const ptrRange_t &r) const {
    return ((start <= r.start) && (r.start < end));
  }

  bool ptrRange_t::operator != (const ptrRange_t &r) const {
    return ((r.start < start) || (end <= r.start));
  }

  int operator < (const ptrRange_t &a, const ptrRange_t &b) {
    return ((a != b) && (a.start < b.start));
  }

  uvaPtrInfo_t::uvaPtrInfo_t() :
    mem(NULL) {}

  uvaPtrInfo_t::uvaPtrInfo_t(void *ptr) {
    ptrRangeMap_t::iterator it = uvaMap.find(ptr);

    if (it != uvaMap.end()) {
      mem = (it->second);
    } else {
      mem = (occa::memory_v*) ptr; // Defaults to ptr being a memory_v
    }
  }

  uvaPtrInfo_t::uvaPtrInfo_t(occa::memory_v *mem_) :
    mem(mem_) {}

  uvaPtrInfo_t::uvaPtrInfo_t(const uvaPtrInfo_t &upi) :
    mem(upi.mem) {}

  uvaPtrInfo_t& uvaPtrInfo_t::operator = (const uvaPtrInfo_t &upi) {
    mem = upi.mem;
    return *this;
  }

  occa::device uvaPtrInfo_t::getDevice() {
    return occa::device(mem->dHandle);
  }

  occa::memory uvaPtrInfo_t::getMemory() {
    return occa::memory(mem);
  }

  occa::memory_v* uvaToMemory(void *ptr) {
    ptrRangeMap_t::iterator it = uvaMap.find(ptr);
    return (it == uvaMap.end()) ? NULL : it->second;
  }

  void startManaging(void *ptr) {
    occa::memory_v *mem = uvaToMemory(ptr);
    if (mem != NULL) {
      mem->memInfo |= uvaFlag::isManaged;
      mem->uvaPtr = (char*) ptr;
    }
  }

  void stopManaging(void *ptr) {
    occa::memory_v *mem = uvaToMemory(ptr);
    if (mem != NULL) {
      mem->memInfo &= ~uvaFlag::isManaged;
      mem->uvaPtr = NULL;
    }
  }

  void syncToDevice(void *ptr, const udim_t bytes) {
    occa::memory_v *mem = uvaToMemory(ptr);
    if (mem) {
      syncMemToDevice(mem, bytes, ptrDiff(mem->uvaPtr, ptr));
    }
  }

  void syncToHost(void *ptr, const udim_t bytes) {
    occa::memory_v *mem = uvaToMemory(ptr);
    if (mem) {
      syncMemToHost(mem, bytes, ptrDiff(mem->uvaPtr, ptr));
    }
  }

  void syncMemToDevice(occa::memory_v *mem,
                       const udim_t bytes,
                       const udim_t offset) {

    if (mem->dHandle->hasSeparateMemorySpace()) {
      occa::memory(mem).syncToDevice(bytes, offset);
    }
  }

  void syncMemToHost(occa::memory_v *mem,
                     const udim_t bytes,
                     const udim_t offset) {

    if (mem->dHandle->hasSeparateMemorySpace()) {
      occa::memory(mem).syncToHost(bytes, offset);
    }
  }

  bool needsSync(void *ptr) {
    occa::memory_v *mem = uvaToMemory(ptr);
    return (mem == NULL) ? false : mem->isStale();
  }

  void sync(void *ptr) {
    occa::memory_v *mem = uvaToMemory(ptr);

    if (mem != NULL) {
      if (mem->inDevice()) {
        syncMemToHost(mem);
      } else {
        syncMemToDevice(mem);
      }
    }
  }

  void dontSync(void *ptr) {
    removeFromStaleMap(ptr);
  }

  void removeFromStaleMap(void *ptr) {
    ptrRangeMap_t::iterator it = uvaMap.find(ptr);
    if (it == uvaMap.end()) {
      return;
    }

    memory m(it->second);
    if (!m.uvaIsStale()) {
      return;
    }

    removeFromStaleMap(m.getMHandle());
  }

  void removeFromStaleMap(memory_v *mem) {
    occa::memory m(mem);
    const size_t staleEntries = uvaStaleMemory.size();

    for (size_t i = 0; i < staleEntries; ++i) {
      if (uvaStaleMemory[i] == mem) {
        m.uvaMarkFresh();
        uvaStaleMemory.erase(uvaStaleMemory.begin() + i);
        break;
      }
    }
  }

  void free(void *ptr) {
    ptrRangeMap_t::iterator it = uvaMap.find(ptr);

    if ((it != uvaMap.end()) &&
       (((void*) it->first.start) != ((void*) it->second))) {
      occa::memory(it->second).free();
    } else {
      ::free(ptr);
    }
  }
}
<|endoftext|>