/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE		Header
.NAME		buffer.h
.LANGUAGE	C
.AUTHOR		Francois Ochsenbein [ESO-IPG]
.CATEGORY	Buffer, Stack
.COMMENTS	Automatic processing of buffers.
.ENVIRONMENT
.VERSION 1.0   	23-Jun-1986: Extracted from STESODEF.
.VERSION 2.0	15-Apr-1988: Changed Names
.VERSION 2.1	07-Apr-1989: Added BUF_SaveString
.VERSION 2.2	10-Sep-1991: Added BUF_CurrentItem
.VERSION 3.0	04-Nov-1994: Redesignation of some routines
.VERSION 3.1	11-Oct-2010: BUF_printf
.VERSION 3.2	03-Dec-2010: BUF_AppendInt
------------------------------------------------------------*/

#ifndef BUFFER_DEF
#define BUFFER_DEF	0
#ifndef _ARGS
#ifdef __STDC__
#define _ARGS(A)	A /* ANSI */
#else
#define _ARGS(A)	()  /* non-ansi */
#endif
#endif

/* Use the "osmemory" routines */
#ifdef OSM
#ifndef malloc
#define malloc	osmalloc
#define free	osmfree
#define realloc	osmexpand
#define strdup	osmdup
#include <stdlib.h>
#endif
#endif

/*===========================================================================
 *		BUFFER Structure
 *===========================================================================*/

typedef struct BUFFER_struct {
	char	*buf;		/* Position of buffer in memory		*/
	int	allocated;	/* Presently available memory		*/
	int	increment;	/* Increment unit for expansion		*/
	int	used;		/* Presently used memory		*/
	int	offset;		/* For "locate"	or stacking facilities	*/
    } BUFFER;

/*===========================================================================
 *		Function Templates
 *===========================================================================*/

 	/* mm_b...  deal with Buffer */
BUFFER 	*mm_bnew	_ARGS((int size, int increment));
int	mm_bkill	_ARGS((BUFFER *b));
int	mm_bfree	_ARGS((BUFFER *b));
int 	mm_bexp		_ARGS((BUFFER *b, int new_size));
char 	*mm_bstack	_ARGS((BUFFER *b, char *record, int item_len));  
char 	*mm_bunstack	_ARGS((BUFFER *b));
char 	*mm_bapp	_ARGS((BUFFER *b, char *record, int length)); 
char 	*mm_balloc	_ARGS((BUFFER *b, int length));
char    *mm_bedi	_ARGS((BUFFER *b, int value));

 	/* mm_z...  deal with an array of zero-filled items */
char 	*mm_zfree	_ARGS((BUFFER *b, int index, int item_len)); 
char 	*mm_zindex	_ARGS((BUFFER *b, int index, int item_len));
char 	*mm_zloc	_ARGS((BUFFER *b, int item_len));

char    *mm_printf	_ARGS((BUFFER *b, char *format, ...));

/*======================================================================*
 * 		Macros dealing with Buffers
 *======================================================================*/

#define BUF_Init(type, incr)		{(char *)0, 0, sizeof(type)*incr, 0, 0}
#define BUF_New(type, n, incr)		mm_bnew(sizeof(type)*(n), \
						sizeof(type)*incr)
#define BUF_Kill(b)			mm_bkill(b)			
#define BUF_Free(b)			mm_bkill(b)			
#define BUF_Expand(b, type, n)		mm_bexp(b, sizeof(type)*n)
#define BUF_Open			BUF_New
#define BUF_Close(b)			mm_bfree(b)			
#define BUF_Clear(b)			(b)->used = 0, (b)->offset = 0

#define BUF_AllocateItems(b, type, n)	(type *)mm_balloc(b, sizeof(type)*(n))
#define BUF_AllocateItem(b, type)	BUF_AllocateItems(b,type,1)

#define BUF_AllocateBytes(b,len)	mm_balloc(b,len)
#define BUF_ReserveBytes(b,len)		mm_balloc(b,-(len))
#define BUF_Append			BUF_AppendString
#define BUF_AppendInt(b,n)		mm_bedi(b,n)
#define BUF_AppendItems(b, type, a, n)	(type *)mm_bapp(b, (char *)a, \
						sizeof(type)*(n))
#define BUF_AppendItem(b, type, a)	BUF_AppendItems(b,type,a,1)
#define BUF_AppendString(b, s)		BUF_AppendItems(b, char, s, strlen(s))
#define BUF_SaveString(b, s)		BUF_AppendItems(b, char, s, 1+strlen(s))
#define BUF_printf			mm_printf

#define BUF_StackItem(b, type, a)	(type *)mm_bstack(b, (char *)a, \
						sizeof(type))
#define BUF_StackString(b, s)		mm_bstack(b, s, strlen(s)+1)

#define BUF_UnstackItem(b, type)	(type *)mm_bunstack(b)
#define BUF_Unstack(b)			mm_bunstack(b)

#define BUF_ItemPosition(b, type)	(type *)((b)->buf + (b)->offset)
#define BUF_CurrentItem(b, type)	(type *)((b)->buf + (b)->offset)
#define BUF_Items(b,type)		((b)->used - (b)->offset)/sizeof(type)

/*======================================================================*
 * 		Macros dealing with SETs (arrays of structures)
 *======================================================================*/

#define SET_Init			BUF_Init
#define SET_New				BUF_New
#define SET_Kill			BUF_Kill
#define SET_Open			BUF_Open
#define SET_Close			BUF_Close			

#define SET_FindItem(b, type, i)	(type *)mm_zindex(b, i, sizeof(type))
#define SET_FreeItem(b, type, i)	(type *)mm_zfree(b, i, sizeof(type))
#define SET_FindFreeItem(b, type)	(type *)mm_zloc(b, sizeof(type))

#define SET_Item(b, type)		((b)->offset / sizeof(type))
#define SET_Items(b, type)		((b)->used   / sizeof(type))

#define SET_FirstItem(b, type)		(type *)((b)->buf)
#define SET_EndItem(b, type)		(type *)((b)->buf + (b)->used)
#define SET_LastItem(b, type)		(type *)((b)->buf + (b)->used \
						- sizeof(type))

#endif
