diff options
Diffstat (limited to 'libgeome_get_from_file.c')
-rw-r--r-- | libgeome_get_from_file.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/libgeome_get_from_file.c b/libgeome_get_from_file.c new file mode 100644 index 0000000..bbed448 --- /dev/null +++ b/libgeome_get_from_file.c @@ -0,0 +1,95 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +static int +parse(char *s, struct location *location) +{ + errno = 0; + + location->latitude = strtod(s, &s); + if (errno) + return -1; + + while (isspace(*s)) + s++; + if (*s == ',' || *s == ':') + s++; + while (isspace(*s)) + s++; + + location->longitude = strtod(s, &s); + if (errno) + return -1; + + while (isspace(*s) && *s != '\n') + s++; + + return (*s && *s != '\n') ? -1 : 0; +} + + +int +libgeome_get_from_file(struct libgeome_context *ctx, struct libgeome_data *out, const char *path) +{ + struct location location; + FILE *f; + char *line = NULL; + size_t size = 0; + int r; + + if (!path) + path = GEOFILE; + + f = fopen(path, "r"); + if (!f) { + if (errno == ENOENT) + ctx->print_debug(ctx, "fopen %s r: %s\n", path, strerror(errno)); + else + ctx->print_error(ctx, "fopen %s r: %s\n", path, strerror(errno)); + return 1; + } + +again: + if (getline(&line, &size, f) < 0) { + if (feof(f)) { + ctx->print_debug(ctx, "%s is empty\n", path, strerror(errno)); + } else { + if (errno == EINTR) { + clearerr(f); + goto again; + } + ctx->print_error(ctx, "getline %s: %s\n", path, strerror(errno)); + } + fclose(f); + free(line); + return 1; + } + + fclose(f); + + r = parse(line, &location); + free(line); + if (!r) { + if (!isfinite(location.latitude) || !isfinite(location.longitude)) + r = -1; + else if (location.latitude < -90 || location.latitude > 90) + r = -1; + else if (location.longitude < -180 || location.longitude > 180) + r = -1; + } + if (r) { + ctx->print_debug(ctx, "the first line of %s was not a coordinate pair\n", path, strerror(errno)); + return 1; + } + + out->requested_data &= LIBGEOME_DATUM_LATITUDE | LIBGEOME_DATUM_LONGITUDE; + if (out->requested_data) { + if (out->requested_data & LIBGEOME_DATUM_LATITUDE) + out->latitude = location.latitude; + if (out->requested_data & LIBGEOME_DATUM_LONGITUDE) + out->longitude = location.longitude; + } + + return 0; +} |