diff options
author | Holden Rohrer <hr@hrhr.dev> | 2020-03-30 02:10:05 -0400 |
---|---|---|
committer | Holden Rohrer <hr@hrhr.dev> | 2020-03-30 02:10:05 -0400 |
commit | fb604ec3a0ffa3b4bc878bab374fdb8f0b6c919f (patch) | |
tree | e010fe24489d8654fe1efd00bce0c8d0675c33c1 | |
parent | 5331b7c6c4ab6522ae27d9e439a3e2fe451829ec (diff) |
queue-like string buffer (undocumented)
-rw-r--r-- | buf.c | 123 | ||||
-rw-r--r-- | buf.h | 16 |
2 files changed, 82 insertions, 57 deletions
@@ -1,82 +1,109 @@ #include <stdlib.h> +#include <stdio.h> +#include <string.h> #include "buf.h" -int max(int a, int b){ - if (a > b) return a; - return b; -} -int min(int a, int b){ - if (a < b) return a; - return b; -} +#define min(a,b) (a<b) ? a : b struct buf_node{ char* text; - size_t space; struct buf_node* next; - struct buf_node* prev; }; struct buf{ buf_node* head; buf_node* tail; size_t cap; -}; - -buf* newbuf(size_t cap){ - buf* buffer = malloc(sizeof(buf)); - buffer->cap = cap; - buffer->tail = buffer->head = newbufnode(cap); - return buffer; -} + size_t ins; + size_t pop; +}; // a "thick" linked list (buffered for mem efficiency) buf_node* newbufnode(size_t cap){ - buf_node* bufnode = calloc(sizeof(buf_node)); + buf_node* bufnode = malloc(sizeof(buf_node)); bufnode->text = malloc(sizeof(char)*cap); return bufnode; } -void bextendbuf(buf* buffer){ - buffer->tail = buffer->tail->prev->next - = buffer->tail->prev = newbufnode(); -} - -void fextendbuf(buf* buffer){ - buffer->head = buffer->head->next->prev - = buffer->head->next = newbufnode(); +buf* newbuf(size_t cap){ + buf* buffer = malloc(sizeof(buf)); + buffer->tail = buffer->head = newbufnode(cap); + buffer->cap = cap; + buffer->ins = buffer->pop = 0; + return buffer; } -void addchrbuf(buf* buffer, char chr){ // front - buf_node* head = buffer->head - if (head->space < 0 || head->space == buffer->cap) - fextendbuf(buffer); - *(head->text + head->space) = chr; - head->space++; -} -void addstrbuf(buf* buffer, char* str){ - +size_t buflen(buf* buffer){ + buf_node* cur = buffer->tail; + size_t size = buffer->ins-buffer->pop+buffer->cap; + while (cur != buffer->head) { + cur = cur->next; // skips one iter ^^^ + size += buffer->cap; + }; + return size; } -char remchrbuf(buf* buffer){ +void extendbuf(buf* buffer){ + buffer->head->next = newbufnode(buffer->cap); + buffer->head = buffer->head->next; + // buffer->ins = 0 is taken care of in the function that uses this. } -char* remchrbuf(buf* buffer, int ct){ +void shortenbuf(buf* buffer){ + buf_node* tmp = buffer->tail; + buffer->tail = buffer->tail->next; + free(tmp); + buffer->pop = 0; } -void prechrbuf(buf* buffer, char chr){ // back - +char popchrbuf(buf* buffer){ + if (buffer->pop == buffer->cap) shortenbuf(buffer); + buffer->pop++; + return buffer->tail->text[buffer->pop-1]; } -void prestrbuf(buf* buffer, char* str){ - +char* popstrbuf(buf* buffer, size_t ct){ + char* str = malloc((ct+1)*sizeof(char)); str[ct] = 0; + size_t rem; + for (size_t loc = 0; ct>loc; loc += rem){ + if (buffer->pop == buffer->cap) shortenbuf(buffer); + rem = min(buffer->cap, ct-loc); + memcpy(str+loc, buffer->tail->text+buffer->pop, rem); + buffer->pop += rem; + } /* probably some inefficiencies here*/ + return str; } -char shfchrbuf(buf* buffer){ +void inschrbuf(buf* buffer, char chr){ + if (buffer->ins == buffer->cap) extendbuf(buffer); + buffer->cap++; + buffer->head->text[buffer->cap-1] = chr; } -char* shfstrbuf(buf* buffer, int ct){ - +void insstrbuf(buf* buffer, char* str){ + size_t len = strlen(str); + size_t tgt = min(len, buffer->cap - buffer->ins); + memcpy(buffer->head->text+buffer->ins, str, tgt); + buffer->ins += len; + buffer->ins %= buffer->cap; + for (;tgt<len; tgt += buffer->cap){ + extendbuf(buffer); + memcpy(buffer->head->text, str+tgt, min(len-tgt, buffer->cap)); + } } -char* strpeekbuf(buf* buffer, int loc, int len){ - +char* strpeekbuf(buf* buffer, size_t loc, size_t len){ + char* str = malloc(sizeof(char)*(len+1)); str[len] = 0; + buf_node* start; + + loc += buffer->ins; + for (start = buffer->tail; loc>0; + loc -= buffer->cap) + start = start->next; // start,loc is where one starts streaming + if (len > buffer->cap){ + memcpy(str, start->text+loc, buffer->cap-loc); + len -= buffer->cap - loc; + } + for (; len > buffer->cap; len -= buffer->cap ){ + memcpy(str, start->text, buffer->cap); + } + memcpy(str, start->text, len); + return str; } - @@ -6,16 +6,14 @@ typedef struct buf buf; buf* newbuf(size_t cap); -void addchrbuf(buf* buffer, char chr); // front -void addstrbuf(buf* buffer, char* str); -char remchrbuf(buf* buffer); -char* remstrbuf(buf* buffer, int ct); +size_t buflen(buf* buffer); -void prechrbuf(buf* buffer, char chr); // back -void prestrbuf(buf* buffer, char* str); -char shfchrbuf(buf* buffer); -char* shfstrbuf(buf* buffer, int ct); +char popchrbuf(buf* buffer); +char* popstrbuf(buf* buffer, size_t ct); -char* strpeekbuf(buf* buffer, int loc); +void inschrbuf(buf* buffer, char chr); +void insstrbuf(buf* buffer, char* str); + +char* strpeekbuf(buf* buffer, size_t loc, size_t len); #endif |