vi: repeat and execute commands
[neatvi.git] / sbuf.c
blobfbffdfb70d3e9d26c7880bcb235927bd0d84fc8f
1 /* variable length string buffer */
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "vi.h"
8 #define SBUFSZ 128
9 #define ALIGN(n, a) (((n) + (a) - 1) & ~((a) - 1))
11 struct sbuf {
12 char *s; /* allocated buffer */
13 int s_n; /* length of the string stored in s[] */
14 int s_sz; /* size of memory allocated for s[] */
17 static void sbuf_extend(struct sbuf *sbuf, int newsz)
19 char *s = sbuf->s;
20 sbuf->s_sz = newsz;
21 sbuf->s = malloc(sbuf->s_sz);
22 if (sbuf->s_n)
23 memcpy(sbuf->s, s, sbuf->s_n);
24 free(s);
27 struct sbuf *sbuf_make(void)
29 struct sbuf *sb = malloc(sizeof(*sb));
30 memset(sb, 0, sizeof(*sb));
31 return sb;
34 char *sbuf_buf(struct sbuf *sb)
36 if (!sb->s)
37 sbuf_extend(sb, 1);
38 sb->s[sb->s_n] = '\0';
39 return sb->s;
42 char *sbuf_done(struct sbuf *sb)
44 char *s = sbuf_buf(sb);
45 free(sb);
46 return s;
49 void sbuf_free(struct sbuf *sb)
51 free(sb->s);
52 free(sb);
55 void sbuf_chr(struct sbuf *sbuf, int c)
57 if (sbuf->s_n + 2 >= sbuf->s_sz)
58 sbuf_extend(sbuf, sbuf->s_sz + SBUFSZ);
59 sbuf->s[sbuf->s_n++] = c;
62 void sbuf_mem(struct sbuf *sbuf, char *s, int len)
64 if (sbuf->s_n + len + 1 >= sbuf->s_sz)
65 sbuf_extend(sbuf, ALIGN(sbuf->s_n + len + 1, SBUFSZ));
66 memcpy(sbuf->s + sbuf->s_n, s, len);
67 sbuf->s_n += len;
70 void sbuf_str(struct sbuf *sbuf, char *s)
72 sbuf_mem(sbuf, s, strlen(s));
75 int sbuf_len(struct sbuf *sbuf)
77 return sbuf->s_n;
80 void sbuf_cut(struct sbuf *sb, int len)
82 if (sb->s_n > len)
83 sb->s_n = len;
86 void sbuf_printf(struct sbuf *sbuf, char *s, ...)
88 char buf[256];
89 va_list ap;
90 va_start(ap, s);
91 vsnprintf(buf, sizeof(buf), s, ap);
92 va_end(ap);
93 sbuf_str(sbuf, buf);