1/*****************************************************************************/
2/* */
3/* strbuf.h */
4/* */
5/* Variable sized string buffers */
6/* */
7/* */
8/* */
9/* (C) 2001-2009, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* */
15/* This software is provided 'as-is', without any expressed or implied */
16/* warranty. In no event will the authors be held liable for any damages */
17/* arising from the use of this software. */
18/* */
19/* Permission is granted to anyone to use this software for any purpose, */
20/* including commercial applications, and to alter it and redistribute it */
21/* freely, subject to the following restrictions: */
22/* */
23/* 1. The origin of this software must not be misrepresented; you must not */
24/* claim that you wrote the original software. If you use this software */
25/* in a product, an acknowledgment in the product documentation would be */
26/* appreciated but is not required. */
27/* 2. Altered source versions must be plainly marked as such, and must not */
28/* be misrepresented as being the original software. */
29/* 3. This notice may not be removed or altered from any source */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36#ifndef STRBUF_H
37#define STRBUF_H
38
39
40
41#include <stdarg.h>
42#include <string.h>
43
44/* common */
45#include "attrib.h"
46#include "check.h"
47#include "inline.h"
48
49
50
51/*****************************************************************************/
52/* Data */
53/*****************************************************************************/
54
55
56
57typedef struct StrBuf StrBuf;
58struct StrBuf {
59 char* Buf; /* Pointer to buffer */
60 unsigned Len; /* Length of the string */
61 unsigned Index; /* Used for reading (Get and friends) */
62 unsigned Allocated; /* Size of allocated memory */
63};
64
65/* An empty string buf */
66extern const StrBuf EmptyStrBuf;
67
68/* Initializer for static string bufs */
69#define STATIC_STRBUF_INITIALIZER { 0, 0, 0, 0 }
70
71/* Initializer for auto string bufs */
72#define AUTO_STRBUF_INITIALIZER { 0, 0, 0, 0 }
73
74/* Initialize with a string literal (beware: evaluates str twice!) */
75#define LIT_STRBUF_INITIALIZER(str) { (char*)str, sizeof(str)-1, 0, 0 }
76
77
78
79/*****************************************************************************/
80/* Code */
81/*****************************************************************************/
82
83
84
85#if defined(HAVE_INLINE)
86INLINE StrBuf* SB_Init (StrBuf* B)
87/* Initialize a string buffer */
88{
89 *B = EmptyStrBuf;
90 return B;
91}
92#else
93StrBuf* SB_Init (StrBuf* B);
94#endif
95
96StrBuf* SB_InitFromString (StrBuf* B, const char* S);
97/* Initialize a string buffer from a literal string. Beware: The buffer won't
98** store a copy but a pointer to the actual string. A buffer initialized with
99** this routine may be "forgotten" without calling SB_Done, since no memory
100** has been allocated.
101*/
102
103void SB_Done (StrBuf* B);
104/* Free the data of a string buffer (but not the struct itself) */
105
106StrBuf* NewStrBuf (void);
107/* Allocate, initialize and return a new StrBuf */
108
109void FreeStrBuf (StrBuf* B);
110/* Free a string buffer */
111
112void SB_Realloc (StrBuf* B, unsigned NewSize);
113/* Reallocate the string buffer space, make sure at least NewSize bytes are
114** available.
115*/
116
117#if defined(HAVE_INLINE)
118INLINE unsigned SB_GetLen (const StrBuf* B)
119/* Return the length of the buffer contents */
120{
121 return B->Len;
122}
123#else
124# define SB_GetLen(B) (B)->Len
125#endif
126
127#if defined(HAVE_INLINE)
128INLINE unsigned SB_GetIndex (const StrBuf* B)
129/* Return the user index of the string buffer */
130{
131 return B->Index;
132}
133#else
134# define SB_GetIndex(B) (B)->Index
135#endif
136
137#if defined(HAVE_INLINE)
138INLINE void SB_SetIndex (StrBuf* B, unsigned Index)
139/* Set the user index of the string buffer */
140{
141 B->Index = Index;
142}
143#else
144# define SB_SetIndex(B, Idx) ((B)->Index = (Idx))
145#endif
146
147#if defined(HAVE_INLINE)
148INLINE const char* SB_GetConstBuf (const StrBuf* B)
149/* Return a buffer pointer */
150{
151 return B->Buf;
152}
153#else
154# define SB_GetConstBuf(B) (B)->Buf
155#endif
156
157#if defined(HAVE_INLINE)
158INLINE char* SB_GetBuf (StrBuf* B)
159/* Return a buffer pointer */
160{
161 return B->Buf;
162}
163#else
164# define SB_GetBuf(B) (B)->Buf
165#endif
166
167#if defined(HAVE_INLINE)
168INLINE char SB_At (const StrBuf* B, unsigned Index)
169/* Get a character from the buffer */
170{
171 PRECONDITION (Index < B->Len);
172 return B->Buf[Index];
173}
174#else
175char SB_At (const StrBuf* B, unsigned Index);
176/* Get a character from the buffer */
177#endif
178
179#if defined(HAVE_INLINE)
180INLINE char SB_AtUnchecked (const StrBuf* B, unsigned Index)
181/* Get a character from the buffer */
182{
183 return B->Buf[Index];
184}
185#else
186# define SB_AtUnchecked(B, Index) ((B)->Buf[Index])
187#endif
188
189#if defined(HAVE_INLINE)
190INLINE int SB_IsEmpty (const StrBuf* B)
191/* Return true if the string buffer is empty */
192{
193 return (B->Len == 0);
194}
195#else
196# define SB_IsEmpty(B) ((B)->Len == 0)
197#endif
198
199#if defined(HAVE_INLINE)
200INLINE int SB_NotEmpty (const StrBuf* B)
201/* Return true if the string buffer is not empty */
202{
203 return (B->Len > 0);
204}
205#else
206# define SB_NotEmpty(B) ((B)->Len > 0)
207#endif
208
209#if defined(HAVE_INLINE)
210INLINE void SB_Clear (StrBuf* B)
211/* Clear the string buffer (make it empty) */
212{
213 B->Len = B->Index = 0;
214}
215#else
216# define SB_Clear(B) ((B)->Len = (B)->Index = 0)
217#endif
218
219#if defined(HAVE_INLINE)
220INLINE void SB_Reset (StrBuf* B)
221/* Reset the string buffer index to zero */
222{
223 B->Index = 0;
224}
225#else
226# define SB_Reset(B) ((B)->Index = 0)
227#endif
228
229#if defined(HAVE_INLINE)
230INLINE char SB_Get (StrBuf* B)
231/* Return the next character from the string incrementing Index. Returns NUL
232** if the end of the string is reached.
233*/
234{
235 return (B->Index < B->Len)? B->Buf[B->Index++] : '\0';
236}
237#else
238# define SB_Get(B) (((B)->Index < (B)->Len)? (B)->Buf[(B)->Index++] : '\0')
239#endif
240
241#if defined(HAVE_INLINE)
242INLINE char SB_Peek (const StrBuf* B)
243/* Look at the next character from the string without incrementing Index.
244** Returns NUL if the end of the string is reached.
245*/
246{
247 return (B->Index < B->Len)? B->Buf[B->Index] : '\0';
248}
249#else
250# define SB_Peek(B) (((B)->Index < (B)->Len)? (B)->Buf[(B)->Index] : '\0')
251#endif
252
253#if defined(HAVE_INLINE)
254INLINE char SB_LookAt (const StrBuf* B, unsigned Index)
255/* Look at a specific character from the string. Returns NUL if the given
256** index is greater than the size of the string.
257*/
258{
259 return (Index < B->Len)? B->Buf[Index] : '\0';
260}
261#else
262# define SB_LookAt(B,Index) (((Index) < (B)->Len)? (B)->Buf[(Index)] : '\0')
263#endif
264
265#if defined(HAVE_INLINE)
266INLINE char SB_LookAtLast (const StrBuf* B)
267/* Look at the last character from the string. Returns NUL if the string buffer
268** is empty.
269*/
270{
271 return (B->Len > 0)? B->Buf[B->Len-1] : '\0';
272}
273#else
274# define SB_LookAtLast(B) (((B)->Len > 0)? (B)->Buf[(B)->Len-1] : '\0')
275#endif
276
277#if defined(HAVE_INLINE)
278INLINE void SB_Skip (StrBuf* B)
279/* Skip the next character in the string buffer if this is possible. */
280{
281 if (B->Index < B->Len) {
282 ++B->Index;
283 }
284}
285#else
286# define SB_Skip(B) do { if ((B)->Index < (B)->Len) ++(B)->Index; } while (0)
287#endif
288
289#if defined(HAVE_INLINE)
290INLINE void SB_SkipMultiple (StrBuf* B, unsigned Count)
291/* Skip a number of characters in the string buffer if this is possible. */
292{
293 if ((B->Index += Count) > B->Len) {
294 B->Index = B->Len;
295 }
296}
297#else
298# define SB_SkipMultiple(B, Count) \
299 do { if (((B)->Index += (Count)) > (B)->Len) (B)->Index = (B)->Len; } while (0)
300#endif
301
302void SB_Drop (StrBuf* B, unsigned Count);
303/* Drop characters from the end of the string. */
304
305void SB_Terminate (StrBuf* B);
306/* Zero terminate the given string buffer. NOTE: The terminating zero is not
307** accounted for in B->Len, if you want that, you have to use AppendChar!
308*/
309
310void SB_CopyBuf (StrBuf* Target, const char* Buf, unsigned Size);
311/* Copy Buf to Target, discarding the old contents of Target */
312
313#if defined(HAVE_INLINE)
314INLINE void SB_CopyStr (StrBuf* Target, const char* S)
315/* Copy S to Target, discarding the old contents of Target */
316{
317 SB_CopyBuf (Target, S, strlen (S));
318}
319#else
320void SB_CopyStr (StrBuf* Target, const char* S);
321/* Copy S to Target, discarding the old contents of Target */
322#endif
323
324#if defined(HAVE_INLINE)
325INLINE void SB_Copy (StrBuf* Target, const StrBuf* Source)
326/* Copy Source to Target, discarding the old contents of Target */
327{
328 SB_CopyBuf (Target, Source->Buf, Source->Len);
329 Target->Index = Source->Index;
330}
331#else
332void SB_Copy (StrBuf* Target, const StrBuf* Source);
333/* Copy Source to Target, discarding the old contents of Target */
334#endif
335
336void SB_AppendChar (StrBuf* B, int C);
337/* Append a character to a string buffer */
338
339void SB_AppendBuf (StrBuf* B, const char* S, unsigned Size);
340/* Append a character buffer to the end of the string buffer */
341
342#if defined(HAVE_INLINE)
343INLINE void SB_AppendStr (StrBuf* B, const char* S)
344/* Append a string to the end of the string buffer */
345{
346 SB_AppendBuf (B, S, strlen (S));
347}
348#else
349void SB_AppendStr (StrBuf* B, const char* S);
350/* Append a string to the end of the string buffer */
351#endif
352
353#if defined(HAVE_INLINE)
354INLINE void SB_Append (StrBuf* Target, const StrBuf* Source)
355/* Append the contents of Source to Target */
356{
357 SB_AppendBuf (Target, Source->Buf, Source->Len);
358}
359#else
360void SB_Append (StrBuf* Target, const StrBuf* Source);
361/* Append the contents of Source to Target */
362#endif
363
364#if defined(HAVE_INLINE)
365INLINE void SB_Cut (StrBuf* B, unsigned Len)
366/* Cut the contents of B at the given length. If the current length of the
367** buffer is smaller than Len, nothing will happen.
368*/
369{
370 if (Len < B->Len) {
371 B->Len = Len;
372 }
373}
374#else
375void SB_Cut (StrBuf* B, unsigned Len);
376/* Cut the contents of B at the given length. If the current length of the
377** buffer is smaller than Len, nothing will happen.
378*/
379#endif
380
381void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len);
382/* Copy a slice from Source into Target. The current contents of Target are
383** destroyed. If Start is greater than the length of Source, or if Len
384** characters aren't available, the result will be a buffer with less than Len
385** bytes.
386*/
387
388void SB_Move (StrBuf* Target, StrBuf* Source);
389/* Move the complete contents of Source to target. This will delete the old
390** contents of Target, and Source will be empty after the call.
391*/
392
393void SB_ToLower (StrBuf* S);
394/* Convert all characters in S to lower case */
395
396void SB_ToUpper (StrBuf* S);
397/* Convert all characters in S to upper case */
398
399int SB_Compare (const StrBuf* S1, const StrBuf* S2);
400/* Do a lexical compare of S1 and S2. See strcmp for result codes. */
401
402int SB_CompareStr (const StrBuf* S1, const char* S2);
403/* Do a lexical compare of S1 and S2. See strcmp for result codes. */
404
405void SB_VPrintf (StrBuf* S, const char* Format, va_list ap) attribute ((format (printf, 2, 0)));
406/* printf function with S as target. The function is safe, which means that
407** the current contents of S are discarded, and are allocated again with
408** a matching size for the output. The function will call FAIL when problems
409** are detected (anything that let xsnprintf return -1).
410*/
411
412void SB_Printf (StrBuf* S, const char* Format, ...) attribute ((format (printf, 2, 3)));
413/* vprintf function with S as target. The function is safe, which means that
414** the current contents of S are discarded, and are allocated again with
415** a matching size for the output. The function will call FAIL when problems
416** are detected (anything that let xsnprintf return -1).
417*/
418
419
420
421/* End of strbuf.h */
422
423#endif
424