-
Notifications
You must be signed in to change notification settings - Fork 3
/
sbuf.c
117 lines (99 loc) · 2.59 KB
/
sbuf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* Copyright: Pádraig Brady 2005
* Summary: Variable length strings
* License: LGPL
* History:
* 10 Nov 2005 : Initial version
* 29 Nov 2005 : Made portable to early/non gcc
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sbuf.h"
static void sbuf_init(sbuf_t *sb) {
sb->buf = NULL;
sb->NUL = 0;
sb->buflen = 0;
}
sbuf_t *sbuf_new() {
sbuf_t *sb = malloc(sizeof(*sb));
if (!sb) abort(); //out of mem
sbuf_init(sb);
return sb;
}
void sbuf_delete(sbuf_t *sb) {
free(sb->buf);
free(sb);
}
void sbuf_reset(sbuf_t *sb) {
sb->NUL = 0;
}
char *sbuf_ptr(sbuf_t *sb) {
return sb->NUL ? sb->buf : "";
}
int sbuf_len(sbuf_t *sb) {
return sb->NUL;
}
char *sbuf_detach(sbuf_t *sb) {
char* buf = sb->buf;
if (!buf) buf = strdup("");
sbuf_init(sb);
return buf;
}
void sbuf_move(sbuf_t *src, sbuf_t *dest) {
free(dest->buf);
dest->buf = src->buf;
dest->NUL = src->NUL;
dest->buflen = src->buflen;
sbuf_init(src);
}
void sbuf_truncate(sbuf_t *sb, int len) {
if (len < 0 || len > sb->NUL)
return;
sb->NUL = len;
if (sb->buf)
sb->buf[sb->NUL] = '\0';
}
/* Extend the buffer in sb by at least len bytes.
* Note len should include the space required for the NUL terminator */
static void sbuf_extendby(sbuf_t *sb, int len) {
len = sb->NUL;
if (len <= sb->buflen) return;
if (!sb->buflen) sb->buflen=64; //min size (to alleviate fragmentation)
while (len > sb->buflen) sb->buflen *= 2;
char* buf = realloc(sb->buf, sb->buflen);
if (!buf) abort(); //out of mem
sb->buf = buf;
}
void sbuf_appendbytes(sbuf_t *sb, const char *str, int len) {
sbuf_extendby(sb, len 1);
memcpy(&sb->buf[sb->NUL], str, len);
sb->NUL = len;
sb->buf[sb->NUL] = '\0';
}
void sbuf_appendchar(sbuf_t *sb, char c) {
sbuf_extendby(sb, 2);
sb->buf[sb->NUL ] = c;
sb->buf[sb->NUL] = '\0';
}
void sbuf_appendstr(sbuf_t *sb, const char *str) {
sbuf_appendbytes(sb, str, strlen(str));
}
static void sbuf_vappendf(sbuf_t *sb, const char *fmt, const va_list ap) {
int num_required;
while ((num_required = vsnprintf(sb->buf sb->NUL, sb->buflen-sb->NUL, fmt, ap)) >= sb->buflen-sb->NUL)
sbuf_extendby(sb, num_required 1);
sb->NUL = num_required;
}
void sbuf_printf(sbuf_t *sb, const char *fmt, ...) {
sbuf_reset(sb);
va_list ap;
va_start(ap, fmt);
sbuf_vappendf(sb, fmt, ap);
va_end(ap);
}
void sbuf_appendf(sbuf_t *sb, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
sbuf_vappendf(sb, fmt, ap);
va_end(ap);
}