aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Krahl <me@robin-krahl.de>2016-05-31 11:45:58 +0200
committerRobin Krahl <me@robin-krahl.de>2016-05-31 11:45:58 +0200
commit9512da3f7af8193bf381080cf52e1b0d29e71e6c (patch)
tree371fb177d2d277897a8e7fa7c41c4218d64f981c
parent285c16c44b8e12aa5b7a7e71855399de7449cae4 (diff)
downloaddbfp-9512da3f7af8193bf381080cf52e1b0d29e71e6c.tar.gz
dbfp-9512da3f7af8193bf381080cf52e1b0d29e71e6c.tar.bz2
dbfp: refactoring: introduce generic object parser
This commit replaces the manual parsing of the XML location element with a generic read_object method. The structure of the element to parse and the destination of the parsed data is defined in an object_data array.
-rw-r--r--dbfp.c139
1 files changed, 80 insertions, 59 deletions
diff --git a/dbfp.c b/dbfp.c
index 0b41810..05343a1 100644
--- a/dbfp.c
+++ b/dbfp.c
@@ -26,18 +26,24 @@ struct location_data {
struct dbfp_location *locations;
};
+struct object_data {
+ const char *name;
+ int (*read)(const char **, size_t, void *);
+ void *value;
+};
+
static int dbfp_parse(void *contents, size_t len, size_t n, void *data);
static int dbfp_request(struct dbfp *dbfp, char *service, char *query,
XML_Parser parser);
static int dbfp_url(struct dbfp *dbfp, char *service, char *query, char **url);
static int check_ele_error(const char *name, const char **atts);
-static int read_string(const char **atts, size_t idx, char **str);
-static int read_float(const char **atts, size_t idx, float *f);
+static int read_string(const char **atts, size_t idx, void *value);
+static int read_float(const char **atts, size_t idx, void *value);
+static int read_object_indizes(const char **atts, struct object_data *data,
+ size_t *indizes);
+static int read_object(const char **atts, struct object_data *data);
-static int add_location(struct location_data *ld, const char **atts,
- size_t idx_name, size_t idx_id, size_t idx_lon,
- size_t idx_lat);
static void location_start(void *data, const char *name, const char **atts);
static void location_end(void *data, const char *name);
@@ -147,6 +153,7 @@ int dbfp_query_location_name(struct dbfp *dbfp, char *input,
*locations = ld.locations;
cleanup:
+ // TODO check whether the elements of ld.locations should be closed
if (err)
free(ld.locations);
if (input_enc)
@@ -235,8 +242,10 @@ static int check_ele_error(const char *name, const char **atts)
return 0;
}
-static int read_string(const char **atts, size_t idx, char **str)
+static int read_string(const char **atts, size_t idx, void *value)
{
+ char **str = (char **)value;
+
*str = strdup(atts[idx]);
if (!*str)
return ENOMEM;
@@ -244,8 +253,9 @@ static int read_string(const char **atts, size_t idx, char **str)
return 0;
}
-static int read_float(const char **atts, size_t idx, float *f)
+static int read_float(const char **atts, size_t idx, void *value)
{
+ float *f = (float *)value;
char *endptr = NULL;
errno = 0;
@@ -256,48 +266,58 @@ static int read_float(const char **atts, size_t idx, float *f)
return 0;
}
-static int add_location(struct location_data *ld, const char **atts,
- size_t idx_name, size_t idx_id, size_t idx_lon,
- size_t idx_lat)
+static int read_object_indizes(const char **atts, struct object_data *data,
+ size_t *indizes)
+{
+ size_t i;
+ size_t j;
+
+ for (i = 0; data[i].name; i++)
+ indizes[i] = 0;
+
+ for (i = 0; atts[i]; i += 2) {
+ for (j = 0; data[j].name; j++) {
+ if (strcmp(atts[i], data[j].name) == 0) {
+ indizes[j] = i + 1;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; data[i].name; i++) {
+ if (!indizes[i])
+ return DBFP_ERROR_STRUCTURE;
+ }
+
+ return 0;
+}
+
+static int read_object(const char **atts, struct object_data *data)
{
int err = 0;
- char *name = NULL;
- char *id = NULL;
- float lon;
- float lat;
+ size_t i = 0;
+ size_t n = 0;
+ size_t *indizes;
- err = read_string(atts, idx_name, &name);
- if (err)
- goto cleanup;
- err = read_string(atts, idx_id, &id);
- if (err)
- goto cleanup;
- err = read_float(atts, idx_lon, &lon);
- if (err)
- goto cleanup;
- err = read_float(atts, idx_lat, &lat);
+ for (i = 0; data[i].name; i++)
+ n++;
+
+ indizes = malloc(n * sizeof(*indizes));
+ if (!indizes)
+ return ENOMEM;
+
+ err = read_object_indizes(atts, data, indizes);
if (err)
goto cleanup;
- /* TODO(robin.krahl): don't give up the old memory if realloc fails */
- ld->locations = realloc(ld->locations,
- (ld->n + 1) * sizeof(*ld->locations));
- if (!ld->locations) {
- err = ENOMEM;
- goto cleanup;
+ for (i = 0; data[i].name; i++) {
+ err = data[i].read(atts, indizes[i], data[i].value);
+ if (err)
+ goto cleanup;
}
- ld->locations[ld->n].name = name;
- ld->locations[ld->n].id = id;
- ld->locations[ld->n].lon = lon;
- ld->locations[ld->n].lat = lat;
- ld->n++;
-
cleanup:
- if (err) {
- free(name);
- free(id);
- }
+ free(indizes);
return err;
}
@@ -307,11 +327,14 @@ static void location_start(void *data, const char *name, const char **atts)
int err = 0;
struct parse_data *pd = (struct parse_data *)data;
struct location_data *ld = (struct location_data *)pd->data;
- size_t idx_name = 0;
- size_t idx_id = 0;
- size_t idx_lon = 0;
- size_t idx_lat = 0;
- size_t i;
+ struct dbfp_location location = { NULL, NULL, 0, 0 };
+ struct object_data od[] = {
+ { "name", &read_string, &location.name },
+ { "id", &read_string, &location.id },
+ { "lon", &read_float, &location.lon },
+ { "lat", &read_float, &location.lat },
+ { NULL, NULL, NULL }
+ };
err = check_ele_error(name, atts);
if (err)
@@ -320,27 +343,25 @@ static void location_start(void *data, const char *name, const char **atts)
if (strcmp(name, "StopLocation") != 0)
goto cleanup;
- for (i = 0; atts[i]; i += 2) {
- if (strcmp(atts[i], "name") == 0)
- idx_name = i + 1;
- else if (strcmp(atts[i], "id") == 0)
- idx_id = i + 1;
- else if (strcmp(atts[i], "lon") == 0)
- idx_lon = i + 1;
- else if (strcmp(atts[i], "lat") == 0)
- idx_lat = i + 1;
- }
+ err = read_object(atts, od);
+ if (err)
+ goto cleanup;
- if (!idx_name || !idx_id || !idx_lon || !idx_lat) {
- err = DBFP_ERROR_STRUCTURE;
+ ld->locations = realloc(ld->locations,
+ (ld->n + 1) * sizeof(*ld->locations));
+ if (!ld->locations) {
+ err = ENOMEM;
goto cleanup;
}
- err = add_location(ld, atts, idx_name, idx_id, idx_lon, idx_lat);
+ ld->locations[ld->n] = location;
+ ld->n++;
cleanup:
- if (err)
+ if (err) {
+ dbfp_location_close(&location);
pd->error = err;
+ }
}
static void location_end(void *data, const char *name)