Example #1
0
static bUnitDef *unit_detect_from_str(bUnitCollection *usys, const char *str, const char *str_prev)
{
	/* Try to find a default unit from current or previous string.
	 * This allows us to handle cases like 2 + 2mm, people would expect to get 4mm, not 2.002m!
	 * Note this does not handle corner cases like 2 + 2cm + 1 + 2.5mm... We can't support everything. */
	bUnitDef *unit = NULL;

	/* see which units the new value has */
	for (unit = usys->units; unit->name; unit++) {
		if (unit_find(str, unit))
			break;
	}
	/* Else, try to infer the default unit from the previous string. */
	if (str_prev && (unit == NULL || unit->name == NULL)) {
		/* see which units the original value had */
		for (unit = usys->units; unit->name; unit++) {
			if (unit_find(str_prev, unit))
				break;
		}
	}
	/* Else, fall back to default unit. */
	if (unit == NULL || unit->name == NULL) {
		unit = unit_default(usys);
	}

	return unit;
}
Example #2
0
File: wm.c Project: oracc/oracc
void
unit_controller(char *id)
{
  struct wm_range *u = NULL;
  if ((u = unit_find(id)))
    unit_print(outfp, project_of(id), skip_project(id), u);
}
Example #3
0
/** Convert to a complex
	Converts a string to a complex property.  This function uses the global
	variable \p global_complex_format to perform the conversion.
	@return 1 when only real is read, 2 imaginary part is also read, 3 when notation is also read, 0 on failure, -1 is conversion was incomplete
 **/
int convert_to_complex(const char *buffer, /**< a pointer to the string buffer */
					   void *data, /**< a pointer to the data */
					   PROPERTY *prop) /**< a pointer to keywords that are supported */
{
	complex *v = (complex*)data;
	char unit[256];
	char notation[2]={'\0','\0'}; /* force detection invalid complex number */
	int n;
	double a=0, b=0; 
	if(buffer[0] == 0){
		/* empty string */
		v->SetRect(0.0, 0.0,v->Notation());
		return 1;
	}
	n = sscanf(buffer,"%lg%lg%1[ijdr]%s",&a,&b,notation,unit);
	if (n==1) /* only real part */
		v->SetRect(a,0,v->Notation());
	else if (n < 3 || strchr("ijdr",notation[0])==NULL) /* incomplete imaginary part or missing notation */
	{
		output_error("convert_to_complex('%s',%s): complex number format is not valid", buffer,prop->name);
		/* TROUBLESHOOT
			A complex number was given that doesn't meet the formatting requirements, e.g., <real><+/-><imaginary><notation>.  
			Check the format of your complex numbers and try again.
		 */
		return 0;
	}
	/* appears ok */
	else if (notation[0]==A) /* polar degrees */
		v->SetPolar(a,b*PI/180.0,v->Notation()); 
	else if (notation[0]==R) /* polar radians */
		v->SetPolar(a,b,v->Notation()); 
	else 
		v->SetRect(a,b,v->Notation()); /* rectangular */
	if (v->Notation()==I) /* only override notation when property is using I */
		v->Notation() = (CNOTATION)notation[0];

	if ( n>3 && prop->unit!=NULL ) /* unit given and unit allowed */
	{
		UNIT *from = unit_find(unit);
		double scale=1.0;
		if ( from != prop->unit && unit_convert_ex(from,prop->unit,&scale)==0)
		{
			output_error("convert_to_double(const char *buffer='%s', void *data=0x%*p, PROPERTY *prop={name='%s',...}): unit conversion failed", buffer, sizeof(void*), data, prop->name);
			/* TROUBLESHOOT 
			   This error is caused by an attempt to convert a value from a unit that is
			   incompatible with the unit of the target property.  Check your units and
			   try again.
		     */
			return 0;
		}
		v->Re() *= scale;
		v->Im() *= scale;
	}
	return 1;
}
Example #4
0
/** Convert to a \e double
	Converts a string to a \e double property.  This function uses the global
	variable \p global_double_format to perform the conversion.
	@return 1 on success, 0 on failure, -1 is conversion was incomplete
 **/
int convert_to_double(const char *buffer, /**< a pointer to the string buffer */
					  void *data, /**< a pointer to the data */
					  PROPERTY *prop) /**< a pointer to keywords that are supported */
{
	char unit[256];
	int n = sscanf(buffer,"%lg%s",data,unit);
	if ( n>1 && prop->unit!=NULL ) /* unit given and unit allowed */
	{
		UNIT *from = unit_find(unit);
		if ( from != prop->unit && unit_convert_ex(from,prop->unit,(double*)data)==0)
		{
			output_error("convert_to_double(const char *buffer='%s', void *data=0x%*p, PROPERTY *prop={name='%s',...}): unit conversion failed", buffer, sizeof(void*), data, prop->name);
			/* TROUBLESHOOT 
			   This error is caused by an attempt to convert a value from a unit that is
			   incompatible with the unit of the target property.  Check your units and
			   try again.
		     */
			return 0;
		}
	}
	return n;
}
Example #5
0
/** This function builds an collection of objects into an aggregation.  
	The aggregation can be run using aggregate_value(AGGREGATION*)
 **/
AGGREGATION *aggregate_mkgroup(char *aggregator, /**< aggregator (min,max,avg,std,sum,prod,mbe,mean,var,skew,kur,count,gamma) */
							   char *group_expression) /**< grouping rule; see find_mkpgm(char *)*/
{
	AGGREGATOR op = AGGR_NOP;
	AGGREGATION *result=NULL;
	char aggrop[9], aggrval[257], *aggrpart;
	char aggrprop[33], aggrunit[9];
	unsigned char flags=0x00;

	//Change made for collector to handle propeties of objects
	OBJECT *obj;
	PROPERTY *pinfo=NULL;
	FINDPGM *pgm = NULL;
	FINDLIST *list=NULL;	
	//Change ends here

	UNIT *from_unit = NULL, *to_unit = NULL;
	double scale = 1.0;

	if (sscanf(aggregator,"%8[A-Za-z0-9_](%256[][A-Za-z0-9_.^])",aggrop,aggrval)!=2 &&
		(flags|=AF_ABS,
		sscanf(aggregator,"%8[A-Za-z0-9_]|%256[][A-Za-z0-9_.^]|",aggrop,aggrval)!=2 
		))
	{
		output_error("aggregate group '%s' is not valid", aggregator);
		/* TROUBLESHOOT
			An aggregation expression does not have the required syntax, e.g., <i>aggregation</i>(<i>value</i>[.<i>part</i>]).
			Check the aggregation's syntax and make sure it conforms to the required syntax.
		 */
		errno = EINVAL;
		return NULL;
	}

	//Change made for collector to handle propeties of objects
	pgm = find_mkpgm(group_expression);
	if(pgm != NULL){
		list = find_runpgm(NULL,pgm);
		if(list != NULL){
			obj = find_first(list);
			if(obj != NULL){
				pinfo = class_find_property(obj->oclass,aggrval);
				if (pinfo==NULL)
				{
					aggrpart = strrchr(aggrval,'.');
					/* if an aggregate part is found */
					if (aggrpart!=NULL)
						*aggrpart++ = '\0';	// split the value and the part
					else
						aggrpart=""; // no part given
				}
					else
				{
					aggrpart=""; // no part given
				}
			}
		}
	}
	//Change ends here

	if(sscanf(aggrval, "%32[A-Za-z0-9_][%[A-Za-z0-9_^]]", aggrprop, aggrunit) == 2){
		to_unit = unit_find(aggrunit);
		if(to_unit == NULL){
			output_error("aggregate group '%s' has invalid units (%s)", aggrval, aggrunit);
			/* TROUBLESHOOT
				An aggregation expression include a unit specification in the value expression, but the unit is not found.
				Check your aggregations and make sure all the units are defined.
			 */
			errno = EINVAL;
			return NULL;
		}
		strcpy(aggrval, aggrprop); // write property back into value, sans unit
	}

	if (stricmp(aggrop,"min")==0) op=AGGR_MIN;
	else if (stricmp(aggrop,"max")==0) op=AGGR_MAX;
	else if (stricmp(aggrop,"avg")==0) op=AGGR_AVG;
	else if (stricmp(aggrop,"std")==0) op=AGGR_STD;
	else if (stricmp(aggrop,"sum")==0) op=AGGR_SUM;
	else if (stricmp(aggrop,"prod")==0) op=AGGR_SUM;
	else if (stricmp(aggrop,"mbe")==0) op=AGGR_MBE;
	else if (stricmp(aggrop,"mean")==0) op=AGGR_MEAN;
	else if (stricmp(aggrop,"var")==0) op=AGGR_VAR;
	else if (stricmp(aggrop,"skew")==0) op=AGGR_SKEW;
	else if (stricmp(aggrop,"kur")==0) op=AGGR_KUR;
	else if (stricmp(aggrop,"count")==0) op=AGGR_COUNT;
	else if (stricmp(aggrop,"gamma")==0) op=AGGR_GAMMA;
	else
	{
		output_error("aggregate group '%s' does not use a known aggregator", aggregator);
		/* TROUBLESHOOT
			An aggregation expression uses an aggregator that is not defined.  
			Check that all your aggregators used allowed functions (e.g., min, max, avg, std, sum, count, etc.).
		 */
		errno = EINVAL;
		return NULL;
	}
	if (op!=AGGR_NOP)
	{		
		AGGRPART part=AP_NONE;	
		
		if (pgm==NULL)
		{
			output_error("aggregate group expression '%s' failed", group_expression);
			/* TROUBLESHOOT
				A group expression failed to generate a useful group.  
				Check that all your groups are correctly defined.
			 */
			errno = EINVAL;
			return NULL;
		}
		else
		{
			PGMCONSTFLAGS flags = find_pgmconstants(pgm); 
			
			/* the search must be over the same class so that the property offset is known in advance */
			if ((flags&CF_CLASS)!=CF_CLASS)
			{
				output_error("aggregate group expression '%s' does not result in a set with a fixed class", group_expression);
				/* TROUBLESHOOT
					A group expression generated a group whose members vary over time.  
					This is not allowed.  
					Check that all your groups are defined such that the group membership is constant.
				 */
				errno = EINVAL;
				free(pgm);
				pgm = NULL;
				return NULL;
			}
			else
			{				
				if (list==NULL)
				{
					output_error("aggregate group expression '%s' does not result is a usable object list", group_expression);
					/* TROUBLESHOOT
						A group expression failed to generate a useful group.  
						Check that all your groups are correctly defined.
					 */
					free(pgm);
					pgm = NULL;
					errno=EINVAL;
					return NULL;
				}
				
				if (obj==NULL)
				{
					output_error("aggregate group expression '%s' results is an empty object list", group_expression);
					/* TROUBLESHOOT
						A group expression generated an empty group.  
						Check that all your groups are correctly defined.
					 */
					free(pgm);
					pgm = NULL;
					free(list);
					list = NULL;
					errno=EINVAL;
					return NULL;
				}
				pinfo = class_find_property(obj->oclass,aggrval);
				if (pinfo==NULL)
				{
					output_error("aggregate group property '%s' is not found in the objects satisfying search criteria '%s'", aggrval, group_expression);
					/* TROUBLESHOOT
						A group expression failed to generate a group that contains objects that meet the required criteria.  
						Check that all your groups are correctly defined.
					 */
					errno = EINVAL;
					free(pgm);
					pgm = NULL;
					free(list);
					list = NULL;
					return NULL;
				}
				else if (pinfo->ptype==PT_double || pinfo->ptype==PT_random || pinfo->ptype==PT_loadshape )
				{
					if (strcmp(aggrpart,"")!=0)
					{	/* doubles cannot have parts */
						output_error("aggregate group property '%s' cannot have part '%s'", aggrval, aggrpart);
						/* TROUBLESHOOT
							An aggregate part refers to a property that is a real number and does not have any parts.  
							Check that all your aggregate parts refer a property with parts, e.g., a complex value.
						 */
						errno = EINVAL;
						free(pgm);
						pgm = NULL;
						free(list);
						list = NULL;
						return NULL;
					}
					part = AP_NONE;
				}
				else if (pinfo->ptype==PT_complex || pinfo->ptype==PT_enduse)
				{	/* complex must have parts */
					if (strcmp(aggrpart,"real")==0)
						part = AP_REAL;
					else if (strcmp(aggrpart,"imag")==0)
						part = AP_IMAG;
					else if (strcmp(aggrpart,"mag")==0)
						part = AP_MAG;
					else if (strcmp(aggrpart,"ang")==0)
						part = AP_ANG;
					else if (strcmp(aggrpart,"arg")==0)
						part = AP_ARG;
					else
					{
						output_error("aggregate group property '%s' cannot have part '%s'", aggrval, aggrpart);
						/* TROUBLESHOOT
							The aggregate part requested is not recognized for the property given.  
							Check that your aggregate part is defined for a complex value.
						 */
						errno = EINVAL;
						free(pgm);
						pgm = NULL;
						free(list);
						list = NULL;
						return NULL;
					}
				}
				else
				{
					output_error("aggregate group property '%s' cannot be aggregated", aggrval);
					/* TROUBLESHOOT
						The aggregate referred to a type of property that cannot be aggregated.  
						Check that your aggregate part refers to a numeric value.
					 */
					errno = EINVAL;
					free(pgm);
					pgm = NULL;
					free(list);
					list = NULL;
					return NULL;
				}
				from_unit = pinfo->unit;
				if(to_unit != NULL && from_unit == NULL){
					output_error("aggregate group property '%s' is unitless and cannot be converted", aggrval);
					/* TROUBLESHOOT
						The aggregate attempted to convert the units of a property that is unitless.  
						Check that your aggregate part does not include a unit specification.
					 */
					errno = EINVAL;
					free(pgm);
					pgm = NULL;
					free(list);
					list = NULL;
					return NULL;
				}
				if (from_unit != NULL && to_unit != NULL && unit_convert_ex(from_unit, to_unit, &scale) == 0){
					output_error("aggregate group property '%s' cannot use units '%s'", aggrval, aggrunit);
					/* TROUBLESHOOT
						The aggregate attempted to convert a property to a unit that is not compatible with the
						property's original unit.  Check that your aggregate uses a unit that is fundamentally 
						compatible.
					 */
					errno = EINVAL;
					free(pgm);
					pgm = NULL;
					free(list);
					list = NULL;
					return NULL;
				}
			}
		}

		/* build aggregation unit */
		result = (AGGREGATION*)malloc(sizeof(AGGREGATION));
		if (result!=NULL)
		{
			result->op = op;
			result->group = pgm;
			result->pinfo = pinfo;
			result->part = part;
			result->last = list;
			result->next = NULL;
			result->flags = flags;
			result->punit = to_unit;
			result->scale = scale;
		}
		else
		{
			errno=ENOMEM;
			free(pgm);
			pgm = NULL;
			free(list);
			list = NULL;
			return NULL;
		}
	}

	return result;
}
Example #6
0
/* make a copy of the string that replaces the units with numbers
 * this is used before parsing
 * This is only used when evaluating user input and can afford to be a bit slower
 *
 * This is to be used before python evaluation so..
 * 10.1km -> 10.1*1000.0
 * ...will be resolved by python.
 *
 * values will be split by a comma's
 * 5'2" -> 5'0.0254, 2*0.3048
 *
 * str_prev is optional, when valid it is used to get a base unit when none is set.
 *
 * return true of a change was made.
 */
int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
{
	bUnitCollection *usys = unit_get_system(system, type);

	bUnitDef *unit;
	char str_tmp[TEMP_STR_SIZE];
	int changed = 0;

	if (usys == NULL || usys->units[0].name == NULL) {
		return 0;
	}

	/* make lowercase */
	BLI_ascii_strtolower(str, len_max);

	for (unit = usys->units; unit->name; unit++) {
		/* in case there are multiple instances */
		while (unit_replace(str, len_max, str_tmp, scale_pref, unit))
			changed = true;
	}
	unit = NULL;

	{
		/* try other unit systems now, so we can evaluate imperial when metric is set for eg. */
		bUnitCollection *usys_iter;
		int system_iter;

		for (system_iter = 0; system_iter < UNIT_SYSTEM_TOT; system_iter++) {
			if (system_iter != system) {
				usys_iter = unit_get_system(system_iter, type);
				if (usys_iter) {
					for (unit = usys_iter->units; unit->name; unit++) {
						int ofs = 0;
						/* in case there are multiple instances */
						while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref, unit)))
							changed = true;
					}
				}
			}
		}
	}
	unit = NULL;

	if (changed == 0) {
		/* no units given so infer a unit from the previous string or default */
		if (str_prev) {
			/* see which units the original value had */
			for (unit = usys->units; unit->name; unit++) {
				if (unit_find(str_prev, unit))
					break;
			}
		}

		if (unit == NULL || unit->name == NULL)
			unit = unit_default(usys);

		/* add the unit prefix and re-run, use brackets in case there was an expression given */
		if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)%s", str, unit->name) < sizeof(str_tmp)) {
			strncpy(str, str_tmp, len_max);
			return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type);
		}
		else {
			/* BLI_snprintf would not fit into str_tmp, cant do much in this case
			 * check for this because otherwise bUnit_ReplaceString could call its self forever */
			return 0;
		}

	}

	/* replace # with commas when there is no operator between it and the next number
	 *
	 * "1*1# 3*100# * 3"  ->  "1 *1, 3 *100  * 3"
	 *
	 * */
	{
		char *str_found = str;
		char *ch = str;

		while ((str_found = strchr(str_found, SEP_CHR))) {

			int op_found = 0;
			/* any operators after this?*/
			for (ch = str_found + 1; *ch != '\0'; ch++) {

				if (*ch == ' ' || *ch == '\t') {
					/* do nothing */
				}
				else if (ch_is_op(*ch) || *ch == ',') { /* found an op, no need to insert a ',' */
					op_found = 1;
					break;
				}
				else { /* found a non-op character */
					op_found = 0;
					break;
				}
			}

			*str_found++ = op_found ? ' ' : ',';
		}
	}

	return changed;
}
char *gld_loadHndl::read_object_prop(char *buffer, size_t len){
	//wchar_t wbuff[1024];
	//char tbuff[1024];
	char *rand_ptr = NULL;
	char *rand_mode_ptr = NULL;
	char *unit_ptr = NULL;
	double realval = 0.0;
	UNIT *unit=NULL;
	SAXParseException *e = NULL;
	void *addr = object_get_addr(obj, propname); /* get the & to set later */
	if(this->obj == NULL){
		sprintf(errmsg, "Null object pointer in read_object_prop(%s)", buffer);
		return errmsg;	//	no object
	}
	if(this->prop == NULL){
		if (strcmp(propname, "parent")==0){
			if (strcmp(propname, "root")==0){
				obj->parent = NULL;
			} else {
				add_unresolved(obj,PT_object,(void*)&obj->parent,oclass,buffer,"XML",42,UR_RANKS); 
			}
		} else if (strcmp(propname, "rank")==0){
			obj->rank = atoi(buffer);
		} else if (strcmp(propname, "clock")==0){
			obj->clock = atoi64(buffer);
		} else if (strcmp(propname, "latitude")==0){
			obj->latitude = load_latitude(buffer);
		} else if (strcmp(propname, "longitude")==0){
			obj->longitude = load_longitude(buffer);
		} else if (strcmp(propname, "in")==0){
			obj->in_svc = convert_to_timestamp(buffer);
		} else if (strcmp(propname, "out")==0){
			obj->out_svc = convert_to_timestamp(buffer);
		} else {
			sprintf(errmsg, "Null property pointer in read_object_prop(%s)", buffer);
			return errmsg;
		}
		return NULL;
	}
	//	determine property type
	switch(prop->ptype){
		case PT_double:
			//	scan for "random"
			if(strncmp("random.", buffer, 7) == 0){
				char temp[256];
				char *modep = NULL;
				double first = 0.0, second = 0.0;
				RANDOMTYPE rt;
				strncpy(temp, buffer, 256);
				modep = strtok(temp+7, "(");
				if(modep == NULL){
					//output_error("XML_Load: misformed random() value");
					load_state = false;
					sprintf(errmsg, "Misformed random() value in read_object_prop(%s)", buffer);
					return errmsg;
				}
				rt = random_type(modep);
				if(rt == 0){
					//output_message("XML_Load: '%s' ~ %s is not a valid random distribution", buffer, modep);
					load_state = false;
					sprintf(errmsg, "Invalid random distribution in read_object_prop(%s)", buffer);
					return errmsg;
				} else {
					first = atof(strtok(NULL, ","));
					second = atof(strtok(NULL, ")"));
					realval = random_value(rt, first, second);
				}
				if(strlen(strchr(buffer, ')')+1) > 0){ /* look for units */
					unit = unit_find(strchr(buffer, ')') + 2);
					if (unit!=NULL && prop->unit!=NULL && unit_convert_ex(unit,prop->unit,&realval)==0){
						sprintf(errmsg, "Cannot convert units from %s to %s in read_object_prop(%s)", unit->name,prop->unit->name, buffer);
						load_state = false;
						return errmsg;
					}
				}
			} else {
				unit_ptr = NULL;
				realval = strtod(buffer, &unit_ptr);
				if(unit_ptr != NULL){
					while(*unit_ptr == ' ') ++unit_ptr;
					unit = unit_find(unit_ptr);
					if(strlen(unit_ptr) > 0){
						if (unit!=NULL && prop->unit!=NULL && unit_convert_ex(unit,prop->unit,&realval)==0){
							sprintf(errmsg, "Cannot convert units from %s to %s in read_object_prop(%s)", unit->name,prop->unit->name, buffer);
							load_state = false;
							return errmsg;
						}
					}
				}
			}
			/* if((unit_ptr != NULL) && (*unit_ptr != '\0')){;} */
			if(object_set_double_by_name(obj, propname, realval) == 0){
				sprintf(errmsg, "Could not set \"%s\" to %f in read_object_prop(%s)", propname, realval, buffer);
				load_state = false;
				return errmsg;
			} else {
				return NULL; /* success */
			}
			break;
		case PT_object:
			if(add_unresolved(obj,PT_object,(void*)addr,oclass,buffer,"XML",42,UR_NONE) == NULL){
				sprintf(errmsg, "Failure with add_unresolved() in read_object_prop(%s)", buffer);
				return errmsg;
			}
			break;
		default:
			if(prop->ptype < _PT_LAST){	//	set value by name
				if (object_set_value_by_name(obj, propname, buffer)==0)	{
					//output_error("XML_Load: property %s of %s:%s could not be set to '%s'", propname, obj->oclass->name, obj->id, buffer);
					sprintf(errmsg, "Property %s of %s:%i could not be set to \"%s\" in read_object_prop()", propname, obj->oclass->name, obj->id, buffer);
					load_state = false;
					return errmsg;
				} else {
					;
				}
			} else {
				sprintf(errmsg, "Invalid property id = %i in read_object_prop(%s)", prop->ptype, buffer);
				return errmsg;
			}
	}
	return 0;
}