bproxy/include/buffer.h

138 lines
3.1 KiB
C

#ifndef BUFFER_H
#define BUFFER_H
#include <stdbool.h>
#include <unistd.h>
/**
* 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