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;
}