MBED port of https://github.com/ys1382/filagree . The only change is adding #define MBED

Dependents:   filagree_test

Revision:
0:1a89e28dea91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/struct.c	Wed May 30 21:13:01 2012 +0000
@@ -0,0 +1,516 @@
+/* struct.c
+ *
+ * implements array, byte_array, lifo and map
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "vm.h"
+#include "struct.h"
+#include "util.h"
+
+#define BYTE_ARRAY_MAX_LEN      10000
+#define ERROR_BYTE_ARRAY_LEN    "byte array too long"
+
+
+// array ///////////////////////////////////////////////////////////////////
+
+struct array *array_new() {
+    return array_new_size(0);
+}
+
+struct array *array_new_size(uint32_t size) {
+    struct array *a = (struct array*)malloc(sizeof(struct array));
+    a->data = a->current = NULL;
+    a->length = 0;
+    return a;
+}
+
+void array_del(struct array *a) {
+    for (int i=0; i<a->length; i++)
+        free(array_get(a, i));
+    free(a->data);
+    free(a);
+}
+
+void array_resize(struct array *a, uint32_t length) {
+    a->data = (void**)realloc(a->data, length * sizeof(void*));
+    null_check(a->data);
+    memset(&a->data[a->length], 0, length-a->length);
+    a->length = length;
+}
+
+uint32_t array_add(struct array *a, void *datum) {
+    a->data = (void**)realloc(a->data, (a->length+1) * sizeof(void*));
+    a->data[a->length++] = datum;
+    return a->length-1;
+}
+
+void array_insert(struct array *a, uint32_t index, void *datum)
+{
+    a->data = (void**)realloc(a->data, (a->length+1) * sizeof(void*));
+    uint32_t i;
+    for (i=a->length; i>index; i--)
+        a->data[i] = a->data[i-1];
+    a->data[i] = datum;
+    a->length++;
+}
+
+void* array_get(const struct array *a, uint32_t index) {
+    assert_message(a && index < a->length, ERROR_INDEX);
+    //DEBUGPRINT("array_get %d = %x\n", index, a->data[index]);
+    return a->data[index];
+}
+
+void array_set(struct array *a, uint32_t index, void* datum) {
+    null_check(a);
+    null_check(datum);
+    if (a->length <= index)
+        array_resize(a, index+1);
+    //DEBUGPRINT("array_set %d %x\n", index, datum);
+    a->data[index] = datum;
+}
+
+void *list_remove(void *data, uint32_t *end, uint32_t start, int32_t length, size_t width)
+{
+    null_check(data);
+    null_check(end);
+    length = length < 0 ? *end - start : length;
+    assert_message(start < *end && start+length <= *end, "index out of bounds");
+    
+    memmove((uint8_t*)data+start*width, (uint8_t*)data+(start+length)*width, (*end-start-length)*width);
+    *end -= (uint32_t)length;
+    return realloc(data, *end * width);
+}
+
+void array_remove(struct array *self, uint32_t start, int32_t length) {
+    self->data = (void**)list_remove(self->data, &self->length, start, length, sizeof(void*));
+}
+
+struct array *array_copy(const struct array* original) {
+    if (!original)
+        return NULL;
+    struct array* copy = (struct array*)malloc(sizeof(struct array));
+    copy->data = (void**)malloc(original->length);
+    memcpy(copy->data, original->data, original->length);
+    copy->length = original->length;
+    copy->current = copy->data + (original->current - original->data);
+    return copy;
+}
+
+struct array *array_part(struct array *within, uint32_t start, uint32_t length)
+{
+    struct array *p = array_copy(within);
+    array_remove(p, start+length, within->length-start-length);
+    array_remove(p, 0, start);
+    return p;
+}
+
+void array_append(struct array *a, const struct array* b)
+{
+    null_check(a);
+    null_check(b);
+    array_resize(a, a->length + b->length);
+    memcpy(&a->data[a->length], b->data, b->length);
+    a->current = a->data + a->length;
+}
+
+// byte_array ///////////////////////////////////////////////////////////////
+
+struct byte_array *byte_array_new() {
+    struct byte_array* ba = (struct byte_array*)malloc(sizeof(struct byte_array));
+    ba->data = ba->current = 0;
+    ba->length = 0;
+    return ba;
+}
+
+void byte_array_del(struct byte_array* ba) {
+    if (ba->data)
+        free(ba->data);
+    free(ba);
+}
+
+struct byte_array *byte_array_new_size(uint32_t size) {
+    struct byte_array* ba = (struct byte_array*)malloc(sizeof(struct byte_array));
+    ba->data = ba->current = (uint8_t*)malloc(size);
+    ba->length = size;
+    return ba;
+}
+
+void byte_array_resize(struct byte_array* ba, uint32_t size) {
+    assert_message(ba->current >= ba->data, "byte_array corrupt");
+    uint32_t delta = ba->current - ba->data;
+    ba->data = (uint8_t*)realloc(ba->data, size);
+    assert(ba->data);
+    ba->current = ba->data + delta;
+    ba->length = size;
+}
+
+bool byte_array_equals(const struct byte_array *a, const struct byte_array* b) {
+    if (a==b)
+        return true;
+    if (!a != !b) // one is null and the other is not
+        return false;
+    if (a->length != b->length)
+        return false;
+    
+    int i;
+    for (i = 0; i<a->length; i++)
+        if (a->data[i] != b->data[i])
+            return false;
+    return true;
+}
+
+struct byte_array *byte_array_copy(const struct byte_array* original) {
+    if (!original)
+        return NULL;
+    struct byte_array* copy = (struct byte_array*)malloc(sizeof(struct byte_array));
+    copy->data = (uint8_t*)malloc(original->length);
+    memcpy(copy->data, original->data, original->length);
+    copy->length = original->length;
+    copy->current = copy->data + (original->current - original->data);
+    return copy;
+}
+
+void byte_array_append(struct byte_array *a, const struct byte_array* b) {
+    null_check(a);
+    null_check(b);
+    uint32_t offset = a->length;
+    byte_array_resize(a, a->length + b->length);
+    memcpy(&a->data[offset], b->data, b->length);
+    a->current = a->data + a->length;
+}
+
+void byte_array_remove(struct byte_array *self, uint32_t start, int32_t length) {
+    self->data = (uint8_t*)list_remove(self->data, &self->length, start, length, sizeof(uint8_t));
+}
+
+struct byte_array *byte_array_part(struct byte_array *within, uint32_t start, uint32_t length)
+{
+    struct byte_array *p = byte_array_copy(within);
+    byte_array_remove(p, start+length, within->length-start-length);
+    byte_array_remove(p, 0, start);
+    return p;
+}
+
+struct byte_array *byte_array_from_string(const char* str)
+{
+    int len = strlen(str);
+    struct byte_array* ba = byte_array_new_size(len);
+    memcpy(ba->data, str, len);
+    return ba;
+}
+
+char* byte_array_to_string(const struct byte_array* ba)
+{
+    int len = ba->length;
+    char* s = (char*)malloc(len+1);
+    memcpy(s, ba->data, len);
+    s[len] = 0;
+    return s;
+}
+
+void byte_array_reset(struct byte_array* ba) {
+    ba->current = ba->data;
+}
+
+struct byte_array *byte_array_concatenate(int n, const struct byte_array* ba, ...)
+{
+    struct byte_array* result = byte_array_copy(ba);
+
+    va_list argp;
+    for(va_start(argp, ba); --n;) {
+        struct byte_array* parameter = va_arg(argp, struct byte_array* );
+        if (!parameter)
+            continue;
+        assert_message(result->length + parameter->length < BYTE_ARRAY_MAX_LEN, ERROR_BYTE_ARRAY_LEN);
+        byte_array_append(result, parameter);
+    }
+
+    va_end(argp);
+
+    if (result)
+        result->current = result->data + result->length;
+    return result;
+}
+
+struct byte_array *byte_array_add_byte(struct byte_array *a, uint8_t b) {
+    byte_array_resize(a, a->length+1);
+    a->current = a->data + a->length;
+    a->data[a->length-1] = b;
+    return a;
+}
+
+void byte_array_print(const char* text, const struct byte_array* ba) {
+    int offset = ba->current-ba->data;
+    if (text)
+        printf("%s @%d\n", text, offset);
+    for (int i=0; i<ba->length; i++)
+        printf("\t%s%d\n", i==offset?">":" ", ba->data[i]);
+}
+
+int32_t byte_array_find(struct byte_array *within, struct byte_array *sought, uint32_t start)
+{
+    null_check(within);
+    null_check(sought);
+    
+    uint32_t ws = within->length;
+    uint32_t ss = sought->length;
+    assert_message(start < within->length, "out of bounds");
+    
+    uint8_t *wd = within->data;
+    uint8_t *sd = sought->data;
+    for (int32_t i=start; i<ws-ss+1; i++)
+        if (!memcmp(wd + i, sd, ss)) 
+            return i; 
+    
+    return -1;
+}
+
+struct byte_array *byte_array_replace(struct byte_array *within, struct byte_array *replacement, uint32_t start, int32_t length)
+{
+    null_check(within);
+    null_check(replacement);
+    uint32_t ws = within->length;
+    assert_message(start < ws, "index out of bounds");
+    if (length < 0)
+        length = ws - start;
+    
+    int32_t new_length = within->length - length + replacement->length;
+    struct byte_array *replaced = byte_array_new_size(new_length);
+    
+    memcpy(replaced->data, within->data, start);
+    memcpy(replaced->data + start, replacement->data, replacement->length);
+    memcpy(replaced->data + start + replacement->length, within->data + start + length, within->length - start - length);
+    
+    return replaced;
+}
+
+
+// stack ////////////////////////////////////////////////////////////////////
+
+struct stack* stack_new() {
+    return (struct stack*)calloc(sizeof(struct stack), 1);
+}
+
+struct stack_node* stack_node_new() {
+    return (struct stack_node*)calloc(sizeof(struct stack_node), 1);
+}
+
+void stack_push(struct stack* stack, void* data)
+{
+    null_check(data);
+    if (!stack->head)
+        stack->head = stack->tail = stack_node_new();
+    else {
+        struct stack_node* old_head = stack->head;
+        stack->head = stack_node_new();
+        null_check(stack->head);
+        stack->head->next = old_head;
+    }
+    stack->head->data = data;
+}
+
+void* stack_pop(struct stack* stack)
+{
+    if (!stack->head)
+        return NULL;
+    void* data = stack->head->data;
+    stack->head = stack->head->next;
+    null_check(data);
+    return data;
+}
+
+void* stack_peek(const struct stack* stack, uint8_t index)
+{
+    null_check(stack);
+    struct stack_node*p = stack->head;
+    for (; index && p; index--, p=p->next);
+    return p ? p->data : NULL;
+}
+
+bool stack_empty(const struct stack* stack)
+{
+    null_check(stack);
+    return stack->head == NULL;// && stack->tail == NULL;
+}
+
+// map /////////////////////////////////////////////////////////////////////
+
+static size_t def_hash_func(const struct byte_array* key)
+{
+    size_t hash = 0;
+    int i = 0;
+    for (i = 0; i<key->length; i++)
+        hash += key->data[i];
+    return hash;
+}
+
+struct map* map_new()
+{
+    struct map* m;
+    if (!(m =(struct map*)malloc(sizeof(struct map)))) return NULL;
+    m->size = 16;
+    m->hash_func = def_hash_func;
+    
+    if (!(m->nodes = (struct hash_node**)calloc(m->size, sizeof(struct hash_node*)))) {
+        free(m);
+        return NULL;
+    }
+    
+    return m;
+}
+
+void map_del(struct map* m)
+{
+    DEBUGPRINT("map_destroy\n");
+    size_t n;
+    struct hash_node *node, *oldnode;
+    
+    for(n = 0; n<m->size; ++n) {
+        node = m->nodes[n];
+        while (node) {
+            byte_array_del(node->key);
+            oldnode = node;
+            node = node->next;
+            free(oldnode);
+        }
+    }
+    free(m->nodes);
+    free(m);
+}
+
+int map_insert(struct map* m, const struct byte_array* key, void *data)
+{
+    struct hash_node *node;
+    size_t hash = m->hash_func(key) % m->size;    
+    
+    node = m->nodes[hash];
+    while (node) {
+        if (byte_array_equals(node->key, key)) {
+            node->data = data;
+            return 0;
+        }
+        node = node->next;
+    }
+    
+    if (!(node = (struct hash_node*)malloc(sizeof(struct hash_node))))
+        return -1;
+    if (!(node->key = byte_array_copy(key))) {
+        free(node);
+        return -1;
+    }
+    node->data = data;
+    node->next = m->nodes[hash];
+    m->nodes[hash] = node;
+    
+    return 0;
+}
+
+struct array* map_keys(const struct map* m) {
+    struct array *a = array_new();
+    for (int i=0; i<m->size; i++)
+        for (const struct hash_node* n = m->nodes[i]; n; n=n->next)
+            if (n->data)
+                array_add(a, n->key);
+    return a;
+}
+
+struct array* map_values(const struct map* m) {
+    struct array *a = array_new();
+    for (int i=0; i<m->size; i++)
+        for (const struct hash_node* n = m->nodes[i]; n; n=n->next)
+            if (n->data)
+                array_add(a, n->data);
+    return a;
+}
+
+int map_remove(struct map* m, const struct byte_array* key)
+{
+    struct hash_node *node, *prevnode = NULL;
+    size_t hash = m->hash_func(key)%m->size;
+    
+    node = m->nodes[hash];
+    while(node) {
+        if (byte_array_equals(node->key, key)) {
+            byte_array_del(node->key);
+            if (prevnode) prevnode->next = node->next;
+            else m->nodes[hash] = node->next;
+            free(node);
+            return 0;
+        }
+        prevnode = node;
+        node = node->next;
+    }    
+    return -1;
+}
+
+bool map_has(const struct map* m, const struct byte_array* key) {
+    struct hash_node *node;
+    size_t hash = m->hash_func(key) % m->size;
+    node = m->nodes[hash];
+    while (node) {
+        if (byte_array_equals(node->key, key))
+            return true;
+        node = node->next;
+    }
+    return false;
+}
+
+void *map_get(const struct map* m, const struct byte_array* key)
+{
+    struct hash_node *node;
+    size_t hash = m->hash_func(key) % m->size;
+    node = m->nodes[hash];
+    while (node) {
+        if (byte_array_equals(node->key, key))
+            return node->data;
+        node = node->next;
+    }
+    return NULL;
+}
+
+int map_resize(struct map* m, size_t size)
+{
+    DEBUGPRINT("map_resize\n");
+    struct map newtbl;
+    size_t n;
+    struct hash_node *node,*next;
+    
+    newtbl.size = size;
+    newtbl.hash_func = m->hash_func;
+    
+    if (!(newtbl.nodes = (struct hash_node**)calloc(size, sizeof(struct hash_node*))))
+        return -1;
+    
+    for(n = 0; n<m->size; ++n) {
+        for(node = m->nodes[n]; node; node = next) {
+            next = node->next;
+            map_insert(&newtbl, node->key, node->data);
+            map_remove(m, node->key);
+            
+        }
+    }
+    
+    free(m->nodes);
+    m->size = newtbl.size;
+    m->nodes = newtbl.nodes;
+    
+    return 0;
+}
+
+// in case of intersection, a wins
+void map_update(struct map *a, const struct map *b)
+{
+    const struct array *keys = map_keys(b);
+    for (int i=0; i<keys->length; i++) {
+        const struct byte_array *key = (const struct byte_array*)array_get(keys, i);
+        if (!map_has(a, key))
+            map_insert(a, key, map_get(b, key));
+    }
+}