diff options
Diffstat (limited to 'navit')
-rw-r--r-- | navit/traffic.c | 112 | ||||
-rw-r--r-- | navit/traffic.h | 6 |
2 files changed, 102 insertions, 16 deletions
diff --git a/navit/traffic.c b/navit/traffic.c index 28eb8f873..66f68efd6 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -813,6 +813,40 @@ static struct map_methods traffic_map_meth = { }; /** + * @brief Whether the contents of an event are valid. + * + * This identifies any malformed events in which mandatory members are not set. + * + * @return true if the event is valid, false if it is malformed + */ +static int traffic_event_is_valid(struct traffic_event * this_) { + if (!this_->event_class || !this_->type) + return 0; + switch (this_->event_class) { + case event_class_congestion: + if ((this_->type < event_congestion_cleared) || (this_->type >= event_delay_clearance)) + return 0; + break; + case event_class_delay: + if ((this_->type < event_delay_clearance) + || (this_->type >= event_restriction_access_restrictions_lifted)) + return 0; + break; + case event_class_restriction: + if ((this_->type < event_restriction_access_restrictions_lifted) + || (this_->type > event_restriction_speed_limit_lifted)) + return 0; + break; + default: + return 0; + } + if (this_->si_count && !this_->si) + return 0; + /* TODO check SI */ + return 1; +} + +/** * @brief Determines the degree to which the attributes of a location and a map item match. * * The result of this method is used to match a location to a map item. Its result is a score—the higher @@ -1873,6 +1907,19 @@ static GList * traffic_location_get_matching_points(struct traffic_location * th } /** + * @brief Whether the contents of a location are valid. + * + * This identifies any malformed locations in which mandatory members are not set. + * + * @return true if the locations is valid, false if it is malformed + */ +static int traffic_location_is_valid(struct traffic_location * this_) { + if (!this_->at && !(this_->from && this_->to)) + return 0; + return 1; +} + +/** * @brief Generates segments affected by a traffic message. * * This translates the approximate coordinates in the `from`, `at`, `to`, `via` and `not_via` members of @@ -2507,6 +2554,36 @@ static void traffic_message_dump_to_stderr(struct traffic_message * this_) { } /** + * @brief Whether the contents of a message are valid. + * + * This identifies any malformed messages in which mandatory members are not set. + * + * @return true if the message is valid, false if it is malformed + */ +static int traffic_message_is_valid(struct traffic_message * this_) { + int i; + + if (!this_->id || !this_->id[0]) + return 0; + if (!this_->receive_time || !this_->update_time) + return 0; + if (!this_->is_cancellation) { + if (!this_->expiration_time && !this_->end_time) + return 0; + if (!this_->location) + return 0; + if (!traffic_location_is_valid(this_->location)) + return 0; + if (!this_->event_count || !this_->events) + return 0; + for (i = 0; i < this_->event_count; i++) + if (!this_->events[i] || !traffic_event_is_valid(this_->events[i])) + return 0; + } + return 1; +} + +/** * @brief Parses the events of a traffic message. * * @param message The message to parse @@ -3153,7 +3230,6 @@ static int traffic_xml_is_tagstack_valid(struct xml_state * state) { * @param values Attribute values (indices correspond to `names`) * @param data Points to a `struct xml_state` holding parser state */ -/* TODO prevent building of semantically incorrect messages */ static void traffic_xml_start(xml_context *dummy, const char *tag_name, const char **names, const char **values, void *data, GError **error) { struct xml_state * state = (struct xml_state *) data; @@ -3198,10 +3274,10 @@ static void traffic_xml_start(xml_context *dummy, const char *tag_name, const ch * @param tag_name The tag name * @param data Points to a `struct xml_state` holding parser state */ -/* TODO prevent building of semantically incorrect messages */ static void traffic_xml_end(xml_context *dummy, const char *tag_name, void *data, GError **error) { struct xml_state * state = (struct xml_state *) data; struct xml_element * el = state->tagstack ? (struct xml_element *) state->tagstack->data : NULL; + struct traffic_message * message; struct traffic_point ** point = NULL; /* Iterator and child element count */ @@ -3232,20 +3308,24 @@ static void traffic_xml_end(xml_context *dummy, const char *tag_name, void *data iter = g_list_next(iter); } } - state->messages = g_list_append(state->messages, - traffic_message_new(traffic_xml_get_attr("id", el->names, el->values), - time_new(traffic_xml_get_attr("receive_time", el->names, el->values)), - time_new(traffic_xml_get_attr("update_time", el->names, el->values)), - time_new(traffic_xml_get_attr("expiration_time", el->names, el->values)), - time_new(traffic_xml_get_attr("start_time", el->names, el->values)), - time_new(traffic_xml_get_attr("end_time", el->names, el->values)), - boolean_new(traffic_xml_get_attr("cancellation", el->names, el->values), 0), - boolean_new(traffic_xml_get_attr("forecast", el->names, el->values), 0), - /* TODO replaces */ - 0, NULL, - state->location, - count, - (struct traffic_event **) children)); + message = traffic_message_new(traffic_xml_get_attr("id", el->names, el->values), + time_new(traffic_xml_get_attr("receive_time", el->names, el->values)), + time_new(traffic_xml_get_attr("update_time", el->names, el->values)), + time_new(traffic_xml_get_attr("expiration_time", el->names, el->values)), + time_new(traffic_xml_get_attr("start_time", el->names, el->values)), + time_new(traffic_xml_get_attr("end_time", el->names, el->values)), + boolean_new(traffic_xml_get_attr("cancellation", el->names, el->values), 0), + boolean_new(traffic_xml_get_attr("forecast", el->names, el->values), 0), + /* TODO replaces */ + 0, NULL, + state->location, + count, + (struct traffic_event **) children); + if (!traffic_message_is_valid(message)) { + dbg(lvl_error, "malformed message detected, skipping\n"); + traffic_message_destroy(message); + } else + state->messages = g_list_append(state->messages, message); g_free(children); state->location = NULL; g_list_free(state->events); diff --git a/navit/traffic.h b/navit/traffic.h index 8cd41b12f..4988cc6ba 100644 --- a/navit/traffic.h +++ b/navit/traffic.h @@ -60,6 +60,7 @@ extern "C" { /** * @brief Classes for events. */ +/* If additional event classes are introduced, traffic_event_is_valid() must be adapted to recognize them. */ enum event_class { event_class_invalid = 0, /*!< Invalid event which should be ignored */ event_class_congestion, /*!< Traffic congestion, typically indicating the approximate speed */ @@ -71,6 +72,11 @@ enum event_class { /** * @brief Event types. */ +/* If additional events are introduced, remember to do the following: + * - If the events belong to an existing class, insert them right after the last existing event for that class. + * - If the events belong to a new class, insert them at the end of the list. + * - Always keep events of the same class together. + * - After adding events (of any class) at the end of the list, adapt traffic_event_is_valid() to recognize them. */ enum event_type { event_invalid = 0, /*!< Invalid event which should be ignored */ event_congestion_cleared, /*!< Traffic congestion cleared */ |