From: Ben Pfaff Date: Wed, 28 Oct 2009 18:06:31 +0000 (-0700) Subject: byteq: Move from extras/ezio into lib and export some private functions. X-Git-Tag: v1.0.0~259^2~525 X-Git-Url: http://git.cascardo.eti.br/?a=commitdiff_plain;h=1c617a495fdc6bb91e29bf00df4c837f63d63199;p=cascardo%2Fovs.git byteq: Move from extras/ezio into lib and export some private functions. The upcoming JSON-RPC library wants to use this library, and it needs some functions that are currently declared static. --- diff --git a/extras/ezio/automake.mk b/extras/ezio/automake.mk index 7c7db2412..eae11cd15 100644 --- a/extras/ezio/automake.mk +++ b/extras/ezio/automake.mk @@ -25,8 +25,6 @@ install-data-hook: bin_PROGRAMS += extras/ezio/ezio-term extras_ezio_ezio_term_SOURCES = \ - extras/ezio/byteq.c \ - extras/ezio/byteq.h \ extras/ezio/ezio-term.c \ extras/ezio/ezio.c \ extras/ezio/ezio.h \ diff --git a/extras/ezio/byteq.c b/extras/ezio/byteq.c deleted file mode 100644 index b7df400fd..000000000 --- a/extras/ezio/byteq.c +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (c) 2008, 2009 Nicira Networks, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "extras/ezio/byteq.h" -#include -#include -#include -#include -#include "util.h" - -/* The queue size must be a power of 2. */ -BUILD_ASSERT_DECL(!(BYTEQ_SIZE & (BYTEQ_SIZE - 1))); - -static uint8_t *head(struct byteq *); -static int headroom(const struct byteq *); -static void advance_head(struct byteq *, unsigned int n); -static int tailroom(const struct byteq *); -static const uint8_t *tail(const struct byteq *); -static void advance_tail(struct byteq *, unsigned int n); - -/* Initializes 'q' as empty. */ -void -byteq_init(struct byteq *q) -{ - q->head = q->tail = 0; -} - -/* Returns the number of bytes current queued in 'q'. */ -int -byteq_used(const struct byteq *q) -{ - return q->head - q->tail; -} - -/* Returns the number of bytes that can be added to 'q' without overflow. */ -int -byteq_avail(const struct byteq *q) -{ - return BYTEQ_SIZE - byteq_used(q); -} - -/* Returns true if no bytes are queued in 'q', - * false if at least one byte is queued. */ -bool -byteq_is_empty(const struct byteq *q) -{ - return !byteq_used(q); -} - -/* Returns true if 'q' has no room to queue additional bytes, - * false if 'q' has room for at least one more byte. */ -bool -byteq_is_full(const struct byteq *q) -{ - return !byteq_avail(q); -} - -/* Adds 'c' at the head of 'q', which must not be full. */ -void -byteq_put(struct byteq *q, uint8_t c) -{ - assert(!byteq_is_full(q)); - *head(q) = c; - q->head++; -} - -/* Adds the 'n' bytes in 'p' at the head of 'q', which must have at least 'n' - * bytes of free space. */ -void -byteq_putn(struct byteq *q, const void *p_, size_t n) -{ - const uint8_t *p = p_; - assert(byteq_avail(q) >= n); - while (n > 0) { - size_t chunk = MIN(n, headroom(q)); - memcpy(head(q), p, chunk); - advance_head(q, chunk); - p += chunk; - n -= chunk; - } -} - -/* Appends null-terminated string 's' to the head of 'q', which must have - * enough space. The null terminator is not added to 'q'. */ -void -byteq_put_string(struct byteq *q, const char *s) -{ - byteq_putn(q, s, strlen(s)); -} - -/* Removes a byte from the tail of 'q' and returns it. 'q' must not be - * empty. */ -uint8_t -byteq_get(struct byteq *q) -{ - uint8_t c; - assert(!byteq_is_empty(q)); - c = *tail(q); - q->tail++; - return c; -} - -/* Writes as much of 'q' as possible to 'fd'. Returns 0 if 'q' is fully - * drained by the write, otherwise a positive errno value (e.g. EAGAIN if a - * socket or tty buffer filled up). */ -int -byteq_write(struct byteq *q, int fd) -{ - while (!byteq_is_empty(q)) { - ssize_t n = write(fd, tail(q), tailroom(q)); - if (n > 0) { - advance_tail(q, n); - } else { - assert(n < 0); - return errno; - } - } - return 0; -} - -/* Reads as much possible from 'fd' into 'q'. Returns 0 if 'q' is completely - * filled up by the read, EOF if end-of-file was reached before 'q' was filled, - * and otherwise a positive errno value (e.g. EAGAIN if a socket or tty buffer - * was drained). */ -int -byteq_read(struct byteq *q, int fd) -{ - while (!byteq_is_full(q)) { - ssize_t n = read(fd, head(q), headroom(q)); - if (n > 0) { - advance_head(q, n); - } else { - return !n ? EOF : errno; - } - } - return 0; -} - -/* Returns the number of contiguous bytes of in-use space starting at the tail - * of 'q'. */ -static int -tailroom(const struct byteq *q) -{ - int used = byteq_used(q); - int tail_to_end = BYTEQ_SIZE - (q->tail & (BYTEQ_SIZE - 1)); - return MIN(used, tail_to_end); -} - -/* Returns the first in-use byte of 'q', the point at which data is removed - * from 'q'. */ -static const uint8_t * -tail(const struct byteq *q) -{ - return &q->buffer[q->tail & (BYTEQ_SIZE - 1)]; -} - -/* Removes 'n' bytes from the tail of 'q', which must have at least 'n' bytes - * of tailroom. */ -static void -advance_tail(struct byteq *q, unsigned int n) -{ - assert(tailroom(q) >= n); - q->tail += n; -} - -/* Returns the byte after the last in-use byte of 'q', the point at which new - * data will be added to 'q'. */ -static uint8_t * -head(struct byteq *q) -{ - return &q->buffer[q->head & (BYTEQ_SIZE - 1)]; -} - -/* Returns the number of contiguous bytes of free space starting at the head - * of 'q'. */ -static int -headroom(const struct byteq *q) -{ - int avail = byteq_avail(q); - int head_to_end = BYTEQ_SIZE - (q->head & (BYTEQ_SIZE - 1)); - return MIN(avail, head_to_end); -} - -/* Adds to 'q' the 'n' bytes after the last currently in-use byte of 'q'. 'q' - * must have at least 'n' bytes of headroom. */ -static void -advance_head(struct byteq *q, unsigned int n) -{ - assert(headroom(q) >= n); - q->head += n; -} diff --git a/extras/ezio/byteq.h b/extras/ezio/byteq.h deleted file mode 100644 index 0a016cd54..000000000 --- a/extras/ezio/byteq.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2008, 2009 Nicira Networks, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef BYTEQ_H -#define BYTEQ_H 1 - -#include -#include -#include - -/* Maximum number of bytes in a byteq. */ -#define BYTEQ_SIZE 512 - -/* General-purpose circular queue of bytes. */ -struct byteq { - uint8_t buffer[BYTEQ_SIZE]; /* Circular queue. */ - unsigned int head; /* Head of queue. */ - unsigned int tail; /* Chases the head. */ -}; - -void byteq_init(struct byteq *); -int byteq_used(const struct byteq *); -int byteq_avail(const struct byteq *); -bool byteq_is_empty(const struct byteq *); -bool byteq_is_full(const struct byteq *); -void byteq_put(struct byteq *, uint8_t c); -void byteq_putn(struct byteq *, const void *, size_t n); -void byteq_put_string(struct byteq *, const char *); -uint8_t byteq_get(struct byteq *); -int byteq_write(struct byteq *, int fd); -int byteq_read(struct byteq *, int fd); - -#endif /* byteq.h */ diff --git a/extras/ezio/ezio-term.c b/extras/ezio/ezio-term.c index 846ccfded..8f12a7bc4 100644 --- a/extras/ezio/ezio-term.c +++ b/extras/ezio/ezio-term.c @@ -26,8 +26,8 @@ #include #include #include +#include "byteq.h" #include "command-line.h" -#include "extras/ezio/byteq.h" #include "extras/ezio/tty.h" #include "extras/ezio/vt.h" #include "daemon.h" diff --git a/lib/automake.mk b/lib/automake.mk index fd791c281..8dc289906 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -14,6 +14,8 @@ lib_libopenvswitch_a_SOURCES = \ lib/backtrace.h \ lib/bitmap.c \ lib/bitmap.h \ + lib/byteq.c \ + lib/byteq.h \ lib/cfg.c \ lib/cfg.h \ lib/classifier.c \ diff --git a/lib/byteq.c b/lib/byteq.c new file mode 100644 index 000000000..aa1e06f71 --- /dev/null +++ b/lib/byteq.c @@ -0,0 +1,197 @@ +/* Copyright (c) 2008, 2009 Nicira Networks, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "byteq.h" +#include +#include +#include +#include +#include "util.h" + +/* The queue size must be a power of 2. */ +BUILD_ASSERT_DECL(!(BYTEQ_SIZE & (BYTEQ_SIZE - 1))); + +/* Initializes 'q' as empty. */ +void +byteq_init(struct byteq *q) +{ + q->head = q->tail = 0; +} + +/* Returns the number of bytes current queued in 'q'. */ +int +byteq_used(const struct byteq *q) +{ + return q->head - q->tail; +} + +/* Returns the number of bytes that can be added to 'q' without overflow. */ +int +byteq_avail(const struct byteq *q) +{ + return BYTEQ_SIZE - byteq_used(q); +} + +/* Returns true if no bytes are queued in 'q', + * false if at least one byte is queued. */ +bool +byteq_is_empty(const struct byteq *q) +{ + return !byteq_used(q); +} + +/* Returns true if 'q' has no room to queue additional bytes, + * false if 'q' has room for at least one more byte. */ +bool +byteq_is_full(const struct byteq *q) +{ + return !byteq_avail(q); +} + +/* Adds 'c' at the head of 'q', which must not be full. */ +void +byteq_put(struct byteq *q, uint8_t c) +{ + assert(!byteq_is_full(q)); + *byteq_head(q) = c; + q->head++; +} + +/* Adds the 'n' bytes in 'p' at the head of 'q', which must have at least 'n' + * bytes of free space. */ +void +byteq_putn(struct byteq *q, const void *p_, size_t n) +{ + const uint8_t *p = p_; + assert(byteq_avail(q) >= n); + while (n > 0) { + size_t chunk = MIN(n, byteq_headroom(q)); + memcpy(byteq_head(q), p, chunk); + byteq_advance_head(q, chunk); + p += chunk; + n -= chunk; + } +} + +/* Appends null-terminated string 's' to the head of 'q', which must have + * enough space. The null terminator is not added to 'q'. */ +void +byteq_put_string(struct byteq *q, const char *s) +{ + byteq_putn(q, s, strlen(s)); +} + +/* Removes a byte from the tail of 'q' and returns it. 'q' must not be + * empty. */ +uint8_t +byteq_get(struct byteq *q) +{ + uint8_t c; + assert(!byteq_is_empty(q)); + c = *byteq_tail(q); + q->tail++; + return c; +} + +/* Writes as much of 'q' as possible to 'fd'. Returns 0 if 'q' is fully + * drained by the write, otherwise a positive errno value (e.g. EAGAIN if a + * socket or tty buffer filled up). */ +int +byteq_write(struct byteq *q, int fd) +{ + while (!byteq_is_empty(q)) { + ssize_t n = write(fd, byteq_tail(q), byteq_tailroom(q)); + if (n > 0) { + byteq_advance_tail(q, n); + } else { + assert(n < 0); + return errno; + } + } + return 0; +} + +/* Reads as much possible from 'fd' into 'q'. Returns 0 if 'q' is completely + * filled up by the read, EOF if end-of-file was reached before 'q' was filled, + * and otherwise a positive errno value (e.g. EAGAIN if a socket or tty buffer + * was drained). */ +int +byteq_read(struct byteq *q, int fd) +{ + while (!byteq_is_full(q)) { + ssize_t n = read(fd, byteq_head(q), byteq_headroom(q)); + if (n > 0) { + byteq_advance_head(q, n); + } else { + return !n ? EOF : errno; + } + } + return 0; +} + +/* Returns the number of contiguous bytes of in-use space starting at the tail + * of 'q'. */ +int +byteq_tailroom(const struct byteq *q) +{ + int used = byteq_used(q); + int tail_to_end = BYTEQ_SIZE - (q->tail & (BYTEQ_SIZE - 1)); + return MIN(used, tail_to_end); +} + +/* Returns the first in-use byte of 'q', the point at which data is removed + * from 'q'. */ +const uint8_t * +byteq_tail(const struct byteq *q) +{ + return &q->buffer[q->tail & (BYTEQ_SIZE - 1)]; +} + +/* Removes 'n' bytes from the tail of 'q', which must have at least 'n' bytes + * of tailroom. */ +void +byteq_advance_tail(struct byteq *q, unsigned int n) +{ + assert(byteq_tailroom(q) >= n); + q->tail += n; +} + +/* Returns the byte after the last in-use byte of 'q', the point at which new + * data will be added to 'q'. */ +uint8_t * +byteq_head(struct byteq *q) +{ + return &q->buffer[q->head & (BYTEQ_SIZE - 1)]; +} + +/* Returns the number of contiguous bytes of free space starting at the head + * of 'q'. */ +int +byteq_headroom(const struct byteq *q) +{ + int avail = byteq_avail(q); + int head_to_end = BYTEQ_SIZE - (q->head & (BYTEQ_SIZE - 1)); + return MIN(avail, head_to_end); +} + +/* Adds to 'q' the 'n' bytes after the last currently in-use byte of 'q'. 'q' + * must have at least 'n' bytes of headroom. */ +void +byteq_advance_head(struct byteq *q, unsigned int n) +{ + assert(byteq_headroom(q) >= n); + q->head += n; +} diff --git a/lib/byteq.h b/lib/byteq.h new file mode 100644 index 000000000..84d8696fe --- /dev/null +++ b/lib/byteq.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2008, 2009 Nicira Networks, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BYTEQ_H +#define BYTEQ_H 1 + +#include +#include +#include + +/* Maximum number of bytes in a byteq. */ +#define BYTEQ_SIZE 512 + +/* General-purpose circular queue of bytes. */ +struct byteq { + uint8_t buffer[BYTEQ_SIZE]; /* Circular queue. */ + unsigned int head; /* Head of queue. */ + unsigned int tail; /* Chases the head. */ +}; + +void byteq_init(struct byteq *); +int byteq_used(const struct byteq *); +int byteq_avail(const struct byteq *); +bool byteq_is_empty(const struct byteq *); +bool byteq_is_full(const struct byteq *); +void byteq_put(struct byteq *, uint8_t c); +void byteq_putn(struct byteq *, const void *, size_t n); +void byteq_put_string(struct byteq *, const char *); +uint8_t byteq_get(struct byteq *); +int byteq_write(struct byteq *, int fd); +int byteq_read(struct byteq *, int fd); + +uint8_t *byteq_head(struct byteq *); +int byteq_headroom(const struct byteq *); +void byteq_advance_head(struct byteq *, unsigned int n); +int byteq_tailroom(const struct byteq *); +const uint8_t *byteq_tail(const struct byteq *); +void byteq_advance_tail(struct byteq *, unsigned int n); + +#endif /* byteq.h */