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; }
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); }
/** 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; }
/** 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; }
/** 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; }
/* 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; }