/*!
@file builtin_array.h
@since 2004/1/6
@note


*/



#ifndef __S34_BUILTIN_ARRAY_H_
#define __S34_BUILTIN_ARRAY_H_


namespace stx {

  template<class T>
  class builtin_array {

    T*     first_;
    T*     last_;
    size_t size_;

    // no-definition to prevent copy
    builtin_array();
    builtin_array(const builtin_array&);
    builtin_array& operator=(const builtin_array&);

  public:
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;
    typedef T&        reference;
    typedef const T&  const_reference;
    typedef T         value_type;
    typedef T*        pointer;
    typedef const T*  const_pointer;
    typedef T*        iterator;
    typedef const T*  const_iterator;
    typedef std::reverse_iterator<iterator,T>       reverse_iterator;
    typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;

    builtin_array(T* first, T* last) 
      : first_(first), last_(last), size_(last-first) {}
    builtin_array(T* first, size_t size) 
      : first_(first), last_(first+size), size_(size) {}

    iterator begin()          
      { return first_; }
    const_iterator begin() const    
      { return first_; }

    iterator end()            
      { return last_; }
    const_iterator end() const      
      { return last_; }

    reverse_iterator rbegin()         
      { return reverse_iterator(last_); }
    const_reverse_iterator rbegin() const   
      { return const_reverse_iterator(last_); }

    reverse_iterator rend()           
      { return reverse_iterator(first_); }
    const_reverse_iterator rend() const     
      { return const_reverse_iterator(first_); }

    size_type size() const     
      { return size_; }
    size_type max_size() const 
      { return size_; }
    size_type capacity() const 
      { return size_; }
    bool empty() const    
      { return size_ == 0; }

    reference operator[](size_type n)       
      { return *(first_+n); }
    const_reference operator[](size_type n) const 
      { return *(first_+n); }

    reference at(size_type n) 
      { if ( size_ <= n ) _Xran(); return *(first_+n); }
    const_reference at(size_type n) const 
      { if ( size_ <= n ) _Xran(); return *(first_+n); }

    reference front()
      { return *first_; }
    const_reference front() const
      { return *first_; }

    reference back()
      { return *(last_-1); }
    const_reference back() const
      { return *(last_-1); }

    pointer body()       
      { return first_; }
    const_pointer body() const 
      { return first_; }

    std::pair<pointer,size_type> data()
      { return std::pair<pointer,size_type>(first_,size_); }

    std::pair<const_pointer,size_type> data() const
      { return std::pair<const_pointer,size_type>(first_,size_); }

    void swap(builtin_array& x) {
      std::swap(first_, x.first_);
      std::swap(last_,  x.last_);
      std::swap(size_,  x.size_);
    }

    friend void swap(builtin_array& x, builtin_array& y) 
      { x.swap(y); }

    // internal use internary
    bool _Eq(const builtin_array& x) const 
      { return size() == x.size() && std::equal(begin(), end(), x.begin()); }

    bool _Lt(const builtin_array& _X) const 
      { return std::lexicographical_compare(begin(), end(), x.begin(), x.end()); }

  private:

    void _Xran () const 
      { throw std::out_of_range("invalid builtin_array<T> subscript"); }

  };

  template<class T> inline
  bool operator==(const builtin_array<T>& x, const builtin_array<T>& y) 
    { return x._Eq(y); }

  template<class T> inline
  bool operator!=(const builtin_array<T>& x, const builtin_array<T>& y) 
    { return !(_X == _Y); }

  template<class T> inline 
  bool operator<(const builtin_array<T>& x,  const builtin_array<T>& y) 
    { return x._Lt(y); }

  template<class T> inline 
  bool operator>(const builtin_array<T>& x,  const builtin_array<T>& y) 
    { return y < x; }

  template<class T> inline 
  bool operator<=(const builtin_array<T>& x, const builtin_array<T>& y) 
    { return !(y < x); }

  template<class T> inline 
  bool operator>=(const builtin_array<T>& x, const builtin_array<T>& y) 
    { return !(x < y); }


}//end of namespace


#endif //end of include once
