summaryrefslogtreecommitdiff
path: root/lib/stringbuf.c
blob: 548c745dc5b0599b186fbcff3c23222385b2887e (plain)
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
#include "system.h"

#include "stringbuf.h"

#define BUF_CHUNK 1024

struct StringBufRec {
    /*@owned@*/ char *buf;
    /*@dependent@*/ char *tail;     /* Points to first "free" char */
    int allocated;
    int free;
};

StringBuf newStringBuf(void)
{
    StringBuf sb = xmalloc(sizeof(struct StringBufRec));

    sb->free = sb->allocated = BUF_CHUNK;
    sb->buf = xcalloc(sb->allocated, sizeof(*sb->buf));
    sb->buf[0] = '\0';
    sb->tail = sb->buf;
    
    return sb;
}

void freeStringBuf(StringBuf sb)
{
    if (! sb) {
	return;
    }
    
    free(sb->buf);
    free(sb);
}

void truncStringBuf(StringBuf sb)
{
    sb->buf[0] = '\0';
    sb->tail = sb->buf;
    sb->free = sb->allocated;
}

void stripTrailingBlanksStringBuf(StringBuf sb)
{
    while (sb->free != sb->allocated) {
	if (! isspace(*(sb->tail - 1))) {
	    break;
	}
	sb->free++;
	sb->tail--;
    }
    sb->tail[0] = '\0';
}

char *getStringBuf(StringBuf sb)
{
    return sb->buf;
}

void appendStringBufAux(StringBuf sb, const char *s, int nl)
{
    int l;

    l = strlen(s);
    /* If free == l there is no room for NULL terminator! */
    while ((l + nl + 1) > sb->free) {
        sb->allocated += BUF_CHUNK;
	sb->free += BUF_CHUNK;
        sb->buf = xrealloc(sb->buf, sb->allocated);
	sb->tail = sb->buf + (sb->allocated - sb->free);
    }
    
    strcpy(sb->tail, s);
    sb->tail += l;
    sb->free -= l;
    if (nl) {
        sb->tail[0] = '\n';
        sb->tail[1] = '\0';
	sb->tail++;
	sb->free--;
    }
}