aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHolden Rohrer <hr@hrhr.dev>2020-03-30 02:10:05 -0400
committerHolden Rohrer <hr@hrhr.dev>2020-03-30 02:10:05 -0400
commitfb604ec3a0ffa3b4bc878bab374fdb8f0b6c919f (patch)
treee010fe24489d8654fe1efd00bce0c8d0675c33c1
parent5331b7c6c4ab6522ae27d9e439a3e2fe451829ec (diff)
queue-like string buffer (undocumented)
-rw-r--r--buf.c123
-rw-r--r--buf.h16
2 files changed, 82 insertions, 57 deletions
diff --git a/buf.c b/buf.c
index eb1655e..b76fa0b 100644
--- a/buf.c
+++ b/buf.c
@@ -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;
}
-
diff --git a/buf.h b/buf.h
index 7323b83..808cd3f 100644
--- a/buf.h
+++ b/buf.h
@@ -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