From e0544300fb7da9a660a55eaf25f1996af573cd43 Mon Sep 17 00:00:00 2001
From: dec05eba <dec05eba@protonmail.com>
Date: Sun, 24 Feb 2019 20:01:58 +0100
Subject: Separate buffers from general allocation, but still have them in
 scoped allocator

---
 include/ast.h              |  1 +
 include/buffer.h           |  8 +++++---
 include/scoped_allocator.h |  8 ++++++--
 src/ast.c                  |  2 +-
 src/buffer.c               | 42 ++++++++++++++++++++++++++++--------------
 src/parser.c               |  2 +-
 src/scoped_allocator.c     | 19 +++++++++++++++++--
 7 files changed, 59 insertions(+), 23 deletions(-)

diff --git a/include/ast.h b/include/ast.h
index ef06257..f3580c0 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -4,6 +4,7 @@
 #include "buffer_view.h"
 #include "buffer.h"
 #include "misc.h"
+#include "scoped_allocator.h"
 
 typedef struct FunctionDecl FunctionDecl;
 typedef struct FunctionCall FunctionCall;
diff --git a/include/buffer.h b/include/buffer.h
index 700ae7b..e0c4046 100644
--- a/include/buffer.h
+++ b/include/buffer.h
@@ -1,19 +1,21 @@
 #ifndef AMALGAM_BUFFER_H
 #define AMALGAM_BUFFER_H
 
-#include "scoped_allocator.h"
+#include "types.h"
+#include "misc.h"
 
 #define BUFFER_OK 0
 #define BUFFER_ALLOC_FAIL -1
 
 typedef struct {
-    ScopedAllocator *allocator;
+    struct ScopedAllocator *allocator;
     char* data;
     usize size;
     usize capacity;
 } Buffer;
 
-CHECK_RESULT int buffer_init(Buffer *self, ScopedAllocator *allocator, usize initial_capacity);
+CHECK_RESULT int buffer_init(Buffer *self, struct ScopedAllocator *allocator);
+void buffer_deinit(Buffer *self);
 
 CHECK_RESULT int buffer_append(Buffer *self, void *data, usize size);
 void* buffer_get(Buffer *self, usize index, usize type_size);
diff --git a/include/scoped_allocator.h b/include/scoped_allocator.h
index 1193439..fdaee2a 100644
--- a/include/scoped_allocator.h
+++ b/include/scoped_allocator.h
@@ -3,8 +3,10 @@
 
 #include "misc.h"
 #include "types.h"
+#include "buffer.h"
 
 typedef struct ScopedAllocatorNode ScopedAllocatorNode;
+typedef struct ScopedAllocator ScopedAllocator;
 
 struct ScopedAllocatorNode {
     char *data;
@@ -12,10 +14,11 @@ struct ScopedAllocatorNode {
     ScopedAllocatorNode *next;
 };
 
-typedef struct {
+struct ScopedAllocator {
     ScopedAllocatorNode head;
     ScopedAllocatorNode *current;
-} ScopedAllocator;
+    Buffer buffers;
+};
 
 CHECK_RESULT int scoped_allocator_node_init(ScopedAllocatorNode *self);
 void scoped_allocator_node_deinit(ScopedAllocatorNode *self);
@@ -23,5 +26,6 @@ void scoped_allocator_node_deinit(ScopedAllocatorNode *self);
 CHECK_RESULT int scoped_allocator_init(ScopedAllocator *self);
 void scoped_allocator_deinit(ScopedAllocator *self);
 CHECK_RESULT int scoped_allocator_alloc(ScopedAllocator *self, usize size, void **mem);
+CHECK_RESULT int scoped_allocator_add_buffer(ScopedAllocator *self, Buffer *buffer);
 
 #endif
\ No newline at end of file
diff --git a/src/ast.c b/src/ast.c
index 2802c3b..3ea4fe1 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -9,7 +9,7 @@ Ast ast_none() {
 
 int funcdecl_init(FunctionDecl *self, ScopedAllocator *allocator) {
     self->name = create_buffer_view_null();
-    return buffer_init(&self->body, allocator, sizeof(Ast) * 4);
+    return buffer_init(&self->body, allocator);
 }
 
 int funcdecl_add_to_body(FunctionDecl *self, Ast ast) {
diff --git a/src/buffer.c b/src/buffer.c
index ad50771..349c186 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1,41 +1,55 @@
 #include "../include/buffer.h"
 #include "../include/alloc.h"
 #include "../include/mem.h"
+#include "../include/scoped_allocator.h"
 #include <assert.h>
 
-int buffer_init(Buffer *self, ScopedAllocator *allocator, usize initial_capacity) {
+int buffer_init(Buffer *self, ScopedAllocator *allocator) {
+    self->data = NULL;
+    self->size = 0;
+    self->capacity = 0;
     self->allocator = allocator;
+    if(self->allocator)
+        return scoped_allocator_add_buffer(self->allocator, self);
+    return 0;
+}
+
+void buffer_deinit(Buffer *self) {
+    am_free(self->data);
+    self->data = NULL;
     self->size = 0;
-    self->capacity = initial_capacity;
-    return scoped_allocator_alloc(self->allocator, initial_capacity, (void**)&self->data);
+    self->capacity = 0;
 }
 
-static CHECK_RESULT int buffer_ensure_capacity_for(Buffer *self, usize size) {
+static CHECK_RESULT int buffer_ensure_capacity(Buffer *self, usize new_capacity) {
+    usize capacity;
     void *new_mem;
     int alloc_result;
-    usize new_capacity;
-    new_capacity = self->size + size;
 
     if(self->capacity >= new_capacity)
         return BUFFER_OK;
     
-    /*
-    We are using alloc here instead of realloc because we are using scoped allocator
-    which doesn't reallocate. TODO: Verify if scoped allocator node size is enough to hold buffers...
-    */
-    alloc_result = scoped_allocator_alloc(self->allocator, new_capacity, &new_mem);
+    capacity = self->capacity;
+    if(capacity == 0) {
+        capacity = new_capacity;
+    } else {
+        while(capacity < new_capacity) {
+            capacity *= 1.5;
+        }
+    }
+
+    alloc_result = am_realloc(self->data, capacity, &new_mem);
     if(alloc_result != ALLOC_OK)
         return BUFFER_ALLOC_FAIL;
     
     self->data = new_mem;
-    self->capacity = new_capacity;
+    self->capacity = capacity;
     return BUFFER_OK;
 }
 
 int buffer_append(Buffer *self, void *data, usize size) {
-    return_if_error(buffer_ensure_capacity_for(self, size));
+    return_if_error(buffer_ensure_capacity(self, self->size + size));
     am_memcpy(self->data + self->size, data, size);
-    self->size += size;
     return BUFFER_OK; 
 }
 
diff --git a/src/parser.c b/src/parser.c
index 6a1c796..78b0018 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -8,7 +8,7 @@ static CHECK_RESULT int parser_parse_body(Parser *self, Ast *ast);
 
 int parser_init(Parser *self) {
     return_if_error(scoped_allocator_init(&self->allocator));
-    return_if_error(buffer_init(&self->ast_objects, &self->allocator, sizeof(Ast) * 8));
+    return_if_error(buffer_init(&self->ast_objects, &self->allocator));
     return PARSER_OK;
 }
 
diff --git a/src/scoped_allocator.c b/src/scoped_allocator.c
index cbf1aad..7e2cb0d 100644
--- a/src/scoped_allocator.c
+++ b/src/scoped_allocator.c
@@ -2,7 +2,7 @@
 #include "../include/alloc.h"
 #include <assert.h>
 
-#define ALLOC_NODE_SIZE 65536
+#define ALLOC_NODE_SIZE 4096
 
 int scoped_allocator_node_init(ScopedAllocatorNode *self) {
     self->data = NULL;
@@ -25,11 +25,22 @@ void scoped_allocator_node_deinit(ScopedAllocatorNode *self) {
 int scoped_allocator_init(ScopedAllocator *self) {
     return_if_error(scoped_allocator_node_init(&self->head));
     self->current = &self->head;
-    return 0;
+    return buffer_init(&self->buffers, NULL);
 }
+
 void scoped_allocator_deinit(ScopedAllocator *self) {
+    Buffer *buffer;
+    Buffer *buffer_end;
+
     scoped_allocator_node_deinit(&self->head);
     self->current = NULL;
+    buffer = (Buffer*)&self->buffers.data[0];
+    buffer_end = buffer + self->buffers.size / sizeof(Buffer);
+    while(buffer != buffer_end) {
+        buffer_deinit(buffer);
+        ++buffer;
+    }
+    buffer_deinit(&self->buffers);
 }
 
 static CHECK_RESULT int scoped_allocator_ensure_capacity_for(ScopedAllocator *self, usize size) {
@@ -57,4 +68,8 @@ int scoped_allocator_alloc(ScopedAllocator *self, usize size, void **mem) {
     *mem = &self->current->data[self->current->size];
     self->current->size += size;
     return 0;
+}
+
+int scoped_allocator_add_buffer(ScopedAllocator *self, Buffer *buffer) {
+    return buffer_append(&self->buffers, buffer, sizeof(buffer));
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2