/***************************************************************************
 *                                                                         *
 *   GENDPK.C                                                              *
 *                                                                         *
 *   Copyright (c) 1994-1997 Galacticomm, Inc.        All Rights Reserved. *
 *                                                                         *
 *   The "generic dynapak database" is a data file used to store dynapaks  *
 *   on the server-side.  Agents and offline utilities can use this data-  *
 *   base instead of creating special databases of their own.  This API    *
 *   contains routines to initialize, read from, write to, and shut down   *
 *   the generic dynapak database.                                         *
 *                                                                         *
 *                                            - C. Robert   1/17/94        *
 *                                              T. Stryker                 *
 *                                                                         *
 ***************************************************************************/

#define FILREV "$Revision: 15 $"

#include "gcomm.h"
#include "gcspsrv.h"

DFAFILE *gdpbb;                    /* generic dynapak database Btrieve ptr */

#define NAME ((CHAR *)name+SIDSIZ)
#define GDPNAME (gdpbb->data+SIDSIZ)

static USHORT readgdp(INT direction,struct saunam *name,USHORT length,
                   VOID *dest,CHAR *suffix);
static USHORT cvtgdp(USHORT gdpsiz,USHORT length,VOID *dest,
                   struct flddef *fda);

VOID
opngdp(VOID)                       /* open the generic dynapak database    */
{
     gdpbb=dfaOpen("wgserv2.dat",fldoff(gdprec,value)+MAXDPKV,0);
     inicvt();
}

USHORT                             /*   return number of bytes read        */
readgdpEQ(                         /* read dnp from GDP db w/ conversion   */
struct saunam *name,               /*   dpk to read and dest for name read */
USHORT length,                     /*   length of passed dest buffer       */
VOID *dest,                        /*   destination (NULL=leave in GDPBTR) */
struct flddef *fda)                /*   field def. array                   */
{
     USHORT retval;

     retval=readgdp(0,name,length,dest,"");
     return(cvtgdp(retval,length,dest,fda));
}

USHORT                             /*   return number of bytes read        */
readgdpGT(                         /* read dnp from GDP db w/ conversion   */
struct saunam *name,               /*   dpk to read and dest for name read */
USHORT length,                     /*   length of passed dest buffer       */
VOID *dest,                        /*   destination (NULL=leave in GDPBTR) */
CHAR *suffix,                      /*   suffix for minimal match           */
struct flddef *fda)                /*   field def. array                   */
{
     USHORT retval;

     retval=readgdp(1,name,length,dest,suffix);
     return(cvtgdp(retval,length,dest,fda));
}

USHORT                             /*   return number of bytes read        */
readgdpLT(                         /* read dnp from GDP db w/ conversion   */
struct saunam *name,               /*   dpk to read and dest for name read */
USHORT length,                     /*   length of passed dest buffer       */
VOID *dest,                        /*   destination (NULL=leave in GDPBTR) */
CHAR *suffix,                      /*   suffix for minimal match           */
struct flddef *fda)                /*   field def. array                   */
{
     USHORT retval;

     retval=readgdp(-1,name,length,dest,suffix);
     return(cvtgdp(retval,length,dest,fda));
}

static USHORT                      /*   return number of bytes read        */
readgdp(                           /* read a dynapak from the GDP database */
INT direction,                     /*   direction for read op (1, 0, or -1)*/
struct saunam *name,               /*   dpk to read and dest for name read */
USHORT length,                     /*   length of passed dest buffer       */
VOID *dest,                        /*   destination (NULL=leave in GDPBTR) */
CHAR *suffix)                      /*   suffix for minimal match           */
{
     USHORT retval;

     retval=0;
     dfaSetBlk(gdpbb);
     if (direction == 0 ? dfaAcqEQ(NULL,NAME,0) :
      (direction == 1 ? dfaAcqGT(NULL,NAME,0) : dfaAcqLT(NULL,NAME,0))) {
          if (direction == 0
           || (memicmp(GDPNAME,NAME,fldoff(saunam,suffix)-SIDSIZ) == 0
            && sameto(suffix,&(gdpbb->data[fldoff(saunam,suffix)])))) {
               retval=dfaLastLen()-sizeof(struct saunam);
               ASSERT(retval+sizeof(struct saunam) >= sizeof(struct saunam));
               if (dest != NULL) {
                    movmem(GDPNAME,NAME,sizeof(struct saunam)-SIDSIZ);
                    if (length < retval) {
                         retval=length;
                    }
                    movmem(GDPBTR->value,dest,retval);
               }
          }
     }
     dfaRstBlk();
     if (dest != NULL) {
          setmem((CHAR *)dest+retval,length-retval,0);
     }
     else if (retval < MAXDPKV) {
          GDPBTR->value[retval]='\0';
     }
     return(retval);
}

static USHORT                      /*   return number of bytes read        */
cvtgdp(                            /* unpack dpk from GDP database         */
USHORT gdpsiz,                     /*   dpk size                           */
USHORT length,                     /*   length of passed dest buffer       */
VOID *dest,                        /*   destination (NULL=leave in GDPBTR) */
struct flddef *fda)                /*   field def. array                   */
{
     if (fda != NULL && gdpsiz != 0
      && !(fda == charsFDA && length == STGLEN)) {
          if (dest == NULL) {
               gdpsiz=cvtData(GDPBTR->value,cvttmp,gdpsiz,fda,
                              CVTCLIENT,CVTSERVER,CHAN_NUL);
               movmem(cvttmp,GDPBTR->value,gdpsiz);
               GDPBTR->value[gdpsiz]='\0';
          }
          else {
               gdpsiz=cvtData(dest,cvttmp,gdpsiz,fda,CVTCLIENT,CVTSERVER,CHAN_NUL);
               if (length < gdpsiz) {
                    gdpsiz=length;
               }
               movmem(cvttmp,dest,gdpsiz);
          }
     }
     return(gdpsiz);
}

VOID
writegdp(                          /* write dnp to the GDP db w/ conversion*/
struct saunam *name,               /*   name of dynapak to write           */
USHORT length,                     /*   length of dynapak value            */
VOID *value,                       /*   pointer to dynapak value           */
struct flddef *fda)
{
     VOID *pData;

     if (fda != NULL && !(fda == charsFDA && length == STGLEN) && length != 0) {
          length=cvtData(value,cvttmp,length,fda,CVTSERVER,CVTCLIENT,CHAN_NUL);
          ASSERTM(length != 0,"Invalid length or FDA passed to writegdp()");
          pData=cvttmp;
     }
     else {
          pData=value;
     }
     if (length == STGLEN) {
          length=strlen(pData);
     }
     if (length > MAXDPKV) {
          length=MAXDPKV;
     }
     dfaSetBlk(gdpbb);
     if (dfaAcqEQ(NULL,NAME,0)) {
          if (length != 0) {
               movmem(name,&GDPBTR->name,sizeof(struct saunam));
               movmem(pData,GDPBTR->value,length);
               dfaUpdateV(NULL,(USHORT)(sizeof(struct saunam)+length));
          }
          else {
               dfaDelete();
          }
     }
     else if (length != 0) {
          movmem(name,&GDPBTR->name,sizeof(struct saunam));
          movmem(pData,GDPBTR->value,length);
          dfaInsertV(NULL,(USHORT)(sizeof(struct saunam)+length));
     }
     dfaRstBlk();
}

VOID
clsgdp(VOID)                       /* close the generic dynapak database   */
{
     dfaClose(gdpbb);
}
