VOTable.cc

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 = &param;        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 = &paramref;     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
Documentation generated on Sun Nov 18 12:06:20 UTC 2007