summaryrefslogtreecommitdiff
path: root/src/mbuf.h
blob: a5dbc39e67369faf61d1dce94437b1b8f3444242 (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
/*
 * Copyright (c) 2018-2019 Richard Braun.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Upstream site with license notes :
 * http://git.sceen.net/rbraun/librbraun.git/
 *
 *
 * FIFO message buffer.
 */

#ifndef MBUF_H
#define MBUF_H

#include <stdbool.h>
#include <stddef.h>

#include "cbuf.h"

/*
 * Message buffer.
 *
 * Message buffers are built on top of circular byte buffers. They provide
 * discrete message transfer from a producer to a consumer.
 *
 * The order is computed from the maximum message size, and is used to
 * determine a header size that can represent up to 2^order - 1 bytes.
 */
struct mbuf {
    struct cbuf cbuf;
    size_t max_msg_size;
    unsigned int order;
};

static inline size_t
mbuf_start(const struct mbuf *mbuf)
{
    return cbuf_start(&mbuf->cbuf);
}

static inline size_t
mbuf_end(const struct mbuf *mbuf)
{
    return cbuf_end(&mbuf->cbuf);
}

/*
 * Initialize a message buffer.
 *
 * The descriptor is set to use the given buffer for storage. Capacity
 * must be a power-of-two.
 */
void mbuf_init(struct mbuf *mbuf, void *buf, size_t capacity,
               size_t max_msg_size);

/*
 * Clear a message buffer.
 */
void mbuf_clear(struct mbuf *mbuf);

/*
 * Push a message to a message buffer.
 *
 * If the message doesn't fit in the message buffer, either because it is
 * larger than the capacity, or because the function isn't allowed to erase
 * old messages and the message buffer doesn't have enough available memory
 * for the new message, EMSGSIZE is returned. If the message is larger than
 * the maximum message size, EINVAL is returned.
 */
int mbuf_push(struct mbuf *mbuf, const void *buf, size_t size, bool erase);

/*
 * Pop a message from a message buffer.
 *
 * On entry, the sizep argument points to the size of the output buffer.
 * On return, it is updated to the size of the message. If the message
 * doesn't fit in the output buffer, it is not popped, EMSGSIZE is
 * returned, but the sizep argument is updated nonetheless to let the
 * user know the message size, to potentially retry with a larger buffer.
 *
 * If the buffer is empty, EAGAIN is returned, and the size of the output
 * buffer is unmodified.
 *
 * The output buffer may be NULL, in which case this function acts as if
 * it wasn't, but without writing output data.
 */
int mbuf_pop(struct mbuf *mbuf, void *buf, size_t *sizep);

/*
 * Read a message from a message buffer.
 *
 * On entry, the indexp argument points to the index of the message to
 * read in the message buffer, and the sizep argument points to the size
 * of the output buffer. On return, if successful, indexp is updated
 * to the index of the next message, and sizep to the size of the
 * message read.
 *
 * If the message doesn't fit in the output buffer, it is not read,
 * EMSGSIZE is returned, and the sizep argument is updated nonetheless
 * to let the user know the message size, to potentially retry with a
 * larger buffer.
 *
 * If the given index refers to the end of the buffer, then EAGAIN is
 * returned. If it's outside buffer boundaries, EINVAL is returned.
 * Otherwise, if it doesn't point to the beginning of a message, the
 * behavior is undefined.
 *
 * The message buffer isn't changed by this operation.
 */
int mbuf_read(const struct mbuf *mbuf, size_t *indexp,
              void *buf, size_t *sizep);

#endif /* MBUF_H */