diff options
Diffstat (limited to 'navit/attr.c')
-rw-r--r-- | navit/attr.c | 1522 |
1 files changed, 752 insertions, 770 deletions
diff --git a/navit/attr.c b/navit/attr.c index 24b6cbe6a..f7e5d1fac 100644 --- a/navit/attr.c +++ b/navit/attr.c @@ -16,10 +16,10 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ - + /** @file attr.c * @brief Attribute handling code - * + * * Structures and functions for working with attributes. * * @author Navit Team @@ -45,13 +45,13 @@ #include "xmlconfig.h" struct attr_name { - enum attr_type attr; - char *name; + enum attr_type attr; + char *name; }; /** List of attr_types with their names as strings. */ -static struct attr_name attr_names[]={ +static struct attr_name attr_names[]= { #define ATTR2(x,y) ATTR(y) #define ATTR(x) { attr_##x, #x }, @@ -67,24 +67,20 @@ static struct attr_name attr_names[]={ static GHashTable *attr_hash; -void -attr_create_hash(void) -{ - int i; - attr_hash=g_hash_table_new(g_str_hash, g_str_equal); - for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { - g_hash_table_insert(attr_hash, attr_names[i].name, GINT_TO_POINTER(attr_names[i].attr)); - } +void attr_create_hash(void) { + int i; + attr_hash=g_hash_table_new(g_str_hash, g_str_equal); + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + g_hash_table_insert(attr_hash, attr_names[i].name, GINT_TO_POINTER(attr_names[i].attr)); + } } -void -attr_destroy_hash(void) -{ - g_hash_table_destroy(attr_hash); - attr_hash=NULL; +void attr_destroy_hash(void) { + g_hash_table_destroy(attr_hash); + attr_hash=NULL; } -/** +/** * @brief Converts a string to an attr_type * * This function reads a string and returns the corresponding attr_type. @@ -92,18 +88,16 @@ attr_destroy_hash(void) * @param name The attribute name * @return The corresponding {@code attr_type}, or {@code attr_none} if the string specifies a nonexistent or invalid attribute type. */ -enum attr_type -attr_from_name(const char *name) -{ - int i; +enum attr_type attr_from_name(const char *name) { + int i; - if (attr_hash) - return GPOINTER_TO_INT(g_hash_table_lookup(attr_hash, name)); - for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { - if (! strcmp(attr_names[i].name, name)) - return attr_names[i].attr; - } - return attr_none; + if (attr_hash) + return GPOINTER_TO_INT(g_hash_table_lookup(attr_hash, name)); + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + if (! strcmp(attr_names[i].name, name)) + return attr_names[i].attr; + } + return attr_none; } @@ -111,7 +105,7 @@ static int attr_match(enum attr_type search, enum attr_type found); -/** +/** * @brief Converts an attr_type to a string * * @param attr The attribute type to be converted. @@ -119,19 +113,17 @@ static int attr_match(enum attr_type search, enum attr_type found); * The calling function should create a copy of the string if it needs to alter it or relies on the * string being available permanently. */ -char * -attr_to_name(enum attr_type attr) -{ - int i; +char *attr_to_name(enum attr_type attr) { + int i; - for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { - if (attr_names[i].attr == attr) - return attr_names[i].name; - } - return NULL; + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + if (attr_names[i].attr == attr) + return attr_names[i].name; + } + return NULL; } -/** +/** * @brief Creates an attribute from text information * * This function creates an attribute from two strings specifying the name and @@ -142,219 +134,216 @@ attr_to_name(enum attr_type attr) * @return The new attribute */ struct attr * -attr_new_from_text(const char *name, const char *value) -{ - enum attr_type attr; - struct attr *ret; - struct coord_geo *g; - struct coord c; - enum item_type item_type; - char *pos,*type_str,*str,*tok; - int min,max,count; - - ret=g_new0(struct attr, 1); - dbg(lvl_debug,"enter name='%s' value='%s'\n", name, value); - attr=attr_from_name(name); - ret->type=attr; - switch (attr) { - case attr_item_type: - ret->u.item_type=item_from_name(value); - break; - case attr_item_types: - count=0; - type_str=g_strdup(value); - str=type_str; - while ((tok=strtok(str, ","))) { - ret->u.item_types=g_realloc(ret->u.item_types, (count+2)*sizeof(enum item_type)); - item_type=item_from_name(tok); - if (item_type!=type_none) { - ret->u.item_types[count++]=item_type; - ret->u.item_types[count]=type_none; - } else { - dbg(lvl_error,"Unknown item type '%s' ignored.\n",tok); - } - str=NULL; - } - g_free(type_str); - break; - case attr_attr_types: - count=0; - type_str=g_strdup(value); - str=type_str; - while ((tok=strtok(str, ","))) { - ret->u.attr_types=g_realloc(ret->u.attr_types, (count+2)*sizeof(enum attr_type)); - ret->u.attr_types[count++]=attr_from_name(tok); - ret->u.attr_types[count]=attr_none; - str=NULL; - } - g_free(type_str); - break; - case attr_dash: - count=0; - type_str=g_strdup(value); - str=type_str; - while ((tok=strtok(str, ","))) { - ret->u.dash=g_realloc(ret->u.dash, (count+2)*sizeof(int)); - ret->u.dash[count++]=g_ascii_strtoull(tok,NULL,0); - ret->u.dash[count]=0; - str=NULL; - } - g_free(type_str); - break; - case attr_order: - case attr_sequence_range: - case attr_angle_range: - case attr_speed_range: - pos=strchr(value, '-'); - min=0; - max=32767; - if (! pos) { - sscanf(value,"%d",&min); - max=min; - } else if (pos == value) - sscanf(value,"-%d",&max); - else - sscanf(value,"%d-%d",&min, &max); - ret->u.range.min=min; - ret->u.range.max=max; - break; - default: - if (attr >= attr_type_string_begin && attr <= attr_type_string_end) { - ret->u.str=g_strdup(value); - break; - } - if (attr >= attr_type_int_begin && attr < attr_type_rel_abs_begin) { - char *tail; - if (value[0] == '0' && value[1] == 'x') - ret->u.num=strtoul(value, &tail, 0); - else - ret->u.num=strtol(value, &tail, 0); - if (*tail) { - dbg(lvl_error, "Incorrect value '%s' for attribute '%s'; expected a number. " - "Defaulting to 0.\n", value, name); - ret->u.num=0; - } - break; - } - if (attr >= attr_type_rel_abs_begin && attr < attr_type_boolean_begin) { - char *tail; - int value_is_relative=0; - ret->u.num=strtol(value, &tail, 0); - if (*tail) { - if (!strcmp(tail, "%")) { - value_is_relative=1; - } else { - dbg(lvl_error, "Incorrect value '%s' for attribute '%s'; expected a number or a relative value in percent. " - "Defaulting to 0.\n", value, name); - ret->u.num=0; - } - } - if (value_is_relative) { - if ((ret->u.num > ATTR_REL_MAXREL) || (ret->u.num < ATTR_REL_MINREL)) { - dbg(lvl_error, "Relative possibly-relative attribute with value out of range: %li\n", ret->u.num); - } - - ret->u.num += ATTR_REL_RELSHIFT; - } else { - if ((ret->u.num > ATTR_REL_MAXABS) || (ret->u.num < ATTR_REL_MINABS)) { - dbg(lvl_error, "Non-relative possibly-relative attribute with value out of range: %li\n", ret->u.num); - } - } - break; - } - if (attr >= attr_type_boolean_begin && attr <= attr_type_int_end) { - if (!(g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false"))) - ret->u.num=0; - else if (!(g_ascii_strcasecmp(value,"yes") && g_ascii_strcasecmp(value,"1") && g_ascii_strcasecmp(value,"true"))) - ret->u.num=1; - else { - dbg(lvl_error, "Incorrect value '%s' for attribute '%s'; expected a boolean (no/0/false or yes/1/true). " - "Defaulting to 'true'.\n", value, name); - ret->u.num=1; - } - break; - } - if (attr >= attr_type_color_begin && attr <= attr_type_color_end) { - struct color *color=g_new0(struct color, 1); - int r,g,b,a; - ret->u.color=color; - if(strlen(value)==7){ - sscanf(value,"#%02x%02x%02x", &r, &g, &b); - color->r = (r << 8) | r; - color->g = (g << 8) | g; - color->b = (b << 8) | b; - color->a = (65535); - } else if(strlen(value)==9){ - sscanf(value,"#%02x%02x%02x%02x", &r, &g, &b, &a); - color->r = (r << 8) | r; - color->g = (g << 8) | g; - color->b = (b << 8) | b; - color->a = (a << 8) | a; - } else { - dbg(lvl_error,"color %s has unknown format\n",value); - } - break; - } - if (attr >= attr_type_coord_geo_begin && attr <= attr_type_coord_geo_end) { - g=g_new(struct coord_geo, 1); - ret->u.coord_geo=g; - coord_parse(value, projection_mg, &c); - transform_to_geo(projection_mg, &c, g); - break; - } - dbg(lvl_debug,"unknown attribute\n"); - g_free(ret); - ret=NULL; - } - return ret; +attr_new_from_text(const char *name, const char *value) { + enum attr_type attr; + struct attr *ret; + struct coord_geo *g; + struct coord c; + enum item_type item_type; + char *pos,*type_str,*str,*tok; + int min,max,count; + + ret=g_new0(struct attr, 1); + dbg(lvl_debug,"enter name='%s' value='%s'", name, value); + attr=attr_from_name(name); + ret->type=attr; + switch (attr) { + case attr_item_type: + ret->u.item_type=item_from_name(value); + break; + case attr_item_types: + count=0; + type_str=g_strdup(value); + str=type_str; + while ((tok=strtok(str, ","))) { + ret->u.item_types=g_realloc(ret->u.item_types, (count+2)*sizeof(enum item_type)); + item_type=item_from_name(tok); + if (item_type!=type_none) { + ret->u.item_types[count++]=item_type; + ret->u.item_types[count]=type_none; + } else { + dbg(lvl_error,"Unknown item type '%s' ignored.",tok); + } + str=NULL; + } + g_free(type_str); + break; + case attr_attr_types: + count=0; + type_str=g_strdup(value); + str=type_str; + while ((tok=strtok(str, ","))) { + ret->u.attr_types=g_realloc(ret->u.attr_types, (count+2)*sizeof(enum attr_type)); + ret->u.attr_types[count++]=attr_from_name(tok); + ret->u.attr_types[count]=attr_none; + str=NULL; + } + g_free(type_str); + break; + case attr_dash: + count=0; + type_str=g_strdup(value); + str=type_str; + while ((tok=strtok(str, ","))) { + ret->u.dash=g_realloc(ret->u.dash, (count+2)*sizeof(int)); + ret->u.dash[count++]=g_ascii_strtoull(tok,NULL,0); + ret->u.dash[count]=0; + str=NULL; + } + g_free(type_str); + break; + case attr_order: + case attr_sequence_range: + case attr_angle_range: + case attr_speed_range: + pos=strchr(value, '-'); + min=0; + max=32767; + if (! pos) { + sscanf(value,"%d",&min); + max=min; + } else if (pos == value) + sscanf(value,"-%d",&max); + else + sscanf(value,"%d-%d",&min, &max); + ret->u.range.min=min; + ret->u.range.max=max; + break; + default: + if (attr >= attr_type_string_begin && attr <= attr_type_string_end) { + ret->u.str=g_strdup(value); + break; + } + if (attr >= attr_type_int_begin && attr < attr_type_rel_abs_begin) { + char *tail; + if (value[0] == '0' && value[1] == 'x') + ret->u.num=strtoul(value, &tail, 0); + else + ret->u.num=strtol(value, &tail, 0); + if (*tail) { + dbg(lvl_error, "Incorrect value '%s' for attribute '%s'; expected a number. " + "Defaulting to 0.\n", value, name); + ret->u.num=0; + } + break; + } + if (attr >= attr_type_rel_abs_begin && attr < attr_type_boolean_begin) { + char *tail; + int value_is_relative=0; + ret->u.num=strtol(value, &tail, 0); + if (*tail) { + if (!strcmp(tail, "%")) { + value_is_relative=1; + } else { + dbg(lvl_error, "Incorrect value '%s' for attribute '%s'; expected a number or a relative value in percent. " + "Defaulting to 0.\n", value, name); + ret->u.num=0; + } + } + if (value_is_relative) { + if ((ret->u.num > ATTR_REL_MAXREL) || (ret->u.num < ATTR_REL_MINREL)) { + dbg(lvl_error, "Relative possibly-relative attribute with value out of range: %li", ret->u.num); + } + + ret->u.num += ATTR_REL_RELSHIFT; + } else { + if ((ret->u.num > ATTR_REL_MAXABS) || (ret->u.num < ATTR_REL_MINABS)) { + dbg(lvl_error, "Non-relative possibly-relative attribute with value out of range: %li", ret->u.num); + } + } + break; + } + if (attr >= attr_type_boolean_begin && attr <= attr_type_int_end) { + if (!(g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false"))) + ret->u.num=0; + else if (!(g_ascii_strcasecmp(value,"yes") && g_ascii_strcasecmp(value,"1") && g_ascii_strcasecmp(value,"true"))) + ret->u.num=1; + else { + dbg(lvl_error, "Incorrect value '%s' for attribute '%s'; expected a boolean (no/0/false or yes/1/true). " + "Defaulting to 'true'.\n", value, name); + ret->u.num=1; + } + break; + } + if (attr >= attr_type_color_begin && attr <= attr_type_color_end) { + struct color *color=g_new0(struct color, 1); + int r,g,b,a; + ret->u.color=color; + if(strlen(value)==7) { + sscanf(value,"#%02x%02x%02x", &r, &g, &b); + color->r = (r << 8) | r; + color->g = (g << 8) | g; + color->b = (b << 8) | b; + color->a = (65535); + } else if(strlen(value)==9) { + sscanf(value,"#%02x%02x%02x%02x", &r, &g, &b, &a); + color->r = (r << 8) | r; + color->g = (g << 8) | g; + color->b = (b << 8) | b; + color->a = (a << 8) | a; + } else { + dbg(lvl_error,"color %s has unknown format",value); + } + break; + } + if (attr >= attr_type_coord_geo_begin && attr <= attr_type_coord_geo_end) { + g=g_new(struct coord_geo, 1); + ret->u.coord_geo=g; + coord_parse(value, projection_mg, &c); + transform_to_geo(projection_mg, &c, g); + break; + } + dbg(lvl_debug,"unknown attribute"); + g_free(ret); + ret=NULL; + } + return ret; } -/** +/** * @brief Converts access flags to a human-readable string. * * @param flags The flags as a number * @return The flags in human-readable form */ -static char * -flags_to_text(int flags) -{ - char *ret=g_strdup_printf("0x%x:",flags); - if (flags & AF_ONEWAY) ret=g_strconcat_printf(ret,"%sAF_ONEWAY",ret?"|":""); - if (flags & AF_ONEWAYREV) ret=g_strconcat_printf(ret,"%sAF_ONEWAYREV",ret?"|":""); - if (flags & AF_SEGMENTED) ret=g_strconcat_printf(ret,"%sAF_SEGMENTED",ret?"|":""); - if (flags & AF_ROUNDABOUT) ret=g_strconcat_printf(ret,"%sAF_ROUNDABOUT",ret?"|":""); - if (flags & AF_ROUNDABOUT_VALID) ret=g_strconcat_printf(ret,"%sAF_ROUNDABOUT_VALID",ret?"|":""); - if (flags & AF_ONEWAY_EXCEPTION) ret=g_strconcat_printf(ret,"%sAF_ONEWAY_EXCEPTION",ret?"|":""); - if (flags & AF_SPEED_LIMIT) ret=g_strconcat_printf(ret,"%sAF_SPEED_LIMIT",ret?"|":""); - if (flags & AF_RESERVED1) ret=g_strconcat_printf(ret,"%sAF_RESERVED1",ret?"|":""); - if (flags & AF_SIZE_OR_WEIGHT_LIMIT) ret=g_strconcat_printf(ret,"%sAF_SIZE_OR_WEIGHT_LIMIT",ret?"|":""); - if (flags & AF_THROUGH_TRAFFIC_LIMIT) ret=g_strconcat_printf(ret,"%sAF_THROUGH_TRAFFIC_LIMIT",ret?"|":""); - if (flags & AF_TOLL) ret=g_strconcat_printf(ret,"%sAF_TOLL",ret?"|":""); - if (flags & AF_SEASONAL) ret=g_strconcat_printf(ret,"%sAF_SEASONAL",ret?"|":""); - if (flags & AF_UNPAVED) ret=g_strconcat_printf(ret,"%sAF_UNPAVED",ret?"|":""); - if (flags & AF_FORD) ret=g_strconcat_printf(ret,"%sAF_FORD",ret?"|":""); - if (flags & AF_UNDERGROUND) ret=g_strconcat_printf(ret,"%sAF_UNDERGROUND",ret?"|":""); - if (flags & AF_DANGEROUS_GOODS) ret=g_strconcat_printf(ret,"%sAF_DANGEROUS_GOODS",ret?"|":""); - if ((flags & AF_ALL) == AF_ALL) - return g_strconcat_printf(ret,"%sAF_ALL",ret?"|":""); - if ((flags & AF_ALL) == AF_MOTORIZED_FAST) - return g_strconcat_printf(ret,"%sAF_MOTORIZED_FAST",ret?"|":""); - if (flags & AF_EMERGENCY_VEHICLES) ret=g_strconcat_printf(ret,"%sAF_EMERGENCY_VEHICLES",ret?"|":""); - if (flags & AF_TRANSPORT_TRUCK) ret=g_strconcat_printf(ret,"%sAF_TRANSPORT_TRUCK",ret?"|":""); - if (flags & AF_DELIVERY_TRUCK) ret=g_strconcat_printf(ret,"%sAF_DELIVERY_TRUCK",ret?"|":""); - if (flags & AF_PUBLIC_BUS) ret=g_strconcat_printf(ret,"%sAF_PUBLIC_BUS",ret?"|":""); - if (flags & AF_TAXI) ret=g_strconcat_printf(ret,"%sAF_TAXI",ret?"|":""); - if (flags & AF_HIGH_OCCUPANCY_CAR) ret=g_strconcat_printf(ret,"%sAF_HIGH_OCCUPANCY_CAR",ret?"|":""); - if (flags & AF_CAR) ret=g_strconcat_printf(ret,"%sAF_CAR",ret?"|":""); - if (flags & AF_MOTORCYCLE) ret=g_strconcat_printf(ret,"%sAF_MOTORCYCLE",ret?"|":""); - if (flags & AF_MOPED) ret=g_strconcat_printf(ret,"%sAF_MOPED",ret?"|":""); - if (flags & AF_HORSE) ret=g_strconcat_printf(ret,"%sAF_HORSE",ret?"|":""); - if (flags & AF_BIKE) ret=g_strconcat_printf(ret,"%sAF_BIKE",ret?"|":""); - if (flags & AF_PEDESTRIAN) ret=g_strconcat_printf(ret,"%sAF_PEDESTRIAN",ret?"|":""); - return ret; +static char *flags_to_text(int flags) { + char *ret=g_strdup_printf("0x%x:",flags); + if (flags & AF_ONEWAY) ret=g_strconcat_printf(ret,"%sAF_ONEWAY",ret?"|":""); + if (flags & AF_ONEWAYREV) ret=g_strconcat_printf(ret,"%sAF_ONEWAYREV",ret?"|":""); + if (flags & AF_SEGMENTED) ret=g_strconcat_printf(ret,"%sAF_SEGMENTED",ret?"|":""); + if (flags & AF_ROUNDABOUT) ret=g_strconcat_printf(ret,"%sAF_ROUNDABOUT",ret?"|":""); + if (flags & AF_ROUNDABOUT_VALID) ret=g_strconcat_printf(ret,"%sAF_ROUNDABOUT_VALID",ret?"|":""); + if (flags & AF_ONEWAY_EXCEPTION) ret=g_strconcat_printf(ret,"%sAF_ONEWAY_EXCEPTION",ret?"|":""); + if (flags & AF_SPEED_LIMIT) ret=g_strconcat_printf(ret,"%sAF_SPEED_LIMIT",ret?"|":""); + if (flags & AF_RESERVED1) ret=g_strconcat_printf(ret,"%sAF_RESERVED1",ret?"|":""); + if (flags & AF_SIZE_OR_WEIGHT_LIMIT) ret=g_strconcat_printf(ret,"%sAF_SIZE_OR_WEIGHT_LIMIT",ret?"|":""); + if (flags & AF_THROUGH_TRAFFIC_LIMIT) ret=g_strconcat_printf(ret,"%sAF_THROUGH_TRAFFIC_LIMIT",ret?"|":""); + if (flags & AF_TOLL) ret=g_strconcat_printf(ret,"%sAF_TOLL",ret?"|":""); + if (flags & AF_SEASONAL) ret=g_strconcat_printf(ret,"%sAF_SEASONAL",ret?"|":""); + if (flags & AF_UNPAVED) ret=g_strconcat_printf(ret,"%sAF_UNPAVED",ret?"|":""); + if (flags & AF_FORD) ret=g_strconcat_printf(ret,"%sAF_FORD",ret?"|":""); + if (flags & AF_UNDERGROUND) ret=g_strconcat_printf(ret,"%sAF_UNDERGROUND",ret?"|":""); + if (flags & AF_DANGEROUS_GOODS) ret=g_strconcat_printf(ret,"%sAF_DANGEROUS_GOODS",ret?"|":""); + if ((flags & AF_ALL) == AF_ALL) + return g_strconcat_printf(ret,"%sAF_ALL",ret?"|":""); + if ((flags & AF_ALL) == AF_MOTORIZED_FAST) + return g_strconcat_printf(ret,"%sAF_MOTORIZED_FAST",ret?"|":""); + if (flags & AF_EMERGENCY_VEHICLES) ret=g_strconcat_printf(ret,"%sAF_EMERGENCY_VEHICLES",ret?"|":""); + if (flags & AF_TRANSPORT_TRUCK) ret=g_strconcat_printf(ret,"%sAF_TRANSPORT_TRUCK",ret?"|":""); + if (flags & AF_DELIVERY_TRUCK) ret=g_strconcat_printf(ret,"%sAF_DELIVERY_TRUCK",ret?"|":""); + if (flags & AF_PUBLIC_BUS) ret=g_strconcat_printf(ret,"%sAF_PUBLIC_BUS",ret?"|":""); + if (flags & AF_TAXI) ret=g_strconcat_printf(ret,"%sAF_TAXI",ret?"|":""); + if (flags & AF_HIGH_OCCUPANCY_CAR) ret=g_strconcat_printf(ret,"%sAF_HIGH_OCCUPANCY_CAR",ret?"|":""); + if (flags & AF_CAR) ret=g_strconcat_printf(ret,"%sAF_CAR",ret?"|":""); + if (flags & AF_MOTORCYCLE) ret=g_strconcat_printf(ret,"%sAF_MOTORCYCLE",ret?"|":""); + if (flags & AF_MOPED) ret=g_strconcat_printf(ret,"%sAF_MOPED",ret?"|":""); + if (flags & AF_HORSE) ret=g_strconcat_printf(ret,"%sAF_HORSE",ret?"|":""); + if (flags & AF_BIKE) ret=g_strconcat_printf(ret,"%sAF_BIKE",ret?"|":""); + if (flags & AF_PEDESTRIAN) ret=g_strconcat_printf(ret,"%sAF_PEDESTRIAN",ret?"|":""); + return ret; } -/** +/** * @brief Converts attribute data to human-readable text * * @param attr The attribute to be formatted @@ -370,119 +359,119 @@ flags_to_text(int flags) * @return The attribute data in human-readable form. The caller is responsible for calling {@code g_free()} on * the result when it is no longer needed. */ -char * -attr_to_text_ext(struct attr *attr, char *sep, enum attr_format fmt, enum attr_format def_fmt, struct map *map) -{ - char *ret; - enum attr_type type=attr->type; - - if (!sep) - sep=""; - - if (type >= attr_type_item_begin && type <= attr_type_item_end) { - struct item *item=attr->u.item; - struct attr type, data; - if (! item) - return g_strdup("(nil)"); - if (! item->map || !map_get_attr(item->map, attr_type, &type, NULL)) - type.u.str=""; - if (! item->map || !map_get_attr(item->map, attr_data, &data, NULL)) - data.u.str=""; - return g_strdup_printf("type=0x%x id=0x%x,0x%x map=%p (%s:%s)", item->type, item->id_hi, item->id_lo, item->map, type.u.str, data.u.str); - } - if (type >= attr_type_string_begin && type <= attr_type_string_end) { - if (map) { - char *mstr; - if (attr->u.str) { - mstr=map_convert_string(map, attr->u.str); - ret=g_strdup(mstr); - map_convert_free(mstr); - } else - ret=g_strdup("(null)"); - - } else - ret=g_strdup(attr->u.str); - return ret; - } - if (type == attr_flags || type == attr_through_traffic_flags) - return flags_to_text(attr->u.num); - if (type == attr_destination_length) { - if (fmt == attr_format_with_units) { - double distance=attr->u.num; - if (distance > 10000) - return g_strdup_printf("%.0f%skm",distance/1000,sep); - return g_strdup_printf("%.1f%skm",distance/1000,sep); - } - } - if (type == attr_destination_time) { - if (fmt == attr_format_with_units) { - int seconds=(attr->u.num+5)/10; - int minutes=seconds/60; - int hours=minutes/60; - int days=hours/24; - hours%=24; - minutes%=60; - seconds%=60; - if (days) - return g_strdup_printf("%d:%02d:%02d:%02d",days,hours,minutes,seconds); - if (hours) - return g_strdup_printf("%02d:%02d:%02d",hours,minutes,seconds); - return g_strdup_printf("%02d:%02d",minutes,seconds); - } - } - if (type >= attr_type_int_begin && type <= attr_type_int_end) - return g_strdup_printf("%ld", attr->u.num); - if (type >= attr_type_int64_begin && type <= attr_type_int64_end) - return g_strdup_printf(LONGLONG_FMT, *attr->u.num64); - if (type >= attr_type_double_begin && type <= attr_type_double_end) - return g_strdup_printf("%f", *attr->u.numd); - if (type >= attr_type_object_begin && type <= attr_type_object_end) - return g_strdup_printf("(object[%s])", attr_to_name(type)); - if (type >= attr_type_color_begin && type <= attr_type_color_end) { - if (attr->u.color->a != 65535) - return g_strdup_printf("#%02x%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8, attr->u.color->a>>8); - else - return g_strdup_printf("#%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8); - } - if (type >= attr_type_coord_geo_begin && type <= attr_type_coord_geo_end) - return g_strdup_printf("%f %f",attr->u.coord_geo->lng,attr->u.coord_geo->lat); - if (type == attr_zipfile_ref_block) { - int *data=attr->u.data; - return g_strdup_printf("0x%x,0x%x,0x%x",data[0],data[1],data[2]); - } - if (type == attr_item_id) { - int *data=attr->u.data; - return g_strdup_printf("0x%x,0x%x",data[0],data[1]); - } - if (type == attr_item_types) { - enum item_type *item_types=attr->u.item_types; - char *sep="",*ret=NULL; - while (item_types && *item_types) { - ret=g_strconcat_printf(ret,"%s%s",sep,item_to_name(*item_types++)); - sep=","; - } - return ret; - } - if (type >= attr_type_group_begin && type <= attr_type_group_end) { - int i=0; - char *ret=g_strdup(""); - char *sep=""; - while (attr->u.attrs[i].type) { - char *val=attr_to_text_ext(&attr->u.attrs[i], sep, fmt, def_fmt, map); - ret=g_strconcat_printf(ret,"%s%s=%s",sep,attr_to_name(attr->u.attrs[i].type),val); - g_free(val); - sep=" "; - i++; - } - return ret; - } - if (type >= attr_type_item_type_begin && type <= attr_type_item_type_end) { - return g_strdup_printf("0x%ld[%s]",attr->u.num,item_to_name(attr->u.num)); - } - if (type == attr_nav_status) { - return nav_status_to_text(attr->u.num); - } - return g_strdup_printf("(no text[%s])", attr_to_name(type)); +char *attr_to_text_ext(struct attr *attr, char *sep, enum attr_format fmt, enum attr_format def_fmt, struct map *map) { + char *ret; + enum attr_type type=attr->type; + + if (!sep) + sep=""; + + if (type >= attr_type_item_begin && type <= attr_type_item_end) { + struct item *item=attr->u.item; + struct attr type, data; + if (! item) + return g_strdup("(nil)"); + if (! item->map || !map_get_attr(item->map, attr_type, &type, NULL)) + type.u.str=""; + if (! item->map || !map_get_attr(item->map, attr_data, &data, NULL)) + data.u.str=""; + return g_strdup_printf("type=0x%x id=0x%x,0x%x map=%p (%s:%s)", item->type, item->id_hi, item->id_lo, item->map, + type.u.str, data.u.str); + } + if (type >= attr_type_string_begin && type <= attr_type_string_end) { + if (map) { + char *mstr; + if (attr->u.str) { + mstr=map_convert_string(map, attr->u.str); + ret=g_strdup(mstr); + map_convert_free(mstr); + } else + ret=g_strdup("(null)"); + + } else + ret=g_strdup(attr->u.str); + return ret; + } + if (type == attr_flags || type == attr_through_traffic_flags) + return flags_to_text(attr->u.num); + if (type == attr_destination_length) { + if (fmt == attr_format_with_units) { + double distance=attr->u.num; + if (distance > 10000) + return g_strdup_printf("%.0f%skm",distance/1000,sep); + return g_strdup_printf("%.1f%skm",distance/1000,sep); + } + } + if (type == attr_destination_time) { + if (fmt == attr_format_with_units) { + int seconds=(attr->u.num+5)/10; + int minutes=seconds/60; + int hours=minutes/60; + int days=hours/24; + hours%=24; + minutes%=60; + seconds%=60; + if (days) + return g_strdup_printf("%d:%02d:%02d:%02d",days,hours,minutes,seconds); + if (hours) + return g_strdup_printf("%02d:%02d:%02d",hours,minutes,seconds); + return g_strdup_printf("%02d:%02d",minutes,seconds); + } + } + if (type >= attr_type_int_begin && type <= attr_type_int_end) + return g_strdup_printf("%ld", attr->u.num); + if (type >= attr_type_int64_begin && type <= attr_type_int64_end) + return g_strdup_printf(LONGLONG_FMT, *attr->u.num64); + if (type >= attr_type_double_begin && type <= attr_type_double_end) + return g_strdup_printf("%f", *attr->u.numd); + if (type >= attr_type_object_begin && type <= attr_type_object_end) + return g_strdup_printf("(object[%s])", attr_to_name(type)); + if (type >= attr_type_color_begin && type <= attr_type_color_end) { + if (attr->u.color->a != 65535) + return g_strdup_printf("#%02x%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8, + attr->u.color->a>>8); + else + return g_strdup_printf("#%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8); + } + if (type >= attr_type_coord_geo_begin && type <= attr_type_coord_geo_end) + return g_strdup_printf("%f %f",attr->u.coord_geo->lng,attr->u.coord_geo->lat); + if (type == attr_zipfile_ref_block) { + int *data=attr->u.data; + return g_strdup_printf("0x%x,0x%x,0x%x",data[0],data[1],data[2]); + } + if (type == attr_item_id) { + int *data=attr->u.data; + return g_strdup_printf("0x%x,0x%x",data[0],data[1]); + } + if (type == attr_item_types) { + enum item_type *item_types=attr->u.item_types; + char *sep="",*ret=NULL; + while (item_types && *item_types) { + ret=g_strconcat_printf(ret,"%s%s",sep,item_to_name(*item_types++)); + sep=","; + } + return ret; + } + if (type >= attr_type_group_begin && type <= attr_type_group_end) { + int i=0; + char *ret=g_strdup(""); + char *sep=""; + while (attr->u.attrs[i].type) { + char *val=attr_to_text_ext(&attr->u.attrs[i], sep, fmt, def_fmt, map); + ret=g_strconcat_printf(ret,"%s%s=%s",sep,attr_to_name(attr->u.attrs[i].type),val); + g_free(val); + sep=" "; + i++; + } + return ret; + } + if (type >= attr_type_item_type_begin && type <= attr_type_item_type_end) { + return g_strdup_printf("0x%ld[%s]",attr->u.num,item_to_name(attr->u.num)); + } + if (type == attr_nav_status) { + return nav_status_to_text(attr->u.num); + } + return g_strdup_printf("(no text[%s])", attr_to_name(type)); } /** @@ -494,13 +483,11 @@ attr_to_text_ext(struct attr *attr, char *sep, enum attr_format fmt, enum attr_f * @param map The translation map, see {@code attr_to_text_ext()} * @param pretty Not used */ -char * -attr_to_text(struct attr *attr, struct map *map, int pretty) -{ - return attr_to_text_ext(attr, NULL, attr_format_default, attr_format_default, map); +char *attr_to_text(struct attr *attr, struct map *map, int pretty) { + return attr_to_text_ext(attr, NULL, attr_format_default, attr_format_default, map); } -/** +/** * @brief Searches for an attribute of a given type * * This function searches an array of pointers to attributes for a given @@ -513,35 +500,32 @@ attr_to_text(struct attr *attr, struct map *map, int pretty) * @return Pointer to the first matching attribute, or NULL if no match was found. */ struct attr * -attr_search(struct attr **attrs, struct attr *last, enum attr_type attr) -{ - dbg(lvl_info, "enter attrs=%p\n", attrs); - while (*attrs) { - dbg(lvl_debug,"*attrs=%p\n", *attrs); - if ((*attrs)->type == attr) { - return *attrs; - } - attrs++; - } - return NULL; -} - -static int -attr_match(enum attr_type search, enum attr_type found) -{ - switch (search) { - case attr_any: - return 1; - case attr_any_xml: - switch (found) { - case attr_callback: - return 0; - default: - return 1; - } - default: - return search == found; - } +attr_search(struct attr **attrs, struct attr *last, enum attr_type attr) { + dbg(lvl_info, "enter attrs=%p", attrs); + while (*attrs) { + dbg(lvl_debug,"*attrs=%p", *attrs); + if ((*attrs)->type == attr) { + return *attrs; + } + attrs++; + } + return NULL; +} + +static int attr_match(enum attr_type search, enum attr_type found) { + switch (search) { + case attr_any: + return 1; + case attr_any_xml: + switch (found) { + case attr_callback: + return 0; + default: + return 1; + } + default: + return search == found; + } } /** @@ -570,31 +554,30 @@ attr_match(enum attr_type search, enum attr_type found) * @param iter An iterator. This parameter may be NULL. * @return True if a matching attribute was found, false if not. */ -int -attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, struct attr_iter *iter) -{ - while (attrs && *attrs) { - if (attr_match(type,(*attrs)->type)) { - *attr=**attrs; - if (!iter) - return 1; - if (*((void **)iter) < (void *)attrs) { - *((void **)iter)=(void *)attrs; - return 1; - } - } - attrs++; - } - if (type == attr_any || type == attr_any_xml) - return 0; - while (def_attrs && *def_attrs) { - if ((*def_attrs)->type == type) { - *attr=**def_attrs; - return 1; - } - def_attrs++; - } - return 0; +int attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, + struct attr_iter *iter) { + while (attrs && *attrs) { + if (attr_match(type,(*attrs)->type)) { + *attr=**attrs; + if (!iter) + return 1; + if (*((void **)iter) < (void *)attrs) { + *((void **)iter)=(void *)attrs; + return 1; + } + } + attrs++; + } + if (type == attr_any || type == attr_any_xml) + return 0; + while (def_attrs && *def_attrs) { + if ((*def_attrs)->type == type) { + *attr=**def_attrs; + return 1; + } + def_attrs++; + } + return 0; } /** @@ -605,32 +588,32 @@ attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_ty * contain an attribute whose type matches that of the new one, the new * attribute is inserted into the list. * - * @param attrs Points to the array of attribute pointers to be updated + * @param attrs Points to the array of attribute pointers to be updated (if NULL, this function will + * create a new list containing only the new attribute) * @param attr The new attribute. * @return Pointer to the updated attribute list */ struct attr ** -attr_generic_set_attr(struct attr **attrs, struct attr *attr) -{ - struct attr **curr=attrs; - int i,count=0; - dbg(lvl_debug, "enter, attrs=%p, attr=%p (%s)\n", attrs, attr, attr_to_name(attr->type)); - while (curr && *curr) { - if ((*curr)->type == attr->type) { - attr_free(*curr); - *curr=attr_dup(attr); - return attrs; - } - curr++; - count++; - } - curr=g_new0(struct attr *, count+2); - for (i = 0 ; i < count ; i++) - curr[i]=attrs[i]; - curr[count]=attr_dup(attr); - curr[count+1]=NULL; - g_free(attrs); - return curr; +attr_generic_set_attr(struct attr **attrs, struct attr *attr) { + struct attr **curr=attrs; + int i,count=0; + dbg(lvl_debug, "enter, attrs=%p, attr=%p (%s)", attrs, attr, attr_to_name(attr->type)); + while (curr && *curr) { + if ((*curr)->type == attr->type) { + attr_free(*curr); + *curr=attr_dup(attr); + return attrs; + } + curr++; + count++; + } + curr=g_new0(struct attr *, count+2); + for (i = 0 ; i < count ; i++) + curr[i]=attrs[i]; + curr[count]=attr_dup(attr); + curr[count+1]=NULL; + g_free(attrs); + return curr; } /** @@ -643,331 +626,335 @@ attr_generic_set_attr(struct attr **attrs, struct attr *attr) * @return Pointer to the updated attribute list */ struct attr ** -attr_generic_add_attr(struct attr **attrs, struct attr *attr) -{ - struct attr **curr=attrs; - int i,count=0; - dbg(lvl_debug, "enter, attrs=%p, attr=%p (%s)\n", attrs, attr, attr_to_name(attr->type)); - while (curr && *curr) { - curr++; - count++; - } - curr=g_new0(struct attr *, count+2); - for (i = 0 ; i < count ; i++) - curr[i]=attrs[i]; - curr[count]=attr_dup(attr); - curr[count+1]=NULL; - g_free(attrs); - return curr; +attr_generic_add_attr(struct attr **attrs, struct attr *attr) { + struct attr **curr=attrs; + int i,count=0; + dbg(lvl_debug, "enter, attrs=%p, attr=%p (%s)", attrs, attr, attr_to_name(attr->type)); + while (curr && *curr) { + curr++; + count++; + } + curr=g_new0(struct attr *, count+2); + for (i = 0 ; i < count ; i++) + curr[i]=attrs[i]; + curr[count]=attr_dup(attr); + curr[count+1]=NULL; + g_free(attrs); + return curr; } struct attr ** -attr_generic_add_attr_list(struct attr **attrs, struct attr **add) -{ - while (add && *add) { - attrs=attr_generic_add_attr(attrs, *add); - add++; - } - return attrs; +attr_generic_add_attr_list(struct attr **attrs, struct attr **add) { + while (add && *add) { + attrs=attr_generic_add_attr(attrs, *add); + add++; + } + return attrs; } struct attr ** -attr_generic_prepend_attr(struct attr **attrs, struct attr *attr) -{ - struct attr **curr=attrs; - int i,count=0; - while (curr && *curr) { - curr++; - count++; - } - curr=g_new0(struct attr *, count+2); - for (i = 0 ; i < count ; i++) - curr[i+1]=attrs[i]; - curr[0]=attr_dup(attr); - curr[count+1]=NULL; - g_free(attrs); - return curr; +attr_generic_prepend_attr(struct attr **attrs, struct attr *attr) { + struct attr **curr=attrs; + int i,count=0; + while (curr && *curr) { + curr++; + count++; + } + curr=g_new0(struct attr *, count+2); + for (i = 0 ; i < count ; i++) + curr[i+1]=attrs[i]; + curr[0]=attr_dup(attr); + curr[count+1]=NULL; + g_free(attrs); + return curr; } +/** + * @brief Removes an attribute from an attribute list. + * + * If `attrs` contains `attr`, a new attribute list is created (which contains all attributes, except + * for `attr`) and both `attrs` (the original attribute list) and `attr` are freed. + * + * If `attrs` does not contain `attr`, this function is a no-op. + * + * @param attrs The attribute list + * @param attr The attribute to remove from the list + * + * @return The new attribute list + */ struct attr ** -attr_generic_remove_attr(struct attr **attrs, struct attr *attr) -{ - struct attr **curr=attrs; - int i,j,count=0,found=0; - while (curr && *curr) { - if ((*curr)->type == attr->type && (*curr)->u.data == attr->u.data) - found=1; - curr++; - count++; - } - if (!found) - return attrs; - curr=g_new0(struct attr *, count); - j=0; - for (i = 0 ; i < count ; i++) { - if (attrs[i]->type != attr->type || attrs[i]->u.data != attr->u.data) - curr[j++]=attrs[i]; - else - attr_free(attrs[i]); - } - curr[j]=NULL; - g_free(attrs); - return curr; -} - -enum attr_type -attr_type_begin(enum attr_type type) -{ - if (type < attr_type_item_begin) - return attr_none; - if (type < attr_type_int_begin) - return attr_type_item_begin; - if (type < attr_type_string_begin) - return attr_type_int_begin; - if (type < attr_type_special_begin) - return attr_type_string_begin; - if (type < attr_type_double_begin) - return attr_type_special_begin; - if (type < attr_type_coord_geo_begin) - return attr_type_double_begin; - if (type < attr_type_color_begin) - return attr_type_coord_geo_begin; - if (type < attr_type_object_begin) - return attr_type_color_begin; - if (type < attr_type_coord_begin) - return attr_type_object_begin; - if (type < attr_type_pcoord_begin) - return attr_type_coord_begin; - if (type < attr_type_callback_begin) - return attr_type_pcoord_begin; - if (type < attr_type_int64_begin) - return attr_type_callback_begin; - if (type <= attr_type_int64_end) - return attr_type_int64_begin; - return attr_none; -} - -int -attr_data_size(struct attr *attr) -{ - if (attr->type == attr_none) - return 0; - if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) - return attr->u.str?strlen(attr->u.str)+1:0; - if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) - return sizeof(attr->u.num); - if (attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end) - return sizeof(*attr->u.coord_geo); - if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end) - return sizeof(*attr->u.color); - if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) - return sizeof(void *); - if (attr->type >= attr_type_item_begin && attr->type <= attr_type_item_end) - return sizeof(struct item); - if (attr->type >= attr_type_int64_begin && attr->type <= attr_type_int64_end) - return sizeof(*attr->u.num64); - if (attr->type == attr_order) - return sizeof(attr->u.range); - if (attr->type >= attr_type_double_begin && attr->type <= attr_type_double_end) - return sizeof(*attr->u.numd); - if (attr->type == attr_item_types) { - int i=0; - while (attr->u.item_types[i++] != type_none); - return i*sizeof(enum item_type); - } - if (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end) - return sizeof(enum item_type); - if (attr->type == attr_attr_types) { - int i=0; - while (attr->u.attr_types[i++] != attr_none); - return i*sizeof(enum attr_type); - } - dbg(lvl_error,"size for %s unknown\n", attr_to_name(attr->type)); - return 0; -} - -void * -attr_data_get(struct attr *attr) -{ - if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) || - (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end)) - return &attr->u.num; - if (attr->type == attr_order) - return &attr->u.range; - return attr->u.data; -} - -void -attr_data_set(struct attr *attr, void *data) -{ - if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) || - (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end)) - attr->u.num=*((int *)data); - else - attr->u.data=data; -} - -void -attr_data_set_le(struct attr * attr, void * data) -{ - if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) || - (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end)) - attr->u.num=le32_to_cpu(*((int *)data)); - else if (attr->type == attr_order) { - attr->u.num=le32_to_cpu(*((int *)data)); - attr->u.range.min=le16_to_cpu(attr->u.range.min); - attr->u.range.max=le16_to_cpu(attr->u.range.max); - } - else -/* Fixme: Handle long long */ - attr->u.data=data; - -} - -static void -attr_free_content_do(struct attr *attr) -{ - if (!attr) - return; - if (HAS_OBJECT_FUNC(attr->type)) { - struct navit_object *obj=attr->u.data; - if (obj && obj->func && obj->func->unref) - obj->func->unref(obj); - } - if (!(attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) && - !(attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) && - attr->type != attr_item_type) - g_free(attr->u.data); -} - -void -attr_free_content(struct attr *attr) -{ - attr_free_content_do(attr); - memset(attr,0,sizeof(*attr)); -} - -void -attr_free(struct attr *attr) -{ - attr_free_content_do(attr); - g_free(attr); -} - -void -attr_dup_content(struct attr *src, struct attr *dst) -{ - int size; - dst->type=src->type; - if (src->type >= attr_type_int_begin && src->type <= attr_type_int_end) - dst->u.num=src->u.num; - else if (src->type == attr_item_type) - dst->u.item_type=src->u.item_type; - else if (src->type >= attr_type_object_begin && src->type <= attr_type_object_end) { - if (HAS_OBJECT_FUNC(src->type)) { - struct navit_object *obj=src->u.data; - if (obj && obj->func && obj->func->ref) { - dst->u.data=obj->func->ref(obj); - } else - dst->u.data=obj; - } else - dst->u.data=src->u.data; - } else { - size=attr_data_size(src); - if (size) { - dst->u.data=g_malloc(size); - memcpy(dst->u.data, src->u.data, size); - } - } +attr_generic_remove_attr(struct attr **attrs, struct attr *attr) { + struct attr **curr=attrs; + int i,j,count=0,found=0; + while (curr && *curr) { + if ((*curr)->type == attr->type && (*curr)->u.data == attr->u.data) + found=1; + curr++; + count++; + } + if (!found) + return attrs; + curr=g_new0(struct attr *, count); + j=0; + for (i = 0 ; i < count ; i++) { + if (attrs[i]->type != attr->type || attrs[i]->u.data != attr->u.data) + curr[j++]=attrs[i]; + else + attr_free(attrs[i]); + } + curr[j]=NULL; + g_free(attrs); + return curr; +} + +enum attr_type attr_type_begin(enum attr_type type) { + if (type < attr_type_item_begin) + return attr_none; + if (type < attr_type_int_begin) + return attr_type_item_begin; + if (type < attr_type_string_begin) + return attr_type_int_begin; + if (type < attr_type_special_begin) + return attr_type_string_begin; + if (type < attr_type_double_begin) + return attr_type_special_begin; + if (type < attr_type_coord_geo_begin) + return attr_type_double_begin; + if (type < attr_type_color_begin) + return attr_type_coord_geo_begin; + if (type < attr_type_object_begin) + return attr_type_color_begin; + if (type < attr_type_coord_begin) + return attr_type_object_begin; + if (type < attr_type_pcoord_begin) + return attr_type_coord_begin; + if (type < attr_type_callback_begin) + return attr_type_pcoord_begin; + if (type < attr_type_int64_begin) + return attr_type_callback_begin; + if (type <= attr_type_int64_end) + return attr_type_int64_begin; + return attr_none; +} + +int attr_data_size(struct attr *attr) { + if (attr->type == attr_none) + return 0; + if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) + return attr->u.str?strlen(attr->u.str)+1:0; + if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) + return sizeof(attr->u.num); + if (attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end) + return sizeof(*attr->u.coord_geo); + if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end) + return sizeof(*attr->u.color); + if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) + return sizeof(void *); + if (attr->type >= attr_type_item_begin && attr->type <= attr_type_item_end) + return sizeof(struct item); + if (attr->type >= attr_type_int64_begin && attr->type <= attr_type_int64_end) + return sizeof(*attr->u.num64); + if (attr->type == attr_order) + return sizeof(attr->u.range); + if (attr->type >= attr_type_double_begin && attr->type <= attr_type_double_end) + return sizeof(*attr->u.numd); + if (attr->type == attr_item_types) { + int i=0; + while (attr->u.item_types[i++] != type_none); + return i*sizeof(enum item_type); + } + if (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end) + return sizeof(enum item_type); + if (attr->type == attr_attr_types) { + int i=0; + while (attr->u.attr_types[i++] != attr_none); + return i*sizeof(enum attr_type); + } + dbg(lvl_error,"size for %s unknown", attr_to_name(attr->type)); + return 0; +} + +void *attr_data_get(struct attr *attr) { + if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) || + (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end)) + return &attr->u.num; + if (attr->type == attr_order) + return &attr->u.range; + return attr->u.data; +} + +void attr_data_set(struct attr *attr, void *data) { + if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) || + (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end)) + attr->u.num=*((int *)data); + else + attr->u.data=data; +} + +void attr_data_set_le(struct attr * attr, void * data) { + if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) || + (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end)) + attr->u.num=le32_to_cpu(*((int *)data)); + else if (attr->type == attr_order) { + attr->u.num=le32_to_cpu(*((int *)data)); + attr->u.range.min=le16_to_cpu(attr->u.range.min); + attr->u.range.max=le16_to_cpu(attr->u.range.max); + } else + /* Fixme: Handle long long */ + attr->u.data=data; + +} + +static void attr_free_content_do(struct attr *attr) { + if (!attr) + return; + if (HAS_OBJECT_FUNC(attr->type)) { + struct navit_object *obj=attr->u.data; + if (obj && obj->func && obj->func->unref) + obj->func->unref(obj); + } + if (!(attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) && + !(attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) && + attr->type != attr_item_type) + g_free(attr->u.data); +} + +void attr_free_content(struct attr *attr) { + attr_free_content_do(attr); + memset(attr,0,sizeof(*attr)); +} + +void attr_free(struct attr *attr) { + attr_free_content_do(attr); + g_free(attr); +} + +void attr_dup_content(struct attr *src, struct attr *dst) { + int size; + dst->type=src->type; + if (src->type >= attr_type_int_begin && src->type <= attr_type_int_end) + dst->u.num=src->u.num; + else if (src->type == attr_item_type) + dst->u.item_type=src->u.item_type; + else if (src->type >= attr_type_object_begin && src->type <= attr_type_object_end) { + if (HAS_OBJECT_FUNC(src->type)) { + struct navit_object *obj=src->u.data; + if (obj && obj->func && obj->func->ref) { + dst->u.data=obj->func->ref(obj); + } else + dst->u.data=obj; + } else + dst->u.data=src->u.data; + } else { + size=attr_data_size(src); + if (size) { + dst->u.data=g_malloc(size); + memcpy(dst->u.data, src->u.data, size); + } + } } struct attr * -attr_dup(struct attr *attr) -{ - struct attr *ret=g_new0(struct attr, 1); - attr_dup_content(attr, ret); - return ret; +attr_dup(struct attr *attr) { + struct attr *ret=g_new0(struct attr, 1); + attr_dup_content(attr, ret); + return ret; } -void -attr_list_free(struct attr **attrs) -{ - int count=0; - while (attrs && attrs[count]) { - attr_free(attrs[count++]); - } - g_free(attrs); +/** + * @brief Frees a list of attributes. + * + * This frees the pointer array as well as the attributes referenced by the pointers. + * + * It is safe to call this function with a NULL argument; doing so is a no-op. + * + * @param attrs The attribute list to free + */ +void attr_list_free(struct attr **attrs) { + int count=0; + while (attrs && attrs[count]) { + attr_free(attrs[count++]); + } + g_free(attrs); } +/** + * @brief Duplicates a list of attributes. + * + * This creates a deep copy, i.e. the attributes in the list are copied as well. + * + * It is safe to call this function with a NULL argument; in this case, NULL will be returned. + * + * @param attrs The attribute list to copy + * + * @return The copy of the attribute list + */ struct attr ** -attr_list_dup(struct attr **attrs) -{ - struct attr **ret; - int i,count=0; - - if (!attrs) - return NULL; - - while (attrs[count]) - count++; - ret=g_new0(struct attr *, count+1); - for (i = 0 ; i < count ; i++) - ret[i]=attr_dup(attrs[i]); - return ret; -} - -int -attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret) -{ - int len=0,quoted; - char *p,*e,*n; - - dbg(lvl_debug,"get_tag %s from %s\n", name, line); - if (name) - len=strlen(name); - if (pos) - p=line+*pos; - else - p=line; - for(;;) { - while (*p == ' ') { - p++; - } - if (! *p) - return 0; - n=p; - e=strchr(p,'='); - if (! e) - return 0; - p=e+1; - quoted=0; - while (*p) { - if (*p == ' ' && !quoted) - break; - if (*p == '"') - quoted=1-quoted; - p++; - } - if (name == NULL || (e-n == len && !strncmp(n, name, len))) { - if (name_ret) { - len=e-n; - strncpy(name_ret, n, len); - name_ret[len]='\0'; - } - e++; - len=p-e; - if (e[0] == '"') { - e++; - len-=2; - } - strncpy(val_ret, e, len); - val_ret[len]='\0'; - if (pos) - *pos=p-line; - return 1; - } - } - return 0; +attr_list_dup(struct attr **attrs) { + struct attr **ret; + int i,count=0; + + if (!attrs) + return NULL; + + while (attrs[count]) + count++; + ret=g_new0(struct attr *, count+1); + for (i = 0 ; i < count ; i++) + ret[i]=attr_dup(attrs[i]); + return ret; +} + +int attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret) { + int len=0,quoted; + char *p,*e,*n; + + dbg(lvl_debug,"get_tag %s from %s", name, line); + if (name) + len=strlen(name); + if (pos) + p=line+*pos; + else + p=line; + for(;;) { + while (*p == ' ') { + p++; + } + if (! *p) + return 0; + n=p; + e=strchr(p,'='); + if (! e) + return 0; + p=e+1; + quoted=0; + while (*p) { + if (*p == ' ' && !quoted) + break; + if (*p == '"') + quoted=1-quoted; + p++; + } + if (name == NULL || (e-n == len && !strncmp(n, name, len))) { + if (name_ret) { + len=e-n; + strncpy(name_ret, n, len); + name_ret[len]='\0'; + } + e++; + len=p-e; + if (e[0] == '"') { + e++; + len-=2; + } + strncpy(val_ret, e, len); + val_ret[len]='\0'; + if (pos) + *pos=p-line; + return 1; + } + } + return 0; } /** @@ -978,15 +965,13 @@ attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret) * * @return True if the attribute type was found, false if it was not found or if {@code types} is empty */ -int -attr_types_contains(enum attr_type *types, enum attr_type type) -{ - while (types && *types != attr_none) { - if (*types == type) - return 1; - types++; - } - return 0; +int attr_types_contains(enum attr_type *types, enum attr_type type) { + while (types && *types != attr_none) { + if (*types == type) + return 1; + types++; + } + return 0; } /** @@ -1001,13 +986,11 @@ attr_types_contains(enum attr_type *types, enum attr_type type) * * @return True if the attribute type was found, false if it was not found, {@code deflt} if types is empty. */ -int -attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt) -{ - if (!types) { - return deflt; - } - return attr_types_contains(types, type); +int attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt) { + if (!types) { + return deflt; + } + return attr_types_contains(types, type); } /** @@ -1019,12 +1002,11 @@ attr_types_contains_default(enum attr_type *types, enum attr_type type, int defl * * @return Absolute value corresponding to given relative value. */ -int attr_rel2real(int attrval, int whole, int treat_neg_as_rel) -{ - if (attrval > ATTR_REL_MAXABS) - return whole * (attrval - ATTR_REL_RELSHIFT)/100; - if(treat_neg_as_rel && attrval<0 ) - return whole+attrval; - return attrval; +int attr_rel2real(int attrval, int whole, int treat_neg_as_rel) { + if (attrval > ATTR_REL_MAXABS) + return whole * (attrval - ATTR_REL_RELSHIFT)/100; + if(treat_neg_as_rel && attrval<0 ) + return whole+attrval; + return attrval; } |