blob: dd9cb2d0247ccd2b59334752ab896e77d3808bf7 [file] [log] [blame]
/* 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 <stdint.h>
#include <stdlib.h>
#include <sys/param.h>
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_ */