Changeset 562


Ignore:
Timestamp:
Dec 15, 2006 11:11:16 PM (17 years ago)
Author:
dkearney
Message:

adjustments to how gauge.tcl deals with values for integer and number entries and properly identifies users inputted units if any.
added tests to units.test for some corner case inputs i found caused segfaults. these corner cases were fixed in the core units library and in the tcl bindings. they were mainly bugs regarding the new "rappture units search for" function and the description function. addeda function called unitsSlice() which centralizes the function used to split a string into what we think are probably units and a double value. this was centralized in preparation for possible inclusion of demensionless values like which might be refered to with a name in front of the numerical value, like "mach 1"

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/gui/scripts/gauge.tcl

    r556 r562  
    220220        if {$units != ""} {
    221221            set nvUnits [Rappture::Units::Search::for $nv]
     222            if { "" == $nvUnits} {
     223                set msg [Rappture::Units::description $units]
     224                error "Unrecognized units: $nv\n$mesg"
     225            }
    222226            set newval [Rappture::Units::convert $newval \
    223227                -context $units]
  • trunk/src/core/RpUnits.cc

    r559 r562  
    987987        }
    988988
     989        // check to see if we came across a '*' character
     990        if (myInUnits[last] == '*') {
     991            // type = myInUnits[last] + type;
     992            // ignore * because we assume everything is multiplied together
     993            myInUnits.erase(last);
     994            continue;
     995        }
     996
    989997        // get the exponent
    990998        offset = RpUnits::grabExponent(myInUnits,&exponent);
    991999        myInUnits.erase(offset);
    9921000        idx = offset - 1;
     1001        last = myInUnits.length()-1;
     1002        if (last == -1) {
     1003            // the string is empty, units were not correctly entered
     1004            err = 1;
     1005            break;
     1006        }
    9931007
    9941008        // grab the largest string we can find
    9951009        offset = RpUnits::grabUnitString(myInUnits);
    996         idx = offset;
     1010
     1011        // if idx > length, then the grabUnitString went through the whole
     1012        // string and did not find a good string we could use as units.
     1013        // this generally means the string was filled with non alphabetical
     1014        // symbols like *&^%$#@!)(~`{}[]:;"'?/><,.-_=+\ or |
     1015
     1016        if (offset > last) {
     1017            err = 1;
     1018            // erase the last offending character
     1019            myInUnits.erase(last);
     1020            // reset our vars and try again
     1021            idx = 0;
     1022            offset = 0;
     1023            exponent = 1;
     1024            continue;
     1025        }
     1026        else {
     1027            idx = offset;
     1028        }
    9971029
    9981030        // figure out if we have some defined units in that string
     
    10191051            // raise error and delete character for now
    10201052            err = 1;
    1021             myInUnits.erase(last);
     1053            myInUnits.erase(idx);
    10221054        }
    10231055
     
    12471279    double fromExp = 0;
    12481280    int convErr = 0;
    1249     char* endptr = NULL;
    12501281    std::stringstream outVal;
    12511282
     
    12721303    //
    12731304
    1274     numVal = strtod(val.c_str(),&endptr);
     1305    convErr = unitSlice(val,fromUnitsName,numVal);
    12751306    origNumVal = numVal;
    12761307
    1277     if ( (numVal == 0) && (endptr == val.c_str()) ) {
     1308    if (convErr != 0) {
    12781309        // no conversion was done.
    12791310        // number in incorrect format probably.
     
    12841315    }
    12851316
    1286     fromUnitsName = std::string(endptr);
    1287 
    12881317    if (toUnitsName.empty())  {
    1289         // there were no units in the input 
     1318        // there were no units in the input
    12901319        // string or no conversion needed
    12911320        // assume fromUnitsName = toUnitsName
     
    26852714    return retVal;
    26862715}
     2716
     2717/**********************************************************************/
     2718// FUNCTION: unitSlice()
     2719/// Convert a std::string into what might be the value and units
     2720/**
     2721 * Returns 0 on success, anything else is error
     2722 */
     2723
     2724int
     2725unitSlice (std::string inStr, std::string& outUnits, double& outVal)
     2726{
     2727    int retVal      = 0;  // return val 0 is success, otherwise failure
     2728    char *endptr    = NULL;
     2729
     2730    outVal = strtod(inStr.c_str(), &endptr);
     2731
     2732    if ( (outVal == 0) && (endptr == inStr.c_str()) ) {
     2733        // no conversion performed
     2734        retVal = 1;
     2735    }
     2736    else {
     2737    }
     2738
     2739    outUnits = std::string(endptr);
     2740
     2741    return retVal;
     2742}
  • trunk/src/core/RpUnits.h

    r559 r562  
    708708int list2str (std::list<std::string>& inList, std::string& outString);
    709709
     710int unitSlice (std::string inStr, std::string& outUnits, double& outVal);
     711
    710712#endif // ifdef __cplusplus
    711713
  • trunk/src/tcl/src/RpUnitsTclInterface.cc

    r560 r562  
    327327    // parse through command line options
    328328    if (argc != 2) {
    329         Tcl_AppendResult(interp, 
     329        Tcl_AppendResult(interp,
    330330                "wrong # args: should be \"", argv[0],
    331331                " units\"", (char*)NULL);
     
    500500{
    501501    std::string unitsName     = ""; // name of the units provided by user
     502    std::string origUnitsName = ""; // name of the units provided by user
    502503    std::string type          = ""; // junk variable that validate() needs
    503504    int nextarg               = 1; // start parsing using the '2'th argument
    504505    int err                   = 0; // err code for validate
    505     char* endptr              = NULL;
     506    double val                = 0;
    506507
    507508    Tcl_ResetResult(interp);
     
    515516
    516517    // find where the unitsName begins
    517     strtod(argv[nextarg],&endptr);
    518     unitsName = std::string(endptr);
     518    unitSlice(std::string(argv[nextarg]),unitsName,val);
    519519
    520520    err = RpUnits::validate(unitsName,type);
    521521    if (err) {
    522522        /*
    523          * according to tcl version, in this case we 
     523         * according to tcl version, in this case we
    524524         * should return an empty string. i happen to disagree.
    525525         * the next few lines is what i think the user should see.
    526526        Tcl_AppendResult(interp,
    527             "The units named: \"", unitsName.c_str(),
    528             "\" is not a recognized unit for rappture",
    529             (char*)NULL);
     527            "Unrecognized units: \"", origUnitsName.c_str(), "\"", (char*)NULL);
    530528        return TCL_ERROR;
    531529        */
  • trunk/src/tcl/tests/units.test

    r560 r562  
    188188} {0 {}}
    189189
    190 #test desc-2.2.0.1 {Rappture::Units::descption, valid units} {
    191 ## this test passes for old tcl version, fails for new tcl bindings
    192 ## because different order of units
    193 #    list [catch {Rappture::Units::description eV} msg] $msg
    194 #} {0 {energy (eV,J)}}
    195 
    196 test desc-2.2.0.2 {Rappture::Units::descption, valid units} {
     190test desc-2.2.0 {Rappture::Units::descption, valid units} {
    197191# this test passes for new tcl bindings, fails for old tcl version
    198192    list [catch {Rappture::Units::description eV} msg] $msg
    199193} {0 {energy (J,eV)}}
     194
     195test desc-2.2.1 {Rappture::Units::descption, *cm2*K/Vs} {
     196    list [catch {Rappture::Units::description *cm2*K/Vs} msg] $msg
     197} {0 {length*temperature/electric_potential*time (/V,/s,A2,C,F,K,R,cm2,in2,m2)}}
     198
     199test desc-2.2.2 {Rappture::Units::descption, cm2 areas} {
     200    list [catch {Rappture::Units::description cm2} msg] $msg
     201} {0 {area (A2,cm2,in2,m2)}}
     202
     203test desc-2.2.3 {Rappture::Units::descption, cm3 volumes} {
     204    list [catch {Rappture::Units::description cm3} msg] $msg
     205} {0 {volume (A3,cm3,in3,m3)}}
     206
     207test desc-2.2.4 {Rappture::Units::descption, K temperature} {
     208    list [catch {Rappture::Units::description K} msg] $msg
     209} {0 {temperature (C,F,K,R)}}
     210
     211test desc-2.2.5 {Rappture::Units::descption, s time} {
     212    list [catch {Rappture::Units::description s} msg] $msg
     213} {0 {time (s)}}
    200214
    201215test desc-2.3.0 {Rappture::Units::descption, too many args} {
     
    203217} {1 {wrong # args: should be "Rappture::Units::description units"}}
    204218
     219test desc-2.3.0 {Rappture::Units::descption, incorrect input type} {
     220    list [catch {Rappture::Units::description 3cm} msg] $msg
     221} {0 {}}
    205222
    206223#----------------------------------------------------------
     
    842859} {0 {}}
    843860
    844 test search-for-6.0.1.2 {Rappture::Units::Search::for, notaunit} {
     861test search-for-6.0.1.3 {Rappture::Units::Search::for, notaunit} {
    845862    list [catch {Rappture::Units::Search::for ^&} msg] $msg
    846863} {0 {}}
    847864
     865test search-for-6.0.1.4 {Rappture::Units::Search::for, notaunit} {
     866    list [catch {Rappture::Units::Search::for x44} msg] $msg
     867} {0 {}}
     868
     869test search-for-6.0.1.5 {Rappture::Units::Search::for, notaunit} {
     870    list [catch {Rappture::Units::Search::for 3*44eV} msg] $msg
     871} {0 {}}
     872
    848873::tcltest::cleanupTests
    849874return
Note: See TracChangeset for help on using the changeset viewer.