/* Nessuslib -- the Nessus Library
 * Copyright (C) 1998 Renaud Deraison
 *
 * $Id: harglists.h,v 1.8 1999/11/25 20:55:29 renaud Exp $
 *
 * Author: Jordan Hrycaj <jordan@mjh.teddy-net.com>
 *
 * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Jordan re-wrote Renauds idea of an arglists management on top
 * of the hash list manager
 *
 * --------------------------------------------------------------------
 *
 * There is a generic interface to symbolic run time variable managemet.
 * Althoug opaque variable types are supported, the idea is to let the
 * C language to type defs checking as far a possible.
 *
 *
 * Vitual data types supported:
 * ----------------------------
 *
 * HARG_NONE:    may be casted to (int)0, means no data type at all
 *		 and is used in special cases, only.
 *
 * HARG_STRING:  is stored as a '\0' terminated character string, the
 *               corresponding type group is BLOB
 *
 * HARG_BLOB:    is considered similar as HARG_STRING but without the
 *               terminating '\0', is stored as Binary Large OBject,
 *               the corresponding type group is BLOB
 *
 * HARG_PTR      is stored as a (var*)pointer, the corresponding type
 *               group is SCALAR
 *
 * HARG_INT      is stored as a HARG_PTR and interpreted as integer, the
 *               corresponding type group is SCALAR
 *
 * HARG_HARGLST  is stored and treated as a HARG_PTR with the only
 *               exception, that harg_dup() and harg_close_all() will
 *               recurse to that sublist implied and process it, too;
 *               the corresponding type group is SCALAR
 *
 *
 * List construction/destruction:
 * ------------------------------
 *
 * harglst*   harg_create              (unsigned estimated_size);
 * harglst*   harg_dup       (harglst*, unsigned estimated_size);
 * void       harg_close     (harglst*);
 * void       harg_close_all (harglst*);
 *
 * Both, harg_create() and harg_dup() create new variable lists,
 * the latter copies the access tree forthat list, recursively (see 
 * HARG_HARGLST, above.)
 *
 *
 * Adding symbolically accessed data:
 * ----------------------------------
 *
 * hargkey_t *harg_add_string         (harglst*, hargkey_t*, char*);
 * hargkey_t *harg_add_blob           (harglst*, hargkey_t*, unsigned, void*);
 * hargkey_t *harg_add_ptr            (harglst*, hargkey_t*, void*);
 * hargkey_t *harg_add_harg           (harglst*, hargkey_t*  harglst*)
 * hargkey_t *harg_add_int            (harglst*, hargkey_t*  int);
 *
 * hargkey_t *harg_add_default_string (harglst*, hargkey_t*, char*);
 * hargkey_t *harg_add_default_blob   (harglst*, hargkey_t*, unsigned, void*);
 * hargkey_t *harg_add_default_ptr    (harglst*, hargkey_t*, void*);
 * hargkey_t *harg_add_default_harg   (harglst*, hargkey_t*  harglst*)
 * hargkey_t *harg_add_default_int    (harglst*, hargkey_t*  int);
 *
 * Add some typed entry to the list.  If an entry with the given key exists,
 * already, the harg_add_default_*() directive will have no effect, whreas
 * the others always overwrite an exixting entry.
 *
 * The return value is always a pointer to a copy of the second argument,
 * the access key which exists as long as the table entry exists without
 * beeing overwitten.
 *
 * Only when the list pointer (the first argument) is NULL the return value
 * is also NULL.
 *
 *
 * Deleting symbolically accessed data:
 * ------------------------------------
 *
 * int harg_remove (harglst*, hargkey_t*);
 *
 *
 * Modifying symbolically accessed data:
 * --------------------------------------
 *
 * int harg_set_string (harglst*, hargkey_t*, char*);
 * int harg_set_blob   (harglst*, hargkey_t*, unsigned, void*);
 * int harg_set_ptr    (harglst*, hargkey_t*, void*);
 * int harg_set_harg   (harglst*, hargkey_t*, harglst*);
 * int harg_set_int    (harglst*, hargkey_t*, int);
 * int harg_set_value  (harglst*, hargkey_t*, void*);
 *
 * An existing table entry is assigned a new value.  The directive
 * harg_set_value() will not do any type checking and assume the new
 * value given as third argument matches the internal data type. All
 * other function will do a type checking and detect an error if the
 * types don't match. Upon error, -1 is returned and 0,  otherwise.
 *
 * int harg_type_set_string (harglst*, hargkey_t*);
 * int harg_type_set_blob   (harglst*, hargkey_t*);
 * int harg_type_set_ptr    (harglst*, hargkey_t*);
 * int harg_type_set_harg   (harglst*, hargkey_t*);
 * int harg_type_set_int    (harglst*, hargkey_t*);
 *
 * These functions redefine an existing type of a table entry to a new
 * type. This only works among the same type groups scalar (ptr, harg, 
 * and int) or object (blob and string.) Upon error, -1 is returned and 0,
 * otherwise.
 *
 * int harg_set_id (harglst*, hargkey_t*, int);
 *
 * This functions overwites the internal id any element get by default. The
 * default id of an element is non-zero and sort of unique over all elements
 * in the list in that sense, that any newly created element gets a new
 * positive value  from the incremented list counter (which may overflow and
 * start anew at 1.)   The internal id will not change when list entries are
 * assigned new values, or types.  Upon error, -1 is returned  and 0, otherwise.
 *
 *
 * Retrieving symbolically accessed data:
 * --------------------------------------
 *
 * char      *harg_get_string  (harglst*, hargkey_t*);
 * void      *harg_get_ptr     (harglst*, hargkey_t*);
 * harglst   *harg_get_harg    (harglst*, hargkey_t*);
 * void      *harg_get_blob    (harglst*, hargkey_t*);
 * int        harg_get_int     (harglst*, hargkey_t*);
 * void      *harg_get_value   (harglst*, hargkey_t*);
 *
 *
 * hargkey_t *harg_inx_key     (harglst*,unsigned);
 *
 * Get the key of the n-th element as given as second argument, and the NULL 
 * pointer if there was none. Note that the list needs sorting before the key 
 * is retrieved if the structure has changed since the last time, this directive 
 * was used.
 *
 *
 * unsigned   harg_get_size    (harglst*,hargkey_t*);
 *
 * hargkey_t *harg_inx_key     (harglst*,unsigned);
 *
 * Get the key of the n-th element as given as second argument, and the NULL 
 * pointer if there was none. Note that the list needs sorting before the key 
 * is retrieved if the structure has changed since the last time, this directive 
 * was used.
 *
 *
 * hargtype_t harg_get_type    (harglst*,hargkey_t*);
 * int        harg_get_id      (harglst*,hargkey_t*);
 *
 *
 * Operations on all entries of a list:
 * ------------------------------------
 *
 * void      harg_dump       (harglst*);
 * hargwalk *harg_walk_init   (harglst*);
 * char*     harg_walk_next  (hargwalk*);
 * void      harg_walk_stop  (hargwalk*);
 * int       harg_do         (harglst*, int(*call_back)(), void *);
 */

#ifndef __HARGLIST_H__
#define __HARGLIST_H__

typedef
enum _hargtype_t {
  HARG_NONE = 0,
  HARG_STRING,
  HARG_PTR,
  HARG_INT,
  HARG_ARGLIST,
  HARG_BLOB,
  HARG_HARGLST
} hargtype_t ;

typedef const char hargkey_t ;

#ifdef __HARG_INTERNAL__
typedef 
struct _harglst {
  hlst             *x ;
  unsigned     autoid ;
  int destroy_sublist ;
} harglst;
#else

typedef struct _harglst  {char opaq;} harglst;
#endif /* __HARG_INTERNAL__ */

typedef struct _hargwalk {char opaq;} hargwalk;

/* functinal interface */

extern harglst*   harg_create     (unsigned estimated_size);
extern harglst*   harg_dup        (harglst*, unsigned estimated_size);
extern void       harg_close      (harglst*);
extern void       harg_close_all  (harglst*);

extern hargkey_t *harg_add        (harglst*,hargkey_t*,hargtype_t,unsigned,void*);
extern hargkey_t *harg_add_default(harglst*,hargkey_t*,hargtype_t,unsigned,void*);
extern int        harg_remove     (harglst*,hargkey_t*);

extern int        harg_set_tvalue (harglst*,hargkey_t*,hargtype_t,unsigned,void*);
extern int        harg_set_type   (harglst*,hargkey_t*,hargtype_t);
extern int        harg_set_id     (harglst*,hargkey_t*,int);

extern void      *harg_get_tvalue (harglst*,hargkey_t*,hargtype_t);
extern hargtype_t harg_get_type   (harglst*,hargkey_t*);
extern int        harg_get_id     (harglst*,hargkey_t*);
extern unsigned   harg_get_size   (harglst*,hargkey_t*);
extern hargkey_t *harg_inx_key    (harglst*,unsigned);

extern void       harg_dump       (harglst*);
extern hargwalk  *harg_walk_init   (harglst*);
extern hargkey_t *harg_walk_next  (hargwalk*);
extern void       harg_walk_stop  (hargwalk*);

extern int        harg_do         (harglst*, 
   int(*)(void*state,void*data,hargtype_t,unsigned size,int id,hargkey_t*),
   void *state) ;

/* convenience macros */

#define harg_add_string(d,key,str) harg_add (d, key, HARG_STRING,  0, (void*)str)
#define harg_add_nstring(d,key,n,str) harg_add(d,key, HARG_STRING, n, (void*)str)
#define harg_add_ptr(   d,key,ptr) harg_add (d, key, HARG_PTR,     0, ptr)
#define harg_add_harg(  d,key,lst) harg_add (d, key, HARG_HARGLST, 0, lst)
#define harg_add_blob(d,key,l,ptr) harg_add (d, key, HARG_BLOB,    l, ptr)
#define harg_add_int(   d,key,  n) harg_add (d, key, HARG_INT, 0, (void*)(n))

#define harg_add_default_string(d,key,str) harg_add_default (d, key, HARG_STRING,  0, (void*)str)
#define harg_add_default_ptr(   d,key,ptr) harg_add_default (d, key, HARG_PTR,     0, ptr)
#define harg_add_default_harg(  d,key,lst) harg_add_default (d, key, HARG_HARGLST, 0, lst)
#define harg_add_default_blob(d,key,l,ptr) harg_add_default (d, key, HARG_BLOB,    l, ptr)
#define harg_add_default_int(   d,key,num) harg_add_default (d, key, HARG_INT, 0, (void*)(num))

#define harg_get_string(d,key)    ((char*)harg_get_tvalue (d, key, HARG_STRING))
#define harg_get_ptr(   d,key)    ((void*)harg_get_tvalue (d, key, HARG_PTR))
#define harg_get_harg(  d,key) ((harglst*)harg_get_tvalue (d, key, HARG_HARGLST))
#define harg_get_blob(  d,key)    ((void*)harg_get_tvalue (d, key, HARG_BLOB))
#define harg_get_int(   d,key)      ((int)harg_get_tvalue (d, key, HARG_INT))
#define harg_get_value( d,key)            harg_get_tvalue (d, key, HARG_NONE)

#define harg_set_string(d,key,str) harg_set_tvalue (d, key, HARG_STRING, 0, str)
#define harg_set_nstring(d,key,n,str) harg_set_tvalue(d, key, HARG_STRING, n, str)
#define harg_set_ptr(   d,key,ptr) harg_set_tvalue (d, key, HARG_PTR,    0, ptr)
#define harg_set_harg(  d,key,lst) harg_set_tvalue (d, key, HARG_HARGLST,0, lst) 
#define harg_set_blob(d,key,l,ptr) harg_set_tvalue (d, key, HARG_BLOB,   l, ptr)
#define harg_set_int(   d,key,num) harg_set_tvalue (d, key, HARG_INT,    0, (void*)(num))
#define harg_set_value( d,key,val) harg_set_tvalue (d, key, HARG_NONE,   0, val)

#define harg_type_set_string(d,key)  harg_set_type (d, key, HARG_STRING)
#define harg_type_set_ptr(   d,key)  harg_set_type (d, key, HARG_PTR)
#define harg_type_set_harg(  d,key)  harg_set_type (d, key, HARG_HARGLST) 
#define harg_type_set_blob(  d,key)  harg_set_type (d, key, HARG_BLOB)
#define harg_type_set_int(   d,key)  harg_set_type (d, key, HARG_INT)

void * harg_ptr_get_ptr(harglst *, void*);
int harg_ptr_remove_ptr(harglst*, void*);
hargkey_t* harg_ptr_add_ptr(harglst*, void*);
#endif /* __HARGLIST_H__ */
