text:
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_CHANNEL_HPP
#define BOOST_GIL_CHANNEL_HPP

#include <boost/gil/utilities.hpp>

#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#include <boost/integer/integer_mask.hpp>

#include <cstdint>
#include <limits>
#include <type_traits>

#ifdef BOOST_GIL_DOXYGEN_ONLY
/// \def BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
/// \brief Define to allow unaligned memory access for models of packed channel
/// value. Theoretically (or historically?) on platforms which support
/// dereferencing on non-word memory boundary, unaligned access may result in
/// performance improvement. \warning Unfortunately, this optimization may be a
/// C/C++ strict aliasing rules violation, if accessed data buffer has effective
/// type that cannot be aliased without leading to undefined behaviour.
#define BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
#endif

#ifdef BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
#if defined(sun) || defined(__sun) || \ // SunOS
defined(__osf__) || defined(__osf) || \ // Tru64
    defined(_hpux) ||
    defined(hpux) || \ // HP-UX
    defined(__arm__) ||
    defined(__ARM_ARCH) || \ // ARM
    defined(_AIX)            // AIX
#error Unaligned access strictly disabled for some UNIX platforms or ARM architecture
#elif defined(__i386__) || defined(__x86_64__) || defined(__vax__)
// The check for little-endian architectures that tolerate unaligned memory
// accesses is just an optimization. Nothing will break if it fails to detect
// a suitable architecture.
//
// Unfortunately, this optimization may be a C/C++ strict aliasing rules
// violation if accessed data buffer has effective type that cannot be aliased
// without leading to undefined behaviour.
BOOST_PRAGMA_MESSAGE("CAUTION: Unaligned access tolerated on little-endian may "
                     "cause undefined behaviour")
#else
#error Unaligned access disabled for unknown platforms and architectures
#endif
#endif // defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)

    namespace boost {
  namespace gil {

  ///////////////////////////////////////////
  ////  channel_traits
  ////
  ////  \ingroup ChannelModel
  ////  \class channel_traits
  ////  \brief defines properties of channels, such as their range and
  ///associated types
  ////
  ////  The channel traits must be defined for every model of ChannelConcept
  ////  Default traits are provided. For built-in types the default traits use
  ////  built-in pointer and reference and the channel range is the physical
  ////  range of the type. For classes, the default traits forward the
  ///associated types /  and range to the class.
  ////
  ///////////////////////////////////////////

  namespace detail {

  template <typename T, bool IsClass> struct channel_traits_impl;

  // channel traits for custom class
  template <typename T> struct channel_traits_impl<T, true> {
    using value_type = typename T::value_type;
    using reference = typename T::reference;
    using pointer = typename T::pointer;
    using const_reference = typename T::const_reference;
    using const_pointer = typename T::const_pointer;
    static constexpr bool is_mutable = T::is_mutable;
    static value_type min_value() { return T::min_value(); }
    static value_type max_value() { return T::max_value(); }
  };

  // channel traits implementation for built-in integral or floating point
  // channel type
  template <typename T> struct channel_traits_impl<T, false> {
    using value_type = T;
    using reference = T &;
    using pointer = T *;
    using const_reference = T const &;
    using const_pointer = T const *;
    static constexpr bool is_mutable = true;
    static value_type min_value() { return (std::numeric_limits<T>::min)(); }
    static value_type max_value() { return (std::numeric_limits<T>::max)(); }
  };

  // channel traits implementation for constant built-in scalar or floating
  // point type
  template <typename T>
  struct channel_traits_impl<T const, false> : channel_traits_impl<T, false> {
    using reference = T const &;
    using pointer = T const *;
    static constexpr bool is_mutable = false;
  };

  } // namespace detail

  /**
  \ingroup ChannelModel
  \brief Traits for channels. Contains the following members:
  \code
  template <typename Channel>
  struct channel_traits {
      using value_type = ...;
      using reference = ...;
      using pointer = ...;
      using const_reference = ...;
      using const_pointer = ...;

      static const bool is_mutable;
      static value_type min_value();
      static value_type max_value();
  };
  \endcode
  */
  template <typename T>
  struct channel_traits
      : detail::channel_traits_impl<T, std::is_class<T>::value> {};

  // Channel traits for C++ reference type - remove the reference
  template <typename T> struct channel_traits<T &> : channel_traits<T> {};

  // Channel traits for constant C++ reference type
  template <typename T> struct channel_traits<T const &> : channel_traits<T> {
    using reference = typename channel_traits<T>::const_reference;
    using pointer = typename channel_traits<T>::const_pointer;
    static constexpr bool is_mutable = false;
  };

  ///////////////////////////////////////////
  ////  scoped_channel_value
  ///////////////////////////////////////////

  /// \defgroup ScopedChannelValue scoped_channel_value
  /// \ingroup ChannelModel
  /// \brief A channel adaptor that modifies the range of the source channel.
  /// Models: ChannelValueConcept
  ///
  /// Example:
  /// \code
  /// // Create a double channel with range [-0.5 .. 0.5]
  /// struct double_minus_half  { static double apply() { return -0.5; } };
  /// struct double_plus_half   { static double apply() { return  0.5; } };
  /// using bits64custom_t = scoped_channel_value<double, double_minus_half,
  /// double_plus_half>;
  ///
  /// // channel_convert its maximum should map to the maximum
  /// bits64custom_t x = channel_traits<bits64custom_t>::max_value();
  /// assert(x == 0.5);
  /// uint16_t y = channel_convert<uint16_t>(x);
  /// assert(y == 65535);
  /// \endcode

  /// \ingroup ScopedChannelValue
  /// \brief A channel adaptor that modifies the range of the source channel.
  /// Models: ChannelValueConcept \tparam BaseChannelValue base channel (models
  /// ChannelValueConcept) \tparam MinVal class with a static apply() function
  /// returning the minimum channel values \tparam MaxVal class with a static
  /// apply() function returning the maximum channel values
  template <typename BaseChannelValue, typename MinVal, typename MaxVal>
  struct scoped_channel_value {
    using value_type = scoped_channel_value<BaseChannelValue, MinVal, MaxVal>;
    using reference = value_type &;
    using pointer = value_type *;
    using const_reference = value_type const &;
    using const_pointer = value_type const *;
    static constexpr bool is_mutable =
        channel_traits<BaseChannelValue>::is_mutable;

    using base_channel_t = BaseChannelValue;

    static value_type min_value() { return MinVal::apply(); }
    static value_type max_value() { return MaxVal::apply(); }

    scoped_channel_value() = default;
    scoped_channel_value(scoped_channel_value const &other)
        : value_(other.value_) {}
    scoped_channel_value &
    operator=(scoped_channel_value const &other) = default;
    scoped_channel_value(BaseChannelValue value) : value_(value) {}
    scoped_channel_value &operator=(BaseChannelValue value) {
      value_ = value;
      return *this;
    }

    scoped_channel_value &operator++() {
      ++value_;
      return *this;
    }
    scoped_channel_value &operator--() {
      --value_;
      return *this;
    }

    scoped_channel_value operator++(int) {
      scoped_channel_value tmp = *this;
      this->operator++();
      return tmp;
    }
    scoped_channel_value operator--(int) {
      scoped_channel_value tmp = *this;
      this->operator--();
      return tmp;
    }

    template <typename Scalar2> scoped_channel_value &operator+=(Scalar2 v) {
      value_ += v;
      return *this;
    }
    template <typename Scalar2> scoped_channel_value &operator-=(Scalar2 v) {
      value_ -= v;
      return *this;
    }
    template <typename Scalar2> scoped_channel_value &operator*=(Scalar2 v) {
      value_ *= v;
      return *this;
    }
    template <typename Scalar2> scoped_channel_value &operator/=(Scalar2 v) {
      value_ /= v;
      return *this;
    }

    operator BaseChannelValue() const { return value_; }

  private:
    BaseChannelValue value_{};
  };

  template <typename T> struct float_point_zero {
    static constexpr T apply() { return 0.0f; }
  };

  template <typename T> struct float_point_one {
    static constexpr T apply() { return 1.0f; }
  };

  ///////////////////////////////////////////
  ////  Support for sub-byte channels. These are integral channels whose value
  ///is contained in a range of bits inside an integral type
  ///////////////////////////////////////////

  // It is necessary for packed channels to have their own value type. They
  // cannot simply use an integral large enough to store the data. Here is why:
  // - Any operation that requires returning the result by value will otherwise
  // return the built-in integral type, which will have incorrect range
  //   That means that after getting the value of the channel we cannot properly
  //   do channel_convert, channel_invert, etc.
  // - Two channels are declared compatible if they have the same value type.
  // That means that a packed channel is incorrectly declared compatible with an
  // integral type
  namespace detail {

  // returns the smallest fast unsigned integral type that has at least NumBits
  // bits
  template <int NumBits>
  struct min_fast_uint
      : std::conditional<
            NumBits <= 8, std::uint_least8_t,
            typename std::conditional<
                NumBits <= 16, std::uint_least16_t,
                typename std::conditional<NumBits <= 32, std::uint_least32_t,
                                          std::uintmax_t>::type>::type> {};

  template <int NumBits>
      struct num_value_fn
      : std::conditional < NumBits<32, std::uint32_t, std::uint64_t> {};

  template <int NumBits>
  struct max_value_fn
      : std::conditional<NumBits <= 32, std::uint32_t, std::uint64_t> {};

  } // namespace detail

  /// \defgroup PackedChannelValueModel packed_channel_value
  /// \ingroup ChannelModel
  /// \brief Represents the value of an unsigned integral channel operating over
  /// a bit range. Models: ChannelValueConcept Example: \code
  /// // A 4-bit unsigned integral channel.
  /// using bits4 = packed_channel_value<4>;
  ///
  /// assert(channel_traits<bits4>::min_value()==0);
  /// assert(channel_traits<bits4>::max_value()==15);
  /// assert(sizeof(bits4)==1);
  /// static_assert(gil::is_channel_integral<bits4>::value, "");
  /// \endcode

  /// \ingroup PackedChannelValueModel
  /// \brief The value of a subbyte channel. Models: ChannelValueConcept
  template <int NumBits> class packed_channel_value {
  public:
    using integer_t = typename detail::min_fast_uint<NumBits>::type;

    using value_type = packed_channel_value<NumBits>;
    using reference = value_type &;
    using const_reference = value_type const &;
    using pointer = value_type *;
    using const_pointer = value_type const *;
    static constexpr bool is_mutable = true;

    static value_type min_value() { return 0; }
    static value_type max_value() { return low_bits_mask_t<NumBits>::sig_bits; }

    packed_channel_value() = default;
    packed_channel_value(integer_t v) {
      value_ =
          static_cast<integer_t>(v & low_bits_mask_t<NumBits>::sig_bits_fast);
    }

    template <typename Scalar> packed_channel_value(Scalar v) {
      value_ = packed_channel_value(static_cast<integer_t>(v));
    }

    static unsigned int num_bits() { return NumBits; }

    operator integer_t() const { return value_; }

  private:
    integer_t value_{};
  };

  namespace detail {

  template <std::size_t K> struct static_copy_bytes {
    void operator()(unsigned char const *from, unsigned char *to) const {
      *to = *from;
      static_copy_bytes<K - 1>()(++from, ++to);
    }
  };

  template <> struct static_copy_bytes<0> {
    void operator()(unsigned char const *, unsigned char *) const {}
  };

  template <typename Derived, typename BitField, int NumBits, bool IsMutable>
  class packed_channel_reference_base {
  protected:
    using data_ptr_t =
        typename std::conditional<IsMutable, void *, void const *>::type;

  public:
    data_ptr_t _data_ptr; // void* pointer to the first byte of the bit range

    using value_type = packed_channel_value<NumBits>;
    using reference = const Derived;
    using pointer = value_type *;
    using const_pointer = const value_type *;
    static constexpr int num_bits = NumBits;
    static constexpr bool is_mutable = IsMutable;

    static value_type min_value() {
      return channel_traits<value_type>::min_value();
    }
    static value_type max_value() {
      return channel_traits<value_type>::max_value();
    }

    using bitfield_t = BitField;
    using integer_t = typename value_type::integer_t;

    packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {}
    packed_channel_reference_base(const packed_channel_reference_base &ref)
        : _data_ptr(ref._data_ptr) {}
    const Derived &operator=(integer_t v) const {
      set(v);
      return derived();
    }

    const Derived &operator++() const {
      set(get() + 1);
      return derived();
    }
    const Derived &operator--() const {
      set(get() - 1);
      return derived();
    }

    Derived operator++(int) const {
      Derived tmp = derived();
      this->operator++();
      return tmp;
    }
    Derived operator--(int) const {
      Derived tmp = derived();
      this->operator--();
      return tmp;
    }

    template <typename Scalar2> const Derived &operator+=(Scalar2 v) const {
      set(static_cast<integer_t>(get() + v));
      return derived();
    }
    template <typename Scalar2> const Derived &operator-=(Scalar2 v) const {
      set(static_cast<integer_t>(get() - v));
      return derived();
    }
    template <typename Scalar2> const Derived &operator*=(Scalar2 v) const {
      set(static_cast<integer_t>(get() * v));
      return derived();
    }
    template <typename Scalar2> const Derived &operator/=(Scalar2 v) const {
      set(static_cast<integer_t>(get() / v));
      return derived();
    }

    operator integer_t() const { return get(); }
    data_ptr_t operator&() const { return _data_ptr; }

  protected:
    using num_value_t = typename detail::num_value_fn<NumBits>::type;
    using max_value_t = typename detail::max_value_fn<NumBits>::type;

    static const num_value_t num_values = static_cast<num_value_t>(1)
                                          << NumBits;
    static const max_value_t max_val = static_cast<max_value_t>(num_values - 1);

#if defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
    const bitfield_t &get_data() const {
      return *static_cast<const bitfield_t *>(_data_ptr);
    }
    void set_data(const bitfield_t &val) const {
      *static_cast<bitfield_t *>(_data_ptr) = val;
    }
#else
  bitfield_t get_data() const {
    bitfield_t ret;
    static_copy_bytes<sizeof(bitfield_t)>()(
        gil_reinterpret_cast_c<const unsigned char *>(_data_ptr),
        gil_reinterpret_cast<unsigned char *>(&ret));
    return ret;
  }
  void set_data(const bitfield_t &val) const {
    static_copy_bytes<sizeof(bitfield_t)>()(
        gil_reinterpret_cast_c<const unsigned char *>(&val),
        gil_reinterpret_cast<unsigned char *>(_data_ptr));
  }
#endif

  private:
    void set(integer_t value) const { // can this be done faster??
      this->derived().set_unsafe(((value % num_values) + num_values) %
                                 num_values);
    }
    integer_t get() const { return derived().get(); }
    const Derived &derived() const {
      return static_cast<const Derived &>(*this);
    }
  };
  } // namespace detail

  /// \defgroup PackedChannelReferenceModel packed_channel_reference
  /// \ingroup ChannelModel
  /// \brief Represents a reference proxy to a channel operating over a bit
  /// range whose offset is fixed at compile time. Models ChannelConcept
  /// Example:
  /// \code
  /// // Reference to a 2-bit channel starting at bit 1 (i.e. the second bit)
  /// using bits2_1_ref_t = packed_channel_reference<uint16_t,1,2,true> const;
  ///
  /// uint16_t data=0;
  /// bits2_1_ref_t channel_ref(&data);
  /// channel_ref = channel_traits<bits2_1_ref_t>::max_value();   // == 3
  /// assert(data == 6);                                          // == 3<<1 ==
  /// 6 \endcode

  /// \tparam BitField A type that holds the bits of the pixel from which the
  /// channel is referenced. Typically an integral type, like std::uint16_t
  /// \tparam Defines the sequence of bits in the data value that contain the
  /// channel \tparam true if the reference is mutable
  template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
  class packed_channel_reference;

  /// \tparam A type that holds the bits of the pixel from which the channel is
  /// referenced. Typically an integral type, like std::uint16_t \tparam Defines
  /// the sequence of bits in the data value that contain the channel \tparam
  /// true if the reference is mutable
  template <typename BitField, int NumBits, bool IsMutable>
  class packed_dynamic_channel_reference;

  /// \ingroup PackedChannelReferenceModel
  /// \brief A constant subbyte channel reference whose bit offset is fixed at
  /// compile time. Models ChannelConcept
  template <typename BitField, int FirstBit, int NumBits>
  class packed_channel_reference<BitField, FirstBit, NumBits, false>
      : public detail::packed_channel_reference_base<
            packed_channel_reference<BitField, FirstBit, NumBits, false>,
            BitField, NumBits, false> {
    using parent_t = detail::packed_channel_reference_base<
        packed_channel_reference<BitField, FirstBit, NumBits, false>, BitField,
        NumBits, false>;

    friend class packed_channel_reference<BitField, FirstBit, NumBits, true>;

    static const BitField channel_mask =
        static_cast<BitField>(parent_t::max_val) << FirstBit;

    void operator=(packed_channel_reference const &);

  public:
    using const_reference =
        packed_channel_reference<BitField, FirstBit, NumBits, false> const;
    using mutable_reference =
        packed_channel_reference<BitField, FirstBit, NumBits, true> const;
    using integer_t = typename parent_t::integer_t;

    explicit packed_channel_reference(const void *data_ptr)
        : parent_t(data_ptr) {}
    packed_channel_reference(const packed_channel_reference &ref)
        : parent_t(ref._data_ptr) {}
    packed_channel_reference(const mutable_reference &ref)
        : parent_t(ref._data_ptr) {}

    unsigned first_bit() const { return FirstBit; }

    integer_t get() const {
      return integer_t((this->get_data() & channel_mask) >> FirstBit);
    }
  };

  /// \ingroup PackedChannelReferenceModel
  /// \brief A mutable subbyte channel reference whose bit offset is fixed at
  /// compile time. Models ChannelConcept
  template <typename BitField, int FirstBit, int NumBits>
  class packed_channel_reference<BitField, FirstBit, NumBits, true>
      : public detail::packed_channel_reference_base<
            packed_channel_reference<BitField, FirstBit, NumBits, true>,
            BitField, NumBits, true> {
    using parent_t = detail::packed_channel_reference_base<
        packed_channel_reference<BitField, FirstBit, NumBits, true>, BitField,
        NumBits, true>;
    friend class packed_channel_reference<BitField, FirstBit, NumBits, false>;

    static const BitField channel_mask =
        static_cast<BitField>(parent_t::max_val) << FirstBit;

  public:
    using const_reference =
        packed_channel_reference<BitField, FirstBit, NumBits, false> const;
    using mutable_reference =
        packed_channel_reference<BitField, FirstBit, NumBits, true> const;
    using integer_t = typename parent_t::integer_t;

    explicit packed_channel_reference(void *data_ptr) : parent_t(data_ptr) {}
    packed_channel_reference(const packed_channel_reference &ref)
        : parent_t(ref._data_ptr) {}

    packed_channel_reference const &operator=(integer_t value) const {
      BOOST_ASSERT(value <= parent_t::max_val);
      set_unsafe(value);
      return *this;
    }

    const packed_channel_reference &
    operator=(const mutable_reference &ref) const {
      set_from_reference(ref.get_data());
      return *this;
    }
    const packed_channel_reference &
    operator=(const const_reference &ref) const {
      set_from_reference(ref.get_data());
      return *this;
    }

    template <bool Mutable1>
    const packed_channel_reference &
    operator=(const packed_dynamic_channel_reference<BitField, NumBits,
                                                     Mutable1> &ref) const {
      set_unsafe(ref.get());
      return *this;
    }

    unsigned first_bit() const { return FirstBit; }

    integer_t get() const {
      return integer_t((this->get_data() & channel_mask) >> FirstBit);
    }
    void set_unsafe(integer_t value) const {
      this->set_data((this->get_data() & ~channel_mask) |
                     ((static_cast<BitField>(value) << FirstBit)));
    }

  private:
    void set_from_reference(const BitField &other_bits) const {
      this->set_data((this->get_data() & ~channel_mask) |
                     (other_bits & channel_mask));
    }
  };

  } // namespace gil
} // namespace boost

namespace std {
// We are forced to define swap inside std namespace because on some platforms
// (Visual Studio 8) STL calls swap qualified. swap with 'left bias':
// - swap between proxy and anything
// - swap between value type and proxy
// - swap between proxy and proxy

/// \ingroup PackedChannelReferenceModel
/// \brief swap for packed_channel_reference
template <typename BF, int FB, int NB, bool M, typename R>
inline void swap(boost::gil::packed_channel_reference<BF, FB, NB, M> const x,
                 R &y) {
  boost::gil::swap_proxy<
      typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type>(
      x, y);
}

/// \ingroup PackedChannelReferenceModel
/// \brief swap for packed_channel_reference
template <typename BF, int FB, int NB, bool M>
inline void swap(
    typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type &x,
    boost::gil::packed_channel_reference<BF, FB, NB, M> const y) {
  boost::gil::swap_proxy<
      typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type>(
      x, y);
}

/// \ingroup PackedChannelReferenceModel
/// \brief swap for packed_channel_reference
template <typename BF, int FB, int NB, bool M>
inline void swap(boost::gil::packed_channel_reference<BF, FB, NB, M> const x,
                 boost::gil::packed_channel_reference<BF, FB, NB, M> const y) {
  boost::gil::swap_proxy<
      typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type>(
      x, y);
}

} // namespace std

namespace boost {
namespace gil {

/// \defgroup PackedChannelDynamicReferenceModel
/// packed_dynamic_channel_reference \ingroup ChannelModel \brief Represents a
/// reference proxy to a channel operating over a bit range whose offset is
/// specified at run time. Models ChannelConcept
///
/// Example:
/// \code
/// // Reference to a 2-bit channel whose offset is specified at construction
/// time using bits2_dynamic_ref_t =
/// packed_dynamic_channel_reference<uint8_t,2,true> const;
///
/// uint16_t data=0;
/// bits2_dynamic_ref_t channel_ref(&data,1);
/// channel_ref = channel_traits<bits2_dynamic_ref_t>::max_value();     // == 3
/// assert(data == 6);                                                  // ==
/// (3<<1) == 6 \endcode

/// \brief Models a constant subbyte channel reference whose bit offset is a
/// runtime parameter. Models ChannelConcept
///        Same as packed_channel_reference, except that the offset is a runtime
///        parameter
/// \ingroup PackedChannelDynamicReferenceModel
template <typename BitField, int NumBits>
class packed_dynamic_channel_reference<BitField, NumBits, false>
    : public detail::packed_channel_reference_base<
          packed_dynamic_channel_reference<BitField, NumBits, false>, BitField,
          NumBits, false> {
  using parent_t = detail::packed_channel_reference_base<
      packed_dynamic_channel_reference<BitField, NumBits, false>, BitField,
      NumBits, false>;
  friend class packed_dynamic_channel_reference<BitField, NumBits, true>;

  unsigned _first_bit; // 0..7

  void operator=(const packed_dynamic_channel_reference &);

public:
  using const_reference =
      packed_dynamic_channel_reference<BitField, NumBits, false> const;
  using mutable_reference =
      packed_dynamic_channel_reference<BitField, NumBits, true> const;
  using integer_t = typename parent_t::integer_t;

  packed_dynamic_channel_reference(const void *data_ptr, unsigned first_bit)
      : parent_t(data_ptr), _first_bit(first_bit) {}
  packed_dynamic_channel_reference(const const_reference &ref)
      : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
  packed_dynamic_channel_reference(const mutable_reference &ref)
      : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}

  unsigned first_bit() const { return _first_bit; }

  integer_t get() const {
    const BitField channel_mask = static_cast<integer_t>(parent_t::max_val)
                                  << _first_bit;
    return static_cast<integer_t>((this->get_data() & channel_mask) >>
                                  _first_bit);
  }
};

/// \brief Models a mutable subbyte channel reference whose bit offset is a
/// runtime parameter. Models ChannelConcept
///        Same as packed_channel_reference, except that the offset is a runtime
///        parameter
/// \ingroup PackedChannelDynamicReferenceModel
template <typename BitField, int NumBits>
class packed_dynamic_channel_reference<BitField, NumBits, true>
    : public detail::packed_channel_reference_base<
          packed_dynamic_channel_reference<BitField, NumBits, true>, BitField,
          NumBits, true> {
  using parent_t = detail::packed_channel_reference_base<
      packed_dynamic_channel_reference<BitField, NumBits, true>, BitField,
      NumBits, true>;
  friend class packed_dynamic_channel_reference<BitField, NumBits, false>;

  unsigned _first_bit;

public:
  using const_reference =
      packed_dynamic_channel_reference<BitField, NumBits, false> const;
  using mutable_reference =
      packed_dynamic_channel_reference<BitField, NumBits, true> const;
  using integer_t = typename parent_t::integer_t;

  packed_dynamic_channel_reference(void *data_ptr, unsigned first_bit)
      : parent_t(data_ptr), _first_bit(first_bit) {}
  packed_dynamic_channel_reference(const packed_dynamic_channel_reference &ref)
      : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}

  packed_dynamic_channel_reference const &operator=(integer_t value) const {
    BOOST_ASSERT(value <= parent_t::max_val);
    set_unsafe(value);
    return *this;
  }

  const packed_dynamic_channel_reference &
  operator=(const mutable_reference &ref) const {
    set_unsafe(ref.get());
    return *this;
  }
  const packed_dynamic_channel_reference &
  operator=(const const_reference &ref) const {
    set_unsafe(ref.get());
    return *this;
  }

  template <typename BitField1, int FirstBit1, bool Mutable1>
  const packed_dynamic_channel_reference &
  operator=(const packed_channel_reference<BitField1, FirstBit1, NumBits,
                                           Mutable1> &ref) const {
    set_unsafe(ref.get());
    return *this;
  }

  unsigned first_bit() const { return _first_bit; }

  integer_t get() const {
    const BitField channel_mask = static_cast<integer_t>(parent_t::max_val)
                                  << _first_bit;
    return static_cast<integer_t>((this->get_data() & channel_mask) >>
                                  _first_bit);
  }

  void set_unsafe(integer_t value) const {
    const BitField channel_mask = static_cast<integer_t>(parent_t::max_val)
                                  << _first_bit;
    this->set_data((this->get_data() & ~channel_mask) | value << _first_bit);
  }
};
} // namespace gil
} // namespace boost

namespace std {
// We are forced to define swap inside std namespace because on some platforms
// (Visual Studio 8) STL calls swap qualified. swap with 'left bias':
// - swap between proxy and anything
// - swap between value type and proxy
// - swap between proxy and proxy

/// \ingroup PackedChannelDynamicReferenceModel
/// \brief swap for packed_dynamic_channel_reference
template <typename BF, int NB, bool M, typename R>
inline void
swap(const boost::gil::packed_dynamic_channel_reference<BF, NB, M> x, R &y) {
  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<
      BF, NB, M>::value_type>(x, y);
}

/// \ingroup PackedChannelDynamicReferenceModel
/// \brief swap for packed_dynamic_channel_reference
template <typename BF, int NB, bool M>
inline void
swap(typename boost::gil::packed_dynamic_channel_reference<BF, NB,
                                                           M>::value_type &x,
     const boost::gil::packed_dynamic_channel_reference<BF, NB, M> y) {
  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<
      BF, NB, M>::value_type>(x, y);
}

/// \ingroup PackedChannelDynamicReferenceModel
/// \brief swap for packed_dynamic_channel_reference
template <typename BF, int NB, bool M>
inline void
swap(const boost::gil::packed_dynamic_channel_reference<BF, NB, M> x,
     const boost::gil::packed_dynamic_channel_reference<BF, NB, M> y) {
  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<
      BF, NB, M>::value_type>(x, y);
}
} // namespace std

// \brief Determines the fundamental type which may be used, e.g., to cast from
// larger to smaller channel types.
namespace boost {
namespace gil {
template <typename T> struct base_channel_type_impl { using type = T; };

template <int N> struct base_channel_type_impl<packed_channel_value<N>> {
  using type = typename packed_channel_value<N>::integer_t;
};

template <typename B, int F, int N, bool M>
struct base_channel_type_impl<packed_channel_reference<B, F, N, M>> {
  using type = typename packed_channel_reference<B, F, N, M>::integer_t;
};

template <typename B, int N, bool M>
struct base_channel_type_impl<packed_dynamic_channel_reference<B, N, M>> {
  using type = typename packed_dynamic_channel_reference<B, N, M>::integer_t;
};

template <typename ChannelValue, typename MinV, typename MaxV>
struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV>> {
  using type = ChannelValue;
};

template <typename T>
struct base_channel_type
    : base_channel_type_impl<typename std::remove_cv<T>::type> {};

} // namespace gil
} // namespace boost

#endif

max_stars_repo_name: sdebionne/gil-reformated

max_issues_repo_name: sdebionne/gil-reformated

max_forks_repo_name: sdebionne/gil-reformated


text:
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/def.hpp>
#include <boost/python/args.hpp>
#include <boost/python/list.hpp>
#include <boost/python/make_constructor.hpp>
#include <boost/python/object.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>

#include <scitbx/array_family/shared.h>
#include <ucif/parser.h>
#include <iotbx/error.h>

namespace iotbx { namespace cif {

  struct shared_array_wrapper : ucif::array_wrapper_base
  {
    scitbx::af::shared<std::string> array;

    shared_array_wrapper()
    :
    array()
    {}

    virtual void push_back(std::string const& value)
    {
      array.push_back(value);
    }

    virtual std::string operator[](unsigned const& i) const
    {
      return array[i];
    }

    virtual unsigned size() const
    {
      return array.size();
    }

  };

  struct py_builder : ucif::builder_base
  {
    boost::python::object builder;

    py_builder(boost::python::object builder_)
      :
    builder(builder_) {}

    virtual void start_save_frame(std::string const& save_frame_heading)
    {
      builder.attr("start_save_frame")(save_frame_heading);
    }

    virtual void end_save_frame()
    {
      builder.attr("end_save_frame")();
    }

    virtual void add_data_item(std::string const& tag, std::string const& value)
    {
      builder.attr("add_data_item")(tag, value);
    }

    virtual void add_loop(ucif::array_wrapper_base const& loop_headers,
                          std::vector<ucif::array_wrapper_base*> const& values)
    {
      boost::python::list result;
      for (std::size_t i=0; i<loop_headers.size(); i++) {
        result.append(
          dynamic_cast<shared_array_wrapper* const>(values[i])->array);
      }
      builder.attr("add_loop")(
        dynamic_cast<shared_array_wrapper const&>(loop_headers).array,
        result
      );
    }

    virtual void add_data_block(std::string const& data_block_heading)
    {
      builder.attr("add_data_block")(data_block_heading);
    }

    virtual ucif::array_wrapper_base* new_array()
    {
      return new shared_array_wrapper();
    }

  };

  struct parser_wrapper : ucif::parser
  {
    parser_wrapper(ucif::builder_base* builder,
                   std::string input_string,
                   std::string filename="memory",
                   bool strict=true)
    : ucif::parser(builder, input_string, filename, strict) {}

    scitbx::af::shared<std::string>& parser_errors() {
      return dynamic_cast<shared_array_wrapper*>(psr->errors)->array;
    }

    scitbx::af::shared<std::string>& lexer_errors() {
      return dynamic_cast<shared_array_wrapper*>(lxr->errors)->array;
    }

  };

  static iotbx::cif::parser_wrapper* run_cif_parser(
    boost::python::object& builder_,
    std::string input_string,
    std::string filename, bool strict)
  {
    iotbx::cif::py_builder builder(builder_);
    return new iotbx::cif::parser_wrapper(
      &builder, input_string, filename, strict);
  }

namespace boost_python {

  struct cif_wrapper
  {
    typedef iotbx::cif::parser_wrapper wt;

    static void wrap(char const *name) {
      using namespace boost::python;
      typedef return_value_policy<return_by_value> rbv;
      class_<wt, boost::noncopyable>(name, no_init)
        .def("__init__", make_constructor(run_cif_parser,
          default_call_policies(),
          (arg("builder"), arg("input_string"),
           arg("filename"), arg("strict")=true)))
        .def("parser_errors", &wt::parser_errors, rbv())
        .def("lexer_errors", &wt::lexer_errors, rbv())
        ;
    }
  };

  void init_module() {
    using namespace boost::python;

    cif_wrapper::wrap("fast_reader");
  }

}}} //iotbx::cif::boost_python

BOOST_PYTHON_MODULE(iotbx_cif_ext)
{
        iotbx::cif::boost_python::init_module();
}

ext: cpp


text:
/// @file
/// @brief

#include <stdexcept>
#include <iostream>

#include <boost/core/ignore_unused.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp>

struct TmpPath
{
     explicit TmpPath( const boost::filesystem::path& p = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path( "pfr-service-tmp-%%%%%%%%%%%%%%%%" ) ) : path{ p }
     {
          std::cout << "Created temp path " << path << ".\n";
     }
     TmpPath( const TmpPath& ) = delete;
     TmpPath( TmpPath&& ) = default;
     ~TmpPath()
     {
          std::cout << "Let's remove file " << path << "!\n";
          boost::system::error_code err;
          boost::filesystem::remove( path, err );
     }
     const boost::filesystem::path path;
     operator boost::filesystem::path() const
     {
          return path;
     }
};

std::ostream& operator<<( std::ostream& os, const TmpPath& tp )
{
     return os << tp.path;
}

TmpPath getTmpPath()
{
     TmpPath tmp;
     boost::filesystem::ofstream{ tmp } << "Important data...";
     return tmp;
}

void doSmth( TmpPath&& tp )
{
     std::cout << "Do something with " << tp << '\n';
}

int main( int argc, char** argv )
{
     boost::ignore_unused( argc, argv );
     try
     {
          std::cout << "Start!\n";
          auto tmp = getTmpPath();
          doSmth( std::move( tmp ) );
          std::cout << "Done.\n";
     }
     catch( const std::exception& e )
     {
          std::cerr << "exception: " << boost::diagnostic_information( e ) << '\n';
          return 1;
     }
     return 0;
}


text:
#include <thread>

#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>

#include "aktualizr-lite/api.h"

#define LOG_INFO    BOOST_LOG_TRIVIAL(info)
#define LOG_WARNING BOOST_LOG_TRIVIAL(warning)
#define LOG_ERROR   BOOST_LOG_TRIVIAL(error)

static void reboot(const std::string &reboot_cmd) {
  LOG_INFO << "Device is going to reboot with " << reboot_cmd;
  if (setuid(0) != 0) {
    LOG_ERROR << "Failed to set/verify a root user so cannot reboot system programmatically";
  } else {
    sync();
    if (std::system(reboot_cmd.c_str()) == 0) {
      exit(0);
    }
    LOG_ERROR << "Failed to execute the reboot command";
  }
  exit(1);
}

static std::string get_reboot_cmd(const AkliteClient &client) {
  auto reboot_cmd = client.GetConfig().get("bootloader.reboot_command", "");
  // boost property_tree will include surrounding quotes which we need to
  // strip:
  if (reboot_cmd.front() == '"') {
    reboot_cmd.erase(0, 1);
  }
  if (reboot_cmd.back() == '"') {
    reboot_cmd.erase(reboot_cmd.size() - 1);
  }

  return reboot_cmd;
}

int main(int argc, char **argv) {
  boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::info);

  AkliteClient client(AkliteClient::CONFIG_DIRS);
  auto interval = client.GetConfig().get("uptane.polling_sec", 600);
  auto reboot_cmd = get_reboot_cmd(client);

  if (access(reboot_cmd.c_str(), X_OK) != 0) {
    LOG_ERROR << "Reboot command: " << reboot_cmd << " is not executable";
    return EXIT_FAILURE;
  }

  LOG_INFO << "Starting aklite client with " << interval << " second interval";

  auto current = client.GetCurrent();
  while (true) {
    LOG_INFO << "Active Target: " << current.Name() << ", sha256: " << current.Sha256Hash();
    LOG_INFO << "Checking for a new Target...";

    try {
      auto res = client.CheckIn();
      if (res.status != CheckInResult::Status::Ok && res.status != CheckInResult::Status::OkCached) {
        LOG_WARNING << "Unable to update latest metadata, going to sleep for " << interval
                    << " seconds before starting a new update cycle";
        std::this_thread::sleep_for(std::chrono::seconds(interval));
        continue;  // There's no point trying to look for an update
      }

      auto latest = res.GetLatest();
      LOG_INFO << "Found Latest Target: " << latest.Name();
      if (latest.Name() != current.Name() && !client.IsRollback(latest)) {
        std::string reason = "Updating from " + current.Name() + " to " + latest.Name();
        auto installer = client.Installer(latest, reason);
        auto dres = installer->Download();
        if (dres.status != DownloadResult::Status::Ok) {
          LOG_ERROR << "Unable to download target: " << dres;
          continue;
        }
        auto ires = installer->Install();
        if (ires.status == InstallResult::Status::Ok) {
          current = latest;
          continue;
        } else if (ires.status == InstallResult::Status::NeedsCompletion) {
          reboot(reboot_cmd);
          break;
        } else {
          LOG_ERROR << "Unable to install target: " << ires;
        }
      } else {
        auto installer = client.CheckAppsInSync();
        if (installer != nullptr) {
          LOG_INFO << "Syncing Active Target Apps";
          auto dres = installer->Download();
          if (dres.status != DownloadResult::Status::Ok) {
            LOG_ERROR << "Unable to download target: " << dres;
          } else {
            auto ires = installer->Install();
            if (ires.status != InstallResult::Status::Ok) {
              LOG_ERROR << "Unable to install target: " << ires;
            }
          }
        }
      }
    } catch (const std::exception &exc) {
      LOG_ERROR << "Failed to find or update Target: " << exc.what();
      continue;
    }

    std::this_thread::sleep_for(std::chrono::seconds(interval));
  }
}

ext: cc

max_stars_repo_name: doanac/meta-subscriber-overrides

max_issues_repo_name: doanac/meta-subscriber-overrides

max_forks_repo_name: doanac/meta-subscriber-overrides


text:
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <rte_launch.h>
#include <rte_malloc.h>
#include <vector>

#include "logging.hpp"
#include "clock.hpp"
#include "libcyclone.hpp"
#include "dpdk_client.hpp"
#include "vector/adjvector-client.h"

#define TWITTER_DATA_FILE "/home/pfernando/cyclone/cyclone.git/benchmarks/data/twitter/twitter_rv_15066953.net"

/* right now we statically allocate node list */
#define MAX_GRAPH_NODES 10000

/* pmem structure names */
const uint16_t adjvector_st = 0;

int driver(void *arg);

typedef struct driver_args_st
{
	int leader;
	int me;
	int mc;
	int replicas;
	int clients;
	int partitions;
	int buf_cap;
	pmemdsclient::DPDKPMClient *dpdkClient;
	pmemdsclient::AdjVectorEngine *adjVector;
	void **handles;
	void operator() ()
	{
		(void)driver((void *)this);
	}
} driver_args_t;

int driver(void *arg)
{
	unsigned long request_id = 0UL; // wrap around at MAX
	driver_args_t *dargs = (driver_args_t *)arg;
	int me = dargs->me;
	int mc = dargs->mc;
	int replicas = dargs->replicas;
	int clients = dargs->clients;
	int partitions = dargs->partitions;
	void **handles = dargs->handles;
	pmemdsclient::DPDKPMClient *pmlib = dargs->dpdkClient;
	pmemdsclient::AdjVectorEngine *adjv = dargs->adjVector;
	srand(time(NULL));
	int ret;
	int rpc_flags;
	int my_core;

	double coin;
	double frac_read = 0.5;
	//twitter bench specific
	unsigned long fromnode_id, tonode_id,node_id;
	FILE *fp;
	fp = fopen(TWITTER_DATA_FILE, "r");
	if(fp == NULL){
		BOOST_LOG_TRIVIAL(info) << "could not open twitter data file";
		exit(-1);
	}

	unsigned  long key;
	char value_buffer[64];
	srand(rtc_clock::current_time());

	pmlib->open("twitterApp");
	uint8_t creation_flag = 0;
	adjv->create(creation_flag);

	for(int i=0 ;i<100000 ;i++ ){ // pre-loading some values
		if(fscanf(fp,"%lu %lu", &tonode_id, &fromnode_id) != 2){
			BOOST_LOG_TRIVIAL(info) << "error reading file values, exiting";
			exit(-1);
		}
		//BOOST_LOG_TRIVIAL(info) << "preload, add_edge from -> to : " << fromnode_id  << " -> "<< tonode_id;
		adjv->add_edge(fromnode_id,tonode_id);
	}
	for( ; ; ){
		coin = ((double)rand())/RAND_MAX;
		if(coin > frac_read){ // update
			if(fscanf(fp,"%lu %lu", &tonode_id, &fromnode_id) != 2){
				BOOST_LOG_TRIVIAL(info) << "error reading file values, exiting";
				exit(-1);
			}
			//BOOST_LOG_TRIVIAL(info) << "add_edge from -> to : " << fromnode_id << " -> " << tonode_id;
			adjv->add_edge(fromnode_id,tonode_id, nullptr);
		}else {
			unsigned long node_id = rand() % MAX_GRAPH_NODES;
			//BOOST_LOG_TRIVIAL(info) << "vertex_outdegree of :" << node_id;
			adjv->vertex_outdegree(node_id, nullptr);
		}
	}
	adjv->close(nullptr);
	pmlib->close(nullptr);
	fclose(fp);
	return 0;
}

int main(int argc, const char *argv[])
{
	if (argc != 11)
	{
		printf("Usage: %s client_id_start client_id_stop mc replicas clients partitions cluster_config quorum_config_prefix server_ports inflight_cap\n", argv[0]);
		exit(-1);
	}

	int client_id_start = atoi(argv[1]);
	int client_id_stop  = atoi(argv[2]);
	driver_args_t *dargs;
	void **prev_handles;
	cyclone_network_init(argv[7], 1, atoi(argv[3]), 2 + client_id_stop - client_id_start);
	driver_args_t ** dargs_array =
		(driver_args_t **)malloc((client_id_stop - client_id_start) * sizeof(driver_args_t *));
	//BOOST_LOG_TRIVIAL(info) << "no. clients: " << (client_id_stop - client_id_start);
	for (int me = client_id_start; me < client_id_stop; me++)
	{
		dargs = (driver_args_t *) malloc(sizeof(driver_args_t));
		dargs_array[me - client_id_start] = dargs;
		if (me == client_id_start)
		{
			dargs->leader = 1;
		}
		else
		{
			dargs->leader = 0;
		}
		dargs->me = me;
		dargs->mc = atoi(argv[3]);
		dargs->replicas = atoi(argv[4]);
		dargs->clients  = atoi(argv[5]);
		dargs->partitions = atoi(argv[6]);
		dargs->buf_cap = atoi(argv[10]);
		dargs->handles = new void *[dargs->partitions];
		BOOST_LOG_TRIVIAL(info) << "no. of partitions: " << dargs->partitions;
		char fname_server[50]/* IMPORTANT - set to large enough value */;
		char fname_client[50];
		for (int i = 0; i < dargs->partitions; i++){
			sprintf(fname_server, "%s", argv[7]);
			sprintf(fname_client, "%s%d.ini", argv[8], i); // only one raft instance running
			dargs->handles[i] = cyclone_client_init(dargs->me,
					dargs->mc,
					1 + me - client_id_start,
					fname_server,
					atoi(argv[9]),
					fname_client,
					CLIENT_ASYNC,
					dargs->buf_cap);
			BOOST_LOG_TRIVIAL(info) << "init dpdkclient and adjacency-vector";
			dargs->dpdkClient = new pmemdsclient::DPDKPMClient(dargs->handles[i]);
			dargs->adjVector = new pmemdsclient::AdjVectorEngine(dargs->dpdkClient,adjvector_st,1000,1UL);
		}
	}
	for (int me = client_id_start; me < client_id_stop; me++){
		cyclone_launch_clients(dargs_array[me-client_id_start]->handles[0],driver, dargs_array[me-client_id_start], 1+  me-client_id_start);
	}
	rte_eal_mp_wait_lcore();
}