1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
/*** sbuffer.c ****************************************************************
**
** This file is part of BibTool.
** It is distributed under the GNU General Public License.
** See the file COPYING for details.
**
** (c) 1996-2016 Gerd Neugebauer
**
** Net: gene@gerd-neugebauer.de
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2, or (at your option)
** any later version.
**
** This program 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
** Description:
** This module contains functions for dealing with strings of
** aribtrary size. The allocation of memory is done automatically
** when more characters are added.
**
** The functions are modeled after the stream functions of C.
** Currently a |printf|-like function is missing because one was
** not needed yet and it is not so easy to implement---portably.
**
** The functions in this module are very handy to deal with
** strings of arbitrary length where the length is not known in
** advance. E.g. consider the case that a line has to be read
** from a file |file| and the line length should not be restricted by
** some artificial boundry. This can be implemented as follows:
** \\
** |{ StringBuffer *sb = sb_open();|\Ccomment{Declare and
** initialize a string buffer.}\\
** | int c;|\Ccomment{Variable to store a single character.}\\
** | char *s;|\Ccomment{Variable to hold the string at the end.}\\
** | while ( (c=fgetc(file) != EOF|\\
** | && c != '\n')|\\
** | { sbputchar(c,sb); }|\Ccomment{Store each character in the
** string buffer.}\\
** | s = sbflush(sb);|\Ccomment{Get the string from the
** string buffer.}\\
** | puts(s);|\Ccomment{Process the string; e.g. print it.}\\
** | sb_close(sb);|\Ccomment{Free the string buffer.}\\
** |}|
**
** Note that the flushing of the string buffer returns a C string
** which is managed by the string buffer. This memory is freed
** or reused whenever the string buffer needs to. Thus you should
** make a private copy of this string if it should survive the
** next operation of the string buffer. Especially, after the
** call to |sb_close()| this memory has been returned to the
** operating system and is not available any more.
**
******************************************************************************/
#include <bibtool/general.h>
#include <bibtool/sbuffer.h>
/*****************************************************************************/
/* Internal Programs */
/*===========================================================================*/
/*-----------------------------------------------------------------------------
** Function: sbopen()
** Purpose: Allocate a new string buffer.
** Return a pointer to the new string buffer or |NULL| if
** none was available.
** Arguments: none.
** Returns: pointer to new string buffer or NULL
**___________________________________________________ */
StringBuffer* sbopen() /* */
{ register StringBuffer* sb; /* */
/* */
if ( (sb=(StringBuffer*)malloc(sizeof(StringBuffer))) == NULL )/* */
{ return NULL; } /* */
sb->sb__string = NULL; /* */
sb->sb__ptr = sb->sb__size = 0; /* */
return sb; /* */
} /*------------------------*/
/*-----------------------------------------------------------------------------
** Function: sbclose()
** Purpose: Free an old string buffer.
** Arguments:
** sb Pointer to string buffer which should be closed
** Returns: Return |false| upon failure.
**___________________________________________________ */
bool sbclose(sb) /* */
StringBuffer* sb; /* */
{ /* */
if (sb == NULL) return true; /* */
if (sb->sb__string != NULL) free(sb->sb__string);/* */
free((char*)sb); /* */
return false; /* */
} /*------------------------*/
/*-----------------------------------------------------------------------------
** Function: sbputs()
** Purpose: Push a whole string onto a string buffer.
** Arguments:
** s String to be pushed.
** sb Destination string buffer.
** Returns: |false| if something went wrong.
**___________________________________________________ */
bool sbputs(s,sb) /* */
char *s; /* */
StringBuffer* sb; /* */
{ /* */
if (sb == NULL) return false; /* */
/* */
while ( *s ) /* */
{ (void)sbputchar(*s,sb); ++s; /* */
} /* */
return true; /* */
} /*------------------------*/
/*-----------------------------------------------------------------------------
** Function: sbputc()
** Purpose: Push a single character onto a string buffer. In
** contrast to the macro this function handles the
** reallocation of the memory. For the user it should not
** make a difference since the macros uses this function
** when needed.
**
** When no memory is left then the character is discarded
** and this action is signaled via the return value.
** Arguments:
** c Character to put to the string buffer.
** sb Destination string buffer.
** Returns: |false| if no memory is left.
**___________________________________________________ */
bool sbputc(c,sb) /* */
register int c; /* */
register StringBuffer* sb; /* */
{ register char *cp; /* */
/* */
if ( sb->sb__ptr >= sb->sb__size ) /* */
{ sb->sb__size += StringBufferIncrement; /* */
if ( (cp=( sb->sb__ptr == 0 /* */
? malloc(sb->sb__size) /* */
: realloc(sb->sb__string,sb->sb__size))/* */
) == NULL ) /* */
{ sb->sb__size -= StringBufferIncrement; /* */
return false; /* */
} /* */
sb->sb__string = cp; /* */
} /* */
/* */
sb->sb__string[sb->sb__ptr++] = c; /* */
return true; /* */
} /*------------------------*/
/*-----------------------------------------------------------------------------
** Function: sbflush()
** Purpose: Close a string buffer with a trailing |\0| and reset the
** current pointer to the beginning.
** The next write operation starts right at the end. Thus
** additional write operations will overwrite the
** terminating byte.
** Arguments:
** sb String buffer to close.
** Returns: The string contained in the string buffer as a proper
** C string.
**___________________________________________________ */
char* sbflush(sb) /* */
StringBuffer* sb; /* */
{ /* */
(void)sbputchar('\0',sb); /* */
sb->sb__ptr--; /* */
return sb->sb__string; /* */
} /*------------------------*/
/*-----------------------------------------------------------------------------
** Function: sbrewind()
** Purpose: Reset the string buffer pointer to the beginning.
** The next write or read will operate there.
** Arguments:
** sb String buffer to consider.
** Returns: nothing
**___________________________________________________ */
void sbrewind(sb) /* */
StringBuffer* sb; /* */
{ sb->sb__ptr = 0; /* */
} /*------------------------*/
/*-----------------------------------------------------------------------------
** Function: sbtell()
** Purpose: Return the current pointer to the string buffer position.
** This can be used with |sbseek()| to reset it.
** Arguments:
** sb String buffer to consider.
** Returns: The relative byte position of the current writing
** position. This is an integer offset from the beginning
** of the string buffer.
**___________________________________________________ */
int sbtell(sb) /* */
StringBuffer* sb; /* */
{ return sb->sb__ptr; /* */
} /*------------------------*/
/*-----------------------------------------------------------------------------
** Function: sbseek()
** Purpose: Reset the current pointer to the position given. If
** the position is outside the valid region then |true|
** is returned and the position is left unchanged.
** Arguments:
** sb String buffer to reposition.
** pos New position of the string buffer.
** Returns: |false| if everything went right.
**___________________________________________________ */
bool sbseek(sb, pos) /* */
StringBuffer* sb; /* */
int pos; /* */
{ /* */
if ( pos < 0 || pos > sb->sb__ptr ) return true; /* */
sb->sb__ptr = pos; /* */
return false; /* */
} /*------------------------*/
|