// This may look like C code, but it is really -*- C++ -*-
/* 
Copyright (C) 1988 Free Software Foundation
    written by Doug Lea (dl@rocky.oswego.edu)

This file is part of the GNU C++ Library.  This library is free
software; you can redistribute it and/or modify it under the terms of
the GNU Library General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.  This library is distributed in the hope
that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/


#ifndef _Vec_h
#ifdef __GNUG__
#pragma interface
#endif
#define _Vec_h 1

#include <builtin.h>
#include "<T>.defs.h"

#ifndef _<T>_typedefs
#define _<T>_typedefs 1
typedef void (*<T>Procedure)(<T&>);
typedef <T>  (*<T>Mapper)(<T&>);
typedef <T>  (*<T>Combiner)(<T&>, <T&>);
typedef int  (*<T>Predicate)(<T&>);
//typedef int  (*<T>Comparator)(<T&>, <T&>);
#endif

typedef int (*BaseComparator)(void*, void*);

class BaseVec
{
protected:
  int                   len;
  void                   *s; // Actually: <T>* s;
  virtual void init_item(void *dst, void *src) = 0;
  virtual void assign_item(void *dst, void *src) = 0;
  int sizeof_item() = 0;
  void assign(const BaseVec& v);
  BaseVec() { len = 0; s = 0; }
  void                  sort(size_t el_size, BaseComparator f);
public:
  int                   capacity() { return len; }
  void                  reverse();
  void                  error(const char* msg);
  void                  range_error();
};

template <class T>
class Vec : BaseVec
{
   virtual void init_item(void *dst, const void *src)
     { (T*)dst->T::T(*(T*)src);} /* FIXME: Should this work for non-class T? */
   virtual void assign_item(void *dst, const void *src)
     { *(T*)dst = *(T*)src; }
   virtual void destroy_item(void *item)
     { T::~T((T*)item); }
   virtual size_t sizeof_item() { return sizeof(T); }
protected:      
                        <T>Vec(int l, <T>* d);
public:
#ifdef TODO
   Vec () : BaseVec() { }
                        <T>Vec (int l);
                        <T>Vec (int l, <T&> fill_value);
                        <T>Vec (<T>Vec&);
                        ~<T>Vec ();

  <T>Vec &              operator = (const <T>Vec & a)
    { assign (a);  return *this; }
  <T>Vec                at(int from = 0, int n = -1);

  void                  resize(int newlen);                        
#endif
  T&                    operator [] (int n)
    { if ((unsigned)n >= (unsigned)len) range_error();
      return s[n]; }
#ifdef TODO
  T&                    elem(int n) { return ((T*)s)[n]; }

  friend <T>Vec         concat(<T>Vec & a, <T>Vec & b);
  friend <T>Vec         map(<T>Mapper f, <T>Vec & a);
  friend <T>Vec         merge(<T>Vec & a, <T>Vec & b, <T>Comparator f);
  friend <T>Vec         combine(<T>Combiner f, <T>Vec & a, <T>Vec & b);
  friend <T>Vec         reverse(<T>Vec & a);
#endif
  void                  sort(int (*f)(T&, T&)) { sort((BaseComparator)f); }
#ifdef TODO
  void                  fill(<T&> val, int from = 0, int n = -1);

  void                  apply(<T>Procedure f);
  <T>                   reduce(<T>Combiner f, <T&> base);
  int                   index(<T&> targ);

  friend int            operator == (<T>Vec& a, <T>Vec& b);
#endif
  friend int            operator != (<T>Vec& a, <T>Vec& b);
};

extern void default_Vec_error_handler(const char*);
extern one_arg_error_handler_t Vec_error_handler;

extern one_arg_error_handler_t 
        set_Vec_error_handler(one_arg_error_handler_t f);

#ifdef TODO
inline <T>Vec::<T>Vec(int l)
{
  s = new <T> [len = l];
}


inline <T>Vec::<T>Vec(int l, <T>* d) :len(l), s(d) {}


inline <T>Vec::~<T>Vec()
{
  delete [] s;
}
#endif /* TODO */

template<class T>
inline int operator != (Vec<T>& a, Vec<T>& b)
{
  return !(a == b);
}

#endif
