/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef BYTE_BUFFER_H_ #define BYTE_BUFFER_H_ #include #include #include struct byte_buffer { unsigned int write_idx; unsigned int read_idx; unsigned int level; unsigned int max_size; unsigned int used_size; uint8_t bytes[]; }; /* Create a byte buffer to hold buffer_size_bytes worth of data. */ static inline struct byte_buffer *byte_buffer_create(size_t buffer_size_bytes) { struct byte_buffer *buf; buf = (struct byte_buffer *)calloc(1, sizeof(struct byte_buffer) + buffer_size_bytes); if (!buf) return buf; buf->max_size = buffer_size_bytes; buf->used_size = buffer_size_bytes; return buf; } static inline void byte_buffer_set_used_size(struct byte_buffer *buf, size_t used_size) { buf->used_size = MIN(used_size, buf->max_size); } /* Destory a byte_buffer created with byte_buffer_create. */ static inline void byte_buffer_destroy(struct byte_buffer **buf) { free(*buf); *buf = NULL; } static inline unsigned int buf_writable(struct byte_buffer *buf) { if (buf->level >= buf->used_size) return 0; if (buf->write_idx < buf->read_idx) return buf->read_idx - buf->write_idx; return buf->used_size - buf->write_idx; } static inline unsigned int buf_readable(struct byte_buffer *buf) { if (buf->level == 0) return 0; if (buf->read_idx < buf->write_idx) return buf->write_idx - buf->read_idx; return buf->used_size - buf->read_idx; } /* Adjust readable size to given value. Use with caution. */ static inline unsigned int buf_adjust_readable(struct byte_buffer *buf, size_t readable) { buf->level = MIN(readable, buf->used_size); buf->write_idx = (buf->read_idx + buf->level) % buf->used_size; return 0; } static inline unsigned int buf_queued(struct byte_buffer *buf) { return buf->level; } static inline unsigned int buf_available(const struct byte_buffer *buf) { return buf->used_size - buf->level; } static inline uint8_t *buf_read_pointer(struct byte_buffer *buf) { return &buf->bytes[buf->read_idx]; } static inline uint8_t *buf_read_pointer_size(struct byte_buffer *buf, unsigned int *readable) { *readable = buf_readable(buf); return buf_read_pointer(buf); } static inline void buf_increment_read(struct byte_buffer *buf, size_t inc) { inc = MIN(inc, buf->level); buf->read_idx += inc; buf->read_idx %= buf->used_size; buf->level -= inc; } static inline uint8_t *buf_write_pointer(struct byte_buffer *buf) { return &buf->bytes[buf->write_idx]; } static inline uint8_t *buf_write_pointer_size(struct byte_buffer *buf, unsigned int *writeable) { *writeable = buf_writable(buf); return buf_write_pointer(buf); } static inline void buf_increment_write(struct byte_buffer *buf, size_t inc) { buf->write_idx += inc; buf->write_idx %= buf->used_size; if (buf->level + inc < buf->used_size) buf->level += inc; else buf->level = buf->used_size; } static inline void buf_reset(struct byte_buffer *buf) { buf->write_idx = 0; buf->read_idx = 0; buf->level = 0; } #endif /* BYTE_BUFFER_H_ */