Initial commit.
authorethereal <ethereal@ethv.net>
Sun, 26 Jan 2014 07:19:30 +0000 (00:19 -0700)
committerethereal <ethereal@ethv.net>
Sun, 26 Jan 2014 07:19:30 +0000 (00:19 -0700)
Basic node manipulation interface/hash table implemented.

.gitignore [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/CMakeLists.txt [new file with mode: 0644]
src/main.c [new file with mode: 0644]
src/yacjs.c [new file with mode: 0644]
src/yacjs.h [new file with mode: 0644]
src/yacjs_dict.c [new file with mode: 0644]
src/yacjs_dict.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8eca1fe
--- /dev/null
@@ -0,0 +1,5 @@
+/build
+/.vimrc
+
+/yacjs_test
+/.ycm_extra_conf.py*
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..15e4636
--- /dev/null
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.6)
+
+project(yacjs C)
+
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
+
+add_subdirectory(src)
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..0ac7f01
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+.PHONY: all
+all:
+       $(MAKE) -C build
+
+.PHONY: redep
+redep:
+       mkdir -p build/ ; cd build/ ; cmake .. ; cd ..
+
+.PHONY: clean
+clean:
+       $(MAKE) -C build clean
+
+.PHONY: distclean
+distclean:
+       $(MAKE) -C build clean
+       rm -rf build
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d2c4fa0
--- /dev/null
@@ -0,0 +1,3 @@
+add_definitions(-W -Wall -std=c99)
+
+add_executable(yacjs_test yacjs.c yacjs_dict.c main.c)
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..39f17ab
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+#include "yacjs.h"
+
+int main() {
+    return 0;
+}
diff --git a/src/yacjs.c b/src/yacjs.c
new file mode 100644 (file)
index 0000000..78874ed
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdlib.h>
+
+#include "yacjs.h"
+#include "yacjs_dict.h"
+
+struct yacjs_node {
+    enum yacjs_node_type type;
+    union {
+        const char *string;
+        int64_t number;
+        double fp;
+        struct {
+            struct yacjs_node *entries;
+            int entries_count;
+            int entries_size;
+        } array;
+        struct yacjs_dict *dict;
+    } data;
+};
+
+static enum yacjs_error last_error = YACJS_ERROR_NONE;
+
+enum yacjs_error yacjs_last_error() {
+    enum yacjs_error err = last_error;
+    last_error = YACJS_ERROR_NONE;
+    return err;
+}
+
+struct yacjs_node *yacjs_parse(const char *string) {
+    return NULL;
+}
+
+enum yacjs_node_type yacjs_node_type(struct yacjs_node *node) {
+    return node->type;
+}
+
+const char *yacjs_node_str(struct yacjs_node *node) {
+    if(node->type != YACJS_NODE_STRING) {
+        last_error = YACJS_ERROR_TYPE;
+        return NULL;
+    }
+    return node->data.string;
+}
+
+int64_t yacjs_node_num(struct yacjs_node *node) {
+    if(node->type != YACJS_NODE_NUMBER) {
+        last_error = YACJS_ERROR_TYPE;
+        return -1;
+    }
+    return node->data.number;
+}
+
+double yacjs_node_float(struct yacjs_node *node) {
+    if(node->type != YACJS_NODE_FLOAT) {
+        last_error = YACJS_ERROR_TYPE;
+        return 1/0.0;
+    }
+    return node->data.fp;
+}
+
+int yacjs_node_array_size(struct yacjs_node *node) {
+    if(node->type != YACJS_NODE_ARRAY) {
+        last_error = YACJS_ERROR_TYPE;
+        return -1;
+    }
+    return node->data.array.entries_count;
+}
+
+struct yacjs_node *yacjs_node_array_elem(struct yacjs_node *node, int index) {
+    if(node->type != YACJS_NODE_ARRAY) {
+        last_error = YACJS_ERROR_TYPE;
+        return NULL;
+    }
+    if(index >= node->data.array.entries_count || index < 0) {
+        last_error = YACJS_ERROR_BOUNDS;
+        return NULL;
+        
+    }
+    return node->data.array.entries + index;
+}
+
+struct yacjs_node *yacjs_node_dict_get(struct yacjs_node *node,
+    const char *key) {
+
+    if(node->type != YACJS_NODE_DICT) {
+        last_error = YACJS_ERROR_TYPE;
+        return NULL;
+    }
+
+    return yacjs_dict_get(node->data.dict, key);
+}
diff --git a/src/yacjs.h b/src/yacjs.h
new file mode 100644 (file)
index 0000000..bf6dfa2
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef YACJS_H
+#define YACJS_H
+
+#include <stdint.h>
+
+struct yacjs_node;
+
+enum yacjs_node_type {
+    YACJS_NODE_STRING,
+    YACJS_NODE_NUMBER,
+    YACJS_NODE_FLOAT,
+    YACJS_NODE_ARRAY,
+    YACJS_NODE_DICT,
+    YACJS_NODE_TYPES
+};
+
+enum yacjs_error {
+    YACJS_ERROR_NONE,
+    YACJS_ERROR_PARSE,
+    YACJS_ERROR_MEMORY,
+    YACJS_ERROR_TYPE,
+    YACJS_ERROR_BOUNDS,
+    YACJS_ERROR_TYPES
+};
+
+enum yacjs_error yacjs_last_error();
+
+struct yacjs_node *yacjs_parse(const char *string);
+
+enum yacjs_node_type yacjs_node_type(struct yacjs_node *node);
+const char *yacjs_node_str(struct yacjs_node *node);
+int64_t yacjs_node_num(struct yacjs_node *node);
+double yacjs_node_float(struct yacjs_node *node);
+int yacjs_node_array_size(struct yacjs_node *node);
+struct yacjs_node *yacjs_node_array_elem(struct yacjs_node *node, int index);
+struct yacjs_node *yacjs_node_dict_get(struct yacjs_node *node,
+    const char *key);
+
+#endif
diff --git a/src/yacjs_dict.c b/src/yacjs_dict.c
new file mode 100644 (file)
index 0000000..1d1606d
--- /dev/null
@@ -0,0 +1,108 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "yacjs_dict.h"
+
+struct yacjs_dict_entry {
+    char *key;
+    void *value;
+    uint64_t key_hash;
+};
+
+struct yacjs_dict {
+    struct yacjs_dict_entry *entries;
+    int entries_size;
+    int entries_count;
+};
+
+static char *ystrdup(const char *string);
+static uint64_t string_hash(const char *string);
+static void resize(struct yacjs_dict *dict, int newsize);
+static void insert_helper(struct yacjs_dict *dict, uint64_t hash,
+    const char *key, void *value);
+
+struct yacjs_dict *yacjs_dict_make() {
+    struct yacjs_dict *result = malloc(sizeof(*result));
+
+    result->entries = NULL;
+    result->entries_size = 0;
+    result->entries_count = 0;
+
+    return result;
+}
+
+void yacjs_dict_destroy(struct yacjs_dict *dict, yacjs_dict_visitor visitor) {
+    if(visitor) {
+        for(int i = 0; i < dict->entries_size; i ++) {
+            if(dict->entries[i].key) {
+                visitor(dict->entries[i].value);
+                free(dict->entries[i].key);
+            }
+        }
+    }
+    free(dict);
+}
+
+void yacjs_dict_set(struct yacjs_dict *dict, const char *key,
+    void *value) {
+
+    if(dict->entries_size == dict->entries_count) {
+        resize(dict, dict->entries_size*2 + 1);
+    }
+
+    uint64_t hash = string_hash(key);
+    insert_helper(dict, hash, ystrdup(key), value);
+}
+
+void *yacjs_dict_get(struct yacjs_dict *dict, const char *key) {
+    uint64_t hash = string_hash(key);
+    for(int i = 0; i < dict->entries_size; i ++) {
+        int in = (i+hash) % dict->entries_size;
+        if(!dict->entries[in].key) return NULL;
+        if(dict->entries[in].key_hash == hash) return dict->entries[in].value;
+    }
+    return NULL;
+}
+
+static char *ystrdup(const char *string) {
+    return strcpy(malloc(strlen(string)+1), string);
+}
+
+static uint64_t string_hash(const char *string) {
+    uint64_t result = 14695981039346656037ULL; 
+
+    while(*string) {
+        result ^= *string;
+        result *= 1099511628211ULL;
+        string ++;
+    }
+
+    return result;
+}
+
+static void resize(struct yacjs_dict *dict, int newsize) {
+    struct yacjs_dict_entry *oentries = dict->entries;
+    int osize = dict->entries_size;
+    dict->entries_size = newsize;
+    dict->entries_count = 0;
+    dict->entries = calloc(newsize, sizeof(oentries[0]));
+
+    for(int i = 0; i < osize; i ++) {
+        if(!oentries[i].key) continue;
+        insert_helper(dict, oentries[i].key_hash, oentries[i].key,
+            oentries[i].value);
+    }
+}
+
+static void insert_helper(struct yacjs_dict *dict, uint64_t hash,
+    const char *key, void *value) {
+    for(int i = 0; i < dict->entries_size; i ++) {
+        int in = (i+hash) % dict->entries_size;
+        if(dict->entries[in].key) continue;
+        dict->entries[in].key = ystrdup(key);
+        dict->entries[in].key_hash = hash;
+        dict->entries[in].value = value;
+        break;
+    }
+}
diff --git a/src/yacjs_dict.h b/src/yacjs_dict.h
new file mode 100644 (file)
index 0000000..2cf3fca
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef YACJS_DICT_H
+#define YACJS_DICT_H
+
+struct yacjs_dict;
+
+typedef void (*yacjs_dict_visitor)(void *value);
+
+struct yacjs_dict *yacjs_dict_make();
+void yacjs_dict_destroy(struct yacjs_dict *dict, yacjs_dict_visitor visitor);
+
+void yacjs_dict_set(struct yacjs_dict *dict, const char *key,
+    void *value);
+void *yacjs_dict_get(struct yacjs_dict *dict, const char *key);
+
+#endif