Logo Search packages:      
Sourcecode: kbib version File versions  Download package

newstr.cpp

/*
 * newstr.c
 *
 * Copyright (c) Chris Putnam 1999-2005
 *
 * Source code released under the GPL
 *
 *
 * newstring routines for dynamically allocated strings
 *
 * C. Putnam 3/29/02  Clean up newstr_findreplace() (x4 speed increase too)
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "newstr.h"
#include "is_ws.h"

#define newstr_initlen (64)

void 
newstr_init(newstr *string)
{
      if (string==NULL) return;
      string->dim=0;
      string->len=0;
      string->data=NULL;
}

static void 
newstr_initalloc(newstr *string, unsigned long minsize)
{
      unsigned long size = newstr_initlen;
      if (string==NULL) return;
      if (minsize > newstr_initlen) size=minsize;
      string->data = (char *) malloc (sizeof( *(string->data) ) * size);
      if (string->data==NULL) {
            fprintf(stderr,"Error.  Cannot allocate memory in newstr_initalloc.\n");
            exit(1);
      }
      string->data[0]='\0';
      string->dim=size;
      string->len=0;
}

newstr *
newstr_new( void )
{
      newstr *string;
      string = (newstr *) malloc( sizeof( *string ) );
      if (string!=NULL) 
            newstr_initalloc( string, newstr_initlen );
      return string;
}

/* newstr_empty()
 *
 * empty data in string
 */
void
newstr_empty( newstr *string )
{
      if (string && string->data) {
            string->data[0]='\0';
            string->len=0;
      }
}

#ifndef NEWSTR_PARANOIA

void 
newstr_free(newstr *string)
{
      if (string==NULL) return;
      string->dim=0;
      string->len=0;
      if (string->data!=NULL) free(string->data);
      string->data=NULL;
}

static void 
newstr_realloc(newstr *string, unsigned long minsize)
{
      char *newptr;
      unsigned long size;
      size = 2 * string->dim;
      if (size < minsize) size = minsize;
      newptr = (char *) realloc (string->data, sizeof( *(string->data) )*size);
      if (newptr==NULL) {
            fprintf(stderr,"Error.  Cannot reallocate memory (%ld bytes) in newstr_realloc.\n", sizeof(*(string->data))*size);
            exit(1);
      }
      string->data = newptr;
      string->dim = size;
}

#else

void 
newstr_free(newstr *string)
{
      unsigned long i;
      if (string==NULL) return;
      for (i=0; i<string->dim; ++i) string->data[i]='\0';
      string->dim=0;
      if (string->data!=NULL) free(string->data);
      string->data=NULL;
}

void 
newstr_realloc(newstr *string, unsigned long minsize)
{
      char *newptr;
      unsigned long size;
      unsigned long i;
      size = 2 * string->dim;
      if (size < minsize) size = minsize;
      newptr = (char *) malloc( sizeof( *(string->data) ) * size );
      if ( newptr == NULL ) {
            fprintf(stderr,"Error.  Cannot reallocate memory (%d bytes) in newstr_realloc.\n", sizeof(*(string->data))*size);
            exit(1);
      }
      for (i=0; i<string->dim; ++i) string->data[i]='\0';
      free( string->data );
      string->data = newptr;
      string->dim = size;
}

#endif

void
newstr_addchar(newstr *string, char newchar)
{
      if ( !string ) return;
      if ( !string->data || string->dim==0 ) 
            newstr_initalloc(string,newstr_initlen);
      if ( string->len + 2 > string->dim ) 
            newstr_realloc(string,string->len+2);
      string->data[string->len++] = newchar;
      string->data[string->len] = '\0';
}

void 
newstr_fprintf( FILE *fp, newstr *string )
{
    if ( string && string->data ) fprintf(fp,"%s",string->data);
}

void
newstr_prepend( newstr *string, char *addstr )
{
      unsigned long lenaddstr, i;
      if ( !string || !addstr ) return;
      lenaddstr = strlen( addstr );
      if ( string->data==NULL || string->dim==0 )
            newstr_initalloc( string, lenaddstr+1 );
      else {
            if ( string->len + lenaddstr  + 1 > string->dim )
                  newstr_realloc( string, string->len + lenaddstr + 1 );
            for ( i=string->len+lenaddstr-1; i>=lenaddstr; i-- )
                  string->data[i] = string->data[i-lenaddstr];
      }
      strncpy( string->data, addstr, lenaddstr );
      string->len += lenaddstr;
      string->data[ string->len ] = '\0';
}

void 
newstr_strcat( newstr *string, char *addstr )
{
      unsigned long lenaddstr;
      if ( !string || !addstr ) return;
      lenaddstr = strlen( addstr );
      if (string->data==NULL || string->dim==0) 
            newstr_initalloc(string, lenaddstr+1 );
      else {
            if ( string->len + lenaddstr + 1 > string->dim )
                  newstr_realloc( string, string->len + lenaddstr + 1 );
      }
      strncpy(&(string->data[string->len]),addstr,lenaddstr);
      string->len += lenaddstr;
      string->data[string->len]='\0';
}

void
newstr_segcat( newstr *string, char *startat, char *endat )
{
      unsigned int seglength;
      char *p, *q;

      if (string==NULL || startat==NULL || endat==NULL ) return;
      if ( (unsigned long) startat > (unsigned long) endat ) return;

      seglength=(unsigned long) endat - (unsigned long) startat;
      if (string->data==NULL || string->dim==0)
            newstr_initalloc(string, seglength+1);
      else {
            if ( string->len + seglength + 1 > string->dim )
                  newstr_realloc(string, string->len + seglength+1);
      }
      q = &(string->data[string->len]);
      p = startat;
      while ( *p && p!=endat ) *q++ = *p++;
      *q = '\0';
      string->len += seglength;
}

void 
newstr_strcpy (newstr *string, char *addstr)
{
      unsigned long lenaddstr;
      if ( !string || !addstr ) return;
      lenaddstr = strlen( addstr );
      if (string->data==NULL || string->dim==0)
            newstr_initalloc( string, lenaddstr+1 );
      else if ( lenaddstr+1 > string->dim) 
            newstr_realloc(string,lenaddstr+1);
      strncpy(string->data,addstr,lenaddstr);
      string->data[lenaddstr]='\0';
      string->len=lenaddstr;
}

/* newstr_segcpy( s, start, end );
 *
 * copies [start,end) into s
 */
void
newstr_segcpy (newstr *string, char *startat, char *endat )
{
      unsigned long seglength;
      char *p, *q;

      if (string==NULL || startat==NULL || endat==NULL ) return;
      if ( (unsigned long) startat > (unsigned long) endat ) return;

      seglength=(unsigned long) endat - (unsigned long) startat;
      if (string->data==NULL || string->dim==0)
            newstr_initalloc(string, seglength+1);
      else {
            if ( seglength+1 > string->dim )
                  newstr_realloc(string, seglength+1);
      }
      q = string->data;
      p = startat;
      while ( *p && p!=endat ) *q++ = *p++;
      *q = '\0';
      string->len = seglength;
}

void
newstr_segdel( newstr *s, char *p, char *q )
{
      newstr tmp1, tmp2;
      char *r = &(s->data[s->len]);
      newstr_init( &tmp1 );
      newstr_init( &tmp2 );
      newstr_segcpy( &tmp1, s->data, p );
      newstr_segcpy( &tmp2, q, r );
      newstr_strcpy( s, tmp1.data );
      newstr_strcat( s, tmp2.data );
      newstr_free( &tmp2 );
      newstr_free( &tmp1 );
}

/*
 * newstr_findreplace()
 *
 *   if replace is "" or NULL, then delete find
 */

int
newstr_findreplace( newstr *string, char *find, char *replace )
{
      long diff;
      unsigned long findstart, searchstart;
      unsigned long p1, p2;
      unsigned long find_len, rep_len, curr_len;
      char empty[2] = "";
      unsigned long minsize;
      char *p;
      int n = 0;

      if ( !string || !string->data || !string->dim || !find ) return n;
      if ( !replace ) replace = empty;

      find_len = strlen( find );
      rep_len  = strlen( replace );
      diff     = rep_len - find_len;
      if ( diff < 0 ) diff = 0;

      searchstart=0;
      while ((p=strstr(string->data + searchstart,find))!=NULL) {
            curr_len = strlen(string->data);
            findstart=(unsigned long) p - (unsigned long) string->data;
            minsize = curr_len + diff + 1;
            if (string->dim <= minsize) newstr_realloc( string, minsize );
            if ( find_len > rep_len ) {
                  p1 = findstart + rep_len;
                  p2 = findstart + find_len;
                  while( string->data[p2] )
                        string->data[p1++]=string->data[p2++];
                  string->data[p1]='\0';
                  n++;
            } else if ( find_len < rep_len ) {
                  for (p1=curr_len; p1>=findstart+find_len; p1--)
                        string->data[p1+diff] = string->data[p1];
                  n++;
            }
            for (p1=0; p1<rep_len; p1++)
                  string->data[findstart+p1]=replace[p1];
            searchstart = findstart + rep_len; 
            string->len += rep_len - find_len;
      }
      return n;
}


/* newstr_fget()
 *   returns 0 if we're done, 1 if we're not done
 *   extracts line by line (regardless of end characters)
 *   and feeds from buf....
 */
int
newstr_fget( FILE *fp, char *buf, int bufsize, int *pbufpos, newstr *outs )
{
      int  bufpos = *pbufpos, done = 0;
      char *ok;
      newstr_empty( outs );
      while ( !done ) {
            while ( buf[bufpos] && buf[bufpos]!='\r' && buf[bufpos]!='\n' )
                  newstr_addchar( outs, buf[bufpos++] );
            if ( buf[bufpos]=='\0' ) {
                  ok = fgets( buf, bufsize, fp );
                  bufpos=*pbufpos=0;
                  if ( !ok && feof(fp) ) { /* end-of-file */
                        buf[bufpos] = 0;
                        if ( outs->len==0 ) return 0; /*nothing in out*/
                        else return 1; /*one last out */
                  }
            } else if ( buf[bufpos]=='\r' || buf[bufpos]=='\n' ) done=1;
      }
      if ( ( buf[bufpos]=='\n' && buf[bufpos+1]=='\r') ||
           ( buf[bufpos]=='\r' && buf[bufpos+1]=='\n') ) bufpos+=2;
      else if ( buf[bufpos]=='\n' || buf[bufpos]=='\r' ) bufpos+=1; 
      *pbufpos = bufpos;
      return 1;
}

void
newstr_toupper( newstr *s )
{
      unsigned int i;
      if ( !s ) return;
      for ( i=0; i<s->len; ++i )
            s->data[i] = toupper( s->data[i] );
}

/* newstr_swapstrings( s1, s2 )
 * be sneaky and swap internal newstring data from one
 * string to another
 */
void
newstr_swapstrings( newstr *s1, newstr *s2 )
{
      char *tmpp;
      int tmp;

      /* swap dimensioning info */
      tmp = s1->dim;
      s1->dim = s2->dim;
      s2->dim = tmp;

      /* swap length info */
      tmp = s1->len;
      s1->len = s2->len;
      s2->len = tmp;

      /* swap data */
      tmpp = s1->data;
      s1->data = s2->data;
      s2->data = tmpp;
}

void
newstr_trimendingws( newstr *s )
{
      while ( s->len > 0 && is_ws( s->data[s->len-1] ) ) {
            s->data[s->len-1] = '\0';
            s->len--;
      }
}


Generated by  Doxygen 1.6.0   Back to index