// #include <map>
#include <netinet/in.h>
#include "be_conv"

// using namespace std;

template<class T> // big endian value
class be_val
{
  public:
    typedef T value_type;
    typedef be_val<value_type> my_type;

#ifdef DEBUG
    /* Debugging */
    inline void print ()
    {
      unsigned long *lp = (unsigned long *)((void *) &data);
      printf ("%08lx", *lp);
    }
#endif

    be_val () {}

    // explicit: this constructor is not used
    //           for automatic type promotion
    explicit be_val (value_type d) : data (ne2be (d)) {}

    be_val (const my_type& other)
    {
      data = other.data;
    }

    operator value_type () const
    {
      return static_cast<value_type> (be2ne (data));
    }
    const my_type& operator= (const value_type d)
    {
      *this = my_type (d);
      return *this;
    }
    const my_type& operator++ () // pre increment operator
    {
      value_type tmp = static_cast<value_type> (*this);
      return *this = my_type (++tmp);
    }
    const my_type operator++ (int) // post increment operator
    {
      my_type tmp = *this;
      (*this)++;
      return tmp;
    }
    const my_type& operator-- () // pre increment operator
    {
      value_type tmp = static_cast<value_type> (*this);
      return *this = my_type (--tmp);
    }
    const my_type operator-- (int) // post increment operator
    {
      my_type tmp = *this;
      (*this)--;
      return tmp;
    }
    const my_type& operator+= (const my_type& other)
    {
      *this = *this + other;
    }
    const my_type& operator-= (const my_type& other)
    {
      *this = *this - other;
    }
    const my_type& operator*= (const my_type& other)
    {
      *this = *this * other;
    }
    const my_type& operator/= (const my_type& other)
    {
      *this = *this / other;
    }
    const my_type& operator&= (const my_type& other)
    {
      *this = *this & other;
    }
    const my_type& operator|= (const my_type& other)
    {
      *this = *this | other;
    }
    const my_type& operator%= (const my_type& other)
    {
      *this = *this % other;
    }
    const my_type& operator^= (const my_type& other)
    {
      *this = *this ^ other;
    }
    const my_type& operator<<= (const my_type& other)
    {
      *this = *this << other;
    }
    const my_type& operator>>= (const my_type& other)
    {
      *this = *this >> other;
    }

  protected:
    value_type data;
};

template<class C>
inline const be_val<C> operator+ (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) + static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator- (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) - static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator* (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) * static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator/ (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) / static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator% (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) % static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator^ (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) ^ static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator& (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) & static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator| (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) | static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator<< (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) << static_cast<C> (b));
}

template<class C>
inline const be_val<C> operator>> (const be_val<C>& a, const be_val<C>& b)
{
  return be_val<C>(static_cast<C> (a) >> static_cast<C> (b));
}

template<class C>
inline bool operator< (const be_val<C>& a, const be_val<C>& b)
{
  return static_cast<C> (a) < static_cast<C> (b);
}

template<class C>
inline bool operator> (const be_val<C>& a, const be_val<C>& b)
{
  return static_cast<C> (a) > static_cast<C> (b);
}

template<class C>
inline bool operator<= (const be_val<C>& a, const be_val<C>& b)
{
  return static_cast<C> (a) <= static_cast<C> (b);
}

template<class C>
inline bool operator>= (const be_val<C>& a, const be_val<C>& b)
{
  return static_cast<C> (a) >= static_cast<C> (b);
}

template<class C>
inline bool operator== (const be_val<C>& a, const be_val<C>& b)
{
  return static_cast<C> (a) == static_cast<C> (b);
}

template<class C>
inline bool operator!= (const be_val<C>& a, const be_val<C>& b)
{
  return static_cast<C> (a) != static_cast<C> (b);
}
