summaryrefslogtreecommitdiff
path: root/src/vf/string_buffer.c
blob: 28df6ae0b5be5bcd43bbaa14fde2413533206347 (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <stdlib.h>
#include <string.h>

#include <rte_log.h>
#include <rte_branch_prediction.h>

#include "string_buffer.h"

#define RTE_LOGTYPE_SPP_STRING_BUFF RTE_LOGTYPE_USER1

/* get message buffer capacity */
inline size_t
strbuf_get_capacity(const char *strbuf)
{
	return *((const size_t *)(strbuf - sizeof(size_t)));
}

/* re-allocate message buffer */
inline char*
strbuf_reallocate(char *strbuf, size_t required_len)
{
	size_t new_cap = strbuf_get_capacity(strbuf) * 2;
	char *new_strbuf = NULL;

	while (unlikely(new_cap <= required_len))
		new_cap *= 2;

	new_strbuf = spp_strbuf_allocate(new_cap);
	if (unlikely(new_strbuf == NULL))
		return NULL;

	strcpy(new_strbuf, strbuf);
	spp_strbuf_free(strbuf);

	return new_strbuf;
}

/* allocate message buffer */
char*
spp_strbuf_allocate(size_t capacity)
{
	char *buf = (char *)malloc(capacity + sizeof(size_t));
	if (unlikely(buf == NULL))
		return NULL;

	memset(buf, 0x00, capacity + sizeof(size_t));
	*((size_t *)buf) = capacity;
	RTE_LOG(DEBUG, SPP_STRING_BUFF,
			";alloc  ; addr=%p; size=%lu; str= ; len=0;\n",
			buf + sizeof(size_t), capacity);

	return buf + sizeof(size_t);
}

/* free message buffer */
void
spp_strbuf_free(char *strbuf)
{
	if (likely(strbuf != NULL)) {
		RTE_LOG(DEBUG, SPP_STRING_BUFF,
				";free   ; addr=%p; size=%lu; str=%s; len=%lu;\n",
				strbuf, strbuf_get_capacity(strbuf),
				strbuf, strlen(strbuf));
		free(strbuf - sizeof(size_t));
	}
}

/* append message to buffer */
char*
spp_strbuf_append(char *strbuf, const char *append, size_t append_len)
{
	size_t cap = strbuf_get_capacity(strbuf);
	size_t len = strlen(strbuf);
	char *new_strbuf = strbuf;

	if (unlikely(len + append_len >= cap)) {
		new_strbuf = strbuf_reallocate(strbuf, len + append_len);
		if (unlikely(new_strbuf == NULL))
			return NULL;
	}

	memcpy(new_strbuf + len, append, append_len);
	*(new_strbuf + len + append_len) = '\0';
	RTE_LOG(DEBUG, SPP_STRING_BUFF,
			";append ; addr=%p; size=%lu; str=%s; len=%lu;\n",
			new_strbuf, strbuf_get_capacity(new_strbuf),
			new_strbuf, strlen(new_strbuf));

	return new_strbuf;
}

/* remove message from front */
char*
spp_strbuf_remove_front(char *strbuf, size_t remove_len)
{
	size_t len = strlen(strbuf);
	size_t new_len = len - remove_len;

	if (likely(new_len == 0)) {
		*strbuf = '\0';
		return strbuf;
	}

	return memmove(strbuf, strbuf + remove_len, new_len + 1);
}