aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--src/argparser.c126
-rw-r--r--src/argparser.h2
2 files changed, 119 insertions, 9 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);
+}
diff --git a/src/argparser.h b/src/argparser.h
index 72f2265..4fc158c 100644
--- a/src/argparser.h
+++ b/src/argparser.h
@@ -75,7 +75,7 @@ typedef struct
long key_count;
/**
- * Indefinite depth array with 17 elements per level, the last being the value at the position
+ * Indefinite depth array with 16 or 17 elements per level, the last being the value at the position. The first level has 17 elements and the levels alternates between 16 and 17 elements.
*/
void** data;