mbox: include messages added to an mbox before saving it
[neatmail.git] / sbuf.c
blobaf6369835a41c6e3f0806f6e9eb1bc4d00f389c3
1 /* variable length string buffer */
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "mail.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)
11 #define MAX(a, b) ((a) < (b) ? (b) : (a))
13 struct sbuf {
14 char *s; /* allocated buffer */
15 int s_n; /* length of the string stored in s[] */
16 int s_sz; /* size of memory allocated for s[] */
19 static void sbuf_extend(struct sbuf *sbuf, int newsz)
21 char *s = sbuf->s;
22 sbuf->s_sz = newsz;
23 sbuf->s = malloc(sbuf->s_sz);
24 if (sbuf->s_n)
25 memcpy(sbuf->s, s, sbuf->s_n);
26 free(s);
29 struct sbuf *sbuf_make(void)
31 struct sbuf *sb = malloc(sizeof(*sb));
32 memset(sb, 0, sizeof(*sb));
33 return sb;
36 char *sbuf_buf(struct sbuf *sb)
38 if (!sb->s)
39 sbuf_extend(sb, 1);
40 sb->s[sb->s_n] = '\0';
41 return sb->s;
44 char *sbuf_done(struct sbuf *sb)
46 char *s = sbuf_buf(sb);
47 free(sb);
48 return s;
51 void sbuf_free(struct sbuf *sb)
53 free(sb->s);
54 free(sb);
57 void sbuf_chr(struct sbuf *sbuf, int c)
59 if (sbuf->s_n + 2 >= sbuf->s_sz)
60 sbuf_extend(sbuf, NEXTSZ(sbuf->s_sz, 1));
61 sbuf->s[sbuf->s_n++] = c;
64 void sbuf_mem(struct sbuf *sbuf, char *s, int len)
66 if (sbuf->s_n + len + 1 >= sbuf->s_sz)
67 sbuf_extend(sbuf, NEXTSZ(sbuf->s_sz, len + 1));
68 memcpy(sbuf->s + sbuf->s_n, s, len);
69 sbuf->s_n += len;
72 void sbuf_str(struct sbuf *sbuf, char *s)
74 sbuf_mem(sbuf, s, strlen(s));
77 int sbuf_len(struct sbuf *sbuf)
79 return sbuf->s_n;
82 void sbuf_cut(struct sbuf *sb, int len)
84 if (sb->s_n > len)
85 sb->s_n = len;
88 void sbuf_printf(struct sbuf *sbuf, char *s, ...)
90 char buf[256];
91 va_list ap;
92 va_start(ap, s);
93 vsnprintf(buf, sizeof(buf), s, ap);
94 va_end(ap);
95 sbuf_str(sbuf, buf);