372 lines
12 KiB
C++
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;
|
|
}
|