Mercurial > code
annotate buf.c @ 125:b9723c197038
Add brand new string buffer
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 07 Mar 2012 09:51:01 +0100 |
parents | |
children | 911201e7574f |
rev | line source |
---|---|
125
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
1 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
2 * buf.c -- easy way to manipulate strings |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
3 * |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
4 * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr> |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
5 * |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
6 * Permission to use, copy, modify, and/or distribute this software for any |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
7 * purpose with or without fee is hereby granted, provided that the above |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
8 * copyright notice and this permission notice appear in all copies. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
9 * |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
17 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
18 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
19 #include <stdio.h> |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
20 #include <stdlib.h> |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
21 #include <string.h> |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
22 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
23 #include "buf.h" |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
24 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
25 #define BUF_AVAIL(buf) ((buf)->alsize - (buf)->length - 1) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
26 #define BUF_SAFE(buf) (!((buf)->flags & BUF_UNSAFE)) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
27 #define BUF_FIXED(buf) ((buf)->flags & BUF_FIXED) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
28 #define BUF_AUTO(buf) (buf->flags == 0) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
29 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
30 static void copy(struct buf *, const void *, size_t); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
31 static int grow(struct buf *, size_t); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
32 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
33 int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
34 buf_init(struct buf *buf) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
35 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
36 /* Set defaults if needed */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
37 buf->bsize = (buf->bsize <= 0) ? BUF_DEFAULT_BSIZE : buf->bsize; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
38 buf->alsize = buf->bsize + 1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
39 buf->malloc = (buf->malloc == NULL) ? &malloc : buf->malloc; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
40 buf->realloc = (buf->realloc == NULL) ? &realloc : buf->realloc; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
41 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
42 if ((buf->text = buf->malloc(buf->alsize)) == NULL) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
43 return -1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
44 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
45 memset(buf->text, 0, buf->alsize); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
46 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
47 return 0; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
48 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
49 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
50 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
51 * This function appends not more than max characters from str. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
52 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
53 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
54 int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
55 buf_ncat(struct buf *buf, const char *str, size_t max) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
56 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
57 size_t tocopy = max; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
58 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
59 for (tocopy = 0; str[tocopy] != '\0' && tocopy < max; ++tocopy) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
60 continue; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
61 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
62 if (BUF_AVAIL(buf) < tocopy) { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
63 /* Can't add more */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
64 if (BUF_SAFE(buf) && BUF_FIXED(buf)) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
65 return -1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
66 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
67 if (BUF_AUTO(buf)) { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
68 if (grow(buf, tocopy) < 0) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
69 return -1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
70 } else { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
71 /* String is unsafe, truncate to the available size */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
72 tocopy = BUF_AVAIL(buf); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
73 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
74 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
75 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
76 copy(buf, str, tocopy); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
77 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
78 return 0; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
79 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
80 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
81 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
82 * Append the string str to the end of the string buffer. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
83 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
84 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
85 int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
86 buf_cat(struct buf *buf, const char *str) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
87 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
88 return buf_ncat(buf, str, strlen(str)); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
89 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
90 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
91 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
92 * Copy at most max character from str to string buffer. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
93 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
94 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
95 int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
96 buf_ncopy(struct buf *buf, const char *str, size_t max) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
97 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
98 buf_clear(buf); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
99 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
100 return buf_ncat(buf, str, max); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
101 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
102 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
103 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
104 * Copy the string str to the string buffer. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
105 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
106 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
107 int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
108 buf_copy(struct buf *buf, const char *str) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
109 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
110 return buf_ncopy(buf, str, strlen(str)); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
111 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
112 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
113 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
114 * Copy the printf(3) like call to the string buffer, this function |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
115 * returns -1 on fixed safe buffer, otherwise 0 is returned if there |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
116 * is no allocation failure. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
117 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
118 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
119 int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
120 buf_vprintf(struct buf *buf, const char *fmt, va_list ap) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
121 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
122 int copied, done = 0; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
123 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
124 if (BUF_FIXED(buf) && BUF_SAFE(buf)) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
125 return -1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
126 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
127 buf_clear(buf); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
128 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
129 do { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
130 copied = vsnprintf(buf->text, buf->alsize, fmt, ap); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
131 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
132 if (copied > BUF_AVAIL(buf)) { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
133 if (BUF_FIXED(buf)) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
134 done = 1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
135 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
136 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
137 * vsnprintf returns -1 on windows, we need to grow |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
138 * the buffer by block size. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
139 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
140 if (grow(buf, buf->alsize + buf->bsize) < 0) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
141 return -1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
142 } else { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
143 done = 1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
144 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
145 } while (!done); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
146 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
147 return 0; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
148 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
149 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
150 int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
151 buf_printf(struct buf *buf, const char *fmt, ...) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
152 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
153 va_list ap; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
154 int rv; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
155 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
156 va_start(ap, fmt); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
157 rv = buf_vprintf(buf, fmt, ap); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
158 va_end(ap); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
159 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
160 return rv; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
161 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
162 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
163 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
164 * Clear the string buffer. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
165 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
166 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
167 void |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
168 buf_clear(struct buf *buf) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
169 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
170 memset(buf->text, 0, buf->alsize); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
171 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
172 buf->length = 0; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
173 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
174 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
175 void |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
176 buf_free(struct buf *buf) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
177 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
178 buf_clear(buf); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
179 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
180 free(buf->text); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
181 buf->text = NULL; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
182 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
183 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
184 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
185 * Valid options that can be set for a buffer : |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
186 * l -> optional buf block size of type int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
187 * m -> malloc function that must matches void * (*malloc)(size_t) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
188 * r -> realloc function that must matches void * (*realloc)(void *, size_t) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
189 * f -> buffer flags that are OR'ed |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
190 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
191 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
192 void |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
193 buf_set(struct buf *buf, const char *fmt, ...) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
194 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
195 va_list ap; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
196 const char *p; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
197 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
198 va_start(ap, fmt); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
199 for (p = fmt; *p != '\0'; ++p) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
200 switch (*p) { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
201 case 'l': |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
202 buf->bsize = va_arg(ap, int); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
203 break; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
204 case 'm': |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
205 buf->malloc = va_arg(ap, void *(*)(size_t)); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
206 break; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
207 case 'r': |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
208 buf->realloc = va_arg(ap, void *(*)(void *, size_t)); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
209 break; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
210 case 'f': |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
211 case 't': |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
212 buf->flags = va_arg(ap, int); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
213 break; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
214 default: |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
215 break; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
216 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
217 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
218 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
219 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
220 * Append to the end of buffer the void ptr of count size. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
221 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
222 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
223 static void |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
224 copy(struct buf *buf, const void *ptr, size_t count) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
225 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
226 memcpy(buf->text + buf->length, ptr, count); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
227 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
228 buf->text[buf->length + count] = '\0'; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
229 buf->length += count; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
230 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
231 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
232 /* |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
233 * Grow the text buffer until the available size fit the needed |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
234 * size. This function may return -1 on allocation failure. |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
235 */ |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
236 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
237 static int |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
238 grow(struct buf *buf, size_t needed) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
239 { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
240 while (BUF_AVAIL(buf) <= needed) { |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
241 buf->text = buf->realloc(buf->text, buf->alsize + buf->bsize); |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
242 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
243 if (buf->text == NULL) |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
244 return -1; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
245 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
246 buf->alsize += buf->bsize; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
247 } |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
248 |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
249 return 0; |
b9723c197038
Add brand new string buffer
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
250 } |