Line data Source code
1 : #include <alma/ASDMBinaries/SDMDataObjectStreamReader.h>
2 :
3 : #ifdef WITHOUT_BOOST
4 : #include <regex>
5 : #include <alma/ASDM/Misc.h>
6 : #endif
7 :
8 : using namespace CorrelationModeMod;
9 : using namespace CorrelatorTypeMod;
10 : using namespace PrimitiveDataTypeMod;
11 : using namespace ProcessorTypeMod;
12 :
13 : using namespace std;
14 :
15 : namespace asdmbinaries {
16 :
17 0 : SDMDataObjectStreamReaderException::SDMDataObjectStreamReaderException():message("SDMDataObjectStreamReaderException:") {;}
18 :
19 0 : SDMDataObjectStreamReaderException::SDMDataObjectStreamReaderException(const string & message): message("SDMDataObjectStreamReaderException:" + message) {;}
20 :
21 0 : const string& SDMDataObjectStreamReaderException::getMessage() { return message; }
22 :
23 0 : SDMDataObjectStreamReader::SDMDataObjectStreamReader() {
24 : // cout << "SDMDataObjectStreamReader::SDMDataObjectStreamReader() : entering" << endl;
25 0 : const char *partNames[] = {"actualDurations", "actualTimes", "autoData", "crossData", "zeroLags", "flags"};
26 0 : set<string> dummy(partNames, partNames+6);
27 0 : s_partNames = dummy;
28 0 : sdmDataSubset = SDMDataSubset(&sdmDataObject);
29 :
30 0 : boundary_1 = "" ;
31 0 : currentState = S_NO_BDF;
32 : // cout << "SDMDataObjectStreamReader::SDMDataObjectStreamReader() : exiting" << endl;
33 0 : }
34 :
35 0 : SDMDataObjectStreamReader::~SDMDataObjectStreamReader() {
36 : //cout << "SDMDataObjectStreamReader::~SDMDataObjectStreamReader : entering" << endl;
37 0 : this->close();
38 : //cout << "SDMDataObjectStreamReader::~SDMDataObjectStreamReader : exiting" << endl;
39 0 : }
40 :
41 0 : void SDMDataObjectStreamReader::open(const string& path) {
42 0 : checkState(T_OPEN, "open");
43 0 : this->path = path;
44 0 : f.open(path.c_str(), ifstream::in);
45 0 : if (f.fail())
46 0 : throw SDMDataObjectStreamReaderException("could not open '" + path + "'.");
47 :
48 0 : boundary_1 = requireMIMEHeader();
49 : // cout << "Boundary = " << boundary_1 << endl;
50 0 : sdmDataObject.valid_ = true;
51 0 : requireSDMDataHeaderMIMEPart();
52 0 : sdmDataObject.owns();
53 0 : integrationIndex = -1; // We have not yet read any integration.
54 :
55 0 : currentState = S_AT_BEGINNING;
56 0 : }
57 :
58 0 : int64_t SDMDataObjectStreamReader::position() {
59 0 : return (int64_t) f.tellg();
60 : }
61 :
62 0 : void SDMDataObjectStreamReader::position(int64_t p) {
63 0 : f.seekg(p);
64 0 : }
65 :
66 0 : void SDMDataObjectStreamReader::close() {
67 : // cout << "SDMDataObjectStreamReader::close -- Entering" << endl;
68 0 : if (f.is_open()) {
69 0 : releaseMemory(sdmDataSubset);
70 0 : for (unsigned int i = 0; i < remainingSubsets.size(); i++)
71 0 : releaseMemory(remainingSubsets[i]);
72 0 : for (unsigned int i = 0; i < someSubsets.size(); i++)
73 0 : releaseMemory(someSubsets[i]);
74 0 : f.close();
75 0 : currentState = S_NO_BDF;
76 : }
77 : // cout << "SDMDataObjectStreamReader::close -- Exiting" << endl;
78 0 : }
79 :
80 0 : unsigned int SDMDataObjectStreamReader::currentIntegrationIndex() const { checkState(T_QUERY, "currentIntegrationIndex"); return integrationIndex; }
81 0 : unsigned long long SDMDataObjectStreamReader::currentIntegrationStartsAt() const { checkState(T_QUERY, "currentIntegrationStartAt"); return integrationStartsAt; }
82 0 : string SDMDataObjectStreamReader::title() const { checkState(T_QUERY, "title"); return sdmDataObject.title(); }
83 0 : const ByteOrder* SDMDataObjectStreamReader::byteOrder() const { checkState(T_QUERY, "byteOrder"); return sdmDataObject.byteOrder(); }
84 0 : unsigned long long SDMDataObjectStreamReader::startTime() const { checkState(T_QUERY, "startTime"); return sdmDataObject.startTime(); }
85 0 : unsigned int SDMDataObjectStreamReader::numTime() const { checkState(T_QUERY, "numTime"); return sdmDataObject.numTime(); }
86 0 : string SDMDataObjectStreamReader::dataOID() const { checkState(T_QUERY, "dataOID"); return sdmDataObject.dataOID(); }
87 0 : string SDMDataObjectStreamReader::execBlockUID() const { checkState(T_QUERY, "execBlockUID"); return sdmDataObject.execBlockUID(); }
88 0 : unsigned int SDMDataObjectStreamReader::execBlockNum() const { checkState(T_QUERY, "execBlockNum"); return sdmDataObject.execBlockNum(); }
89 0 : unsigned int SDMDataObjectStreamReader::scanNum() const { checkState(T_QUERY, "scanNum"); return sdmDataObject.scanNum(); }
90 0 : unsigned int SDMDataObjectStreamReader::subscanNum() const { checkState(T_QUERY, "subscanNum"); return sdmDataObject.subscanNum(); }
91 0 : unsigned int SDMDataObjectStreamReader::numAntenna() const { checkState(T_QUERY, "numAntenna"); return sdmDataObject.numAntenna(); }
92 0 : CorrelationMode SDMDataObjectStreamReader::correlationMode() const { checkState(T_QUERY, "correlationMode"); return sdmDataObject.correlationMode(); }
93 0 : OptionalSpectralResolutionType SDMDataObjectStreamReader::spectralResolutionType() const { checkState(T_QUERY, "spectralResolutionType"); return sdmDataObject.spectralResolutionType(); }
94 0 : ProcessorType SDMDataObjectStreamReader::processorType() const { checkState(T_QUERY, "processorType"); return sdmDataObject.processorType(); }
95 0 : CorrelatorType SDMDataObjectStreamReader::correlatorType() const { checkState(T_QUERY, "correlatorType"); return sdmDataObject.correlatorType(); }
96 0 : bool SDMDataObjectStreamReader::hasPackedData() const { checkState(T_QUERY, "isTP"); return sdmDataObject.hasPackedData();}
97 0 : bool SDMDataObjectStreamReader::isTP() const { checkState(T_QUERY, "isTP"); return sdmDataObject.isTP();}
98 0 : bool SDMDataObjectStreamReader::isWVR() const {checkState(T_QUERY, "isCorrelation"); return sdmDataObject.isWVR();}
99 0 : bool SDMDataObjectStreamReader::isCorrelation() const {checkState(T_QUERY, "isCorrelation"); return sdmDataObject.isCorrelation();}
100 0 : const SDMDataObject::DataStruct& SDMDataObjectStreamReader::dataStruct() const { checkState(T_QUERY, "dataStruct"); return sdmDataObject.dataStruct();}
101 0 : bool SDMDataObjectStreamReader::aborted() const {checkState(T_QUERY, "aborted"); return sdmDataObject.aborted();}
102 0 : unsigned long long SDMDataObjectStreamReader::abortTime() const { checkState(T_QUERY, "abortTime"); return sdmDataObject.abortTime(); }
103 0 : string SDMDataObjectStreamReader::abortReason() const { checkState(T_QUERY, "abortReason"); return sdmDataObject.abortReason(); }
104 0 : string SDMDataObjectStreamReader::toString() const { checkState(T_QUERY, "toString"); return sdmDataObject.toString(); }
105 :
106 0 : void SDMDataObjectStreamReader::checkState(Transitions t, const string& methodName) const {
107 : // cout << "Entering checkState with currentState = " << currentState << " and transition = " << t << " for method " << methodName << endl;
108 0 : switch (currentState) {
109 0 : case S_NO_BDF:
110 0 : if ( t == T_OPEN ) {
111 0 : return;
112 : }
113 0 : break;
114 :
115 0 : case S_AT_BEGINNING :
116 0 : switch (t) {
117 0 : case T_QUERY:
118 : case T_TEST_END:
119 : case T_READ:
120 : case T_READ_NEXT:
121 : case T_READ_ALL:
122 : case T_CLOSE:
123 0 : return;
124 0 : default :
125 0 : break;
126 : }
127 0 : break;
128 :
129 0 : case S_READING:
130 0 : switch (t) {
131 0 : case T_TEST_END:
132 : case T_READ:
133 : case T_READ_NEXT:
134 : case T_READ_ALL:
135 : case T_QUERY:
136 : case T_CLOSE:
137 0 : return;
138 0 : default :
139 0 : break;
140 : }
141 0 : break;
142 :
143 0 : case S_AT_END:
144 0 : switch(t) {
145 0 : case T_TEST_END:
146 : case T_QUERY:
147 : case T_READ_NEXT:
148 : case T_READ_ALL:
149 : case T_CLOSE:
150 0 : return;
151 0 : default:
152 0 : break;
153 : }
154 0 : break;
155 : } // end switch on currentState
156 :
157 : // Any other pair (transition, currentState) will throw an exception.
158 0 : throw SDMDataObjectStreamReaderException("Invalid call of method '" + methodName + "' in the current context.");
159 : }
160 :
161 0 : bool SDMDataObjectStreamReader::hasSubset() {
162 0 : checkState(T_TEST_END, "hasSubset");
163 0 : bool atEnd = currentLine.compare("--"+boundary_1+"--") == 0;
164 0 : if (atEnd) currentState = S_AT_END;
165 0 : return !atEnd;
166 : }
167 :
168 0 : const vector<SDMDataSubset>& SDMDataObjectStreamReader::nextSubsets(unsigned int nSubsets) {
169 0 : checkState(T_READ_NEXT, "nextSubsets");
170 :
171 : // Deep empty of the vector nextSubsets
172 : // Firstly free all memory dynamically allocated in every element of the vector.
173 0 : for (unsigned int i = 0; i < someSubsets.size(); i++)
174 0 : releaseMemory(someSubsets.at(i));
175 :
176 : // Then clear the vector.
177 0 : someSubsets.clear();
178 :
179 : // Then populate the vector nextSubsets with as many SDMDataSubsets as possible up to a limit
180 : // of nSubsets read from the current position.
181 0 : unsigned int nRead = 0;
182 0 : while ((nRead < nSubsets) && hasSubset()) {
183 0 : someSubsets.push_back(SDMDataSubset(&sdmDataObject));
184 0 : integrationIndex++; nRead++;
185 0 : requireSDMDataSubsetMIMEPart(someSubsets.back());
186 0 : string line = nextLine();
187 0 : }
188 :
189 0 : return someSubsets;
190 : }
191 :
192 0 : const vector<SDMDataSubset>& SDMDataObjectStreamReader::allRemainingSubsets() {
193 : // cout << "SDMDataObjectStreamReader::allRemainingSubsets: entering." << endl;
194 0 : checkState(T_READ_ALL, "allRemainingSubsets");
195 :
196 : // Deep empty of the vector remainingSubsets.
197 : // Firstly free all memory dynamically allocated in every element of the vector.
198 0 : for (unsigned int i = 0; i < remainingSubsets.size(); i++)
199 0 : releaseMemory(remainingSubsets.at(i));
200 :
201 : // Then clear the vector.
202 0 : remainingSubsets.clear();
203 :
204 : // Then populate the vector with a new collection.
205 0 : while (hasSubset()) {
206 0 : remainingSubsets.push_back(SDMDataSubset(&sdmDataObject));
207 0 : integrationIndex++;
208 0 : requireSDMDataSubsetMIMEPart(remainingSubsets.back());
209 0 : string line = nextLine();
210 0 : }
211 :
212 : // cout << "SDMDataObjectStreamReader::allRemainingSubsets: exiting." << endl;
213 0 : return remainingSubsets;
214 : }
215 :
216 0 : const SDMDataSubset & SDMDataObjectStreamReader::getSubset() {
217 0 : checkState(T_READ, "getSubset");
218 0 : integrationIndex++;
219 0 : requireSDMDataSubsetMIMEPart(sdmDataSubset);
220 0 : string line = nextLine();
221 :
222 0 : currentState = S_READING;
223 0 : return sdmDataSubset;
224 0 : }
225 :
226 0 : string SDMDataObjectStreamReader::nextLine() {
227 0 : unsigned long long whereAmI = f.tellg();
228 0 : getline(f, currentLine);
229 0 : if (f.fail()) {
230 0 : ostringstream oss ;
231 0 : oss << "SDMDataObjectStreamReader::nextLine() : I could not read a line in '" << path << "' at position " << whereAmI << ".";
232 0 : throw SDMDataObjectStreamReaderException(oss.str());
233 0 : }
234 : // cout << "nextLine has read '" << currentLine << "'" << endl;
235 0 : return currentLine;
236 : }
237 :
238 0 : pair<string, string> SDMDataObjectStreamReader::headerField2Pair(const string& hf){
239 0 : string name, value;
240 0 : size_t colonIndex = hf.find(":");
241 0 : if (colonIndex == string::npos)
242 0 : throw SDMDataObjectStreamReaderException(" could not detect a well formed MIME header field in '"+hf+"'");
243 :
244 0 : if (colonIndex > 0) {
245 0 : name = hf.substr(0, colonIndex);
246 : #ifndef WITHOUT_BOOST
247 : boost::algorithm::trim(name);
248 : #else
249 0 : asdm::trim(name);
250 : #endif
251 : }
252 :
253 0 : if (colonIndex < hf.size()) {
254 0 : value = hf.substr(colonIndex+1);
255 : #ifndef WITHOUT_BOOST
256 : boost::algorithm::trim(value);
257 : #else
258 0 : asdm::trim(value);
259 : #endif
260 : }
261 :
262 0 : return make_pair(name, value);
263 0 : }
264 :
265 0 : pair<string, string> SDMDataObjectStreamReader::requireHeaderField(const string & hf) {
266 0 : pair<string, string> hf2pair(headerField2Pair(nextLine()));
267 : // cout << hf2pair.first << ", " << hf2pair.second << endl;
268 : #ifndef WITHOUT_BOOST
269 : if (boost::algorithm::to_upper_copy(hf2pair.first) != hf)
270 : throw SDMDataObjectStreamReaderException("read '" + currentLine + "'. Was expecting '" + hf + "'...");
271 : #else
272 0 : if (asdm::str_toupper(hf2pair.first) != hf)
273 0 : throw SDMDataObjectStreamReaderException("read '" + currentLine + "'. Was expecting '" + hf + "'...");
274 : #endif
275 0 : return hf2pair;
276 0 : }
277 :
278 0 : string unquote(const string& s, string& unquoted) {
279 0 : if (s.size() >= 2)
280 0 : if (((s.at(0) == '"') && (s.at(s.size()-1) == '"')) || ((s.at(0) == '\'') && (s.at(s.size()-1) == '\''))) {
281 0 : if (s.size() == 2)
282 0 : unquoted = "";
283 : else
284 0 : unquoted = s.substr(1, s.size() - 2);
285 : }
286 : else
287 0 : unquoted = s;
288 : else
289 0 : unquoted = s;
290 0 : return unquoted;
291 : }
292 :
293 :
294 :
295 0 : string SDMDataObjectStreamReader::requireBoundaryInCT(const string& ctValue) {
296 0 : vector<string> cvValueItems;
297 :
298 : #ifndef WITHOUT_BOOST
299 : boost::algorithm::split (cvValueItems, ctValue, boost::algorithm::is_any_of(";"));
300 : vector<string> cvValueItemsNameValue;
301 : for ( vector<string>::const_iterator iter = cvValueItems.begin(); iter != cvValueItems.end() ; iter++ ) {
302 : cvValueItemsNameValue.clear();
303 : boost::algorithm::split(cvValueItemsNameValue, *iter, boost::algorithm::is_any_of("="));
304 : string boundary;
305 : if ((cvValueItemsNameValue.size() > 1) && (boost::algorithm::to_upper_copy(boost::algorithm::trim_copy(cvValueItemsNameValue[0])) == "BOUNDARY") && (unquote(cvValueItemsNameValue[1], boundary).size() > 0))
306 : return boundary;
307 : }
308 : #else
309 0 : asdm::strsplit (ctValue, ';', cvValueItems);
310 0 : vector<string> cvValueItemsNameValue;
311 0 : for ( vector<string>::const_iterator iter = cvValueItems.begin(); iter != cvValueItems.end() ; iter++ ) {
312 0 : cvValueItemsNameValue.clear();
313 0 : asdm::strsplit(*iter,'=',cvValueItemsNameValue);
314 0 : string boundary;
315 0 : if ((cvValueItemsNameValue.size() > 1) && (asdm::str_toupper(asdm::trim_copy(cvValueItemsNameValue[0])) == "BOUNDARY") && (unquote(cvValueItemsNameValue[1], boundary).size() > 0))
316 0 : return boundary;
317 0 : }
318 : #endif
319 0 : throw SDMDataObjectStreamReaderException("could not find a boundary definition in '" + ctValue + "'.");
320 0 : }
321 :
322 0 : void SDMDataObjectStreamReader::skipAsLongAsLineStartsWith(const string& start) {
323 0 : int64_t curpos = 0;
324 : do {
325 0 : curpos = position();
326 0 : nextLine();
327 : }
328 0 : while (currentLine.find(start) == 0);
329 0 : position(curpos);
330 0 : return;
331 : }
332 :
333 0 : void SDMDataObjectStreamReader::skipUntilEmptyLine(int maxSkips) {
334 : // cout << "Entering skipUntilEmptyLine" << endl;
335 0 : int numSkips = 0;
336 0 : string line = nextLine();
337 0 : while ((line.size() != 0) && (numSkips <= maxSkips)) {
338 0 : line = nextLine();
339 0 : numSkips += 1;
340 : }
341 :
342 0 : if (numSkips > maxSkips) {
343 0 : ostringstream oss;
344 0 : oss << "could not find an empty line is less than " << maxSkips + 1 << " lines." << endl;
345 0 : throw SDMDataObjectStreamReaderException(oss.str());
346 0 : }
347 : // cout << "Exiting skipUntilEmptyLine" << endl;
348 0 : }
349 :
350 :
351 0 : string SDMDataObjectStreamReader::requireMIMEHeader() {
352 : // MIME-Version
353 0 : pair<string, string>name_value(headerField2Pair(nextLine()));
354 : // cout << name_value.first << "=" << name_value.second << endl;
355 : // if (currentLine != "MIME-Version: 1.0") // a work around for the case when the very first character is not the expected "M" (happened with some corrupted data).
356 : #ifndef WITHOUT_BOOST
357 : if (! boost::algorithm::iends_with(currentLine, "IME-Version: 1.0"))
358 : #else
359 0 : std::string versionEnd = "IME-Version: 1.0";
360 0 : if ((currentLine.size()<=versionEnd.size()) || (currentLine.compare((currentLine.size()-versionEnd.size()),versionEnd.size(),versionEnd)!=0))
361 : #endif
362 0 : throw SDMDataObjectStreamReaderException("'MIME-Version: 1.0' missing at the very beginning of the file '"+path+"'.");
363 :
364 : // Content-Type
365 0 : boundary_1 = requireBoundaryInCT(requireHeaderField("CONTENT-TYPE").second);
366 :
367 : // cout << "boundary_1 =" << boundary_1 << endl;
368 :
369 : // Content-Description
370 0 : name_value = requireHeaderField("CONTENT-DESCRIPTION");
371 :
372 : // Content-Location
373 0 : name_value = requireHeaderField("CONTENT-LOCATION");
374 :
375 : // Look for an empty line in the at most 10 subsequent lines.
376 0 : skipUntilEmptyLine(10);
377 :
378 0 : return boundary_1;
379 0 : }
380 :
381 0 : string SDMDataObjectStreamReader::accumulateUntilBoundary(const string& boundary, int maxLines) {
382 : // cout << "Entering accumulateUntilBoundary with maxLines = " << maxLines << endl;
383 0 : int numLines = 0;
384 0 : string line = nextLine();
385 0 : string result;
386 0 : while ((numLines <= maxLines) && (line.find("--"+boundary) == string::npos)) {
387 0 : result += line;
388 0 : numLines++;
389 0 : line = nextLine();
390 : }
391 :
392 0 : if (numLines > maxLines) {
393 0 : ostringstream oss;
394 0 : oss << "could not find the boundary string '"<< boundary << "' in less than " << maxLines + 1 << " lines." << endl;
395 0 : throw SDMDataObjectStreamReaderException(oss.str());
396 0 : }
397 :
398 0 : return result;
399 0 : }
400 :
401 0 : void SDMDataObjectStreamReader::requireBoundary(const string& boundary, int maxLines) {
402 : // cout << "Entering require boundary with boundary == '" << boundary << "' and maxLines = " << maxLines << endl;
403 0 : int numLines = 0;
404 0 : string dashdashBoundary = "--"+boundary;
405 0 : string line = nextLine();
406 0 : while ((numLines <= maxLines) && (line.compare(dashdashBoundary) != 0)) {
407 0 : numLines++;
408 0 : line = nextLine();
409 : }
410 :
411 0 : if (numLines > maxLines) {
412 0 : ostringstream oss;
413 0 : oss << "could not find the boundary string '"<< boundary << "' in less than " << maxLines + 1 << " lines." << endl;
414 0 : throw SDMDataObjectStreamReaderException(oss.str());
415 0 : }
416 0 : }
417 :
418 0 : void SDMDataObjectStreamReader::lookForBinaryPartSize(xmlNode* aNode) {
419 : #ifndef WITHOUT_BOOST
420 : const boost::regex UINT("[0-9]+");
421 : #else
422 0 : const std::regex UINT("[0-9]+");
423 : #endif
424 0 : xmlNode *curNode = NULL;
425 :
426 0 : for (curNode = aNode; curNode ; curNode = curNode->next) {
427 0 : if (curNode->type == XML_ELEMENT_NODE) {
428 0 : if (s_partNames.find(string((char *)curNode->name)) != s_partNames.end()){
429 0 : if (xmlHasProp(curNode, (const xmlChar*) "size")) {
430 0 : xmlChar * value = xmlGetProp(curNode, (const xmlChar *) "size");
431 : #ifndef WITHOUT_BOOST
432 : boost::cmatch what;
433 : if (boost::regex_match((char*) value, what, UINT)) {
434 : #else
435 0 : std::cmatch what;
436 0 : if (std::regex_match((char*) value, what, UINT)) {
437 : #endif
438 0 : int64_t result = ::atoi(what[0].first);
439 0 : xmlFree(value);
440 0 : binaryPartSize[string((char *) curNode->name)] = result;
441 : }
442 : else {
443 0 : xmlFree(value);
444 0 : throw SDMDataObjectStreamReaderException("In '" + string((const char*) curNode->name) + "' failed to parse the value of '"+string((const char*) value)+"' as an int.");
445 : }
446 0 : }
447 : else {
448 0 : throw SDMDataObjectStreamReaderException("In '" + string((const char*) curNode->name) + "' could not find the attribute 'size'.");
449 : }
450 : }
451 : }
452 0 : lookForBinaryPartSize(curNode->children);
453 : }
454 0 : }
455 :
456 0 : string SDMDataObjectStreamReader::requireCrossDataType(xmlNode* parent) {
457 0 : string result;
458 :
459 0 : string comparee("crossData");
460 0 : xmlNode * child = parent->children;
461 :
462 0 : while ((child != 0) && (comparee.compare((const char*) child->name) != 0))
463 0 : child = child->next;
464 :
465 0 : if ((child == 0) || (child->type != XML_ELEMENT_NODE)) {
466 0 : ostringstream oss;
467 0 : oss << "could not find the element 'crossData'." << endl;
468 0 : throw SDMDataObjectStreamReaderException(oss.str());
469 0 : }
470 :
471 0 : if (xmlHasProp(child, (const xmlChar*) "type")) {
472 0 : xmlChar * value = xmlGetProp(child, (const xmlChar *) "type");
473 0 : result = string((const char *) value);
474 0 : xmlFree(value);
475 0 : return result;
476 : }
477 : else
478 0 : throw SDMDataObjectStreamReaderException("In '" + string((const char*) child->name) + "' could not find the attribute 'type'.");
479 0 : }
480 :
481 0 : void SDMDataObjectStreamReader::printElementNames(xmlNode * a_node) {
482 0 : xmlNode *cur_node = NULL;
483 :
484 0 : for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
485 0 : if (cur_node->type == XML_ELEMENT_NODE) {
486 0 : cout << "node type: Element, name: " << cur_node->name << endl;
487 : }
488 0 : printElementNames(cur_node->children);
489 : }
490 0 : }
491 :
492 0 : void SDMDataObjectStreamReader::requireSDMDataHeaderMIMEPart() {
493 : //
494 : // Requires the presense of boundary_1
495 0 : requireBoundary(boundary_1, 0);
496 :
497 : // Ignore header fields
498 : // requireHeaderField("CONTENT-TYPE")
499 : // requireHeaderField("CONTENT-TRANSFER-ENCODING")
500 : // requireHeaderField("CONTENT-LOCATION")
501 :
502 : //
503 : // Look for an empty line at most distant from 100 lines from here.
504 0 : skipUntilEmptyLine(10);
505 0 : string sdmDataHeader = accumulateUntilBoundary(boundary_1, 100);
506 :
507 : /*
508 : xmlDoc * doc = xmlReadMemory(sdmDataHeader.data(), sdmDataHeader.size(), "SDMDataHeader.xml", NULL, XML_PARSE_NOBLANKS);
509 : xmlChar* xmlBuff;
510 : int bufferSize;
511 : xmlDocDumpFormatMemory(doc, &xmlBuff, &bufferSize, 1);
512 : cout << string((const char*) xmlBuff, bufferSize) << endl;
513 : xmlFree(xmlBuff);
514 : xmlNode* root_element = xmlDocGetRootElement(doc);
515 : if ( root_element == NULL || root_element->type != XML_ELEMENT_NODE )
516 : throw SDMDataObjectStreamReaderException("Failed to parse the SDMDataHeader into a DOM structure.");
517 : */
518 :
519 0 : parser.parseMemoryHeader(sdmDataHeader, sdmDataObject);
520 : unsigned int bps;
521 0 : if ((bps = sdmDataObject.dataStruct().flags().size()))
522 0 : binaryPartSize["flags"] = bps;
523 :
524 0 : if ((bps = sdmDataObject.dataStruct().actualTimes().size()))
525 0 : binaryPartSize["actualTimes"] = bps;
526 :
527 0 : if ((bps = sdmDataObject.dataStruct().actualDurations().size()))
528 0 : binaryPartSize["actualDurations"] = bps;
529 :
530 0 : if ((bps = sdmDataObject.dataStruct().zeroLags().size()))
531 0 : binaryPartSize["zeroLags"] = bps;
532 :
533 0 : if ((bps = sdmDataObject.dataStruct().autoData().size()))
534 0 : binaryPartSize["autoData"] = bps;
535 :
536 0 : if ((bps = sdmDataObject.dataStruct().crossData().size()))
537 0 : binaryPartSize["crossData"] = bps;
538 0 : }
539 :
540 0 : void SDMDataObjectStreamReader::requireSDMDataSubsetMIMEPart(SDMDataSubset & sdmDataSubset) {
541 0 : integrationStartsAt = f.tellg();
542 :
543 0 : skipAsLongAsLineStartsWith("--"+boundary_1); // <--- this was added to preserve compatiblity with SDMDataObjectReader, which
544 : // was less strict on the respect of the BDF specifications. (cf CAS-8151)
545 : // Here the problem was caused by two successive occurrences of --MIME_boundary_1
546 : // instead of only one as indicated in the specs at the very beginning of
547 : // an SDMDataSubsetHeader. M.Caillat - 4 decembre 2015
548 0 : pair<string, string> name_value = requireHeaderField("CONTENT-TYPE");
549 0 : boundary_2 = requireBoundaryInCT(name_value.second);
550 : // cout << "boundary_2 = " << boundary_2 << endl;
551 0 : name_value = requireHeaderField("CONTENT-DESCRIPTION");
552 0 : requireBoundary(boundary_2, 10);
553 0 : skipUntilEmptyLine(10);
554 :
555 : //
556 : // We assume that the subset header can't be longer than 100 lines.
557 : //
558 0 : string sdmDataSubsetHeader = accumulateUntilBoundary(boundary_2, 100);
559 :
560 : //
561 : // Empty sdmDataSubset if necessary.
562 : //
563 0 : releaseMemory(sdmDataSubset);
564 :
565 : // We can start to acquire a new SDMDataSubset.
566 0 : if (sdmDataObject.isCorrelation())
567 0 : parser.parseMemoryCorrSubsetHeader(sdmDataSubsetHeader, sdmDataSubset);
568 : else
569 0 : parser.parseMemoryTPSubsetHeader(sdmDataSubsetHeader, sdmDataSubset);
570 :
571 0 : attachmentFlags.reset();
572 : #ifndef WITHOUT_BOOST
573 : boost::regex BINARYPARTLOC("([0-9]+/)+(actualDurations|actualTimes|autoData|crossData|zeroLags|flags)\\.bin");
574 : #else
575 0 : std::regex BINARYPARTLOC("([0-9]+/)+(actualDurations|actualTimes|autoData|crossData|zeroLags|flags)\\.bin");
576 : #endif
577 0 : bool done = false;
578 0 : while (!done) {
579 0 : name_value = requireHeaderField("CONTENT-TYPE");
580 0 : name_value = requireHeaderField("CONTENT-LOCATION");
581 :
582 : #ifndef WITHOUT_BOOST
583 : boost::smatch what;
584 : const string contentLocation = boost::algorithm::trim_copy(name_value.second);
585 : if (!boost::regex_search(contentLocation, what, BINARYPARTLOC)) {
586 : throw SDMDataObjectStreamReaderException("Invalid field : '" + name_value.first + ":" + name_value.second + "'.");
587 : }
588 : #else
589 0 : std::smatch what;
590 0 : const string contentLocation = asdm::trim_copy(name_value.second);
591 0 : if (!std::regex_search(contentLocation, what, BINARYPARTLOC)) {
592 0 : throw SDMDataObjectStreamReaderException("Invalid field : '" + name_value.first + ":" + name_value.second + "'.");
593 : }
594 : #endif
595 : // cout << "Binary part name = " << what[2] << "...";
596 0 : string binaryPartName = string(what[2]);
597 0 : if (binaryPartSize.find(binaryPartName) == binaryPartSize.end())
598 0 : throw SDMDataObjectStreamReaderException("The size of '"+binaryPartName+"' was not announced in the data header.!");
599 :
600 0 : if (binaryPartSize[binaryPartName] == 0)
601 0 : throw SDMDataObjectStreamReaderException("The size of '"+binaryPartName+"' was announced as null. I was not expecting a '"+binaryPartName+"' attachment here.");
602 :
603 0 : skipUntilEmptyLine(10);
604 0 : int numberOfCharsPerValue = 0;
605 0 : char** binaryPartPtrPtr = 0;
606 0 : if (binaryPartName == "actualDurations") {
607 0 : attachmentFlags.set(ACTUALDURATIONS);
608 0 : binaryPartPtrPtr = (char**) &sdmDataSubset.actualDurations_;
609 0 : sdmDataSubset.nActualDurations_ = binaryPartSize[binaryPartName];
610 0 : sdmDataSubset.actualDurationsPosition_ = f.tellg();
611 0 : numberOfCharsPerValue = 8;
612 : }
613 0 : else if (binaryPartName == "actualTimes") {
614 0 : attachmentFlags.set(ACTUALTIMES);
615 0 : binaryPartPtrPtr = (char **) &sdmDataSubset.actualTimes_;
616 0 : sdmDataSubset.nActualTimes_ = binaryPartSize[binaryPartName];
617 0 : sdmDataSubset.actualTimesPosition_ = f.tellg();
618 0 : numberOfCharsPerValue = 8;
619 : }
620 0 : else if (binaryPartName == "autoData") {
621 0 : attachmentFlags.set(AUTODATA);
622 0 : binaryPartPtrPtr = (char **) &sdmDataSubset.autoData_;
623 0 : sdmDataSubset.nAutoData_ = binaryPartSize[binaryPartName];
624 0 : sdmDataSubset.autoDataPosition_ = f.tellg();
625 0 : numberOfCharsPerValue = 4;
626 : }
627 0 : else if (binaryPartName == "crossData") {
628 0 : attachmentFlags.set(CROSSDATA);
629 0 : sdmDataSubset.shortCrossData_ = 0;
630 0 : sdmDataSubset.longCrossData_ = 0;
631 0 : sdmDataSubset.floatCrossData_ = 0;
632 0 : sdmDataSubset.nCrossData_ = binaryPartSize[binaryPartName];
633 0 : sdmDataSubset.crossDataPosition_ = f.tellg();
634 0 : PrimitiveDataType pdt = sdmDataSubset.crossDataType();
635 0 : switch (pdt) {
636 0 : case INT16_TYPE:
637 0 : binaryPartPtrPtr = (char **) &sdmDataSubset.shortCrossData_;
638 0 : numberOfCharsPerValue = 2;
639 0 : break;
640 0 : case INT32_TYPE:
641 0 : binaryPartPtrPtr = (char **) &sdmDataSubset.longCrossData_;
642 0 : numberOfCharsPerValue = 4;
643 0 : break;
644 0 : case FLOAT32_TYPE:
645 0 : binaryPartPtrPtr = (char **) &sdmDataSubset.floatCrossData_;
646 0 : numberOfCharsPerValue = 4;
647 0 : break;
648 0 : default:
649 0 : throw SDMDataObjectStreamReaderException("Invalid data type for cross data '" + CPrimitiveDataType::name(pdt) + "'.");
650 : }
651 : }
652 0 : else if (binaryPartName == "flags") {
653 0 : attachmentFlags.set(FLAGS);
654 0 : binaryPartPtrPtr = (char **) &sdmDataSubset.flags_;
655 0 : sdmDataSubset.nFlags_ = binaryPartSize[binaryPartName];
656 0 : sdmDataSubset.flagsPosition_ = f.tellg();
657 0 : numberOfCharsPerValue = 4;
658 : }
659 0 : else if (binaryPartName == "zeroLags") {
660 0 : attachmentFlags.set(ZEROLAGS);
661 0 : binaryPartPtrPtr = (char **) &sdmDataSubset.zeroLags_;
662 0 : sdmDataSubset.nZeroLags_ = binaryPartSize[binaryPartName];
663 0 : sdmDataSubset.zeroLagsPosition_ = f.tellg();
664 0 : numberOfCharsPerValue = 4;
665 : }
666 :
667 0 : int64_t numberOfCharsToRead = numberOfCharsPerValue * binaryPartSize[binaryPartName];
668 0 : *binaryPartPtrPtr = new char[numberOfCharsToRead * sizeof(char)];
669 0 : if (*binaryPartPtrPtr == 0) {
670 0 : ostringstream oss;
671 0 : oss << "Processing integration # " << integrationIndex << ": I could not get memory to store '" << binaryPartName << "'." << endl;
672 0 : throw SDMDataObjectStreamReaderException(oss.str());
673 0 : }
674 :
675 0 : f.read(*binaryPartPtrPtr, numberOfCharsToRead * sizeof(char));
676 0 : if (f.fail()) {
677 0 : ostringstream oss;
678 0 : oss << "Processing integration # " << integrationIndex << ": a problem occurred while reading '" << binaryPartName << "'." << endl;
679 0 : throw SDMDataObjectStreamReaderException(oss.str());
680 0 : }
681 0 : if (f.eof()) {
682 0 : ostringstream oss;
683 0 : oss << "Processing integration # " << integrationIndex << ": a unexpected end of file occurred while reading '" << binaryPartName << "'." << endl;
684 0 : throw SDMDataObjectStreamReaderException(oss.str());
685 0 : }
686 :
687 0 : string line = nextLine(); // Absorb the nl right after the last byte of the binary attachment
688 0 : line = nextLine(); // This should boundary_2
689 :
690 0 : if (line.find("--" + boundary_2) != 0) {
691 0 : ostringstream oss;
692 0 : oss << "Processing integration # " << integrationIndex << ": unexpected '" << line << "' after the binary part '" << binaryPartName << "'." << endl;
693 0 : throw SDMDataObjectStreamReaderException(oss.str());
694 0 : }
695 :
696 0 : done = line.compare("--" + boundary_2+"--") == 0;
697 0 : }
698 :
699 : // Now check if the binary attachments found are compatible with the correlation mode
700 : // and if their sizes are equal to what is announced in the global header.
701 : //
702 : // The presence of crossData and autoData depends on the correlation mode.
703 :
704 0 : switch (sdmDataObject.correlationMode()) {
705 0 : case CROSS_ONLY:
706 0 : if (!attachmentFlags.test(CROSSDATA)) {
707 0 : ostringstream oss;
708 0 : oss << "Data subset '"<<sdmDataSubset.projectPath()<<"': ";
709 0 : oss << "a binary attachment 'crossData' was expected in integration #" << integrationIndex;
710 0 : throw SDMDataObjectStreamReaderException(oss.str());
711 0 : }
712 :
713 0 : if (attachmentFlags.test(AUTODATA)) {
714 0 : ostringstream oss;
715 0 : oss << "Data subset '"<<sdmDataSubset.projectPath()<<"': ";
716 0 : oss << "found an unexpected attachment 'autoData' in integration #" << integrationIndex << ".";
717 0 : throw SDMDataObjectStreamReaderException(oss.str());
718 0 : }
719 0 : break;
720 :
721 0 : case AUTO_ONLY:
722 0 : if (!attachmentFlags.test(AUTODATA)) {
723 0 : ostringstream oss;
724 0 : oss << "Data subset '"<<sdmDataSubset.projectPath()<<"': ";
725 0 : oss << "a binary attachment 'autoData' was expected.in integration #" << integrationIndex << ".";
726 0 : throw SDMDataObjectStreamReaderException(oss.str());
727 0 : }
728 :
729 0 : if (attachmentFlags.test(CROSSDATA)) {
730 0 : ostringstream oss;
731 0 : oss << "Data subset '"<<sdmDataSubset.projectPath()<<"': ";
732 0 : oss << "found an unexpected attachment 'crossData' in integration #" << integrationIndex << ".";
733 0 : throw SDMDataObjectStreamReaderException(oss.str());
734 0 : }
735 0 : break;
736 :
737 0 : case CROSS_AND_AUTO:
738 0 : if (!attachmentFlags.test(AUTODATA)) {
739 0 : ostringstream oss;
740 0 : oss << "Data subset '"<<sdmDataSubset.projectPath()<<"': ";
741 0 : oss << "a binary attachment 'autoData' was expected in integration #" << integrationIndex << ".";
742 0 : throw SDMDataObjectStreamReaderException(oss.str());
743 0 : }
744 :
745 0 : if (!attachmentFlags.test(CROSSDATA)) {
746 0 : ostringstream oss;
747 0 : oss << "Data subset '"<<sdmDataSubset.projectPath()<<"': ";
748 0 : oss << "a binary attachment 'crossData' was expected in integration #" << integrationIndex << ".";
749 0 : throw SDMDataObjectStreamReaderException(oss.str());
750 0 : }
751 0 : break;
752 :
753 0 : default:
754 0 : throw SDMDataObjectStreamReaderException("Data subset '"+sdmDataSubset.projectPath()+"': unrecognized correlation mode");
755 : break;
756 : }
757 :
758 :
759 0 : if (attachmentFlags.test(ZEROLAGS)) {
760 : // Refuse the zeroLags attachment if it's not a Correlator or if the correlator is a CORRELATOR_FX (ACA).
761 0 : if ((sdmDataObject.processorType_ != CORRELATOR) || (sdmDataObject.correlatorType() == FX))
762 0 : throw SDMDataObjectStreamReaderException("zeroLags are not expected from a correlator CORRELATOR_FX");
763 : }
764 0 : }
765 :
766 0 : void SDMDataObjectStreamReader::releaseMemory(SDMDataSubset & sdmDataSubset) {
767 : // cout << "SDMDataObjectStreamReader::releaseMemory : entering." << endl;
768 0 : if (sdmDataSubset.actualTimes_ != 0) {
769 : // cout << "actualTimes" << endl;
770 0 : delete[] sdmDataSubset.actualTimes_;
771 0 : sdmDataSubset.actualTimes_ = 0;
772 : }
773 0 : sdmDataSubset.nActualTimes_ = 0;
774 :
775 :
776 0 : if (sdmDataSubset.actualDurations_ != 0) {
777 : // cout << "actualDurations" << endl;
778 0 : delete[] sdmDataSubset.actualDurations_;
779 0 : sdmDataSubset.actualDurations_ = 0;
780 : }
781 0 : sdmDataSubset.nActualDurations_ = 0;
782 :
783 0 : if (sdmDataSubset.flags_ != 0) {
784 : // cout << "Flags" << endl;
785 0 : delete[] sdmDataSubset.flags_;
786 0 : sdmDataSubset.flags_ = 0;
787 : }
788 0 : sdmDataSubset.nFlags_ = 0;
789 :
790 0 : if (sdmDataSubset.zeroLags_ != 0) {
791 : // cout << "zeroLags" << endl;
792 0 : delete[] sdmDataSubset.zeroLags_;
793 0 : sdmDataSubset.zeroLags_ = 0;
794 : }
795 0 : sdmDataSubset.nZeroLags_ = 0;
796 :
797 0 : if (sdmDataSubset.autoData_ != 0) {
798 : //cout << "autoData_ = " << sdmDataSubset.autoData_ << " before deletion" << endl;
799 0 : delete[] sdmDataSubset.autoData_;
800 0 : sdmDataSubset.autoData_ = 0;
801 : }
802 0 : sdmDataSubset.nAutoData_ = 0;
803 :
804 0 : if (sdmDataSubset.shortCrossData_ != 0) {
805 : //cout << "shortCrossData_ = " << sdmDataSubset.shortCrossData_ << " before deletion" << endl;
806 0 : delete[] sdmDataSubset.shortCrossData_;
807 0 : sdmDataSubset.shortCrossData_ = 0;
808 : }
809 :
810 0 : if (sdmDataSubset.longCrossData_ != 0) {
811 : // cout << "longCrossData" << endl;
812 0 : delete[] sdmDataSubset.longCrossData_;
813 0 : sdmDataSubset.longCrossData_ = 0;
814 : }
815 :
816 0 : if (sdmDataSubset.floatCrossData_ != 0) {
817 : // cout << "floatCrossData" << endl;
818 0 : delete[] sdmDataSubset.floatCrossData_;
819 0 : sdmDataSubset.floatCrossData_ = 0;
820 : }
821 0 : sdmDataSubset.nCrossData_ = 0;
822 :
823 : // cout << "SDMDataObjectStreamReader::releaseMemory : exiting." << endl;
824 0 : return;
825 : }
826 : } // end namespace asdmbinaries
827 :
828 : using namespace asdmbinaries;
829 :
830 : #ifdef TEST_CLASS
831 : int main (int argC, char* argV[]) {
832 : if (argC < 2) {
833 : cout << "a.out filename" << endl;
834 : exit(1);
835 : }
836 :
837 : SDMDataObjectStreamReader ssr;
838 : try {
839 : ssr.open(argV[1]);
840 : cout << ssr.toString() << endl;
841 : while (ssr.hasSubset()) {
842 : const SDMDataSubset & sdmdss = ssr.getSubset();
843 : cout << "block of data #" << ssr.currentIntegrationIndex() << " starting at byte #" << ssr.currentIntegrationStartsAt() << endl;
844 : cout << sdmdss.toString(128) << endl;
845 : }
846 : }
847 : catch (SDMDataObjectStreamReaderException& e) {
848 : cout << e.getMessage() << endl;
849 : }
850 : catch (SDMDataObjectParserException& e) {
851 : cout << e.getMessage() << endl;
852 : }
853 : catch (SDMDataObjectException& e) {
854 : cout << e.getMessage() << endl;
855 : }
856 : }
857 : #endif
|