first commit

This commit is contained in:
cozis
2021-10-31 04:17:57 +00:00
commit 7a5d0d1dcb
55 changed files with 5204 additions and 0 deletions
+217
View File
@@ -0,0 +1,217 @@
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#include "defs.h"
#include "bpalloc.h"
#if USING_VALGRIND
#include <valgrind/memcheck.h>
#endif
#define CHUNK_SIZE 4096
#define PADDING 8
typedef struct BPAllocChunk BPAllocChunk;
struct BPAllocChunk {
BPAllocChunk *prev;
char body[];
};
struct xBPAlloc {
int flags;
void *userp;
void *(*fn_malloc)(void *userp, int size);
void (*fn_free )(void *userp, void *addr);
int minsize, size, used;
BPAllocChunk *tail;
};
enum {
FG_STATIC = 1,
};
static void *default_fn_malloc(void *userp, int size);
static void default_fn_free (void *userp, void *addr);
BPAlloc *BPAlloc_Init(int chunk_size)
{
return BPAlloc_Init2(-1, chunk_size, NULL, NULL, NULL);
}
BPAlloc *BPAlloc_Init2(int first_size, int chunk_size,
void *userp,
void *(*fn_malloc)(void *userp, int size),
void (*fn_free )(void *userp, void *addr))
{
if(chunk_size < 0)
chunk_size = CHUNK_SIZE;
if(first_size < 0)
first_size = chunk_size;
if(fn_malloc == NULL)
{
userp = NULL;
fn_malloc = default_fn_malloc;
fn_free = default_fn_free;
}
void *temp = fn_malloc(userp, sizeof(BPAlloc) + sizeof(BPAllocChunk) + first_size + PADDING);
if(temp == NULL)
return NULL;
BPAlloc *alloc = temp;
BPAllocChunk *chunk = (BPAllocChunk*) (alloc + 1);
chunk->prev = NULL;
alloc->flags = 0;
alloc->used = 0;
alloc->size = first_size;
alloc->tail = chunk;
alloc->minsize = chunk_size;
alloc->userp = userp;
alloc->fn_malloc = fn_malloc;
alloc->fn_free = fn_free;
#if USING_VALGRIND
VALGRIND_CREATE_MEMPOOL(alloc, PADDING, 0);
#endif
return alloc;
}
BPAlloc *BPAlloc_Init3(void *mem, int mem_size, int chunk_size,
void *userp,
void *(*fn_malloc)(void *userp, int size),
void (*fn_free )(void *userp, void *addr))
{
assert(mem != NULL);
assert(mem_size >= 0);
if(chunk_size < 0)
chunk_size = CHUNK_SIZE;
if(fn_malloc == NULL)
{
userp = NULL;
fn_malloc = default_fn_malloc;
fn_free = default_fn_free;
}
int required = sizeof(BPAlloc)
+ sizeof(BPAllocChunk)
+ PADDING;
if(mem_size < required)
// Not enough memory was provided.
return NULL;
BPAlloc *alloc = mem;
BPAllocChunk *chunk = (BPAllocChunk*) (alloc + 1);
chunk->prev = NULL;
alloc->flags = FG_STATIC;
alloc->used = 0;
alloc->size = mem_size - sizeof(BPAlloc) - sizeof(BPAllocChunk);
alloc->tail = chunk;
alloc->minsize = chunk_size;
alloc->userp = userp;
alloc->fn_malloc = fn_malloc;
alloc->fn_free = fn_free;
#if USING_VALGRIND
VALGRIND_CREATE_MEMPOOL(alloc, PADDING, 0);
#endif
return alloc;
}
void BPAlloc_Free(BPAlloc *alloc)
{
assert(alloc != NULL);
#if USING_VALGRIND
VALGRIND_DESTROY_MEMPOOL(alloc);
#endif
BPAllocChunk *chunk = alloc->tail;
while(chunk->prev)
{
BPAllocChunk *prev = chunk->prev;
if(alloc->fn_free)
alloc->fn_free(alloc->userp, chunk);
chunk = prev;
}
if(!(alloc->flags & FG_STATIC))
if(alloc->fn_free)
alloc->fn_free(alloc->userp, alloc);
}
void *BPAlloc_Malloc(BPAlloc *alloc, int req_size)
{
assert(alloc != NULL);
assert(req_size >= 0);
alloc->used += PADDING;
if(alloc->used & 7)
alloc->used = (alloc->used & ~7) + 8;
if(alloc->used + req_size > alloc->size)
{
// If the chunk size is lower than the
// requested size, then set the chunk
// size to the requested size.
int chunk_size = MAX(alloc->minsize, req_size + PADDING);
assert(alloc->fn_malloc != NULL);
BPAllocChunk *chunk = alloc->fn_malloc(alloc->userp, sizeof(BPAllocChunk) + chunk_size);
if(chunk == NULL)
return NULL;
chunk->prev = alloc->tail;
alloc->tail = chunk;
alloc->size = chunk_size;
alloc->used = PADDING;
if(alloc->used & 7)
alloc->used = (alloc->used & ~7) + 8;
}
void *addr = alloc->tail->body + alloc->used;
assert(((intptr_t) addr) % 8 == 0);
alloc->used += req_size;
#if USING_VALGRIND
VALGRIND_MEMPOOL_ALLOC(alloc, addr, req_size);
// VALGRIND_MAKE_MEM_NOACCESS((char*) addr - PADDING, PADDING);
// VALGRIND_MAKE_MEM_NOACCESS((char*) addr + req_size, PADDING);
#endif
return addr;
}
static void *default_fn_malloc(void *userp, int size)
{
assert(userp == NULL);
assert(size >= 0);
return malloc(size);
}
static void default_fn_free(void *userp, void *addr)
{
assert(userp == NULL);
free(addr);
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef BPALLOC_H
#define BPALLOC_H
typedef struct xBPAlloc BPAlloc;
BPAlloc* BPAlloc_Init(int chunk_size);
BPAlloc* BPAlloc_Init2(int first_size, int chunk_size, void *userp, void *(*fn_malloc)(void *userp, int size), void (*fn_free )(void *userp, void *addr));
BPAlloc* BPAlloc_Init3(void *mem, int mem_size, int chunk_size, void *userp, void *(*fn_malloc)(void *userp, int size), void (*fn_free )(void *userp, void *addr));
void BPAlloc_Free(BPAlloc *alloc);
void* BPAlloc_Malloc(BPAlloc *alloc, int req_size);
#endif
+177
View File
@@ -0,0 +1,177 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "bucketlist.h"
#include "defs.h"
#define MIN_BUCKET_SIZE 4096
typedef struct Bucket Bucket;
struct Bucket {
Bucket* next;
int size,
used,
aidx;
char body[];
};
struct xBucketList {
BPAlloc *alloc;
Bucket *head,
*tail;
int size;
};
BucketList *BucketList_New(BPAlloc *alloc)
{
assert(alloc != NULL);
BucketList *blist = BPAlloc_Malloc(alloc, sizeof(BucketList) + sizeof(Bucket) + MIN_BUCKET_SIZE);
if(blist == NULL)
return NULL;
Bucket *head = (Bucket*) (blist + 1);
head->next = NULL;
head->size = MIN_BUCKET_SIZE;
head->used = 0;
head->aidx = 0;
blist->alloc = alloc;
blist->head = head;
blist->tail = head;
blist->size = 0;
return blist;
}
int BucketList_Size(BucketList *blist)
{
return blist->size;
}
static Bucket *make_bucket(BPAlloc *alloc, int size)
{
Bucket *new_bucket = BPAlloc_Malloc(alloc, sizeof(Bucket) + size);
if(new_bucket == NULL)
return NULL;
// Initialize it.
new_bucket->next = NULL;
new_bucket->size = size;
new_bucket->used = 0;
new_bucket->aidx = -1;
return new_bucket;
}
static void append_bucket(BucketList *blist, Bucket *new_bucket)
{
new_bucket->aidx = blist->size;
blist->tail->next = new_bucket;
blist->tail = new_bucket;
}
_Bool BucketList_Append(BucketList *blist, const void *data, int size)
{
assert(blist != NULL);
assert(size >= 0);
int not_copied_yet = size;
while(not_copied_yet > 0)
{
// Copy until there's nothing left
// or until the current bucket is
// full. If the bucket is already
// full, add another one.
int left_in_bucket = blist->tail->size - blist->tail->used;
if(left_in_bucket == 0)
{
Bucket *new_bucket = make_bucket(blist->alloc, MIN_BUCKET_SIZE);
if(new_bucket == NULL)
return 0;
append_bucket(blist, new_bucket);
}
// Decide how much to copy.
int copying = MIN(not_copied_yet, left_in_bucket);
// Copy into the bucket.
{
char *dst = blist->tail->body + blist->tail->used;
if(data == NULL)
memset(dst, 0, copying);
else
memcpy(dst, data + size - not_copied_yet, copying);
blist->tail->used += copying;
}
not_copied_yet -= copying;
}
blist->size += size;
return 1;
}
void *BucketList_Append2(BucketList *blist, const void *data, int size)
{
assert(blist != NULL);
assert(size >= 0);
// If the data doesn't fit inside the
// current bucket, add another one with
// enough space.
if(blist->tail->used + size > blist->tail->size)
{
int bucket_size = MAX(MIN_BUCKET_SIZE, size);
Bucket *new_bucket = make_bucket(blist->alloc, bucket_size);
if(new_bucket == NULL)
return 0;
append_bucket(blist, new_bucket);
}
void *addr = blist->tail->body + blist->tail->used;
// Do the copying.
if(data == NULL)
memset(addr, 0, size);
else
memcpy(addr, data, size);
blist->tail->used += size;
blist->size += size;
return addr;
}
void BucketList_Copy(BucketList *blist, void *dest, int len)
{
assert(blist != NULL);
assert(dest != NULL);
if(len < 0)
len = blist->size;
int copied = 0;
Bucket *bucket = blist->head;
while(bucket && copied < len)
{
int copying = MIN(len - copied, bucket->used);
assert(copying >= 0);
memcpy((char*) dest + copied, bucket->body, copying);
copied += copying;
bucket = bucket->next;
}
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef BUCKETLIST_H
#define BUCKETLIST_H
#include "bpalloc.h"
typedef struct xBucketList BucketList;
BucketList *BucketList_New(BPAlloc *alloc);
int BucketList_Size(BucketList *blist);
void BucketList_Copy(BucketList *blist, void *dest, int len);
_Bool BucketList_Append (BucketList *blist, const void *data, int size);
void *BucketList_Append2(BucketList *blist, const void *data, int size);
#endif
+17
View File
@@ -0,0 +1,17 @@
#include <assert.h>
#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
#ifndef NULL
#define NULL ((void*) 0)
#endif
#define UNREACHABLE assert(0);
#define membersizeof(type, member) (sizeof(((type*) 0)->member))
+88
View File
@@ -0,0 +1,88 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "error.h"
void Error_Init(Error *err)
{
memset(err, 0, sizeof (Error));
}
void Error_Init2(Error *err, void (*on_report)(Error *err))
{
memset(err, 0, sizeof (Error));
err->on_report = on_report;
}
void Error_Free(Error *err)
{
if(err->message2 != err->message)
free(err->message);
memset(err, 0, sizeof (Error));
}
void _Error_Report(Error *err, _Bool internal,
const char *file, const char *func, int line,
const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
_Error_Report2(err, internal, file, func, line, fmt, va);
va_end(va);
}
void _Error_Report2(Error *err, _Bool internal,
const char *file, const char *func, int line,
const char *fmt, va_list va)
{
assert(err);
assert(file);
assert(func);
assert(line > 0);
assert(fmt);
assert(err->occurred == 0);
err->occurred = 1;
err->internal = internal;
err->file = file;
err->func = func;
err->line = line;
va_list va2;
va_copy(va2, va);
int p = vsnprintf(err->message2, sizeof(err->message2), fmt, va);
assert(p > -1);
if((unsigned int) p > sizeof(err->message2)-1)
{
char *temp = malloc(p+1);
if(temp == NULL)
{
err->truncated = 1;
err->message = err->message2;
err->length = sizeof(err->message2)-1;
}
else
{
snprintf(temp, p+1, fmt, va2);
err->truncated = 0;
err->message = temp;
err->length = p;
}
}
else
{
err->truncated = 0;
err->message = err->message2;
err->length = p;
}
va_end(va2);
if(err->on_report)
err->on_report(err);
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef ERROR_H
#define ERROR_H
#include <stdarg.h>
typedef struct Error Error;
struct Error {
void (*on_report)(Error *err);
_Bool occurred,
internal,
truncated;
int length;
char* message;
char message2[256];
const char *file,
*func;
int line;
};
void Error_Init(Error *err);
void Error_Init2(Error *err, void (*on_report)(Error *err));
void Error_Free(Error *err);
#define Error_Report(err, internal, fmt, ...) _Error_Report(err, internal, __FILE__, __func__, __LINE__, fmt, ## __VA_ARGS__)
void _Error_Report (Error *err, _Bool internal, const char *file, const char *func, int line, const char *fmt, ...);
void _Error_Report2(Error *err, _Bool internal, const char *file, const char *func, int line, const char *fmt, va_list va);
#endif
+19
View File
@@ -0,0 +1,19 @@
#include <stdint.h>
#include "hash.h"
int hashbytes(unsigned char *str, int len)
{
int x = (intptr_t) str; // just to not use 0.
x ^= *str << 7;
for(int i = 0; i < len; i += 1)
x = (1000003UL * x) ^ *str++;
x ^= len;
if(x == -1)
x = -2;
return x;
}
+4
View File
@@ -0,0 +1,4 @@
#ifndef HASH_H
#define HASH_H
int hashbytes(unsigned char *str, int len);
#endif
+106
View File
@@ -0,0 +1,106 @@
#include <assert.h>
#include <string.h>
#include "promise.h"
#include "defs.h"
typedef struct Gap Gap;
struct Gap {
Gap *next;
void *dest;
void *userp;
void (*callback)(void*);
};
struct xPromise {
BPAlloc *alloc;
_Bool set;
Gap *gaps;
int size;
char body[];
};
Promise *Promise_New(BPAlloc *alloc, int size)
{
assert(alloc != NULL);
assert(size >= 0);
Promise *promise = BPAlloc_Malloc(alloc, sizeof(Promise) + size);
if(promise == NULL)
return NULL;
promise->alloc = alloc;
promise->set = 0;
promise->gaps = NULL;
promise->size = size;
return promise;
}
unsigned int Promise_Size(Promise *promise)
{
return promise->size;
}
void Promise_Delete(Promise *promise)
{
assert(promise->set == 1);
}
void Promise_Resolve(Promise *promise, const void *data, int size)
{
assert(size >= 0);
assert(size == promise->size);
assert(promise->set == 0);
memcpy(promise->body, data, size);
promise->set = 1;
Gap *gap = promise->gaps;
while(gap)
{
memcpy(gap->dest, data, size);
if(gap->callback)
gap->callback(gap->userp);
gap = gap->next;
}
promise->gaps = NULL;
}
_Bool Promise_Subscribe(Promise *promise, void *dest)
{
assert(promise != NULL);
assert(dest != NULL);
return Promise_Subscribe2(promise, dest, NULL, NULL);
}
_Bool Promise_Subscribe2(Promise *promise, void *dest, void *userp, void (*callback)(void*))
{
assert(promise != NULL);
assert(dest != NULL);
if(promise->set == 0)
{
Gap *gap = BPAlloc_Malloc(promise->alloc, sizeof(Gap));
if(gap == NULL)
return 0;
gap->next = promise->gaps;
gap->dest = dest;
gap->userp = userp;
gap->callback = callback;
promise->gaps = gap;
}
else
{
memcpy(dest, promise->body, promise->size);
if(callback)
callback(userp);
}
return 1;
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef PROMISE_H
#define PROMISE_H
#include "bpalloc.h"
typedef struct xPromise Promise;
Promise *Promise_New(BPAlloc *alloc, int size);
unsigned int Promise_Size(Promise *promise);
void Promise_Delete(Promise *promise);
void Promise_Resolve(Promise *promise, const void *data, int size);
_Bool Promise_Subscribe(Promise *promise, void *dest);
_Bool Promise_Subscribe2(Promise *promise, void *dest, void *userp, void (*callback)(void*));
#endif
+160
View File
@@ -0,0 +1,160 @@
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include "source.h"
struct xSource {
char *name;
char *body;
int size;
int refs;
};
Source *Source_Copy(Source *s)
{
s->refs += 1;
return s;
}
void Source_Free(Source *s)
{
s->refs -= 1;
assert(s->refs >= 0);
if(s->refs == 0)
free(s);
}
const char *Source_GetName(const Source *s)
{
return s->name;
}
const char *Source_GetBody(const Source *s)
{
return s->body;
}
unsigned int Source_GetSize(const Source *s)
{
return s->size;
}
Source *Source_FromFile(const char *file, Error *error)
{
assert(file != NULL);
// Open the file and get it's size.
// at the end of the block, the file
// cursor will point at the start of
// the file.
FILE *fp;
int size;
{
fp = fopen(file, "rb");
if(fp == NULL)
{
if(errno == ENOENT)
Error_Report(error, 0, "File \"%s\" doesn't exist", file);
else
Error_Report(error, 1, "Call to fopen failed (%s, errno = %d)", strerror(errno), errno);
return NULL;
}
if(fseek(fp, 0, SEEK_END))
{
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
fclose(fp);
return NULL;
}
size = ftell(fp);
if(size < 0)
{
Error_Report(error, 1, "Call to ftell failed (%s, errno = %d)", strerror(errno), errno);
fclose(fp);
return NULL;
}
if(fseek(fp, 0, SEEK_END))
{
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
fclose(fp);
return NULL;
}
}
// Allocate the source structure.
Source *s;
{
int namel = strlen(file);
s = malloc(sizeof(Source) + namel + size + 2);
if(s == NULL)
{
Error_Report(error, 1, "No memory");
fclose(fp);
return NULL;
}
s->name = (char*) (s + 1);
s->body = s->name + namel + 1;
}
// Copy the name into it.
strcpy(s->name, file);
s->size = size;
s->refs = 1;
// Now copy the file contents into it.
{
int p = fread(s->body, 1, size, fp);
if(p != size)
{
Error_Report(error, 1, "Call to fread failed, %d bytes out of %d were read (%s, errno = %d)", p, size, strerror(errno), errno);
fclose(fp);
free(s);
return NULL;
}
s->body[s->size] = '\0';
}
fclose(fp);
return s;
}
Source *Source_FromString(const char *name, const char *body, int size, Error *error)
{
assert(body != NULL);
if(size < 0)
size = strlen(body);
int namel = name ? strlen(name) : 0;
void *memory = malloc(sizeof(Source) + namel + size + 2);
if(memory == NULL)
{
Error_Report(error, 1, "No memory");
return NULL;
}
Source *s = memory;
s->name = (char*) (s + 1);
s->body = s->name + namel + 1;
s->size = size;
s->refs = 1;
if(name)
strcpy(s->name, name);
strncpy(s->body, body, size);
return s;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef SOURCE_H
#define SOURCE_H
#include "error.h"
typedef struct xSource Source;
Source *Source_Copy(Source *s);
void Source_Free(Source *s);
const char *Source_GetName(const Source *s);
const char *Source_GetBody(const Source *s);
unsigned int Source_GetSize(const Source *s);
Source *Source_FromFile(const char *file, Error *error);
Source *Source_FromString(const char *name, const char *body, int size, Error *error);
#endif
+73
View File
@@ -0,0 +1,73 @@
#include <stdlib.h>
#include "stack.h"
#include "defs.h"
struct xStack {
unsigned int size, used;
void *body[];
};
void *Stack_New(int size)
{
if(size < 0)
size = 1024;
Stack *s = malloc(sizeof(Stack) + sizeof(void*) * size);
if(s == NULL)
return NULL;
s->size = size;
s->used = 0;
return s;
}
void *Stack_Top(Stack *s, int n)
{
assert(n <= 0);
if(s->used == 0)
return NULL;
if((int) s->used + n - 1 < 0)
return NULL;
return s->body[s->used + n - 1];
}
_Bool Stack_Pop(Stack *s, unsigned int n)
{
if(s->used < n)
return 0;
s->used -= n;
return 1;
}
_Bool Stack_Push(Stack *s, void *item)
{
assert(s != NULL);
assert(item != NULL);
if(s->used == s->size)
return 0;
s->body[s->used] = item;
s->used += 1;
return 1;
}
void Stack_Free(Stack *s)
{
free(s);
}
unsigned int Stack_Size(Stack *s)
{
return s->used;
}
unsigned int Stack_Capacity(Stack *s)
{
return s->size;
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef STACK_H
#define STACK_H
typedef struct xStack Stack;
void *Stack_New(int size);
void *Stack_Top(Stack *s, int n);
_Bool Stack_Pop(Stack *s, unsigned int n);
_Bool Stack_Push(Stack *s, void *item);
void Stack_Free(Stack *s);
unsigned int Stack_Size(Stack *s);
unsigned int Stack_Capacity(Stack *s);
#endif