/***************************************************************************
 * RMI - The RMI Project
 *
 * Copyright 2000, Patrick Powell, San Diego, CA
 *     papowell@astart.com
 * See LICENSE for conditions of use.
 * $Id: perlobj.h,v 1.3 2002/05/01 01:10:38 papowell Exp papowell $
 ***************************************************************************/

#ifndef _PERLOBJS_H_
#define _PERLOBJS_H_ 1

/*
 *  PERL Objects
 *  
 The general approach is to model things a la Perl:

   We have an object with a type (NONE, STR, ARRAY, HASH, LIST, and USER_ARRAY)

   The STR object can be a 'real' string with dynamically allocated memory
       or a 'fake string' whose memory is actually in the object.  We use
       these only in HASH objects to save a bit of space.

   The ARRAY is what it appears to be:  an array of OBJS.

   The LIST is an array of pointers to dynamically allocate strings.

   The USER_ARRAY is basically a way to do a malloc of an array of structures
       for the user.  We can even include a 'callback' to free them if we want...

   The HASH is a key/value array, sorted by key value, a la perl.
 */

# define VALUESEP " \t="
# define PRINTCAPSEP ":|"
# define LISTSEP ",; \t"
# define FILESEP ",;: \t\n\f\015"
# define WHITESPACE " \t\n\f\015"
# define LINEENDS "\n\014"

enum OBJ_ST{ OBJ_ST_INT, OBJ_ST_DOUBLE, OBJ_ST_PTR,
		OBJ_ST_SHORTSTR, OBJ_ST_STR, OBJ_ST_BINSTR };
enum OBJ_T_OBJ { OBJ_T_NONE = 0, OBJ_T_SCALAR, OBJ_T_STR, OBJ_T_ARRAY,
	OBJ_T_HASH, OBJ_T_USER_ARRAY, OBJ_T_LIST };

struct obj_obj;

typedef void (*obj_proc_free)( void *p ); 
typedef void (*obj_proc_dump)( int verbose, const char *indent,
	const char *header, void *p );
typedef void (*obj_proc_copy)( void *dest, void *src, MEMPASS ); 

typedef struct scalar_obj {
	union {
		long ival;	/* integer (actually long) value */
		double dval; /* double */
		void *pval; /* pointer */
	} value;
} SCALAR_OBJ;

typedef struct array_obj {
	int len, maxlen;	/* current length, maximum length */
	int size;			/* size of element */
	obj_proc_free free_user_obj; /* call this to free element for user array */
	obj_proc_dump dump_user_obj; /* call this to dump */
	obj_proc_copy copy_user_obj; /* call this to copy */
	void *value;		/* pointer to allocated memory */
} ARRAY_OBJ;

#define SHORT_STR_LEN 24
typedef struct obj_obj {
	unsigned char type, subtype;
	union {
	SCALAR_OBJ scalar;
	ARRAY_OBJ array;
	char strval[SHORT_STR_LEN];
	} info;
} OBJ;

typedef struct hash_element {
	OBJ key;
	OBJ value;
} HASH_ELEMENT;

/* allocate this much more for an object when doing an allocation  */
#define STR_PAD  2
#define HASH_PAD 8
#define ARRAY_PAD 8
#define USER_ARRAY_PAD 8
#define LIST_PAD 8

/* PROTOTYPES */
const char *Type_to_str( int key );
const char *Subtype_to_str( int key );
int TYPE_OBJ( OBJ *p );
int SUBTYPE_OBJ( OBJ *p );
OBJ *NEW_OBJ( OBJ *p, MEMPASS );
OBJ *Clear_OBJ( OBJ *p );
void FREE_OBJ( OBJ *p );
long IVAL_OBJ( OBJ *p );
double DVAL_OBJ( OBJ *p );
void * PVAL_OBJ( OBJ *p );
/* VARARGS2 */
#ifdef HAVE_STDARGS
 OBJ * SET_SCALAR_OBJ( MEMPASS, OBJ *p, int type, ... )
#else
# if defined(DEF)
 OBJ * SET_SCALAR_OBJ(va_alist) va_dcl
# else
 OBJ * SET_SCALAR_OBJ()
# endif
#endif
;
OBJ * SET_IVAL_OBJ( OBJ *p, int v, MEMPASS );
OBJ * SET_DVAL_OBJ( OBJ *p, double v, MEMPASS );
OBJ * SET_PVAL_OBJ( OBJ *p, void *v, MEMPASS );
int IS_STR_OBJ( OBJ *p );
char * VAL_SHORTSTR_OBJ( OBJ *p );
char * VAL_STR_OBJ( OBJ *p);
void * VAL_BINSTR_OBJ( OBJ *p);
int LEN_STR_OBJ( OBJ *p);
int LEN_BINSTR_OBJ( OBJ *p);
OBJ * SET_STR_OBJ(OBJ *p, const char *str, MEMPASS);
OBJ * SET_SHORTSTR_OBJ(OBJ *p, const char *str, MEMPASS);
OBJ * SET_MAXLEN_STR_OBJ( OBJ *p, int maxlen, MEMPASS );
int GET_MAXLEN_STR_OBJ( OBJ *p );
OBJ *SET_MAXLEN_BINSTR_OBJ( OBJ *p, int maxlen, MEMPASS);
OBJ *SET_LEN_BINSTR_OBJ( OBJ *p, int len, MEMPASS);
int GET_MAXLEN_BINSTR_OBJ( OBJ *p, int maxlen);
OBJ * SET_BINSTR_OBJ( OBJ *p, const char *str, int len, MEMPASS );
/* VARARGS2 */
#ifdef HAVE_STDARGS
 OBJ * APPEND_STR_OBJ( MEMPASS,  OBJ *p, ... )
#else
# if defined(DEF)
 OBJ * APPEND_STR_OBJ(va_alist) va_dcl
# else
 OBJ * APPEND_STR_OBJ()
# endif
#endif
;
/* VARARGS2 */
#ifdef HAVE_STDARGS
 OBJ * PREFIX_STR_OBJ( MEMPASS,  OBJ *p, ... )
#else
# if defined(DEF)
 OBJ * PREFIX_STR_OBJ(va_alist) va_dcl
# else
 OBJ * PREFIX_STR_OBJ()
# endif
#endif
;
/* VARARGS2 */
#ifdef HAVE_STDARGS
 OBJ * APPEND_BINSTR_OBJ(  OBJ *p, ... )
#else
# if defined(DEF)
 OBJ * APPEND_BINSTR_OBJ(va_alist) va_dcl
# else
 OBJ * APPEND_BINSTR_OBJ()
# endif
#endif
;
OBJ * NEW_STR_OBJ( const char *str, MEMPASS );
OBJ * NEW_BINSTR_OBJ( void *str, int len, MEMPASS );
int LEN_ARRAY_OBJ( OBJ *p );
void * AT_ARRAY_OBJ( OBJ *p, int indexv );
OBJ * EXTEND_ARRAY_OBJ( OBJ *p, int len, int size, MEMPASS );
OBJ * TRUNC_ARRAY_OBJ( OBJ *p, int len, MEMPASS );
OBJ *SHIFT_DOWN_ARRAY_OBJ( OBJ *p, MEMPASS );
OBJ *ROTATE_DOWN_ARRAY_OBJ( OBJ *p, MEMPASS );
OBJ * NEW_ARRAY_OBJ( OBJ *p, MEMPASS);
OBJ * NEW_USER_ARRAY_OBJ( OBJ *p, int size, obj_proc_free freeit,
	obj_proc_dump dumpit, obj_proc_copy copyit, MEMPASS );
int GET_SIZE_ARRAY_OBJ( OBJ *p );
OBJ * NEW_LIST_OBJ( OBJ *p, MEMPASS);
int LEN_LIST_OBJ( OBJ *p );
char ** GET_LIST_OBJ( OBJ *p );
char * GET_ENTRY_LIST_OBJ( OBJ *p, int indexv );
OBJ * SET_ENTRY_LIST_OBJ( OBJ *p, int indexv, const char *s, MEMPASS );
OBJ * APPEND_LIST_OBJ( OBJ *p, const char *s, MEMPASS );
OBJ * APPEND_LIST_BIN_OBJ( OBJ *p, const char *s, int valuelen, MEMPASS );
OBJ * EXTEND_LIST_OBJ( OBJ *p, int len, MEMPASS );
int LEN_HASH_OBJ( OBJ *p );
OBJ * KEY_HASH_OBJ( OBJ *p, int indexv );
OBJ * VALUE_HASH_OBJ( OBJ *p, int indexv );
OBJ * GET_HASH_OBJ( OBJ *p, const char *key );
OBJ * SET_HASH_OBJ( OBJ *p, const char *key, OBJ *value, MEMPASS );
OBJ *SET_HASH_STR_OBJ( OBJ *p, const char *key, const char *str, MEMPASS );
char *GET_HASH_STR_OBJ( OBJ *p, const char *key, MEMPASS );
char *To_STR_CONV( OBJ *p, MEMPASS );
long To_IVAL_CONV( OBJ *p, MEMPASS );
OBJ *SET_HASH_IVAL_OBJ( OBJ *p, const char *key, int val, MEMPASS );
int GET_HASH_IVAL_OBJ( OBJ *p, const char *key );
OBJ *SET_HASH_DVAL_OBJ( OBJ *p, const char *key, double val, MEMPASS );
double GET_HASH_DVAL_OBJ( OBJ *p, const char *key );
OBJ *SET_HASH_PVAL_OBJ( OBJ *p, const char *key, void * val, MEMPASS );
void * GET_HASH_PVAL_OBJ( OBJ *p, const char *key );
void REMOVE_HASH_OBJ( OBJ *p, const char *key );
OBJ * NEW_HASH_OBJ(OBJ *p, MEMPASS);
OBJ * COPY_OBJ( OBJ *dest, OBJ *p, MEMPASS );
void To_STR_OBJ( OBJ *p, MEMPASS );
void DUMP_OBJ( const char *header, OBJ *p);
void SHORT_DUMP_OBJ( const char *header, OBJ *p);
void REAL_DUMP_OBJ( int verbose, const char *indent, const char *header, OBJ *p);
int Read_fd_STR_OBJ( OBJ **p_ptr, const char *filename, int fd, char *errstr, int errlen, MEMPASS );
int Read_file_STR_OBJ( OBJ **p_ptr, const char *filename, char *errstr, int errlen, MEMPASS );
OBJ *Split_STR_OBJ( OBJ *p, int nomod, char *str, 
    int type, const char *linesep, const char *escape,
        int commentchar, int trim,
	char *keysep, int do_append, int lc, int flagvalues, int value_urlunesc, MEMPASS );
int NeedURLEsc( int c, int full );
int NeedURLEscStr( const char *s, int *extra, int full );
OBJ *URLEsc_OBJ( OBJ *p, const char *instr, int full, MEMPASS );
void URLUnEscStr( char *s );
OBJ *URLUnEsc_OBJ( OBJ *p );
int NeedBackslashEsc( char *str, char *escape );
int NeedBackslashEscStr( const char *s, int *extra, char *escape );
OBJ *BackslashEsc_OBJ( OBJ *p, const char *instr, char *escape, MEMPASS );
OBJ *Hash_to_LIST_OBJ( OBJ *list, OBJ *hash, char *sep, int urlesc, int full,
	char *backslash_esc, MEMPASS );
OBJ *Join_list_OBJ( OBJ *str, OBJ *list, char *prefix, char *suffix, MEMPASS );
OBJ *Hash_to_STR_OBJ( OBJ *str, OBJ *hash, char *prefix, char *suffix,
	char *sep, int urlesc, int full, char *backslash_esc, MEMPASS );
OBJ *Split_file_LIST_OBJ( OBJ *list, char *filelist );
int Read_file_list_OBJ( OBJ *output,
	const char *filenames, char *directories, int required,
	int doinclude, int depth, int maxdepth,
    int type, const char *linesep, const char *escape,
    int commentchar, int trim,
    char *keysep, int do_append, int lc, int flagvalues, int unesc,
	char *errmsg, int errlen, MEMPASS )
;
OBJ *Obj_to_STR_OBJ( OBJ *str, OBJ *obj, MEMPASS );
OBJ *Str_to_STR_OBJ( OBJ *str, char *s, MEMPASS );
OBJ *Str_obj_to_STR_OBJ( OBJ *str, OBJ *obj, MEMPASS );
OBJ *Hash_obj_to_STR_OBJ( OBJ *str, OBJ *obj, char *prefix, MEMPASS );
OBJ *Array_obj_to_STR_OBJ( OBJ *str, OBJ *obj, char *prefix, MEMPASS );
OBJ *List_obj_to_STR_OBJ( OBJ *str, OBJ *obj, char *prefix, MEMPASS );
OBJ *Obj_obj_to_STR_OBJ( OBJ *str, OBJ *obj, char *prefix, MEMPASS );
char *Parse_token_to_str( int c );
void Init_parse( char *str );
char *Get_parse_position( void );
int Get_parse_token( OBJ *str );
int Parse_hash_obj_str( OBJ *hash );
int Parse_array_obj_str( OBJ *array );
int Parse_obj_obj_str( OBJ **objp );
char *Parse_err_msg( void );

#endif
