V10/ipc/mgrs/ns/attribute.c
#include <libc.h>
#include <fio.h>
#include <string.h>
#include "dbtypes.h"
/*
* free the value and type of an attribute
*/
Attribute::~Attribute()
{
if(value){
free(value);
}
if(type){
free(type);
}
}
/*
* Parse a linear version of an attribute. Anything ending in an
* the wildcard character specifies that this attribute is a key matching
* anything following the wildcard position.
*
* Any unrooted domain name is treated has a '.' attached and is treated
* as if it ended in a wild card.
*/
Attribute::Attribute(char *str, Tuple *t, char wildcard)
{
char *ttype;
char *wildp;
char *p;
ttype = strchr(str, ',');
if(ttype){
*ttype++ = '\0';
type = strdup(ttype);
} else
type = (char *)0;
wildp = str+strlen(str)-1;
if(*wildp==wildcard){
*wildp = '\0';
wild = 1;
} else
wild = 0;
if(fstrcmp(type, "dom")==0){
/*
* domains are case insensitive, convert to lower
*/
for(p = str; *p; p++)
*p = tolower(*p);
/*
* root the wild card
*/
if(wildcard && type && !wild && *wildp!='.'){
*(wildp+1) = '.';
*(wildp+2) = '\0';
wild = 1;
}
}
value = strdup(str);
tuple = t;
next = 0;
}
/*
* Compute the distance between two attributes. The distance measure is at
* most MAXDISTANCE and depends on the type of the attributes. Only attributes
* of the same type match.
*/
Attribute::distance(Attribute *origin)
{
if(type==0 || fstrcmp(origin->type, type)!=0)
return MAXDISTANCE;
else if(fstrcmp(origin->type, "dom")==0)
return dom_distance(value, origin->value);
else if(fstrcmp(origin->type, "dk")==0)
return dk_distance(value, origin->value);
return MAXDISTANCE;
}
/*
* output a linear version of the attribute on fd
*/
int
Attribute::simpleprint(int fd)
{
if(type)
return Fprint(fd, "%s,%s ", value, type);
else
return Fprint(fd, "%s ", value);
}
void
Attribute::print(int fd)
{
simpleprint(fd);
if(tuple){
Fprint(fd, " -> ");
tuple->print(fd);
}
}
/*
* return true if this is a key attribute
*/
int
Attribute::iskey()
{
return fstrcmp(type, "org")!=0;
}
/*
* compare 2 attributes. the key may have the type "name" which matches
* only an empty type.
*/
Attribute::compare(Ordered *o)
{
register rv;
Attribute *pattern=(Attribute *)o;
if(pattern->wild)
rv = strncmp(value, pattern->value, strlen(pattern->value));
else
rv = fstrcmp(value, pattern->value);
if(rv==0){
if(pattern->type && strcmp(pattern->type, "name")!=0){
if(type)
rv = fstrcmp(type, pattern->type);
else
rv = -1;
} else {
if(type && pattern->type)
rv = -1;
}
}
return rv;
}
/*
* Compare 2 attributes. If they have matching values, return non-zero.
*/
Attribute::compatible(Ordered *o)
{
Attribute *pattern=(Attribute *)o;
if(pattern->wild)
return !strncmp(value, pattern->value, strlen(pattern->value));
else
return !fstrcmp(value, pattern->value);
}
/*
* Print the value if attribute type == t. Return 0 if a value
* is printed.
*/
int
Attribute::printvalue(int fd, char *t)
{
if(type){
if (strcmp(t, type)==0){
Fprint(fd, "\t%s\n", value);
return 0;
}
} else if(strcmp(t, "name")==0){
Fprint(fd, "\t%s\n", value);
return 0;
}
return -1;
}