[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[UDUNITS #BUK-910616]: ut_get_name() returning NULL?



David,

> Moving the "<symbol>lb</symbol>" out of the "aliases" section functioned
> as expected and the three output lines all changed to:
> ut_get_unit_by_name( "pound" ) returned "lb"

If that's all it takes (promoting the standard name and symbol from the 
"aliases" section) then all that's needed is for that to be done for all the 
unit entries. Shouldn't take more than a day.

I wish I had a day.

> In the process I uncovered a bug. I accidentally copied the
> "<symbol>lb</symbol>" out of the aliases instead of moving it (i.e., it
> was defined both in and out of the aliases). This resulted in a
> segmentation fault... :-(

Interesting! I'll have to see if I can replicate that. It's been added to the 
list of issues on the GitHub site.

> I am still a little confused by UDUNITS definition of a unit-system
> since it seems that the definition that base units are SI is totally
> irrelevant when actually using the unit-system.

Not quite. A unit system defines the base units -- the units from which all 
other units are defined and to which all other units will be converted for 
comparison and conversion purposes.

> Even more than that,
> however, I don't see a way to even know if a value with units parsed by
> the system is in SI units or not. Whether ut_get_name() returned NULL or
> a name was a clue, but not a very good one.

If the function ut_read_xml() is given a NULL argument, then the resulting unit 
system will be the SI.

> Can I propose an extension to the library that might help? I would be
> willing to assist with its implementation as my time permits.
> 
> What I would propose is adding the concept of a "named system".
> Examples, and probably predefined, would be "SI", "MKS", "cgs", "
> avoirdupois", "imperial system", "US", etc. Maybe allowing aliases for
> these would be good too. This would be completely general however so a
> user could define their own favorite units system. Any given unit could
> be part of any number of named units systems and of course the named
> unit system could have any number of units.

This is possible now by specifying the pathname of the unit database to open to 
the function ut_read_xml(). For example "ut_read_xml("imperial.xml"). Doing so 
would require that the "imperial.xml" database exists, however. 

The unfortunate result of doing this, however, is that units in different unit 
systems are not comparable and values in units in different unit systems are 
not convertible.

> Extensions to the API could be something like:
> 1) ut_status  ut_add_named_system( ut_system* system, const char
> *system_name );
> 2) ut_status  ut_map_name_to_named_system( ut_system* system, const
> char *new_name, const char *system_name );
> 3) ut_status  ut_add_unit_to_named_system( const ut_unit* unit,
> const char *system_name );
> 4) ut_status  ut_remove_unit_from_named_system( const ut_unit*
> unit, const char *system_name );
> 5) int            ut_is_in_named_system( const ut_unit *unit, const
> char* system_name );
> 6) ut_unit*    ut_unit_in_named_system_convertible_with_unit( const
> char* system_name, const ut_unit* unit );
> 
> With these code like:
> 
> if( !ut_is_in_named_system( usersUnits, "SI" ) ) {
> ut_unit *siEquiv =
> ut_unit_in_named_system_convertible_with_unit( "SI", usersUnits );
> printf( "The value provided by the user is in %s but will
> be converted to %s\n",
> ut_get_name( usersUnits ), ut_get_name( siEquiv ) );
> }
> 
> or
> chart *userPreferedUnitSystem = "US";
> 
> if( !ut_is_in_named_system( unitsForSensorValue,
> userPreferedUnitSystem ) ) {
> ut_unit *preferedEquiv =
> ut_unit_in_named_system_convertible_with_unit( userPreferedUnitSystem,
> unitsForSensorValue );
> cv_converter *converter = ut_get_converter(
> unitsForSensorValue, preferedEquiv );
> double equivValue = cv_convert_double( converter,
> valueFromSensor );
> printf( "The current sensor value is %g %s\n", equivValue,
> ut_get_symbol( preferedEquiv ) );
> } else {
> printf( "The current sensor value is %g %s\n",
> valueFromSensor, ut_get_symbol( unitsForSensorValue ) );
> }
> 
> or
> // Maybe an application would have a user initialization file
> these could be set from....
> ut_add_named_system( system, const "outback" );
> ut_status ut_add_unit_to_named_system( ut_get_unit_by_name(
> "jigger" ), "outback" );
> ut_status ut_add_unit_to_named_system( ut_get_unit_by_name(
> "furlong" ), "outback" );
> ut_status ut_add_unit_to_named_system( ut_get_unit_by_name(
> "hand" ), "outback" );
> ut_status ut_add_unit_to_named_system( ut_get_unit_by_name(
> "stone" ), "outback" );
> 
> ut_unit *volumeUnits = ut_get_unit_by_name( system, "liter" );
> ut_unit *australianVolumeUnits =
> ut_unit_in_named_system_convertible_with_unit( "outback", volumeUnits );
> printf( "In the outback unit system milk is bought in %s\n",
> ut_get_name( australianVolumeUnits ) );
> 
> There could be extensions to specify units as base units within a named
> system, etc., if this would improve the interface. This would require
> extending the XML. Maybe with an attribute or new tag defined for a unit
> or potentially simpler would be a new top level tag "named-unit-system"
> that would contain a name, an aliases section, and a list of the units
> it contains.
> 
> What do you think?

I think this is a possible solution to the wrong problem. User's usually want 
something like this so that, when a program prints a value with a unit, the 
unit is something that the user wants (e.g., mass in pounds rather than 
kilograms). A better solution to this problem would be to make programs 
configurable in terms of the units the user wants to see for output values.

Regards,
Steve Emmerson

Ticket Details
===================
Ticket ID: BUK-910616
Department: Support UDUNITS
Priority: High
Status: Closed