#ifndef BUFFER_H #define BUFFER_H #include #include /** * buffer.c - buffer con acceso directo (útil para I/O) que mantiene * mantiene puntero de lectura y de escritura. * * * Para esto se mantienen dos punteros, uno de lectura * y otro de escritura, y se provee funciones para * obtener puntero base y capacidad disponibles. * * R=0 * ↓ * +---+---+---+---+---+---+ * | | | | | | | * +---+---+---+---+---+---+ * ↑ ↑ * W=0 limit=6 * * Invariantes: * R <= W <= limit * * Se quiere escribir en el bufer cuatro bytes. * * ptr + 0 <- buffer_write_ptr(b, &wbytes), wbytes=6 * n = read(fd, ptr, wbytes) * buffer_write_adv(b, n = 4) * * R=0 * ↓ * +---+---+---+---+---+---+ * | H | O | L | A | | | * +---+---+---+---+---+---+ * ↑ ↑ * W=4 limit=6 * * Quiero leer 3 del buffer * ptr + 0 <- buffer_read_ptr, wbytes=4 * buffer_read_adv(b, 3); * * R=3 * ↓ * +---+---+---+---+---+---+ * | H | O | L | A | | | * +---+---+---+---+---+---+ * ↑ ↑ * W=4 limit=6 * * Quiero escribir 2 bytes mas * ptr + 4 <- buffer_write_ptr(b, &wbytes=2); * buffer_write_adv(b, 2) * * R=3 * ↓ * +---+---+---+---+---+---+ * | H | O | L | A | | M | * +---+---+---+---+---+---+ * ↑ * limit=6 * W=4 * Compactación a demanda * R=0 * ↓ * +---+---+---+---+---+---+ * | A | | M | | | | * +---+---+---+---+---+---+ * ↑ ↑ * W=3 limit=6 * * Leo los tres bytes, como R == W, se auto compacta. * * R=0 * ↓ * +---+---+---+---+---+---+ * | | | | | | | * +---+---+---+---+---+---+ * ↑ ↑ * W=0 limit=6 */ typedef struct buffer buffer; struct buffer { uint8_t * data; /** límite superior del buffer. inmutable */ uint8_t * limit; /** puntero de lectura */ uint8_t * read; /** puntero de escritura */ uint8_t * write; }; /** * inicializa el buffer sin utilizar el heap */ void buffer_init(buffer * b, const size_t n, uint8_t * data); /** * Retorna un puntero donde se pueden escribir hasta `*nbytes`. * Se debe notificar mediante la función `buffer_write_adv' */ uint8_t * buffer_write_ptr(buffer * b, size_t * nbyte); void buffer_write_adv(buffer * b, const ssize_t bytes); uint8_t * buffer_read_ptr(buffer * b, size_t * nbyte); void buffer_read_adv(buffer *b, const ssize_t bytes); /** * obtiene un byte */ uint8_t buffer_read(buffer * b); /** escribe un byte */ void buffer_write(buffer * b, uint8_t c); /** * compacta el buffer */ void buffer_compact(buffer * b); /** * Reinicia todos los punteros */ void buffer_reset(buffer * b); /** retorna true si hay bytes para leer del buffer */ bool buffer_can_read(buffer * b); /** retorna true si se pueden escribir bytes en el buffer */ bool buffer_can_write(buffer *b); #endif