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