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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
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;
}
|