damaris-backends/core/xml_states.cpp

372 lines
12 KiB
C++

/* **************************************************************************
Author: Achim Gaedke
Created: June 2004
****************************************************************************/
#include "states.h"
#include "xml_states.h"
#include <fcntl.h>
#include <unistd.h>
#include <stdarg.h>
#include <cstring>
#ifndef SIZETPRINTFLETTER
# ifndef __LP64__
# define SIZETPRINTFLETTER "u"
# else
# define SIZETPRINTFLETTER "lu"
# endif
#endif
void xml_state_reader_startelement_handler(xml_state_reader* self,
const XML_Char *name,
const XML_Char **atts ) {
self->start_element(name,atts);
}
void xml_state_reader_endelement_handler(xml_state_reader* self,
const XML_Char *name) {
self->end_element(name);
}
const XML_Char* xml_state_reader::search_attribute(const XML_Char** atts,const XML_Char* attr_name) const {
if (atts==NULL || atts[0]==NULL) return NULL;
size_t attr_idx=0;
while (strcmp(atts[attr_idx],attr_name)!=0) {
attr_idx+=2;
if (atts[attr_idx]==NULL) return NULL;
}
return atts[attr_idx+1];
}
const XML_Char* xml_state_reader::search_attributes(const XML_Char** atts, ...) const {
if (atts==NULL || atts[0]==NULL) return NULL;
va_list names;
va_start(names,atts);
const XML_Char* attr_name=va_arg(names, const XML_Char*);
while (attr_name!=NULL) {
size_t attr_idx=0;
while (atts[attr_idx]!=NULL && strcmp(atts[attr_idx],attr_name)!=0)
attr_idx+=2;
if (atts[attr_idx]!=NULL) {
va_end(names);
return atts[attr_idx+1];
}
attr_name=va_arg(names, const XML_Char*);
}
va_end(names);
return NULL;
}
state_atom* xml_state_reader::state_factory(const XML_Char *name,
const XML_Char **atts) const {
if (strcmp(name,"state")==0) {
state* s=new state(1);
const XML_Char* length=search_attributes(atts,"length","time",(XML_Char*)NULL);
if (length!=NULL) s->length=strtod(length,NULL);
return s;
}
if (strcmp(name,"sequent")==0) {
state_sequent* s=new state_sequent();
const XML_Char* repeat=search_attribute(atts,"repeat");
if (repeat!=NULL)
s->repeat=strtoul(repeat,0,0);
else
s->repeat=1;
return s;
}
if (strcmp(name,"parallel")==0) {
return new state_parallel();
}
if (strcmp(name,"ttlout")==0) {
ttlout* ttls=new ttlout();
const XML_Char* id=search_attributes(atts,"id","i",(XML_Char*)NULL);
if (id!=NULL) ttls->id=strtol(id,NULL,0);
const XML_Char* value=search_attribute(atts,"value");
if (value!=NULL) ttls->ttls=strtoul(value,NULL,0);
const XML_Char* channel=search_attribute(atts,"channel");
if (channel!=NULL) {
const XML_Char* state=search_attribute(atts,"state");
if (state!=NULL) {
size_t number=strtoul(channel,0,0);
char state_char=(state)[0];
if (state_char=='h' || state_char=='1')
ttls->ttls.set(number,1);
else
ttls->ttls.set(number,0);
}
else {
fprintf(stderr,"found invalid ttl state: ignoring\n");
delete ttls;
ttls=NULL;
}
}
return (state_atom*)ttls;
}
if (strcmp(name,"analogout")==0) {
analogout* aout=new analogout();
const XML_Char* channel=search_attributes(atts,"channel","c","id","i",(XML_Char*)NULL);
const XML_Char* frequency=search_attributes(atts,"frequency","f",(XML_Char*)NULL);
const XML_Char* phase=search_attributes(atts,"phase","p",(XML_Char*)NULL);
const XML_Char* amplitude=search_attributes(atts,"amplitude","a",(XML_Char*)NULL);
const XML_Char* dac_value=search_attributes(atts,"dac_value","d",(XML_Char*)NULL);
if (dac_value!=NULL) aout->dac_value=strtol(dac_value,NULL,0);
if (channel!=NULL) aout->id=strtoul(channel,NULL,0);
if (frequency!=NULL) aout->frequency=strtod(frequency,NULL);
if (phase!=NULL) aout->phase=strtod(phase,NULL);
if (amplitude!=NULL)
aout->amplitude=strtod(amplitude,NULL);
else
aout->amplitude=1.0;
return (state_atom*)aout;
}
if (strcmp(name,"analogin")==0) {
analogin* ain=new analogin();
const XML_Char* id=search_attributes(atts,"id","i",(XML_Char*)NULL);
const XML_Char* frequency=search_attributes(atts,"f","frequency",(XML_Char*)NULL);
const XML_Char* samples=search_attributes(atts,"s","samples",(XML_Char*)NULL);
const XML_Char* channels=search_attributes(atts,"c","channels",(XML_Char*)NULL);
const XML_Char* resolution = search_attributes(atts,"r","res","resolution",(XML_Char*)NULL);
if (resolution!=NULL)
ain->resolution=strtoul(resolution,NULL,0);
else
ain->resolution=14; // was 12
if (frequency!=NULL) ain->sample_frequency=strtod(frequency,NULL);
if (samples!=NULL) ain->samples=strtoul(samples,NULL,0);
if (id!=NULL) ain->id=strtoul(id,NULL,0);
if (channels!=NULL) {
ain->channels = channel_array(strtoul(channels,NULL,0));
ain->nchannels = ain->channels.count();
} else {
ain->channels = channel_array(3);
ain->nchannels = ain->channels.count();
}
// set parameters for each channel
for (int i = 0; i < ain->nchannels; i++) {
if (ain->channels[i] == true) {
char buffer1[100];
char buffer2[100];
sprintf(buffer1, "sen%i", i);
sprintf(buffer2, "sensitivity%i", i - 1);
// read sensitivity
const XML_Char* sensitivity = search_attributes(atts, buffer1, buffer2,(XML_Char*)NULL);
if (sensitivity != NULL) {
if (ain->sensitivity == NULL) {
ain->sensitivity = new double[ain->nchannels];
}
ain->sensitivity[i] = strtod(sensitivity, NULL);
} else {
ain->sensitivity[i] = ADC_M2I_DEFAULT_SENSITIVITY;
}
delete sensitivity;
// read offset
sprintf(buffer1, "offset%i", i);
const XML_Char* offset = search_attributes(atts, buffer1, (XML_Char*)NULL);
if (offset != NULL) {
if (ain->offset == NULL) {
ain->offset = new int[ain->nchannels];
}
ain->offset[i] = strtol(offset, NULL, 0);
} else {
ain->offset[i] = ADC_M2I_DEFAULT_OFFSET;
}
delete offset;
// read impedance
sprintf(buffer1, "impedance%i", i);
const XML_Char* impedance = search_attributes(atts, buffer1, (XML_Char*)NULL);
if (impedance != NULL) {
if (ain->impedance == NULL) {
ain->impedance = new double[ain->nchannels];
}
ain->impedance[i] = strtol(impedance, NULL, 0);
} else {
ain->impedance[i] = ADC_M2I_DEFAULT_IMPEDANCE;
}
delete impedance;
}
}
return (state_atom*)ain;
}
fprintf(stderr,"unknown tag %s found\n",name);
return NULL;
}
void xml_state_reader::start_element(const XML_Char *name,
const XML_Char **atts) {
state_atom* new_element=state_factory(name,atts);
if (root==NULL)
root=new_element;
if (new_element!=NULL && !pending_elements.empty()) {
state* container=dynamic_cast<state*>(pending_elements.back());
if (container!=NULL)
container->push_back(new_element);
else
fprintf(stderr,"found invalid nested element %s\n",name);
}
pending_elements.push_back(new_element);
}
void xml_state_reader::end_element(const XML_Char *name) {
pending_elements.pop_back();
}
xml_state_reader::xml_state_reader() {
fprintf(stderr, "xml_state_reader class is decrepated, please shift to xerces supporting classes.\n");
root=(state_atom*)NULL;
parser=XML_ParserCreate((XML_Char*)NULL);
XML_SetUserData(parser,(void*)this);
XML_SetElementHandler(parser,
(XML_StartElementHandler)xml_state_reader_startelement_handler,
(XML_EndElementHandler)xml_state_reader_endelement_handler);
}
state_atom* xml_state_reader::read_from_string(const std::string& data) {
if (!XML_Parse(parser,data.c_str(), data.size(),1)) {
/* handle parse error */
fprintf(stderr,"error while parsing\n");
delete root;
root=NULL;
return NULL;
}
state_atom* return_value=root;
root=NULL;
return return_value;
}
state_atom* xml_state_reader::read_from_file(const std::string& filename) {
int docfd=open(filename.c_str(),O_RDONLY);
for (;;) {
const size_t BUFF_SIZE=1<<12;
int bytes_read;
void *buff = XML_GetBuffer(parser, BUFF_SIZE);
if (buff == NULL) {
fprintf(stderr, "could not get the buffer from XML Parser\n");
close(docfd);
return NULL;
}
bytes_read = read(docfd, buff, BUFF_SIZE);
if (bytes_read < 0) {
/* handle error */
fprintf(stderr,"error while reading\n");
if (root!=NULL) delete root;
root=NULL;
break;
}
if (! XML_ParseBuffer(parser, bytes_read, bytes_read == 0)) {
/* handle parse error */
fprintf(stderr,"error while parsing\n");
if (root!=NULL) delete root;
root=NULL;
break;
}
// peaceful end
if (bytes_read == 0) break;
};
close(docfd);
state_atom* return_value=root;
root=NULL;
return return_value;
}
xml_state_reader::~xml_state_reader(){
XML_ParserFree(parser);
if (root!=NULL) delete root;
}
int xml_state_writer::write_states(FILE* output, const state_atom& states_to_write, int add_header, int indent_size) {
if (add_header) {
fprintf(output,"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
}
std::string indent_string(indent_size,' ');
const state_sequent* ss=dynamic_cast<const state_sequent*>(&states_to_write);
if (ss!=NULL) {
if (ss->repeat==1)
fprintf(output,"%s<sequent>\n",indent_string.c_str());
else
fprintf(output,"%s<sequent repeat=\"%" SIZETPRINTFLETTER "\">\n",indent_string.c_str(),ss->repeat);
for (state::const_iterator i=ss->begin();i!=ss->end(); i++) {
write_states(output,**i,0,indent_size+indent_increase);
}
fprintf(output,"%s</sequent>\n",indent_string.c_str());
return 1;
}
const state_parallel* sp=dynamic_cast<const state_parallel*>(&states_to_write);
if (sp!=NULL){
fprintf(output,"%s<parallel>\n",indent_string.c_str());
for (state::const_iterator i=sp->begin();i!=sp->end(); i++) {
write_states(output,**i,0,indent_size+indent_increase);
}
fprintf(output,"%s</parallel>\n",indent_string.c_str());
return 1;
}
const state* st=dynamic_cast<const state*>(&states_to_write);
if (st!=NULL) {
fprintf(output,"%s<state length=\"%g\">\n",indent_string.c_str(),st->length);
for (state::const_iterator i=st->begin();i!=st->end(); i++) {
write_states(output,**i,0,indent_size+indent_increase);
}
fprintf(output,"%s</state>\n",indent_string.c_str());
return 1;
}
const ttlout* ttlo=dynamic_cast<const ttlout*>(&states_to_write);
if (ttlo!=NULL) {
fprintf(output,"%s<ttlout value=\"0x%lx\"/>\n",
indent_string.c_str(),
ttlo->ttls.to_ulong());
return 1;
}
const analogout* ao=dynamic_cast<const analogout*>(&states_to_write);
if (ao!=NULL) {
fprintf(output,
"%s<analogout id=\"%d\" frequency=\"%g\" amplitude=\"%g\" phase=\"%g\" dac_value=\"%d\"/>\n",
indent_string.c_str(),
ao->id,
ao->frequency,
ao->amplitude,
ao->phase,
ao->dac_value);
return 1;
}
const analogin* ai=dynamic_cast<const analogin*>(&states_to_write);
if (ai!=NULL) {
char args[2000];
char buffer[1000];
sprintf(args, "%s<analogin id=\"%d\" samples=\"%" SIZETPRINTFLETTER "\" sample_frequency=\"%g\" channels=\"%lu\" resolution=\"%" SIZETPRINTFLETTER "\"",
indent_string.c_str(),
ai->id,
ai->samples,
ai->sample_frequency,
ai->channels.to_ulong(),
ai->resolution);
for (int i = 0; i < ai->nchannels; i++) {
sprintf(buffer, "sensitivity%d=\"%g\" offset%d=\"%d\" impedance%d=\"%g\"", i, ai->sensitivity[i], i, ai->offset[i], i, ai->impedance[i]);
strcat(args, buffer);
}
strcat(args, "/>\n");
// fix -Werror=format-security
//fprintf(output, args);
fputs(args,output);
return 1;
}
fprintf(output,"%s<!-- something missing -->\n",indent_string.c_str());
return 0;
}