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