Add extern "C" to more header files.
[sliver-openvswitch.git] / extras / ezio / byteq.c
1 /* Copyright (c) 2008, 2009 Nicira Networks, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17 #include "extras/ezio/byteq.h"
18 #include <assert.h>
19 #include <errno.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include "util.h"
23
24 /* The queue size must be a power of 2. */
25 BUILD_ASSERT_DECL(!(BYTEQ_SIZE & (BYTEQ_SIZE - 1)));
26
27 static uint8_t *head(struct byteq *);
28 static int headroom(const struct byteq *);
29 static void advance_head(struct byteq *, unsigned int n);
30 static int tailroom(const struct byteq *);
31 static const uint8_t *tail(const struct byteq *);
32 static void advance_tail(struct byteq *, unsigned int n);
33
34 /* Initializes 'q' as empty. */
35 void
36 byteq_init(struct byteq *q)
37 {
38     q->head = q->tail = 0;
39 }
40
41 /* Returns the number of bytes current queued in 'q'. */
42 int
43 byteq_used(const struct byteq *q)
44 {
45     return q->head - q->tail;
46 }
47
48 /* Returns the number of bytes that can be added to 'q' without overflow. */
49 int
50 byteq_avail(const struct byteq *q)
51 {
52     return BYTEQ_SIZE - byteq_used(q);
53 }
54
55 /* Returns true if no bytes are queued in 'q',
56  * false if at least one byte is queued.  */
57 bool
58 byteq_is_empty(const struct byteq *q)
59 {
60     return !byteq_used(q);
61 }
62
63 /* Returns true if 'q' has no room to queue additional bytes,
64  * false if 'q' has room for at least one more byte.  */
65 bool
66 byteq_is_full(const struct byteq *q)
67 {
68     return !byteq_avail(q);
69 }
70
71 /* Adds 'c' at the head of 'q', which must not be full. */
72 void
73 byteq_put(struct byteq *q, uint8_t c)
74 {
75     assert(!byteq_is_full(q));
76     *head(q) = c;
77     q->head++;
78 }
79
80 /* Adds the 'n' bytes in 'p' at the head of 'q', which must have at least 'n'
81  * bytes of free space. */
82 void
83 byteq_putn(struct byteq *q, const void *p_, size_t n)
84 {
85     const uint8_t *p = p_;
86     assert(byteq_avail(q) >= n);
87     while (n > 0) {
88         size_t chunk = MIN(n, headroom(q));
89         memcpy(head(q), p, chunk);
90         advance_head(q, chunk);
91         p += chunk;
92         n -= chunk;
93     }
94 }
95
96 /* Appends null-terminated string 's' to the head of 'q', which must have
97  * enough space.  The null terminator is not added to 'q'. */
98 void
99 byteq_put_string(struct byteq *q, const char *s)
100 {
101     byteq_putn(q, s, strlen(s));
102 }
103
104 /* Removes a byte from the tail of 'q' and returns it.  'q' must not be
105  * empty. */
106 uint8_t
107 byteq_get(struct byteq *q)
108 {
109     uint8_t c;
110     assert(!byteq_is_empty(q));
111     c = *tail(q);
112     q->tail++;
113     return c;
114 }
115
116 /* Writes as much of 'q' as possible to 'fd'.  Returns 0 if 'q' is fully
117  * drained by the write, otherwise a positive errno value (e.g. EAGAIN if a
118  * socket or tty buffer filled up). */
119 int
120 byteq_write(struct byteq *q, int fd)
121 {
122     while (!byteq_is_empty(q)) {
123         ssize_t n = write(fd, tail(q), tailroom(q));
124         if (n > 0) {
125             advance_tail(q, n);
126         } else {
127             assert(n < 0);
128             return errno;
129         }
130     }
131     return 0;
132 }
133
134 /* Reads as much possible from 'fd' into 'q'.  Returns 0 if 'q' is completely
135  * filled up by the read, EOF if end-of-file was reached before 'q' was filled,
136  * and otherwise a positive errno value (e.g. EAGAIN if a socket or tty buffer
137  * was drained). */
138 int
139 byteq_read(struct byteq *q, int fd)
140 {
141     while (!byteq_is_full(q)) {
142         ssize_t n = read(fd, head(q), headroom(q));
143         if (n > 0) {
144             advance_head(q, n);
145         } else {
146             return !n ? EOF : errno;
147         }
148     }
149     return 0;
150 }
151 \f
152 /* Returns the number of contiguous bytes of in-use space starting at the tail
153  * of 'q'. */
154 static int
155 tailroom(const struct byteq *q)
156 {
157     int used = byteq_used(q);
158     int tail_to_end = BYTEQ_SIZE - (q->tail & (BYTEQ_SIZE - 1));
159     return MIN(used, tail_to_end);
160 }
161
162 /* Returns the first in-use byte of 'q', the point at which data is removed
163  * from 'q'. */
164 static const uint8_t *
165 tail(const struct byteq *q)
166 {
167     return &q->buffer[q->tail & (BYTEQ_SIZE - 1)];
168 }
169
170 /* Removes 'n' bytes from the tail of 'q', which must have at least 'n' bytes
171  * of tailroom. */
172 static void
173 advance_tail(struct byteq *q, unsigned int n)
174 {
175     assert(tailroom(q) >= n);
176     q->tail += n;
177 }
178
179 /* Returns the byte after the last in-use byte of 'q', the point at which new
180  * data will be added to 'q'. */
181 static uint8_t *
182 head(struct byteq *q)
183 {
184     return &q->buffer[q->head & (BYTEQ_SIZE - 1)];
185 }
186
187 /* Returns the number of contiguous bytes of free space starting at the head
188  * of 'q'. */
189 static int
190 headroom(const struct byteq *q)
191 {
192     int avail = byteq_avail(q);
193     int head_to_end = BYTEQ_SIZE - (q->head & (BYTEQ_SIZE - 1));
194     return MIN(avail, head_to_end);
195 }
196
197 /* Adds to 'q' the 'n' bytes after the last currently in-use byte of 'q'.  'q'
198  * must have at least 'n' bytes of headroom. */
199 static void
200 advance_head(struct byteq *q, unsigned int n)
201 {
202     assert(headroom(q) >= n);
203     q->head += n;
204 }