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 #ifndef BYTE_BUFFER_H_
7 #define BYTE_BUFFER_H_
8 
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <sys/param.h>
12 
13 struct byte_buffer {
14 	unsigned int write_idx;
15 	unsigned int read_idx;
16 	unsigned int level;
17 	unsigned int max_size;
18 	unsigned int used_size;
19 	uint8_t bytes[];
20 };
21 
22 /* Create a byte buffer to hold buffer_size_bytes worth of data. */
byte_buffer_create(size_t buffer_size_bytes)23 static inline struct byte_buffer *byte_buffer_create(size_t buffer_size_bytes)
24 {
25 	struct byte_buffer *buf;
26 	buf = (struct byte_buffer *)calloc(1, sizeof(struct byte_buffer) +
27 						      buffer_size_bytes);
28 	if (!buf)
29 		return buf;
30 	buf->max_size = buffer_size_bytes;
31 	buf->used_size = buffer_size_bytes;
32 	return buf;
33 }
34 
byte_buffer_set_used_size(struct byte_buffer * buf,size_t used_size)35 static inline void byte_buffer_set_used_size(struct byte_buffer *buf,
36 					     size_t used_size)
37 {
38 	buf->used_size = MIN(used_size, buf->max_size);
39 }
40 
41 /* Destory a byte_buffer created with byte_buffer_create. */
byte_buffer_destroy(struct byte_buffer ** buf)42 static inline void byte_buffer_destroy(struct byte_buffer **buf)
43 {
44 	free(*buf);
45 	*buf = NULL;
46 }
47 
buf_writable(struct byte_buffer * buf)48 static inline unsigned int buf_writable(struct byte_buffer *buf)
49 {
50 	if (buf->level >= buf->used_size)
51 		return 0;
52 	if (buf->write_idx < buf->read_idx)
53 		return buf->read_idx - buf->write_idx;
54 
55 	return buf->used_size - buf->write_idx;
56 }
57 
buf_readable(struct byte_buffer * buf)58 static inline unsigned int buf_readable(struct byte_buffer *buf)
59 {
60 	if (buf->level == 0)
61 		return 0;
62 
63 	if (buf->read_idx < buf->write_idx)
64 		return buf->write_idx - buf->read_idx;
65 
66 	return buf->used_size - buf->read_idx;
67 }
68 
69 /* Adjust readable size to given value. Use with caution. */
buf_adjust_readable(struct byte_buffer * buf,size_t readable)70 static inline unsigned int buf_adjust_readable(struct byte_buffer *buf,
71 					       size_t readable)
72 {
73 	buf->level = MIN(readable, buf->used_size);
74 	buf->write_idx = (buf->read_idx + buf->level) % buf->used_size;
75 	return 0;
76 }
77 
buf_queued(struct byte_buffer * buf)78 static inline unsigned int buf_queued(struct byte_buffer *buf)
79 {
80 	return buf->level;
81 }
82 
buf_available(const struct byte_buffer * buf)83 static inline unsigned int buf_available(const struct byte_buffer *buf)
84 {
85 	return buf->used_size - buf->level;
86 }
87 
buf_read_pointer(struct byte_buffer * buf)88 static inline uint8_t *buf_read_pointer(struct byte_buffer *buf)
89 {
90 	return &buf->bytes[buf->read_idx];
91 }
92 
buf_read_pointer_size(struct byte_buffer * buf,unsigned int * readable)93 static inline uint8_t *buf_read_pointer_size(struct byte_buffer *buf,
94 					     unsigned int *readable)
95 {
96 	*readable = buf_readable(buf);
97 	return buf_read_pointer(buf);
98 }
99 
buf_increment_read(struct byte_buffer * buf,size_t inc)100 static inline void buf_increment_read(struct byte_buffer *buf, size_t inc)
101 {
102 	inc = MIN(inc, buf->level);
103 	buf->read_idx += inc;
104 	buf->read_idx %= buf->used_size;
105 	buf->level -= inc;
106 }
107 
buf_write_pointer(struct byte_buffer * buf)108 static inline uint8_t *buf_write_pointer(struct byte_buffer *buf)
109 {
110 	return &buf->bytes[buf->write_idx];
111 }
112 
buf_write_pointer_size(struct byte_buffer * buf,unsigned int * writeable)113 static inline uint8_t *buf_write_pointer_size(struct byte_buffer *buf,
114 					      unsigned int *writeable)
115 {
116 	*writeable = buf_writable(buf);
117 	return buf_write_pointer(buf);
118 }
119 
buf_increment_write(struct byte_buffer * buf,size_t inc)120 static inline void buf_increment_write(struct byte_buffer *buf, size_t inc)
121 {
122 	buf->write_idx += inc;
123 	buf->write_idx %= buf->used_size;
124 	if (buf->level + inc < buf->used_size)
125 		buf->level += inc;
126 	else
127 		buf->level = buf->used_size;
128 }
129 
buf_reset(struct byte_buffer * buf)130 static inline void buf_reset(struct byte_buffer *buf)
131 {
132 	buf->write_idx = 0;
133 	buf->read_idx = 0;
134 	buf->level = 0;
135 }
136 
137 #endif /* BYTE_BUFFER_H_ */
138