1 /* dynbuf.h
2 ** dynamic (growable) buffer
3 ** wcm, 2004.04.21 - 2012.08.04
4 ** ===
5 */
6 #ifndef DYNBUF_H
7 #define DYNBUF_H
8 
9 #include <stddef.h>  /* size_t */
10 #include <unistd.h>  /* ssize_t */
11 
12 #define DYNBUF_INITSIZE  1
13 
14 struct dynbuf {
15   void    *buf;
16   size_t   n;   /* actual size allocated  */
17   size_t   p;   /* current position (aka "length", "used") */
18 };
19 typedef struct dynbuf  dynbuf_t;
20 
21 /* constructor for malloc'ed dynbuf: */
22 extern dynbuf_t * dynbuf_new(void);
23 
24 /* destructor for malloc'ed dynbuf: */
25 extern void dynbuf_free(dynbuf_t *);
26 
27 /* dynbuf_INIT()
28 ** static dynbuf object initialization
29 ** usage:
30 **   dynbuf_t dyn = dynbuf_INIT();
31 **
32 ** should be preferred to:
33 **   dynbuf_t d = {0,0,0};
34 */
35 #define dynbuf_INIT() {NULL, 0, 0}
36 
37 /* release internal buffer only: */
38 extern void dynbuf_freebuf(dynbuf_t *);
39 
40 /* no memory release, just set d->p = 0 */
41 extern void dynbuf_clear(dynbuf_t *);
42 #define dynbuf_CLEAR(d) ((d)->p = 0)
43 
44 /* accessors: */
45 extern void * dynbuf_buf(dynbuf_t *);
46 extern size_t dynbuf_len(dynbuf_t *);
47 /* accessor macros: */
48 #define dynbuf_BUF(d) ((d)->buf)
49 #define dynbuf_LEN(d) ((d)->p)
50 
51 /* if necessary, grow to accomodate total need */
52 /* return -1 error, 0 no error */
53 extern int dynbuf_need(dynbuf_t *, size_t need);
54 
55 /* if necessary, grow to accomodate additional add */
56 /* return -1 error, 0 no error */
57 extern int dynbuf_grow(dynbuf_t *, size_t add);
58 
59 /* dynbuf_put*() functions:
60 **   "put" means _append_ to dynbuf
61 **
62 **   return -1 on error, 0 no error
63 */
64 extern int dynbuf_put(dynbuf_t *to, const dynbuf_t *from);
65 extern int dynbuf_putbuf(dynbuf_t *, const void *buf, size_t len);
66 
67 /* dynbuf_putb()
68 ** append single byte to buffer
69 */
70 extern int dynbuf_putb(dynbuf_t *, unsigned char b);
71 
72 /* dynbuf_putc()
73 ** append single char
74 ** note:
75 **    requires char argument in a string, eg:
76 **    dynbuf_putc(d, "K")
77 ** note:
78 **    **deprecated**
79 **    see dynbuf_putb()
80 */
81 #define dynbuf_putc(d,c)  dynbuf_putbuf((d),&(c),1)
82 
83 /* dynbuf_puts()
84 ** str is NUL terminated,
85 ** NUL is _not_ copied into dynbuf
86 */
87 extern int dynbuf_puts(dynbuf_t *, const char *str);
88 
89 /* append '\0' to buffer: */
90 extern int dynbuf_putnul(dynbuf_t *);
91 #define dynbuf_putNUL(d,c)  dynbuf_putb((d),'\0')
92 
93 /* "copy" buf into dynbuf, overwriting previous contents: */
94 extern int dynbuf_copy(dynbuf_t *to, const dynbuf_t *from);
95 extern int dynbuf_copybuf(dynbuf_t *, const void *buf, size_t len);
96 
97 /*
98 ** str is NUL terminated,
99 ** NUL is _not_ copied into dynbuf
100 */
101 extern int dynbuf_copys(dynbuf_t *, const char *str);
102 
103 /* dynbuf_pack()
104 ** pack variable number of uintXX_t arguments specified in fmt into dynbuf
105 ** fmt specification:
106 **   'b': 1 byte    uchar_t
107 **   's': 2 bytes   uint16_t
108 **   'd': 4 bytes   uint32_t
109 **   'L': 8 bytes   uint64_t
110 **
111 ** return:
112 **   >= 0 : number of bytes packed
113 **     -1 : error, errno set
114 **
115 ** errno values include:
116 **   EINVAL:  unknown specifier in fmt
117 **   ENOMEM:  allocation failure
118 **
119 ** notes:
120 **   dynbuf version of upak_pack()
121 */
122 extern ssize_t dynbuf_pack(dynbuf_t *, const char *fmt, ...);
123 
124 #endif /* DYNBUF_H */
125