-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathsbuffer.c
228 lines (217 loc) · 10.3 KB
/
sbuffer.c
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-2020 Gerd Neugebauer
**
** Net: [email protected]
**
** 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; /* */
} /*------------------------*/