/*
   JAMLIB - A JAM subroutine library
   Copyright (C) 1999 Björn Stenberg

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

   Changes made by Johan Billing 2000-04-16:

   - Fixed broken JAM_GetSubfield()
   - #includes stdlib.h instead of malloc.h and memory.h

   Changes made by Johan Billing 2000-09-17:

   - Added JAM_GetSubfield_R()

*/

/***********************************************************************
 **
 **  SUBPACKET.C -- Subfield packet handling
 **
 **  Author: Bjorn Stenberg (bjorn.stenberg@sth.frontec.se)
 **
 ***********************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <jamlib/jam.h>

/***********************************************************************
 **
 **  JAM_NewSubPacket - Create a new subfield packet {{{
 **/
s_JamSubPacket* JAM_NewSubPacket( void )
{
    s_JamSubPacket* Sub_PS;

    /* allocate packet struct */
    Sub_PS = (s_JamSubPacket*) malloc( sizeof( s_JamSubPacket ) );
    if ( !Sub_PS )
	return NULL;

    Sub_PS->NumAlloc  = 20;
    Sub_PS->NumFields = 0;

    /* allocate pointer array */
    Sub_PS->Fields = (s_JamSubfield**) calloc( Sub_PS->NumAlloc, sizeof( s_JamSubfield* ) );

    if ( !Sub_PS->Fields ) {
	free (Sub_PS);
	return NULL;
    }

    return Sub_PS;
}
/** }}}
 **
 ***********************************************************************/

/***********************************************************************
 **
 **  JAM_DelSubPacket - Free the data associated with a subfield packet {{{
 **/
int JAM_DelSubPacket( s_JamSubPacket* SubPack_PS )
{
    int i;

    if (!SubPack_PS)
	return JAM_BAD_PARAM;

    for ( i=0; i < SubPack_PS->NumFields; i++ ) {
	s_JamSubfield* Field_PS = SubPack_PS->Fields[i];

	if ( Field_PS->Buffer )
	    free( Field_PS->Buffer );
	free( Field_PS );
    }
    free( SubPack_PS->Fields );
    free( SubPack_PS );

    return 0;
}
/** }}}
 **
 ***********************************************************************/

/***********************************************************************
 **
 **  JAM_GetSubfield -- Get first/next subfield from a subfield packet {{{
 **                     (not reentrant)
 **/
s_JamSubfield* JAM_GetSubfield( s_JamSubPacket* SubPack_PS )
{
    static s_JamSubPacket* LastPack_PS = NULL;
    static int             NextIndex_I = 0;

    if ( SubPack_PS ) {
	LastPack_PS = SubPack_PS;
	NextIndex_I = 0;
    }

    if ( NextIndex_I < LastPack_PS->NumFields )
	return LastPack_PS->Fields[ NextIndex_I++ ];

    return NULL;
}
/** }}}
 **
 ***********************************************************************/

/***********************************************************************
 **
 **  JAM_GetSubfield_R -- Get first/next subfield from a subfield packet {{{
 **                       (reentrant)
 **/
s_JamSubfield* JAM_GetSubfield_R( s_JamSubPacket* SubPack_PS , ulong* Count_PI)
{
    if ( *Count_PI < SubPack_PS->NumFields )
	return SubPack_PS->Fields[ (*Count_PI)++ ];

    return NULL;
}
/** }}}
 **
 ***********************************************************************/

/***********************************************************************
 **
 **  JAM_PutSubfield -- Add a subfield to a subfield packet {{{
 **/
int JAM_PutSubfield( s_JamSubPacket* SubPack_PS, s_JamSubfield* Field_PS )
{
    s_JamSubfield*	NewField_PS;
    uchar*		NewBuf_PC;

    /* do we have to expand the array? */
    if ( SubPack_PS->NumFields == SubPack_PS->NumAlloc ) {
	s_JamSubfield** Fields_PPS;

	SubPack_PS->NumAlloc *= 2;
	Fields_PPS = (s_JamSubfield**) realloc( SubPack_PS->Fields, SubPack_PS->NumAlloc * sizeof( s_JamSubfield* ) );
	if ( !Fields_PPS )
	    return JAM_NO_MEMORY;

	SubPack_PS->Fields=Fields_PPS;
    }

    /*
    **  Copy the passed subfield
    */

    /* allocate a new subfield */
    NewField_PS = (s_JamSubfield*) malloc( sizeof( s_JamSubfield ) );
    if ( !NewField_PS )
	return JAM_NO_MEMORY;

    /* allocate a new buffer */
    if ( Field_PS->DatLen ) {
	NewBuf_PC = (uchar*) malloc( Field_PS->DatLen );
	if ( !NewBuf_PC ) {
	    free (NewField_PS);
	    return JAM_NO_MEMORY;
	}
	memcpy( NewBuf_PC, Field_PS->Buffer, Field_PS->DatLen );
    }
    else
	NewBuf_PC = NULL;

    /* copy field struct */
    NewField_PS->LoID   = Field_PS->LoID;
    NewField_PS->HiID   = Field_PS->HiID;
    NewField_PS->DatLen = Field_PS->DatLen;
    NewField_PS->Buffer = NewBuf_PC;


    /*
    **  Update subfield packet
    */

    SubPack_PS->Fields[ SubPack_PS->NumFields ] = NewField_PS;
    SubPack_PS->NumFields++;

    return 0;
}
/** }}}
 **
 ***********************************************************************/
/* Local variables:
 * vim:set ts=8 sts=4 sw=4:
 * vim600:fdm=marker:
 */


syntax highlighted by Code2HTML, v. 0.9.1