beginnings of binaryout
[henge/apc.git] / src / pagenode.h
diff --git a/src/pagenode.h b/src/pagenode.h
new file mode 100644 (file)
index 0000000..8497f81
--- /dev/null
@@ -0,0 +1,88 @@
+#include <stdlib.h> //malloc
+
+extern //apc.c
+long sys_pagesize;
+
+#define SYS_PAGESIZE     (sys_pagesize)
+#define NAME_PAGESIZE    (APC_NAME_MAX * 1024)
+#define PL_HEADERSIZE    (sizeof(struct pagenode_header_t))
+#define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)
+#define PL_HEADMEM(_PL)  (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))
+#define  struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))
+/* Memory allocation structures */
+struct pagenode_t;
+struct pagenode_header_t {
+  struct pagenode_t* next;
+  char*              head;
+};
+struct pagenode_t {
+  struct pagenode_header_t header;
+  char                     root[];
+};
+struct pagelist_t {
+  struct pagenode_t* root, * head;
+  size_t             pagesize;
+};
+
+static
+void*    stack_alloc(struct pagelist_t*, size_t);
+static inline
+void*    pagelist_pop(struct pagelist_t*,size_t);
+#define $($)#$
+#define  pagelist_alloc(pagelist) do {                                 \
+    pagelist.head->header.next = (struct pagenode_t*) malloc(pagelist.pagesize); \
+    if (pagelist.head->header.next == NULL)                            \
+      eprintf("Memory allocation error\n");                            \
+    struct_clear(pagelist.head->header.next);                          \
+    pagelist.head = pagelist.head->header.next;                                \
+    pagelist.head->header.head = pagelist.head->root;                  \
+  } while (0)
+#define  pagelist_init(pagelist,size) do {                     \
+    pagelist.pagesize = size;                                  \
+    pagelist.root = (struct pagenode_t*) malloc(size);         \
+    if (pagelist.root == NULL)                                 \
+      eprintf("Memory allocation error\n");                    \
+    struct_clear(pagelist.root);                               \
+    pagelist.head = pagelist.root;                             \
+    pagelist.head->header.head = pagelist.head->root;          \
+  } while (0)
+static
+void     pagenode_free(struct pagenode_t*);
+
+static inline
+void* pagelist_pop
+( struct pagelist_t* pagelist,
+  size_t             size
+)
+{ size_t headsize = PL_HEADSIZE((*pagelist));
+  if (!headsize)
+    { free(pagelist->head);
+      pagelist->head = pagelist->root;
+      while (pagelist->head->header.next != NULL)
+       pagelist->head = pagelist->head->header.next;
+    }
+  if (headsize < size)
+    eprintf("Attempted to pop unaligned value from pagelist\n");
+  pagelist->head->header.head -= size;
+  return pagelist->head->header.head;
+}
+
+/* Recursively clean pagenode linked list, freeing last first */
+static
+void pagenode_free
+( struct pagenode_t* pagenode )
+{ if (pagenode->header.next != NULL)
+    pagenode_free(pagenode->header.next);
+  free(pagenode);
+}
+static
+void* stack_alloc
+( struct pagelist_t* pagelist,
+  size_t bytes )
+{ void* p;
+  if (PL_HEADMEM((*pagelist)) < bytes) 
+    pagelist_alloc((*pagelist));
+  p = pagelist->head->header.head;
+  pagelist->head->header.head += bytes;
+  return p;
+}