aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/perf_counter/strbuf.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-04-20 09:00:56 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-20 11:36:48 -0400
commit0780060124011b94af55830939c86cc0916be0f5 (patch)
tree883a4d0ed69862ab49e6d4bf4e19debafeb5c48c /Documentation/perf_counter/strbuf.c
parentd24e473e5b2ca86d1288b9416227ccc603313d0f (diff)
perf_counter tools: add in basic glue from Git
First very raw version at having a central 'perf' command and a list of subcommands: perf top perf stat perf record perf report ... This is done by picking up Git's collection of utility functions, and hacking them to build fine in this new environment. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter/strbuf.c')
-rw-r--r--Documentation/perf_counter/strbuf.c359
1 files changed, 359 insertions, 0 deletions
diff --git a/Documentation/perf_counter/strbuf.c b/Documentation/perf_counter/strbuf.c
new file mode 100644
index 000000000000..eaba09306802
--- /dev/null
+++ b/Documentation/perf_counter/strbuf.c
@@ -0,0 +1,359 @@
1#include "cache.h"
2
3int prefixcmp(const char *str, const char *prefix)
4{
5 for (; ; str++, prefix++)
6 if (!*prefix)
7 return 0;
8 else if (*str != *prefix)
9 return (unsigned char)*prefix - (unsigned char)*str;
10}
11
12/*
13 * Used as the default ->buf value, so that people can always assume
14 * buf is non NULL and ->buf is NUL terminated even for a freshly
15 * initialized strbuf.
16 */
17char strbuf_slopbuf[1];
18
19void strbuf_init(struct strbuf *sb, size_t hint)
20{
21 sb->alloc = sb->len = 0;
22 sb->buf = strbuf_slopbuf;
23 if (hint)
24 strbuf_grow(sb, hint);
25}
26
27void strbuf_release(struct strbuf *sb)
28{
29 if (sb->alloc) {
30 free(sb->buf);
31 strbuf_init(sb, 0);
32 }
33}
34
35char *strbuf_detach(struct strbuf *sb, size_t *sz)
36{
37 char *res = sb->alloc ? sb->buf : NULL;
38 if (sz)
39 *sz = sb->len;
40 strbuf_init(sb, 0);
41 return res;
42}
43
44void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
45{
46 strbuf_release(sb);
47 sb->buf = buf;
48 sb->len = len;
49 sb->alloc = alloc;
50 strbuf_grow(sb, 0);
51 sb->buf[sb->len] = '\0';
52}
53
54void strbuf_grow(struct strbuf *sb, size_t extra)
55{
56 if (sb->len + extra + 1 <= sb->len)
57 die("you want to use way too much memory");
58 if (!sb->alloc)
59 sb->buf = NULL;
60 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
61}
62
63void strbuf_trim(struct strbuf *sb)
64{
65 char *b = sb->buf;
66 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
67 sb->len--;
68 while (sb->len > 0 && isspace(*b)) {
69 b++;
70 sb->len--;
71 }
72 memmove(sb->buf, b, sb->len);
73 sb->buf[sb->len] = '\0';
74}
75void strbuf_rtrim(struct strbuf *sb)
76{
77 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
78 sb->len--;
79 sb->buf[sb->len] = '\0';
80}
81
82void strbuf_ltrim(struct strbuf *sb)
83{
84 char *b = sb->buf;
85 while (sb->len > 0 && isspace(*b)) {
86 b++;
87 sb->len--;
88 }
89 memmove(sb->buf, b, sb->len);
90 sb->buf[sb->len] = '\0';
91}
92
93void strbuf_tolower(struct strbuf *sb)
94{
95 int i;
96 for (i = 0; i < sb->len; i++)
97 sb->buf[i] = tolower(sb->buf[i]);
98}
99
100struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
101{
102 int alloc = 2, pos = 0;
103 char *n, *p;
104 struct strbuf **ret;
105 struct strbuf *t;
106
107 ret = calloc(alloc, sizeof(struct strbuf *));
108 p = n = sb->buf;
109 while (n < sb->buf + sb->len) {
110 int len;
111 n = memchr(n, delim, sb->len - (n - sb->buf));
112 if (pos + 1 >= alloc) {
113 alloc = alloc * 2;
114 ret = realloc(ret, sizeof(struct strbuf *) * alloc);
115 }
116 if (!n)
117 n = sb->buf + sb->len - 1;
118 len = n - p + 1;
119 t = malloc(sizeof(struct strbuf));
120 strbuf_init(t, len);
121 strbuf_add(t, p, len);
122 ret[pos] = t;
123 ret[++pos] = NULL;
124 p = ++n;
125 }
126 return ret;
127}
128
129void strbuf_list_free(struct strbuf **sbs)
130{
131 struct strbuf **s = sbs;
132
133 while (*s) {
134 strbuf_release(*s);
135 free(*s++);
136 }
137 free(sbs);
138}
139
140int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
141{
142 int len = a->len < b->len ? a->len: b->len;
143 int cmp = memcmp(a->buf, b->buf, len);
144 if (cmp)
145 return cmp;
146 return a->len < b->len ? -1: a->len != b->len;
147}
148
149void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
150 const void *data, size_t dlen)
151{
152 if (pos + len < pos)
153 die("you want to use way too much memory");
154 if (pos > sb->len)
155 die("`pos' is too far after the end of the buffer");
156 if (pos + len > sb->len)
157 die("`pos + len' is too far after the end of the buffer");
158
159 if (dlen >= len)
160 strbuf_grow(sb, dlen - len);
161 memmove(sb->buf + pos + dlen,
162 sb->buf + pos + len,
163 sb->len - pos - len);
164 memcpy(sb->buf + pos, data, dlen);
165 strbuf_setlen(sb, sb->len + dlen - len);
166}
167
168void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
169{
170 strbuf_splice(sb, pos, 0, data, len);
171}
172
173void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
174{
175 strbuf_splice(sb, pos, len, NULL, 0);
176}
177
178void strbuf_add(struct strbuf *sb, const void *data, size_t len)
179{
180 strbuf_grow(sb, len);
181 memcpy(sb->buf + sb->len, data, len);
182 strbuf_setlen(sb, sb->len + len);
183}
184
185void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
186{
187 strbuf_grow(sb, len);
188 memcpy(sb->buf + sb->len, sb->buf + pos, len);
189 strbuf_setlen(sb, sb->len + len);
190}
191
192void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
193{
194 int len;
195 va_list ap;
196
197 if (!strbuf_avail(sb))
198 strbuf_grow(sb, 64);
199 va_start(ap, fmt);
200 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
201 va_end(ap);
202 if (len < 0)
203 die("your vsnprintf is broken");
204 if (len > strbuf_avail(sb)) {
205 strbuf_grow(sb, len);
206 va_start(ap, fmt);
207 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
208 va_end(ap);
209 if (len > strbuf_avail(sb)) {
210 die("this should not happen, your snprintf is broken");
211 }
212 }
213 strbuf_setlen(sb, sb->len + len);
214}
215
216void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
217 void *context)
218{
219 for (;;) {
220 const char *percent;
221 size_t consumed;
222
223 percent = strchrnul(format, '%');
224 strbuf_add(sb, format, percent - format);
225 if (!*percent)
226 break;
227 format = percent + 1;
228
229 consumed = fn(sb, format, context);
230 if (consumed)
231 format += consumed;
232 else
233 strbuf_addch(sb, '%');
234 }
235}
236
237size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
238 void *context)
239{
240 struct strbuf_expand_dict_entry *e = context;
241 size_t len;
242
243 for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
244 if (!strncmp(placeholder, e->placeholder, len)) {
245 if (e->value)
246 strbuf_addstr(sb, e->value);
247 return len;
248 }
249 }
250 return 0;
251}
252
253size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
254{
255 size_t res;
256 size_t oldalloc = sb->alloc;
257
258 strbuf_grow(sb, size);
259 res = fread(sb->buf + sb->len, 1, size, f);
260 if (res > 0)
261 strbuf_setlen(sb, sb->len + res);
262 else if (res < 0 && oldalloc == 0)
263 strbuf_release(sb);
264 return res;
265}
266
267ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
268{
269 size_t oldlen = sb->len;
270 size_t oldalloc = sb->alloc;
271
272 strbuf_grow(sb, hint ? hint : 8192);
273 for (;;) {
274 ssize_t cnt;
275
276 cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
277 if (cnt < 0) {
278 if (oldalloc == 0)
279 strbuf_release(sb);
280 else
281 strbuf_setlen(sb, oldlen);
282 return -1;
283 }
284 if (!cnt)
285 break;
286 sb->len += cnt;
287 strbuf_grow(sb, 8192);
288 }
289
290 sb->buf[sb->len] = '\0';
291 return sb->len - oldlen;
292}
293
294#define STRBUF_MAXLINK (2*PATH_MAX)
295
296int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
297{
298 size_t oldalloc = sb->alloc;
299
300 if (hint < 32)
301 hint = 32;
302
303 while (hint < STRBUF_MAXLINK) {
304 int len;
305
306 strbuf_grow(sb, hint);
307 len = readlink(path, sb->buf, hint);
308 if (len < 0) {
309 if (errno != ERANGE)
310 break;
311 } else if (len < hint) {
312 strbuf_setlen(sb, len);
313 return 0;
314 }
315
316 /* .. the buffer was too small - try again */
317 hint *= 2;
318 }
319 if (oldalloc == 0)
320 strbuf_release(sb);
321 return -1;
322}
323
324int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
325{
326 int ch;
327
328 strbuf_grow(sb, 0);
329 if (feof(fp))
330 return EOF;
331
332 strbuf_reset(sb);
333 while ((ch = fgetc(fp)) != EOF) {
334 if (ch == term)
335 break;
336 strbuf_grow(sb, 1);
337 sb->buf[sb->len++] = ch;
338 }
339 if (ch == EOF && sb->len == 0)
340 return EOF;
341
342 sb->buf[sb->len] = '\0';
343 return 0;
344}
345
346int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
347{
348 int fd, len;
349
350 fd = open(path, O_RDONLY);
351 if (fd < 0)
352 return -1;
353 len = strbuf_read(sb, fd, hint);
354 close(fd);
355 if (len < 0)
356 return -1;
357
358 return len;
359}