#include #include #include #include "libaco/aco.h" struct aco_list { aco_t *co; int fd; struct aco_list *next, *prev; }; struct aco_list *aco_list_new () { struct aco_list *head = malloc (sizeof (struct aco_list)); memset (head, 0, sizeof (struct aco_list)); head->next = head->prev = head; return head; } struct aco_list *aco_list_add (struct aco_list *head, aco_t *co) { struct aco_list *node = malloc (sizeof (struct aco_list)); node->co = co; node->prev = head->prev; node->next = head; head->prev = node; return node; } void aco_list_remove (struct aco_list *iter) { if (iter->next == iter) abort(); iter->prev->next = iter->next; iter->next->prev = iter->prev; } #define SBO_BUF_SMALL 0x80 #define SBO_BUF_BIG 0x00 #define SBO_BUF_MASK 0x80 #define SBO_BUF_SIZEMASK 0x7f #define SBO_BUF_SMALL_MAX_SIZE 0x7f /* 0x80 - 0x1 */ typedef struct sbo_buf { unsigned char hdr; union { char small[SBO_BUF_SMALL_MAX_SIZE]; struct { char *base; size_t size; size_t alloc; } big; } buf; } sbo_buf_t; int sbo_buf_init (sbo_buf_t *buf, char *init, size_t count); void sbo_buf_free (sbo_buf_t *buf); char *sbo_buf_mem (sbo_buf_t *buf); size_t sbo_buf_size (sbo_buf_t *buf); int sbo_buf_type (sbo_buf_t *buf); int sbo_buf_grow (sbo_buf_t *buf, char *grow, size_t count); int sbo_buf_init0 (sbo_buf_t *buf) { memset (buf, 0, sizeof (*buf)); buf->hdr = 0 | SBO_BUF_SMALL; return 0; } int sbo_buf_init (sbo_buf_t *buf, char *init, size_t count) { if (count <= (size_t)SBO_BUF_SMALL_MAX_SIZE) { buf->hdr = 0 | SBO_BUF_SMALL; buf->hdr |= (unsigned char) count; memcpy (buf->buf.small, init, count); } else { buf->buf.big.base = malloc (count); if (!buf->buf.big.base) return errno; buf->hdr = 0 | SBO_BUF_BIG; buf->buf.big.size = count; buf->buf.big.alloc = count; } return 0; } void sbo_buf_free (sbo_buf_t *buf) { if (sbo_buf_type (buf) == SBO_BUF_BIG) free (buf->buf.big.base); } inline char *sbo_buf_mem (sbo_buf_t *buf) { if (sbo_buf_type (buf) == SBO_BUF_BIG) return buf->buf.big.base; return buf->buf.small; } inline size_t sbo_buf_size (sbo_buf_t *buf) { if (sbo_buf_type (buf) == SBO_BUF_BIG) return buf->buf.big.size; return buf->hdr & SBO_BUF_SIZEMASK; } inline int sbo_buf_type (sbo_buf_t *buf) { return buf->hdr & SBO_BUF_MASK; } int sbo_buf_grow (sbo_buf_t *buf, char *grow, size_t count) { if (count == 0) return 0; //size_t bufsize = sbo_buf_size (buf); if (sbo_buf_type (buf) == SBO_BUF_SMALL) { size_t current_size = sbo_buf_size (buf); if (current_size + count <= (size_t)SBO_BUF_SMALL_MAX_SIZE) { /* no need to become big. just concat two existing buffers */ char *dst = sbo_buf_mem (buf) + current_size; memcpy (dst, grow, count); buf->hdr += count; return 0; } /* fallthrough to realloc */ } char *base = sbo_buf_mem (buf); size_t len = sbo_buf_size (buf); char *newbuf = malloc (len + count); if (!newbuf) return errno; memcpy (newbuf, base, len); memcpy (newbuf + len, grow, count); sbo_buf_free (buf); buf->hdr = 0 | SBO_BUF_BIG; /* We definitely exceeded small buffer */ buf->buf.big.base = newbuf; buf->buf.big.alloc = len + count; buf->buf.big.size = len + count; return 0; }