#include <NetInfo/dsdata.h>
#include <NetInfo/dsattribute.h>
#include <stdlib.h>
#include <string.h>
extern void
serialize_32(u_int32_t v, char **p);
extern u_int32_t
deserialize_32(char **p);
extern dsdata *
deserialize_dsdata(char **p);
dsdata *
dsattribute_to_dsdata(dsattribute *a)
{
u_int32_t i, len, type;
dsdata *d;
char *p;
if (a == NULL) return NULL;
len = a->key->length + 12;
for (i = 0; i < a->count; i++)
{
len += (4 + 4 + a->value[i]->length);
}
d = (dsdata *)malloc(sizeof(dsdata));
d->retain = 1;
d->type = DataTypeDSAttribute;
d->length = len;
d->data = malloc(len);
p = d->data;
type = a->key->type;
serialize_32(type, &p);
len = a->key->length;
serialize_32(len, &p);
memmove(p, a->key->data, len);
p += len;
serialize_32(a->count, &p);
for (i = 0; i < a->count; i++)
{
type = a->value[i]->type;
serialize_32(type, &p);
len = a->value[i]->length;
serialize_32(len, &p);
memmove(p, a->value[i]->data, len);
p += len;
}
return d;
}
dsattribute *
dsdata_to_dsattribute(dsdata *d)
{
dsattribute *a;
char *p;
u_int32_t i, len;
if (d == NULL) return NULL;
if (d->type != DataTypeDSAttribute) return NULL;
a = (dsattribute *)malloc(sizeof(dsattribute));
a->retain = 1;
p = d->data;
a->key = deserialize_dsdata(&p);
len = deserialize_32(&p);
a->count = len;
a->value = NULL;
if (len > 0) a->value = (dsdata **)malloc(len * sizeof(dsdata *));
for (i = 0; i < a->count; i++) a->value[i] = deserialize_dsdata(&p);
return a;
}
dsattribute *
dsattribute_new(dsdata *k)
{
dsattribute *x;
if (k == NULL) return NULL;
x = (dsattribute *)malloc(sizeof(dsattribute));
x->key = dsdata_retain(k);
x->count = 0;
x->value = NULL;
x->retain = 1;
return x;
}
dsattribute *
dsattribute_copy(dsattribute *a)
{
dsattribute *x;
int i;
if (a == NULL) return NULL;
x = (dsattribute *)malloc(sizeof(dsattribute));
x->key = dsdata_copy(a->key);
x->count = a->count;
x->value = NULL;
if (x->count > 0)
x->value = (dsdata **)malloc(x->count * sizeof(dsdata *));
for (i = 0; i < x->count; i++)
x->value[i] = dsdata_copy(a->value[i]);
x->retain = 1;
return x;
}
dsattribute *
dsattribute_retain(dsattribute *a)
{
if (a == NULL) return NULL;
a->retain++;
return a;
}
void
dsattribute_release(dsattribute *a)
{
u_int32_t i;
if (a == NULL) return;
a->retain--;
if (a->retain > 0) return;
dsdata_release(a->key);
for (i = 0; i < a->count; i++) dsdata_release(a->value[i]);
if (a->count > 0) free(a->value);
free(a);
}
void
dsattribute_insert(dsattribute *a, dsdata *d, u_int32_t w)
{
u_int32_t i;
if (a == NULL) return;
if (d == NULL) return;
if (w > a->count) w = a->count;
if (a->count == 0)
a->value = (dsdata **)malloc(sizeof(dsdata *));
else
a->value = (dsdata **)realloc(a->value, (a->count + 1) * sizeof(dsdata *));
for (i = a->count; i > w; i--) a->value[i] = a->value[i-1];
a->value[w] = dsdata_retain(d);
a->count++;
}
void
dsattribute_append(dsattribute *a, dsdata *d)
{
if (a == NULL) return;
if (d == NULL) return;
if (a->count == 0)
a->value = (dsdata **)malloc(sizeof(dsdata *));
else
a->value = (dsdata **)realloc(a->value, (a->count + 1) * sizeof(dsdata *));
a->value[a->count] = dsdata_retain(d);
a->count++;
}
void
dsattribute_remove(dsattribute *a, u_int32_t w)
{
u_int32_t i;
if (a == NULL) return;
if (w >= a->count) return;
dsdata_release(a->value[w]);
a->count--;
if (a->count == 0)
{
free(a->value);
a->value = NULL;
return;
}
for (i = w; i < a->count; i++) a->value[i] = a->value[i+1];
a->value = (dsdata **)realloc(a->value, a->count * sizeof(dsdata *));
}
void
dsattribute_merge(dsattribute *a, dsdata *d)
{
u_int32_t i, len;
if (a == NULL) return;
if (d == NULL) return;
len = a->count;
for (i = 0; i < len; i++)
if (dsdata_equal(a->value[i], d)) return;
a->count++;
if (len == 0)
a->value = (dsdata **)malloc(sizeof(dsdata *));
else
a->value = (dsdata **)realloc(a->value, a->count * sizeof(dsdata *));
a->value[len] = dsdata_retain(d);
}
u_int32_t
dsattribute_index(dsattribute *a, dsdata *d)
{
u_int32_t i;
if (a == NULL) return IndexNull;
if (d == NULL) return IndexNull;
for (i = 0; i < a->count; i++)
if (dsdata_equal(a->value[i], d)) return i;
return IndexNull;
}
dsdata *
dsattribute_value(dsattribute *a, u_int32_t w)
{
dsdata *v;
if (a == NULL) return NULL;
if (w >= a->count) return NULL;
v = a->value[w];
return dsdata_retain(v);
}
int
dsattribute_match(dsattribute *a, dsattribute *p)
{
u_int32_t i, j, found;
dsdata *v;
if (a == p) return 1;
if (a == NULL) return 0;
if (p == NULL) return 1;
if (dsdata_equal(a->key, p->key) == 0) return 0;
for (i = 0; i < p->count; i++)
{
v = p->value[i];
found = 0;
for (j = 0; j < a->count; j++)
{
if (dsdata_equal(a->value[j], v))
{
found = 1;
break;
}
}
if (found == 0) return 0;
}
return 1;
}
int
dsattribute_equal(dsattribute *a, dsattribute *b)
{
u_int32_t i, j, found;
dsdata *v;
if (a == b) return 1;
if (a == NULL) return 0;
if (b == NULL) return 0;
if (a->count != b->count) return 0;
if (dsdata_equal(a->key, b->key) == 0) return 0;
for (i = 0; i < a->count; i++)
{
v = a->value[i];
found = 0;
for (j = 0; j < b->count; j++)
{
if (dsdata_equal(b->value[j], v))
{
found = 1;
break;
}
}
if (found == 0) return 0;
}
return 1;
}
void
dsattribute_setkey(dsattribute *a, dsdata *k)
{
if (a == NULL) return;
if (k == NULL) return;
dsdata_release(a->key);
a->key = dsdata_retain(k);
}