#include "xml_result.h" #include #include #include #include #include #include #include //#include #include /* *************************************************************************************************** here starts the reader implementation *****************************************************************************************************/ #ifndef SIZETPRINTFLETTER # ifndef __LP64__ # define SIZETPRINTFLETTER "u" # else # define SIZETPRINTFLETTER "lu" # endif #endif void start_element_stub(void* userdata,const XML_Char* name, const XML_Char** attrs ); void end_element_stub(void* userdata,const XML_Char* name); void data_stub(void* userdata, const XML_Char* data, int len); /** table for translation base64 -> 0 to 63 */ static char base64_table[] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 }; class xml_result_handler { /** */ int alloc_stepsize; /** maximum allocated size of buffer list */ size_t bufferno_max; /** actual or new sample buffer */ size_t bufferno; /** buffers */ short int** buffers; /** number of samples (2 values for one sample) in each buffer, if actual buffer, this is the expected number */ size_t* sampleno; /** */ double* frequencies; /** maximum allocated size of last sample buffer in bytes */ size_t bufferlength; /** position of in actual sample buffer */ size_t bufferpos; /** base64 byte buffer */ char base64buffer[4]; /** the length of content in base64buffer */ int base64buffer_length; /** 1 if we are inside a adcdata section, 2 if we are saving a description */ int section_state; /** error messages, that are found */ std::string error_message; /** descripton sections */ std::string description_text; public: xml_result_handler(XML_Parser p) { /* set event handlers */ alloc_stepsize=1<<10; XML_SetElementHandler(p,start_element_stub,end_element_stub); XML_SetCharacterDataHandler(p,data_stub); XML_SetUserData(p,this); /* allocate some buffers */ sampleno=(size_t*)malloc(alloc_stepsize*sizeof(size_t)); buffers=(short int**)malloc(alloc_stepsize*sizeof(short int*)); frequencies=(double*)malloc(alloc_stepsize*sizeof(double)); if (sampleno==NULL || buffers==NULL) { if (sampleno!=NULL) free(sampleno); if (buffers!=NULL) free(buffers); if (frequencies!=NULL) free(frequencies); /* todo throw something */ return; } bufferno=0; buffers[0]=NULL; bufferno_max=alloc_stepsize; section_state=0; } void start_element(const XML_Char* name, const XML_Char** attrs) { if (strcmp(name,"adcdata")==0) { /* is there enough space in array? */ if (bufferno>=bufferno_max) { bufferno_max+=alloc_stepsize; buffers=(short int**)realloc((void*)buffers,bufferno_max*sizeof(short int*)); sampleno=(size_t*)realloc((void*)sampleno,bufferno_max*sizeof(size_t)); frequencies=(double*)realloc((void*)frequencies,bufferno_max*sizeof(double)); if (buffers==NULL || sampleno==NULL || frequencies==NULL) fprintf(stderr,"could not reallocate the buffer"); } /* todo read sample no*/ const XML_Char** pos=attrs; while (*pos!=NULL) { if (strcmp(*pos,"samples")==0 || strcmp(*pos,"s")==0) { sampleno[bufferno]=strtoul(*(pos+1),NULL,0); } else if (strcmp(*pos,"frequency")==0 || strcmp(*pos,"f")==0) { frequencies[bufferno]=strtod(*(pos+1),NULL); } pos+=2; } if (sampleno[bufferno]!=0) { bufferlength=sampleno[bufferno]*2*sizeof(short int); /* fresh buffer */ buffers[bufferno]=(short int*)malloc(bufferlength); } else { bufferlength=0; buffers[bufferno]=NULL; } bufferpos=0; /* todo check result */ base64buffer_length=0; section_state=1; } if (strcmp(name,"description")) { section_state=3; } if (strcmp(name,"error")==0) { section_state=2; } if (section_state==3) { description_text+="<"; description_text+=name; const XML_Char** attr=attrs; while(*attr!=NULL) { description_text+=" "; description_text+=*(attr++); description_text+="='"; description_text+=*(attr++); description_text+="'"; } description_text+=">"; } } void end_element(const XML_Char* name) { if (strcmp(name,"adcdata")==0) { /* empty base64 buffer */ if (bufferpos+base64buffer_length-1>=bufferlength) { bufferlength+=alloc_stepsize; buffers[bufferno]=(short int*)realloc(buffers[bufferno],bufferlength); /* todo reallocate check */ } if (base64buffer_length>1) { unsigned char s=base64buffer[0]; s<<=2; s|=(base64buffer[1]>>4); ((char*)buffers[bufferno])[bufferpos]=s; bufferpos++; if (base64buffer_length>2) { s=base64buffer[1]&15; s<<=4; s|=(base64buffer[2]>>2); ((char*)buffers[bufferno])[bufferpos]=s; bufferpos++; if (base64buffer_length>3) { s=base64buffer[2]&3; s<<=6; s|=base64buffer[3]; ((char*)buffers[bufferno])[bufferpos]=s; bufferpos++; } } } /* check right sample number */ if (bufferpos!=sampleno[bufferno]*2*sizeof(short int)) { sampleno[bufferno]=bufferpos/(2*sizeof(short int)); } /* prepare for next buffer */ bufferlength=0; bufferno++; section_state=0; } if (strcmp(name,"error")==0) { if (!error_message.empty() && error_message[error_message.size()-1]!='\n') { error_message.push_back('\n'); } section_state=0; } if (section_state==3) { description_text+="<"; description_text+=name; description_text+="/>"; } if (strcmp(name,"description")) { section_state=0; } } void data(const XML_Char* the_data, int len) { if (section_state==1) { int pos=0; while (pos=bufferlength) { /* to do reallocate */ bufferlength+=alloc_stepsize; buffers[bufferno]=(short int*)realloc(buffers[bufferno],bufferlength); if (buffers[bufferno]==NULL) fprintf(stderr,"could not enlarge the sample buffer\n"); } /* read three bytes from four letters */ unsigned char s=base64buffer[0]; s<<=2; s|=(base64buffer[1]>>4); ((char*)buffers[bufferno])[bufferpos]=s; bufferpos++; s=base64buffer[1]&15; s<<=4; s|=(base64buffer[2]>>2); ((char*)buffers[bufferno])[bufferpos]=s; bufferpos++; s=base64buffer[2]&3; s<<=6; s|=base64buffer[3]; ((char*)buffers[bufferno])[bufferpos]=s; bufferpos++; base64buffer_length=0; } } } else if (section_state==3) { description_text+=the_data; } else if (section_state==2) { error_message+=the_data; } } ~xml_result_handler() { if (sampleno!=NULL && buffers!=NULL) { size_t pos=0; while (pos<=bufferno) { if (buffers[pos]!=NULL) free(buffers[pos]); pos++; } } if (sampleno!=NULL) free(sampleno); if (buffers!=NULL) free(buffers); } /** print number of samples and frequency of the obtained data */ void print_info(FILE* f) { if (buffers==NULL || sampleno==NULL) { fprintf(f,"nothing saved\n"); return; } for (size_t i=0; istart_element(name,attrs); } void end_element_stub(void* userdata,const XML_Char* name) { ((xml_result_handler*)userdata)->end_element(name); } void data_stub(void* userdata, const XML_Char* data, int len ) { ((xml_result_handler*)userdata)->data(data,len); } xml_result_reader::xml_result_reader() { jobfilenamepattern=""; } xml_result_reader::~xml_result_reader() { } xml_result_reader::xml_result_reader(const std::string& jobpattern) { jobfilenamepattern=jobpattern; } /* ToDo error handling */ result* xml_result_reader::read(size_t no) { if (jobfilenamepattern=="") return NULL; char* tmp_name=(char*)malloc(jobfilenamepattern.size()+50); if (tmp_name==NULL) return NULL; snprintf(tmp_name,jobfilenamepattern.size()+50,jobfilenamepattern.c_str(),no); result* new_result=NULL; new_result=read(std::string(tmp_name)); free(tmp_name); return new_result; } result* xml_result_reader::read(const std::string& jobfilename) { /*open file*/ FILE* result_file=fopen(jobfilename.c_str(),"rb"); if (result_file==NULL) return NULL; XML_Parser parser=XML_ParserCreate(NULL); if (parser==NULL) { fclose(result_file); return NULL; } xml_result_handler h(parser); for (;;) { const size_t BUFF_SIZE=1<<10; int bytes_read; void *buff = XML_GetBuffer(parser, BUFF_SIZE); if (buff == NULL) { fprintf(stderr, "could not get the buffer from XML Parser\n"); fclose(result_file); return NULL; } bytes_read = fread(buff, 1, BUFF_SIZE, result_file); if (bytes_read < 0) { /* handle error */ fprintf(stderr,"error while reading\n"); break; } if (! XML_ParseBuffer(parser, bytes_read, bytes_read == 0)) { /* handle parse error */ fprintf(stderr,"error while parsing line %d: %s\n",static_cast(XML_GetCurrentLineNumber(parser)),XML_ErrorString(XML_GetErrorCode(parser))); break; } // peaceful end if (bytes_read == 0) break; } fclose(result_file); return NULL; } /* ************************************************************************************************ here starts the writer implementation **************************************************************************************************/ xml_result_writer::xml_result_writer(data_save_mode_type how) { resultfilename_pattern=""; data_save_mode=how; } xml_result_writer::xml_result_writer(const std::string& pattern, data_save_mode_type how) { resultfilename_pattern=pattern; data_save_mode=how; } int xml_result_writer::write_to_file(const std::string& filename, const result* res) const { // find the way to write const adc_result* adc_res=dynamic_cast(res); if (adc_res!=NULL) { write_adc_to_file(filename,adc_res); return 0; } const adc_results* adc_ress=dynamic_cast(res); if (adc_ress!=NULL) { write_adcs_to_file(filename, adc_ress); return 0; } const configuration_results* config_ress=dynamic_cast(res); if (config_ress!=NULL) { write_configuration_results_to_file(filename, *config_ress); return 0; } const error_result* err_res=dynamic_cast(res); if (err_res!=NULL) write_error_to_file(filename,err_res); else write_unknown_to_file(filename, res); return 0; } int xml_result_writer::write_unknown_to_file(const std::string& filename, const result* res) const { FILE* out=fopen(filename.c_str(),"w"); if (out==0) fprintf(stderr,"could not open file %s\n",filename.c_str()); fprintf(out,"\n"); fprintf(out,"\n",res->job_no); if (res==NULL) fprintf(out,"\n"); else fprintf(out,"\n"); fprintf(out,"\n"); fclose(out); return 0; } int xml_result_writer::write_error_to_file(const std::string& filename, const error_result* res) const { /* write an extra message to stderr */ fprintf(stderr,"job %" SIZETPRINTFLETTER ": %s\n",res->job_no,res->error_message.c_str()); FILE* out=fopen(filename.c_str(),"w"); if (out==0) { fprintf(stderr,"could not open file %s\n",filename.c_str()); return 0; } fprintf(out,"\n"); fprintf(out,"\n",res->job_no); fprintf(out," %s\n",res->error_message.c_str()); fprintf(out,""); fclose(out); return 0; } int xml_result_writer::write_configuration_results_to_file(const std::string& filename, const configuration_results& ress) const { FILE* out=fopen(filename.c_str(),"w"); fprintf(out,"\n"); fprintf(out,"\n\n",ress.job_no); XMLCh tempStr[300]; xercesc::XMLString::transcode("LS", tempStr, 299); xercesc::DOMImplementation *impl2 = xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr); xercesc::DOMLSSerializer *theSerializer=(static_cast(impl2))->createLSSerializer(); xercesc::DOMLSOutput *theOutputDesc=(static_cast(impl2))->createLSOutput(); for (configuration_results::const_iterator i=ress.begin(); i!=ress.end(); ++i) if ((*i)->tag->getDocumentElement()!=NULL) { xercesc::MemBufFormatTarget mem; theOutputDesc->setByteStream(&mem); xercesc::DOMNode *the_node = (*i)->tag->getDocumentElement(); theSerializer->write(the_node ,theOutputDesc); //theSerializer->writeNode(&mem,*((*i)->tag->getDocumentElement())); fwrite((char*)mem.getRawBuffer(),sizeof(char),mem.getLen(),out); mem.reset(); } theSerializer->release(); // todo fprintf(out,"\n\n"); fclose(out); return 0; } int xml_result_writer::write_adcs_to_file(const std::string& filename, const adc_results* ress) const { // fall back to some default mode data_save_mode_type how=data_save_mode; if (how==defaultmode) how=ascii; FILE* out=fopen(filename.c_str(),"w"); if (out==0) { fprintf(stderr,"could not open file %s\n",filename.c_str()); return 0; } fprintf(out,"\n"); fprintf(out,"\n",ress->job_no); fwrite(ress->description.c_str(),ress->description.size(),1,out); fprintf(out,"\n"); int num_res=0; for (adc_results::const_iterator res=ress->begin(); res!=ress->end(); ++res) { switch (how) { case separate_file: { // write separate data file char result_filename[1<<10]; snprintf(result_filename,sizeof(result_filename),"adc.%09" SIZETPRINTFLETTER ".%d.bin",ress->job_no,num_res); write_adcdata_separate(out, std::string(result_filename), *res); } break; case base64: write_adcdata_base64(out,*res); break; case csv: write_adcdata_formated(out,"%d; %d\n",*res); break; case ascii: write_adcdata_formated(out,"%d\t%d\n",*res); break; default: /* forget data */ fprintf(stderr,"forgeting adc data\n"); } num_res++; } fprintf(out,"\n"); fclose(out); return 0; } int xml_result_writer::write_adc_to_file(const std::string& filename, const adc_result* res) const { // fall back to some default mode data_save_mode_type how=data_save_mode; if (how==defaultmode) how=ascii; FILE* out=fopen(const_cast(filename.c_str()),"w"); if (out==0) { fprintf(stderr,"write_adc_to_file: could not open file %s\n",filename.c_str()); return 0; } fprintf(out,"\n"); fprintf(out,"\n",res->job_no); fwrite(res->description.c_str(),res->description.size(),1,out); fprintf(out,"\n"); switch (how) { case separate_file: { // write separate data file write_adcdata_separate(out, filename+".bin", res); } break; case base64: write_adcdata_base64(out,res); break; case csv: write_adcdata_formated(out,"%d; %d\n",res); break; case ascii: write_adcdata_formated(out,"%d\t%d\n",res); break; default: /* forget data */ fprintf(stderr,"forgetting adc data\n"); } fprintf(out,"\n"); fclose(out); return 0; } int xml_result_writer::write_adcdata_separate(FILE* out, const std::string& datafilename, const adc_result* res) const { /* todo: error handling */ FILE* binout=fopen(datafilename.c_str(),"wb"); if (binout==0) { fprintf(stderr,"could not open file %s\n",datafilename.c_str()); return 0; } fwrite(res->data, sizeof(short int)*res->nchannels, res->samples, binout); fclose(binout); fprintf(out, "\n", datafilename.c_str(), res->samples, res->sampling_frequency, res->nchannels); return 0; } int xml_result_writer::write_adcdata_formated(FILE* out, const std::string& format, const adc_result* res) const { fprintf(out,"\n",res->samples,res->sampling_frequency, res->nchannels); for(size_t i=0;isamples;++i) { for(int j=0;jnchannels;++j) { fprintf(out, format.c_str(), res->data[i*2+ j]); } } fprintf(out,"\n"); return 0; } int xml_result_writer::write_adcdata_base64(FILE* out, const adc_result* res) const { xercesc::XMLPlatformUtils::Initialize(); fprintf(out,"\n",res->samples,res->sampling_frequency, res->nchannels); unsigned int base64length=0; XMLByte* base64buffer=xercesc::Base64::encode( reinterpret_cast(res->data), res->samples*res->nchannels*sizeof(short int), reinterpret_cast(&base64length), xercesc::XMLPlatformUtils::fgMemoryManager ); fwrite(base64buffer,1,base64length,out); fprintf(out,"\n"); xercesc::XMLPlatformUtils::fgMemoryManager->deallocate(base64buffer); return 0; }