summaryrefslogtreecommitdiff
path: root/code/core/interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'code/core/interface.cpp')
-rw-r--r--code/core/interface.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/code/core/interface.cpp b/code/core/interface.cpp
new file mode 100644
index 0000000..c2d3a3b
--- /dev/null
+++ b/code/core/interface.cpp
@@ -0,0 +1,262 @@
+#include <unistd.h>
+#include <asm-generic/errno.h>
+#include <boost/lexical_cast.hpp>
+
+#include "type2name.h"
+#include "log.h"
+#include "min.h"
+
+#include "interface.h"
+
+/* action definitions (the stuff implementing the different reflection primtives) */
+
+// (abstract) action (to implement filtering stuff)
+template<class interface>
+class Action {
+public:
+ Action<interface>(interface *ifc) : ifc(ifc) {}
+
+ bool isFiltered(char *desc) { // true -> don't use this element
+ return ! (ifc->ife.empty() || ifc->ifo.count(desc));
+ }
+
+ interface *ifc;
+};
+
+// count the length of a record assuming binary encoding
+template<class interface>
+class ActionCountRecordSize : public Action<interface> {
+public:
+ ActionCountRecordSize<interface>(interface ifc) : Action<interface>(ifc), result(0) {}
+
+ template<class T>
+ bool operator() (T &val, char *desc) {
+ if (this->isFiltered(desc)) return true;
+ result += sizeof(val);
+ return true;
+ }
+
+ int result;
+};
+
+// put the chosen titles in a string
+template<class interface>
+class ActionWriteTitle : public Action<interface> {
+public:
+ ActionWriteTitle<interface>(interface ifc) : Action<interface>(ifc) {}
+
+ template<class T>
+ bool operator() (T &val, char * desc) {
+ if (this->isFiltered(desc)) return true;
+ this->ifc->bufWrite(desc);
+ this->ifc->bufWrite(" ");
+ return true;
+ }
+};
+
+// put the choosen types in a string
+template<class interface>
+class ActionWriteTypes : public Action<interface> {
+public:
+ ActionWriteTypes<interface>(interface ifc) : Action<interface>(ifc) {}
+
+ template<class T>
+ bool operator() (T &val, char * desc) {
+ if (this->isFiltered(desc)) return true;
+ this->ifc->buf.append(type2name<T>());
+ this->ifc->buf.append(" ");
+ return true;
+ }
+};
+
+// put the serialized values to the string (space-delimited)
+// put the binary values to the string (no delimiter)
+template<class interface>
+class ActionWriteValues : public Action<interface> {
+public:
+ ActionWriteValues<interface>(interface ifc) : Action<interface>(ifc) {}
+
+ template<class T>
+ bool operator() (T &val, char *desc) {
+ if (this->isFiltered(desc)) return true;
+ return this->ifc->bufWrite(val);
+ }
+};
+
+// read serialized values
+template<class interface>
+class ActionRead : public Action<interface> {
+public:
+ ActionRead<interface>(interface ifc) : Action<interface>(ifc) {}
+
+ template<class T>
+ bool operator() (T &val, char * desc) {
+ if (this->isFiltered(desc)) return true;
+ return this->ifc->bufRead(val);
+ }
+};
+
+/* implementation of InputInterface */
+
+template<class T>
+InputInterface<T>::InputInterface(int fd, bool binary, IfObjectFilter *ifo, IfElementFilter *ife)
+ : binary(binary), fd(fd), ifo(ifo), ifo(ife), buf(), rpos(0), npos(0), wpos(0), eof(false) {
+ buf.reserve(buf_size);
+}
+
+template<class T>
+bool InputInterface<T>::garantueeBuf(size_t size) {
+ // no chance?
+ if (eof) return (wpos - rpos >= size);
+ if (size >= buf_size/2) return false;
+
+ // relocate buffer?
+ if (rpos > buf_size/2) {
+ buf = buf.substr(rpos);
+ buf.reserve(buf_size);
+ npos -= rpos;
+ wpos -= rpos;
+ rpos = 0;
+ }
+
+ // read more?
+ do {
+ if (wpos < buf_size) {
+ ssize_t res = read(fd, buf.data(), buf_size - wpos);
+ switch (res) {
+ case 0: // EOF
+ eof = true;
+ break;
+
+ case EAGAIN:
+ // TO DECIDE: wait?
+ // read again (if neccessary)
+ break;
+
+ case EIO: case EBADF: case EINVAL: case EINTR: case EFAULT:
+ return false;
+
+ default:
+ // read res bytes
+ wpos += res;
+ }
+ }
+ } while ((wpos - rpos < size) || eof); // loop in case of EAGAIN
+
+ return wpos - rpos >= size;
+}
+
+// make sure that a "\n"-terminated, non-empty string is in the buffer (starting at rpos)
+template<class T>
+bool InputInterface<T>::garantueeLine() {
+ if (npos <= rpos) npos = rpos + 1;
+ while (true) {
+ if ((npos > wpos) && !garantueeBuf(npos - rpos)) return false; // increase amount of data in buffer
+ if (buf[npos] == '\n') return true;
+ npos++;
+ }
+}
+
+template<class T>
+double InputInterface<T>::peekNextTime() {
+ double res;
+ if (!bufRead(res, false)) {
+ if (eof) {
+ return INFINITY;
+ }else{
+ DIE("peeking next time failed");
+ }
+ }
+ return res;
+}
+
+
+template<class Tif> template<class Tval>
+bool InputInterface<Tif>::bufRead(Tval &val, bool proceedRPos=true) {
+ if (binary) {
+ if (!garantueeBuf(sizeof(Tval))) return false;
+ val = *((Tval*) &(buf[npos]));
+ if (proceedRPos) rpos += sizeof(Tval);
+ }else{
+ if (!garantueeLine()) return false;
+
+ // find next delimiter
+ size_t p = buf.find_first_of(" \n", rpos);
+ if (!p || (p == buf.npos)) return false;
+
+ // parse substring
+ try {
+ val = boost::lexical_cast<Tval>(buf.substr(rpos, p-1));
+ } catch(...) {
+ return false;
+ }
+
+ if (proceedRPos) rpos = p + 1;
+ }
+ return true;
+}
+
+template<class T>
+bool InputInterface<T>::readEntireFile() {
+ return readFileUntil(INFINITY);
+}
+
+template<typename T>
+bool InputInterface<T>::readFileUntil(double time) {
+ // iterate over events
+ while (peekNextTime() <= min(time, INFINITY)) {
+ // read (and forget) time to proceed rpos
+ double _foo; bufRead(_foo);
+
+ // get element id
+ typename T::id_type id;
+ if (!bufRead(id)) return false;
+ // TODO: check if the id refers to a valid object
+
+ // ignore it?
+ if (!ifo->empty() && !ifo->count(id)) return false;
+
+ // construct interface action and apply it
+ ActionRead<InputInterface<T> > ia(this);
+ if (!(T::singleton(id)->interface(ia))) return false;
+ }
+ return true;
+}
+
+template<class T>
+OutputInterface<T>::OutputInterface(int fd, bool binary, IfObjectFilter *ifo, IfElementFilter *ife)
+ : fd(fd), binary(binary), ifo(ifo), ife(ife), buf() {}
+
+template<class T>
+bool OutputInterface<T>::pushObject(T *o) {
+ ActionWriteValues<OutputInterface<T> > ia(this);
+ return o->interface(ia);
+}
+
+template<class T>
+bool OutputInterface<T>::pushClass() {
+ if (ifo->empty()) {
+ // for every object of the class
+ for (int i=0; i<T::numElements(); i++)
+ if (!pushObject(T::singleton(i))) return false;
+ }else{
+ // for all objects specified by ifo
+ for (IfObjectFilter::iterator i = ifo->begin(); i != ifo->end(); i++)
+ if (!pushObject(T::singleton(*i))) return false;
+ }
+}
+
+template<class T>
+bool OutputInterface<T>::isContained(typename T::id_type id) {
+ return ifo->empty() || ifo->count(id);
+}
+
+template<class Tif> template<class Tval>
+bool OutputInterface<Tif>::bufWrite(Tval &val) {
+ try {
+ buf.append(boost::lexical_cast<std::string>(val));
+ }catch (...) {
+ return false;
+ }
+ return true;
+}
contact: Jan Huwald // Impressum