1 /* -*- Mode: C -*- */
2
3 /* filament.h --- a bit like a string but different =)O|
4 * Copyright (C) 1998, 1999, 2000, 2002 Gary V. Vaughan
5 * Originally by Gary V. Vaughan, 1998
6 * This file is part of Snprintfv
7 *
8 * Snprintfv is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * Snprintfv program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses>.
20 *
21 * As a special exception to the GNU General Public License, if you
22 * distribute this file as part of a program that also links with and
23 * uses the libopts library from AutoGen, you may include it under
24 * the same distribution terms used by the libopts library.
25 */
26
27 /* Code: */
28
29 #ifndef FILAMENT_H
30 #define FILAMENT_H 1
31
32 #include <snprintfv/compat.h>
33
34 #ifdef __cplusplus
35 extern "C"
36 {
37 #if 0
38 /* This brace is so that emacs can still indent properly: */ }
39 #endif
40 #endif /* __cplusplus */
41
42 #define FILAMENT_BUFSIZ (512 - sizeof(char *) - (2 * sizeof(size_t)))
43
44 /**
45 * Filament:
46 * Opaque data type used to hold 8-bit clean dynamic strings which know
47 * their own length and resize themselves to avoid buffer overruns.
48 **/
49 typedef struct filament Filament;
50
51 struct filament
52 {
53 char *value; /* pointer to the start of the string */
54 size_t length; /* length of the string */
55 size_t size; /* total memory allocated */
56 char buffer[FILAMENT_BUFSIZ]; /* usually string == &buffer[0] */
57 };
58
59 /**
60 * filnew: constructor
61 * @init: address of the first byte to copy into the new object.
62 * @len: the number of bytes to copy into the new object.
63 *
64 * Create a new Filament object, initialised to hold a copy of the
65 * first @len bytes starting at address @init. If @init is NULL, or
66 * @len is 0 (or less), then the initialised Filament will return the
67 * empty string, "", if its value is queried.
68 *
69 * Return value:
70 * A newly created Filament object is returned.
71 **/
72 extern Filament *
73 filnew (const char *const init, size_t len);
74
75 /**
76 * filinit:
77 * @fil: The Filament object to initialise.
78 * @init: address of the first byte to copy into the new object.
79 * @len: the number of bytes to copy into the new object.
80 *
81 * Initialise a Filament object to hold a copy of the first @len bytes
82 * starting at address @init. If @init is NULL, or @len is 0 (or less),
83 * then the Filament will be reset to hold the empty string, "".
84 *
85 * Return value:
86 * The initialised Filament object is returned.
87 **/
88 extern Filament *
89 filinit (Filament *fil, const char *const init, size_t len);
90
91 /**
92 * fildelete: destructor
93 * @fil: The Filament object for recycling.
94 *
95 * The memory being used by @fil is recycled.
96 *
97 * Return value:
98 * The original contents of @fil are converted to a null terminated
99 * string which is returned, either to be freed itself or else used
100 * as a normal C string. The entire Filament contents are copied into
101 * this string including any embedded nulls.
102 **/
103 extern char *
104 fildelete (Filament *fil);
105
106 /**
107 * _fil_extend:
108 * @fil: The Filament object which may need more string space.
109 * @len: The length of the data to be stored in @fil.
110 * @copy: whether to copy data from the static buffer on reallocation.
111 *
112 * This function will will assign a bigger block of memory to @fil
113 * considering the space left in @fil and @len, the length required
114 * for the prospective contents.
115 */
116 extern void
117 _fil_extend (Filament *fil, size_t len, bool copy);
118
119 #line 60 "filament.in"
120
121 /* Save the overhead of a function call in the great majority of cases. */
122 #define fil_maybe_extend(fil, len, copy) \
123 (((len)>=(fil)->size) ? _fil_extend((fil), (len), (copy)) : (void)0)
124
125 /**
126 * filval:
127 * @fil: The Filament object being queried.
128 *
129 * Return value:
130 * A pointer to the null terminated string held by the Filament
131 * object is returned. Since the @fil may contain embedded nulls, it
132 * is not entirely safe to use the strfoo() API to examine the contents
133 * of the return value.
134 **/
135 SNV_INLINE char *
filval(Filament * fil)136 filval (Filament *fil)
137 {
138 /* Because we have been careful to ensure there is always at least
139 one spare byte of allocated memory, it is safe to set it here. */
140 fil->value[fil->length] = '\0';
141 return (char *) (fil->value);
142 }
143
144 /**
145 * fillen:
146 * @fil: The Filament object being queried.
147 *
148 * Return value:
149 * The length of @fil, including any embedded nulls, but excluding the
150 * terminating null, is returned.
151 **/
152 SNV_INLINE size_t
fillen(Filament * fil)153 fillen (Filament *fil)
154 {
155 return fil->length;
156 }
157
158 /**
159 * filelt:
160 * @fil: The Filament being queried.
161 * @n: A zero based index into @fil.
162 *
163 * This function looks for the @n'th element of @fil.
164 *
165 * Return value:
166 * If @n is an index inside the Filament @fil, then the character stored
167 * at that index cast to an int is returned, otherwise @n is outside
168 * this range and -1 is returned.
169 **/
170 SNV_INLINE int
filelt(Filament * fil,ssize_t n)171 filelt (Filament *fil, ssize_t n)
172 {
173 if ((n >= 0) && (n < (ssize_t)fil->length))
174 return (int) fil->value[n];
175 else
176 return -1;
177 }
178
179 /**
180 * filncat:
181 * @fil: The destination Filament of the concatenation.
182 * @str: The address of the source bytes for concatenation.
183 * @n: The number of bytes to be copied from @str.
184 *
185 * @n bytes starting with the byte at address @str are destructively
186 * concatenated to @fil. If necessary, @fil is dynamically reallocated
187 * to make room for this operation.
188 *
189 * Return value:
190 * A pointer to the (not null terminated) string which is the result
191 * of this concatenation is returned.
192 **/
193 SNV_INLINE char *
filncat(Filament * fil,const char * str,size_t n)194 filncat (Filament *fil, const char *str, size_t n)
195 {
196 fil_maybe_extend (fil, n + fil->length, true);
197 memcpy (fil->value + fil->length, str, n);
198 fil->length += n;
199 return fil->value;
200 }
201
202 /**
203 * filcat:
204 * @fil: The destination Filament of the concatenation.
205 * @str: The address of the source bytes for concatenation.
206 *
207 * The bytes starting at address @str upto and including the first null
208 * byte encountered are destructively concatenated to @fil. If
209 * necessary @fil is dynamically reallocated to make room for this
210 * operation.
211 *
212 * Return value:
213 * A pointer to the (not null terminated) string which is the result
214 * of this concatenation is returned.
215 **/
216 SNV_INLINE char *
filcat(Filament * fil,const char * str)217 filcat (Filament *fil, const char *str)
218 {
219 size_t length = strlen (str);
220 return filncat (fil, str, length);
221 }
222
223 /**
224 * filccat:
225 * @fil: The destination Filament of the concatenation.
226 * @c: The character to append to @fil.
227 *
228 * @c is destructively concatenated to @fil. If necessary, @fil is
229 * dynamically reallocated to make room for this operation. When used
230 * repeatedly this function is less efficient than %filncat,
231 * since it must check whether to extend the filament before each
232 * character is appended.
233 *
234 * Return value:
235 * A pointer to the (not null terminated) string which is the result
236 * of this concatenation is returned.
237 **/
238 SNV_INLINE char *
filccat(Filament * fil,int c)239 filccat (Filament *fil, int c)
240 {
241 fil_maybe_extend (fil, 1 + fil->length, true);
242 fil->value[fil->length++] = (char)(c & 0xFF);
243 return fil->value;
244 }
245
246 #ifdef __cplusplus
247 #if 0
248 /* This brace is so that emacs can still indent properly: */
249 {
250 #endif
251 }
252 #endif /* __cplusplus */
253
254 #endif /* FILAMENT_H */
255
256 /* filament.h ends here */
257