/* ar.h - decls for variable size arrays
 *
 ****************************************************************
 * Copyright (C) 1998, 2000 Thomas Lord
 * 
 * See the file "COPYING" for further information about
 * the copyright and warranty status of this work.
 */


#ifndef INCLUDE__ARRAYS__AR_H
#define INCLUDE__ARRAYS__AR_H

#include "hackerlab/machine/types.h"
#include "hackerlab/mem/talloc.h"



typedef union 
{
  void * void_ptr;              /* for passing to ar_* functions */

  t_uchar * uchar_ptr;          /* array of char */
  t_uchar ** uchar_ptr_ptr;     /* array of char * */
  void ** void_ptr_ptr;         /* array of void * */
  int * int_ptr;                /* array of int */
  off_t *off_t_ptr;             /* array of off_t */
} t_converter;



/* automatically generated __STDC__ prototypes */
extern int ar_size (void * base);
#define ar_ref(base, n, szof) _ar_ref (base, n, szof,  "ar_ref: "__location__)
extern void * _ar_ref (void ** base,
                      int n,
                      int szof,
                      char const * name);
#define ar_setsize(base, n, szof) _ar_setsize (base, n, szof,  "ar_setsize: "__location__)
extern int _ar_setsize (void ** base,
                       int n,
                       size_t szof,
                       char const * name);
extern void ar_compact (void ** base,
                        size_t szof);
extern void ar_free (void ** base);
extern void * ar_pop (void ** base,
                      size_t szof);
extern void * ar_copy (void * base,
                       size_t szof);
extern void * ar_insert (void **base,
                         int index,
                         int szof);
extern void * ar_base (void *base);

/* macros for too-trivial-routines */
/************************************************************************
 *(h2 "Variable Sized Arrays as Stacks")
 */

/*(c ar_push)
 * void * ar_push (void ** base, size_t szof);
 * 
 * Return the address of element `n' in an array previously containing
 * only `n-1' elements.
 *
 * `base' is a pointer to a pointer to the array.
 * 
 * `szof' is the size, in bytes, of one element.
 *
 * The new array element is filled with 0 bytes.
 *
 * This function may resize and relocate the array.  If it does,
 * `*base' is updated to point to the new location of the array.
 */
#define ar_push(base, szof) ar_ref (base, ar_size (*base), szof)

/* macros for typesafe inline methods */

/* TODO factor out into 
  and the majority becomes AR_TYPEDEF_.. #define AR_TYPEDEF(type, name) AR_TYPEDEF_(type, ar_ ## name)
  however the fn calls dont support that at the moment */
#define AR_TYPEDEF(type, ar_type_name) \
  typedef type * ar_##ar_type_name; \
  static inline ar_##ar_type_name \
ar_ref_##ar_type_name (ar_##ar_type_name *array, int index)  \
{ \
    return (ar_##ar_type_name)_ar_ref ((void **)array, \
                                            index, \
                                            sizeof (type), \
                                            "ar_ref_"#ar_type_name": "__location__); \
} \
\
static inline int \
ar_size_##ar_type_name (ar_##ar_type_name array) \
{ \
    return ar_size (array); \
} \
\
static inline void \
ar_free_##ar_type_name (ar_##ar_type_name *array) \
{ \
    ar_free ((void **)(array)); \
    *array = NULL; \
} \
\
static inline ar_##ar_type_name \
ar_push_##ar_type_name (ar_##ar_type_name *array, type value) \
{ \
    ar_##ar_type_name result = \
    (ar_##ar_type_name)ar_push ((void **)array, \
				sizeof (type)); \
    *result = value; \
    talloc_set_name_const (ar_base (*array), "ar_push: " __location__); \
    return result; \
} \
static inline ar_##ar_type_name \
ar_push_ext_##ar_type_name (ar_##ar_type_name *array, type value, char const * name) \
{ \
    ar_##ar_type_name result = \
    (ar_##ar_type_name)ar_push ((void **)array, \
				sizeof (type)); \
    *result = value; \
    talloc_set_name_const (ar_base (*array), name); \
    return result; \
} \
static inline type \
ar_pop_##ar_type_name (ar_##ar_type_name *array) \
{ \
    return *(ar_##ar_type_name)ar_pop ((void **)array, \
                                            sizeof (type)); \
} \
\
static inline void \
ar_insert_##ar_type_name (ar_##ar_type_name *array, int index, type value) \
{ \
    * (ar_##ar_type_name) ar_insert ((void **)array, \
		index, \
	        sizeof (type)) = value; \
} \
static inline void \
ar_remove_##ar_type_name (ar_##ar_type_name *array, int toDelete) \
{ \
    int position = toDelete; \
    if (toDelete < 0 || toDelete + 1 > ar_size_##ar_type_name (*array)) \
        return; \
    for (position = toDelete; position + 1 < ar_size_##ar_type_name (*array); ++position) \
      { \
        *ar_ref_##ar_type_name (array, position) = *ar_ref_##ar_type_name (array, position + 1); \
      } \
    ar_pop_##ar_type_name (array); \
}  \
static inline int \
ar_setsize_##ar_type_name (ar_##ar_type_name *array, int count) \
{ \
    return _ar_setsize ((void **)array, \
                       count, \
		       sizeof (type), \
		       "ar_setsize_"#ar_type_name": "__location__); \
} \
static inline int \
ar_setsize_ext_##ar_type_name (ar_##ar_type_name *array, int count, char const * name) \
{ \
    return _ar_setsize ((void **)array, \
                       count, \
		       sizeof (type), \
		       name); \
}

#define ar_for_each(array, varname) for (varname = 0; varname < ar_size (array); ++varname)

/* common types */
AR_TYPEDEF (int, int);
AR_TYPEDEF (size_t, size_t);
AR_TYPEDEF (long, long);
AR_TYPEDEF (unsigned long, ulong);
AR_TYPEDEF (off_t, off_t);
AR_TYPEDEF (char *, char_star);
AR_TYPEDEF (unsigned char *, uchar_star);

#endif  /* INCLUDE__ARRAYS__AR_H */


syntax highlighted by Code2HTML, v. 0.9.1