diff --git a/src/geojson.c b/src/geojson.c new file mode 100644 index 0000000..6eba032 --- /dev/null +++ b/src/geojson.c @@ -0,0 +1,119 @@ +#include "geojson.h" +#include "dijkstrasearch.h" +#include "logging.h" + +#include +#include +#include + +int add_geojson_to_dijkstra(GList **nodes, + GList **paths, + char *filename) +{ + JsonParser *parser; + JsonNode *root; + JsonArray *arr; + JsonNode *node; + JsonReader *reader; + GError *error; + + int i, j; + int i_max, j_max; + + char *name = NULL; + int x, y; + int x_last, y_last; + + struct _stats { + int nodes; + int paths; + } stats = {.nodes = 0, .paths = 0}; + + report(LL_INFO, "Loading GeoJson data from %s...", filename); + + parser = json_parser_new (); + + error = NULL; + json_parser_load_from_file(parser, filename, &error); + if (error) + { + report(LL_ERROR, "Unable to parse `%s': %s\n", filename, error->message); + g_error_free(error); + g_object_unref(parser); + return EXIT_FAILURE; + } + + root = json_parser_get_root(parser); + + arr = json_node_get_array(root); + if (arr) { + i_max = json_array_get_length(arr); + for (i = 0; i < i_max; i++) + { + node = json_array_get_element(arr, i); + if (node) { + reader = json_reader_new(node); + + json_reader_read_member(reader, "properties"); + if (json_reader_get_error(reader)) { + g_object_unref(reader); + continue; + } + json_reader_read_member(reader, "name"); + name = strdup(json_reader_get_string_value(reader)); + json_reader_end_member(reader); // name + json_reader_end_member(reader); // properties + + json_reader_read_member(reader, "geometry"); + json_reader_read_member(reader, "coordinates"); + if (json_reader_is_array(reader)) { + j_max = json_reader_count_elements(reader); + for (j = 0; j < j_max; j++) { + json_reader_read_element(reader, j); + if (json_reader_is_array(reader)) { + stats.nodes++; + json_reader_read_element(reader, 0); + x = json_reader_get_int_value(reader); + json_reader_end_element(reader); + json_reader_read_element(reader, 1); + y = json_reader_get_int_value(reader); + json_reader_end_element(reader); + + if (j > 0) { + stats.paths++; + dijkstra_path_new_to_list(nodes, paths, + x_last, y_last, + x, y, + name, 1); + } + + x_last = x; + y_last = y; + } else { + report(LL_WARNING, "err 1\n"); + } + json_reader_end_element(reader); + } + } else { + report(LL_WARNING, "err 0\n"); + } + json_reader_end_member(reader); // coordinates + json_reader_end_member(reader); // geometry + + g_object_unref(reader); + } else { + report(LL_ERROR, "Invalid geojson file.\n"); + } + } + } else { + report(LL_ERROR, "Invalid geojson file.\n"); + } + + report(LL_INFO, "Imported %d nodes and %d paths from GeoJson.", + stats.nodes, + stats.paths); + + g_object_unref (parser); + + return EXIT_SUCCESS; +} diff --git a/src/geojson.h b/src/geojson.h new file mode 100644 index 0000000..7ad3c7e --- /dev/null +++ b/src/geojson.h @@ -0,0 +1,10 @@ +#ifndef GEOJSON_H +#define GEOJSON_H + +#include + +int add_geojson_to_dijkstra(GList **nodes, + GList **paths, + char *filename); + +#endif // GEOJSON_H diff --git a/src/logging.c b/src/logging.c new file mode 100644 index 0000000..aa9f562 --- /dev/null +++ b/src/logging.c @@ -0,0 +1,60 @@ +/* ---------------------------------------------------------------------------- + * C-Report + * ---------------------------------------------------------------------------- + * Author : Markus Koch + * Contributors : None + * License : Mozilla Public License (MPL) Version 2 + * ---------------------------------------------------------------------------- +*/ + +#include "logging.h" +#include +#include +#include + +static enum log_level current_log_level = LL_INFO; + +static const char *ll_string[] = { + "\x1B[31m\x1B[1m[X] ", + "\x1B[31m[E] ", + "\x1B[33m[W] ", + "\x1B[32m[I] ", + "\x1B[34m[D] ", + "\x1B[34m[d] ", + "[?] " +}; + +int should_report(enum log_level log_level) +{ + return (log_level <= current_log_level); +} + +enum log_level report(enum log_level log_level, const char *format, ...) +{ + va_list vargs; + + if (log_level > LL_COUNT) + log_level = LL_COUNT; + + if (should_report(log_level)) { + va_start(vargs, format); + fprintf(stderr, "%s", ll_string[log_level]); + vfprintf(stderr, format, vargs); + fprintf(stderr, "\x1B[0m\n"); + va_end(vargs); + } + + return log_level; +} + +void set_log_level(enum log_level log_level) +{ + if (log_level >= LL_COUNT) + log_level = LL_COUNT - 1; + current_log_level = log_level; +} + +enum log_level get_log_level() +{ + return current_log_level; +} diff --git a/src/logging.h b/src/logging.h new file mode 100644 index 0000000..400ed74 --- /dev/null +++ b/src/logging.h @@ -0,0 +1,28 @@ +/* ---------------------------------------------------------------------------- + * C-Report + * ---------------------------------------------------------------------------- + * Author : Markus Koch + * Contributors : None + * License : Mozilla Public License (MPL) Version 2 + * ---------------------------------------------------------------------------- +*/ + + +#ifndef LOGGING_H +#define LOGGING_H + +#include + +enum log_level {LL_CRITICAL = 0, + LL_ERROR, + LL_WARNING, + LL_INFO, + LL_DEBUG, + LL_NOISY, + LL_COUNT}; +int should_report(enum log_level log_level); +enum log_level report(enum log_level log_level, const char *format, ...); +void set_log_level(enum log_level log_level); +enum log_level get_log_level(); + +#endif // LOGGING_H diff --git a/src/main.c b/src/main.c index 3b5bca0..8de7024 100644 --- a/src/main.c +++ b/src/main.c @@ -1,10 +1,46 @@ #include +#include +#include + #include "dijkstrasearch.h" #include +#include "geojson.h" +#include "logging.h" - -int main() +void add_test_map(GList **nodes, + GList **paths) { + dijkstra_path_new_to_list(nodes, + paths, + 0,0, + 0,10, + "Vertical", + 1); + + dijkstra_path_new_to_list(nodes, + paths, + 0,5, + 10,5, + "Horizontal", + 1); +} + +void help(const char *exec) +{ + fprintf(stderr, + "Usage: %s [OPTION] [FILE]...\n" + "Start the lifo-dijkstraserv routing server.\n\n" + " -s\tset output to silent\n" + " -v\tincrease verbosity. Maybe used multiple times.\n" + " -p\tport number (default 6802)\n", + exec); +} + +int main(int argc, char *argv[]) +{ + int opt; + int i; + GList *nodes = NULL; GList *paths = NULL; @@ -12,36 +48,76 @@ int main() struct dijkstra_node *node; struct dijkstra_path *path; - dijkstra_path_new_to_list(&nodes, - &paths, - 0,0, - 0,10, - "Vertical", - 1); + set_log_level(LL_INFO); - dijkstra_path_new_to_list(&nodes, - &paths, - 0,5, - 10,5, - "Horizontal", - 1); + // Process arguments + while((opt = getopt(argc, argv, "vs")) != -1) { + switch(opt) + { + case 'v': + set_log_level(get_log_level() + 1); + break; + case 's': + set_log_level(0); + break; + case ':': + case '?': + help(argv[0]); + return 1; + default: + break; + } + } + + if (optind == argc) { + help(argv[0]); + return 1; + } + + /* Parse file list */ + for (i = optind; i < argc; ++i) { + add_geojson_to_dijkstra(&nodes, &paths, argv[i]); + } + + // add_test_map(&nodes, &paths); + + if (should_report(LL_NOISY)) { + for (l = nodes; l != NULL; l = l->next) { + node = (struct dijkstra_node*) l->data; + printf("Node %p: %f,\t%f [%d paths]\n", node, node->position.x, node->position.y, g_list_length(node->paths)); + } + printf("\n"); + + for (l = paths; l != NULL; l = l->next) { + path = (struct dijkstra_path*) l->data; + printf("Path %p: %p (%f,%f) -> %p (%f,%f) \t\"%s\"\n", path, + path->source, path->source->position.x, path->source->position.y, + path->destination, path->destination->position.x, path->destination->position.y, + path->name); + } + printf("\n"); + } + + report(LL_INFO, "Created graph with %d nodes and %d paths.", + g_list_length(nodes), + g_list_length(paths)); + + // Free memory + for (l = paths; l != NULL; l = l->next) { + path = (struct dijkstra_path*) l->data; + // TODO: free(path->name); + // Currently, we reuse the existing memory block when for the + // name when cloning streets. As such, clearing it here will + // cause a double free if the street has been split. + free(path); + } + g_list_free(paths); for (l = nodes; l != NULL; l = l->next) { node = (struct dijkstra_node*) l->data; - printf("Node %p: %f,\t%f [%d paths]\n", node, node->position.x, node->position.y, g_list_length(node->paths)); + free(node); } - printf("\n"); + g_list_free(nodes); - for (l = paths; l != NULL; l = l->next) { - path = (struct dijkstra_path*) l->data; - printf("Path %p: %p (%f,%f) -> %p (%f,%f) \t\"%s\"\n", path, - path->source, path->source->position.x, path->source->position.y, - path->destination, path->destination->position.x, path->destination->position.y, - path->name); - } - - printf("\nDone.\n"); - - // TODO: Free memory return 0; }