00001 // ----------------------------------------------------------------------^ 00002 // Copyright (C) 2004, 2005, 2006, 2007 Giorgio Calderone <gcalderone@ifc.inaf.it> 00003 // 00004 // This file is part of VOTPP. 00005 // 00006 // VOTPP is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation; either version 2 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // VOTPP is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with VOTPP; if not, write to the Free Software 00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 // 00020 // ----------------------------------------------------------------------$ 00021 00022 #include <assert.h> 00023 #include <libxml/xmlreader.h> 00024 #include <libxml/xmlwriter.h> 00025 00026 00027 #include "votpp.hh" 00028 using namespace votpp; 00029 00030 00031 Element::~Element() {} 00032 00033 //Static members 00034 const string Element::def_empty = ""; 00035 const enum Resource_type Element::def_Resource_type = RESOURCE_RESULTS; 00036 const enum Values_Type Element::def_Values_type = VALUES_LEGAL; 00037 const bool Element::def_inclusive = true; 00038 const enum Stream_type Element::def_Stream_type = STREAM_TYPE_LOCATOR; 00039 const enum Stream_actuate Element::def_Stream_actuate = STREAM_ACTUATE_ONREQUEST; 00040 const enum EncodingType Element::def_encoding = ENCODING_NONE; 00041 00042 void Element::hk_reset() {} 00043 void Element::hk_setAttribute(string name, string value) {} 00044 void Element::hk_setChild(Element* child) {} 00045 void Element::setParentInChild(Element* child) { child->lparent = this; } 00046 enum Nodetype Element::nodeType() { return lnodetype; } 00047 string Element::className() { return lclassname; } 00048 00049 void Element::print(bool verbose) {} 00050 void Element::reset() {} 00051 void Element::done() {} 00052 00053 bool Element::setAttribute(string name, string value) { return true; } 00054 bool Element::setChild(Element* child) { return true; } 00055 bool Element::setNext(Element* next) { 00056 if (lnext) 00057 abort(); 00058 00059 lnext = next; next->lprev = this; 00060 return true; 00061 } 00062 00063 Element* Element::next() { return lnext; } 00064 Element* Element::prev() { return lprev; } 00065 Element* Element::parent() { return lparent; } 00066 00067 00068 00069 00070 00071 unsigned int Element::depth() 00072 { return ldepth; } 00073 00074 00075 unsigned int Element::ord() 00076 { return lord; } 00077 00078 00079 string Element::space_indent(int d) { 00080 int i; 00081 string s = ""; 00082 char buf[4]; 00083 snprintf(buf, 4, "%02d ", d); 00084 00085 for(i=0; i<d; i++) 00086 s += " "; 00087 00088 s += buf; 00089 return s; 00090 } 00091 00092 00093 00094 00095 00096 00097 bool Element::sto_bool(string s) 00098 { 00099 if ((strcmp(s.c_str(), "yes") == 0) || 00100 (strcmp(s.c_str(), "1") == 0)) 00101 return true; 00102 else 00103 return false; 00104 } 00105 00106 00107 enum Nodetype Element::sto_Nodetype(string s) 00108 { 00109 if (strcmp(s.c_str(), VOTable::sta_nodeName().c_str() ) == 0) return VOTABLE; 00110 else if (strcmp(s.c_str(), Resource::sta_nodeName().c_str() ) == 0) return RESOURCE; 00111 else if (strcmp(s.c_str(), Description::sta_nodeName().c_str()) == 0) return DESCRIPTION; 00112 else if (strcmp(s.c_str(), Definitions::sta_nodeName().c_str()) == 0) return DEFINITIONS; 00113 else if (strcmp(s.c_str(), Info::sta_nodeName().c_str() ) == 0) return INFO; 00114 else if (strcmp(s.c_str(), Param::sta_nodeName().c_str() ) == 0) return PARAM; 00115 else if (strcmp(s.c_str(), Table::sta_nodeName().c_str() ) == 0) return TABLE; 00116 else if (strcmp(s.c_str(), Field::sta_nodeName().c_str() ) == 0) return FIELD; 00117 else if (strcmp(s.c_str(), Group::sta_nodeName().c_str() ) == 0) return GROUP; 00118 else if (strcmp(s.c_str(), FieldRef::sta_nodeName().c_str() ) == 0) return FIELDref; 00119 else if (strcmp(s.c_str(), ParamRef::sta_nodeName().c_str() ) == 0) return PARAMref; 00120 else if (strcmp(s.c_str(), Values::sta_nodeName().c_str() ) == 0) return VALUES; 00121 else if (strcmp(s.c_str(), Min::sta_nodeName().c_str() ) == 0) return MIN; 00122 else if (strcmp(s.c_str(), Max::sta_nodeName().c_str() ) == 0) return MAX; 00123 else if (strcmp(s.c_str(), Option::sta_nodeName().c_str() ) == 0) return OPTION; 00124 else if (strcmp(s.c_str(), Link::sta_nodeName().c_str() ) == 0) return LINK; 00125 else if (strcmp(s.c_str(), Data::sta_nodeName().c_str() ) == 0) return DATA; 00126 else if (strcmp(s.c_str(), Tabledata::sta_nodeName().c_str() ) == 0) return TABLEDATA; 00127 else if (strcmp(s.c_str(), Column::sta_nodeName().c_str() ) == 0) return TD; 00128 else if (strcmp(s.c_str(), Row::sta_nodeName().c_str() ) == 0) return TR; 00129 else if (strcmp(s.c_str(), Fits::sta_nodeName().c_str() ) == 0) return FITS; 00130 else if (strcmp(s.c_str(), Binary::sta_nodeName().c_str() ) == 0) return BINARY; 00131 else if (strcmp(s.c_str(), Stream::sta_nodeName().c_str() ) == 0) return STREAM; 00132 else if (strcmp(s.c_str(), Coosys::sta_nodeName().c_str() ) == 0) return COOSYS; 00133 else 00134 throw MCS_ERROR( MSG_VOT_INVALID_NODETYPE, s); 00135 } 00136 00137 00138 enum Datatype Element::sto_Datatype(string s) 00139 { 00140 if (strcmp(s.c_str(), "boolean") == 0) return BOOLEAN ; 00141 else if (strcmp(s.c_str(), "bit") == 0) return BIT ; 00142 else if (strcmp(s.c_str(), "unsignedByte") == 0) return UNSIGNEDBYTE ; 00143 else if (strcmp(s.c_str(), "short") == 0) return SHORT ; 00144 else if (strcmp(s.c_str(), "int") == 0) return INT ; 00145 else if (strcmp(s.c_str(), "long") == 0) return LONG ; 00146 else if (strcmp(s.c_str(), "char") == 0) return CHAR ; 00147 else if (strcmp(s.c_str(), "unicodeChar") == 0) return UNICODECHAR ; 00148 else if (strcmp(s.c_str(), "float") == 0) return FLOAT ; 00149 else if (strcmp(s.c_str(), "double") == 0) return DOUBLE ; 00150 else if (strcmp(s.c_str(), "floatComplex") == 0) return FLOATCOMPLEX ; 00151 else if (strcmp(s.c_str(), "doubleComplex") == 0) return DOUBLECOMPLEX; 00152 else 00153 throw MCS_ERROR( MSG_VOT_INVALID_DATATYPE, s); 00154 } 00155 00156 00157 enum EncodingType Element::sto_EncodingType(string s) 00158 { 00159 if (strcmp(s.c_str(), "gzip") == 0) return ENCODING_GZIP ; 00160 else if (strcmp(s.c_str(), "base64") == 0) return ENCODING_BASE64 ; 00161 else if (strcmp(s.c_str(), "dynamic") == 0) return ENCODING_DYNAMIC ; 00162 else if (strcmp(s.c_str(), "none") == 0) return ENCODING_NONE ; 00163 else 00164 throw MCS_ERROR( MSG_VOT_INVALID_ENCODINGTYPE, s); 00165 } 00166 00167 00168 enum Resource_type Element::sto_Resource_type(string s) 00169 { 00170 if (strcmp(s.c_str(), "results") == 0) return RESOURCE_RESULTS ; 00171 else if (strcmp(s.c_str(), "meta") == 0) return RESOURCE_META ; 00172 else 00173 throw MCS_ERROR( MSG_VOT_INVALID_RESOURCE_TYPE, s); 00174 } 00175 00176 00177 enum Field_type Element::sto_Field_type(string s) 00178 { 00179 if (strcmp(s.c_str(), "hidden") == 0) return FIELD_HIDDEN ; 00180 else if (strcmp(s.c_str(), "no_query") == 0) return FIELD_NO_QUERY ; 00181 else if (strcmp(s.c_str(), "trigger") == 0) return FIELD_TRIGGER ; 00182 else if (strcmp(s.c_str(), "location") == 0) return FIELD_LOCATION ; 00183 else 00184 throw MCS_ERROR( MSG_VOT_INVALID_FIELD_TYPE, s); 00185 } 00186 00187 00188 enum Values_Type Element::sto_Values_type(string s) 00189 { 00190 if (strcmp(s.c_str(), "legal") == 0) return VALUES_LEGAL ; 00191 else if (strcmp(s.c_str(), "actual") == 0) return VALUES_ACTUAL ; 00192 else 00193 throw MCS_ERROR( MSG_VOT_INVALID_VALUES_TYPE, s); 00194 } 00195 00196 00197 enum Link_content_role Element::sto_Link_content_role(string s) 00198 { 00199 if (strcmp(s.c_str(), "query") == 0) return LINK_QUERY ; 00200 else if (strcmp(s.c_str(), "hints") == 0) return LINK_HINTS ; 00201 else if (strcmp(s.c_str(), "doc") == 0) return LINK_DOC ; 00202 else if (strcmp(s.c_str(), "location") == 0) return LINK_LOCATION ; 00203 else 00204 throw MCS_ERROR( MSG_VOT_INVALID_LINK_CONTENT_ROLE, s); 00205 } 00206 00207 00208 enum Stream_type Element::sto_Stream_type(string s) 00209 { 00210 if (strcmp(s.c_str(), "locator") == 0) return STREAM_TYPE_LOCATOR ; 00211 else if (strcmp(s.c_str(), "other") == 0) return STREAM_TYPE_OTHER ; 00212 else 00213 throw MCS_ERROR( MSG_VOT_INVALID_STREAM_TYPE, s); 00214 } 00215 00216 00217 enum Stream_actuate Element::sto_Stream_actuate(string s) 00218 { 00219 if (strcmp(s.c_str(), "onLoad") == 0) return STREAM_ACTUATE_ONLOAD ; 00220 else if (strcmp(s.c_str(), "onRequest") == 0) return STREAM_ACTUATE_ONREQUEST ; 00221 else if (strcmp(s.c_str(), "other") == 0) return STREAM_ACTUATE_OTHER ; 00222 else if (strcmp(s.c_str(), "none") == 0) return STREAM_ACTUATE_NONE ; 00223 else 00224 throw MCS_ERROR( MSG_VOT_INVALID_STREAM_ACTUATE, s); 00225 } 00226 00227 00228 enum Coosys_system Element::sto_Coosys_system(string s) 00229 { 00230 if (strcmp(s.c_str(), "eq_FK4") == 0) return COOSYS_EQ_FK4 ; 00231 else if (strcmp(s.c_str(), "eq_FK5") == 0) return COOSYS_EQ_FK5 ; 00232 else if (strcmp(s.c_str(), "ICRS") == 0) return COOSYS_ICRS ; 00233 else if (strcmp(s.c_str(), "ecl_FK4") == 0) return COOSYS_ECL_FK4 ; 00234 else if (strcmp(s.c_str(), "ecl_FK5") == 0) return COOSYS_ECL_FK5 ; 00235 else if (strcmp(s.c_str(), "galactic") == 0) return COOSYS_GALACTIC ; 00236 else if (strcmp(s.c_str(), "supergalactic") == 0) return COOSYS_SUPERGALACTIC ; 00237 else if (strcmp(s.c_str(), "xy") == 0) return COOSYS_XY ; 00238 else if (strcmp(s.c_str(), "barycentric") == 0) return COOSYS_BARYCENTRIC ; 00239 else if (strcmp(s.c_str(), "geo_app") == 0) return COOSYS_GEO_APP ; 00240 else 00241 throw MCS_ERROR( MSG_VOT_INVALID_COOSYS_SYSTEM, s); 00242 } 00243 00244 00245 00246 Element* Element::makeCopy() 00247 { 00248 Element* n = NULL; 00249 00250 switch (lnodetype) { 00251 case VOTABLE: n = new VOTable (*((VOTable *) this)); break; 00252 case RESOURCE: n = new Resource (*((Resource *) this)); break; 00253 case DESCRIPTION: n = new Description(*((Description*) this)); break; 00254 case DEFINITIONS: n = new Definitions(*((Definitions*) this)); break; 00255 case INFO: n = new Info (*((Info *) this)); break; 00256 case PARAM: n = new Param (*((Param *) this)); break; 00257 case TABLE: n = new Table (*((Table *) this)); break; 00258 case FIELD: n = new Field (*((Field *) this)); break; 00259 case GROUP: n = new Group (*((Group *) this)); break; 00260 case FIELDref: n = new FieldRef (*((FieldRef *) this)); break; 00261 case PARAMref: n = new ParamRef (*((ParamRef *) this)); break; 00262 case VALUES: n = new Values (*((Values *) this)); break; 00263 case MIN: n = new Min (*((Min *) this)); break; 00264 case MAX: n = new Max (*((Max *) this)); break; 00265 case OPTION: n = new Option (*((Option *) this)); break; 00266 case LINK: n = new Link (*((Link *) this)); break; 00267 case DATA: n = new Data (*((Data *) this)); break; 00268 case TABLEDATA: n = new Tabledata (*((Tabledata *) this)); break; 00269 case TD: n = new Column (*((Column *) this)); break; 00270 case TR: n = new Row (*((Row *) this)); break; 00271 case FITS: n = new Fits (*((Fits *) this)); break; 00272 case BINARY: n = new Binary (*((Binary *) this)); break; 00273 case STREAM: n = new Stream (*((Stream *) this)); break; 00274 case COOSYS: n = new Coosys (*((Coosys *) this)); break; 00275 } 00276 00277 return n; 00278 } 00279 00280 00281 00282 00283 00284 00285 00286 00287 #define XML 0 00288 #define BIN 1 00289 00290 char* VOTableReaderSplit::NodeStream[2] = { "<STREAM", "</STREAM" }; 00291 00292 VOTableReaderSplit::VOTableReaderSplit() : URLReader() 00293 { 00294 pMatch[XML] = NodeStream[XML]; 00295 pMatch[BIN] = NodeStream[BIN]; 00296 00297 pMatchLen[XML] = strlen(NodeStream[XML]); 00298 pMatchLen[BIN] = strlen(NodeStream[BIN]); 00299 00300 //SIMMETRY BREAKING: At the very start we deal with XML text 00301 sel = XML; 00302 nse = (sel + 1) % 2; 00303 00304 bin_filecount = 1; 00305 bin_outfd = 0; 00306 bin_file_prefix = ""; 00307 synchro.synchronize(true); 00308 00309 lbinpipe = NULL; 00310 consumerReady = false; 00311 } 00312 00313 00314 VOTableReaderSplit::~VOTableReaderSplit() 00315 { 00316 if (lbinpipe) 00317 lbinpipe->closeWrite(); 00318 } 00319 00320 //NOTE: this method must be called before OpenAs* 00321 void VOTableReaderSplit::saveBinaryStream(string fn) 00322 { 00323 bin_file_prefix = fn; 00324 } 00325 00326 00327 mcs::Pipe* VOTableReaderSplit::binpipe() 00328 { 00329 if (lbinpipe && (!consumerReady)) { 00330 synchro.enter(); 00331 lbinpipe->create(); 00332 consumerReady = true; 00333 synchro.leave(); 00334 } 00335 00336 return lbinpipe; 00337 } 00338 00339 00340 unsigned int VOTableReaderSplit::writeSplit(char* buf, unsigned int len) 00341 { 00342 unsigned int ret = 0; 00343 unsigned int retbin = 0; 00344 00345 if (sel == BIN) { 00346 00347 if (! bin_file_prefix.empty()) { //Save the stream on a file 00348 if (! bin_outfd) { //Open output file 00349 00350 char fn[100]; 00351 sprintf(fn, "%s.%03d", bin_file_prefix.c_str(), bin_filecount); 00352 bin_filecount++; 00353 00354 bin_outfd = ::open(fn, 00355 O_WRONLY | O_CREAT | O_TRUNC, 00356 S_IRUSR | S_IWUSR); 00357 } 00358 00359 len = b64.decode(buf, len); //, buf); 00360 retbin = write(bin_outfd, b64.buffer(), b64.bufUsed()); 00361 } 00362 00363 else { //Write the stream on a Pipe object 00364 if (! lbinpipe) { //Output pipe need to be opened 00365 lbinpipe = new mcs::Pipe(); 00366 00367 //Ensures consumer knows we are writing on a different pipe 00368 while (1) { 00369 synchro.enter(); 00370 if (consumerReady) { 00371 synchro.leave(); 00372 break; 00373 } 00374 else { 00375 URLReader::Write((void*) "\n", 1, 1); 00376 URLReader::flush(); 00377 synchro.leave(); 00378 mcs::sleep_ms(1); 00379 } 00380 } 00381 } 00382 00383 len = b64.decode(buf, len); //, buf); 00384 retbin = write(lbinpipe->getFD_write(), b64.buffer(), b64.bufUsed()); 00385 } 00386 00387 if (retbin != len) 00388 return 0; //ERROR 00389 } 00390 else { 00391 if (lbinpipe || bin_outfd) { 00392 //Eventually write bytes left in b64 cache 00393 unsigned int l = b64.decode(buf, 0); 00394 00395 if (bin_outfd) { 00396 retbin = write(bin_outfd, b64.buffer(), b64.bufUsed()); 00397 ::close(bin_outfd); 00398 bin_outfd = 0; 00399 } 00400 else { 00401 retbin = write(lbinpipe->getFD_write(), b64.buffer(), b64.bufUsed()); 00402 lbinpipe->closeWrite(); 00403 delete lbinpipe; 00404 lbinpipe = NULL; 00405 00406 } 00407 00408 if (retbin != l) 00409 return 0; //ERROR 00410 } 00411 00412 //Write on URLReader 00413 ret = URLReader::Write(buf, 1, len); 00414 if (ret != len) 00415 return 0; 00416 } 00417 00418 //Must return exactly "len" bytes, otherwise CURL will raise an error 00419 return len; 00420 } 00421 00422 00423 unsigned int VOTableReaderSplit::Write(void *buf, unsigned int size, 00424 unsigned int nmemb) 00425 { 00426 char* p = (char*) buf; 00427 char* cur; 00428 char* start[2]; 00429 start[sel] = p; 00430 start[nse] = NULL; 00431 size *= nmemb; 00432 nmemb = size; //nmemb will be used as return value 00433 00434 while ((cur = (char*) memchr(p, '<', size))) { 00435 00436 if (memcmp(cur, pMatch[sel], pMatchLen[sel]) == 0) { 00437 if (sel == XML) { //For xml data search for the end of STREAM tag 00438 cur = (char*) memchr(cur, '>', size); 00439 cur++; 00440 } 00441 start[nse] = cur; 00442 00443 if (writeSplit(start[sel], cur - start[sel]) == 0) 00444 return 0; //An error occurred 00445 00446 nse = sel; 00447 sel = (sel + 1) % 2; 00448 } 00449 00450 size -= cur - p + 1; 00451 p = cur + 1; 00452 } 00453 00454 if (writeSplit(start[sel], p + size - start[sel]) == 0) 00455 return 0; 00456 00457 return nmemb; 00458 } 00459 00460 00461 00462 00463 00464 00465 00466 00467 00468 00469 00470 00471 00472 00473 00474 00475 Parser_Stream::Parser_Stream() { 00476 flopen = false; 00477 lnode = NULL; 00478 nodeord = 0; 00479 pReader = malloc(sizeof(xmlTextReaderPtr)); 00480 lbinstream = NULL; 00481 } 00482 00483 00484 Parser_Stream::~Parser_Stream() { 00485 close(); 00486 free(pReader); 00487 } 00488 00489 string Parser_Stream::filename() { 00490 return lfilename; 00491 } 00492 00493 00494 enum Nodetype Parser_Stream::nodeType() { 00495 return lnodetype; 00496 } 00497 00498 00499 unsigned int Parser_Stream::depth() { 00500 return ldepth; 00501 } 00502 00503 00504 00505 NodePointer Parser_Stream::node() { 00506 NodePointer node; 00507 node.element = lnode; 00508 return node; 00509 } 00510 00511 00512 00513 00514 void Parser_Stream::open(string filename) 00515 { 00516 if (! filename.empty()) { 00517 close(); 00518 00519 00520 lfilename = filename; 00521 00522 xmlTextReaderPtr* reader = (xmlTextReaderPtr*) pReader; 00523 00524 //*reader = xmlNewTextReaderFilename(filename.c_str()); 00525 //int ret = xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE , 1); 00526 00527 //filename = input.OpenAsFile(filename); 00528 //*reader = xmlReaderForFile(filename.c_str(), NULL, 0); 00529 // XML_PARSE_DTDATTR | // default DTD attributes 00530 // XML_PARSE_NOENT | // substitute entities 00531 // XML_PARSE_DTDVALID); // validate with the DTD 00532 00533 00534 int fd = input.OpenAsFD(filename); 00535 *reader = xmlReaderForFd(fd, filename.c_str(), NULL, 0); 00536 00537 // XML_PARSE_DTDATTR | // default DTD attributes 00538 // XML_PARSE_NOENT | // substitute entities 00539 // XML_PARSE_DTDVALID); // validate with the DTD 00540 00541 if (! reader) 00542 throw MCS_ERROR( MSG_VOT_CANT_OPEN_FILE, filename ); 00543 00544 flopen = true; 00545 //fleof = false; 00546 continue_read = false; 00547 } 00548 } 00549 00550 00551 void Parser_Stream::close() { 00552 if (flopen) { 00553 xmlTextReaderPtr* reader = (xmlTextReaderPtr*) pReader; 00554 00555 xmlFreeTextReader(*reader); 00556 flopen = false; 00557 lnode = NULL; 00558 nodeord = 0; 00559 } 00560 } 00561 00562 00563 00564 00565 int Parser_Stream::parse() { 00566 int xml_type; 00567 string name, value; 00568 int ret; 00569 xmlChar* xmlval; 00570 00571 xmlTextReaderPtr* reader = (xmlTextReaderPtr*) pReader; 00572 00573 xml_type = xmlTextReaderNodeType(*reader); 00574 name = (char*) xmlTextReaderName(*reader); 00575 xmlval = xmlTextReaderValue(*reader); 00576 00577 value = ""; 00578 if (xmlval) { 00579 value = (char*) xmlval; 00580 xmlFree(xmlval); 00581 } 00582 00583 switch(xml_type) { 00584 00585 case XML_READER_TYPE_ELEMENT: 00586 flnewinfo = true; 00587 lnodetype = Element::sto_Nodetype(name); 00588 ldepth = xmlTextReaderDepth(*reader); 00589 00590 //cout << "XML_READER_TYPE_ELEMENT " << name << " " << ldepth << endl; 00591 00592 switch (lnodetype) { 00593 case VOTABLE: lnode = &votable; break; 00594 case RESOURCE: lnode = &resource; break; 00595 case DESCRIPTION: lnode = &description; break; 00596 case DEFINITIONS: lnode = &definitions; break; 00597 case INFO: lnode = &info; break; 00598 case PARAM: lnode = ¶m; break; 00599 case TABLE: lnode = &table; table.filename = lfilename; break; 00600 case FIELD: lnode = &field; break; 00601 case GROUP: lnode = &group; break; 00602 case FIELDref: lnode = &fieldref; break; 00603 case PARAMref: lnode = ¶mref; break; 00604 case VALUES: lnode = &values; break; 00605 case MIN: lnode = &min; break; 00606 case MAX: lnode = &max; break; 00607 case OPTION: lnode = &option; break; 00608 case LINK: lnode = &link; break; 00609 case DATA: lnode = &data; break; 00610 case TABLEDATA: lnode = &tabledata; break; 00611 case TD: lnode = &column; break; 00612 case TR: lnode = &row; break; 00613 case FITS: lnode = &fits; break; 00614 case BINARY: lnode = &binary; break; 00615 case STREAM: lnode = &stream; break; 00616 case COOSYS: lnode = &coosys; break; 00617 } 00618 00619 lnode->reset(); 00620 lnode->ldepth = ldepth; 00621 lnode->lord = nodeord; 00622 00623 //Loop through the attributes 00624 while ((ret = xmlTextReaderMoveToNextAttribute(*reader))) { 00625 if (ret < 0) 00626 throw MCS_ERROR( MSG_VOT_PARSE_FAILED, lfilename); 00627 00628 parse(); 00629 } 00630 00631 if ((nodeType() == DESCRIPTION) || 00632 (nodeType() == INFO) || 00633 (nodeType() == TD) 00634 ) 00635 continue_read = true; 00636 00637 if (nodeType() == STREAM) { 00638 ; 00639 } 00640 00641 /* 00642 if (nodeType() == BINARY) { 00643 int len; 00644 xmlParserInputBufferPtr* input = (xmlParserInputBufferPtr*) pInput; 00645 00646 while ((len = xmlParserInputBufferRead(*input, 1))) { 00647 char buf[10000]; 00648 00649 memcpy(buf, (*input)->buffer->content, len); 00650 buf[len] = '\0'; 00651 00652 cout << buf << endl; 00653 00654 if ((strchr(buf, '<')) && 00655 (strchr(buf, '/')) ) 00656 break; 00657 } 00658 } 00659 */ 00660 00661 break; 00662 00663 case XML_READER_TYPE_END_ELEMENT: //cout << "XML_READER_TYPE_END_ELEMENT " << name << endl; 00664 continue_read = false; 00665 break; 00666 00667 case XML_READER_TYPE_ATTRIBUTE: //cout << "XML_READER_TYPE_ATTRIBUTE " << name << " = " << value << endl; 00668 00669 if (! lnode->setAttribute(name, value)) { 00670 cerr << MCS_ERROR( MSG_VOT_UNEXPECTED_ATTRIBUTE, name).msg() << endl; 00671 } 00672 //throw MCS_ERROR( MSG_VOT_UNEXPECTED_ATTRIBUTE, name); 00673 00674 break; 00675 00676 case XML_READER_TYPE_TEXT: //cout << "XML_READER_TYPE_TEXT " << value << endl; 00677 00678 if ( (lnodetype == DESCRIPTION) || 00679 (lnodetype == INFO) || 00680 (lnodetype == TD) ) 00681 lnode->setAttribute("value", value); 00682 00683 break; 00684 00685 case XML_READER_TYPE_NONE: //IGNORED //cout << "XML_READER_TYPE_NONE " << endl; 00686 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: //cout << "XML_READER_TYPE_SIGNIFICANT_WHITESPACE " << name << endl; 00687 case XML_READER_TYPE_WHITESPACE: //cout << "XML_READER_TYPE_WHITESPACE " << name << endl; 00688 case XML_READER_TYPE_CDATA: //cout << "XML_READER_TYPE_CDATA " << name << endl; 00689 case XML_READER_TYPE_ENTITY_REFERENCE: //cout << "XML_READER_TYPE_ENTITY_REFERENCE " << name << endl; 00690 case XML_READER_TYPE_ENTITY: //cout << "XML_READER_TYPE_ENTITY " << name << endl; 00691 case XML_READER_TYPE_PROCESSING_INSTRUCTION: //cout << "XML_READER_TYPE_PROCESSING_INSTRUCTION " << name << endl; 00692 case XML_READER_TYPE_COMMENT: //cout << "XML_READER_TYPE_COMMENT " << name << endl; 00693 case XML_READER_TYPE_DOCUMENT: //cout << "XML_READER_TYPE_DOCUMENT " << name << endl; 00694 case XML_READER_TYPE_DOCUMENT_TYPE: //cout << "XML_READER_TYPE_DOCUMENT_TYPE " << name << endl; 00695 case XML_READER_TYPE_DOCUMENT_FRAGMENT: //cout << "XML_READER_TYPE_DOCUMENT_FRAGMENT " << name << endl; 00696 case XML_READER_TYPE_NOTATION: //cout << "XML_READER_TYPE_NOTATION " << name << endl; 00697 break; 00698 00699 default: 00700 cerr << MCS_ERROR( MSG_VOT_UNEXPECTED_NODE_TYPE, "", xml_type).msg() << endl; 00701 //throw MCS_ERROR( MSG_VOT_UNEXPECTED_NODE_TYPE, "", xml_type); 00702 } 00703 00704 return xml_type; 00705 } 00706 00707 00708 00709 int Parser_Stream::next_xmlnode(bool skipSubTree) { 00710 int ret; 00711 xmlTextReaderPtr* reader = (xmlTextReaderPtr*) pReader; 00712 00713 if (skipSubTree) { 00714 int d = depth(); 00715 00716 do { 00717 ret = xmlTextReaderRead(*reader); 00718 nodeord++; 00719 } 00720 while ((ret == 1) && (d != xmlTextReaderDepth(*reader))); 00721 } 00722 else { 00723 ret = xmlTextReaderRead(*reader); 00724 nodeord++; 00725 } 00726 00727 if (ret < 0) 00728 throw MCS_ERROR( MSG_VOT_PARSE_FAILED, lfilename); 00729 00730 return ret; 00731 } 00732 00733 00734 00735 00736 mcs::RecordSet* Parser_Stream::binstream() 00737 { return lbinstream; } 00738 00739 NodePointer Parser_Stream::next(bool skipSubTree) { 00740 flnewinfo = false; 00741 00742 if (lbinstream) { 00743 delete lbinstream; 00744 lbinstream = NULL; 00745 } 00746 00747 00748 do { 00749 if (next_xmlnode(skipSubTree) == 0) { //End of file 00750 lnode = NULL; 00751 break; 00752 } 00753 else 00754 parse(); 00755 } 00756 while ( 00757 (continue_read) || //Nodes to be read in their entirety 00758 (! flnewinfo) 00759 ); 00760 00761 if (lnode) 00762 lnode->done(); 00763 00764 if ((nodeType() == STREAM) && (node().element)) { 00765 if (input.binpipe()) { 00766 mcs::FITSReader* fits = new mcs::FITSReader(); 00767 fits->open(input.binpipe()->getFD_read()); 00768 lbinstream = fits; 00769 } 00770 } 00771 00772 return node(); 00773 } 00774 00775 00776 NodePointer Parser_Stream::skip(unsigned int n) 00777 { 00778 for (; n>1; n--) 00779 next_xmlnode(false); 00780 00781 next(false); 00782 return node(); 00783 } 00784 00785 00786 void Parser_Stream::saveBinaryStream(string fn) 00787 { input.saveBinaryStream(fn); } 00788 00789 00790 00791 00792 00793 00794 00795 Parser_Tree::Parser_Tree(bool smartmode) 00796 { 00797 this->smartmode = smartmode; 00798 lroot = NULL; 00799 } 00800 00801 00802 Parser_Tree::~Parser_Tree() 00803 { 00804 free(); 00805 } 00806 00807 void Parser_Tree::free() 00808 { 00809 if (lroot) 00810 delete lroot; 00811 } 00812 00813 00814 VOTable* Parser_Tree::root() 00815 { 00816 return lroot; 00817 } 00818 00819 00820 00821 void Parser_Tree::addNodes(Element* cur, unsigned int d) { 00822 Element* curchild = NULL; 00823 bool skip = false; 00824 00825 static Element* last = lroot; //The first time is set to the root node 00826 00827 do { 00828 00829 if (stream.depth() > d+1) { 00830 assert(stream.depth() == d+2); 00831 addNodes(curchild, d+1); 00832 } 00833 00834 if (! stream.node().element) 00835 return; 00836 00837 if (stream.depth() == d+1) { 00838 curchild = stream.node().element->makeCopy(); 00839 last->setNext(curchild); 00840 last = curchild; 00841 00842 if (! cur->setChild(curchild)) 00843 throw MCS_ERROR( MSG_VOT_UNEXPECTED_NODE_TYPE, "", curchild->nodeType()); 00844 } 00845 00846 if (stream.depth() <= d) 00847 return; 00848 00849 if (smartmode) 00850 switch (stream.node().element->nodeType()) { 00851 case TABLEDATA: 00852 case BINARY: 00853 case FITS: 00854 skip = true; 00855 break; 00856 default: 00857 skip = false; 00858 } 00859 00860 } 00861 while (stream.next(skip).element); 00862 } 00863 00864 00865 00866 00867 00868 void Parser_Tree::open(string filename) 00869 { 00870 stream.saveBinaryStream(basename(filename.c_str())); 00871 stream.open(filename); 00872 00873 stream.next(); 00874 if (stream.nodeType() != VOTABLE) 00875 throw MCS_ERROR( MSG_VOT_ROOT_IS_NOT_VOTABLE, "", stream.node().element->nodeType()); 00876 00877 lroot = (VOTable*) stream.node().element->makeCopy(); 00878 stream.next(); 00879 00880 addNodes(lroot, 0); 00881 } 00882 00883 00884 00885 00886 00887 00888 00889 00890 00891 00892 00893 00894 00896 //Parser_Table::Parser_Table(Table& nodeTable) : RecordSet() 00897 //{ 00898 // fn = nodeTable.filename; 00899 // ord_nodeTable = nodeTable.ord(); 00900 // 00901 // 00902 // stream.open(fn); 00903 // node = stream.skip(ord_nodeTable).element; 00904 //} 00905 // 00906 // 00907 // 00908 // 00909 //Parser_Table::Parser_Table(string fn, int tableOrd) : RecordSet() 00910 //{ 00911 // this->fn = fn; 00912 // 00913 // stream.open(fn); 00914 // stream.next(); 00915 // node = stream.node().element; 00916 // 00917 // for (int i=0; i<tableOrd; i++) { 00918 // do { 00919 // if (stream.node().element->nodeType() == TABLE) 00920 // break; 00921 // } 00922 // while (stream.next().element); 00923 // 00924 // stream.next(); 00925 // } 00926 // 00927 // if (! stream.node().element) //End of file 00928 // ; //ERROR: table ord not found 00929 // 00930 // searchStartData(); 00931 //} 00932 // 00933 // 00934 // 00935 // 00936 //Parser_Table::~Parser_Table() 00937 //{ 00938 // stream.close(); 00939 //} 00940 // 00941 // 00942 // 00943 // 00944 //void Parser_Table::searchStartData() 00945 //{ 00946 // //Prepare meta information and search the beginning of real data 00947 // do { 00948 // switch (node->nodeType()) { 00949 // 00950 // case FIELD: 00951 // addMeta((*((Field*) node))); 00952 // break; 00953 // 00954 // case TABLEDATA: 00955 // type = DATA_TABLEDATA; 00956 // goto exitloop; 00957 // 00958 // case FITS: 00959 // type = DATA_FITS; 00960 // goto exitloop; 00961 // 00962 // case BINARY: 00963 // type = DATA_BINARY; 00964 // goto exitloop; 00965 // 00966 // default: 00967 // ; 00968 // } 00969 // } 00970 // while ((node = stream.next().element)); 00971 // 00972 // exitloop: 00973 // 00974 // init(MCS_RS_USEMETAREC, 0, &meta); 00975 // startFetch(); 00976 //} 00977 // 00978 // 00979 // 00980 // 00981 //void Parser_Table::addMeta(Field& field) 00982 //{ 00983 // mcs::Data* d = NULL; 00984 // string s = field.arraysize(); 00985 // 00986 // /* 00987 // unsigned int d1, d2, d3, d4, d5; 00988 // bool foundDynamic = false; 00989 // 00990 // //Store the dimension specification for later use during data reading. 00991 // arrsizes.push_back(field.arraysize()); 00992 // 00993 // //Calculate array dimensions 00994 // d1 = d2 = d3 = d4 = d5 = 1; 00995 // if (! field.arraysize_isNull()) { 00996 // vector<string> values = split(field.arraysize(), "x"); 00997 // 00998 // if (values.size() > 5) 00999 // ; //ERROR: we can handle up to five dimensions 01000 // 01001 // 01002 // for (i=0; i<values.size(); i++) { 01003 // if (foundDynamic) 01004 // ; //ERROR: there can be only one dynamic dimension and it must 01005 // //be the last. 01006 // 01007 // string& s = values[i]; 01008 // 01009 // if (strchr(s.c_str(), '*')) { 01010 // //In a dimension spec there can be a *, meaning that effective 01011 // //size will be determined during data reading. 01012 // // 01013 // //If a number is present then it will be the maximum size, 01014 // //else the size is completely dynamic. 01015 // 01016 // s.replace(s.find("*", 0), 1, " "); 01017 // foundDynamic = true; 01018 // } 01019 // 01020 // switch (i) { 01021 // case 0: 01022 // d1 = stoi(values[i], false, 1); 01023 // break; 01024 // 01025 // case 1: 01026 // d2 = stoi(values[i], false, 1); 01027 // break; 01028 // 01029 // case 2: 01030 // d3 = stoi(values[i], false, 1); 01031 // break; 01032 // 01033 // case 3: 01034 // d4 = stoi(values[i], false, 1); 01035 // break; 01036 // 01037 // case 4: 01038 // d5 = stoi(values[i], false, 1); 01039 // break; 01040 // } 01041 // } 01042 // } 01043 // */ 01044 // 01045 // 01046 // 01047 // //Create appropriate mcs::Data objects 01048 // switch (field.datatype()) { 01049 // 01050 // case CHAR: 01051 // d = new mcs::Data(mcs::STRING, 1, false, s); 01052 // break; 01053 // 01054 // case UNICODECHAR: 01055 // //ERROR: type not handled 01056 // break; 01057 // 01058 // case BOOLEAN: 01059 // d = new mcs::Data(mcs::TINY, 0, false, s); 01060 // break; 01061 // 01062 // case BIT: 01063 // d = new mcs::Data(mcs::BLOB, 1, false, s); 01064 // break; 01065 // 01066 // case UNSIGNEDBYTE: 01067 // d = new mcs::Data(mcs::TINY, 0, true, s); 01068 // break; 01069 // 01070 // case SHORT: 01071 // d = new mcs::Data(mcs::SMALL, 0, false, s); 01072 // break; 01073 // 01074 // case INT: 01075 // d = new mcs::Data(mcs::INT, 0, false, s); 01076 // break; 01077 // 01078 // case LONG: 01079 // d = new mcs::Data(mcs::BIGINT, 0, false, s); 01080 // break; 01081 // 01082 // case FLOAT: 01083 // d = new mcs::Data(mcs::FLOAT, 0, false, s); 01084 // break; 01085 // 01086 // case DOUBLE: 01087 // d = new mcs::Data(mcs::DOUBLE, 0, false, s); 01088 // break; 01089 // 01090 // case FLOATCOMPLEX: 01091 // d = new mcs::Data(mcs::FLOAT, 0, false, s); 01092 // break; 01093 // 01094 // case DOUBLECOMPLEX: 01095 // //We need an extra dimension to handle real and imaginary part. 01096 // s = "2x" + s; 01097 // d = new mcs::Data(mcs::DOUBLE, 0, false, s); 01098 // break; 01099 // 01100 // default: 01101 // ; 01102 // //ERROR 01103 // } 01104 // 01105 // //Set name and add to the meta record. 01106 // d->setName(field.name()); 01107 // meta.addField(d); 01108 //} 01109 // 01110 // 01111 // 01112 // 01113 //bool Parser_Table::fetch(unsigned int newpos, bool random) { 01114 // rec().clear(); 01115 // 01116 // switch (type) { 01117 // case DATA_TABLEDATA: 01118 // return fetch_tabledata(newpos, random); 01119 // case DATA_FITS: 01120 // return fetch_fits(newpos, random); 01121 // case DATA_BINARY: 01122 // return fetch_binary(newpos, random); 01123 // } 01124 // 01125 // ; //ERROR: unexpected 01126 // return false; 01127 //} 01128 // 01129 // 01130 //bool Parser_Table::fetch_tabledata(unsigned int newpos, bool random) 01131 //{ 01132 // mcs::Data* d; 01133 // //unsigned int p, i1, i2, i3, i4, i5; 01134 // unsigned int p; 01135 // int i; 01136 // string s; 01137 // 01138 // if (! node) { 01139 // stream.close(); 01140 // return false; 01141 // } 01142 // 01143 // //Search for start of record 01144 // if (node->nodeType() != TR) { 01145 // node = stream.next().element; 01146 // 01147 // if (! node) { 01148 // stream.close(); 01149 // return false; 01150 // } 01151 // 01152 // if (node->nodeType() != TR) { 01153 // stream.close(); 01154 // return false; //End of file 01155 // } 01156 // } 01157 // 01158 // 01159 // //Search for first field 01160 // if (node->nodeType() != TD) { 01161 // node = stream.next().element; 01162 // if (node->nodeType() != TD) 01163 // ; //ERROR: unexpected node type 01164 // } 01165 // 01166 // 01167 // //There must be at least meta.count() fields. 01168 // for (i=0; i<meta.count(); i++) { 01169 // if (node->nodeType() != TD) 01170 // ; //ERROR 01171 // 01172 // //Get a pointer to current Column node 01173 // Column* f = (Column*) node; 01174 // 01175 // //Create a new mcs::Data object based on the correspondig template in the meta record 01176 // d = new mcs::Data(meta[i]); 01177 // 01178 // if (f->value_isNull()) 01179 // d->setNull(); 01180 // 01181 // else { 01182 // s = f->value(); 01183 // 01184 // if (! VarLenType(d->type())) { 01185 // vector<string> values = mcs::split(s, " "); 01186 // 01187 // if (values.size() > d->arraySize()) 01188 // ; //ERROR there are more data than cells in the array 01189 // 01190 // for (p=0; p<values.size(); p++) 01191 // (*d)(p) = values[p]; 01192 // } 01193 // 01194 // else { 01195 // switch (d->type()) { 01196 // case mcs::STRING: 01197 // (*d)() = s; 01198 // break; 01199 // 01200 // case mcs::TINY_BLOB: 01201 // //ERROR: unexpected because no VOTable type is associated 01202 // //with TINY_BLOB 01203 // break; 01204 // 01205 // case mcs::BLOB: 01206 // break; 01207 // 01208 // default: 01209 // ;//ERROR: unexpected 01210 // } 01211 // } 01212 // } 01213 // 01214 // rec().addField(d); 01215 // node = stream.next().element; 01216 // } 01217 // 01218 // return true; 01219 //} 01220 // 01221 // 01222 //bool Parser_Table::fetch_binary(unsigned int newpos, bool random) 01223 //{ 01224 // return false; 01225 //} 01226 // 01227 // 01228 //bool Parser_Table::fetch_fits(unsigned int newpos, bool random) 01229 //{ 01230 // return false; 01231 //} 01232 // 01233 // 01234 // 01235 // 01236 // 01237 // 01238 // 01239 // 01240 // 01241 // 01242 //Writer_Stream::Writer_Stream() 01243 //{ 01244 // level = 0; 01245 // flopen = 0; 01246 // node = NULL; 01247 // pWriter = malloc(sizeof(xmlTextWriterPtr)); 01248 //} 01249 // 01250 //Writer_Stream::~Writer_Stream() 01251 //{ 01252 // close(); 01253 //} 01254 // 01255 // 01256 //void Writer_Stream::open(string filename, enum Data_format format, bool include) 01257 //{ 01258 // close(); 01259 // 01260 // xmlTextWriterPtr* writer = (xmlTextWriterPtr*) pWriter; 01261 // *writer = xmlNewTextWriterFilename(filename.c_str(), 0); 01262 // 01263 // flopen = true; 01264 //} 01265 // 01266 // 01267 //void Writer_Stream::close() 01268 //{ 01269 // if (flopen) { 01270 // 01271 // if (node) 01272 // delete node; 01273 // 01274 // flopen = false; 01275 // } 01276 //} 01277 // 01278 // 01279 //const Writer_Stream& Writer_Stream::operator<<(Element* newnode) 01280 //{ 01281 // if (! node) { 01282 // if (newnode->nodeType() != VOTABLE) 01283 // ; //ERROR 01284 // 01285 // node = (Element*) new VOTable(*((VOTable*) newnode)); 01286 // } 01287 // else { 01288 // level++; 01289 // if (! node->setChild(newnode->makeCopy())) 01290 // ; //Error 01291 // 01292 // node = newnode; 01293 // } 01294 // 01295 // cout << Element::space_indent(level) << node->className() << endl; 01296 // 01297 // return *this; 01298 //} 01299 // 01300 // 01301 //const Writer_Stream& Writer_Stream::operator<<(const int& endnode) 01302 //{ 01303 // int i; 01304 // 01305 // for (i=0; i<endnode; i++) { 01306 // cout << Element::space_indent(level) << "---- " << node->className() << endl; 01307 // 01308 // Element* p = node; 01309 // node = node->parent(); 01310 // delete p; 01311 // level -= endnode; 01312 // } 01313 // 01314 // return *this; 01315 //}
VOTPP (VOTable C++ Parser) ver. 0.3.2-alpha1
|