1 | /* |
---|
2 | * ---------------------------------------------------------------------- |
---|
3 | * RpUnits.h - Header file for Rappture Units |
---|
4 | * |
---|
5 | * RpUnits Class Declaration / Definition |
---|
6 | * |
---|
7 | * ====================================================================== |
---|
8 | * AUTHOR: Derrick Kearney, Purdue University |
---|
9 | * Copyright (c) 2004-2007 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 | |
---|
16 | #ifndef _RpUNITS_H |
---|
17 | #define _RpUNITS_H |
---|
18 | |
---|
19 | enum RP_UNITS_CONSTS { |
---|
20 | RPUNITS_UNITS_OFF = 0, |
---|
21 | RPUNITS_UNITS_ON = 1, |
---|
22 | |
---|
23 | // units naming flags |
---|
24 | RPUNITS_POS_EXP = 1, |
---|
25 | RPUNITS_NEG_EXP = 2, |
---|
26 | RPUNITS_STRICT_NAME = 4, |
---|
27 | RPUNITS_ORIG_EXP = 7 |
---|
28 | }; |
---|
29 | |
---|
30 | // RpUnits Case Insensitivity define |
---|
31 | #define RPUNITS_CASE_INSENSITIVE true |
---|
32 | |
---|
33 | #define RPUNITS_METRIC true |
---|
34 | |
---|
35 | //define our different types of units |
---|
36 | #define RP_TYPE_ENERGY "energy" |
---|
37 | #define RP_TYPE_EPOT "electric_potential" |
---|
38 | #define RP_TYPE_LENGTH "length" |
---|
39 | #define RP_TYPE_TEMP "temperature" |
---|
40 | #define RP_TYPE_TIME "time" |
---|
41 | #define RP_TYPE_VOLUME "volume" |
---|
42 | #define RP_TYPE_ANGLE "angle" |
---|
43 | #define RP_TYPE_MASS "mass" |
---|
44 | #define RP_TYPE_PREFIX "prefix" |
---|
45 | #define RP_TYPE_PRESSURE "pressure" |
---|
46 | #define RP_TYPE_CONC "concentration" |
---|
47 | #define RP_TYPE_FORCE "force" |
---|
48 | #define RP_TYPE_MISC "misc" |
---|
49 | |
---|
50 | |
---|
51 | #ifdef __cplusplus |
---|
52 | |
---|
53 | #include <iostream> |
---|
54 | #include <string> |
---|
55 | #include <list> |
---|
56 | #include <sstream> |
---|
57 | #include <stdlib.h> |
---|
58 | #include <errno.h> |
---|
59 | #include <math.h> |
---|
60 | |
---|
61 | #include "RpDict.h" |
---|
62 | #include "RpUnitsStd.h" |
---|
63 | |
---|
64 | #define LIST_TEMPLATE RpUnitsListEntry |
---|
65 | |
---|
66 | class RpUnits; |
---|
67 | |
---|
68 | class RpUnitsPreset { |
---|
69 | public: |
---|
70 | RpUnitsPreset () { |
---|
71 | addPresetAll(); |
---|
72 | }; |
---|
73 | |
---|
74 | static int addPresetAll(); |
---|
75 | static int addPresetEnergy(); |
---|
76 | static int addPresetLength(); |
---|
77 | static int addPresetTemp(); |
---|
78 | static int addPresetTime(); |
---|
79 | static int addPresetVolume(); |
---|
80 | static int addPresetAngle(); |
---|
81 | static int addPresetMass(); |
---|
82 | static int addPresetPrefix(); |
---|
83 | static int addPresetPressure(); |
---|
84 | static int addPresetConcentration(); |
---|
85 | static int addPresetForce(); |
---|
86 | static int addPresetMisc(); |
---|
87 | }; |
---|
88 | |
---|
89 | class RpUnitsTypes { |
---|
90 | public: |
---|
91 | |
---|
92 | typedef bool (*RpUnitsTypesHint)(RpUnits*); |
---|
93 | static RpUnitsTypesHint getTypeHint (std::string type); |
---|
94 | |
---|
95 | static bool hintTypePrefix ( RpUnits* unitObj ); |
---|
96 | static bool hintTypeNonPrefix ( RpUnits* unitObj ); |
---|
97 | static bool hintTypeEnergy ( RpUnits* unitObj ); |
---|
98 | static bool hintTypeEPot ( RpUnits* unitObj ); |
---|
99 | static bool hintTypeLength ( RpUnits* unitObj ); |
---|
100 | static bool hintTypeTemp ( RpUnits* unitObj ); |
---|
101 | static bool hintTypeTime ( RpUnits* unitObj ); |
---|
102 | static bool hintTypeVolume ( RpUnits* unitObj ); |
---|
103 | static bool hintTypeAngle ( RpUnits* unitObj ); |
---|
104 | static bool hintTypeMass ( RpUnits* unitObj ); |
---|
105 | static bool hintTypePressure ( RpUnits* unitObj ); |
---|
106 | static bool hintTypeConc ( RpUnits* unitObj ); |
---|
107 | static bool hintTypeForce ( RpUnits* unitObj ); |
---|
108 | static bool hintTypeMisc ( RpUnits* unitObj ); |
---|
109 | |
---|
110 | private: |
---|
111 | |
---|
112 | RpUnitsTypes () {}; |
---|
113 | }; |
---|
114 | |
---|
115 | // simple class to hold info about a conversion. |
---|
116 | // holds where we are converting from |
---|
117 | // holds where we are converting to |
---|
118 | // hold the pointer to a function to do the forward conversion (from->to) |
---|
119 | // hold the pointer to a function to do the backward conversion (to->from) |
---|
120 | // |
---|
121 | class conversion |
---|
122 | { |
---|
123 | public: |
---|
124 | |
---|
125 | const RpUnits* getFrom() { return (const RpUnits*) fromPtr; }; |
---|
126 | const RpUnits* getTo() { return (const RpUnits*) toPtr; }; |
---|
127 | |
---|
128 | friend class RpUnits; |
---|
129 | |
---|
130 | // copy constructor |
---|
131 | conversion ( conversion& other) |
---|
132 | : fromPtr (other.fromPtr), |
---|
133 | toPtr (other.toPtr), |
---|
134 | convForwFxnPtr (other.convForwFxnPtr), |
---|
135 | convBackFxnPtr (other.convBackFxnPtr), |
---|
136 | convForwFxnPtrDD (other.convForwFxnPtrDD), |
---|
137 | convBackFxnPtrDD (other.convBackFxnPtrDD), |
---|
138 | convForwFxnPtrVoid (other.convForwFxnPtrVoid), |
---|
139 | convForwData (other.convForwData), |
---|
140 | convBackFxnPtrVoid (other.convBackFxnPtrVoid), |
---|
141 | convBackData (other.convBackData) |
---|
142 | {}; |
---|
143 | |
---|
144 | // copy assignment operator |
---|
145 | conversion& operator= ( conversion& other ) |
---|
146 | { |
---|
147 | fromPtr = other.fromPtr; |
---|
148 | toPtr = other.toPtr; |
---|
149 | convForwFxnPtr = other.convForwFxnPtr; |
---|
150 | convBackFxnPtr = other.convBackFxnPtr; |
---|
151 | convForwFxnPtrDD = other.convForwFxnPtrDD; |
---|
152 | convBackFxnPtrDD = other.convBackFxnPtrDD; |
---|
153 | convForwFxnPtrVoid = other.convForwFxnPtrVoid; |
---|
154 | convForwData = other.convForwData; |
---|
155 | convBackFxnPtrVoid = other.convBackFxnPtrVoid; |
---|
156 | convBackData = other.convBackData; |
---|
157 | return *this; |
---|
158 | } |
---|
159 | |
---|
160 | // default destructor |
---|
161 | virtual ~conversion () |
---|
162 | {} |
---|
163 | |
---|
164 | private: |
---|
165 | |
---|
166 | const RpUnits* fromPtr; |
---|
167 | const RpUnits* toPtr; |
---|
168 | double (*convForwFxnPtr)(double); |
---|
169 | double (*convBackFxnPtr)(double); |
---|
170 | double (*convForwFxnPtrDD)(double,double); |
---|
171 | double (*convBackFxnPtrDD)(double,double); |
---|
172 | void* (*convForwFxnPtrVoid)(void*, void*); |
---|
173 | void* convForwData; |
---|
174 | void* (*convBackFxnPtrVoid)(void*, void*); |
---|
175 | void* convBackData; |
---|
176 | |
---|
177 | // constructor |
---|
178 | // private because i only want RpUnits to be able to |
---|
179 | // create a conversion |
---|
180 | conversion ( |
---|
181 | const RpUnits* fromPtr, |
---|
182 | const RpUnits* toPtr, |
---|
183 | double (*convForwFxnPtr)(double), |
---|
184 | double (*convBackFxnPtr)(double) |
---|
185 | ) |
---|
186 | : fromPtr (fromPtr), |
---|
187 | toPtr (toPtr), |
---|
188 | convForwFxnPtr (convForwFxnPtr), |
---|
189 | convBackFxnPtr (convBackFxnPtr), |
---|
190 | convForwFxnPtrDD (NULL), |
---|
191 | convBackFxnPtrDD (NULL), |
---|
192 | convForwFxnPtrVoid (NULL), |
---|
193 | convForwData (NULL), |
---|
194 | convBackFxnPtrVoid (NULL), |
---|
195 | convBackData (NULL) |
---|
196 | {}; |
---|
197 | |
---|
198 | // constructor for 2 argument conversion functions |
---|
199 | conversion ( |
---|
200 | const RpUnits* fromPtr, |
---|
201 | const RpUnits* toPtr, |
---|
202 | double (*convForwFxnPtr)(double,double), |
---|
203 | double (*convBackFxnPtr)(double,double) |
---|
204 | ) |
---|
205 | : fromPtr (fromPtr), |
---|
206 | toPtr (toPtr), |
---|
207 | convForwFxnPtr (NULL), |
---|
208 | convBackFxnPtr (NULL), |
---|
209 | convForwFxnPtrDD (convForwFxnPtr), |
---|
210 | convBackFxnPtrDD (convBackFxnPtr), |
---|
211 | convForwFxnPtrVoid (NULL), |
---|
212 | convForwData (NULL), |
---|
213 | convBackFxnPtrVoid (NULL), |
---|
214 | convBackData (NULL) |
---|
215 | {}; |
---|
216 | |
---|
217 | // constructor for user defined void* returning 1 arg conversion fxns. |
---|
218 | // the 1 arg is a user defined void* object |
---|
219 | conversion ( |
---|
220 | const RpUnits* fromPtr, |
---|
221 | const RpUnits* toPtr, |
---|
222 | void* (*convForwFxnPtrVoid)(void*, void*), |
---|
223 | void* convForwData, |
---|
224 | void* (*convBackFxnPtrVoid)(void*, void*), |
---|
225 | void* convBackData |
---|
226 | ) |
---|
227 | : fromPtr (fromPtr), |
---|
228 | toPtr (toPtr), |
---|
229 | convForwFxnPtr (NULL), |
---|
230 | convBackFxnPtr (NULL), |
---|
231 | convForwFxnPtrDD (NULL), |
---|
232 | convBackFxnPtrDD (NULL), |
---|
233 | convForwFxnPtrVoid (convForwFxnPtrVoid), |
---|
234 | convForwData (convForwData), |
---|
235 | convBackFxnPtrVoid (convBackFxnPtrVoid), |
---|
236 | convBackData (convBackData) |
---|
237 | {}; |
---|
238 | |
---|
239 | }; |
---|
240 | |
---|
241 | // used by the RpUnits class to create a linked list of the conversions |
---|
242 | // associated with the specific unit. |
---|
243 | // |
---|
244 | // we could templitize this and make a generic linked list |
---|
245 | // or could use generic linked list class from book programming with objects |
---|
246 | // |
---|
247 | class convEntry |
---|
248 | { |
---|
249 | |
---|
250 | public: |
---|
251 | |
---|
252 | friend class RpUnits; |
---|
253 | |
---|
254 | virtual ~convEntry() |
---|
255 | {} |
---|
256 | |
---|
257 | private: |
---|
258 | |
---|
259 | conversion* conv; |
---|
260 | convEntry* prev; |
---|
261 | convEntry* next; |
---|
262 | |
---|
263 | convEntry ( |
---|
264 | conversion* conv, |
---|
265 | convEntry* prev, |
---|
266 | convEntry* next |
---|
267 | ) |
---|
268 | : conv (conv), |
---|
269 | prev (prev), |
---|
270 | next (next) |
---|
271 | {}; |
---|
272 | |
---|
273 | }; |
---|
274 | |
---|
275 | // used by the RpUnits class to create a linked list of the incarnated units |
---|
276 | // associated with the specific unit. |
---|
277 | // |
---|
278 | // we could templitize this and make a generic linked list |
---|
279 | // or could use generic linked list class from book programming with objects |
---|
280 | // |
---|
281 | class incarnationEntry |
---|
282 | { |
---|
283 | |
---|
284 | public: |
---|
285 | |
---|
286 | friend class RpUnits; |
---|
287 | |
---|
288 | virtual ~incarnationEntry() |
---|
289 | {} |
---|
290 | |
---|
291 | private: |
---|
292 | |
---|
293 | const RpUnits* unit; |
---|
294 | incarnationEntry* prev; |
---|
295 | incarnationEntry* next; |
---|
296 | |
---|
297 | incarnationEntry ( |
---|
298 | const RpUnits* unit, |
---|
299 | incarnationEntry* prev, |
---|
300 | incarnationEntry* next |
---|
301 | ) |
---|
302 | : unit (unit), |
---|
303 | prev (prev), |
---|
304 | next (next) |
---|
305 | {}; |
---|
306 | |
---|
307 | }; |
---|
308 | |
---|
309 | class RpUnitsListEntry |
---|
310 | { |
---|
311 | |
---|
312 | public: |
---|
313 | |
---|
314 | // constructor |
---|
315 | RpUnitsListEntry (const RpUnits* unit, double exponent, const RpUnits* prefix=NULL) |
---|
316 | : unit (unit), |
---|
317 | exponent (exponent), |
---|
318 | prefix (prefix) |
---|
319 | {}; |
---|
320 | |
---|
321 | // copy constructor |
---|
322 | RpUnitsListEntry (const RpUnitsListEntry& other) |
---|
323 | : unit (other.unit), |
---|
324 | exponent (other.exponent), |
---|
325 | prefix (other.prefix) |
---|
326 | {}; |
---|
327 | |
---|
328 | // copy assignment operator |
---|
329 | RpUnitsListEntry& operator= (const RpUnitsListEntry& other) { |
---|
330 | unit = other.unit; |
---|
331 | exponent = other.exponent; |
---|
332 | prefix = other.prefix; |
---|
333 | return *this; |
---|
334 | } |
---|
335 | |
---|
336 | // negate the exponent |
---|
337 | void negateExponent() const; |
---|
338 | |
---|
339 | // print the name of the object |
---|
340 | std::string name(int flags=RPUNITS_ORIG_EXP) const; |
---|
341 | |
---|
342 | // report the basis of the RpUnits object being stored. |
---|
343 | const RpUnits* getBasis() const; |
---|
344 | |
---|
345 | // return the RpUnits* |
---|
346 | const RpUnits* getUnitsObj() const; |
---|
347 | |
---|
348 | // return the exponent |
---|
349 | double getExponent() const; |
---|
350 | |
---|
351 | // return the metric prefix associated with this object |
---|
352 | const RpUnits* getPrefix() const; |
---|
353 | |
---|
354 | // destructor |
---|
355 | virtual ~RpUnitsListEntry () |
---|
356 | {} |
---|
357 | |
---|
358 | private: |
---|
359 | |
---|
360 | const RpUnits* unit; |
---|
361 | mutable double exponent; |
---|
362 | const RpUnits* prefix; |
---|
363 | }; |
---|
364 | |
---|
365 | class RpUnits |
---|
366 | { |
---|
367 | /* |
---|
368 | * helpful units site |
---|
369 | * http://aurora.regenstrief.org/~gunther/units.html |
---|
370 | * http://www.nodc.noaa.gov/dsdt/ucg/ |
---|
371 | * http://www.cellml.org/meeting_minutes/archive/ |
---|
372 | * 20010110_meeting_minutes.html |
---|
373 | */ |
---|
374 | |
---|
375 | public: |
---|
376 | |
---|
377 | static bool cmpFxn (char c1, char c2) |
---|
378 | { |
---|
379 | int lc1 = toupper(static_cast<unsigned char>(c1)); |
---|
380 | int lc2 = toupper(static_cast<unsigned char>(c2)); |
---|
381 | |
---|
382 | if ( (lc1 < lc2) || (lc1 > lc2) ) { |
---|
383 | return false; |
---|
384 | } |
---|
385 | |
---|
386 | return true; |
---|
387 | |
---|
388 | } |
---|
389 | struct _key_compare: |
---|
390 | public |
---|
391 | std::binary_function<std::string,std::string,bool> { |
---|
392 | |
---|
393 | bool operator() ( const std::string& lhs, |
---|
394 | const std::string& rhs ) const |
---|
395 | { |
---|
396 | return std::lexicographical_compare( lhs.begin(),lhs.end(), |
---|
397 | rhs.begin(),rhs.end(), |
---|
398 | RpUnits::cmpFxn ); |
---|
399 | } |
---|
400 | }; |
---|
401 | |
---|
402 | // why are these functions friends... |
---|
403 | // probably need to find a better way to let RpUnits |
---|
404 | // use the RpDict and RpDictEntry fxns |
---|
405 | friend class RpDict<std::string,RpUnits*,_key_compare>; |
---|
406 | friend class RpDictEntry<std::string,RpUnits*,_key_compare>; |
---|
407 | // users member fxns |
---|
408 | std::string getUnits() const; |
---|
409 | std::string getUnitsName(int flags=RPUNITS_ORIG_EXP) const; |
---|
410 | std::string getSearchName() const; |
---|
411 | double getExponent() const; |
---|
412 | const RpUnits* getBasis() const; |
---|
413 | RpUnits& setMetric(bool newVal); |
---|
414 | |
---|
415 | // retrieve a units type. |
---|
416 | std::string getType() const; |
---|
417 | |
---|
418 | // retrieve the case insensitivity of this unit object |
---|
419 | bool getCI() const; |
---|
420 | |
---|
421 | // retrieve a list of compatible units. |
---|
422 | std::list<std::string> getCompatible(double expMultiplier=1.0) const; |
---|
423 | |
---|
424 | |
---|
425 | // convert from one RpUnits to another if the conversion is defined |
---|
426 | double convert( const RpUnits* toUnits, |
---|
427 | double val, |
---|
428 | int* result=NULL ) const; |
---|
429 | // convert from one RpUnits to another if the conversion is defined |
---|
430 | void* convert( const RpUnits* toUnits, |
---|
431 | void* val, |
---|
432 | int* result=NULL) const; |
---|
433 | // convert from one RpUnits to another if the conversion is defined |
---|
434 | // double convert(std::string, double val); |
---|
435 | // convert from one RpUnits to another if the conversion is defined |
---|
436 | std::string convert ( const RpUnits* toUnits, |
---|
437 | double val, |
---|
438 | int showUnits = RPUNITS_UNITS_OFF, |
---|
439 | int* result = NULL ) const; |
---|
440 | |
---|
441 | static std::string convert ( std::string val, |
---|
442 | std::string toUnits, |
---|
443 | int showUnits = RPUNITS_UNITS_OFF, |
---|
444 | int* result = NULL ); |
---|
445 | |
---|
446 | // turn the current unit to the metric system |
---|
447 | // this should only be used for units that are part of the |
---|
448 | // metric system. doesnt deal with exponents, just prefixes |
---|
449 | double makeBasis(double value, int* result = NULL) const; |
---|
450 | const RpUnits & makeBasis(double* value, int* result = NULL) const; |
---|
451 | |
---|
452 | static int makeMetric(RpUnits * basis); |
---|
453 | |
---|
454 | // find a RpUnits object that should exist in RpUnitsTable |
---|
455 | // returns 0 on success (object was found) |
---|
456 | // returns !0 on failure (object not found) |
---|
457 | static const RpUnits* find( std::string key, |
---|
458 | RpDict<std::string,RpUnits*,_key_compare>::RpDictHint hint = NULL); |
---|
459 | |
---|
460 | // validate is very similar to find, but it works better |
---|
461 | // for seeing complex units can be interpreted. |
---|
462 | // it validates that if the a certain units string is |
---|
463 | // provided as a unit type, then all of the base components |
---|
464 | // of that unit are available for conversions. |
---|
465 | // returns 0 on success (units are valid) |
---|
466 | // returns !0 on failure (units not valid) |
---|
467 | static int validate(std::string& inUnits, |
---|
468 | std::string& type, |
---|
469 | std::list<std::string>* compatList=NULL); |
---|
470 | |
---|
471 | // user calls define to add a RpUnits object or to add a relation rule |
---|
472 | // |
---|
473 | // add RpUnits Object |
---|
474 | static RpUnits * define(const std::string units, |
---|
475 | const RpUnits* basis=NULL, |
---|
476 | const std::string type="", |
---|
477 | bool metric=false, |
---|
478 | bool caseInsensitive=RPUNITS_CASE_INSENSITIVE); |
---|
479 | |
---|
480 | // add relation rule |
---|
481 | |
---|
482 | static RpUnits * define(const RpUnits* from, |
---|
483 | const RpUnits* to, |
---|
484 | double (*convForwFxnPtr)(double), |
---|
485 | double (*convBackFxnPtr)(double)); |
---|
486 | |
---|
487 | static RpUnits * define(const RpUnits* from, |
---|
488 | const RpUnits* to, |
---|
489 | double (*convForwFxnPtr)(double,double), |
---|
490 | double (*convBackFxnPtr)(double,double)); |
---|
491 | |
---|
492 | static RpUnits * define(const RpUnits* from, |
---|
493 | const RpUnits* to, |
---|
494 | void* (*convForwFxnPtr)(void*, void*), |
---|
495 | void* convForwData, |
---|
496 | void* (*convBackFxnPtr)(void*, void*), |
---|
497 | void* convBackData); |
---|
498 | |
---|
499 | static int incarnate ( const RpUnits* abstraction, |
---|
500 | const RpUnits* entity); |
---|
501 | |
---|
502 | // populate the dictionary with a set of units specified by group |
---|
503 | // if group equals........................then load................ |
---|
504 | // "all" load all available units |
---|
505 | // RP_TYPE_ENERGY "energy" load units related to energy |
---|
506 | // RP_TYPE_EPOT "electric_potential" load units related to electric potential |
---|
507 | // RP_TYPE_LENGTH "length" load units related to length |
---|
508 | // RP_TYPE_TEMP "temperature" load units related to temperature |
---|
509 | // RP_TYPE_TIME "time" load units related to time |
---|
510 | // RP_TYPE_VOLUME "volume" load units related to volume |
---|
511 | // RP_TYPE_ANGLE "angle" load units related to angles |
---|
512 | // RP_TYPE_MASS "mass" load units related to mass |
---|
513 | // RP_TYPE_PREFIX "prefix" load unit prefixes |
---|
514 | // RP_TYPE_PRESSURE "pressure" load units related to pressure |
---|
515 | // RP_TYPE_CONC "concentration" load units related to concentration |
---|
516 | // RP_TYPE_FORCE "force" load units related to force |
---|
517 | // RP_TYPE_MISC "misc" load units related to everything else |
---|
518 | // (no other groups have been created) |
---|
519 | |
---|
520 | static int addPresets (const std::string group); |
---|
521 | |
---|
522 | // undefining a relation rule is probably not needed |
---|
523 | // int undefine(); // delete a relation |
---|
524 | |
---|
525 | |
---|
526 | friend int insert(std::string key,RpUnits* val); |
---|
527 | |
---|
528 | |
---|
529 | // copy constructor |
---|
530 | RpUnits (RpUnits &other) |
---|
531 | : units (other.units), |
---|
532 | exponent (other.exponent), |
---|
533 | basis (other.basis), |
---|
534 | type (other.type), |
---|
535 | metric (other.metric), |
---|
536 | ci (other.ci), |
---|
537 | convList (NULL) |
---|
538 | { |
---|
539 | convEntry* q = NULL; |
---|
540 | convEntry* curr = NULL; |
---|
541 | |
---|
542 | incarnationEntry* r = NULL; |
---|
543 | incarnationEntry* rcurr = NULL; |
---|
544 | |
---|
545 | dict = other.dict; |
---|
546 | |
---|
547 | if (other.convList) { |
---|
548 | q = other.convList; |
---|
549 | convList = new convEntry (q->conv,NULL,NULL); |
---|
550 | curr = convList; |
---|
551 | while (q->next) { |
---|
552 | q = q->next; |
---|
553 | curr->next = new convEntry (q->conv,curr,NULL); |
---|
554 | curr = curr->next; |
---|
555 | } |
---|
556 | } |
---|
557 | |
---|
558 | if (other.incarnationList) { |
---|
559 | r = other.incarnationList; |
---|
560 | incarnationList = new incarnationEntry (r->unit,NULL,NULL); |
---|
561 | rcurr = incarnationList; |
---|
562 | while (r->next) { |
---|
563 | r = r->next; |
---|
564 | rcurr->next = new incarnationEntry (r->unit,rcurr,NULL); |
---|
565 | rcurr = rcurr->next; |
---|
566 | } |
---|
567 | } |
---|
568 | |
---|
569 | } |
---|
570 | |
---|
571 | // copy assignment operator |
---|
572 | RpUnits& operator= (const RpUnits& other) { |
---|
573 | |
---|
574 | convEntry* q = NULL; |
---|
575 | convEntry* curr = NULL; |
---|
576 | |
---|
577 | incarnationEntry* r = NULL; |
---|
578 | incarnationEntry* rcurr = NULL; |
---|
579 | |
---|
580 | if ( this != &other ) { |
---|
581 | delete convList; |
---|
582 | } |
---|
583 | |
---|
584 | dict = other.dict; |
---|
585 | units = other.units; |
---|
586 | exponent = other.exponent; |
---|
587 | basis = other.basis; |
---|
588 | type = other.type; |
---|
589 | metric = other.metric; |
---|
590 | ci = other.ci; |
---|
591 | |
---|
592 | if (other.convList) { |
---|
593 | q = other.convList; |
---|
594 | convList = new convEntry (q->conv,NULL,NULL); |
---|
595 | curr = convList; |
---|
596 | while (q->next) { |
---|
597 | q = q->next; |
---|
598 | curr->next = new convEntry (q->conv,curr,NULL); |
---|
599 | curr = curr->next; |
---|
600 | } |
---|
601 | } |
---|
602 | |
---|
603 | if (other.incarnationList) { |
---|
604 | r = other.incarnationList; |
---|
605 | incarnationList = new incarnationEntry (r->unit,NULL,NULL); |
---|
606 | rcurr = incarnationList; |
---|
607 | while (r->next) { |
---|
608 | r = r->next; |
---|
609 | rcurr->next = new incarnationEntry (r->unit,rcurr,NULL); |
---|
610 | rcurr = rcurr->next; |
---|
611 | } |
---|
612 | } |
---|
613 | |
---|
614 | return *this; |
---|
615 | } |
---|
616 | |
---|
617 | // default destructor |
---|
618 | // |
---|
619 | ~RpUnits () |
---|
620 | { |
---|
621 | // go to the type list and remove a variable by this name |
---|
622 | |
---|
623 | |
---|
624 | // clean up dynamic memory |
---|
625 | |
---|
626 | convEntry* p = convList; |
---|
627 | convEntry* tmp = p; |
---|
628 | |
---|
629 | incarnationEntry* r = incarnationList; |
---|
630 | incarnationEntry* rtmp = r; |
---|
631 | |
---|
632 | while (p != NULL) { |
---|
633 | tmp = p; |
---|
634 | p = p->next; |
---|
635 | delete tmp; |
---|
636 | } |
---|
637 | |
---|
638 | while (p != NULL) { |
---|
639 | rtmp = r; |
---|
640 | r = r->next; |
---|
641 | delete rtmp; |
---|
642 | } |
---|
643 | } |
---|
644 | |
---|
645 | private: |
---|
646 | |
---|
647 | // i hope to replace these vars with a small class representing a |
---|
648 | // of a linked list of units. that way we can handle complex units. |
---|
649 | // this will also require that we move the getUnits, getExponent, |
---|
650 | // and getBasis, makeBasis functionality into the smaller class, |
---|
651 | // that represents each part of the units. we should keep getUnits, |
---|
652 | // getBasis, and makeBasis in this class, but modify them to go |
---|
653 | // through the linked list of units and combine the units back into |
---|
654 | // what the caller expects to see. |
---|
655 | // ie. cm2/Vms (mobility), will be split into the objects cm2, V, ms |
---|
656 | // when getUnits is called, the user should see cm2/Vms again. |
---|
657 | // for basis, possibly let the user choose a basis, and for makeBasis |
---|
658 | // move through the linked list, only converting the metric elements. |
---|
659 | // |
---|
660 | |
---|
661 | std::string units; |
---|
662 | double exponent; |
---|
663 | const RpUnits* basis; |
---|
664 | std::string type; |
---|
665 | |
---|
666 | // tell if the unit can accept metric prefixes |
---|
667 | bool metric; |
---|
668 | |
---|
669 | // should this unit be inserted as a case insensitive unit? |
---|
670 | bool ci; |
---|
671 | |
---|
672 | // linked list of units this RpUnit can convert to |
---|
673 | // its mutable because the connectConversion function takes in a |
---|
674 | // const RpUnits* and attempts to change the convList variable |
---|
675 | // within the RpUnits Object |
---|
676 | mutable convEntry* convList; |
---|
677 | |
---|
678 | // linked list of incarnation units for this RpUnit |
---|
679 | // its mutable because the connectIncarnation function takes in a |
---|
680 | // const RpUnits* and attempts to change the incarnationList variable |
---|
681 | // within the RpUnits Object |
---|
682 | mutable incarnationEntry* incarnationList; |
---|
683 | |
---|
684 | // dictionary to store the units. |
---|
685 | static RpDict<std::string,RpUnits*,_key_compare>* dict; |
---|
686 | |
---|
687 | // create a units element |
---|
688 | // class takes in three pieces of info |
---|
689 | // 1) string describing the units |
---|
690 | // 2) double describing the exponent |
---|
691 | // 3) pointer to RpUnits object describing the basis |
---|
692 | // of the units (the fundamental unit) |
---|
693 | // |
---|
694 | |
---|
695 | RpUnits ( |
---|
696 | const std::string& units, |
---|
697 | double& exponent, |
---|
698 | const RpUnits* basis, |
---|
699 | const std::string type, |
---|
700 | bool metric, |
---|
701 | bool caseInsensitive |
---|
702 | ) |
---|
703 | : units (units), |
---|
704 | exponent (exponent), |
---|
705 | basis (basis), |
---|
706 | type (type), |
---|
707 | metric (metric), |
---|
708 | ci (caseInsensitive), |
---|
709 | convList (NULL), |
---|
710 | incarnationList (NULL) |
---|
711 | {}; |
---|
712 | |
---|
713 | // insert new RpUnits object into RpUnitsTable |
---|
714 | // returns 0 on success (object inserted or already exists) |
---|
715 | // returns !0 on failure (object cannot be inserted or dne) |
---|
716 | // int RpUnits::insert(std::string key) const; |
---|
717 | |
---|
718 | typedef std::list<LIST_TEMPLATE> RpUnitsList; |
---|
719 | typedef double (*convFxnPtrD) (double); |
---|
720 | typedef std::list<convFxnPtrD> convertList; |
---|
721 | typedef RpUnitsList::iterator RpUnitsListIter; |
---|
722 | |
---|
723 | // void newExponent (double newExponent) {exponent = newExponent;}; |
---|
724 | |
---|
725 | static int units2list ( const std::string& inUnits, |
---|
726 | RpUnitsList& outList, |
---|
727 | std::string& type ); |
---|
728 | static int list2units ( RpUnitsList& inList, |
---|
729 | std::string& outUnitsStr ); |
---|
730 | static int grabExponent ( const std::string& inStr, |
---|
731 | double* exp ); |
---|
732 | static int grabUnitString ( const std::string& inStr ); |
---|
733 | static int grabUnits ( std::string inStr, |
---|
734 | int* offset, |
---|
735 | const RpUnits** unit, |
---|
736 | const RpUnits** prefix ); |
---|
737 | static int checkMetricPrefix ( std::string inStr, |
---|
738 | int* offset, |
---|
739 | const RpUnits** prefix ); |
---|
740 | static int negateListExponents ( RpUnitsList& unitsList ); |
---|
741 | static int printList ( RpUnitsList& unitsList ); |
---|
742 | |
---|
743 | static int compareListEntryBasis ( RpUnitsList& fromList, |
---|
744 | RpUnitsListIter& fromIter, |
---|
745 | RpUnitsListIter& toIter ); |
---|
746 | |
---|
747 | static int compareListEntrySearch ( RpUnitsList& fromList, |
---|
748 | RpUnitsListIter& fromIter, |
---|
749 | RpUnitsListIter& toIter ); |
---|
750 | |
---|
751 | void connectConversion ( conversion* conv ) const; |
---|
752 | void connectIncarnation ( const RpUnits* unit ) const; |
---|
753 | |
---|
754 | // return the conversion object that will convert |
---|
755 | // from this RpUnits to the proovided toUnits object |
---|
756 | // if the conversion is defined |
---|
757 | int getConvertFxnList ( const RpUnits* toUnits, |
---|
758 | convertList& cList ) const; |
---|
759 | static int applyConversion ( double* val, |
---|
760 | convertList& cList ); |
---|
761 | static int combineLists ( convertList& l1, |
---|
762 | convertList& l2 ); |
---|
763 | static int printList ( convertList& l1 ); |
---|
764 | |
---|
765 | }; |
---|
766 | |
---|
767 | /*--------------------------------------------------------------------------*/ |
---|
768 | /*--------------------------------------------------------------------------*/ |
---|
769 | |
---|
770 | int list2str (std::list<std::string>& inList, std::string& outString); |
---|
771 | |
---|
772 | int unitSlice (std::string inStr, std::string& outUnits, double& outVal); |
---|
773 | |
---|
774 | #endif // ifdef __cplusplus |
---|
775 | |
---|
776 | #endif // ifndef _RpUNITS_H |
---|