haskell-igraph-0.4.0: cbits/haskell_attributes.c
#include "haskell_attributes.h"
/* An attribute is either a numeric vector (vector_t) or a string
vector (strvector_t). The attribute itself is stored in a
struct igraph_attribute_record_t, there is one such object for each
attribute. The igraph_t has a pointer to an array of three
vector_ptr_t's which contains pointers to
igraph_haskell_attribute_t's. Graph attributes are first, then vertex
and edge attributes. */
igraph_bool_t igraph_haskell_attribute_find(const igraph_vector_ptr_t *ptrvec,
const char *name, long int *idx) {
long int i, n=igraph_vector_ptr_size(ptrvec);
igraph_bool_t l=0;
for (i=0; !l && i<n; i++) {
igraph_attribute_record_t *rec=VECTOR(*ptrvec)[i];
l= !strcmp(rec->name, name);
}
if (idx) { *idx=i-1; }
return l;
}
int igraph_haskell_attributes_copy_attribute_record(igraph_attribute_record_t **newrec,
const igraph_attribute_record_t *rec) {
bsvector_t *str, *newstr;
*newrec=igraph_Calloc(1, igraph_attribute_record_t);
if (!(*newrec)) { IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM); }
IGRAPH_FINALLY(igraph_free, *newrec);
(*newrec)->type=rec->type;
(*newrec)->name=strdup(rec->name);
if (!(*newrec)->name) { IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM); }
IGRAPH_FINALLY(igraph_free, (void*)(*newrec)->name);
if (rec->type == IGRAPH_ATTRIBUTE_STRING) {
str=(bsvector_t*)rec->value;
newstr=igraph_Calloc(1, bsvector_t);
if (!newstr) {
IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, newstr);
IGRAPH_CHECK(bsvector_copy(newstr, str));
IGRAPH_FINALLY(bsvector_destroy, newstr);
(*newrec)->value=newstr;
} else {
IGRAPH_ERROR("Wrong attribute type", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY_CLEAN(4);
return 0;
}
int igraph_haskell_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) {
igraph_attribute_record_t *attr_rec;
long int i, n;
igraph_haskell_attributes_t *nattr;
n = attr ? igraph_vector_ptr_size(attr) : 0;
nattr=igraph_Calloc(1, igraph_haskell_attributes_t);
if (!nattr) {
IGRAPH_ERROR("Can't init attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, nattr);
IGRAPH_CHECK(igraph_vector_ptr_init(&nattr->gal, n));
IGRAPH_FINALLY(igraph_vector_ptr_destroy, &nattr->gal);
IGRAPH_CHECK(igraph_vector_ptr_init(&nattr->val, 0));
IGRAPH_FINALLY(igraph_vector_ptr_destroy, &nattr->val);
IGRAPH_CHECK(igraph_vector_ptr_init(&nattr->eal, 0));
IGRAPH_FINALLY_CLEAN(3);
for (i=0; i<n; i++) {
IGRAPH_CHECK(igraph_haskell_attributes_copy_attribute_record(
&attr_rec, VECTOR(*attr)[i]));
VECTOR(nattr->gal)[i] = attr_rec;
}
graph->attr=nattr;
return 0;
}
void igraph_haskell_attribute_destroy(igraph_t *graph) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *als[3]= { &attr->gal, &attr->val, &attr->eal };
long int i, n, a;
bsvector_t *str;
igraph_attribute_record_t *rec;
for (a=0; a<3; a++) {
n=igraph_vector_ptr_size(als[a]);
for (i=0; i<n; i++) {
rec=VECTOR(*als[a])[i];
if (rec) {
if (rec->type == IGRAPH_ATTRIBUTE_STRING) {
str=(bsvector_t*)rec->value;
bsvector_destroy(str);
igraph_free(str);
}
igraph_free((char*)rec->name);
igraph_free(rec);
}
}
}
igraph_vector_ptr_destroy(&attr->gal);
igraph_vector_ptr_destroy(&attr->val);
igraph_vector_ptr_destroy(&attr->eal);
igraph_free(graph->attr);
graph->attr=0;
}
/* Almost the same as destroy, but we might have null pointers */
void igraph_haskell_attribute_copy_free(igraph_haskell_attributes_t *attr) {
igraph_vector_ptr_t *als[3] = { &attr->gal, &attr->val, &attr->eal };
long int i, n, a;
bsvector_t *str;
igraph_attribute_record_t *rec;
for (a=0; a<3; a++) {
n=igraph_vector_ptr_size(als[a]);
for (i=0; i<n; i++) {
rec=VECTOR(*als[a])[i];
if (!rec) { continue; }
if (rec->type == IGRAPH_ATTRIBUTE_STRING) {
str=(bsvector_t*)rec->value;
bsvector_destroy(str);
igraph_free(str);
}
igraph_free((char*)rec->name);
igraph_free(rec);
}
}
}
/* No reference counting here. If you use attributes in C you should
know what you're doing. */
int igraph_haskell_attribute_copy(igraph_t *to, const igraph_t *from,
igraph_bool_t ga, igraph_bool_t va, igraph_bool_t ea) {
igraph_haskell_attributes_t *attrfrom=from->attr, *attrto;
igraph_vector_ptr_t *alto[3], *alfrom[3]={ &attrfrom->gal, &attrfrom->val,
&attrfrom->eal };
long int i, n, a;
igraph_bool_t copy[3] = { ga, va, ea };
to->attr=attrto=igraph_Calloc(1, igraph_haskell_attributes_t);
if (!attrto) {
IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, attrto);
IGRAPH_VECTOR_PTR_INIT_FINALLY(&attrto->gal, 0);
IGRAPH_VECTOR_PTR_INIT_FINALLY(&attrto->val, 0);
IGRAPH_VECTOR_PTR_INIT_FINALLY(&attrto->eal, 0);
IGRAPH_FINALLY_CLEAN(3);
IGRAPH_FINALLY(igraph_haskell_attribute_copy_free, attrto);
alto[0]=&attrto->gal; alto[1]=&attrto->val; alto[2]=&attrto->eal;
for (a=0; a<3; a++) {
if (copy[a]) {
n=igraph_vector_ptr_size(alfrom[a]);
IGRAPH_CHECK(igraph_vector_ptr_resize(alto[a], n));
igraph_vector_ptr_null(alto[a]);
for (i=0; i<n; i++) {
igraph_attribute_record_t *newrec;
IGRAPH_CHECK(igraph_haskell_attributes_copy_attribute_record(&newrec,
VECTOR(*alfrom[a])[i]));
VECTOR(*alto[a])[i]=newrec;
}
}
}
IGRAPH_FINALLY_CLEAN(2);
return 0;
}
int igraph_haskell_attribute_add_vertices(igraph_t *graph, long int nv,
igraph_vector_ptr_t *nattr) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *val=&attr->val;
long int length=igraph_vector_ptr_size(val);
long int nattrno=nattr==NULL ? 0 : igraph_vector_ptr_size(nattr);
long int origlen=igraph_vcount(graph)-nv;
long int newattrs=0, i;
igraph_vector_t news;
/* First add the new attributes if any */
newattrs=0;
IGRAPH_VECTOR_INIT_FINALLY(&news, 0);
for (i=0; i<nattrno; i++) {
igraph_attribute_record_t *nattr_entry=VECTOR(*nattr)[i];
const char *nname=nattr_entry->name;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(val, nname, &j);
if (!l) {
newattrs++;
IGRAPH_CHECK(igraph_vector_push_back(&news, i));
} else {
/* check types */
if (nattr_entry->type != ((igraph_attribute_record_t*)VECTOR(*val)[j])->type) {
IGRAPH_ERROR("You cannot mix attribute types", IGRAPH_EINVAL);
}
}
}
/* Add NA/empty string vectors for the existing vertices */
if (newattrs != 0) {
for (i=0; i<newattrs; i++) {
igraph_attribute_record_t *tmp=VECTOR(*nattr)[(long int)VECTOR(news)[i]];
igraph_attribute_record_t *newrec=igraph_Calloc(1, igraph_attribute_record_t);
igraph_attribute_type_t type=tmp->type;
if (!newrec) {
IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, newrec);
newrec->type=type;
newrec->name=strdup(tmp->name);
if (!newrec->name) {
IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, (char*)newrec->name);
if (type==IGRAPH_ATTRIBUTE_STRING) {
bsvector_t *newstr=igraph_Calloc(1, bsvector_t);
if (!newstr) {
IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, newstr);
BSVECTOR_INIT_FINALLY(newstr, origlen);
newrec->value=newstr;
}
IGRAPH_CHECK(igraph_vector_ptr_push_back(val, newrec));
IGRAPH_FINALLY_CLEAN(4);
}
length=igraph_vector_ptr_size(val);
}
/* Now append the new values */
for (i=0; i<length; i++) {
igraph_attribute_record_t *oldrec=VECTOR(*val)[i];
igraph_attribute_record_t *newrec=0;
const char *name=oldrec->name;
long int j;
igraph_bool_t l=0;
if (nattr) { l=igraph_haskell_attribute_find(nattr, name, &j); }
if (l) {
/* This attribute is present in nattr */
bsvector_t *oldstr, *newstr;
newrec=VECTOR(*nattr)[j];
oldstr=(bsvector_t*)oldrec->value;
newstr=(bsvector_t*)newrec->value;
if (oldrec->type != newrec->type) {
IGRAPH_ERROR("Attribute types do not match", IGRAPH_EINVAL);
}
if (oldrec->type == IGRAPH_ATTRIBUTE_STRING) {
if (nv != bsvector_size(newstr)) {
IGRAPH_ERROR("Invalid string attribute length", IGRAPH_EINVAL);
}
IGRAPH_CHECK(bsvector_append(oldstr, newstr));
} else {
IGRAPH_WARNING("Invalid attribute type");
}
} else {
/* No such attribute, append NA's */
bsvector_t *oldstr=(bsvector_t*)oldrec->value;
if (oldrec->type == IGRAPH_ATTRIBUTE_STRING) {
IGRAPH_CHECK(bsvector_resize(oldstr, origlen+nv));
} else {
IGRAPH_WARNING("Invalid attribute type");
}
}
}
igraph_vector_destroy(&news);
IGRAPH_FINALLY_CLEAN(1);
return 0;
}
void igraph_haskell_attribute_permute_free(igraph_vector_ptr_t *v) {
long int i, n=igraph_vector_ptr_size(v);
for (i=0; i<n; i++) {
igraph_attribute_record_t *rec=VECTOR(*v)[i];
igraph_Free(rec->name);
if (rec->type == IGRAPH_ATTRIBUTE_STRING) {
bsvector_t *strv= (bsvector_t*) rec->value;
bsvector_destroy(strv);
igraph_Free(strv);
}
igraph_Free(rec);
}
igraph_vector_ptr_clear(v);
}
int igraph_haskell_attribute_permute_vertices(const igraph_t *graph,
igraph_t *newgraph,
const igraph_vector_t *idx) {
if (graph==newgraph) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *val=&attr->val;
long int valno=igraph_vector_ptr_size(val);
long int i;
for (i=0; i<valno; i++) {
igraph_attribute_record_t *oldrec=VECTOR(*val)[i];
igraph_attribute_type_t type=oldrec->type;
bsvector_t *str, *newstr;
if (type == IGRAPH_ATTRIBUTE_STRING) {
str=(bsvector_t*)oldrec->value;
newstr=igraph_Calloc(1, bsvector_t);
if (!newstr) {
IGRAPH_ERROR("Cannot permute vertex attributes", IGRAPH_ENOMEM);
}
IGRAPH_CHECK(bsvector_init(newstr, 0));
IGRAPH_FINALLY(bsvector_destroy, newstr);
bsvector_index(str, newstr, idx);
oldrec->value=newstr;
bsvector_destroy(str);
igraph_Free(str);
IGRAPH_FINALLY_CLEAN(1);
} else {
IGRAPH_WARNING("Unknown edge attribute ignored");
}
}
} else {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *val=&attr->val;
long int valno=igraph_vector_ptr_size(val);
long int i;
/* New vertex attributes */
igraph_haskell_attributes_t *new_attr=newgraph->attr;
igraph_vector_ptr_t *new_val=&new_attr->val;
if (igraph_vector_ptr_size(new_val) != 0) {
IGRAPH_ERROR("Vertex attributes were already copied",
IGRAPH_EATTRIBUTES);
}
IGRAPH_CHECK(igraph_vector_ptr_resize(new_val, valno));
IGRAPH_FINALLY(igraph_haskell_attribute_permute_free, new_val);
for (i=0; i<valno; i++) {
igraph_attribute_record_t *oldrec=VECTOR(*val)[i];
igraph_attribute_type_t type=oldrec->type;
bsvector_t *str, *newstr;
/* The record itself */
igraph_attribute_record_t *new_rec=
igraph_Calloc(1, igraph_attribute_record_t);
if (!new_rec) {
IGRAPH_ERROR("Cannot create vertex attributes", IGRAPH_ENOMEM);
}
new_rec->name = strdup(oldrec->name);
new_rec->type = oldrec->type;
VECTOR(*new_val)[i]=new_rec;
/* The data */
if (type == IGRAPH_ATTRIBUTE_STRING) {
str=(bsvector_t*)oldrec->value;
newstr=igraph_Calloc(1, bsvector_t);
if (!newstr) {
IGRAPH_ERROR("Cannot permute vertex attributes", IGRAPH_ENOMEM);
}
IGRAPH_CHECK(bsvector_init(newstr, 0));
IGRAPH_FINALLY(bsvector_destroy, newstr);
bsvector_index(str, newstr, idx);
new_rec->value=newstr;
IGRAPH_FINALLY_CLEAN(1);
} else {
IGRAPH_WARNING("Unknown vertex attribute ignored");
}
}
}
IGRAPH_FINALLY_CLEAN(1);
return 0;
}
int igraph_haskell_attribute_combine_vertices(const igraph_t *graph,
igraph_t *newgraph,
const igraph_vector_ptr_t *merges,
const igraph_attribute_combination_t *comb) {
IGRAPH_ERROR("Cannot combine vertex attributes", IGRAPH_ENOMEM);
return 1;
}
int igraph_haskell_attribute_add_edges(igraph_t *graph, const igraph_vector_t *edges,
igraph_vector_ptr_t *nattr) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *eal=&attr->eal;
long int ealno=igraph_vector_ptr_size(eal);
long int ne=igraph_vector_size(edges)/2;
long int origlen=igraph_ecount(graph)-ne;
long int nattrno= nattr == 0 ? 0 : igraph_vector_ptr_size(nattr);
igraph_vector_t news;
long int newattrs, i;
/* First add the new attributes if any */
newattrs=0;
IGRAPH_VECTOR_INIT_FINALLY(&news, 0);
for (i=0; i<nattrno; i++) {
igraph_attribute_record_t *nattr_entry=VECTOR(*nattr)[i];
const char *nname=nattr_entry->name;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(eal, nname, &j);
if (!l) {
newattrs++;
IGRAPH_CHECK(igraph_vector_push_back(&news, i));
} else {
/* check types */
if (nattr_entry->type != ((igraph_attribute_record_t*)VECTOR(*eal)[j])->type) {
IGRAPH_ERROR("You cannot mix attribute types", IGRAPH_EINVAL);
}
}
}
/* Add NA/empty string vectors for the existing vertices */
if (newattrs != 0) {
for (i=0; i<newattrs; i++) {
igraph_attribute_record_t *tmp=VECTOR(*nattr)[(long int)VECTOR(news)[i]];
igraph_attribute_record_t *newrec=igraph_Calloc(1, igraph_attribute_record_t);
igraph_attribute_type_t type=tmp->type;
if (!newrec) {
IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, newrec);
newrec->type=type;
newrec->name=strdup(tmp->name);
if (!newrec->name) {
IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, (char*)newrec->name);
if (type==IGRAPH_ATTRIBUTE_STRING) {
bsvector_t *newstr=igraph_Calloc(1, bsvector_t);
if (!newstr) {
IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, newstr);
BSVECTOR_INIT_FINALLY(newstr, origlen);
newrec->value=newstr;
}
IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, newrec));
IGRAPH_FINALLY_CLEAN(4);
}
ealno=igraph_vector_ptr_size(eal);
}
/* Now append the new values */
for (i=0; i<ealno; i++) {
igraph_attribute_record_t *oldrec=VECTOR(*eal)[i];
igraph_attribute_record_t *newrec=0;
const char *name=oldrec->name;
long int j;
igraph_bool_t l=0;
if (nattr) { l=igraph_haskell_attribute_find(nattr, name, &j); }
if (l) {
/* This attribute is present in nattr */
bsvector_t *oldstr, *newstr;
newrec=VECTOR(*nattr)[j];
oldstr=(bsvector_t*)oldrec->value;
newstr=(bsvector_t*)newrec->value;
if (oldrec->type != newrec->type) {
IGRAPH_ERROR("Attribute types do not match", IGRAPH_EINVAL);
}
if (oldrec->type == IGRAPH_ATTRIBUTE_STRING) {
if (ne != bsvector_size(newstr)) {
IGRAPH_ERROR("Invalid string attribute length", IGRAPH_EINVAL);
}
IGRAPH_CHECK(bsvector_append(oldstr, newstr));
} else {
IGRAPH_WARNING("Invalid attribute type");
}
} else {
/* No such attribute, append NA's */
bsvector_t *oldstr=(bsvector_t*)oldrec->value;
if (oldrec->type == IGRAPH_ATTRIBUTE_STRING) {
IGRAPH_CHECK(bsvector_resize(oldstr, origlen+ne));
} else {
IGRAPH_WARNING("Invalid attribute type");
}
}
}
igraph_vector_destroy(&news);
IGRAPH_FINALLY_CLEAN(1);
return 0;
}
int igraph_haskell_attribute_permute_edges(const igraph_t *graph,
igraph_t *newgraph,
const igraph_vector_t *idx) {
if (graph == newgraph) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *eal=&attr->eal;
long int ealno=igraph_vector_ptr_size(eal);
long int i;
for (i=0; i<ealno; i++) {
igraph_attribute_record_t *oldrec=VECTOR(*eal)[i];
igraph_attribute_type_t type=oldrec->type;
bsvector_t *str, *newstr;
if (type == IGRAPH_ATTRIBUTE_STRING) {
str=(bsvector_t*)oldrec->value;
newstr=igraph_Calloc(1, bsvector_t);
if (!newstr) {
IGRAPH_ERROR("Cannot permute edge attributes", IGRAPH_ENOMEM);
}
IGRAPH_CHECK(bsvector_init(newstr, 0));
IGRAPH_FINALLY(bsvector_destroy, newstr);
bsvector_index(str, newstr, idx);
oldrec->value=newstr;
bsvector_destroy(str);
igraph_Free(str);
IGRAPH_FINALLY_CLEAN(1);
} else {
IGRAPH_WARNING("Unknown edge attribute ignored");
}
}
} else {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *eal=&attr->eal;
long int ealno=igraph_vector_ptr_size(eal);
long int i;
/* New edge attributes */
igraph_haskell_attributes_t *new_attr=newgraph->attr;
igraph_vector_ptr_t *new_eal=&new_attr->eal;
IGRAPH_CHECK(igraph_vector_ptr_resize(new_eal, ealno));
IGRAPH_FINALLY(igraph_haskell_attribute_permute_free, new_eal);
for (i=0; i<ealno; i++) {
igraph_attribute_record_t *oldrec=VECTOR(*eal)[i];
igraph_attribute_type_t type=oldrec->type;
bsvector_t *str, *newstr;
/* The record itself */
igraph_attribute_record_t *new_rec= igraph_Calloc(1, igraph_attribute_record_t);
if (!new_rec) {
IGRAPH_ERROR("Cannot create edge attributes", IGRAPH_ENOMEM);
}
new_rec->name = strdup(oldrec->name);
new_rec->type = oldrec->type;
VECTOR(*new_eal)[i] = new_rec;
if (type == IGRAPH_ATTRIBUTE_STRING) {
str=(bsvector_t*)oldrec->value;
newstr=igraph_Calloc(1, bsvector_t);
if (!newstr) {
IGRAPH_ERROR("Cannot permute edge attributes", IGRAPH_ENOMEM);
}
IGRAPH_CHECK(bsvector_init(newstr, 0));
IGRAPH_FINALLY(bsvector_destroy, newstr);
bsvector_index(str, newstr, idx);
new_rec->value=newstr;
IGRAPH_FINALLY_CLEAN(1);
} else {
IGRAPH_WARNING("Unknown edge attribute ignored");
}
}
IGRAPH_FINALLY_CLEAN(1);
}
return 0;
}
int igraph_haskell_attribute_combine_edges(const igraph_t *graph,
igraph_t *newgraph,
const igraph_vector_ptr_t *merges,
const igraph_attribute_combination_t *comb) {
IGRAPH_ERROR("Cannot combine edge attributes", IGRAPH_ENOMEM);
return 1;
}
int igraph_haskell_attribute_get_info(const igraph_t *graph,
igraph_strvector_t *gnames,
igraph_vector_t *gtypes,
igraph_strvector_t *vnames,
igraph_vector_t *vtypes,
igraph_strvector_t *enames,
igraph_vector_t *etypes) {
igraph_strvector_t *names[3] = { gnames, vnames, enames };
igraph_vector_t *types[3] = { gtypes, vtypes, etypes };
igraph_haskell_attributes_t *at=graph->attr;
igraph_vector_ptr_t *attr[3]={ &at->gal, &at->val, &at->eal };
long int i,j;
for (i=0; i<3; i++) {
igraph_strvector_t *n=names[i];
igraph_vector_t *t=types[i];
igraph_vector_ptr_t *al=attr[i];
long int len=igraph_vector_ptr_size(al);
if (n) {
IGRAPH_CHECK(igraph_strvector_resize(n, len));
}
if (t) {
IGRAPH_CHECK(igraph_vector_resize(t, len));
}
for (j=0; j<len; j++) {
igraph_attribute_record_t *rec=VECTOR(*al)[j];
const char *name=rec->name;
igraph_attribute_type_t type=rec->type;
if (n) {
IGRAPH_CHECK(igraph_strvector_set(n, j, name));
}
if (t) {
VECTOR(*t)[j]=type;
}
}
}
return 0;
}
igraph_bool_t igraph_haskell_attribute_has_attr(const igraph_t *graph,
igraph_attribute_elemtype_t type,
const char *name) {
igraph_haskell_attributes_t *at=graph->attr;
igraph_vector_ptr_t *attr[3]={ &at->gal, &at->val, &at->eal };
long int attrnum;
switch (type) {
case IGRAPH_ATTRIBUTE_GRAPH:
attrnum=0;
break;
case IGRAPH_ATTRIBUTE_VERTEX:
attrnum=1;
break;
case IGRAPH_ATTRIBUTE_EDGE:
attrnum=2;
break;
default:
IGRAPH_ERROR("Unknown attribute element type", IGRAPH_EINVAL);
break;
}
return igraph_haskell_attribute_find(attr[attrnum], name, 0);
}
int igraph_haskell_attribute_gettype(const igraph_t *graph,
igraph_attribute_type_t *type,
igraph_attribute_elemtype_t elemtype,
const char *name) {
long int attrnum;
igraph_attribute_record_t *rec;
igraph_haskell_attributes_t *at=graph->attr;
igraph_vector_ptr_t *attr[3]={ &at->gal, &at->val, &at->eal };
igraph_vector_ptr_t *al;
long int j;
igraph_bool_t l=0;
switch (elemtype) {
case IGRAPH_ATTRIBUTE_GRAPH:
attrnum=0;
break;
case IGRAPH_ATTRIBUTE_VERTEX:
attrnum=1;
break;
case IGRAPH_ATTRIBUTE_EDGE:
attrnum=2;
break;
default:
IGRAPH_ERROR("Unknown attribute element type", IGRAPH_EINVAL);
break;
}
al=attr[attrnum];
l=igraph_haskell_attribute_find(al, name, &j);
if (!l) {
IGRAPH_ERROR("Unknown attribute", IGRAPH_EINVAL);
}
rec=VECTOR(*al)[j];
*type=rec->type;
return 0;
}
int igraph_haskell_attribute_get_numeric_graph_attr(const igraph_t *graph,
const char *name,
igraph_vector_t *value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
int igraph_haskell_attribute_get_bool_graph_attr(const igraph_t *graph,
const char *name,
igraph_vector_bool_t *value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
int igraph_haskell_attribute_get_string_graph_attr(const igraph_t *graph,
const char *name,
igraph_strvector_t *value_) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *gal=&attr->gal;
long int j;
igraph_attribute_record_t *rec;
bsvector_t *str;
igraph_bool_t l=igraph_haskell_attribute_find(gal, name, &j);
if (!l) {
IGRAPH_ERROR("Unknown attribute", IGRAPH_EINVAL);
}
rec=VECTOR(*gal)[j];
str=(bsvector_t*)rec->value;
bsvector_t *value;
bsvector_init(value, 1);
IGRAPH_CHECK(bsvector_set(value, 0, BS(*str,0)));
igraph_strvector_copy(value_, bsvector_to_strvector(value));
return 0;
}
int igraph_haskell_attribute_get_numeric_vertex_attr(const igraph_t *graph,
const char *name,
igraph_vs_t vs,
igraph_vector_t *value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
int igraph_haskell_attribute_get_bool_vertex_attr(const igraph_t *graph,
const char *name,
igraph_vs_t vs,
igraph_vector_bool_t *value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
int igraph_haskell_attribute_get_string_vertex_attr(const igraph_t *graph,
const char *name,
igraph_vs_t vs,
igraph_strvector_t *value_) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *val=&attr->val;
long int j;
igraph_attribute_record_t *rec;
bsvector_t *str;
igraph_bool_t l=igraph_haskell_attribute_find(val, name, &j);
if (!l) {
IGRAPH_ERROR("Unknown attribute", IGRAPH_EINVAL);
}
bsvector_t *value;
bsvector_init(value, 0);
rec=VECTOR(*val)[j];
str=(bsvector_t*)rec->value;
if (igraph_vs_is_all(&vs)) {
bsvector_resize(value, 0);
IGRAPH_CHECK(bsvector_append(value, str));
} else {
igraph_vit_t it;
long int i=0;
IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
IGRAPH_FINALLY(igraph_vit_destroy, &it);
IGRAPH_CHECK(bsvector_resize(value, IGRAPH_VIT_SIZE(it)));
for (; !IGRAPH_VIT_END(it); IGRAPH_VIT_NEXT(it), i++) {
long int v=IGRAPH_VIT_GET(it);
bytestring_t *s;
bsvector_get(str, v, &s);
IGRAPH_CHECK(bsvector_set(value, i, s));
}
igraph_vit_destroy(&it);
IGRAPH_FINALLY_CLEAN(1);
}
igraph_strvector_copy(value_, bsvector_to_strvector(value));
return 0;
}
int igraph_haskell_attribute_get_numeric_edge_attr(const igraph_t *graph,
const char *name,
igraph_es_t es,
igraph_vector_t *value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
int igraph_haskell_attribute_get_string_edge_attr(const igraph_t *graph,
const char *name,
igraph_es_t es,
igraph_strvector_t *value_) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *eal=&attr->eal;
long int j;
igraph_attribute_record_t *rec;
bsvector_t *str;
igraph_bool_t l=igraph_haskell_attribute_find(eal, name, &j);
if (!l) {
IGRAPH_ERROR("Unknown attribute", IGRAPH_EINVAL);
}
bsvector_t *value;
bsvector_init(value, 1);
rec=VECTOR(*eal)[j];
str=(bsvector_t*)rec->value;
if (igraph_es_is_all(&es)) {
bsvector_resize(value, 0);
IGRAPH_CHECK(bsvector_append(value, str));
} else {
igraph_eit_t it;
long int i=0;
IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
IGRAPH_FINALLY(igraph_eit_destroy, &it);
IGRAPH_CHECK(bsvector_resize(value, IGRAPH_EIT_SIZE(it)));
for (; !IGRAPH_EIT_END(it); IGRAPH_EIT_NEXT(it), i++) {
long int e=IGRAPH_EIT_GET(it);
bytestring_t *s;
bsvector_get(str, e, &s);
IGRAPH_CHECK(bsvector_set(value, i, s));
}
igraph_eit_destroy(&it);
IGRAPH_FINALLY_CLEAN(1);
}
igraph_strvector_copy(value_, bsvector_to_strvector(value));
return 0;
}
int igraph_haskell_attribute_get_bool_edge_attr(const igraph_t *graph,
const char *name,
igraph_es_t es,
igraph_vector_bool_t *value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
igraph_real_t igraph_haskell_attribute_GAN(const igraph_t *graph, const char *name) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_GAB
* Query a boolean graph attribute.
*
* Returns the value of the given numeric graph attribute.
* The attribute must exist, otherwise an error is triggered.
* \param graph The input graph.
* \param name The name of the attribute to query.
* \return The value of the attribute.
*
* \sa \ref GAB for a simpler interface.
*
* Time complexity: O(Ag), the number of graph attributes.
*/
igraph_bool_t igraph_haskell_attribute_GAB(const igraph_t *graph, const char *name) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_GAS
* Query a string graph attribute.
*
* Returns a <type>const</type> pointer to the string graph attribute
* specified in \p name.
* The attribute must exist, otherwise an error is triggered.
* \param graph The input graph.
* \param name The name of the attribute to query.
* \return The value of the attribute.
*
* \sa \ref GAS for a simpler interface.
*
* Time complexity: O(Ag), the number of graph attributes.
*/
const bytestring_t* igraph_haskell_attribute_GAS(const igraph_t *graph, const char *name) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *gal=&attr->gal;
long int j;
igraph_attribute_record_t *rec;
bsvector_t *str;
igraph_bool_t l=igraph_haskell_attribute_find(gal, name, &j);
if (!l) {
igraph_error("Unknown attribute", __FILE__, __LINE__, IGRAPH_EINVAL);
return 0;
}
rec=VECTOR(*gal)[j];
str=(bsvector_t*)rec->value;
return BS(*str, 0);
}
/**
* \function igraph_haskell_attribute_VAN
* Query a numeric vertex attribute.
*
* The attribute must exist, otherwise an error is triggered.
* \param graph The input graph.
* \param name The name of the attribute.
* \param vid The id of the queried vertex.
* \return The value of the attribute.
*
* \sa \ref VAN macro for a simpler interface.
*
* Time complexity: O(Av), the number of vertex attributes.
*/
igraph_real_t igraph_haskell_attribute_VAN(const igraph_t *graph, const char *name,
igraph_integer_t vid) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_VAB
* Query a boolean vertex attribute.
*
* The attribute must exist, otherwise an error is triggered.
* \param graph The input graph.
* \param name The name of the attribute.
* \param vid The id of the queried vertex.
* \return The value of the attribute.
*
* \sa \ref VAB macro for a simpler interface.
*
* Time complexity: O(Av), the number of vertex attributes.
*/
igraph_bool_t igraph_haskell_attribute_VAB(const igraph_t *graph, const char *name,
igraph_integer_t vid) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_VAS
* Query a string vertex attribute.
*
* The attribute must exist, otherwise an error is triggered.
* \param graph The input graph.
* \param name The name of the attribute.
* \param vid The id of the queried vertex.
* \return The value of the attribute.
*
* \sa The macro \ref VAS for a simpler interface.
*
* Time complexity: O(Av), the number of vertex attributes.
*/
const bytestring_t* igraph_haskell_attribute_VAS(const igraph_t *graph, const char *name,
igraph_integer_t vid) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *val=&attr->val;
long int j;
igraph_attribute_record_t *rec;
bsvector_t *str;
igraph_bool_t l=igraph_haskell_attribute_find(val, name, &j);
if (!l) {
igraph_error("Unknown attribute", __FILE__, __LINE__, IGRAPH_EINVAL);
return 0;
}
rec=VECTOR(*val)[j];
str=(bsvector_t*)rec->value;
return BS(*str, (long int)vid);
}
/**
* \function igraph_haskell_attribute_EAN
* Query a numeric edge attribute.
*
* The attribute must exist, otherwise an error is triggered.
* \param graph The input graph.
* \param name The name of the attribute.
* \param eid The id of the queried edge.
* \return The value of the attribute.
*
* \sa \ref EAN for an easier interface.
*
* Time complexity: O(Ae), the number of edge attributes.
*/
igraph_real_t igraph_haskell_attribute_EAN(const igraph_t *graph, const char *name,
igraph_integer_t eid) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_EAB
* Query a boolean edge attribute.
*
* The attribute must exist, otherwise an error is triggered.
* \param graph The input graph.
* \param name The name of the attribute.
* \param eid The id of the queried edge.
* \return The value of the attribute.
*
* \sa \ref EAB for an easier interface.
*
* Time complexity: O(Ae), the number of edge attributes.
*/
igraph_bool_t igraph_haskell_attribute_EAB(const igraph_t *graph, const char *name,
igraph_integer_t eid) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_EAS
* Query a string edge attribute.
*
* The attribute must exist, otherwise an error is triggered.
* \param graph The input graph.
* \param name The name of the attribute.
* \param eid The id of the queried edge.
* \return The value of the attribute.
*
* \se \ref EAS if you want to type less.
*
* Time complexity: O(Ae), the number of edge attributes.
*/
const bytestring_t* igraph_haskell_attribute_EAS(const igraph_t *graph, const char *name,
igraph_integer_t eid) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *eal=&attr->eal;
long int j;
igraph_attribute_record_t *rec;
bsvector_t *str;
igraph_bool_t l=igraph_haskell_attribute_find(eal, name, &j);
if (!l) {
igraph_error("Unknown attribute", __FILE__, __LINE__, IGRAPH_EINVAL);
return 0;
}
rec=VECTOR(*eal)[j];
str=(bsvector_t*)rec->value;
return BS(*str, (long int)eid);
}
/**
* \function igraph_haskell_attribute_VANV
* Query a numeric vertex attribute for many vertices
*
* \param graph The input graph.
* \param name The name of the attribute.
* \param vids The vertices to query.
* \param result Pointer to an initialized vector, the result is
* stored here. It will be resized, if needed.
* \return Error code.
*
* Time complexity: O(v), where v is the number of vertices in 'vids'.
*/
int igraph_haskell_attribute_VANV(const igraph_t *graph, const char *name,
igraph_vs_t vids, igraph_vector_t *result) {
return igraph_haskell_attribute_get_numeric_vertex_attr(graph, name, vids,
result);
}
/**
* \function igraph_haskell_attribute_VABV
* Query a boolean vertex attribute for many vertices
*
* \param graph The input graph.
* \param name The name of the attribute.
* \param vids The vertices to query.
* \param result Pointer to an initialized boolean vector, the result is
* stored here. It will be resized, if needed.
* \return Error code.
*
* Time complexity: O(v), where v is the number of vertices in 'vids'.
*/
int igraph_haskell_attribute_VABV(const igraph_t *graph, const char *name,
igraph_vs_t vids, igraph_vector_bool_t *result) {
return igraph_haskell_attribute_get_bool_vertex_attr(graph, name, vids,
result);
}
/**
* \function igraph_haskell_attribute_EANV
* Query a numeric edge attribute for many edges
*
* \param graph The input graph.
* \param name The name of the attribute.
* \param eids The edges to query.
* \param result Pointer to an initialized vector, the result is
* stored here. It will be resized, if needed.
* \return Error code.
*
* Time complexity: O(e), where e is the number of edges in 'eids'.
*/
int igraph_haskell_attribute_EANV(const igraph_t *graph, const char *name,
igraph_es_t eids, igraph_vector_t *result) {
return igraph_haskell_attribute_get_numeric_edge_attr(graph, name, eids,
result);
}
/**
* \function igraph_haskell_attribute_EABV
* Query a boolean edge attribute for many edges
*
* \param graph The input graph.
* \param name The name of the attribute.
* \param eids The edges to query.
* \param result Pointer to an initialized boolean vector, the result is
* stored here. It will be resized, if needed.
* \return Error code.
*
* Time complexity: O(e), where e is the number of edges in 'eids'.
*/
int igraph_haskell_attribute_EABV(const igraph_t *graph, const char *name,
igraph_es_t eids, igraph_vector_bool_t *result) {
return igraph_haskell_attribute_get_bool_edge_attr(graph, name, eids,
result);
}
/**
* \function igraph_haskell_attribute_VASV
* Query a string vertex attribute for many vertices
*
* \param graph The input graph.
* \param name The name of the attribute.
* \param vids The vertices to query.
* \param result Pointer to an initialized string vector, the result
* is stored here. It will be resized, if needed.
* \return Error code.
*
* Time complexity: O(v), where v is the number of vertices in 'vids'.
* (We assume that the string attributes have a bounded length.)
*/
int igraph_haskell_attribute_VASV(const igraph_t *graph, const char *name,
igraph_vs_t vids, igraph_strvector_t *result) {
return igraph_haskell_attribute_get_string_vertex_attr(graph, name, vids,
result);
}
/**
* \function igraph_haskell_attribute_EASV
* Query a string edge attribute for many edges
*
* \param graph The input graph.
* \param name The name of the attribute.
* \param vids The edges to query.
* \param result Pointer to an initialized string vector, the result
* is stored here. It will be resized, if needed.
* \return Error code.
*
* Time complexity: O(e), where e is the number of edges in
* 'eids'. (We assume that the string attributes have a bounded length.)
*/
int igraph_haskell_attribute_EASV(const igraph_t *graph, const char *name,
igraph_es_t eids, igraph_strvector_t *result) {
return igraph_haskell_attribute_get_string_edge_attr(graph, name, eids,
result);
}
/**
* \function igraph_haskell_attribute_list
* List all attributes
*
* See \ref igraph_attribute_type_t for the various attribute types.
* \param graph The input graph.
* \param gnames String vector, the names of the graph attributes.
* \param gtypes Numeric vector, the types of the graph attributes.
* \param vnames String vector, the names of the vertex attributes.
* \param vtypes Numeric vector, the types of the vertex attributes.
* \param enames String vector, the names of the edge attributes.
* \param etypes Numeric vector, the types of the edge attributes.
* \return Error code.
*
* Naturally, the string vector with the attribute names and the
* numeric vector with the attribute types are in the right order,
* i.e. the first name corresponds to the first type, etc.
*
* Time complexity: O(Ag+Av+Ae), the number of all attributes.
*/
int igraph_haskell_attribute_list(const igraph_t *graph,
igraph_strvector_t *gnames, igraph_vector_t *gtypes,
igraph_strvector_t *vnames, igraph_vector_t *vtypes,
igraph_strvector_t *enames, igraph_vector_t *etypes) {
return igraph_haskell_attribute_get_info(graph, gnames, gtypes, vnames, vtypes,
enames, etypes);
}
/**
* \function igraph_haskell_attribute_has_attr
* Checks whether a (graph, vertex or edge) attribute exists
*
* \param graph The graph.
* \param type The type of the attribute, \c IGRAPH_ATTRIBUTE_GRAPH,
* \c IGRAPH_ATTRIBUTE_VERTEX or \c IGRAPH_ATTRIBUTE_EDGE.
* \param name Character constant, the name of the attribute.
* \return Logical value, TRUE if the attribute exists, FALSE otherwise.
*
* Time complexity: O(A), the number of (graph, vertex or edge)
* attributes, assuming attribute names are not too long.
igraph_bool_t igraph_haskell_attribute_has_attr(const igraph_t *graph,
igraph_attribute_elemtype_t type,
const char *name) {
return igraph_haskell_attribute_has_attr(graph, type, name);
}
*/
/**
* \function igraph_haskell_attribute_GAN_set
* Set a numeric graph attribute
*
* \param graph The graph.
* \param name Name of the graph attribute. If there is no such
* attribute yet, then it will be added.
* \param value The (new) value of the graph attribute.
* \return Error code.
*
* \se \ref SETGAN if you want to type less.
*
* Time complexity: O(1).
*/
int igraph_haskell_attribute_GAN_set(igraph_t *graph, const char *name,
igraph_real_t value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_GAB_set
* Set a boolean graph attribute
*
* \param graph The graph.
* \param name Name of the graph attribute. If there is no such
* attribute yet, then it will be added.
* \param value The (new) value of the graph attribute.
* \return Error code.
*
* \se \ref SETGAN if you want to type less.
*
* Time complexity: O(1).
*/
int igraph_haskell_attribute_GAB_set(igraph_t *graph, const char *name,
igraph_bool_t value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_GAS_set
* Set a string graph attribute.
*
* \param graph The graph.
* \param name Name of the graph attribute. If there is no such
* attribute yet, then it will be added.
* \param value The (new) value of the graph attribute. It will be
* copied.
* \return Error code.
*
* \se \ref SETGAS if you want to type less.
*
* Time complexity: O(1).
*/
int igraph_haskell_attribute_GAS_set(igraph_t *graph, const char *name,
const bytestring_t *value) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *gal=&attr->gal;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(gal, name, &j);
if (l) {
igraph_attribute_record_t *rec=VECTOR(*gal)[j];
if (rec->type != IGRAPH_ATTRIBUTE_STRING) {
IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL);
} else {
bsvector_t *str=(bsvector_t*)rec->value;
IGRAPH_CHECK(bsvector_set(str, 0, value));
}
} else {
igraph_attribute_record_t *rec=igraph_Calloc(1, igraph_attribute_record_t);
bsvector_t *str;
if (!rec) {
IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, rec);
rec->name=strdup(name);
if (!rec->name) {
IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, (char*)rec->name);
rec->type=IGRAPH_ATTRIBUTE_STRING;
str=igraph_Calloc(1, bsvector_t);
if (!str) {
IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, str);
BSVECTOR_INIT_FINALLY(str, 1);
IGRAPH_CHECK(bsvector_set(str, 0, value));
rec->value=str;
IGRAPH_CHECK(igraph_vector_ptr_push_back(gal, rec));
IGRAPH_FINALLY_CLEAN(4);
}
return 0;
}
/**
* \function igraph_haskell_attribute_VAN_set
* Set a numeric vertex attribute
*
* The attribute will be added if not present already. If present it
* will be overwritten. The same \p value is set for all vertices
* included in \p vid.
* \param graph The graph.
* \param name Name of the attribute.
* \param vid Vertices for which to set the attribute.
* \param value The (new) value of the attribute.
* \return Error code.
*
* \sa \ref SETVAN for a simpler way.
*
* Time complexity: O(n), the number of vertices if the attribute is
* new, O(|vid|) otherwise.
*/
int igraph_haskell_attribute_VAN_set(igraph_t *graph, const char *name,
igraph_integer_t vid, igraph_real_t value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_VAB_set
* Set a boolean vertex attribute
*
* The attribute will be added if not present already. If present it
* will be overwritten. The same \p value is set for all vertices
* included in \p vid.
* \param graph The graph.
* \param name Name of the attribute.
* \param vid Vertices for which to set the attribute.
* \param value The (new) value of the attribute.
* \return Error code.
*
* \sa \ref SETVAB for a simpler way.
*
* Time complexity: O(n), the number of vertices if the attribute is
* new, O(|vid|) otherwise.
*/
int igraph_haskell_attribute_VAB_set(igraph_t *graph, const char *name,
igraph_integer_t vid, igraph_bool_t value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_VAS_set
* Set a string vertex attribute
*
* The attribute will be added if not present already. If present it
* will be overwritten. The same \p value is set for all vertices
* included in \p vid.
* \param graph The graph.
* \param name Name of the attribute.
* \param vid Vertices for which to set the attribute.
* \param value The (new) value of the attribute.
* \return Error code.
*
* \sa \ref SETVAS for a simpler way.
*
* Time complexity: O(n*l), n is the number of vertices, l is the
* length of the string to set. If the attribute if not new then only
* O(|vid|*l).
*/
int igraph_haskell_attribute_VAS_set(igraph_t *graph, const char *name,
igraph_integer_t vid, const bytestring_t *value) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *val=&attr->val;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(val, name, &j);
if (l) {
igraph_attribute_record_t *rec=VECTOR(*val)[j];
if (rec->type != IGRAPH_ATTRIBUTE_STRING) {
IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL);
} else {
bsvector_t *str=(bsvector_t*)rec->value;
IGRAPH_CHECK(bsvector_set(str, vid, value));
}
} else {
igraph_attribute_record_t *rec=igraph_Calloc(1, igraph_attribute_record_t);
bsvector_t *str;
if (!rec) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, rec);
rec->name=strdup(name);
if (!rec->name) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, (char*)rec->name);
rec->type=IGRAPH_ATTRIBUTE_STRING;
str=igraph_Calloc(1, bsvector_t);
if (!str) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, str);
BSVECTOR_INIT_FINALLY(str, igraph_vcount(graph));
IGRAPH_CHECK(bsvector_set(str, vid, value));
rec->value=str;
IGRAPH_CHECK(igraph_vector_ptr_push_back(val, rec));
IGRAPH_FINALLY_CLEAN(4);
}
return 0;
}
/**
* \function igraph_haskell_attribute_EAN_set
* Set a numeric edge attribute
*
* The attribute will be added if not present already. If present it
* will be overwritten. The same \p value is set for all edges
* included in \p vid.
* \param graph The graph.
* \param name Name of the attribute.
* \param eid Edges for which to set the attribute.
* \param value The (new) value of the attribute.
* \return Error code.
*
* \sa \ref SETEAN for a simpler way.
*
* Time complexity: O(e), the number of edges if the attribute is
* new, O(|eid|) otherwise.
*/
int igraph_haskell_attribute_EAN_set(igraph_t *graph, const char *name,
igraph_integer_t eid, igraph_real_t value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_EAB_set
* Set a boolean edge attribute
*
* The attribute will be added if not present already. If present it
* will be overwritten. The same \p value is set for all edges
* included in \p vid.
* \param graph The graph.
* \param name Name of the attribute.
* \param eid Edges for which to set the attribute.
* \param value The (new) value of the attribute.
* \return Error code.
*
* \sa \ref SETEAB for a simpler way.
*
* Time complexity: O(e), the number of edges if the attribute is
* new, O(|eid|) otherwise.
*/
int igraph_haskell_attribute_EAB_set(igraph_t *graph, const char *name,
igraph_integer_t eid, igraph_bool_t value) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_EAS_set
* Set a string edge attribute
*
* The attribute will be added if not present already. If present it
* will be overwritten. The same \p value is set for all edges
* included in \p vid.
* \param graph The graph.
* \param name Name of the attribute.
* \param eid Edges for which to set the attribute.
* \param value The (new) value of the attribute.
* \return Error code.
*
* \sa \ref SETEAS for a simpler way.
*
* Time complexity: O(e*l), n is the number of edges, l is the
* length of the string to set. If the attribute if not new then only
* O(|eid|*l).
*/
int igraph_haskell_attribute_EAS_set(igraph_t *graph, const char *name,
igraph_integer_t eid, const bytestring_t *value) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *eal=&attr->eal;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(eal, name, &j);
if (l) {
igraph_attribute_record_t *rec=VECTOR(*eal)[j];
if (rec->type != IGRAPH_ATTRIBUTE_STRING) {
IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL);
} else {
bsvector_t *str=(bsvector_t*)rec->value;
IGRAPH_CHECK(bsvector_set(str, eid, value));
}
} else {
igraph_attribute_record_t *rec=igraph_Calloc(1, igraph_attribute_record_t);
bsvector_t *str;
if (!rec) {
IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, rec);
rec->name=strdup(name);
if (!rec->name) {
IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, (char*)rec->name);
rec->type=IGRAPH_ATTRIBUTE_STRING;
str=igraph_Calloc(1, bsvector_t);
if (!str) {
IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, str);
BSVECTOR_INIT_FINALLY(str, igraph_ecount(graph));
IGRAPH_CHECK(bsvector_set(str, eid, value));
rec->value=str;
IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, rec));
IGRAPH_FINALLY_CLEAN(4);
}
return 0;
}
/**
* \function igraph_haskell_attribute_VAN_setv
* Set a numeric vertex attribute for all vertices.
*
* The attribute will be added if not present yet.
* \param graph The graph.
* \param name Name of the attribute.
* \param v The new attribute values. The length of this vector must
* match the number of vertices.
* \return Error code.
*
* \sa \ref SETVANV for a simpler way.
*
* Time complexity: O(n), the number of vertices.
*/
int igraph_haskell_attribute_VAN_setv(igraph_t *graph, const char *name,
const igraph_vector_t *v) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_VAB_setv
* Set a boolean vertex attribute for all vertices.
*
* The attribute will be added if not present yet.
* \param graph The graph.
* \param name Name of the attribute.
* \param v The new attribute values. The length of this boolean vector must
* match the number of vertices.
* \return Error code.
*
* \sa \ref SETVANV for a simpler way.
*
* Time complexity: O(n), the number of vertices.
*/
int igraph_haskell_attribute_VAB_setv(igraph_t *graph, const char *name,
const igraph_vector_bool_t *v) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_VAS_setv
* Set a string vertex attribute for all vertices.
*
* The attribute will be added if not present yet.
* \param graph The graph.
* \param name Name of the attribute.
* \param sv String vector, the new attribute values. The length of this vector must
* match the number of vertices.
* \return Error code.
*
* \sa \ref SETVASV for a simpler way.
*
* Time complexity: O(n+l), n is the number of vertices, l is the
* total length of the strings.
*/
int igraph_haskell_attribute_VAS_setv(igraph_t *graph, const char *name,
const bsvector_t *sv) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *val=&attr->val;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(val, name, &j);
/* Check length first */
if (bsvector_size(sv) != igraph_vcount(graph)) {
IGRAPH_ERROR("Invalid vertex attribute vector length", IGRAPH_EINVAL);
}
if (l) {
/* Already present, check type */
igraph_attribute_record_t *rec=VECTOR(*val)[j];
bsvector_t *str=(bsvector_t *)rec->value;
if (rec->type != IGRAPH_ATTRIBUTE_STRING) {
IGRAPH_ERROR("Attribute type mismatch", IGRAPH_EINVAL);
}
bsvector_clear(str);
IGRAPH_CHECK(bsvector_append(str, sv));
} else {
/* Add it */
igraph_attribute_record_t *rec=igraph_Calloc(1, igraph_attribute_record_t);
bsvector_t *str;
if (!rec) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, rec);
rec->type=IGRAPH_ATTRIBUTE_STRING;
rec->name=strdup(name);
if (!rec->name) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, (char*)rec->name);
str=igraph_Calloc(1, bsvector_t);
if (!str) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, str);
rec->value=str;
IGRAPH_CHECK(bsvector_copy(str, sv));
IGRAPH_FINALLY(bsvector_destroy, str);
IGRAPH_CHECK(igraph_vector_ptr_push_back(val, rec));
IGRAPH_FINALLY_CLEAN(4);
}
return 0;
}
/**
* \function igraph_haskell_attribute_EAN_setv
* Set a numeric edge attribute for all vertices.
*
* The attribute will be added if not present yet.
* \param graph The graph.
* \param name Name of the attribute.
* \param v The new attribute values. The length of this vector must
* match the number of edges.
* \return Error code.
*
* \sa \ref SETEANV for a simpler way.
*
* Time complexity: O(e), the number of edges.
*/
int igraph_haskell_attribute_EAN_setv(igraph_t *graph, const char *name,
const igraph_vector_t *v) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_EAB_setv
* Set a boolean edge attribute for all vertices.
*
* The attribute will be added if not present yet.
* \param graph The graph.
* \param name Name of the attribute.
* \param v The new attribute values. The length of this vector must
* match the number of edges.
* \return Error code.
*
* \sa \ref SETEABV for a simpler way.
*
* Time complexity: O(e), the number of edges.
*/
int igraph_haskell_attribute_EAB_setv(igraph_t *graph, const char *name,
const igraph_vector_bool_t *v) {
IGRAPH_ERROR("Not implemented", IGRAPH_ENOMEM);
return 1;
}
/**
* \function igraph_haskell_attribute_EAS_setv
* Set a string edge attribute for all vertices.
*
* The attribute will be added if not present yet.
* \param graph The graph.
* \param name Name of the attribute.
* \param sv String vector, the new attribute values. The length of this vector must
* match the number of edges.
* \return Error code.
*
* \sa \ref SETEASV for a simpler way.
*
* Time complexity: O(e+l), e is the number of edges, l is the
* total length of the strings.
*/
int igraph_haskell_attribute_EAS_setv(igraph_t *graph, const char *name,
const bsvector_t *sv) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *eal=&attr->eal;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(eal, name, &j);
/* Check length first */
if (bsvector_size(sv) != igraph_ecount(graph)) {
IGRAPH_ERROR("Invalid edge attribute vector length", IGRAPH_EINVAL);
}
if (l) {
/* Already present, check type */
igraph_attribute_record_t *rec=VECTOR(*eal)[j];
bsvector_t *str=(bsvector_t *)rec->value;
if (rec->type != IGRAPH_ATTRIBUTE_STRING) {
IGRAPH_ERROR("Attribute type mismatch", IGRAPH_EINVAL);
}
bsvector_clear(str);
IGRAPH_CHECK(bsvector_append(str, sv));
} else {
/* Add it */
igraph_attribute_record_t *rec=igraph_Calloc(1, igraph_attribute_record_t);
bsvector_t *str;
if (!rec) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, rec);
rec->type=IGRAPH_ATTRIBUTE_STRING;
rec->name=strdup(name);
if (!rec->name) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, (char*)rec->name);
str=igraph_Calloc(1, bsvector_t);
if (!str) {
IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, str);
rec->value=str;
IGRAPH_CHECK(bsvector_copy(str, sv));
IGRAPH_FINALLY(bsvector_destroy, str);
IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, rec));
IGRAPH_FINALLY_CLEAN(4);
}
return 0;
}
void igraph_haskell_attribute_free_rec(igraph_attribute_record_t *rec) {
if (rec->type==IGRAPH_ATTRIBUTE_NUMERIC) {
igraph_vector_t *num=(igraph_vector_t*)rec->value;
igraph_vector_destroy(num);
} else if (rec->type==IGRAPH_ATTRIBUTE_STRING) {
bsvector_t *str=(bsvector_t*)rec->value;
bsvector_destroy(str);
} else if (rec->type==IGRAPH_ATTRIBUTE_BOOLEAN) {
igraph_vector_bool_t *boolvec=(igraph_vector_bool_t*)rec->value;
igraph_vector_bool_destroy(boolvec);
}
igraph_Free(rec->name);
igraph_Free(rec->value);
igraph_Free(rec);
}
/**
* \function igraph_haskell_attribute_remove_g
* Remove a graph attribute
*
* \param graph The graph object.
* \param name Name of the graph attribute to remove.
*
* \sa \ref DELGA for a simpler way.
*
*/
void igraph_haskell_attribute_remove_g(igraph_t *graph, const char *name) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *gal=&attr->gal;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(gal, name, &j);
if (l) {
igraph_haskell_attribute_free_rec(VECTOR(*gal)[j]);
igraph_vector_ptr_remove(gal, j);
} else {
IGRAPH_WARNING("Cannot remove non-existent graph attribute");
}
}
/**
* \function igraph_haskell_attribute_remove_v
* Remove a vertex attribute
*
* \param graph The graph object.
* \param name Name of the vertex attribute to remove.
*
* \sa \ref DELVA for a simpler way.
*
*/
void igraph_haskell_attribute_remove_v(igraph_t *graph, const char *name) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *val=&attr->val;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(val, name, &j);
if (l) {
igraph_haskell_attribute_free_rec(VECTOR(*val)[j]);
igraph_vector_ptr_remove(val, j);
} else {
IGRAPH_WARNING("Cannot remove non-existent graph attribute");
}
}
/**
* \function igraph_haskell_attribute_remove_e
* Remove an edge attribute
*
* \param graph The graph object.
* \param name Name of the edge attribute to remove.
*
* \sa \ref DELEA for a simpler way.
*
*/
void igraph_haskell_attribute_remove_e(igraph_t *graph, const char *name) {
igraph_haskell_attributes_t *attr=graph->attr;
igraph_vector_ptr_t *eal=&attr->eal;
long int j;
igraph_bool_t l=igraph_haskell_attribute_find(eal, name, &j);
if (l) {
igraph_haskell_attribute_free_rec(VECTOR(*eal)[j]);
igraph_vector_ptr_remove(eal, j);
} else {
IGRAPH_WARNING("Cannot remove non-existent graph attribute");
}
}
/**
* \function igraph_haskell_attribute_remove_all
* Remove all graph/vertex/edge attributes
*
* \param graph The graph object.
* \param g Boolean, whether to remove graph attributes.
* \param v Boolean, whether to remove vertex attributes.
* \param e Boolean, whether to remove edge attributes.
*
* \sa \ref DELGAS, \ref DELVAS, \ref DELEAS, \ref DELALL for simpler
* ways.
*/
void igraph_haskell_attribute_remove_all(igraph_t *graph, igraph_bool_t g,
igraph_bool_t v, igraph_bool_t e) {
igraph_haskell_attributes_t *attr=graph->attr;
if (g) {
igraph_vector_ptr_t *gal=&attr->gal;
long int i, n=igraph_vector_ptr_size(gal);
for (i=0;i<n;i++) {
igraph_haskell_attribute_free_rec(VECTOR(*gal)[i]);
}
igraph_vector_ptr_clear(gal);
}
if (v) {
igraph_vector_ptr_t *val=&attr->val;
long int i, n=igraph_vector_ptr_size(val);
for (i=0;i<n;i++) {
igraph_haskell_attribute_free_rec(VECTOR(*val)[i]);
}
igraph_vector_ptr_clear(val);
}
if (e) {
igraph_vector_ptr_t *eal=&attr->eal;
long int i, n=igraph_vector_ptr_size(eal);
for (i=0;i<n;i++) {
igraph_haskell_attribute_free_rec(VECTOR(*eal)[i]);
}
igraph_vector_ptr_clear(eal);
}
}