aboutsummaryrefslogtreecommitdiffstats
path: root/src/argparser.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2013-06-26 01:58:40 +0200
committerMattias Andrée <maandree@operamail.com>2013-06-26 01:58:40 +0200
commit67304a1a82935d58f8b8f48aa2585d9504363aac (patch)
tree73a3f1308040f78a37a2e76f806ac22be388cd49 /src/argparser.c
parentm functio rename (diff)
downloadargparser-67304a1a82935d58f8b8f48aa2585d9504363aac.tar.gz
argparser-67304a1a82935d58f8b8f48aa2585d9504363aac.tar.bz2
argparser-67304a1a82935d58f8b8f48aa2585d9504363aac.tar.xz
implement map
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src/argparser.c')
-rw-r--r--src/argparser.c126
1 files changed, 118 insertions, 8 deletions
diff --git a/src/argparser.c b/src/argparser.c
index a4545be..7a7ad74 100644
--- a/src/argparser.c
+++ b/src/argparser.c
@@ -33,7 +33,11 @@
static void _sort(char** list, long count, char** temp);
static void sort(char** list, long count);
static long cmp(char* a, char* b);
-
+static void map_init(args_Map* map);
+static void* map_get(args_Map* map, char* key);
+static void map_put(args_Map* map, char* key, void* value);
+static void _map_free(void** level, long level_size);
+static void** map_free(args_Map* map);
/**
@@ -1381,12 +1385,118 @@ static void sort(char** list, long count)
}
-/*
-TODO
+/**
+ * Initialises a map
+ *
+ * @param map The address of the map
+ */
+static void map_init(args_Map* map)
+{
+ long i;
+ void** level;
+ map->keys = null;
+ map->key_count = 0;
+ map->data = level = (void**)malloc(17 * sizeof(void*));
+ for (i = 0; i < 17; i++)
+ *(level + i) = null;
+}
+
+/**
+ * Gets the value for a key in a map
+ *
+ * @param map The address of the map
+ * @param key The key
+ * @return The value, `null` if not found
+ */
+static void* map_get(args_Map* map, char* key)
+{
+ void** at = map->data;
+ while (*key)
+ {
+ long a = (long)((*key >> 4) & 15);
+ long b = (long)(*key & 15);
+ if (*(at + a))
+ at = (void**)*(at + a);
+ else
+ return null;
+ if (*(at + b))
+ at = (void**)*(at + b);
+ else
+ return null;
+ }
+ return *(at + 16);
+}
+
+/**
+ * Sets the value for a key in a map
+ *
+ * @param map The address of the map
+ * @param key The key
+ * @param value The value, `null` to remove, however this does not unlist the key
+ */
+static void map_put(args_Map* map, char* key, void* value)
+{
+ long new = false;
+ void** at = map->data;
+ long i;
+ while (*key)
+ {
+ long a = (long)((*key >> 4) & 15);
+ long b = (long)(*key & 15);
+ if (*(at + a))
+ at = (void**)*(at + a);
+ else
+ {
+ at = (void**)(*(at + a) = (void*)malloc(16 * sizeof(void*)));
+ for (i = 0; i < 16; i++)
+ *(at + i) = null;
+ new = true;
+ }
+ if (*(at + b))
+ at = (void**)*(at + b);
+ else
+ {
+ at = (void**)(*(at + a) = (void*)malloc(17 * sizeof(void*)));
+ for (i = 0; i < 17; i++)
+ *(at + i) = null;
+ new = true;
+ }
+ }
+ *(at + 16) = value;
+ if (new)
+ map->keys = realloc(map->keys, (map->key_count + 1) * sizeof(char**));
+}
+
+/**
+ * Frees a level and all sublevels in a map
+ *
+ * @param level The level
+ * @param has_value Whether the level can hold a value
+ */
+static void _map_free(void** level, long has_value)
+{
+ long i;
+ if (level == null)
+ return;
+ for (i = 0; i < 16; i++)
+ free(*(level + i));
+ if (has_value)
+ if (*(level + 16) != null)
+ free(*(level + 16));
+ free(level);
+}
-void map_init(*args_Map)
-void* map_get(*args_Map, char*)
-void map_put(*args_Map, char*, void*)
-void** map_free(*args_Map)
-*/
+/**
+ * Frees the resources of a map
+ *
+ * @param map The address of the map
+ * @return `null`-terminated array of values that you may want to free, but do free this returend array
+ */
+static void** map_free(args_Map* map)
+{
+ if (map->keys != null)
+ free(map->keys);
+ map->keys = null;
+ _map_free(map->data, true);
+}