00001
00002
00003 #include <string>
00004 #include "xmlUtil/Arith.h"
00005 #include "xml/Dom.h"
00006 #include <dom/DOM_Document.hpp>
00007
00008 namespace xmlUtil {
00009
00010 inline DOM_Element firstEltChild(DOM_Element& elt) {
00011 DOM_Node curNode = elt.getFirstChild();
00012 if (curNode == DOM_Node()) return DOM_Element();
00013 while (curNode.getNodeType() != DOM_Node::ELEMENT_NODE) {
00014 curNode = curNode.getNextSibling();
00015 if (curNode == DOM_Node()) return DOM_Element();
00016 }
00017 return DOM_Element(static_cast<DOM_Element &>(curNode));
00018 }
00019
00020 inline DOM_Element nextEltSibling(DOM_Element& elt) {
00021 DOM_Node curNode = elt.getNextSibling();
00022 if (curNode == DOM_Node()) return DOM_Element();
00023 while (curNode.getNodeType() != DOM_Node::ELEMENT_NODE) {
00024 curNode = curNode.getNextSibling();
00025 if (curNode == DOM_Node()) return DOM_Element();
00026 }
00027 return DOM_Element(static_cast<DOM_Element &>(curNode));
00028 }
00029
00030
00031
00032
00033
00034 Arith::ptrDOMString * Arith::typeNames;
00035 Arith::ptrDOMString Arith::valString;
00036 Arith::ptrDOMString Arith::refToString;
00037 Arith::ptrDOMString Arith::constString;
00038 Arith::ptrDOMString Arith::referString;
00039 Arith::ptrDOMString Arith::addString;
00040 Arith::ptrDOMString Arith::minusString;
00041 Arith::ptrDOMString Arith::uminusString;
00042 Arith::ptrDOMString Arith::mulString;
00043 Arith::ptrDOMString Arith::quoString;
00044 Arith::ptrDOMString Arith::maxString;
00045 Arith::ptrDOMString Arith::notesString;
00046 Arith::ptrDOMString Arith::lengthString;
00047 Arith::ptrDOMString Arith::cmString;
00048 Arith::ptrDOMString Arith::mString;
00049
00050 Arith::Arith(const DOM_Element elt) {
00051 int i = 0;
00052 bool notFound = true;
00053 DOMString tagName = elt.getTagName();
00054 m_elt = elt;
00055 m_evaluated = false;
00056 m_tag = -1;
00057 if (typeNames == 0) init();
00058
00059 while ((notFound) && (i < ETAG_n)) {
00060 DOMString *p = typeNames[i];
00061 DOMString tmp = DOMString(*p);
00062 if (tagName.equals(tmp) ) {
00063 m_tag = i;
00064 notFound = false;
00065 }
00066 i++;
00067 }
00068 }
00069
00070 double Arith::evaluate() {
00071 if (!m_evaluated) {
00072 DOM_Element curElt;
00073 switch(m_tag) {
00074 case ETAG_const: {
00075 DOMString val = m_elt.getAttribute(*valString);
00076 if (!(val.equals(DOMString()) ) ) {
00077
00078 m_number = atof(xml::Dom::transToChar(val));
00079 m_number *= getUnitsScale(m_elt);
00080 }
00081 else {
00082
00083
00084 curElt = firstEltChild(m_elt);
00085 if (curElt.getTagName().equals(*notesString)) {
00086 DOM_Node next = curElt.getNextSibling();
00087 curElt = static_cast <DOM_Element &>(next);
00088 }
00089 m_number = Arith(curElt).evaluate();
00090 }
00091 break;
00092 }
00093 case ETAG_refer: {
00094
00095 DOMString ref = m_elt.getAttribute(*refToString);
00096 curElt = (m_elt.getOwnerDocument()).getElementById(ref);
00097 if (curElt.getTagName().equals("prim")) {
00098 m_number =
00099 atof(xml::Dom::transToChar(curElt.getAttribute(*valString)));
00100 m_number *= getUnitsScale(curElt);
00101 }
00102 else {
00103 m_number = Arith(curElt).evaluate();
00104 }
00105 break;
00106 }
00107 case ETAG_uminus: {
00108
00109 curElt = firstEltChild(m_elt);
00110 m_number = -(Arith(curElt).evaluate());
00111 break;
00112 }
00113
00114 case ETAG_add: {
00115 m_number = add();
00116 break;
00117 }
00118
00119 case ETAG_mul: {
00120 m_number = mul();
00121 break;
00122 }
00123
00124 case ETAG_minus: {
00125 m_number = minus();
00126 break;
00127 }
00128 case ETAG_quo: {
00129 m_number = quo();
00130 break;
00131 }
00132
00133 case ETAG_max: {
00134 m_number = myMax();
00135 break;
00136 }
00137 default: {
00138 return 0;
00139 }
00140 }
00141 m_evaluated = true;
00142 }
00143 return m_number;
00144 }
00145
00146 double Arith::add() {
00147 double ans = 0.0;
00148 DOM_Element elt = firstEltChild(m_elt);
00149 ans += Arith(elt).evaluate();
00150 elt = nextEltSibling(elt);
00151 while (elt != DOM_Element()) {
00152 ans += Arith(elt).evaluate();
00153 elt = nextEltSibling(elt);
00154 }
00155 return ans;
00156 }
00157
00158 double Arith::mul() {
00159 double ans = 1.0;
00160 DOM_Element elt = firstEltChild(m_elt);
00161 ans *= Arith(elt).evaluate();
00162 elt = nextEltSibling(elt);
00163 while (elt != DOM_Element()) {
00164 ans *= Arith(elt).evaluate();
00165 elt = nextEltSibling(elt);
00166 }
00167 return ans;
00168 }
00169
00170 double Arith::myMax() {
00171 DOM_Element elt = firstEltChild(m_elt);
00172 double ans = Arith(elt).evaluate();
00173 elt = nextEltSibling(elt);
00174 while (elt != DOM_Element()) {
00175 double newAns = Arith(elt).evaluate();
00176 if (newAns > ans) ans = newAns;
00177 elt = nextEltSibling(elt);
00178 }
00179 return ans;
00180 }
00181 double Arith::minus() {
00182 double ans;
00183 DOM_Element elt = firstEltChild(m_elt);
00184 ans = Arith(elt).evaluate();
00185 elt = nextEltSibling(elt);
00186 ans -= Arith(elt).evaluate();
00187 return ans;
00188 }
00189
00190 double Arith::quo() {
00191 double ans;
00192 double divisor;
00193 DOM_Element elt = firstEltChild(m_elt);
00194 ans = Arith(elt).evaluate();
00195 elt = nextEltSibling(elt);
00196 divisor = Arith(elt).evaluate();
00197 ans /= divisor;
00198 return ans;
00199 }
00200
00201
00202 void Arith::saveValue() {
00203
00204 if (m_tag != ETAG_const) return;
00205
00206 if (!m_evaluated) evaluate();
00207
00208
00209
00210 if (DOMString("int").equals(m_elt.getAttribute("type"))) {
00211
00212
00213
00214 long int intValue = m_number;
00215 double intified = intValue;
00216 if (intified != m_number) {
00217 double fixup = 0.5;
00218 if (m_number < 0.0) fixup = -fixup;
00219 long int intValue = (m_number + fixup);
00220 m_number = intValue;
00221 }
00222 }
00223
00224
00225
00226
00227
00228 xml::Dom::addAttribute(m_elt, *valString, m_number);
00229 xml::Dom::addAttribute(m_elt, std::string("unitLength"),
00230 std::string("mm"));
00231 }
00232
00233 double Arith::getUnitsScale(const DOM_Element& elt) {
00234 if (!(elt.getAttribute("uType")).equals(*lengthString) ) {
00235 return 1.0;
00236 }
00237
00238 DOMString unitLength = elt.getAttribute("unitLength");
00239 if (unitLength.equals(*cmString)) return 10.0;
00240 else if (unitLength.equals(*mString)) return 1000.0;
00241 else return 1.0;
00242 }
00243
00244 void Arith::init() {
00245 constString = new DOMString("const");
00246 referString = new DOMString("refer");
00247 addString = new DOMString("add");
00248 minusString = new DOMString("minus");
00249 mulString = new DOMString("mul");
00250 quoString = new DOMString("quo");
00251 uminusString = new DOMString("uminus");
00252 maxString = new DOMString("max");
00253 notesString = new DOMString("notes");
00254 lengthString = new DOMString("length");
00255 cmString = new DOMString("cm");
00256 mString = new DOMString("m");
00257
00258 valString = new DOMString("value");
00259 refToString = new DOMString("refTo");
00260
00261
00262 typeNames = new ptrDOMString[ETAG_n];
00263 typeNames[ETAG_const] = constString;
00264 typeNames[ETAG_refer] = referString;
00265 typeNames[ETAG_add] = addString;
00266 typeNames[ETAG_minus] = minusString;
00267 typeNames[ETAG_mul] = mulString;
00268 typeNames[ETAG_quo] = quoString;
00269 typeNames[ETAG_uminus] = uminusString;
00270 typeNames[ETAG_max] = maxString;
00271 }
00272 }