return attr_none;
}
+
+static int attr_match(enum attr_type search, enum attr_type found);
+
+
+
char *
attr_to_name(enum attr_type attr)
{
}
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);
break;
default:
if (attr >= attr_type_string_begin && attr <= attr_type_string_end) {
- ret->u.str=(char *)value;
+ ret->u.str=g_strdup(value);
break;
}
if (attr >= attr_type_int_begin && attr <= attr_type_int_end) {
- ret->u.num=atoi(value);
- if (attr >= attr_type_boolean_begin) { // also check for yes and no
+ if (value[0] == '0' && value[1] == 'x')
+ ret->u.num=strtoul(value, NULL, 0);
+ else
+ ret->u.num=strtol(value, NULL, 0);
+
+ if ((attr >= attr_type_rel_abs_begin) && (attr < attr_type_boolean_begin)) {
+ /* Absolute values are from -0x40000000 - 0x40000000, with 0x0 being 0 (who would have thought that?)
+ Relative values are from 0x40000001 - 0x80000000, with 0x60000000 being 0 */
+ if (strchr(value, '%')) {
+ if ((ret->u.num > 0x20000000) || (ret->u.num < -0x1FFFFFFF)) {
+ dbg(0, "Relative possibly-relative attribute with invalid value %i\n", ret->u.num);
+ }
+
+ ret->u.num += 0x60000000;
+ } else {
+ if ((ret->u.num > 0x40000000) || (ret->u.num < -0x40000000)) {
+ dbg(0, "Non-relative possibly-relative attribute with invalid value %i\n", ret->u.num);
+ }
+ }
+ } else if (attr >= attr_type_boolean_begin) { // also check for yes and no
if (g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false"))
ret->u.num=1;
else
ret=g_strdup(attr->u.str);
return ret;
}
+ if (type == attr_flags)
+ return g_strdup_printf("0x%x", attr->u.num);
if (type >= attr_type_int_begin && type <= attr_type_int_end)
return g_strdup_printf("%d", attr->u.num);
if (type >= attr_type_int64_begin && type <= attr_type_int64_end)
return g_strdup_printf("%Ld", *attr->u.num64);
if (type >= attr_type_double_begin && type <= attr_type_double_end)
return g_strdup_printf("%f", *attr->u.numd);
- return g_strdup("(no text)");
+ 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]);
+ }
+ return g_strdup_printf("(no text[%s])", attr_to_name(type));
}
struct attr *
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;
+ }
+}
+
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 ((*attrs)->type == type) {
+ if (attr_match(type,(*attrs)->type)) {
*attr=**attrs;
- return 1;
+ 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 curr;
}
+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)
{
return sizeof(*attr->u.num64);
if (attr->type == attr_order)
return sizeof(attr->u.range);
+ 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_attr_types) {
+ int i=0;
+ while (attr->u.attr_types[i++] != attr_none);
+ return i*sizeof(enum attr_type);
+ }
dbg(0,"size for %s unknown\n", attr_to_name(attr->type));
return 0;
}
void
attr_free(struct attr *attr)
{
- if (attr->type == attr_position_coord_geo)
- g_free(attr->u.coord_geo);
- if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end)
- g_free(attr->u.color);
+ if (!attr)
+ return;
+ 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))
+ g_free(attr->u.data);
g_free(attr);
}
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(1,"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;
+}
+
+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_default(enum attr_type *types, enum attr_type type, int deflt)
+{
+ if (!types) {
+ return deflt;
+ }
+ return attr_types_contains(types, type);
+}