treewide: restucture source tree per project

Signed-off-by: Max Regan <mgregan2@gmail.com>
This commit is contained in:
2017-04-20 18:12:28 -07:00
parent 6ba525b64b
commit e5acc3088c
24 changed files with 43 additions and 45 deletions

10
src/common/common.c Normal file
View File

@@ -0,0 +1,10 @@
#include "common/common.h"
void downcase(char *str)
{
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] >= 'A' && str[i] <= 'Z') {
str[i] += 'a' - 'A';
}
}
}

54
src/common/common.h Normal file
View File

@@ -0,0 +1,54 @@
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdlib.h>
#include <stdio.h>
#define MIN(a,b) ((a) > (b) ? (b) : (a))
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#define ARRAY_SIZE(x) (sizeof((x)) / (sizeof((x)[0])))
/*
* Replaces any characters from A-Z with their lowercase counterpart.
* All other characters preceding '\0' are ignored
*/
void downcase(char *str);
#ifdef DEBUG
#define DEBUG_ON 1
#else
#define DEBUG_ON 0
#endif
#define QUOTE(...) #__VA_ARGS__
#define ASSERT(x) \
if (!(x) && DEBUG_ON) { \
printf("Assert at: %s:%d <%s> : %s\n", \
__FILE__, __LINE__, \
__func__, #x); \
exit(1); \
}
#define ASSERT_MSG(x,...) \
if(!(x) && DEBUG_ON) { \
printf("Assert at: %s:%d <%s> : %s\n", \
__FILE__, __LINE__, \
__func__, #x); \
printf(__VA_ARGS__); \
exit(1); \
}
#define DEBUG_LOG(...) \
do { \
if (DEBUG_ON) { \
printf("DEBUG: %s:%d <%s> : ", \
__FILE__, __LINE__, \
__func__); \
printf(__VA_ARGS__); \
printf("\n"); \
} \
} while (0)
#endif

124
src/common/tests/test.c Normal file
View File

@@ -0,0 +1,124 @@
#include "common/tri.h"
#include "common/common.h"
#include <glib.h>
#include <stdint.h>
#define TO_PTR(x) ((void *) (uintptr_t) (x))
#define TO_INT(x) ((int) (uintptr_t) (x))
static void test_tri_get_string(void)
{
struct tri tri;
tri_init(&tri);
g_assert_cmpint(tri_add_string(&tri, "a", TO_PTR(1)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "ab", TO_PTR(2)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "abc", TO_PTR(3)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "af", TO_PTR(4)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "abd", TO_PTR(5)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "$a!0123~&.`", TO_PTR(6)), ==, 0);
g_assert_cmpint(TO_INT(tri_get_string(&tri, "a")), ==, 1);
g_assert_cmpint(TO_INT(tri_get_string(&tri, "ab")), ==, 2);
g_assert_cmpint(TO_INT(tri_get_string(&tri, "abc")), ==, 3);
g_assert_cmpint(TO_INT(tri_get_string(&tri, "af")), ==, 4);
g_assert_cmpint(TO_INT(tri_get_string(&tri, "abd")), ==, 5);
g_assert_cmpint(TO_INT(tri_get_string(&tri, "abz")), ==, 0);
g_assert_cmpint(TO_INT(tri_get_string(&tri, "ag")), ==, 0);
g_assert_cmpint(TO_INT(tri_get_string(&tri, "$a!0123~&.`")), ==, 6);
tri_free(&tri);
}
static void test_tri_prefix_match(void)
{
struct tri tri;
tri_init(&tri);
g_assert_cmpint(tri_add_string(&tri, "pr", TO_PTR(1)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "pref", TO_PTR(2)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "Z", TO_PTR(3)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "prefix", TO_PTR(4)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "blah", TO_PTR(5)), ==, 0);
g_assert_cmpint(TO_INT(tri_prefix_match(&tri, "p")), ==, 0);
g_assert_cmpint(TO_INT(tri_prefix_match(&tri, "pr")), ==, 1);
g_assert_cmpint(TO_INT(tri_prefix_match(&tri, "pre")), ==, 1);
g_assert_cmpint(TO_INT(tri_prefix_match(&tri, "pref")), ==, 2);
g_assert_cmpint(TO_INT(tri_prefix_match(&tri, "prefix10")), ==, 4);
g_assert_cmpint(TO_INT(tri_prefix_match(&tri, "asdfasdf")), ==, 0);
tri_free(&tri);
}
static void test_tri_autocomplete(void)
{
struct tri tri;
bool ambiguous;
tri_init(&tri);
g_assert_cmpint(tri_add_string(&tri, "pr", TO_PTR(1)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "pref", TO_PTR(2)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "Z", TO_PTR(3)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "prefix", TO_PTR(4)), ==, 0);
g_assert_cmpint(tri_add_string(&tri, "blah", TO_PTR(5)), ==, 0);
g_assert_null(tri_get_string_autocomplete(&tri, "p", &ambiguous));
g_assert_true(ambiguous);
g_assert_null(tri_get_string_autocomplete(&tri, "pr", &ambiguous));
g_assert_true(ambiguous);
g_assert_null(tri_get_string_autocomplete(&tri, "pre", &ambiguous));
g_assert_true(ambiguous);
g_assert_null(tri_get_string_autocomplete(&tri, "pref", &ambiguous));
g_assert_true(ambiguous);
g_assert_null(tri_get_string_autocomplete(&tri, "prefix10", &ambiguous));
g_assert_false(ambiguous);
g_assert_null(tri_get_string_autocomplete(&tri, "asdfasdf", &ambiguous));
g_assert_false(ambiguous);
g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "bla", &ambiguous)), ==, 5);
g_assert_false(ambiguous);
g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "prefi", &ambiguous)), ==, 4);
g_assert_false(ambiguous);
g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "prefix", &ambiguous)), ==, 4);
g_assert_false(ambiguous);
g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "Z", &ambiguous)), ==, 3);
g_assert_false(ambiguous);
tri_free(&tri);
}
static void test_tri_null(void)
{
struct tri tri;
tri_init(&tri);
g_assert_cmpint(tri_add_string(&tri, NULL, TO_PTR(1)), ==, -1);
g_assert_null(tri_prefix_match(&tri, NULL));
}
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/tri/get_string", test_tri_get_string);
g_test_add_func("/tri/prefix_match", test_tri_prefix_match);
g_test_add_func("/tri/autocomplete", test_tri_autocomplete);
g_test_add_func("/tri/null", test_tri_null);
return g_test_run();
}

170
src/common/tri.c Normal file
View File

@@ -0,0 +1,170 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "common/tri.h"
#include "common/common.h"
static size_t char_to_idx(char c)
{
unsigned char c2 = c;
return (size_t) c2;
}
void tri_init(struct tri *tri)
{
tri->head = malloc(sizeof(struct tri_node));
memset(tri->head, 0, sizeof(*tri->head));
}
static void tri_free_node(struct tri_node *node)
{
int i;
if (node == NULL) {
return;
}
for (i = 0; i < ARRAY_SIZE(node->nodes); i++) {
tri_free_node(node->nodes[i]);
}
free(node);
}
void tri_free(struct tri *tri) {
tri_free_node(tri->head);
}
int tri_add_string(struct tri *tri, const char *string, void *value)
{
struct tri_node *node = NULL;
int i = 0;
if (string == NULL) {
return -1;
}
if (value == NULL) {
return -1;
}
node = tri->head;
for (i = 0; i < strlen(string); i++) {
int idx = char_to_idx(string[i]);
if (node->nodes[idx] == NULL) {
node->nodes[idx] = malloc(sizeof(struct tri_node));
memset(node->nodes[idx], 0, sizeof(struct tri_node));
}
node = node->nodes[idx];
}
node->value = value;
return 0;
}
void *tri_get_string(struct tri *tri, const char *string)
{
struct tri_node *node = NULL;
int i = 0;
if (string == NULL) {
return NULL;
}
node = tri->head;
for (i = 0; i < strlen(string); i++) {
int idx = char_to_idx(string[i]);
if (node->nodes[idx] == NULL) {
return NULL;
}
node = node->nodes[idx];
}
return node->value;
}
void *tri_get_string_autocomplete(struct tri *tri, const char *string, bool *ambiguous)
{
struct tri_node *node = NULL;
int i = 0, j = 0;
*ambiguous = false;
if (string == NULL) {
return NULL;
}
node = tri->head;
for (i = 0; i < strlen(string); i++) {
int idx = char_to_idx(string[i]);
if (node->nodes[idx] == NULL) {
return NULL;
}
node = node->nodes[idx];
}
while(1) {
struct tri_node *next_node = NULL;
int num_paths = 0;
for (j = 0; j < ARRAY_SIZE(node->nodes); j++) {
if (node->nodes[j] != NULL) {
next_node = node->nodes[j];
num_paths++;
if (num_paths > 1) {
*ambiguous = true;
return NULL;
}
}
}
if (next_node == NULL) {
return node->value;
} else if (node->value != NULL && next_node != NULL) {
*ambiguous = true;
return NULL;
} else {
node = next_node;
}
}
return node->value;
}
void *tri_prefix_match(struct tri *tri, const char *string)
{
struct tri_node *node = NULL;
void *value = NULL;
int i = 0;
if (string == NULL) {
return NULL;
}
node = tri->head;
for (i = 0; i < strlen(string); i++) {
int idx = char_to_idx(string[i]);
if (node->nodes[idx] == NULL) {
return value;
}
node = node->nodes[idx];
if (node->value != NULL) {
value = node->value;
}
}
return value;
}

58
src/common/tri.h Normal file
View File

@@ -0,0 +1,58 @@
/*
* An implementation of tries.
*/
#ifndef _TRI_H_
#define _TRI_H_
#include <stdbool.h>
#define NUM_ALPHA_CHARS (256)
struct tri_node {
struct tri_node *nodes[NUM_ALPHA_CHARS];
void *value;
};
struct tri {
struct tri_node *head;
};
/**
* Initialize a tri and set its maximum depth.
*/
void tri_init(struct tri *tri);
/**
* Destroys an initialized tri and frees its internal structures.
*/
void tri_free(struct tri *tri);
/**
* Add a string as a key, and a value to the tri.
*/
int tri_add_string(struct tri *tri, const char *string, void * value);
/**
* Returns the value cooresponding to string. If the string is not in the tri, return
* NULL.
*/
void *tri_get_string(struct tri *tri, const char *string);
/**
* Returns the value cooresponding to the longest matching prefix
*/
void *tri_prefix_match(struct tri *tri, const char *string);
/**
* Using 'string' as a prefix, returns the value of the cooresponding string if there
* is only one that matches.
*
* If there are multiple possible matches, return NULL and set 'ambiguous' to true. If
* there are no possible matches, return NULL and set 'ambiguous' to false.
*/
void *tri_get_string_autocomplete(struct tri *tri, const char *string, bool *ambiguous);
#endif

24
src/common/util.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#define ARRAY_SIZE(x) (sizeof((x)) / (sizeof((x)[0]))
#define ASSERT(x) \
if (!(x)) { \
printf("Assert failed at: %s:%d <%s>\n", \
__FILE__, __LINE__, __FUNC__); \
exit(1); \
}
#define ASSERT_MSG(x, msg) \
if(!(x)) { \
printf("Assert failed at: %s:%d <%s>\n", \
__FILE__, __LINE__, __FUNC__); \
printf("%s", msg); \
exit(1); \
} \
#endif