File: buf.c

package info (click to toggle)
gsocket 1.4.43-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,224 kB
  • sloc: ansic: 14,009; sh: 3,629; makefile: 155
file content (130 lines) | stat: -rw-r--r-- 2,484 bytes parent folder | download | duplicates (2)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * A FIFO like buffer to. Used by file transfer as a write-buffer to queue
 * control messages (such as chn_accept, chn_error, ...).
 */
#include "gs-common.h"
#include <gsocket/gsocket.h>
#include "gs-externs.h"

void
GS_BUF_init(GS_BUF *gsb, size_t sz_max_add)
{
	memset(gsb, 0, sizeof *gsb);
	gsb->sz_max_add = sz_max_add;

	// gsb->sz_total = 16*1024*1024; // FIXME
	// gsb->data = malloc(gsb->sz_total); // FIXME

	GS_BUF_resize(gsb, 0);
}

void
GS_BUF_free(GS_BUF *gsb)
{
	XFREE(gsb->data);
	memset(gsb, 0, sizeof *gsb);
}

// Adjust size to have at least sz_min_free available.
int
GS_BUF_resize(GS_BUF *gsb, size_t sz_new)
{
	if (GS_BUF_UNUSED(gsb) >= sz_new + gsb->sz_max_add)
		return 0;

	size_t t = gsb->sz_used + sz_new + gsb->sz_max_add;
	// Round the new size to the next 1k boundary
	gsb->sz_total = t - (t % 1024) + 1024;
	DEBUGF_R("realloc to %zu, used %zu\n", gsb->sz_total, gsb->sz_used);
	gsb->data = realloc(gsb->data, gsb->sz_total);
	if (gsb->data == NULL)
	{
		// Fatal.
		GS_BUF_free(gsb);
		return -1;
	}

	return 0;
}

int
GS_BUF_add_length(GS_BUF *gsb, size_t len)
{
	// Bail. There is sz_max_add space available but looks like caller wrote
	// more data...
	XASSERT(len <= GS_BUF_UNUSED(gsb), "Not enough space in buffer\n");

	gsb->sz_used += len;

	// Resize
	GS_BUF_resize(gsb, 0);

	return 0;
}

int
GS_BUF_add_data(GS_BUF *gsb, void *data, size_t len)
{
	GS_BUF_resize(gsb, len);
	memcpy((uint8_t *)gsb->data + gsb->sz_used, data, len);

	gsb->sz_used += len;

	return 0;
}

int
GS_BUF_printf(GS_BUF *gsb, const char *fmt, ...)
{
	va_list ap;
	int rv;

	va_start(ap, fmt);
	rv = vsnprintf((char *)GS_BUF_WDST(gsb), GS_BUF_UNUSED(gsb), fmt, ap);
	va_end(ap);

	if (rv <= 0)
		return 0;

	if (rv >= GS_BUF_UNUSED(gsb))
	{
		// Make buffer larger...
		GS_BUF_resize(gsb, rv - GS_BUF_UNUSED(gsb) + 1 /*\0*/);
		va_start(ap, fmt);
		rv = vsnprintf((char *)GS_BUF_WDST(gsb), GS_BUF_UNUSED(gsb), fmt, ap);
		va_end(ap);

		if (rv <= 0)
			return 0;
	}

	gsb->sz_used += rv;
	GS_BUF_resize(gsb, 0);

	return 0;
}

int
GS_BUF_memmove(GS_BUF *gsb, void *data, size_t len)
{
	GS_BUF_resize(gsb, len);
	memmove((uint8_t *)gsb->data + gsb->sz_used, data, len);

	gsb->sz_used += len;

	return 0;
}

/*
 * Consume data from beginning.
 */
int
GS_BUF_del(GS_BUF *gsb, size_t len)
{
	XASSERT(gsb->sz_used >= len, "Cant. used=%zu, len=%zu\n", gsb->sz_used, len);
	gsb->sz_used -= len;
	memmove(gsb->data, (uint8_t *)gsb->data + len, gsb->sz_used);

	return 0;
}