File: sbuffer.c

package info (click to toggle)
bibtool 2.55%2Bds-1
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 2,376 kB
  • sloc: ansic: 10,685; perl: 6,205; makefile: 477; sh: 351; tcl: 51
file content (216 lines) | stat: -rw-r--r-- 10,012 bytes parent folder | download
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
/******************************************************************************
** $Id: sbuffer.c,v 1.8 2012-01-26 19:54:21 gene Exp $
**=============================================================================
** 
** This file is part of BibTool.
** It is distributed under the GNU General Public License.
** See the file COPYING for details.
** 
** (c) 1996-2012 Gerd Neugebauer
** 
** Net: gene@gerd-neugebauer.de
** 
**-----------------------------------------------------------------------------
** 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 0 upon failure.
**___________________________________________________			     */
int sbclose(sb)					   /*                        */
  StringBuffer* sb;				   /*                        */
{						   /*                        */
  if ( sb == NULL ) return 1;			   /*                        */
  if ( sb->sb__string != NULL ) free(sb->sb__string);/*                      */
  free((char*)sb);				   /*                        */
  return 0;					   /*                        */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** 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.
**___________________________________________________			     */
int sbputs(s,sb)				   /*                        */
  char         *s;				   /*                        */
  StringBuffer* sb;				   /*                        */
{						   /*                        */
  if ( sb == NULL ) return 1;			   /*                        */
 						   /*                        */
  while ( *s )					   /*                        */
  { (void)sbputchar(*s,sb); ++s;		   /*                        */
  }						   /*                        */
  return 0;					   /*                        */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** 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 discarted
**		and this action is signalled via the return value.
** Arguments:
**	c	Character to put to the string buffer.
**	sb	Destination string buffer.
** Returns:	|FALSE| if no memory is left.
**___________________________________________________			     */
int 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 1;					   /*                        */
    }						   /*                        */
    sb->sb__string = cp;			   /*                        */
  }						   /*                        */
 						   /*                        */
  sb->sb__string[sb->sb__ptr++] = c;		   /*                        */
  return 0;					   /*                        */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** 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.
**___________________________________________________			     */
int sbseek(sb,pos)				   /*                        */
  StringBuffer* sb;				   /*                        */
  int           pos;				   /*                        */
{ 						   /*                        */
  if ( pos < 0 || pos > sb->sb__ptr ) return 1;	   /*                        */
  sb->sb__ptr = pos;				   /*                        */
  return 0;					   /*                        */
}						   /*------------------------*/