ArgMap
's are C++ data structures that store name/value
pairs. The names are used as keys (type ArgKey
) for
getting at the values (type ArgVal
). This type was
generated with
Gnu's AVLMap template class.
It has all the features of this class, along with a few from
Gnu's Set template class. They are stored internally as
AVL trees, but this is of little consequence to
the rest of the code. ArgMap
's are accessed like arrays
and can be traversed with a for-loop in the same was as any of Gnu's
data structures, using what they call Pixes.
The pages on Gnu's data structure libraries give good examples of how
to use these features.
ArgKey
's are just constant character strings. They are
passed as a type of array index to an ArgMap
in the same
way that integer-indexed arrays are passed integers. For example, to
access the value in the fifth slot of array a, one would use
a[5]
. In the case of ArgMap
's, the slots
are simply named instead of numbered. So to look up or
assign a slot named "foo" in an ArgMap
b, the code just
looks like b["foo"]
. This would return, or be
assigned the type ArgVal
, described below.By default, the keys are case insensitive. A function could be added to the main ArgMap class in the future to support turning on case sensitivity for a particular map.
ArgVal
's are more versatile than the key type. They can
be strings, integers, and/or floats, depending on how they are accessed or
assigned. The operators (=,==,!=) for accessing and assigning this
type have been linked to function calls (overloaded) which
automatically carry out any conversions on the fly, if necessary. The
three types currently supported are
params["WIDTH"]
and params["HEIGHT"]
, the
code for printing the area would only need to use
{ ArgMap params; ... printf( "The area is %f.\n", (double)params["WIDTH"]*(double)params["HEIGHT"]); }Since they are typecast as
double
floats, the approriate
function will be called to convert the user's string to a float, even
from sexagesimal notation. Effectively, the code above triggers a
call to cfht_number(). If there is a possibility that the string
could contain invalid characters, then the _OK()
functions built into ArgVal should be used as follows:
{ ArgMap params; ... if ( !params["WIDTH"].flt_OK() || !params["HEIGHT"].flt_OK() ) { printf( "Couldn't convert `%s' or `%s' to a float!\n", (char*)params["WIDTH"],(char*)params["HEIGHT"] ); } else { printf( "The area is %f.\n", (double)params["WIDTH"]*(double)params["HEIGHT"] ); } }In this case, the conversions happen at the
if
statement,
and are retained for the printf
. If the initial value
had been assigned as a type double
to begin with, the
conversion would never have been carried out at all, and the _OK()
function would simply have checked a bit and returned.
The _OK()
functions and conversions are only functions in
the sense that they can be conveniently coded as such. They are
compiled as in-lined function calls, and thus do not even have the overhead
of a normal function call.
Getting data into an ArgVal
is just as straight-forward.
All of statements below have effectively the same result:
{ ... params["AREA"]=2*3; params["AREA"]=6.0000; params["AREA"]="6"; params["AREA"]="6.0"; }The same is true for the comparison operators:
{ ... if (params["AREA"]=="6")... // true, in the context of the above example if (params["AREA"]==6)... // true " if (params["AREA"]!="6.3")... // true statement. }But (>,>=,<, and, <=) have not been defined for strings for this data type. You should typecast to an int or float first for these types to let the built-in C-language behavior of these operators take effect:
{ ... if ((char*)params["AREA"]<"6.3")... // wrong! if ((double)params["AREA"]<6.3)... // right, and true in context }
Summary of ArgVal class functions | ||
---|---|---|
member functions | Overloaded Op. | Description |
a.get_str() | operator char*() | returns the value as a string, regardless of how it was originally stored |
a.get_flt() | operator double() | returns the value converted to a float, or returns a bogus value, in which case a.flt_OK() would test 0. |
a.get_int() | operator int() | returns the value converted to an int. If a fractional part had to be truncated, a.int_OK() would also test 0. |
a.set_str() | operator=(char*) | stores a copy of string. Subsequent calls to get_int() and get_flt() result in a new conversion on the first call. |
a.set_flt() | operator=(double) | stores the float. Subsequent calls to get_int() and get_str() result in a new conversion on the first call. |
a.set_int() | operator=(int) | stores the integer value. Subsequent calls to get_flt() and get_str() result in a new conversion on the first call. |
operator==(char*) | Returns non-zero if strcmp() says the strings are identical | |
operator!=(char*) | Returns non-zero if strcmp says the strings are different. | |
a.has_value() | Returns non-zero if `a' has been assigned a value. | |
a.has_changed() | Returns non-zero if `a' has been assigned and then re-assigned a *different* value from the first assignment. | |
a.str_OK() | Same as a.has_value() since all strings are valid. | |
a.flt_OK() | Returns non-zero if the call to cfht_number() was successful. | |
a.int_OK() | Returns non-zero if the value is an OK flt and has no fractional component |