source: trunk/include/core/RpUnits.h @ 19

Last change on this file since 19 was 19, checked in by dkearney, 16 years ago

initial submission of the Rappture Core components and language bindings

  • Property svn:executable set to *
File size: 13.8 KB
Line 
1#include <iostream>
2#include <string>
3#include <sstream>
4#include <stdlib.h>
5#include <errno.h>
6
7// #include "../include/RpDebug.h"
8#include "../include/RpDict.h"
9#include "../include/RpUnitsStd.h"
10// #include "../include/expr_eval_simple.h"
11
12#ifndef _RpUNITS_H
13#define _RpUNITS_H
14
15class RpUnits;
16
17class unit
18{
19
20    public:
21
22        const std::string getUnits(){ return units; };
23        double getExponent() {return exponent;};
24        RpUnits * getBasis() {return basis;};
25
26        friend class RpUnits;
27
28    private:
29        const std::string units;
30        double exponent;
31        // RpUnits* basis[4];
32        RpUnits* basis;
33
34        unit* prev;
35        unit* next;
36
37        unit (
38                const std::string& units,
39                double&            exponent,
40                // RpUnits**           basis,
41                RpUnits*           basis,
42                unit*              next
43             )
44            :   units    (units),
45                exponent (exponent),
46                basis    (basis),
47                prev     (NULL),
48                next     (next)
49            { };
50
51
52        void newExponent(double newExponent) {exponent = newExponent;};
53
54
55};
56
57// simple class to hold info about a conversion.
58// holds where we are converting from
59// holds where we are converting to
60// hold the pointer to a function to do the forward conversion (from->to)
61// hold the pointer to a function to do the backward conversion (to->from)
62//
63class conversion
64{
65    public:
66
67        const RpUnits* getFrom()    { return (const RpUnits*) fromPtr; };
68        const RpUnits* getTo()      { return (const RpUnits*) toPtr; };
69       
70        friend class RpUnits;
71
72    private:
73
74        RpUnits* fromPtr;
75        RpUnits* toPtr;
76        double (*convForwFxnPtr)(double);
77        double (*convBackFxnPtr)(double);
78        void* (*convForwFxnPtrVoid)(void*, void*);
79        void* convForwData;
80        void* (*convBackFxnPtrVoid)(void*, void*);
81        void* convBackData;
82
83        conversion* prev;
84        conversion* next;
85
86        // constructor
87        // private because i only want RpUnits to be able to
88        // create a conversion
89        conversion (
90                RpUnits* fromPtr,
91                RpUnits* toPtr,
92                double (*convForwFxnPtr)(double),
93                double (*convBackFxnPtr)(double),
94                conversion* prev,
95                conversion* next
96             )
97            :   fromPtr             (fromPtr),
98                toPtr               (toPtr),
99                convForwFxnPtr      (convForwFxnPtr),
100                convBackFxnPtr      (convBackFxnPtr),
101                convForwFxnPtrVoid  (NULL),
102                convForwData        (NULL),
103                convBackFxnPtrVoid  (NULL),
104                convBackData        (NULL),
105                prev                (prev),
106                next                (next)
107            {
108            };
109
110        conversion (
111                RpUnits* fromPtr,
112                RpUnits* toPtr,
113                void* (*convForwFxnPtrVoid)(void*, void*),
114                void* convForwData,
115                void* (*convBackFxnPtrVoid)(void*, void*),
116                void* convBackData,
117                conversion* prev,
118                conversion* next
119             )
120            :   fromPtr             (fromPtr),
121                toPtr               (toPtr),
122                convForwFxnPtr      (NULL),
123                convBackFxnPtr      (NULL),
124                convForwFxnPtrVoid  (convForwFxnPtrVoid),
125                convForwData        (convForwData),
126                convBackFxnPtrVoid  (convBackFxnPtrVoid),
127                convBackData        (convBackData),
128                prev                (prev),
129                next                (next)
130            {
131            };
132
133        // copy constructor
134
135        // destructor
136};
137
138// used by the RpUnits class to create a linked list of the conversions
139// associated with the specific unit.
140//
141// we could templitize this and make a generic linked list
142// or could use generic linked list class from book programming with objects
143//
144class convEntry
145{
146
147    public:
148
149        friend class RpUnits;
150
151    private:
152
153        conversion* conv;
154        convEntry*  prev;
155        convEntry*  next;
156
157        convEntry (
158                conversion* conv,
159                convEntry*  prev,
160                convEntry*  next
161             )
162            :   conv    (conv),
163                prev    (prev),
164                next    (next)
165            { };
166
167        /*
168        ~convEntry()
169        {
170
171        }
172        */
173};
174
175class RpUnits
176{
177    /*
178     * helpful units site
179     * http://aurora.regenstrief.org/~gunther/units.html
180     */
181
182    public:
183       
184        // users member fxns
185        std::string getUnits();
186        std::string getUnitsName();
187        double getExponent();
188        RpUnits* getBasis();
189
190        // convert from one RpUnits to another if the conversion is defined
191        double convert(RpUnits* toUnits, double val, int* result = NULL);
192        // convert from one RpUnits to another if the conversion is defined
193        void* convert(RpUnits* toUnits, void* val, int* result = NULL);
194        // convert from one RpUnits to another if the conversion is defined
195        double convert(std::string, double val);
196        // convert from one RpUnits to another if the conversion is defined
197        std::string convert (   RpUnits* toUnits,
198                                double val,
199                                int showUnits = 0,
200                                int* result = NULL  );
201
202        // dictionary to store the units.
203        // static RpDict<std::string,RpUnits> dict;
204
205        // turn the current unit to the metric system
206        // this should only be used for units that are part of the
207        // metric system. doesnt deal with exponents, just prefixes
208        double makeBasis(double value, int* result = NULL);
209        RpUnits & makeBasis(double* value, int* result = NULL);
210       
211        static int makeMetric(RpUnits * basis);
212
213        // find an RpUnits object that should exist in RpUnitsTable
214        // returns 0 on success (object was found)
215        // returns !0 on failure (object not found)
216        static RpUnits* find(std::string key)
217        {
218            // dict.find seems to return a (RpUnits* const) so i had to
219            // cast it as a (RpUnits*)
220
221            // dict pointer
222             // RpUnits* unitEntry = (RpUnits*) *(dict.find(key).getValue());
223             RpUnits* unitEntry = (RpUnits*) *(dict->find(key).getValue());
224
225            // RpUnits* unitEntry = (RpUnits*) dEntr.getValue();
226
227            // dict pointer
228            // if (unitEntry == (RpUnits*)dict.getNullEntry().getValue()) {
229            if (unitEntry == (RpUnits*)dict->getNullEntry().getValue()) {
230                unitEntry = NULL;
231            }
232
233            return unitEntry;
234        };
235
236        // user calls define to add a RpUnits object or to add a relation rule
237        //
238        // add RpUnits Object
239        static RpUnits * define(const std::string units, RpUnits * basis);
240        //
241        // add relation rule
242
243        static RpUnits * define(RpUnits* from,
244                                RpUnits* to,
245                                double (*convForwFxnPtr)(double),
246                                double (*convBackFxnPtr)(double));
247
248        static RpUnits * define(RpUnits* from,
249                                RpUnits* to,
250                                void* (*convForwFxnPtr)(void*, void*),
251                                void* convForwData,
252                                void* (*convBackFxnPtr)(void*, void*),
253                                void* convBackData);
254
255        // undefining a relation rule is probably not needed
256        // int undefine(); // delete a relation
257
258        // convert fxn will be taken care of in the RpUnitsConversion class
259        // i think
260        // int convert(const char* from, const char* to);
261
262        // why are these functions friends...
263        // probably need to find a better way to let RpUnits
264        // use the RpDict and RpDictEntry fxns
265        friend class RpDict<std::string,RpUnits*>;
266        friend class RpDictEntry<std::string,RpUnits*>;
267
268        // copy constructor
269        RpUnits ( const RpUnits& myRpUnit )
270        {
271
272            /*
273            from = myRpUnit.from;
274            to = myRpUnit.to;
275            convertForw = myRpUnit.convertForw;
276            convertBack = myRpUnit.convertBack;
277            */
278
279            // copy constructor for unit
280            unit* tmp = NULL;
281            unit* newUnit = NULL;
282            unit* p = myRpUnit.head;
283
284            while (p != NULL) {
285                newUnit = new unit(p->units, p->exponent,p->basis,NULL);
286
287                newUnit->prev = tmp;
288                if (tmp) {
289                    tmp->next = newUnit;
290                }
291
292                tmp = newUnit;
293                p = p->next;
294            }
295
296            if (tmp) {
297                while (tmp->prev != NULL) {
298                   tmp = tmp->prev;
299                }
300            }
301
302            head = tmp;
303               
304        };
305
306    private:
307
308        // i hope to replace these vars with a small class representing a
309        // of a linked list of units. that way we can handle complex units.
310        // this will also require that we move the getUnits, getExponent,
311        // and getBasis, makeBasis functionality into the smaller class,
312        // that represents each part of the units. we should keep getUnits,
313        // getBasis, and makeBasis in this class, but modify them to go
314        // through the linked list of units and combine the units back into
315        // what the caller expects to see.
316        // ie. cm2/Vms (mobility), will be split into the objects cm2, V, ms
317        // when getUnits is called, the user should see cm2/Vms again.
318        // for basis, possibly let the user choose a basis, and for makeBasis
319        // move through the linked list, only converting the metric elements.
320        //
321       
322        // used by the RpUnits when defining units elements
323        unit* head;
324
325        // linked list of units this RpUnit can convert to
326        convEntry* convList;
327
328        // used by the RpUnits when defining conversion elements
329        conversion* conv;
330
331        // dictionary to store the units.
332        // dict pointer
333        // static RpDict<std::string,RpUnits*> dict;
334        static RpDict<std::string,RpUnits*>* dict;
335
336        // create a units element
337        // class takes in three pieces of info
338        // 1) string describing the units
339        // 2) double describing the exponent
340        // 3) pointer to RpUnits object describing the basis
341        //      of the units (the fundamental unit)
342        //
343        RpUnits (
344                    const std::string& units,
345                    double& exponent,
346                    // RpUnits* basis[]
347                    RpUnits* basis
348                )
349            :   head        ( new unit( units, exponent, basis, NULL) ),
350                convList    (NULL),
351                conv        (NULL)
352        {};
353
354        // create a conversion element
355
356        RpUnits (
357                    RpUnits* from,
358                    RpUnits* to,
359                    double (*convForwFxnPtr)(double),
360                    double (*convBackFxnPtr)(double),
361                    conversion* prev,
362                    conversion* next
363                )
364            :   head (NULL),
365                convList (NULL),
366                conv (new conversion
367                        (from,to,convForwFxnPtr,convBackFxnPtr,prev,next))
368        {
369            connectConversion(from);
370            connectConversion(to);
371        };
372
373        RpUnits (
374                    RpUnits* from,
375                    RpUnits* to,
376                    void* (*convForwFxnPtr)(void*, void*),
377                    void* convForwData,
378                    void* (*convBackFxnPtr)(void*, void*),
379                    void* convBackData,
380                    conversion* prev,
381                    conversion* next
382                )
383            :   head (NULL),
384                convList (NULL),
385                conv (new conversion (  from, to,
386                                        convForwFxnPtr, convForwData,
387                                        convBackFxnPtr, convBackData,
388                                        prev, next
389                                     )
390                     )
391        {
392            connectConversion(from);
393            connectConversion(to);
394        };
395
396        // default destructor
397        //
398        //~RpUnits ();
399        ~RpUnits ()
400        {
401            // clean up dynamic memory
402
403            unit* p = head;
404            while (p != NULL) {
405                unit* tmp = p;
406                p = p->next;
407                delete tmp;
408            }
409        }
410
411        void RpUnits::connectConversion(RpUnits* myRpUnit);
412
413        void RpUnits::fillMetricMap();
414
415        // create the container keeping track of defined units
416        // returns 0 on success (table created or already exists)
417        // returns !0 on failure (table not created or cannot exist)
418        int RpUnits::createUnitsTable();
419
420        // insert new RpUnits object into RpUnitsTable
421        // returns 0 on success (object inserted or already exists)
422        // returns !0 on failure (object cannot be inserted or dne)
423        int RpUnits::insert(std::string key);   
424
425        // link two RpUnits objects that already exist in RpUnitsTable
426        // returns 0 on success (linking within table was successful)
427        // returns !0 on failure (linking was not successful)
428        int RpUnits::link(RpUnits * unitA);
429
430
431        static int pre_compare( std::string& units, RpUnits* basis = NULL);
432        void addUnit( const std::string& units,
433                      double &  exponent,
434                      RpUnits * basis
435                     );
436
437
438};
439
440/*--------------------------------------------------------------------------*/
441/*--------------------------------------------------------------------------*/
442
443// #include "../src/RpUnits.cc"
444
445#endif
Note: See TracBrowser for help on using the repository browser.