You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

517 lines
13KB

  1. /*
  2. XMLwrapper.C - XML wrapper
  3. Copyright (C) 2003-2009 Nasca Octavian Paul
  4. Author: Nasca Octavian Paul
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of version 2 of the GNU General Public License
  7. as published by the Free Software Foundation.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License (version 2 or later) for more details.
  12. You should have received a copy of the GNU General Public License (version 2)
  13. along with this program; if not, write to the Free Software Foundation,
  14. Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. #include "XMLwrapper.h"
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <zlib.h>
  20. //#include "Util.h"
  21. int xml_k=0;
  22. char tabs[STACKSIZE+2];
  23. const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where){
  24. const char *name=node->value.element.name;
  25. if ((where==MXML_WS_BEFORE_OPEN)&&(!strcmp(name,"?xml"))) return(NULL);
  26. if ((where==MXML_WS_BEFORE_CLOSE)&&(!strcmp(name,"string"))) return(NULL);
  27. if ((where==MXML_WS_BEFORE_OPEN)||(where==MXML_WS_BEFORE_CLOSE)) {
  28. /* const char *tmp=node->value.element.name;
  29. if (tmp!=NULL) {
  30. if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) {
  31. printf("%s ",tmp);
  32. if (where==MXML_WS_BEFORE_OPEN) xml_k++;
  33. if (where==MXML_WS_BEFORE_CLOSE) xml_k--;
  34. if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1;
  35. if (xml_k<0) xml_k=0;
  36. printf("%d\n",xml_k);
  37. printf("\n");
  38. };
  39. };
  40. int i=0;
  41. for (i=1;i<xml_k;i++) tabs[i]='\t';
  42. tabs[0]='\n';tabs[i+1]='\0';
  43. if (where==MXML_WS_BEFORE_OPEN) return(tabs);
  44. else return("\n");
  45. */
  46. return("\n");
  47. };
  48. return(0);
  49. };
  50. XMLwrapper::XMLwrapper(){
  51. ZERO(&parentstack,(int)sizeof(parentstack));
  52. ZERO(&values,(int)sizeof(values));
  53. minimal=true;
  54. stackpos=0;
  55. tree=mxmlNewElement(MXML_NO_PARENT,"?xml version=\"1.0\" encoding=\"UTF-8\"?");
  56. /* for mxml 2.1 (and older)
  57. tree=mxmlNewElement(MXML_NO_PARENT,"?xml");
  58. mxmlElementSetAttr(tree,"version","1.0");
  59. mxmlElementSetAttr(tree,"encoding","UTF-8");
  60. */
  61. mxml_node_t *doctype=mxmlNewElement(tree,"!DOCTYPE");
  62. mxmlElementSetAttr(doctype,"paulstretch-data",NULL);
  63. node=root=mxmlNewElement(tree,"paulstretch-data");
  64. mxmlElementSetAttr(root,"version-major","1");
  65. mxmlElementSetAttr(root,"version-minor","0");
  66. mxmlElementSetAttr(root,"paulstretch-author","Nasca Octavian Paul");
  67. //make the empty branch that will contain the information parameters
  68. info=addparams0("INFORMATION");
  69. //save specifications
  70. beginbranch("BASE_PARAMETERS");
  71. endbranch();
  72. };
  73. XMLwrapper::~XMLwrapper(){
  74. if (tree!=NULL) mxmlDelete(tree);
  75. };
  76. bool XMLwrapper::checkfileinformation(char *filename){
  77. stackpos=0;
  78. ZERO(&parentstack,(int)sizeof(parentstack));
  79. if (tree!=NULL) mxmlDelete(tree);tree=NULL;
  80. char *xmldata=doloadfile(filename);
  81. if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed
  82. char *start=strstr(xmldata,"<INFORMATION>");
  83. char *end=strstr(xmldata,"</INFORMATION>");
  84. if ((start==NULL)||(end==NULL)||(start>end)) {
  85. delete []xmldata;
  86. return(false);
  87. };
  88. end+=strlen("</INFORMATION>");
  89. end[0]='\0';
  90. tree=mxmlNewElement(MXML_NO_PARENT,"?xml");
  91. node=root=mxmlLoadString(tree,xmldata,MXML_OPAQUE_CALLBACK);
  92. if (root==NULL) {
  93. delete []xmldata;
  94. mxmlDelete(tree);
  95. node=root=tree=NULL;
  96. return(false);
  97. };
  98. root=mxmlFindElement(tree,tree,"INFORMATION",NULL,NULL,MXML_DESCEND);
  99. push(root);
  100. if (root==NULL){
  101. delete []xmldata;
  102. mxmlDelete(tree);
  103. node=root=tree=NULL;
  104. return(false);
  105. };
  106. exitbranch();
  107. if (tree!=NULL) mxmlDelete(tree);
  108. delete []xmldata;
  109. node=root=tree=NULL;
  110. return(true);
  111. };
  112. /* SAVE XML members */
  113. int XMLwrapper::saveXMLfile(const char *filename){
  114. char *xmldata=getXMLdata();
  115. if (xmldata==NULL) return(-2);
  116. int compression=3;
  117. int fnsize=strlen(filename)+100;
  118. char *filenamenew=new char [fnsize];
  119. snprintf(filenamenew,fnsize,"%s",filename);
  120. int result=dosavefile(filenamenew,compression,xmldata);
  121. delete []filenamenew;
  122. delete []xmldata;
  123. return(result);
  124. };
  125. char *XMLwrapper::getXMLdata(){
  126. xml_k=0;
  127. ZERO(tabs,STACKSIZE+2);
  128. mxml_node_t *oldnode=node;
  129. node=info;
  130. //Info storing
  131. node=oldnode;
  132. char *xmldata=mxmlSaveAllocString(tree,XMLwrapper_whitespace_callback);
  133. return(xmldata);
  134. };
  135. int XMLwrapper::dosavefile(char *filename,int compression,char *xmldata){
  136. if (compression==0){
  137. FILE *file;
  138. file=fopen(filename,"w");
  139. if (file==NULL) return(-1);
  140. fputs(xmldata,file);
  141. fclose(file);
  142. } else {
  143. if (compression>9) compression=9;
  144. if (compression<1) compression=1;
  145. char options[10];
  146. snprintf(options,10,"wb%d",compression);
  147. gzFile gzfile;
  148. gzfile=gzopen(filename,options);
  149. if (gzfile==NULL) return(-1);
  150. gzputs(gzfile,xmldata);
  151. gzclose(gzfile);
  152. };
  153. return(0);
  154. };
  155. void XMLwrapper::addpar(const char *name,int val){
  156. addparams2("par","name",name,"value",int2str(val));
  157. };
  158. void XMLwrapper::addparreal(const char *name,REALTYPE val){
  159. addparams2("par_real","name",name,"value",real2str(val));
  160. };
  161. void XMLwrapper::addparbool(const char *name,int val){
  162. if (val!=0) addparams2("par_bool","name",name,"value","yes");
  163. else addparams2("par_bool","name",name,"value","no");
  164. };
  165. void XMLwrapper::addparstr(const char *name,const char *val){
  166. mxml_node_t *element=mxmlNewElement(node,"string");
  167. mxmlElementSetAttr(element,"name",name);
  168. mxmlNewText(element,0,val);
  169. };
  170. void XMLwrapper::beginbranch(const char *name){
  171. push(node);
  172. node=addparams0(name);
  173. };
  174. void XMLwrapper::beginbranch(const char *name,int id){
  175. push(node);
  176. node=addparams1(name,"id",int2str(id));
  177. };
  178. void XMLwrapper::endbranch(){
  179. node=pop();
  180. };
  181. /* LOAD XML members */
  182. int XMLwrapper::loadXMLfile(const char *filename){
  183. if (tree!=NULL) mxmlDelete(tree);
  184. tree=NULL;
  185. ZERO(&parentstack,(int)sizeof(parentstack));
  186. ZERO(&values,(int)sizeof(values));
  187. stackpos=0;
  188. char *xmldata=doloadfile(filename);
  189. if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed
  190. printf("%s\n",xmldata);
  191. root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK);
  192. delete []xmldata;
  193. if (tree==NULL) return(-2);//this is not XML
  194. node=root=mxmlFindElement(tree,tree,"paulstretch-data",NULL,NULL,MXML_DESCEND);
  195. if (root==NULL) return(-3);//the XML doesnt embbed required data
  196. push(root);
  197. values.xml_version.major=str2int(mxmlElementGetAttr(root,"version-major"));
  198. values.xml_version.minor=str2int(mxmlElementGetAttr(root,"version-minor"));
  199. return(0);
  200. };
  201. char *XMLwrapper::doloadfile(const char *filename){
  202. char *xmldata=NULL;
  203. int filesize=-1;
  204. //try get filesize as gzip data (first)
  205. gzFile gzfile=gzopen(filename,"rb");
  206. if (gzfile!=NULL){//this is a gzip file
  207. // first check it's size
  208. int bufsize=1024;
  209. char* tmpbuf=new char[bufsize];
  210. filesize=0;
  211. while(!gzeof(gzfile)) {
  212. filesize+=gzread(gzfile,tmpbuf,bufsize);
  213. };
  214. delete []tmpbuf;
  215. //rewind the file and load the data
  216. xmldata=new char[filesize+1];
  217. ZERO(xmldata,filesize+1);
  218. gzrewind(gzfile);
  219. gzread(gzfile,xmldata,filesize);
  220. gzclose(gzfile);
  221. return (xmldata);
  222. } else {//this is not a gzip file
  223. notgzip:
  224. FILE *file=fopen(filename,"rb");
  225. if (file==NULL) return(NULL);
  226. fseek(file,0,SEEK_END);
  227. filesize=ftell(file);
  228. xmldata=new char [filesize+1];
  229. ZERO(xmldata,filesize+1);
  230. rewind(file);
  231. int tmp=fread(xmldata,filesize,1,file);
  232. fclose(file);
  233. return(xmldata);
  234. };
  235. };
  236. bool XMLwrapper::putXMLdata(char *xmldata){
  237. if (tree!=NULL) mxmlDelete(tree);
  238. tree=NULL;
  239. ZERO(&parentstack,(int)sizeof(parentstack));
  240. ZERO(&values,(int)sizeof(values));
  241. stackpos=0;
  242. if (xmldata==NULL) return (false);
  243. root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK);
  244. if (tree==NULL) return(false);
  245. node=root=mxmlFindElement(tree,tree,"paulstretch-data",NULL,NULL,MXML_DESCEND);
  246. if (root==NULL) return (false);;
  247. push(root);
  248. return(true);
  249. };
  250. int XMLwrapper::enterbranch(const char *name){
  251. node=mxmlFindElement(peek(),peek(),name,NULL,NULL,MXML_DESCEND_FIRST);
  252. if (node==NULL) return(0);
  253. push(node);
  254. return(1);
  255. };
  256. int XMLwrapper::enterbranch(const char *name,int id){
  257. snprintf(tmpstr,TMPSTR_SIZE,"%d",id);
  258. node=mxmlFindElement(peek(),peek(),name,"id",tmpstr,MXML_DESCEND_FIRST);
  259. if (node==NULL) return(0);
  260. push(node);
  261. return(1);
  262. };
  263. void XMLwrapper::exitbranch(){
  264. pop();
  265. };
  266. int XMLwrapper::getbranchid(int min, int max){
  267. int id=str2int(mxmlElementGetAttr(node,"id"));
  268. if ((min==0)&&(max==0)) return(id);
  269. if (id<min) id=min;
  270. else if (id>max) id=max;
  271. return(id);
  272. };
  273. int XMLwrapper::getpar(const char *name,int defaultpar,int min,int max){
  274. node=mxmlFindElement(peek(),peek(),"par","name",name,MXML_DESCEND_FIRST);
  275. if (node==NULL) return(defaultpar);
  276. const char *strval=mxmlElementGetAttr(node,"value");
  277. if (strval==NULL) return(defaultpar);
  278. int val=str2int(strval);
  279. if (val<min) val=min;
  280. else if (val>max) val=max;
  281. return(val);
  282. };
  283. int XMLwrapper::getpar127(const char *name,int defaultpar){
  284. return(getpar(name,defaultpar,0,127));
  285. };
  286. int XMLwrapper::getparbool(const char *name,int defaultpar){
  287. node=mxmlFindElement(peek(),peek(),"par_bool","name",name,MXML_DESCEND_FIRST);
  288. if (node==NULL) return(defaultpar);
  289. const char *strval=mxmlElementGetAttr(node,"value");
  290. if (strval==NULL) return(defaultpar);
  291. if ((strval[0]=='Y')||(strval[0]=='y')) return(1);
  292. else return(0);
  293. };
  294. void XMLwrapper::getparstr(const char *name,char *par,int maxstrlen){
  295. ZERO(par,maxstrlen);
  296. node=mxmlFindElement(peek(),peek(),"string","name",name,MXML_DESCEND_FIRST);
  297. if (node==NULL) return;
  298. if (node->child==NULL) return;
  299. if (node->child->type!=MXML_OPAQUE) return;
  300. snprintf(par,maxstrlen,"%s",node->child->value.element.name);
  301. };
  302. REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar){
  303. node=mxmlFindElement(peek(),peek(),"par_real","name",name,MXML_DESCEND_FIRST);
  304. if (node==NULL) return(defaultpar);
  305. const char *strval=mxmlElementGetAttr(node,"value");
  306. if (strval==NULL) return(defaultpar);
  307. return(str2real(strval));
  308. };
  309. REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max){
  310. REALTYPE result=getparreal(name,defaultpar);
  311. if (result<min) result=min;
  312. else if (result>max) result=max;
  313. return(result);
  314. };
  315. /** Private members **/
  316. char *XMLwrapper::int2str(int x){
  317. snprintf(tmpstr,TMPSTR_SIZE,"%d",x);
  318. return(tmpstr);
  319. };
  320. char *XMLwrapper::real2str(REALTYPE x){
  321. snprintf(tmpstr,TMPSTR_SIZE,"%g",x);
  322. return(tmpstr);
  323. };
  324. int XMLwrapper::str2int(const char *str){
  325. if (str==NULL) return(0);
  326. int result=strtol(str,NULL,10);
  327. return(result);
  328. };
  329. REALTYPE XMLwrapper::str2real(const char *str){
  330. if (str==NULL) return(0.0);
  331. REALTYPE result=strtod(str,NULL);
  332. return(result);
  333. };
  334. mxml_node_t *XMLwrapper::addparams0(const char *name){
  335. mxml_node_t *element=mxmlNewElement(node,name);
  336. return(element);
  337. };
  338. mxml_node_t *XMLwrapper::addparams1(const char *name,const char *par1,const char *val1){
  339. mxml_node_t *element=mxmlNewElement(node,name);
  340. mxmlElementSetAttr(element,par1,val1);
  341. return(element);
  342. };
  343. mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2){
  344. mxml_node_t *element=mxmlNewElement(node,name);
  345. mxmlElementSetAttr(element,par1,val1);
  346. mxmlElementSetAttr(element,par2,val2);
  347. return(element);
  348. };
  349. void XMLwrapper::push(mxml_node_t *node){
  350. if (stackpos>=STACKSIZE-1) {
  351. printf("BUG!: XMLwrapper::push() - full parentstack\n");
  352. return;
  353. };
  354. stackpos++;
  355. parentstack[stackpos]=node;
  356. // printf("push %d - %s\n",stackpos,node->value.element.name);
  357. };
  358. mxml_node_t *XMLwrapper::pop(){
  359. if (stackpos<=0) {
  360. printf("BUG!: XMLwrapper::pop() - empty parentstack\n");
  361. return (root);
  362. };
  363. mxml_node_t *node=parentstack[stackpos];
  364. parentstack[stackpos]=NULL;
  365. // printf("pop %d - %s\n",stackpos,node->value.element.name);
  366. stackpos--;
  367. return(node);
  368. };
  369. mxml_node_t *XMLwrapper::peek(){
  370. if (stackpos<=0) {
  371. printf("BUG!: XMLwrapper::peek() - empty parentstack\n");
  372. return (root);
  373. };
  374. return(parentstack[stackpos]);
  375. };