/* IRCfs - IRC FileServ for *nix. * Copyright (C) 2002 Nick 'Zaf' Clifford * For licensing details, refer to the LICENSE file in the source * code directory. */ #include "runtime.h" #include "circbuf.h" struct circbuf { POOL pool; char *buffer; size_t size; char *start, *end; }; struct circbuf *circbuf_create(POOL parent, size_t bytes) { POOL p; struct circbuf *cb; p = pool_new_n(parent,bytes + 64); cb = XMALLOC(p,struct circbuf); cb->pool = p; cb->buffer = (char *)palloc(cb->pool,(sizeof(char) * (bytes+1))); cb->start = cb->buffer; cb->end = cb->buffer; cb->size = bytes+1; return cb; } size_t circbuf_size(struct circbuf *cb) { return cb->size-1; } size_t circbuf_bytes(struct circbuf *cb) { if (cb->start <= cb->end) { return cb->end - cb->start; } else { /* size: 7 start: 6 end:3 * 2345678 * + + * ^ ^^^ * e s * start: 3 end: 7 * 2345678 * ^^^^ * s e */ return cb->size - (cb->start - cb->end); } } size_t circbuf_remaining(struct circbuf *cb) { if (cb->start > cb->end) { return (cb->start-cb->end)-1; } else if (cb->start == cb->end) { return cb->size -1; } else { return cb->size - (cb->end - cb->start) -1; } } int circbuf_resize(struct circbuf *cb, size_t newsize) { return -1; } int circbuf_add(struct circbuf *cb, const char *data, size_t size) { char *cp,*test; size_t count=0; cp = cb->end; if (size == 0) return 0; do { size--; test = cb->start-1; if (test < cb->buffer) test = cb->buffer + cb->size -1; if (cp == test) break; *cp = *data; cp++; data++; count++; if (cp >= cb->buffer + cb->size) cp = cb->buffer; } while(size); if (cp == test) return -1; cb->end = cp; return count; } int circbuf_get(struct circbuf *cb, char *data, size_t size) { char *cp; size_t count=0; cp = cb->start; while(size--) { if (cp == cb->end) break; *data = *cp; data++; cp++; count++; if (cp >= cb->buffer + cb->size) cp = cb->buffer; } cb->start = cp; return count; } int circbuf_get_till(struct circbuf *cb, char *data, size_t size, char ch) { char *cp,f=0; size_t count=0; cp = cb->start; while(size--) { if (cp == cb->end) break; f = *data = *cp; data++; cp++; count++; if (cp >= cb->buffer + cb->size) cp = cb->buffer; if (f == ch) break; } if (f != ch) return -1; cb->start = cp; return count; } int circbuf_find_ch(struct circbuf *cb, char ch) { char *cp; size_t count=0; cp = cb->start; while(*cp != ch) { if (cp == cb->end) break; cp++; count++; if (cp >= cb->buffer + cb->size) cp = cb->buffer; } if (*cp != ch) return -1; return count; } /* Get size bytes from buffer, but don't pop the bytes off */ int circbuf_peek(struct circbuf *cb, char *data, size_t size) { char *cp; size_t count=0; cp = cb->start; while(size--) { if (cp == cb->end) break; *data = *cp; data++; cp++; count++; if (cp >= cb->buffer + cb->size) cp = cb->buffer; } return count; } /* Manually pop size bytes from buffer */ int circbuf_pop(struct circbuf *cb, size_t size) { char *cp = cb->start; cp += size; while (cp > cb->buffer + cb->size) { cp = cp - cb->size; } cb->start = cp; return 0; } void circbuf_destroy(struct circbuf *cb) { pool_destroy(cb->pool); }