/src/openvswitch/lib/byteq.c
Line | Count | Source (jump to first uncovered line) |
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 | | byteq_init(struct byteq *q, uint8_t *buffer, size_t size) |
30 | 0 | { |
31 | 0 | ovs_assert(is_pow2(size)); |
32 | 0 | q->buffer = buffer; |
33 | 0 | q->size = size; |
34 | 0 | q->head = q->tail = 0; |
35 | 0 | } |
36 | | |
37 | | /* Returns the number of bytes current queued in 'q'. */ |
38 | | int |
39 | | byteq_used(const struct byteq *q) |
40 | 0 | { |
41 | 0 | return q->head - q->tail; |
42 | 0 | } |
43 | | |
44 | | /* Returns the number of bytes that can be added to 'q' without overflow. */ |
45 | | int |
46 | | byteq_avail(const struct byteq *q) |
47 | 0 | { |
48 | 0 | return q->size - byteq_used(q); |
49 | 0 | } |
50 | | |
51 | | /* Returns true if no bytes are queued in 'q', |
52 | | * false if at least one byte is queued. */ |
53 | | bool |
54 | | byteq_is_empty(const struct byteq *q) |
55 | 0 | { |
56 | 0 | return !byteq_used(q); |
57 | 0 | } |
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 | | byteq_is_full(const struct byteq *q) |
63 | 0 | { |
64 | 0 | return !byteq_avail(q); |
65 | 0 | } |
66 | | |
67 | | /* Adds 'c' at the head of 'q', which must not be full. */ |
68 | | void |
69 | | byteq_put(struct byteq *q, uint8_t c) |
70 | 0 | { |
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 | | byteq_putn(struct byteq *q, const void *p_, size_t n) |
80 | 0 | { |
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 | 0 | } |
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 | | byteq_put_string(struct byteq *q, const char *s) |
96 | 0 | { |
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 | | byteq_get(struct byteq *q) |
104 | 0 | { |
105 | 0 | 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 | 0 | } |
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 | | byteq_write(struct byteq *q, int fd) |
117 | 0 | { |
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 | 0 | } else { |
123 | 0 | ovs_assert(n < 0); |
124 | 0 | return errno; |
125 | 0 | } |
126 | 0 | } |
127 | 0 | return 0; |
128 | 0 | } |
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 | | byteq_read(struct byteq *q, int fd) |
136 | 0 | { |
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 | 0 | } else { |
142 | 0 | return !n ? EOF : errno; |
143 | 0 | } |
144 | 0 | } |
145 | 0 | return 0; |
146 | 0 | } |
147 | | |
148 | | /* Returns the number of contiguous bytes of in-use space starting at the tail |
149 | | * of 'q'. */ |
150 | | int |
151 | | byteq_tailroom(const struct byteq *q) |
152 | 0 | { |
153 | 0 | int used = byteq_used(q); |
154 | 0 | int tail_to_end = q->size - (q->tail & (q->size - 1)); |
155 | 0 | return MIN(used, tail_to_end); |
156 | 0 | } |
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 | | byteq_tail(const struct byteq *q) |
162 | 0 | { |
163 | 0 | return &q->buffer[q->tail & (q->size - 1)]; |
164 | 0 | } |
165 | | |
166 | | /* Removes 'n' bytes from the tail of 'q', which must have at least 'n' bytes |
167 | | * of tailroom. */ |
168 | | void |
169 | | byteq_advance_tail(struct byteq *q, unsigned int n) |
170 | 0 | { |
171 | 0 | ovs_assert(byteq_tailroom(q) >= n); |
172 | 0 | q->tail += n; |
173 | 0 | } |
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 | | byteq_head(struct byteq *q) |
179 | 0 | { |
180 | 0 | return &q->buffer[q->head & (q->size - 1)]; |
181 | 0 | } |
182 | | |
183 | | /* Returns the number of contiguous bytes of free space starting at the head |
184 | | * of 'q'. */ |
185 | | int |
186 | | byteq_headroom(const struct byteq *q) |
187 | 0 | { |
188 | 0 | int avail = byteq_avail(q); |
189 | 0 | int head_to_end = q->size - (q->head & (q->size - 1)); |
190 | 0 | return MIN(avail, head_to_end); |
191 | 0 | } |
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 | | byteq_advance_head(struct byteq *q, unsigned int n) |
197 | 0 | { |
198 | 0 | ovs_assert(byteq_headroom(q) >= n); |
199 | 0 | q->head += n; |
200 | 0 | } |
201 | | |
202 | | /* Move the head and tail pointers forward to have the most headroom available. |
203 | | * Can only be used on an empty byteq. This is equivalent to advancing both |
204 | | * head and tail by the current headroom size. |
205 | | * Previous pointers returned by byteq_tail() or byteq_head() are potentially |
206 | | * invalid afterwards. */ |
207 | | void |
208 | | byteq_fast_forward(struct byteq *q) |
209 | 0 | { |
210 | 0 | ovs_assert(byteq_is_empty(q)); |
211 | 0 | unsigned int pos = q->head & (q->size - 1); |
212 | |
|
213 | 0 | if (pos) { |
214 | | /* Only advance head if we are not already at a multiple of size. */ |
215 | 0 | q->head += q->size - pos; |
216 | 0 | q->tail = q->head; |
217 | 0 | } |
218 | 0 | } |