/***********************************
  (C) Copyright 1992-1993; dit/upm
  Distributed under the conditions stated in the
  TOPO General Public License (see file LICENSE)
  ***********************************/

/***********************************
  
  Santiago Pavon Gomez
  David Larrabeiti Lopez
  
  27 Nov 1992
  
  String Blocks                    
  
  COMPILATION OPTIONS: The behaviour of this module can be modified
  by the following compilation flags:
  
  MEMTRACE
  
  ************************************/

/* LINTLIBRARY */


/* KJT 12/02/12: Added */
#include <stdlib.h>
#include "listdh.h"
#include "limisc.h"
#include "listrbk.h"


/******************************************************************
 *                                                                                                *
 *      String Blocks                                                 *
 *  Management of strings whose allocated memory space is         *
 *      a multiple of STRBCKINC.                                      *
 *      The user need not care about string overflows.                *
 *                                                                                                *
 *******************************************************************/

#define STRBCKINC 128

typedef struct { int    next,    /* string index where '\0' is.  */
		   size;    /* current string block size.   */
		 char * string;  /* the char string.             */
	       } StrBckRecTyp, *PStrBckRecTyp;

static int new_strbk_count      = 0;
static int released_strbk_count = 0;

/*----------------------------------------------------------------*/

/* InitStrBck
 * Init the module
 */
void InitStrBck()
{
#ifdef SDEBUG
  new_strbk_count      = 0;
  released_strbk_count = 0;
#endif
}

/*----------------------------------------------------------------*/

/* StatStrBck
 * Number of asked  and released strbk nodes
 */
void StatStrBck( new, released )
     int * new, *released;
{
  *new      = new_strbk_count;
  *released = released_strbk_count;
}

/*----------------------------------------------------------------*/

static PStrBckRecTyp NewStrBck()
{
#ifdef SDEBUG
  new_strbk_count++;
#endif
  return (PStrBckRecTyp)NewCellM(sizeof(StrBckRecTyp));
}

/*----------------------------------------------------------------*/

/* CreateStrBck
 * create a string block with an array of char of size STRBCKINC
 */
StrBckTyp CreateStrBck()
{
  PStrBckRecTyp aux;
  
  aux            = NewStrBck();
  aux->string    = (char*)emalloc(STRBCKINC);
  aux->size      = STRBCKINC;
  aux->string[0] = '\0';
  aux->next      = 0;
  return (StrBckTyp)aux;
}

/*----------------------------------------------------------------*/

/* FreeStrBck
 * Free a String Block
 */
void FreeStrBck( strBck )
     StrBckTyp strBck;
{
  PStrBckRecTyp sbPt;
  
  sbPt = (PStrBckRecTyp)strBck;
  if ( sbPt->string!=NULL )
    free( sbPt->string );
  FreeCellM( (void*)sbPt, sizeof(StrBckRecTyp) );
#ifdef SDEBUG
  released_strbk_count++;
#endif
}

/*----------------------------------------------------------------*/

/* CopyStrBck
 * Copy a String Block
 */
StrBckTyp CopyStrBck( strBck )
     StrBckTyp strBck;
{
  PStrBckRecTyp aux;
  
  aux         = NewStrBck();
  if ( ((PStrBckRecTyp)strBck)->size > 0 ) {
    aux->next   = ((PStrBckRecTyp)strBck)->next;
    aux->size   = ( aux->next/STRBCKINC + 1 ) * STRBCKINC ;
    aux->string = (char*)emalloc(aux->size); 
    aux->string = strcpy(aux->string,((PStrBckRecTyp)strBck)->string);
  }
  else {
    aux->next   = -1;
    aux->size   = 0;
    aux->string = NULL;
  }
  return (StrBckTyp)aux;
}

/*----------------------------------------------------------------*/

/* CleanStrBck
 * clean a string block
 */
void CleanStrBck( strBck )
     StrBckTyp strBck;
{
  PStrBckRecTyp sbPt;
  
  sbPt = (PStrBckRecTyp)strBck;
  if ( sbPt->size > 0 ) {
    sbPt->string[0] = '\0';
    sbPt->next      = 0;
  }
}

/*----------------------------------------------------------------*/

/* CopyStrStrBck
 * Make a copy of the string of a string block
 */
char * CopyStrStrBck( strBck )
     StrBckTyp strBck;
{
  if ( ((PStrBckRecTyp)strBck)->size > 0 ) 
    return CopyString(((PStrBckRecTyp)strBck)->string);
  else
    return NULL;
}

/*----------------------------------------------------------------*/

/* LookStrStrBck
 * Look at the string of a string block
 */
char * LookStrStrBck( strBck )
     StrBckTyp strBck;
{
  return ((PStrBckRecTyp)strBck)->string;
}

/*----------------------------------------------------------------*/

/* GetStrStrBck
 * Returns the string stored in the string block "strBck" and
 * sets the string "strBck" to NULL.
 */
char * GetStrStrBck( strBck )
     StrBckTyp strBck;
{
  char * string;
  PStrBckRecTyp sbPt;
  
  sbPt         = (PStrBckRecTyp)strBck;
  string       = sbPt->string;
  sbPt->string = NULL;
  sbPt->next   = -1;
  sbPt->size   = 0;
  return string;
}

/*----------------------------------------------------------------*/

/* ConcatStrBck
 * Concat a char string into a String Block. Never mind size overflow.
 */
StrBckTyp ConcatStrBck( strBck, str )
     StrBckTyp strBck ;
     char    * str;
{
  int newNext, strLength;
  PStrBckRecTyp sbPt;
  
  sbPt = (PStrBckRecTyp)strBck;
  strLength = strlen(str);
  if ( sbPt->size > 0 ) {
    newNext   = sbPt->next + strLength;
    if ( newNext >= sbPt->size ) {
      sbPt->size   = ( ((sbPt->size+strLength+1)/STRBCKINC)+1 ) * STRBCKINC ;
      sbPt->string = (char*)erealloc((void*)ALIGN(sbPt->string),sbPt->size );
    }
    (void)strcat( &(sbPt->string[sbPt->next]), str );
    sbPt->next = newNext;
  }
  else {
    sbPt->next   = strLength;
    sbPt->size   = ( strLength/STRBCKINC + 1 ) * STRBCKINC ;
    sbPt->string = (char*)emalloc(sbPt->size); 
    sbPt->string = strcpy(sbPt->string,str);
  }
  return (StrBckTyp)sbPt;
}

/*----------------------------------------------------------------*/

/* ConcatIntStrBck
 * Convert a integer into a char string and concat it into a String Block.
 */
StrBckTyp ConcatIntStrBck( strBck, n )
     StrBckTyp strBck ;
     int       n;
{
  char * aux;
  
  aux = IntToString(n);
  strBck = ConcatStrBck( strBck, aux );
  free(aux);
  
  return strBck;
}

/*----------------------------------------------------------------*/





