/*

$FILE		:	buffer.c
$VERSIONE	:	1.00
$DATA		:	Novembre 1991
$PROGETTO	:	Tecniche OOP in C, prima soluzione
$AUTORE		:	Paolo Sommaruga
$RUOLO		:	File di codifica del dispatcher e dei metodi di BUFFER.
$USO		:	E` il file principale dell'oggetto BUFFER.

*/

#include "exec/exec.h"

#include "buffer.h"

typedef struct buffer_data_blk {
	#include "buffer.p"		/* file di definizione delle proprieta` */
} BDB;

/*
    BUFFER: Dispatcher generale per i metodi dell'oggetto BUFFER.
*/

int BUFFER( h_ogtIpse, msg, pParam, pResult )
POGT  h_ogtIpse;
int   msg;
CADDR pParam;
CADDR pResult;

{
int errore = 0;

    switch ( msg ) {
        case MSG_NEW_r :
            errore = M_CREA_R( (POGT)pResult );
            break;

        case MSG_ALLOC_p :
            errore = M_ALLOCA_OP( h_ogtIpse , pParam );
            break;

        case MSG_GIVEP_r :
            errore = M_GIVEP_OR( h_ogtIpse , pResult );
            break;

        case MSG_GIVEL_r :
            errore = M_GIVEL_OR( h_ogtIpse , pResult );
            break;

        case MSG_FREE :
            errore = M_FREE_O( h_ogtIpse );
            break;

        case MSG_OFF :
            errore = M_DIST_O( h_ogtIpse );
            break;

        default :
            errore = BASE( h_ogtIpse, msg, pParam, pResult );
            break;
    }

return errore;
} /* Fine di BUFFER */

/*
    M_CREA_R: Alloca memoria per la struttura di controllo e per l'area dati.
              Se fallisce de-alloca tutto e restituisce RETURN_FAIL.
*/

static int M_CREA_R( h_ogtNew )
POGT h_ogtNew;

{
#define METODO_CB "Metodo di creazione BUFFER."
#define E_NOMEM_BD "ERRORE: Fallita AllocMem per BUFFER: area dati."

/* alloca la memoria per la struttura di controllo dell'oggetto */
int errore;

errore = NSC( h_ogtNew );
    if ( errore ) return errore;

h_ogtNew->ogt_pfDispatch = (FUNCTIONP)BUFFER;

/* alloca la memoria per i dati dell'oggetto BUFFER */

h_ogtNew->ogt_pDati = (BDB *)AllocMem( sizeof( BDB ) , MEMF_PUBLIC|MEMF_CLEAR );

if ( !h_ogtNew->ogt_pDati ) {
    DSC( h_ogtNew );
    INFO_SET( METODO_CB , E_NOMEM_BD );
    return RETURN_FAIL;
} /* if */

return RETURN_OK;
} /* Fine di M_CREA_R */

/*
    M_ALLOCA_OP: Alloca un blocco di memoria lungo p_map->map_Len e lo
                 linka all'oggetto puntato, con la lunghezza.
*/

static int M_ALLOCA_OP( h_ogtGen, pMap )
POGT  h_ogtGen;
BA_P *pMap;         /* variabile ptr a BA_P */

{
#define METODO_AB "Metodo di allocazione BUFFER."
#define E_NOMEM_B "ERRORE FATALE: Fallita AllocMem per BUFFER."

/* Assegno un ptr temporaneo con un cast per evitare casini */
BDB *pDati;
pDati = (BDB *)h_ogtGen->ogt_pDati;

pDati->bdb_Len = pMap->map_Len;
pDati->bdb_pBuf = (UBYTE *)AllocMem( pMap->map_Len , MEMF_PUBLIC|MEMF_CLEAR );

if ( !pDati->bdb_pBuf ) {
    INFO_SET( METODO_AB , E_NOMEM_B );
    return RETURN_FAIL;
} /* if */

return RETURN_OK;
} /* Fine di M_ALLOCA_OP */

/*
    M_GIVEP_OR: Restituisce il ptr alla memoria allocata.
*/

int M_GIVEP_OR ( h_ogtMem , pBpr)
POGT h_ogtMem;
BP_R *pBpr;

{
BDB *pLocalData;

/* qui bisogna fare il solito cast con una locale di tipo pDati */
pLocalData = (BDB *)h_ogtMem->ogt_pDati;
pBpr->bprMem = pLocalData->bdb_pBuf;

return RETURN_OK;
} /* Fine di M_GIVEP_OR */

/*
    M_GIVEL_OR: Restituisce il ptr alla memoria allocata.
*/

int M_GIVEL_OR ( h_ogtLen , pBlr )
POGT h_ogtLen;
BL_R *pBlr;

{
BDB * pLocalData;

/* qui bisogna fare il solito cast con una locale di tipo pDati */
pLocalData = (BDB *)h_ogtLen->ogt_pDati;
pBlr->blrLen = pLocalData->bdb_Len;

return RETURN_OK;
} /* Fine di M_GIVEL_OR */

/*
    M_FREE_O: De-alloca il buffer lasciando in vita l'oggetto.
*/

static int M_FREE_O( h_ogtGen )
POGT h_ogtGen;

{
/* Assegno un ptr temporaneo con un cast per evitare casini */
BDB *pDati;
pDati = (BDB *)h_ogtGen->ogt_pDati;

FreeMem( pDati->bdb_pBuf , pDati->bdb_Len );

return RETURN_OK;
} /* Fine di M_FREE_O */

/*
    M_DIST_O: De-alloca il buffer e distrugge l'oggetto.
              IMPORTANTE: il puntatore all'oggetto DEVE essere invalidato
              dal programma client. ( per ora! )
*/

static int M_DIST_O( h_ogtOld )
POGT h_ogtOld;

{
(void)M_FREE_O( h_ogtOld );

FreeMem( h_ogtOld->ogt_pDati , sizeof( BDB ) );
DSC( h_ogtOld );

return RETURN_OK;
} /* Fine di M_DIST_O */
