X-Git-Url: https://pd.if.org/git/?p=lice;a=blobdiff_plain;f=util.c;fp=util.c;h=5aa9f829d659f20fed159f628dd547edba1b6d31;hp=0000000000000000000000000000000000000000;hb=bb650f4a52a456c1aa0a34508d6f3dcce58291b6;hpb=686688990cde8ecd8d9423fde7f88b6ac6ac8a40 diff --git a/util.c b/util.c new file mode 100644 index 0000000..5aa9f82 --- /dev/null +++ b/util.c @@ -0,0 +1,239 @@ +#include +#include +#include +#include +#include + +#include "util.h" + +#define MEMORY 0x8000000 + +static unsigned char *memory_pool = NULL; +static size_t memory_next = 0; + +static void memory_cleanup(void) { + free(memory_pool); +} + +void *memory_allocate(size_t bytes) { + void *value; + + if (!memory_pool) { + memory_pool = malloc(MEMORY); + atexit(memory_cleanup); + } + + if (memory_next > MEMORY) + goto bail; + + value = &memory_pool[memory_next]; + memory_next += bytes; + + if (memory_next > MEMORY) { +bail: + fprintf(stderr, "[lice] out of memory"); + exit(EXIT_FAILURE); + } + + return value; +} + +struct string_s { + char *buffer; + int allocated; + int length; +}; + +static void string_reallocate(string_t *string) { + int size = string->allocated * 2; + char *buffer = memory_allocate(size); + + strcpy(buffer, string->buffer); + string->buffer = buffer; + string->allocated = size; +} + +void string_catf(string_t *string, const char *fmt, ...) { + va_list va; + for (;;) { + int left = string->allocated - string->length; + int write; + + va_start(va, fmt); + write = vsnprintf(string->buffer + string->length, left, fmt, va); + va_end(va); + + if (left <= write) { + string_reallocate(string); + continue; + } + string->length += write; + return; + } +} + +string_t *string_create(void) { + string_t *string = memory_allocate(sizeof(string_t)); + string->buffer = memory_allocate(8); + string->allocated = 8; + string->length = 0; + string->buffer[0] = '\0'; + return string; +} + +char *string_buffer(string_t *string) { + return string->buffer; +} + +void string_cat(string_t *string, char ch) { + if (string->allocated == (string->length + 1)) + string_reallocate(string); + string->buffer[string->length++] = ch; + string->buffer[string->length] = '\0'; +} + +char *string_quote(char *p) { + string_t *string = string_create(); + while (*p) { + if (*p == '\"' || *p == '\\') + string_catf(string, "\\%c", *p); + else if (*p == '\n') + string_catf(string, "\\n"); + else + string_cat(string, *p); + p++; + } + return string->buffer; +} + +size_t string_length(string_t *string) { + return (string) ? string->length : 0; +} + +typedef struct { + char *key; + void *value; +} table_entry_t; + +void *table_create(void *parent) { + table_t *table = memory_allocate(sizeof(table_t)); + table->list = list_create(); + table->parent = parent; + + return table; +} + +void *table_find(table_t *table, const char *key) { + for (; table; table = table->parent) { + for (list_iterator_t *it = list_iterator(table->list); !list_iterator_end(it); ) { + table_entry_t *entry = list_iterator_next(it); + if (!strcmp(key, entry->key)) + return entry->value; + } + } + return NULL; +} + +void table_insert(table_t *table, char *key, void *value) { + table_entry_t *entry = memory_allocate(sizeof(table_entry_t)); + entry->key = key; + entry->value = value; + + list_push(table->list, entry); +} + +void *table_parent(table_t *table) { + return table->parent; +} + +list_t *table_values(table_t *table) { + list_t *list = list_create(); + for (; table; table = table->parent) + for (list_iterator_t *it = list_iterator(table->list); !list_iterator_end(it); ) + list_push(list, ((table_entry_t*)list_iterator_next(it))->value); + return list; +} + +list_t *table_keys(table_t *table) { + list_t *list = list_create(); + for (; table; table = table->parent) + for (list_iterator_t *it = list_iterator(table->list); !list_iterator_end(it); ) + list_push(list, ((table_entry_t*)list_iterator_next(it))->key); + return list; +} + +pair_t *pair_create(void *first, void *second) { + pair_t *pair = memory_allocate(sizeof(pair_t)); + pair->first = first; + pair->second = second; + return pair; +} + +int strcasecmp(const char *s1, const char *s2) { + const unsigned char *u1 = (const unsigned char *)s1; + const unsigned char *u2 = (const unsigned char *)s2; + + while (tolower(*u1) == tolower(*u2++)) + if(*u1++ == '\0') + return 0; + return tolower(*u1) - tolower(*--u2); +} + +int strncasecmp(const char *s1, const char *s2, size_t n) { + const unsigned char *u1 = (const unsigned char *)s1; + const unsigned char *u2 = (const unsigned char *)s2; + + if (!n) + return 0; + + do { + if (tolower(*u1) != tolower(*u2++)) + return tolower(*u1) - tolower(*--u2); + if (*u1++ == '\0') + break; + } while (--n != 0); + + return 0; +} + +size_t getline(char **line, size_t *n, FILE *stream) { + char *buf = NULL; + char *p = buf; + + int size; + int c; + + if (!line) + return -1; + if (!stream) + return -1; + if (!n) + return -1; + + buf = *line; + size = *n; + + if ((c = fgetc(stream)) == EOF) + return -1; + if (!buf) { + buf = malloc(128); + size = 128; + } + p = buf; + while(c != EOF) { + if ((p - buf) > (size - 1)) { + size = size + 128; + buf = realloc(buf, size); + } + *p++ = c; + if (c == '\n') + break; + c = fgetc(stream); + } + + *p++ = '\0'; + *line = buf; + *n = size; + + return p - buf - 1; +}