source: trunk/src/core/RpUnits.cc @ 76

Last change on this file since 76 was 76, checked in by dkearney, 15 years ago
  1. cleaned up make files some more, deleted make.inc files
  2. updated RpUnits module and Cee and Fortran interfaces
  3. changed return values for some fortran interfaces,

error messages not working yet

  1. still need to add copy assignment code to RpUnits
File size: 35.3 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  RpUnits.cc
4 *
5 * Data Members and member functions for the RpUnits class
6 *
7 * ======================================================================
8 *  AUTHOR:  Derrick Kearney, Purdue University
9 *  Copyright (c) 2004-2005
10 *  Purdue Research Foundation, West Lafayette, IN
11 * ======================================================================
12 */
13
14#include "RpUnits.h"
15
16// dict pointer
17RpDict<std::string,RpUnits*>* RpUnits::dict = new RpDict<std::string,RpUnits*>();
18
19/************************************************************************
20 *                                                                     
21 * add RpUnits Object                                                   
22 *                                                                     
23 ************************************************************************/
24
25RpUnits * RpUnits::define(const std::string units, RpUnits * basis)
26{
27    RpUnits * newRpUnit = NULL;
28
29    if (units == "") {
30        // raise error, user sent null units!
31        return NULL;
32    }
33
34    // check to see if the user is trying to trick me!
35    if ( (basis) && (units == basis->getUnits()) ) {
36        // dont trick me!
37        return NULL;
38    }
39
40    double exp = 0.0;
41    double oldExponent = 0;
42    double newExponent = 0;
43    int digiSearch = 0; // flag to show we are searching digits
44    int alphaSearch = 0; // flag to show we are searching chars
45
46    std::string cmpStr = "";
47
48    std::string::size_type length = units.length();
49    int srchIndex = length;
50    std::string srchStr = units;
51
52    while ((srchStr.length() > 0)) {
53
54        srchIndex--;
55 
56        if (srchIndex < 0) {
57            break;
58        }
59 
60        if     ( isdigit(srchStr[srchIndex]) && !digiSearch && !alphaSearch) {
61            digiSearch = 1;
62        }
63        else if(!isdigit(srchStr[srchIndex]) &&  digiSearch && !alphaSearch) {
64 
65            // convert our exponent to integer
66 
67            // check to see if there is a + or - sign
68            if (  ( srchStr[srchIndex] == '+' )
69               || ( srchStr[srchIndex] == '-' ) ) {
70 
71                // evaluate a '+' or '-' sign with the value
72                srchIndex--;
73            }
74 
75            srchIndex++;
76 
77            exp = atoi(&srchStr[srchIndex]);
78 
79            // we are no longer in a digit search
80            digiSearch = 0;
81 
82            // place null character where the number starts
83            // so we know what we've already parsed
84 
85            srchStr.erase(srchIndex);
86            length = srchStr.length();
87 
88        }
89        else if( isalpha(srchStr[srchIndex]) && !digiSearch && !alphaSearch) {
90            alphaSearch = 1;
91        }
92        else if(!isalpha(srchStr[srchIndex]) && !digiSearch && alphaSearch) {
93           
94            // adjust the exponent if none was provided
95            if (exp == 0) {
96                exp = 1;
97            }
98 
99            // compare unit string to see if it is a recognized system
100 
101 
102            std::string cmpStr = srchStr.substr(srchIndex+1,length-srchIndex-1);
103            if (newRpUnit) {
104                 newRpUnit->addUnit( cmpStr, exp, basis);
105            }
106            else {
107                 newRpUnit= new RpUnits(cmpStr, exp, basis);
108            }
109
110            // place a null character at the end of the string
111            // so we know what we've parsed so far.
112         
113            srchStr.erase(srchIndex);
114            length = srchStr.length();
115 
116            // fix our searching flag
117            alphaSearch = 0;
118
119        }
120        else if( srchStr[srchIndex] == '/' ) {
121            // have to go back to all of the objects created and
122            // multiply their exponents by -1.
123 
124            if (newRpUnit) {
125                unit* p = newRpUnit->head;
126                while (p) {
127                    oldExponent = p->getExponent();
128                    newExponent = oldExponent*-1;
129                    p->newExponent(newExponent);
130                    p = p->next;
131                }
132            }
133
134            // place a null character at the end of the string
135            // so we know what we've parsed so far.
136       
137            srchStr.erase(srchIndex);
138            length = srchStr.length();
139
140        }
141        else {
142            continue;
143        }
144
145
146    } // end while loop
147       
148
149    // complete the last iteration
150    if (srchIndex < 0) {
151
152
153        if (digiSearch) {
154            // convert whatever is left
155            exp = atoi(&srchStr[srchIndex+1]);
156           
157            // if we get here, that means units name starts with a digit
158            // normally we wont get here, but if we do, should we place
159            // the unit into the dictionary? i think not since digits are
160            // always considered exponents.
161        }
162        else if (alphaSearch) {
163            // adjust the exponent if none was provided
164            if (exp == 0) {
165                exp = 1;
166            }
167
168            // compare unit string to see if it is a recognized system
169
170            std::string cmpStr = srchStr.substr(srchIndex+1,length-srchIndex-1);
171            newRpUnit= new RpUnits(cmpStr, exp, basis);
172            newRpUnit->insert(newRpUnit->getUnitsName());
173        }
174    }
175
176    // place the new object into the dictionary
177   
178    // return a copy of the new object to user
179    return newRpUnit;
180}
181
182
183/************************************************************************
184 *                                                                     
185 * add a complex RpUnits Object                                                   
186 *                                                                     
187 ************************************************************************/
188
189RpUnits * RpUnits::defineCmplx ( const std::string units,
190                            RpUnits * basis )
191{
192    RpUnits * newRpUnit = NULL;
193
194    if (units == "") {
195        // raise error, user sent null units!
196        return NULL;
197    }
198
199    // check to see if the user is trying to trick me!
200    if ( (basis) && (units == basis->getUnits()) ) {
201        // dont trick me!
202        return NULL;
203    }
204
205    double exp = 0.0;
206    double oldExponent = 0;
207    double newExponent = 0;
208    int digiSearch = 0; // flag to show we are searching digits
209    int alphaSearch = 0; // flag to show we are searching chars
210    std::string dbText = "";
211
212    std::string cmpStr = "";
213    int cmpIndex = 0;
214
215    std::string::size_type length = units.length();
216    int srchIndex = length;
217    std::string srchStr = units;
218
219
220    while ((srchStr.length() > 0)) {
221
222        srchIndex--;
223 
224        if (srchIndex < 0) {
225            break;
226        }
227 
228        if     ( isdigit(srchStr[srchIndex]) && !digiSearch && !alphaSearch) {
229            digiSearch = 1;
230        }
231        else if(!isdigit(srchStr[srchIndex]) &&  digiSearch && !alphaSearch) {
232 
233            // convert our exponent to integer
234 
235            // check to see if there is a + or - sign
236            if (  ( srchStr[srchIndex] == '+' )
237               || ( srchStr[srchIndex] == '-' ) ) {
238 
239                // evaluate a '+' or '-' sign with the value
240                srchIndex--;
241            }
242 
243            srchIndex++;
244 
245            exp = atoi(&srchStr[srchIndex]);
246 
247            // we are no longer in a digit search
248            digiSearch = 0;
249 
250            // place null character where the number starts
251            // so we know what we've already parsed
252 
253            srchStr.erase(srchIndex);
254            length = srchStr.length();
255 
256        }
257        else if( isalpha(srchStr[srchIndex]) && !digiSearch && !alphaSearch) {
258            alphaSearch = 1;
259        }
260        else if(!isalpha(srchStr[srchIndex]) && !digiSearch && alphaSearch) {
261           
262            // adjust the exponent if none was provided
263            if (exp == 0) {
264                exp = 1;
265            }
266 
267            // compare unit string to see if it is a recognized system
268 
269 
270            std::string cmpStr = srchStr.substr(srchIndex+1,length-srchIndex-1);
271            cmpIndex = 0;
272 
273            if ( (unsigned)(cmpIndex = pre_compare(cmpStr,basis)) ==
274                    std::string::npos ) {
275                alphaSearch = 0;
276 
277                // there are units we did not recognize,
278                // right now we ignore them,
279                // we may want to deal with them differntly in the future
280 
281                // erase only the last character and reprocess the string
282                // because our precompare doesnt take care of this yet.
283                srchStr.erase(srchStr.length()-1);
284                length = srchStr.length();
285                srchIndex = length;
286               
287 
288                // continue parsing characters
289                continue;
290            }
291 
292            // the compare function was successful
293            // move the search pointer to one value infront of
294            // where the units were found.
295            //
296            // cmpIndex tells us how far ahead of the srchIndex the matching
297            // unit was found. so we add srchIndex to get the real index.
298            cmpIndex += srchIndex+1;
299            srchIndex = cmpIndex;
300            std::string newUnitText = srchStr.substr(cmpIndex,length-cmpIndex);
301 
302            // call the function to create the unit object
303 
304            // we need pre-compare to return the basis of what it found.
305            if (newRpUnit) {
306                 newRpUnit->addUnit( newUnitText, exp, basis);
307            }
308            else {
309                 newRpUnit= new RpUnits(newUnitText, exp, basis);
310            }
311 
312 
313            // place a null character at the end of the string
314            // so we know what we've parsed so far.
315         
316            srchStr.erase(srchIndex);
317            length = srchStr.length();
318 
319            // fix our searching flag
320            alphaSearch = 0;
321
322        }
323        else if( srchStr[srchIndex] == '/' ) {
324            // have to go back to all of the objects created and
325            // multiply their exponents by -1.
326 
327            if (newRpUnit) {
328                unit* p = newRpUnit->head;
329                while (p) {
330                    oldExponent = p->getExponent();
331                    newExponent = oldExponent*-1;
332                    p->newExponent(newExponent);
333                    p = p->next;
334                }
335            }
336
337            // place a null character at the end of the string
338            // so we know what we've parsed so far.
339       
340            srchStr.erase(srchIndex);
341            length = srchStr.length();
342
343        }
344        else {
345            continue;
346        }
347
348
349    } // end while loop
350       
351
352    // complete the last iteration
353    if (srchIndex < 0) {
354
355
356        if (digiSearch) {
357            // convert whatever is left
358            exp = atoi(&srchStr[srchIndex+1]);
359           
360            // if we get here, that means units name starts with a digit
361            // normally we wont get here, but if we do, should we place
362            // the unit into the dictionary? i think not since digits are
363            // always considered exponents.
364        }
365        else if (alphaSearch) {
366            // adjust the exponent if none was provided
367            if (exp == 0) {
368                exp = 1;
369            }
370
371            // compare unit string to see if it is a recognized system
372
373            std::string cmpStr = srchStr.substr(srchIndex+1,length-srchIndex-1);
374            cmpIndex = 0;
375
376            if ( (cmpIndex = pre_compare(cmpStr,basis)) < 0 ) {
377                // no matches in the compare function
378
379                // there are units we did not recognize,
380
381                // create a new unit with basis of null to show its a
382                // fundamental type
383                newRpUnit = new RpUnits(cmpStr, exp, basis);
384               
385                // put the unit into the dictionary
386                //
387                newRpUnit->insert(newRpUnit->getUnitsName());
388               
389
390            }
391            else {
392
393                // the compare function was successful
394                // move the search pointer to one value infront of
395                // where the units were found.
396                // adjusting the search pointer to point to the units
397                std::string newUnitText = srchStr.substr(cmpIndex,length-cmpIndex);
398
399                // call the function to create the unit object
400
401                // we need pre-compare to return the basis of what it found.
402                if (newRpUnit) {
403                     newRpUnit->addUnit( newUnitText, exp, basis );
404                }
405                else {
406                     newRpUnit = new RpUnits(newUnitText, exp, basis);
407                }
408
409                // creating unit
410                //
411                // putting unit into dictionary
412                newRpUnit->insert(newRpUnit->getUnitsName());
413            }
414
415        }
416    }
417
418    // place the new object into the dictionary
419   
420    // return a copy of the new object to user
421    return newRpUnit;
422}
423
424
425/************************************************************************
426 *                                                                     
427 * add relation rule                                                   
428 *                                                                     
429 ************************************************************************/
430RpUnits * RpUnits::define(  RpUnits* from,
431                            RpUnits* to,
432                            double (*convForwFxnPtr)(double),
433                            double (*convBackFxnPtr)(double))
434{
435    RpUnits* conv = new RpUnits(from,to,convForwFxnPtr,convBackFxnPtr,NULL,NULL);
436   
437    return conv;
438}
439
440RpUnits * RpUnits::define(  RpUnits* from,
441                            RpUnits* to,
442                            void* (*convForwFxnPtr)(void*, void*),
443                            void* convForwData,
444                            void* (*convBackFxnPtr)(void*, void*),
445                            void* convBackData)
446{
447    RpUnits* conv = new RpUnits(    from,
448                                    to,
449                                    convForwFxnPtr,
450                                    convForwData,
451                                    convBackFxnPtr,
452                                    convBackData,
453                                    NULL,
454                                    NULL);
455   
456    return conv;
457}
458
459/************************************************************************
460 *                                                                     
461 * report the units this object represents back to the user             
462 *                                                                     
463 * **********************************************************************/
464std::string RpUnits::getUnits()
465{
466    std::stringstream unitText;
467    unit* p = head;
468   
469    while (p) {
470        unitText << p->getUnits() ;
471        p = p->next;
472    }
473   
474    return (unitText.str());
475}
476
477/************************************************************************
478 *                                                                     
479 * report the units this object represents back to the user             
480 *                                                                     
481 * **********************************************************************/
482std::string RpUnits::getUnitsName()
483{
484    std::stringstream unitText;
485    unit* p = head;
486    double exponent;
487   
488    while (p) {
489
490        exponent = p->getExponent();
491
492        if (exponent == 1) {
493            unitText << p->getUnits();
494        }
495        else {
496            unitText << p->getUnits() << p->getExponent();
497        }
498
499        p = p->next;
500    }
501   
502    return (unitText.str());
503}
504
505/************************************************************************
506 *                                                                     
507 * report the exponent of the units of this object back to the user
508 *                                                                     
509 * **********************************************************************/
510double RpUnits::getExponent()
511{
512    return head->getExponent();
513}
514
515/************************************************************************
516 *                                                                     
517 *  report the basis of this object to the user                         
518 *                                                                     
519 * **********************************************************************/
520RpUnits * RpUnits::getBasis()
521{
522    // check if head exists?
523    return head->getBasis();
524}
525
526/************************************************************************
527 *                                                                     
528 *  convert the current unit to its basis units
529 * 
530 *  Return Codes
531 *      0) no error (could also mean or no prefix was found)
532 *          in some cases, this means the value is in its basis format
533 *      1) the prefix found does not have a built in factor associated.
534 *                                                                     
535 ************************************************************************/
536double RpUnits::makeBasis(double value, int* result)
537{
538
539    RpUnits* basis = getBasis();
540    double retVal = value;
541
542    if (result) {
543        *result = 0;
544    }
545
546    if (basis == NULL) {
547        // this unit is a basis
548        // do nothing
549       
550        if (result) {
551            *result = 1;
552        }
553    }
554    else {
555        retVal = convert(basis,value,result);
556    }
557
558    return retVal;
559}
560
561RpUnits& RpUnits::makeBasis(double* value, int* result)
562{
563    RpUnits* basis = getBasis();
564    double retVal = *value;
565    int convResult = 0;
566
567    if (basis == NULL) {
568        // this unit is a basis
569        // do nothing
570       
571        if (result) {
572            *result = 1;
573        }
574    }
575    else {
576        retVal = convert(basis,retVal,&convResult);
577    }
578
579    if ( (convResult == 1) ) {
580        *value = retVal;
581    }
582
583    if (result) {
584        *result = convResult;
585    }
586
587   
588
589    return *this;
590}
591
592/************************************************************************
593 *                                                                     
594 *  static int makeMetric(RpUnits * basis);                     
595 *  create the metric attachments for the given basis.
596 *  should only be used if this unit is of metric type                 
597 *                                                                     
598 * **********************************************************************/
599int RpUnits::makeMetric(RpUnits * basis) {
600
601    if (!basis) {
602        return 0;
603    }
604
605    std::string basisName = basis->getUnits();
606    std::string name;
607    std::string forw, back;
608   
609    name = "c" + basisName;
610    RpUnits * centi = RpUnits::define(name, basis);
611    RpUnits::define(centi, basis, centi2base, base2centi);
612
613    name = "m" + basisName;
614    RpUnits * milli = RpUnits::define(name, basis);
615    RpUnits::define(milli, basis, milli2base, base2milli);
616
617    name = "u" + basisName;
618    RpUnits * micro = RpUnits::define(name, basis);
619    RpUnits::define(micro, basis, micro2base, base2micro);
620
621    name = "n" + basisName;
622    RpUnits * nano  = RpUnits::define(name, basis);
623    RpUnits::define(nano, basis, nano2base, base2nano);
624   
625    name = "p" + basisName;
626    RpUnits * pico  = RpUnits::define(name, basis);
627    RpUnits::define(pico, basis, pico2base, base2pico);
628
629    name = "f" + basisName;
630    RpUnits * femto = RpUnits::define(name, basis);
631    RpUnits::define(femto, basis, femto2base, base2femto);
632
633    name = "a" + basisName;
634    RpUnits * atto  = RpUnits::define(name, basis);
635    RpUnits::define(atto, basis, atto2base, base2atto);
636
637    name = "k" + basisName;
638    RpUnits * kilo  = RpUnits::define(name, basis);
639    RpUnits::define(kilo, basis, kilo2base, base2kilo);
640
641    name = "M" + basisName;
642    RpUnits * mega  = RpUnits::define(name, basis);
643    RpUnits::define(mega, basis, mega2base, base2mega);
644
645    name = "G" + basisName;
646    RpUnits * giga  = RpUnits::define(name, basis);
647    RpUnits::define(giga, basis, giga2base, base2giga);
648
649    name = "T" + basisName;
650    RpUnits * tera  = RpUnits::define(name, basis);
651    RpUnits::define(tera, basis, tera2base, base2tera);
652
653    name = "P" + basisName;
654    RpUnits * peta  = RpUnits::define(name, basis);
655    RpUnits::define(peta, basis, peta2base, base2peta);
656   
657    return (1);
658}
659
660// convert function so people can just send in two strings and
661// we'll see if the units exists and do a conversion
662// strVal = RpUnits::convert("300K","C",1);
663std::string
664RpUnits::convert (  std::string val,
665                    std::string toUnitsName,
666                    int showUnits,
667                    int* result ) {
668
669    int valLen = 0;
670    RpUnits* toUnits = NULL;
671    RpUnits* fromUnits = NULL;
672    std::string tmpNumVal = "";
673    std::string fromUnitsName = "";
674    std::string convVal = "";
675    double numVal = 0;
676    int idx = 0;
677    int convResult = 0;
678
679
680    // set  default result flag/error code
681    if (result) {
682        *result = 0;
683    }
684   
685    toUnits = find(toUnitsName);   
686
687    // did we find the unit in the dictionary?
688    if (toUnits == NULL) {
689        // toUnitsName was not found in the dictionary
690        return val;
691    }
692   
693    valLen = val.length();
694
695    // search our string to see where the numeric part stops
696    // and the units part starts
697    // make sure not to stop searching if we encounter '.', '-', '+'
698    for (idx=0; idx < valLen; idx++) {
699        if ( !((val[idx] >= '0') && (val[idx] <= '9')) ) {
700            if ( (val[idx] != '.')&&(val[idx] != '-')&&(val[idx] != '+') ) {
701                break;
702            }
703        }
704    }
705
706    if ( (idx < valLen) && (idx > 0) ) {
707        tmpNumVal = val.substr(0,idx);
708        if (!tmpNumVal.empty()) {
709            numVal = atof(tmpNumVal.c_str());
710        }
711        else {
712            // tmpNumVal was empty string?
713            // set error code here and return error
714
715            if (result) {
716                *result = 1;
717            }
718        }
719        fromUnitsName = val.substr(idx, valLen-idx);
720    }
721    else {
722        // return error, no units or no number in the val string?
723        if (result) {
724            *result = 1;
725        }
726    }
727   
728    fromUnits = find(fromUnitsName);   
729
730    // did we find the unit in the dictionary?
731    if (fromUnits == NULL) {
732        // fromUnitsName was not found in the dictionary
733        return val;
734    }
735
736    convVal = fromUnits->convert(toUnits, numVal, showUnits, &convResult);
737   
738    if ( (result) && (*result == 0) ) {
739        *result = convResult;
740    }
741
742    return convVal;
743
744}
745
746std::string RpUnits::convert (   RpUnits* toUnits,
747                        double val,
748                        int showUnits,
749                        int* result )
750{
751    double retVal = convert(toUnits,val,result);
752    std::stringstream unitText;
753   
754
755    if (showUnits) {
756        unitText << retVal << toUnits->getUnits();
757    }
758    else {
759        unitText << retVal;
760    }
761
762    return (unitText.str());
763
764}
765
766// user function to convert a value to the provided RpUnits* toUnits
767// if it exists as a conversion from the basis
768// example
769//      cm.convert(meter,10)
770//      cm.convert(angstrum,100)
771double RpUnits::convert(RpUnits* toUnit, double val, int* result)
772{
773
774    // currently we convert this object to its basis and look for the
775    // connection to the toUnit object from the basis.
776
777    double value = val;
778    RpUnits* basis = this->getBasis();
779    RpUnits* fromUnit = this;
780    RpUnits* dictToUnit = NULL;
781    convEntry *p;
782    int my_result = 0;
783
784    // set *result to a default value
785    if (result) {
786        *result = 0;
787    }
788
789    // guard against converting to the units you are converting from...
790    // ie. meters->meters
791    if (this->getUnits() == toUnit->getUnits()) {
792        if (result) {
793            *result = 0;
794        }
795        return val;
796    }
797   
798    // convert unit to the basis
799    // makeBasis(&value);
800    // trying to avoid the recursive way of converting to the basis.
801    // need to rethink this.
802    //
803    if ( (basis) && (basis->getUnits() != toUnit->getUnits()) ) {
804        value = convert(basis,value,&my_result);
805        if (my_result) {
806            fromUnit = basis;
807        }   
808    }
809
810    // find the toUnit in our dictionary.
811
812    dictToUnit = find(toUnit->getUnits());
813
814    // did we find the unit in the dictionary?
815    if (dictToUnit == NULL) {
816        // toUnit was not found in the dictionary
817        return val;
818    }
819
820    // search through the conversion list to find
821    // the conversion to the toUnit.
822
823    if (basis) {
824        p = basis->convList;
825    }
826    else {
827        p = this->convList;
828    }
829
830    if (p == NULL) {
831        // there are no conversions
832        return val;
833    }
834
835    // loop through our conversion list looking for the correct conversion
836    do {
837       
838        if ( (p->conv->toPtr == dictToUnit) && (p->conv->fromPtr == fromUnit) ) {
839            // we found our conversion
840            // call the function pointer with value
841
842            value = p->conv->convForwFxnPtr(value);
843            if (result) {
844                *result = 0;
845            }
846            break;
847        }
848       
849        if ( (p->conv->toPtr == fromUnit) && (p->conv->fromPtr == dictToUnit) ) {
850            // we found our conversion
851            // call the function pointer with value
852
853            value = p->conv->convBackFxnPtr(value);
854            if (result) {
855                *result = 0;
856            }
857            break;
858        }
859
860        p = p->next;
861
862    } while (p != NULL);
863
864
865    if ( p == NULL) {
866        // we did not find the conversion
867        return val;
868    }
869
870    // we found the conversion.
871    // return the converted value.
872    return value;
873
874}
875
876
877void* RpUnits::convert(RpUnits* toUnit, void* val, int* result)
878{
879
880    // currently we convert this object to its basis and look for the
881    // connection ot the toUnit object from the basis.
882
883    void* value = val;
884    RpUnits* basis = this->getBasis();
885    RpUnits* fromUnit = this;
886    RpUnits* dictToUnit = NULL;
887    convEntry *p;
888    int my_result = 0;
889
890    // set *result to a default value
891    if (result) {
892        *result = 0;
893    }
894
895    // guard against converting to the units you are converting from...
896    // ie. meters->meters
897    if (this->getUnits() == toUnit->getUnits()) {
898        if (result) {
899            *result = 0;
900        }
901        return val;
902    }
903   
904    // convert unit to the basis
905    // makeBasis(&value);
906    // trying to avoid the recursive way of converting to the basis.
907    // need to rethink this.
908    //
909    if ( (basis) && (basis->getUnits() != toUnit->getUnits()) ) {
910        value = convert(basis,value,&my_result);
911        if (my_result) {
912            fromUnit = basis;
913        }   
914    }
915
916    // find the toUnit in our dictionary.
917
918    dictToUnit = find(toUnit->getUnits());
919
920    // did we find the unit in the dictionary?
921    if (dictToUnit == NULL) {
922        // toUnit was not found in the dictionary
923        return val;
924    }
925
926    // search through the conversion list to find
927    // the conversion to the toUnit.
928
929    if (basis) {
930        p = basis->convList;
931    }
932    else {
933        p = this->convList;
934    }
935
936    if (p == NULL) {
937        // there are no conversions
938        return val;
939    }
940
941    // loop through our conversion list looking for the correct conversion
942    do {
943       
944        if ( (p->conv->toPtr == dictToUnit) && (p->conv->fromPtr == fromUnit) ) {
945            // we found our conversion
946            // call the function pointer with value
947
948            value = p->conv->convForwFxnPtrVoid(p->conv->convForwData,value);
949
950            if (result) {
951                *result = 0;
952            }
953            break;
954        }
955       
956        if ( (p->conv->toPtr == fromUnit) && (p->conv->fromPtr == dictToUnit) ) {
957            // we found our conversion
958            // call the function pointer with value
959
960            value = p->conv->convBackFxnPtrVoid(p->conv->convBackData,value);
961            if (result) {
962                *result = 0;
963            }
964            break;
965        }
966
967        p = p->next;
968
969    } while (p != NULL);
970
971
972    if ( p == NULL) {
973        // we did not find the conversion
974        return val;
975    }
976
977    // we found the conversion.
978    // return the converted value.
979    return value;
980
981}
982
983void RpUnits::addUnit( const std::string& units,
984                       double&  exponent,
985                       RpUnits* basis
986                      )
987{
988    unit* p = NULL;
989
990    // check if the list was created previously. if not, start the list
991    if (head == 0) {
992        head = new unit(units,exponent,basis,NULL);
993        return;
994    }
995
996    // now add a new node at the beginning of the list:
997    p = new unit(units,exponent,basis,head);
998    head->prev = p;
999    head = p;
1000
1001}
1002
1003int RpUnits::insert(std::string key)
1004{
1005    int newRecord = 0;
1006    RpUnits* val = this;
1007    // dict pointer
1008    RpUnits::dict->set(key,val,&newRecord);
1009    return newRecord;
1010}
1011
1012
1013int RpUnits::pre_compare( std::string& units, RpUnits* basis )
1014{
1015
1016    // compare the incomming units with the previously defined units.
1017    // compareStr will hold a copy of the incomming string.
1018    // first look for the units as they are listed in the incomming variable
1019    // next look move searchStr toward the end of the string,
1020    // each time the pointer is moved, searchStr should be compared to all of
1021    // the previously defined units.
1022    // if searchStr is at the end of the string, then searchStr will be moved
1023    // back to the beginning of the string.
1024    // next it will traverse the string again, changing the case of the char
1025    // it points to and the resultant string will be compared again to all
1026    // of the previously defined units.
1027
1028    int compareSuccess = 0;
1029    // std::string::size_type units_len = units.length();
1030    // char * retVal = NULL;
1031    int retIndex = std::string::npos;
1032    // std::string compareStr = units;
1033    std::string searchStr = units;
1034    std::string dbText = "";
1035   
1036    // pass 1: look for exact match of units as they came into the function
1037    //          move searchStr pointer through string to find match.
1038    while ( ! compareSuccess &&
1039            (searchStr.length() > 0) ) {
1040
1041        // dict pointer
1042        if (dict->find(searchStr) == dict->getNullEntry()) {
1043            // the string was not found,
1044            // keep incrementing the pointer
1045            // searchStr (pass1)  does not match";
1046        }
1047        else {
1048            // compare was successful,
1049            // searchStr (pass1)  found a match
1050            compareSuccess++;
1051            break;
1052            // is it possible to create the unit here and
1053            // keep looking for units fro mthe provided string?
1054        }
1055
1056        searchStr.erase(0,1);
1057
1058        if (basis) {
1059            if ( (searchStr == basis->getUnits()) &&
1060                 (searchStr.length() == basis->getUnits().length()) )
1061            {
1062                break;
1063            }
1064        }
1065    }
1066
1067
1068    if (compareSuccess == 0) {
1069        // refresh our searchStr var.
1070        searchStr = units;
1071    }
1072
1073    // pass 2: capitolize the first letter of the search string and compare
1074    //          for each letter in the string
1075    while ( ! compareSuccess &&
1076            (searchStr.length() > 0) ) {
1077
1078        if (islower((int)(searchStr[0]))) {
1079            searchStr[0] = (char) toupper((int)(searchStr[0]));
1080        }
1081
1082        // dict pointer
1083        if (dict->find(searchStr) == dict->getNullEntry()) {
1084            // the string was not found,
1085            // keep incrementing the pointer
1086            // searchStr (pass2)  does not match
1087        }
1088        else {
1089            // compare was successful,
1090            // searchStr (pass2)  found a match
1091            compareSuccess++;
1092            break;
1093        }
1094        searchStr.erase(0,1);
1095
1096        // check to see if we are at the basis.
1097        if (basis) {
1098            if ( (searchStr == basis->getUnits()) &&
1099                 (searchStr.length() == basis->getUnits().length()) )
1100            {
1101                break;
1102            }
1103           
1104        }
1105
1106    }
1107
1108
1109
1110    // if we found a match, find the first occurance of the string which
1111    // was used to get the match, in our original units string.
1112    // this gets dicey for capitolizations.
1113    if ( compareSuccess ) {
1114        // need to think about if we want to search from the start
1115        // or the end of the string (find or rfind)
1116        // i think its the start because in this fxn (above)
1117        // we start at the beginning of the string and work
1118        // our way to the end. so if there is a second match at the
1119        // end, we would have only seen the first match.
1120        retIndex = units.find(searchStr);
1121    }
1122
1123    return retIndex;
1124
1125}
1126
1127
1128void RpUnits::connectConversion(RpUnits* myRpUnit)
1129{
1130    convEntry* p = myRpUnit->convList;
1131
1132    if (p == NULL) {
1133        myRpUnit->convList = new convEntry (this->conv,NULL,NULL);
1134    }
1135    else {
1136        while (p->next != NULL) {
1137            p = p->next;
1138        }
1139
1140        p->next = new convEntry (this->conv,p,NULL);
1141    }
1142
1143}
1144
1145// return codes: 0 success, anything else is error
1146int
1147RpUnits::addPresets (std::string group) {
1148    int retVal = -1;
1149    if (group.compare("all") == 0) {
1150        retVal = addPresetAll();
1151    }
1152    else if (group.compare("energy") == 0) {
1153        retVal = addPresetEnergy();
1154    }
1155    else if (group.compare("length") == 0) {
1156        retVal = addPresetLength();
1157    }
1158    else if (group.compare("temp") == 0) {
1159        retVal = addPresetTemp();
1160    }
1161    else if (group.compare("time") == 0) {
1162        retVal = addPresetTime();
1163    }
1164   
1165    return retVal;
1166}
1167   
1168// return codes: 0 success, anything else is error
1169int
1170RpUnits::addPresetAll () {
1171
1172    int result = 0;
1173
1174    result += addPresetTime();
1175    result += addPresetTemp();
1176    result += addPresetLength();
1177    result += addPresetEnergy();
1178
1179    return 0;
1180}
1181
1182// return codes: 0 success, anything else is error
1183int
1184RpUnits::addPresetTime () {
1185
1186    RpUnits* seconds    = RpUnits::define("s", NULL);
1187   
1188    RpUnits::makeMetric(seconds);
1189   
1190    // add time definitions
1191
1192    return 0;
1193}
1194
1195// return codes: 0 success, anything else is error
1196int
1197RpUnits::addPresetTemp () {
1198
1199    RpUnits* fahrenheit = RpUnits::define("F", NULL);
1200    RpUnits* celcius    = RpUnits::define("C", NULL);
1201    RpUnits* kelvin     = RpUnits::define("K", NULL);
1202    RpUnits* rankine    = RpUnits::define("R", NULL);
1203   
1204    // add temperature definitions
1205    RpUnits::define(fahrenheit, celcius, fahrenheit2centigrade, centigrade2fahrenheit);
1206    RpUnits::define(celcius, kelvin, centigrade2kelvin, kelvin2centigrade);
1207    RpUnits::define(fahrenheit, kelvin, fahrenheit2kelvin, kelvin2fahrenheit);
1208    RpUnits::define(rankine, kelvin, rankine2kelvin, kelvin2rankine);
1209
1210    return 0;
1211}
1212
1213// return codes: 0 success, anything else is error
1214int
1215RpUnits::addPresetLength () {
1216
1217    RpUnits* meters     = RpUnits::define("m", NULL);
1218    RpUnits* angstrom   = RpUnits::define("A", NULL);
1219    RpUnits* inch       = RpUnits::define("in", NULL);
1220    RpUnits* feet       = RpUnits::define("ft", NULL);
1221    RpUnits* yard       = RpUnits::define("yd", NULL);
1222   
1223    RpUnits::makeMetric(meters);
1224
1225    // add length definitions
1226    RpUnits::define(angstrom, meters, angstrom2meter, meter2angstrom);
1227    RpUnits::define(inch, meters, inch2meter, meter2inch);
1228    RpUnits::define(feet, meters, feet2meter, meter2feet);
1229    RpUnits::define(yard, meters, yard2meter, meter2yard);
1230
1231    return 0;
1232}
1233
1234// return codes: 0 success, anything else is error
1235int
1236RpUnits::addPresetEnergy () {
1237
1238    RpUnits* volt       = RpUnits::define("V", NULL);
1239    RpUnits* electrVolt = RpUnits::define("eV", NULL);
1240    RpUnits* joule      = RpUnits::define("J", NULL);
1241   
1242    RpUnits::makeMetric(volt);
1243
1244    // add energy definitions
1245    RpUnits::define(electrVolt,joule,electronVolt2joule,joule2electronVolt);
1246
1247    return 0;
1248}
1249
1250// -------------------------------------------------------------------- //
1251
Note: See TracBrowser for help on using the repository browser.