1 /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <sys/param.h>
9
10 struct byte_buffer {
11 unsigned int write_idx;
12 unsigned int read_idx;
13 unsigned int level;
14 unsigned int max_size;
15 unsigned int used_size;
16 uint8_t bytes[];
17 };
18
19 /* Create a byte buffer to hold buffer_size_bytes worth of data. */
byte_buffer_create(size_t buffer_size_bytes)20 static inline struct byte_buffer *byte_buffer_create(size_t buffer_size_bytes)
21 {
22 struct byte_buffer *buf;
23 buf = (struct byte_buffer *)
24 calloc(1, sizeof(struct byte_buffer) + buffer_size_bytes);
25 if (!buf)
26 return buf;
27 buf->max_size = buffer_size_bytes;
28 buf->used_size = buffer_size_bytes;
29 return buf;
30 }
31
byte_buffer_set_used_size(struct byte_buffer * buf,size_t used_size)32 static inline void byte_buffer_set_used_size(struct byte_buffer *buf,
33 size_t used_size)
34 {
35 buf->used_size = MIN(used_size, buf->max_size);
36 }
37
38 /* Destory a byte_buffer created with byte_buffer_create. */
byte_buffer_destroy(struct byte_buffer * buf)39 static inline void byte_buffer_destroy(struct byte_buffer *buf)
40 {
41 free(buf);
42 }
43
buf_writable_bytes(struct byte_buffer * buf)44 static inline unsigned int buf_writable_bytes(struct byte_buffer *buf)
45 {
46 if (buf->level >= buf->used_size)
47 return 0;
48 if (buf->write_idx < buf->read_idx)
49 return buf->read_idx - buf->write_idx;
50
51 return buf->used_size - buf->write_idx;
52 }
53
buf_readable_bytes(struct byte_buffer * buf)54 static inline unsigned int buf_readable_bytes(struct byte_buffer *buf)
55 {
56 if (buf->level == 0)
57 return 0;
58
59 if (buf->read_idx < buf->write_idx)
60 return buf->write_idx - buf->read_idx;
61
62 return buf->used_size - buf->read_idx;
63 }
64
buf_queued_bytes(struct byte_buffer * buf)65 static inline unsigned int buf_queued_bytes(struct byte_buffer *buf)
66 {
67 return buf->level;
68 }
69
buf_available_bytes(const struct byte_buffer * buf)70 static inline unsigned int buf_available_bytes(const struct byte_buffer *buf)
71 {
72 return buf->used_size - buf->level;
73 }
74
buf_read_pointer(struct byte_buffer * buf)75 static inline uint8_t *buf_read_pointer(struct byte_buffer *buf)
76 {
77 return &buf->bytes[buf->read_idx];
78 }
79
buf_read_pointer_size(struct byte_buffer * buf,unsigned int * readable)80 static inline uint8_t *buf_read_pointer_size(struct byte_buffer *buf,
81 unsigned int *readable)
82 {
83 *readable = buf_readable_bytes(buf);
84 return buf_read_pointer(buf);
85 }
86
buf_increment_read(struct byte_buffer * buf,size_t inc)87 static inline void buf_increment_read(struct byte_buffer *buf, size_t inc)
88 {
89 inc = MIN(inc, buf->level);
90 buf->read_idx += inc;
91 buf->read_idx %= buf->used_size;
92 buf->level -= inc;
93 }
94
buf_write_pointer(struct byte_buffer * buf)95 static inline uint8_t *buf_write_pointer(struct byte_buffer *buf)
96 {
97 return &buf->bytes[buf->write_idx];
98 }
99
buf_write_pointer_size(struct byte_buffer * buf,unsigned int * writeable)100 static inline uint8_t *buf_write_pointer_size(struct byte_buffer *buf,
101 unsigned int *writeable)
102 {
103 *writeable = buf_writable_bytes(buf);
104 return buf_write_pointer(buf);
105 }
106
buf_increment_write(struct byte_buffer * buf,size_t inc)107 static inline void buf_increment_write(struct byte_buffer *buf, size_t inc)
108 {
109 buf->write_idx += inc;
110 buf->write_idx %= buf->used_size;
111 if (buf->level + inc < buf->used_size)
112 buf->level += inc;
113 else
114 buf->level = buf->used_size;
115 }
116
buf_reset(struct byte_buffer * buf)117 static inline void buf_reset(struct byte_buffer *buf)
118 {
119 buf->write_idx = 0;
120 buf->read_idx = 0;
121 buf->level = 0;
122 }
123