/* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2021 Free Software Foundation, Inc. * * VAS_EBOOT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VAS_EBOOT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VAS_EBOOT. If not, see . */ #ifndef VAS_EBOOT_BUFFER_H #define VAS_EBOOT_BUFFER_H 1 #include #include #include #include #include struct VasEBoot_buffer { VasEBoot_uint8_t *data; VasEBoot_size_t sz; VasEBoot_size_t pos; VasEBoot_size_t used; }; /* * VasEBoot_buffer_t represents a simple variable sized byte buffer with * read and write cursors. It currently only implements * functionality required by the only user in VAS_EBOOT (append byte[s], * peeking data at a specified position and updating the read cursor. * Some things that this doesn't do yet are: * - Reading a portion of the buffer by copying data from the current * read position in to a caller supplied destination buffer and then * automatically updating the read cursor. * - Dropping the read part at the start of the buffer when an append * requires more space. */ typedef struct VasEBoot_buffer *VasEBoot_buffer_t; /* Allocate a new buffer with the specified initial size. */ extern VasEBoot_buffer_t VasEBoot_buffer_new (VasEBoot_size_t sz); /* Free the buffer and its resources. */ extern void VasEBoot_buffer_free (VasEBoot_buffer_t buf); /* Return the number of unread bytes in this buffer. */ static inline VasEBoot_size_t VasEBoot_buffer_get_unread_bytes (VasEBoot_buffer_t buf) { return buf->used - buf->pos; } /* * Ensure that the buffer size is at least the requested * number of bytes. */ extern VasEBoot_err_t VasEBoot_buffer_ensure_space (VasEBoot_buffer_t buf, VasEBoot_size_t req); /* * Append the specified number of bytes from the supplied * data to the buffer. */ static inline VasEBoot_err_t VasEBoot_buffer_append_data (VasEBoot_buffer_t buf, const void *data, VasEBoot_size_t len) { VasEBoot_size_t req; if (VasEBoot_add (buf->used, len, &req)) return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_RANGE, N_("overflow is detected")); if (VasEBoot_buffer_ensure_space (buf, req) != VAS_EBOOT_ERR_NONE) return VasEBoot_errno; VasEBoot_memcpy (&buf->data[buf->used], data, len); buf->used = req; return VAS_EBOOT_ERR_NONE; } /* Append the supplied character to the buffer. */ static inline VasEBoot_err_t VasEBoot_buffer_append_char (VasEBoot_buffer_t buf, char c) { return VasEBoot_buffer_append_data (buf, &c, 1); } /* * Forget and return the underlying data buffer. The caller * becomes the owner of this buffer, and must free it when it * is no longer required. */ extern void *VasEBoot_buffer_take_data (VasEBoot_buffer_t buf); /* Reset this buffer. Note that this does not deallocate any resources. */ void VasEBoot_buffer_reset (VasEBoot_buffer_t buf); /* * Return a pointer to the underlying data buffer at the specified * offset from the current read position. Note that this pointer may * become invalid if the buffer is mutated further. */ static inline void * VasEBoot_buffer_peek_data_at (VasEBoot_buffer_t buf, VasEBoot_size_t off) { if (VasEBoot_add (buf->pos, off, &off)) { VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_RANGE, N_("overflow is detected")); return NULL; } if (off >= buf->used) { VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_RANGE, N_("peek out of range")); return NULL; } return &buf->data[off]; } /* * Return a pointer to the underlying data buffer at the current * read position. Note that this pointer may become invalid if the * buffer is mutated further. */ static inline void * VasEBoot_buffer_peek_data (VasEBoot_buffer_t buf) { return VasEBoot_buffer_peek_data_at (buf, 0); } /* Advance the read position by the specified number of bytes. */ extern VasEBoot_err_t VasEBoot_buffer_advance_read_pos (VasEBoot_buffer_t buf, VasEBoot_size_t n); #endif /* VAS_EBOOT_BUFFER_H */