1 |
#include <iostream> |
2 |
#include <stdexcept> |
3 |
#include <sstream> |
4 |
using namespace std; |
5 |
|
6 |
#include "units.h" |
7 |
#include "dimensions.h" |
8 |
|
9 |
extern "C"{ |
10 |
#include <ascend/compiler/cmpfunc.h> |
11 |
} |
12 |
|
13 |
UnitsM::UnitsM(){ |
14 |
int errcode; |
15 |
long unsigned pos; |
16 |
u = FindOrDefineUnits("?",&pos,&errcode); |
17 |
if(errcode){ |
18 |
// naughty to throw exceptions during ctor. |
19 |
throw runtime_error("Can't create wildcard (?)"); |
20 |
} |
21 |
} |
22 |
|
23 |
UnitsM::UnitsM(const struct Units *u) : u(u){ |
24 |
// nothing else |
25 |
} |
26 |
|
27 |
/* |
28 |
exception |
29 |
UnitsM::getException(const int &errorcode, const char *ustr, const int &pos){ |
30 |
const char *s; |
31 |
switch(errorcode){ |
32 |
case 0: return runtime_error("This error should not have been thrown!"); |
33 |
case 1: s = "Undefined unit used in string"; break; |
34 |
case 2: s = "Unbalanced parenthesis"; break; |
35 |
case 3: s = "Illegal character"; break; |
36 |
case 4: s = "Illegal real value"; break; |
37 |
case 5: s = "Oversized identifier or real"; break; |
38 |
case 6: s = "Missing operator in real followed by identifier"; break; |
39 |
case 7: s = "Term missing after * or / or ("; break; |
40 |
case 8: s = "Term missing before * or /"; break; |
41 |
case 9: s = "Too many closing parentheses"; break; |
42 |
case 10: s = "Bad fraction exponent"; break; |
43 |
case 11: raise runtime_error("Invalid UnitsM::getException errorcode = 11"); |
44 |
} |
45 |
exception e = runtime_error(s); |
46 |
CONSOLE_DEBUG("Units error: %s",s); |
47 |
CONSOLE_DEBUG("%s",ustr); |
48 |
char indic[strlen(ustr)+1]; |
49 |
for(int i=0; i<pos; ++i){ |
50 |
indic[i] = ' '; |
51 |
} |
52 |
indic[pos] = '^'; indic[pos+1] = '\0'; |
53 |
CONSOLE_DEBUG(indic); |
54 |
return e; |
55 |
} |
56 |
*/ |
57 |
|
58 |
/** |
59 |
Parse a units string, create a new UnitsM object from the string. |
60 |
|
61 |
UnitsM doesn't allocate any storage so it's OK to throw |
62 |
an exception in a ctor |
63 |
*/ |
64 |
UnitsM::UnitsM(const char *units){ |
65 |
const struct Units *u = LookupUnits(units); |
66 |
if(u==NULL){ |
67 |
//cerr << "About to create new units '" << units << "'" << endl; |
68 |
long unsigned pos; |
69 |
int err; |
70 |
u = FindOrDefineUnits(units, &pos, &err); |
71 |
if(u==NULL){ |
72 |
char **errv = UnitsExplainError(units, err, pos); |
73 |
stringstream ss; |
74 |
ss << "Error parsing units: " << errv[0] << endl << errv[1] << endl << errv[2]; |
75 |
throw runtime_error(ss.str()); |
76 |
} |
77 |
}/*else{ |
78 |
cerr << "Units '" << units << "' were found in lookup" << endl; |
79 |
}*/ |
80 |
this->u = u; |
81 |
} |
82 |
|
83 |
const struct Units * |
84 |
UnitsM::getInternalType() const{ |
85 |
return u; |
86 |
} |
87 |
|
88 |
const SymChar |
89 |
UnitsM::getName() const{ |
90 |
return SymChar(SCP( UnitsDescription(u) )); |
91 |
} |
92 |
|
93 |
const Dimensions |
94 |
UnitsM::getDimensions() const{ |
95 |
const dim_type *d = UnitsDimensions(u); |
96 |
return Dimensions(d); |
97 |
} |
98 |
|
99 |
const double |
100 |
UnitsM::getConversion() const{ |
101 |
return UnitsConvFactor(u); |
102 |
} |
103 |
|
104 |
const bool |
105 |
UnitsM::operator==(const UnitsM &other) const{ |
106 |
// because of the FindOrDefineUnits thing, equivalent units will always have the same pointer |
107 |
return 0==CmpRealPtrs(getInternalType(),other.getInternalType()); |
108 |
} |
109 |
|