Branch data Line data Source code
1 : : /* Copyright (c) 2008, 2009, 2012, 2013 Nicira, 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 "byteq.h"
18 : : #include <errno.h>
19 : : #include <string.h>
20 : : #include <unistd.h>
21 : : #include "util.h"
22 : :
23 : : /* Initializes 'q' as an empty byteq that uses the 'size' bytes of 'buffer' to
24 : : * store data. 'size' must be a power of 2.
25 : : *
26 : : * The caller must ensure that 'buffer' remains available to the byteq as long
27 : : * as 'q' is in use. */
28 : : void
29 : 38467 : byteq_init(struct byteq *q, uint8_t *buffer, size_t size)
30 : : {
31 [ - + ]: 38467 : ovs_assert(is_pow2(size));
32 : 38467 : q->buffer = buffer;
33 : 38467 : q->size = size;
34 : 38467 : q->head = q->tail = 0;
35 : 38467 : }
36 : :
37 : : /* Returns the number of bytes current queued in 'q'. */
38 : : int
39 : 3790467 : byteq_used(const struct byteq *q)
40 : : {
41 : 3790467 : return q->head - q->tail;
42 : : }
43 : :
44 : : /* Returns the number of bytes that can be added to 'q' without overflow. */
45 : : int
46 : 1602708 : byteq_avail(const struct byteq *q)
47 : : {
48 : 1602708 : return q->size - byteq_used(q);
49 : : }
50 : :
51 : : /* Returns true if no bytes are queued in 'q',
52 : : * false if at least one byte is queued. */
53 : : bool
54 : 1196682 : byteq_is_empty(const struct byteq *q)
55 : : {
56 : 1196682 : return !byteq_used(q);
57 : : }
58 : :
59 : : /* Returns true if 'q' has no room to queue additional bytes,
60 : : * false if 'q' has room for at least one more byte. */
61 : : bool
62 : 86446 : byteq_is_full(const struct byteq *q)
63 : : {
64 : 86446 : return !byteq_avail(q);
65 : : }
66 : :
67 : : /* Adds 'c' at the head of 'q', which must not be full. */
68 : : void
69 : 0 : byteq_put(struct byteq *q, uint8_t c)
70 : : {
71 [ # # ]: 0 : ovs_assert(!byteq_is_full(q));
72 : 0 : *byteq_head(q) = c;
73 : 0 : q->head++;
74 : 0 : }
75 : :
76 : : /* Adds the 'n' bytes in 'p' at the head of 'q', which must have at least 'n'
77 : : * bytes of free space. */
78 : : void
79 : 0 : byteq_putn(struct byteq *q, const void *p_, size_t n)
80 : : {
81 : 0 : const uint8_t *p = p_;
82 [ # # ]: 0 : ovs_assert(byteq_avail(q) >= n);
83 [ # # ]: 0 : while (n > 0) {
84 [ # # ]: 0 : size_t chunk = MIN(n, byteq_headroom(q));
85 : 0 : memcpy(byteq_head(q), p, chunk);
86 : 0 : byteq_advance_head(q, chunk);
87 : 0 : p += chunk;
88 : 0 : n -= chunk;
89 : : }
90 : 0 : }
91 : :
92 : : /* Appends null-terminated string 's' to the head of 'q', which must have
93 : : * enough space. The null terminator is not added to 'q'. */
94 : : void
95 : 0 : byteq_put_string(struct byteq *q, const char *s)
96 : : {
97 : 0 : byteq_putn(q, s, strlen(s));
98 : 0 : }
99 : :
100 : : /* Removes a byte from the tail of 'q' and returns it. 'q' must not be
101 : : * empty. */
102 : : uint8_t
103 : 0 : byteq_get(struct byteq *q)
104 : : {
105 : : uint8_t c;
106 [ # # ]: 0 : ovs_assert(!byteq_is_empty(q));
107 : 0 : c = *byteq_tail(q);
108 : 0 : q->tail++;
109 : 0 : return c;
110 : : }
111 : :
112 : : /* Writes as much of 'q' as possible to 'fd'. Returns 0 if 'q' is fully
113 : : * drained by the write, otherwise a positive errno value (e.g. EAGAIN if a
114 : : * socket or tty buffer filled up). */
115 : : int
116 : 0 : byteq_write(struct byteq *q, int fd)
117 : : {
118 [ # # ]: 0 : while (!byteq_is_empty(q)) {
119 : 0 : ssize_t n = write(fd, byteq_tail(q), byteq_tailroom(q));
120 [ # # ]: 0 : if (n > 0) {
121 : 0 : byteq_advance_tail(q, n);
122 : : } else {
123 [ # # ]: 0 : ovs_assert(n < 0);
124 : 0 : return errno;
125 : : }
126 : : }
127 : 0 : return 0;
128 : : }
129 : :
130 : : /* Reads as much possible from 'fd' into 'q'. Returns 0 if 'q' is completely
131 : : * filled up by the read, EOF if end-of-file was reached before 'q' was filled,
132 : : * and otherwise a positive errno value (e.g. EAGAIN if a socket or tty buffer
133 : : * was drained). */
134 : : int
135 : 0 : byteq_read(struct byteq *q, int fd)
136 : : {
137 [ # # ]: 0 : while (!byteq_is_full(q)) {
138 : 0 : ssize_t n = read(fd, byteq_head(q), byteq_headroom(q));
139 [ # # ]: 0 : if (n > 0) {
140 : 0 : byteq_advance_head(q, n);
141 : : } else {
142 [ # # ]: 0 : return !n ? EOF : errno;
143 : : }
144 : : }
145 : 0 : return 0;
146 : : }
147 : :
148 : : /* Returns the number of contiguous bytes of in-use space starting at the tail
149 : : * of 'q'. */
150 : : int
151 : 991077 : byteq_tailroom(const struct byteq *q)
152 : : {
153 : 991077 : int used = byteq_used(q);
154 : 991077 : int tail_to_end = q->size - (q->tail & (q->size - 1));
155 : 991077 : return MIN(used, tail_to_end);
156 : : }
157 : :
158 : : /* Returns the first in-use byte of 'q', the point at which data is removed
159 : : * from 'q'. */
160 : : const uint8_t *
161 : 472543 : byteq_tail(const struct byteq *q)
162 : : {
163 : 472543 : return &q->buffer[q->tail & (q->size - 1)];
164 : : }
165 : :
166 : : /* Removes 'n' bytes from the tail of 'q', which must have at least 'n' bytes
167 : : * of tailroom. */
168 : : void
169 : 518534 : byteq_advance_tail(struct byteq *q, unsigned int n)
170 : : {
171 [ - + ]: 518534 : ovs_assert(byteq_tailroom(q) >= n);
172 : 518534 : q->tail += n;
173 : 518534 : }
174 : :
175 : : /* Returns the byte after the last in-use byte of 'q', the point at which new
176 : : * data will be added to 'q'. */
177 : : uint8_t *
178 : 974692 : byteq_head(struct byteq *q)
179 : : {
180 : 974692 : return &q->buffer[q->head & (q->size - 1)];
181 : : }
182 : :
183 : : /* Returns the number of contiguous bytes of free space starting at the head
184 : : * of 'q'. */
185 : : int
186 : 1516262 : byteq_headroom(const struct byteq *q)
187 : : {
188 : 1516262 : int avail = byteq_avail(q);
189 : 1516262 : int head_to_end = q->size - (q->head & (q->size - 1));
190 : 1516262 : return MIN(avail, head_to_end);
191 : : }
192 : :
193 : : /* Adds to 'q' the 'n' bytes after the last currently in-use byte of 'q'. 'q'
194 : : * must have at least 'n' bytes of headroom. */
195 : : void
196 : 541570 : byteq_advance_head(struct byteq *q, unsigned int n)
197 : : {
198 [ - + ]: 541570 : ovs_assert(byteq_headroom(q) >= n);
199 : 541570 : q->head += n;
200 : 541570 : }
|