pdfext: do not use non-POSIX memrchr()
[neatpost.git] / sbuf.c
blobd57f31e8dc231bb1800915acae5d49646b3acfb6
1 /* variable length string buffer */
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "post.h"
8 #define SBUFSZ 128
9 #define ALIGN(n, a) (((n) + (a) - 1) & ~((a) - 1))
10 #define NEXTSZ(o, r) ALIGN(MAX((o) * 2, (o) + (r)), SBUFSZ)
12 struct sbuf {
13 char *s; /* allocated buffer */
14 int s_n; /* length of the string stored in s[] */
15 int s_sz; /* size of memory allocated for s[] */
18 static void sbuf_extend(struct sbuf *sbuf, int newsz)
20 char *s = sbuf->s;
21 sbuf->s_sz = newsz;
22 sbuf->s = malloc(sbuf->s_sz);
23 if (sbuf->s_n)
24 memcpy(sbuf->s, s, sbuf->s_n);
25 free(s);
28 struct sbuf *sbuf_make(void)
30 struct sbuf *sb = malloc(sizeof(*sb));
31 memset(sb, 0, sizeof(*sb));
32 return sb;
35 char *sbuf_buf(struct sbuf *sb)
37 if (!sb->s)
38 sbuf_extend(sb, 1);
39 sb->s[sb->s_n] = '\0';
40 return sb->s;
43 char *sbuf_done(struct sbuf *sb)
45 char *s = sbuf_buf(sb);
46 free(sb);
47 return s;
50 void sbuf_free(struct sbuf *sb)
52 free(sb->s);
53 free(sb);
56 void sbuf_chr(struct sbuf *sbuf, int c)
58 if (sbuf->s_n + 2 >= sbuf->s_sz)
59 sbuf_extend(sbuf, NEXTSZ(sbuf->s_sz, 1));
60 sbuf->s[sbuf->s_n++] = c;
63 void sbuf_mem(struct sbuf *sbuf, char *s, int len)
65 if (sbuf->s_n + len + 1 >= sbuf->s_sz)
66 sbuf_extend(sbuf, NEXTSZ(sbuf->s_sz, len + 1));
67 memcpy(sbuf->s + sbuf->s_n, s, len);
68 sbuf->s_n += len;
71 void sbuf_str(struct sbuf *sbuf, char *s)
73 sbuf_mem(sbuf, s, strlen(s));
76 int sbuf_len(struct sbuf *sbuf)
78 return sbuf->s_n;
81 void sbuf_cut(struct sbuf *sb, int len)
83 if (sb->s_n > len)
84 sb->s_n = len;
87 void sbuf_printf(struct sbuf *sbuf, char *s, ...)
89 char buf[256];
90 va_list ap;
91 va_start(ap, s);
92 vsnprintf(buf, sizeof(buf), s, ap);
93 va_end(ap);
94 sbuf_str(sbuf, buf);