summaryrefslogtreecommitdiffstats
path: root/src/commonlib/include/commonlib/iobuf.h
blob: 472b3687b58e6b0547609de8072f1875658f33b1 (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
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef COMMONLIB_IOBUF_H
#define COMMONLIB_IOBUF_H

#include <stdint.h>
#include <sys/types.h>

/*
 * Two types are provided to aid in dealing with automatic buffer management
 * for code that deals with serializing and deserializing data structures.
 * The ibuf (input buffer) is read from while the obuf (output buffer) is
 * written to. Both keep track of capacity of the buffer as well as current
 * read or write cursor.
 *
 * When splicing or splitting ibufs of obufs the source object doesn't track
 * reads or writes through the newly created objects back to the source object.
 *
 * Any function returning an int encodes the return values as < 0 on error
 * and 0 on success. Any function returning a pointer returns NULL on error
 * and non-NULL on success.
 */

struct ibuf {
	const uint8_t *b;
	size_t n_read;
	size_t capacity;
};

struct obuf {
	uint8_t *b;
	size_t n_written;
	size_t capacity;
};

/* Helper functions. */
static inline size_t ibuf_capacity(const struct ibuf *ib)
{
	return ib->capacity;
}

static inline size_t ibuf_nr_read(const struct ibuf *ib)
{
	return ib->n_read;
}

static inline size_t ibuf_remaining(const struct ibuf *ib)
{
	return ibuf_capacity(ib) - ibuf_nr_read(ib);
}

static inline size_t obuf_capacity(const struct obuf *ob)
{
	return ob->capacity;
}

static inline size_t obuf_nr_written(const struct obuf *ob)
{
	return ob->n_written;
}

static inline size_t obuf_remaining(const struct obuf *ob)
{
	return obuf_capacity(ob) - obuf_nr_written(ob);
}

/* Initialize an ibuf with buffer and size of data. */
void ibuf_init(struct ibuf *ib, const void *b, size_t sz);

/* Create a new ibuf based on a subregion of the src ibuf. */
int ibuf_splice(const struct ibuf *src, struct ibuf *dst, size_t off,
		size_t sz);

/* Same as ibuf_splice(), but start from last read byte offset. */
int ibuf_splice_current(const struct ibuf *src, struct ibuf *dst, size_t sz);

/* Split an ibuf into 2 new ibufs at provided boundary. */
int ibuf_split(const struct ibuf *src, struct ibuf *a, struct ibuf *b,
		size_t boundary);

/* Out-of-band drain of ibuf by returning pointer to data of specified size. */
const void *ibuf_oob_drain(struct ibuf *ib, size_t sz);

/* Read arbitray data from input buffer. */
int ibuf_read(struct ibuf *ib, void *data, size_t sz);

/* Read big endian fixed size values. */
int ibuf_read_be8(struct ibuf *ib, uint8_t *v);
int ibuf_read_be16(struct ibuf *ib, uint16_t *v);
int ibuf_read_be32(struct ibuf *ib, uint32_t *v);
int ibuf_read_be64(struct ibuf *ib, uint64_t *v);

/* Read little endian fixed size values. */
int ibuf_read_le8(struct ibuf *ib, uint8_t *v);
int ibuf_read_le16(struct ibuf *ib, uint16_t *v);
int ibuf_read_le32(struct ibuf *ib, uint32_t *v);
int ibuf_read_le64(struct ibuf *ib, uint64_t *v);

/* Read native endian fixed size values. */
int ibuf_read_n8(struct ibuf *ib, uint8_t *v);
int ibuf_read_n16(struct ibuf *ib, uint16_t *v);
int ibuf_read_n32(struct ibuf *ib, uint32_t *v);
int ibuf_read_n64(struct ibuf *ib, uint64_t *v);

/* Helper to create an ibuf from an obuf after an entity has written data. */
void ibuf_from_obuf(struct ibuf *ib, const struct obuf *ob);

/* Initialize an obuf with buffer and maximum capacity. */
void obuf_init(struct obuf *ob, void *b, size_t sz);

/* Provide the buffer and size of the written contents. */
const void *obuf_contents(const struct obuf *ob, size_t *sz);

/* Create a new obuf based on a subregion of the src obuf. */
int obuf_splice(const struct obuf *src, struct obuf *dst, size_t off,
		size_t sz);

/* Same as obuf_splice(), but start from last written byte offset. */
int obuf_splice_current(const struct obuf *src, struct obuf *dst, size_t sz);

/* Split an obuf into 2 new obufs at provided boundary. */
int obuf_split(const struct obuf *src, struct obuf *a, struct obuf *b,
		size_t boundary);

/* Fill the buffer out-of-band. The size is accounted for. */
void *obuf_oob_fill(struct obuf *ob, size_t sz);

/* Write arbitray data to output buffer. */
int obuf_write(struct obuf *ob, const void *data, size_t sz);

/* Write big endian fixed size values. */
int obuf_write_be8(struct obuf *ob, uint8_t v);
int obuf_write_be16(struct obuf *ob, uint16_t v);
int obuf_write_be32(struct obuf *ob, uint32_t v);
int obuf_write_be64(struct obuf *ob, uint64_t v);

/* Write little endian fixed size values. */
int obuf_write_le8(struct obuf *ob, uint8_t v);
int obuf_write_le16(struct obuf *ob, uint16_t v);
int obuf_write_le32(struct obuf *ob, uint32_t v);
int obuf_write_le64(struct obuf *ob, uint64_t v);

/* Write native endian fixed size values. */
int obuf_write_n8(struct obuf *ob, uint8_t v);
int obuf_write_n16(struct obuf *ob, uint16_t v);
int obuf_write_n32(struct obuf *ob, uint32_t v);
int obuf_write_n64(struct obuf *ob, uint64_t v);

#endif