source: trunk/src/tcl/src/RpUnitsTclInterface.cc @ 262

Last change on this file since 262 was 262, checked in by dkearney, 18 years ago

adding new core units function getType() and getCompatible()
adding new tcl bindings related to getType() and getCompatible()
adjusted test files for testing.

File size: 11.7 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture::units
4 *
5 *  This is an interface to the rappture units module.
6 *  It allows you to convert between units and format values.
7 * ======================================================================
8 *  AUTHOR:  Derrick Kearney, Purdue University
9 *  Copyright (c) 2004-2006  Purdue Research Foundation
10 *
11 *  See the file "license.terms" for information on usage and
12 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * ======================================================================
14 */
15#include <tcl.h>
16#include "core/RpUnits.h"
17#include "RpUnitsTclInterface.h"
18
19#ifdef __cplusplus
20extern "C" {
21#endif
22
23// EXTERN int Rapptureunits_Init _ANSI_ARGS_((Tcl_Interp * interp));
24
25static int RpTclUnitsConvert   _ANSI_ARGS_((    ClientData cdata,
26                                                Tcl_Interp *interp,
27                                                int argc,
28                                                const char *argv[]    ));
29
30static int RpTclUnitsDesc      _ANSI_ARGS_((    ClientData cdata,
31                                                Tcl_Interp *interp,
32                                                int argc,
33                                                const char *argv[]    ));
34
35static int RpTclUnitsSysFor   _ANSI_ARGS_((    ClientData cdata,
36                                                Tcl_Interp *interp,
37                                                int argc,
38                                                const char *argv[]    ));
39
40static int RpTclUnitsSysAll   _ANSI_ARGS_((    ClientData cdata,
41                                                Tcl_Interp *interp,
42                                                int argc,
43                                                const char *argv[]    ));
44
45#ifdef __cplusplus
46}
47#endif
48
49/*
50 * ------------------------------------------------------------------------
51 *  Rapptureunits_Init()
52 *
53 *  Called in RapptureGUI_Init() to initialize the commands defined
54 *  in this file.
55 * ------------------------------------------------------------------------
56 */
57
58int
59Rapptureunits_Init(Tcl_Interp *interp)
60{
61
62    Tcl_CreateCommand(interp, "::Rappture::Units::convert",
63        RpTclUnitsConvert, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
64
65    Tcl_CreateCommand(interp, "::Rappture::Units::description",
66        RpTclUnitsDesc, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
67
68    Tcl_CreateCommand(interp, "::Rappture::Units::System::for",
69        RpTclUnitsSysFor, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
70
71    Tcl_CreateCommand(interp, "::Rappture::Units::System::all",
72        RpTclUnitsSysAll, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
73
74    return TCL_OK;
75}
76
77int
78RpTclUnitsConvert   (   ClientData cdata,
79                        Tcl_Interp *interp,
80                        int argc,
81                        const char *argv[]  )
82{
83    std::string inValue       = ""; // value provided by the user
84    std::string fromUnitsName = ""; // name of the units for user's value
85    std::string toUnitsName   = ""; // name of the units to convert to
86    std::string option        = ""; // tmp var for parsing command line options
87    std::string val           = ""; // inValue + fromUnitsName as one string
88    std::string convertedVal  = ""; // result of conversion
89    int showUnits             = 0;  // flag if we should show units in result
90    int result                = 0;  // flag if the conversion was successful
91
92    int nextarg          = 1; // start parsing using the '2'th argument
93    int argsLeft         = 0; // temp variable for calculation
94    int retVal           = 0; // TCL_OK or TCL_ERROR depending on result val
95    char *endptr         = NULL;
96
97    Tcl_ResetResult(interp);
98
99    // parse through command line options
100    if (argc < 2) {
101        Tcl_AppendResult(interp,
102            "usage: ", argv[0],
103            " <value> ?-context units? ?-to units? ?-units on/off?",
104            (char*)NULL);
105        return TCL_ERROR;
106    }
107
108    inValue = std::string(argv[nextarg++]);
109
110    argsLeft = (argc-nextarg);
111    while (argsLeft > 0 ) {
112        if (*argv[nextarg] == '-') {
113            option = std::string(argv[nextarg]);
114
115            if ( option == "-context" ) {
116                nextarg++;
117                fromUnitsName = std::string(argv[nextarg]);
118                if (RpUnits::find(fromUnitsName) == NULL) {
119                    Tcl_AppendResult(interp,
120                        "-context value \"", fromUnitsName.c_str(),
121                        "\" is not a recognized unit for rappture",
122                        (char*)NULL);
123                    return TCL_ERROR;
124                }
125
126            }
127            else if ( option == "-to" ) {
128                nextarg++;
129                toUnitsName = std::string(argv[nextarg]);
130                if (RpUnits::find(toUnitsName) == NULL) {
131                    Tcl_AppendResult(interp,
132                        "-to value \"", toUnitsName.c_str(),
133                        "\" is not a recognized unit for rappture",
134                        (char*)NULL);
135                    return TCL_ERROR;
136                }
137            }
138            else if ( option == "-units" ) {
139                nextarg++;
140                if (        (*(argv[nextarg]+1) == 'n')
141                        &&  (std::string(argv[nextarg]) == "on") ) {
142                    showUnits = 1;
143                }
144                else if (   (*(argv[nextarg]+1) == 'f')
145                        &&  (std::string(argv[nextarg]) == "off") ) {
146                    showUnits = 0;
147                }
148                else {
149                    // unrecognized value for -units option
150                    Tcl_AppendResult(interp,
151                        "value for -units must be \"on\" or \"off\"",
152                        (char*)NULL);
153                    return TCL_ERROR;
154                }
155            }
156            else {
157                // unrecognized option
158                Tcl_AppendResult(interp, "invalid option: ", option.c_str(),
159                    ".\nusage: ", argv[0],
160                    " <value> ?-context units? ?-to units? ?-units on/off?",
161                    (char*)NULL);
162                return TCL_ERROR;
163            }
164
165            nextarg++;
166        }
167        else {
168            // unrecognized input
169            Tcl_AppendResult(interp, "invalid input: ", argv[nextarg],
170                ".\nusage: ", argv[0],
171                " <value> ?-context units? ?-to units? ?-units on/off?",
172                (char*)NULL);
173            return TCL_ERROR;
174
175        }
176
177        argsLeft = (argc-nextarg);
178    }
179
180    // check the inValue to see if it has units
181    // or if we should use those provided in -context option
182    strtod(inValue.c_str(),&endptr);
183    if ( ((unsigned)(endptr - inValue.c_str())) == inValue.length() ) {
184        // there were no units at the end of the inValue string
185        // rappture units convert expects the val variable to be
186        // the quantity and units in one string
187        val = inValue + fromUnitsName;
188    }
189    else {
190        // there seemed to be units at the end of the inValue string
191        // we will ignore the -context flag and use the units in inValue
192        val = inValue;
193    }
194
195    // call the rappture units convert function
196    convertedVal = RpUnits::convert(val, toUnitsName, showUnits, &result);
197
198    if ( (!convertedVal.empty()) && (result == 0) ) {
199        // store the new result in the interpreter
200        Tcl_AppendResult(interp, convertedVal.c_str(), (char*)NULL);
201        retVal = TCL_OK;
202    }
203    else {
204        // error while converting
205        Tcl_AppendResult(interp,
206                "There was an error while converting\n"
207                "The convert function returned the following string: \"",
208                convertedVal.c_str(),"\"",
209                (char*)NULL);
210        retVal = TCL_ERROR;
211    }
212
213    return retVal;
214}
215
216int
217RpTclUnitsDesc      (   ClientData cdata,
218                        Tcl_Interp *interp,
219                        int argc,
220                        const char *argv[]  )
221{
222    std::string unitsName     = ""; // name of the units provided by user
223    std::string type          = ""; // name of the units provided by user
224    std::string listStr       = ""; // name of the units provided by user
225    const RpUnits* unitsObj   = NULL;
226    std::list<std::string> compatList;
227    std::list<std::string>::iterator compatListIter;
228
229    int nextarg               = 1; // start parsing using the '2'th argument
230
231    Tcl_ResetResult(interp);
232
233    // parse through command line options
234    if (argc != 2) {
235        Tcl_AppendResult(interp, "usage: ", argv[0], " <units>", (char*)NULL);
236        return TCL_ERROR;
237    }
238
239    unitsName = std::string(argv[nextarg]);
240
241    unitsObj = RpUnits::find(unitsName);
242    if (unitsObj == NULL) {
243        Tcl_AppendResult(interp,
244            "The units named: \"", unitsName.c_str(),
245            "\" is not a recognized unit for rappture",
246            (char*)NULL);
247        return TCL_ERROR;
248    }
249
250    type = unitsObj->getType();
251
252    Tcl_AppendResult(interp, type.c_str(), (char*)NULL);
253
254    compatList = unitsObj->getCompatible();
255    compatListIter = compatList.begin();
256
257    while (compatListIter != compatList.end()) {
258        if ( listStr.empty() ) {
259            listStr = *compatListIter;
260        }
261        else {
262            listStr =  listStr + "," + *compatListIter;
263        }
264
265        // increment the iterator
266        compatListIter++;
267    }
268
269    Tcl_AppendResult(interp, " (", listStr.c_str() ,")", (char*)NULL);
270
271    return TCL_OK;
272}
273
274int
275RpTclUnitsSysFor    (   ClientData cdata,
276                        Tcl_Interp *interp,
277                        int argc,
278                        const char *argv[]  )
279{
280    std::string unitsName     = ""; // name of the units provided by user
281    std::string type          = ""; // name of the units provided by user
282    const RpUnits* unitsObj   = NULL;
283    int nextarg               = 1; // start parsing using the '2'th argument
284
285    Tcl_ResetResult(interp);
286
287    // parse through command line options
288    if (argc != 2) {
289        Tcl_AppendResult(interp, "usage: ", argv[0], " <units>", (char*)NULL);
290        return TCL_ERROR;
291    }
292
293    unitsName = std::string(argv[nextarg]);
294
295    unitsObj = RpUnits::find(unitsName);
296    if (unitsObj == NULL) {
297        Tcl_AppendResult(interp,
298            "The units named: \"", unitsName.c_str(),
299            "\" is not a recognized unit for rappture",
300            (char*)NULL);
301        return TCL_ERROR;
302    }
303
304    type = unitsObj->getType();
305
306    Tcl_AppendResult(interp, type.c_str(), (char*)NULL);
307    return TCL_OK;
308
309}
310
311int
312RpTclUnitsSysAll    (   ClientData cdata,
313                        Tcl_Interp *interp,
314                        int argc,
315                        const char *argv[]  )
316{
317    std::string unitsName     = ""; // name of the units provided by user
318    const RpUnits* unitsObj   = NULL;
319    std::list<std::string> compatList;
320    std::list<std::string>::iterator compatListIter;
321    int nextarg               = 1; // start parsing using the '2'th argument
322
323    Tcl_ResetResult(interp);
324
325    // parse through command line options
326    if (argc != 2) {
327        Tcl_AppendResult(interp, "usage: ", argv[0], " <units>", (char*)NULL);
328        return TCL_ERROR;
329    }
330
331    unitsName = std::string(argv[nextarg]);
332
333    unitsObj = RpUnits::find(unitsName);
334    if (unitsObj == NULL) {
335        Tcl_AppendResult(interp,
336            "The units named: \"", unitsName.c_str(),
337            "\" is not a recognized unit for rappture",
338            (char*)NULL);
339        return TCL_ERROR;
340    }
341
342    compatList = unitsObj->getCompatible();
343    compatListIter = compatList.begin();
344
345    while (compatListIter != compatList.end()) {
346        Tcl_AppendElement(interp,(*compatListIter).c_str());
347        // increment the iterator
348        compatListIter++;
349    }
350
351    return TCL_OK;
352}
Note: See TracBrowser for help on using the repository browser.