LCOV - code coverage report
Current view: top level - alma/ASDMBinaries - SDMDataObjectReader.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 11 516 2.1 %
Date: 2025-12-12 07:32:35 Functions: 1 26 3.8 %

          Line data    Source code
       1             : #include <alma/ASDMBinaries/SDMDataObjectReader.h>
       2             : 
       3             : #include <iostream>
       4             : #include <iomanip>
       5             : #include <unistd.h>
       6             : #include <sys/types.h>
       7             : #include <sys/mman.h>
       8             : #include <fcntl.h>
       9             : #include <sys/stat.h>
      10             : #include <errno.h>
      11             : #include <exception>
      12             : #include <sstream>
      13             : #include <cstring>
      14             : 
      15             : #include <alma/ASDMBinaries/CommonDefines.h>
      16             : 
      17             : #if defined( __APPLE__ )
      18             :    #include <AvailabilityMacros.h>
      19             : // 10.5 defines stat64 but Tiger does NOT
      20             :    #if defined(MAC_OS_X_VERSION_10_4) && ! defined(MAC_OS_X_VERSION_10_5)
      21             :       #define  stat64  stat
      22             :       #define fstat64 fstat
      23             :    #endif
      24             : #endif
      25             : 
      26             : using namespace CorrelationModeMod;
      27             : using namespace CorrelatorTypeMod;
      28             : using namespace PrimitiveDataTypeMod;
      29             : using namespace ProcessorTypeMod;
      30             : 
      31             : using namespace std;
      32             : 
      33             : namespace asdmbinaries {
      34             : 
      35             :   const string SDMDataObjectReader::MIMEBOUNDARY_1  = $MIMEBOUNDARY1;
      36             :   const string SDMDataObjectReader::MIMEBOUNDARY_2  = $MIMEBOUNDARY2;
      37             : 
      38             :   const std::regex SDMDataObjectReader::CONTENTIDBINREGEXP(" <([a-zA-Z]+)_([_0-9]+)\\.bin>");
      39             :   const std::regex SDMDataObjectReader::CONTENTIDBINREGEXP1(" <([a-zA-Z]+)_([0-9]+)\\.bin>");
      40             :   const std::regex SDMDataObjectReader::CONTENTIDBINREGEXP2(" <([a-zA-Z]+)_([0-9]+)_([0-9]+)\\.bin>");
      41             :   //  const std::regex SDMDataObjectReader::CONTENTIDSUBSETREGEXP(" <(Subset)_([0-9]+)\\.xml>");
      42             :   const std::regex SDMDataObjectReader::CONTENTIDSUBSETREGEXP(" <(Subset)_([0-9]+)(_[0-9]+)?\\.xml>");
      43             :   const std::regex SDMDataObjectReader::CONTENTIDDATASTRUCTUREREGEXP(" <DataStructure.xml>");
      44             :   set<string> SDMDataObjectReader::BINATTACHNAMES;
      45             :   map<string, SDMDataObjectReader::BINATTACHCODES> SDMDataObjectReader::name2code;
      46             :   const bool SDMDataObjectReader::initClass_ = SDMDataObjectReader::initClass();
      47             : 
      48             :   // SDMDataObjectReader:: methods
      49             :   //
      50           0 :   SDMDataObjectReader::SDMDataObjectReader() {
      51           0 :     init();
      52           0 :   }
      53             : 
      54           0 :   SDMDataObjectReader::~SDMDataObjectReader() {
      55           0 :     done();
      56           0 :   }
      57             : 
      58          12 :   bool SDMDataObjectReader::initClass() {
      59          12 :     char* binAttachNamesC[] = {(char *) "actualDurations", (char *) "actualTimes", (char *) "autoData", (char *) "flags", (char *) "crossData", (char *) "zeroLags", 0};
      60          84 :     for (int i = 0; binAttachNamesC[i]; i++) {
      61          72 :       BINATTACHNAMES.insert(string(binAttachNamesC[i]));
      62             :     }
      63             : 
      64          12 :     name2code["actualDurations"] = ACTUALDURATIONS;
      65          12 :     name2code["actualTimes"]     = ACTUALTIMES;
      66          12 :     name2code["autoData"]        = AUTODATA;
      67          12 :     name2code["flags"]           = FLAGS;
      68          12 :     name2code["crossData"]       = CROSSDATA;
      69          12 :     name2code["zeroLags"]        = ZEROLAGS;
      70             : 
      71          12 :     return true;
      72             :   }
      73             : 
      74           0 :   void SDMDataObjectReader::init() {
      75           0 :     filedes_ = 0;
      76           0 :     data_ = (char *) 0;
      77           0 :     position_ = 0;
      78           0 :     lastPosition_ = 0;
      79           0 :     endPosition_ = 0;
      80             :     
      81           0 :     read_ = UNKNOWN_;
      82             : 
      83           0 :     integrationNum_ = 0;
      84           0 :   }
      85             : 
      86           0 :   string::size_type SDMDataObjectReader::find(const string& s) {
      87             : 
      88             :     while (true) {
      89           0 :       while ((position_ < endPosition_) && (data_[position_++] != s.at(0))) {;}
      90             :       
      91           0 :       if (position_ == endPosition_) return string::npos;
      92             : 
      93           0 :       string::size_type lastPosition_ = position_;      
      94           0 :       unsigned long long int i = 1;
      95             : 
      96           0 :       while ((position_ < endPosition_) && (i < s.length())) {
      97           0 :         if (s.at(i) != data_[position_]) break;
      98           0 :         i++;
      99           0 :         position_++;
     100             :       }
     101             :       
     102           0 :       if (i == s.length()) return (position_ - s.length());
     103             :       
     104           0 :       if (position_ == endPosition_) return string::npos;
     105             :       
     106           0 :       position_ = lastPosition_; //+1;
     107           0 :     }
     108             :   }
     109             :     
     110           0 :   bool SDMDataObjectReader::compare(const string& s) {
     111           0 :     string::size_type index = position_;
     112             : 
     113           0 :     unsigned int i = 0;
     114           0 :     while ((index < endPosition_) && (i < s.length()) && (s.at(i++) == data_[index++])) {
     115             :       ;
     116             :     }
     117           0 :     return (i == s.length());
     118             :   }
     119             : 
     120           0 :   bool SDMDataObjectReader::EOD() {
     121           0 :     return position_ >= endPosition_;
     122             :   }
     123             : 
     124             : 
     125           0 :   string SDMDataObjectReader::extractXMLHeader(const string& boundary) {
     126             :     // cout << "Entering extractXMLHeader"  << endl;
     127             : 
     128           0 :     string boundary_ = "\n--"+boundary;
     129             : 
     130           0 :     unsigned long int positionBeg = 0;
     131           0 :     unsigned long int positionEnd = 0;
     132             : 
     133             :     // We assume that we are at the first character of the body.
     134           0 :     positionBeg = position_;
     135             : 
     136             :     // Look for the next boundary supposed to be found right after an the XML header. 
     137           0 :     if ( (positionEnd = find(boundary_)) == string::npos) {
     138           0 :       ostringstream eos;
     139           0 :       eos << "A second MIME boundary '" << boundary <<"' could not be found in the MIME message after position " << positionBeg << ".";      
     140           0 :       throw SDMDataObjectReaderException(eos.str());      
     141           0 :     }
     142             : 
     143           0 :     string xmlPart = string(data_+positionBeg, positionEnd-positionBeg);
     144             :   
     145             :     // cout << "Found XML Header : " << xmlPart << endl;
     146             :     // cout << "Exiting extractXMLHeader"  << endl;
     147             : 
     148           0 :     return xmlPart;
     149           0 :   }
     150             : 
     151             : 
     152           0 :   void SDMDataObjectReader::tokenize(const string& str,
     153             :                                      vector<string>& tokens,
     154             :                                      const string& delimiters) {
     155             :     // Skip delimiters at beginning.
     156           0 :     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
     157             :     // Find first "non-delimiter".
     158           0 :     string::size_type pos     = str.find_first_of(delimiters, lastPos);
     159             :     
     160           0 :     while (string::npos != pos || string::npos != lastPos) {
     161             :       // Found a token, add it to the vector.
     162           0 :       tokens.push_back(str.substr(lastPos, pos - lastPos));
     163             :       // Skip delimiters.  Note the "not_of"
     164           0 :       lastPos = str.find_first_not_of(delimiters, pos);
     165             :       // Find next "non-delimiter"
     166           0 :       pos = str.find_first_of(delimiters, lastPos);
     167             :     }    
     168           0 :   }
     169             : 
     170             : 
     171           0 :   void SDMDataObjectReader::getFields(const string& header, map<string, string>& fields) {
     172             :     // We are at the last character of the line preceding the 1st field declaration.
     173           0 :     istringstream iss;
     174           0 :     iss.str(header);
     175           0 :     string line;
     176             : 
     177           0 :     getline(iss, line); // skip an nl
     178             :     
     179             :     // Split each line into field-name, field-value
     180           0 :     while (getline(iss, line)) {
     181           0 :       vector<string> nv;
     182           0 :       tokenize(line, nv, ":");
     183           0 :       if (nv.size() < 2) {
     184           0 :         ostringstream oss;
     185           0 :         oss << "Invalid field in a MIME header '" << header << "', integration #" << integrationNum_;
     186           0 :         throw SDMDataObjectReaderException (oss.str());
     187           0 :       }
     188           0 :       fields[nv.at(0)] = nv.at(1);
     189           0 :     }
     190           0 :   }
     191             : 
     192           0 :   string SDMDataObjectReader::getContentID() {
     193             :     // We are at the beginning of an attachment right after its opening boundary.
     194           0 :     string::size_type lastPosition = position_;
     195             :     
     196             :     // Now let's extract the header (which is followed by two successive nl nl)
     197             :     string::size_type endHeader;
     198           0 :     if ( (endHeader = find ("\n\n")) == string::npos) {
     199           0 :       throw SDMDataObjectReaderException("Could not find the end of a MIME header");
     200             :     }
     201             : 
     202           0 :     string header(data_+lastPosition, (endHeader - lastPosition));
     203             :     
     204           0 :     map<string, string> fields;
     205           0 :     getFields(header, fields);
     206             : 
     207             :     // Look for the Content-ID field
     208           0 :     map<string, string>::iterator iter = fields.find("Content-ID");
     209           0 :     if (iter == fields.end()) {
     210           0 :       ostringstream oss;
     211           0 :       oss << "'Content-ID' field is missing the MIME header of an attachment (approx. char position = " << position_ << ").";
     212           0 :       throw SDMDataObjectReaderException(oss.str());
     213           0 :     }
     214           0 :     return iter->second;
     215           0 :   }
     216             : 
     217           0 :   string SDMDataObjectReader::getContentLocation() {
     218             :     // We are at the beginning of an attachment right after its opening boundary.
     219           0 :     string::size_type lastPosition = position_;
     220             :     
     221             :     // Now let's extract the header (which is followed by two successive nl nl)
     222             :     string::size_type endHeader;
     223           0 :     if ( (endHeader = find ("\n\n")) == string::npos) {
     224           0 :       throw SDMDataObjectReaderException("Could not find the end of a MIME header");
     225             :     }
     226             : 
     227           0 :     string header(data_+lastPosition, (endHeader - lastPosition));
     228             :     
     229           0 :     map<string, string> fields;
     230           0 :     getFields(header, fields);
     231             : 
     232             :     // Look for the Content-Location field
     233           0 :     map<string, string>::iterator iter = fields.find("Content-Location");
     234           0 :     if (iter == fields.end()) {
     235           0 :       ostringstream oss;
     236           0 :       oss << "'Content-Location' field is missing the MIME header of an attachment (approx. char position = " << position_ << ").";
     237           0 :       throw SDMDataObjectReaderException(oss.str());
     238           0 :     }
     239           0 :     return iter->second;    
     240           0 :   }
     241             : 
     242           0 :   void SDMDataObjectReader::processBinaryAttachment(const string& boundary, const SDMDataSubset& sdmDataSubset) {
     243             : 
     244           0 :     string contentLocation = getContentLocation();
     245             : 
     246             :     // Extract the attachment name and the integration number.
     247           0 :     std::cmatch what;
     248           0 :     std::regex r(" *" + sdmDataSubset.projectPath()+"(actualDurations|actualTimes|autoData|flags|crossData|zeroLags)\\.bin");
     249           0 :     if (std::regex_match(contentLocation.c_str(), what, r)) {
     250             :     }
     251             :     else {
     252           0 :       ostringstream oss;
     253           0 :       oss << "Invalid Content-Location field '" << contentLocation <<"' in MIME header of an attachment (approx. char position = " << position_ << ").";
     254           0 :       throw SDMDataObjectReaderException(oss.str());
     255           0 :     } 
     256             : 
     257             :     // We are at the first byte of the body of the binary attachment.
     258           0 :     string::size_type startAttachPosition = position_;  // mcaillat
     259             : 
     260             :     // Now look for its closing boundary (or opening boundary of the next one if any).
     261           0 :     string boundary_ = "\n--"+boundary;
     262             :     string::size_type endAttachPosition;
     263           0 :     if ( (endAttachPosition = find(boundary_)) == string::npos) { 
     264           0 :       ostringstream eos;
     265           0 :       eos << "A MIME boundary '" << boundary << "' terminating a binary attachment starting approx. at character " << startAttachPosition <<" could not be found.";
     266           0 :       throw SDMDataObjectReaderException(eos.str());
     267           0 :     }
     268             : 
     269             :     // Compute the length of the attachment.
     270           0 :     string::size_type length = endAttachPosition - startAttachPosition;
     271             :     
     272             : 
     273             : 
     274           0 :     switch (name2code[what[1]]) {
     275           0 :     case ACTUALDURATIONS:
     276           0 :       actualDurations_ = (ACTUALDURATIONSTYPE *) (data_ + startAttachPosition);
     277           0 :       nActualDurations_ = length / sizeof (ACTUALDURATIONSTYPE);
     278           0 :       attachmentFlags.set(ACTUALDURATIONS);
     279             :       //cout << "actualDurations =" << (unsigned long int) actualDurations_ << ", nActualDurations = " << nActualDurations_ << endl;
     280           0 :       break;
     281           0 :     case ACTUALTIMES:
     282           0 :       actualTimes_ = (ACTUALTIMESTYPE *) (data_ + startAttachPosition);
     283           0 :       nActualTimes_ = length / sizeof( ACTUALTIMESTYPE);
     284           0 :       attachmentFlags.set(ACTUALTIMES);
     285             :       //cout << "actualTimes =" << (unsigned long int) actualTimes_ << ", nActualTimes = " << nActualTimes_ << endl;
     286           0 :       break;
     287           0 :     case AUTODATA:
     288           0 :       autoData_ = (AUTODATATYPE *) (data_ + startAttachPosition);
     289           0 :       nAutoData_ = length / sizeof(AUTODATATYPE);
     290           0 :       attachmentFlags.set(AUTODATA);
     291             :       //cout << "autoData =" << (unsigned long int) autoData_ << ", nAutoData = " << nAutoData_ << endl;
     292           0 :       break;
     293           0 :     case FLAGS:
     294           0 :       flags_ = (const FLAGSTYPE *) (data_ + startAttachPosition);
     295           0 :       nFlags_ = length / sizeof(FLAGSTYPE);
     296           0 :       attachmentFlags.set(FLAGS);
     297             :       //cout << "flags =" << (unsigned long int) flags_ << ", nFlags = " << nFlags_ << endl;
     298           0 :       break;
     299           0 :     case CROSSDATA:
     300           0 :       shortCrossData_ = 0;
     301           0 :       longCrossData_  = 0;
     302           0 :       floatCrossData_ = 0;
     303           0 :       switch (sdmDataSubset.crossDataType()) {
     304           0 :       case INT16_TYPE:
     305           0 :         shortCrossData_  = (const SHORTCROSSDATATYPE*) (data_ + startAttachPosition);
     306           0 :         nCrossData_ = length / sizeof (SHORTCROSSDATATYPE);
     307             :         //cout << "shortCrossData = " << (unsigned long int) shortCrossData_ << ", nShortCrossData = " << nCrossData_ << endl;
     308           0 :         break;
     309             :         
     310           0 :       case INT32_TYPE:
     311           0 :         longCrossData_  = (const INTCROSSDATATYPE*) (data_ + startAttachPosition);
     312           0 :         nCrossData_ = length / sizeof (INTCROSSDATATYPE);
     313             :         //cout << "longCrossData = " << (unsigned long int) longCrossData_ << ", nLongCrossData = " << nCrossData_ << endl;
     314           0 :         break;
     315             : 
     316           0 :       case FLOAT32_TYPE:
     317           0 :         floatCrossData_ = (const FLOATCROSSDATATYPE*) (data_ + startAttachPosition);
     318           0 :         nCrossData_ = length / sizeof (FLOATCROSSDATATYPE);
     319           0 :         break;
     320             :        
     321           0 :       default:
     322           0 :         ostringstream eos;
     323           0 :         eos << "'" << CPrimitiveDataType::toString(sdmDataSubset.crossDataType())
     324           0 :             << "' is not a valid primitive data type for CROSSDATA";
     325           0 :         throw SDMDataObjectReaderException(eos.str());  
     326             :         // cout << "Unrecognized type for cross data" << endl;
     327             :       } 
     328           0 :       attachmentFlags.set(CROSSDATA);
     329           0 :       break;
     330           0 :     case ZEROLAGS:
     331           0 :       zeroLags_ = (ZEROLAGSTYPE *) (data_ + startAttachPosition);
     332           0 :       nZeroLags_ = length / sizeof(ZEROLAGSTYPE) ;
     333           0 :       attachmentFlags.set(ZEROLAGS);
     334             :       //cout << "zeroLags =" << (unsigned long int) zeroLags_ << ", nZeroLags = " << nZeroLags_ << endl;
     335           0 :       break;
     336             : 
     337           0 :     default:
     338             :       //cout << "Unrecognized code" << endl;
     339           0 :       break;
     340             :     }
     341             :     // cout << "found a binary attachment" << endl;
     342           0 :   }
     343             :   
     344           0 :   void SDMDataObjectReader::processMIMESDMDataHeader() {
     345             :     // cout << "Entering processMIMESDMDataHeader" << endl;
     346           0 :     string sdmDataHeader = extractXMLHeader(MIMEBOUNDARY_1);
     347           0 :     parser_.parseMemoryHeader(sdmDataHeader, sdmDataObject_);
     348             :     // cout << "Exiting processMIMESDMDataHeader" << endl;
     349           0 :   }
     350             : 
     351           0 :   void SDMDataObjectReader::processMIMESDMDataSubsetHeader(SDMDataSubset& sdmDataSubset) {
     352             :     // cout << "Entering processMIMESDMDataSubsetHeader" << endl;
     353           0 :     string sdmDataSubsetHeader = extractXMLHeader(MIMEBOUNDARY_2);
     354           0 :     if (sdmDataSubset.owner_->isCorrelation())
     355           0 :       parser_.parseMemoryCorrSubsetHeader(sdmDataSubsetHeader, sdmDataSubset);
     356             :     else 
     357           0 :       parser_.parseMemoryTPSubsetHeader(sdmDataSubsetHeader, sdmDataSubset);
     358             :     // cout << "Exiting processMIMESDMDataSubsetHeader" << endl;
     359           0 :   }
     360             : 
     361           0 :   void SDMDataObjectReader::processMIMEIntegration() {
     362             :     // cout << "Entering processMIMEIntegration" << endl;
     363             : 
     364             :     // We are 1 character beyond the end of --<MIMEBOUNDARY_2>
     365           0 :     string contentLocation = getContentLocation();
     366             : 
     367           0 :     std::regex r(" *" + sdmDataObject_.projectPath() + "([[:digit:]]+/){1,2}" + "desc.xml");;
     368           0 :     ostringstream oss;
     369             :     
     370             :     // Extract the Subset name and the integration [, subintegration] number.
     371           0 :     std::cmatch what;
     372           0 :     if (!std::regex_match(contentLocation.c_str(), what, r)) {
     373           0 :       ostringstream oss;
     374           0 :       oss << "Invalid Content-Location field '" << contentLocation <<"' in MIME header of a Subset (approx. char position = " << position_ << ").";
     375           0 :       throw SDMDataObjectReaderException(oss.str());
     376           0 :     } 
     377             :     
     378           0 :     SDMDataSubset integration(&sdmDataObject_);
     379             :     
     380             :     // The SDMDataSubset header.
     381           0 :     processMIMESDMDataSubsetHeader(integration);
     382             :     
     383           0 :     if (integration.aborted_) {
     384             :       // The [sub]integration has been aborted. Just append its header, without trying to get binary attachment.    
     385           0 :       sdmDataObject_.append(integration);
     386             :     }
     387             :     else {
     388             :       // This is regular [sub]integration, process its binary attachments.
     389           0 :       attachmentFlags.reset();
     390           0 :       while (!EOD() && !compare("--")) {
     391           0 :         processBinaryAttachment(MIMEBOUNDARY_2, integration);
     392             :       } 
     393             :     
     394           0 :       if (EOD()) 
     395           0 :         throw SDMDataObjectReaderException("Unexpected end of data");
     396             : 
     397             :       // Now check if the binary attachments found are compatible with the correlation mode
     398             :       // and if their sizes are equal to what is announced in the global header.
     399             :     
     400           0 :       if (!attachmentFlags.test(ACTUALDURATIONS)) {
     401             :         // No actualdurations attachment found, ok then set everything to 0.
     402           0 :         integration.actualDurations_  = 0;
     403           0 :         integration.nActualDurations_ = 0;
     404             :       }
     405             :       else {
     406           0 :         if (nActualDurations_ != sdmDataObject_.dataStruct().actualDurations().size()) {
     407           0 :           ostringstream oss;
     408           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     409           0 :           oss << "zize of 'actualDuration' attachment (" << nActualDurations_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().actualDurations().size() << ")";
     410           0 :           throw SDMDataObjectReaderException(oss.str());
     411           0 :         }
     412             : 
     413           0 :         integration.actualDurations_  = actualDurations_;
     414           0 :         integration.nActualDurations_ = nActualDurations_; 
     415             :       }
     416             : 
     417           0 :       if (!attachmentFlags.test(ACTUALTIMES)) {
     418             :         // No actualtimes attachment found, ok then set everything to 0.
     419           0 :         integration.actualTimes_  = 0;
     420           0 :         integration.nActualTimes_ = 0;
     421             :       }
     422             :       else {
     423           0 :         if (nActualTimes_ != sdmDataObject_.dataStruct().actualTimes().size()) {
     424           0 :           ostringstream oss;
     425           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     426           0 :           oss << "size of 'actualTimes' attachment (" << nActualTimes_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().actualTimes().size() << ")";
     427           0 :           throw SDMDataObjectReaderException(oss.str());
     428           0 :         } 
     429           0 :         integration.actualTimes_  = actualTimes_;
     430           0 :         integration.nActualTimes_ = nActualTimes_;
     431             :       } 
     432             : 
     433             :       // The flags are optional. They may be absent.
     434           0 :       if (!attachmentFlags.test(FLAGS)) {
     435             :         // No flags binary attachment found, ok then set everything to 0.
     436           0 :         integration.flags_  = 0;
     437           0 :         integration.nFlags_ = 0;
     438             :       }
     439             :       else {
     440             :         // flags found
     441             :         // Check size conformity
     442           0 :         if (nFlags_ != sdmDataObject_.dataStruct().flags().size()) {
     443           0 :           ostringstream oss;
     444           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     445           0 :           oss << "size of 'flags' attachment (" << nFlags_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().flags().size() << ")";
     446           0 :           throw SDMDataObjectReaderException(oss.str());
     447           0 :         } 
     448             : 
     449             :         // Set pointer and size
     450           0 :         integration.flags_ = flags_;
     451           0 :         integration.nFlags_ = nFlags_;
     452             :       }
     453             : 
     454             : 
     455             :       //
     456             :       // The presence of crossData and autoData depends on the correlation mode.
     457             : 
     458             :       // crossDataTypeSize is not currently used
     459             :       // unsigned int crossDataTypeSize;    
     460           0 :       switch (sdmDataObject_.correlationMode()) {  
     461           0 :       case CROSS_ONLY:
     462           0 :         if (!attachmentFlags.test(CROSSDATA)) {
     463           0 :           ostringstream oss;
     464           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     465           0 :           oss << "a binary attachment 'crossData' was expected in integration #" << integrationNum_;
     466           0 :           throw SDMDataObjectReaderException(oss.str());
     467           0 :         }
     468             : 
     469             :       
     470           0 :         if (nCrossData_ != sdmDataObject_.dataStruct().crossData().size()) {
     471           0 :           ostringstream oss;
     472           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     473           0 :           oss << "size of 'crossData' attachment (" << nCrossData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().crossData().size() << ")";
     474           0 :           throw SDMDataObjectReaderException(oss.str());
     475           0 :         }
     476             :       
     477             :       
     478           0 :         if (attachmentFlags.test(AUTODATA)) {
     479           0 :           ostringstream oss;
     480           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     481           0 :           oss << "found an unexpected attachment 'autoData' in integration #" << integrationNum_ << ".";
     482           0 :           throw SDMDataObjectReaderException(oss.str());
     483           0 :         }
     484             : 
     485           0 :         integration.shortCrossData_ = 0;
     486           0 :         integration.longCrossData_  = 0;
     487           0 :         integration.floatCrossData_ = 0;
     488           0 :         integration.nCrossData_     = 0;
     489           0 :         switch (integration.crossDataType()) {
     490           0 :         case INT32_TYPE:
     491           0 :           integration.longCrossData_    = longCrossData_;
     492           0 :           integration.nCrossData_       = nCrossData_; 
     493           0 :           break;
     494             : 
     495           0 :         case INT16_TYPE:
     496           0 :           integration.shortCrossData_   = shortCrossData_;
     497           0 :           integration.nCrossData_       = nCrossData_; 
     498           0 :           break;
     499             : 
     500           0 :         case FLOAT32_TYPE:
     501           0 :           integration.floatCrossData_   = floatCrossData_;
     502           0 :           integration.nCrossData_       = nCrossData_;
     503           0 :           break;
     504             : 
     505           0 :         default:
     506           0 :           throw SDMDataObjectReaderException("'"+CPrimitiveDataType::name(integration.crossDataType())+"' unexpected here.");
     507             :         } 
     508           0 :         break;
     509             :       
     510           0 :       case AUTO_ONLY:
     511           0 :         if (!attachmentFlags.test(AUTODATA)) {
     512           0 :           ostringstream oss;
     513           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     514           0 :           oss << "a binary attachment 'autoData' was expected.";
     515           0 :           throw SDMDataObjectReaderException(oss.str());
     516           0 :         }
     517           0 :         if (nAutoData_ != sdmDataObject_.dataStruct().autoData().size()) {
     518           0 :           ostringstream oss;
     519           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     520           0 :           oss << "size of 'autoData' attachment (" << nAutoData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().autoData().size() << ")";
     521           0 :           throw SDMDataObjectReaderException(oss.str());
     522           0 :         }
     523             :       
     524             :       
     525           0 :         if (attachmentFlags.test(CROSSDATA)) {
     526           0 :           ostringstream oss;
     527           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     528           0 :           oss << "found an unexpected attachment 'crossData'";
     529           0 :           throw SDMDataObjectReaderException(oss.str());
     530           0 :         }
     531             : 
     532           0 :         integration.autoData_    = autoData_;
     533           0 :         integration.nAutoData_   = nAutoData_; 
     534             : 
     535           0 :         break;
     536             :       
     537           0 :       case CROSS_AND_AUTO:
     538           0 :         if (!attachmentFlags.test(AUTODATA)) {
     539           0 :           ostringstream oss;
     540           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     541           0 :           oss << "a binary attachment 'autoData' was expected.";
     542           0 :           throw SDMDataObjectReaderException(oss.str());
     543           0 :         }
     544           0 :         if (nAutoData_ != sdmDataObject_.dataStruct().autoData().size()) {
     545           0 :           ostringstream oss;
     546           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     547           0 :           oss << "size of 'autoData' attachment (" << nAutoData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().autoData().size() << ")";
     548           0 :           throw SDMDataObjectReaderException(oss.str());
     549           0 :         }
     550             :       
     551           0 :         if (!attachmentFlags.test(CROSSDATA)) {
     552           0 :           ostringstream oss;
     553           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     554           0 :           oss << "a binary attachment 'crossData' was expected.";
     555           0 :           throw SDMDataObjectReaderException(oss.str());
     556           0 :         }
     557             : 
     558             :         // crossDataTypeSize is not currently used, skip this block
     559             :         // switch (integration.crossDataType()) {
     560             :         // case INT32_TYPE:
     561             :         //   crossDataTypeSize = sizeof(INTCROSSDATATYPE);
     562             :         //   break;
     563             :         // case INT16_TYPE:
     564             :         //   crossDataTypeSize = sizeof(SHORTCROSSDATATYPE);
     565             :         //   break;
     566             :         // case FLOAT32_TYPE:
     567             :         //   crossDataTypeSize = sizeof(FLOATCROSSDATATYPE);
     568             :         //  break;
     569             :         // default:
     570             :         //   throw SDMDataObjectReaderException("'"+CPrimitiveDataType::name(integration.crossDataType())+"' unexpected here.");
     571             :         // }
     572             : 
     573           0 :         if (nCrossData_ != sdmDataObject_.dataStruct().crossData().size()) {
     574           0 :           ostringstream oss;
     575           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     576           0 :           oss << "size of 'crossData' attachment (" << nCrossData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().crossData().size() << ")";
     577           0 :           throw SDMDataObjectReaderException(oss.str());
     578           0 :         }
     579             :         
     580             : 
     581           0 :         integration.shortCrossData_ = 0;
     582           0 :         integration.longCrossData_  = 0;
     583           0 :         integration.floatCrossData_ = 0;
     584           0 :         integration.nCrossData_     = 0;
     585           0 :         switch (integration.crossDataType()) {
     586           0 :         case INT32_TYPE:
     587           0 :           integration.longCrossData_    = longCrossData_;
     588           0 :           integration.nCrossData_       = nCrossData_; 
     589           0 :           break;
     590             :         
     591           0 :         case INT16_TYPE:
     592           0 :           integration.shortCrossData_   = shortCrossData_;
     593           0 :           integration.nCrossData_       = nCrossData_; 
     594           0 :           break;
     595             : 
     596           0 :         case FLOAT32_TYPE:
     597           0 :           integration.floatCrossData_   = floatCrossData_;
     598           0 :           integration.nCrossData_       = nCrossData_;
     599           0 :           break;
     600             : 
     601           0 :         default:
     602           0 :           throw SDMDataObjectReaderException("Data subset '"+contentLocation+"': '"+CPrimitiveDataType::name(integration.crossDataType())+"' unexpected here.");
     603             :         } 
     604             :         
     605           0 :         integration.autoData_    = autoData_;
     606           0 :         integration.nAutoData_   = nAutoData_; 
     607             :         
     608             :         
     609           0 :         break;
     610           0 :       default:
     611           0 :         throw SDMDataObjectReaderException("Data subset '"+contentLocation+"': unrecognized correlation mode");
     612             :         break;
     613             :       }
     614             :       
     615             :       
     616           0 :       if (attachmentFlags.test(ZEROLAGS)) {
     617             :         // Refuse the zeroLags attachment if it's not a Correlator or if the correlator is a CORRELATOR_FX (ACA).
     618           0 :         if ((sdmDataObject_.processorType_ != CORRELATOR) || (sdmDataObject_.correlatorType() == FX))
     619           0 :           throw SDMDataObjectReaderException("zeroLags are not expected from a correlator CORRELATOR_FX");
     620             : 
     621           0 :         if (nZeroLags_ != sdmDataObject_.dataStruct().zeroLags().size()) {
     622           0 :           ostringstream oss;
     623           0 :           oss << "Data subset '"<<contentLocation<<"': ";
     624           0 :           oss << "size of 'zeroLags' attachment (" << nZeroLags_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().zeroLags().size() << ")";
     625           0 :           throw SDMDataObjectReaderException(oss.str());
     626           0 :         }
     627           0 :         integration.zeroLags_  = zeroLags_;
     628           0 :         integration.nZeroLags_ = nZeroLags_;      
     629             :       }
     630             :     
     631           0 :     sdmDataObject_.append(integration);
     632             :   }
     633             : 
     634           0 :     if (!compare("--\n--"+MIMEBOUNDARY_1))
     635           0 :       throw SDMDataObjectReaderException("Data subset '"+contentLocation+"': expecting a '--"+MIMEBOUNDARY_1+"' at the end of a data subset");
     636             :     
     637           0 :     find("--\n--"+MIMEBOUNDARY_1);
     638             :     // cout << "Exiting processMIMEIntegration" << endl;    
     639           0 :   }
     640             : 
     641           0 :   void SDMDataObjectReader::processMIMEIntegrations() {
     642             :     // cout << "Entering processMIMEIntegrations" << endl;
     643             : 
     644           0 :     while (!compare("--")) {
     645             :       // We are one character beyond the last character of --<MIMEBOUNDARY_1>
     646             :       // Let's ignore the MIME Header right after the  --<MIMEBOUNDARY_1> 
     647             :       // and move to the next --<MIMEBOUNDARY_2>
     648           0 :       if (find("--"+MIMEBOUNDARY_2) == string::npos)
     649           0 :         throw SDMDataObjectReaderException("Expecting a boundary '--"+MIMEBOUNDARY_2+"' at this position");
     650             : 
     651             :       //Process the next integration.
     652           0 :       integrationNum_++;
     653           0 :       processMIMEIntegration() ;
     654             :     }
     655             : 
     656             :     // cout << "Exiting processMIMEIntegrations" << endl;
     657           0 :   }
     658             : 
     659           0 :   void SDMDataObjectReader::processMIMESubscan() {
     660             :     //    cout << "Entering processMIMESubscan" << endl;
     661             : 
     662             :     // We are one character beyond the last character of --<MIMEBOUNDARY_1>
     663             :     // Let's ignore the MIME Header right after the  --<MIMEBOUNDARY_1> 
     664             :     // and move to the next --<MIMEBOUNDARY_2>
     665             :     // We are 1 character beyond the end of --<MIMEBOUNDARY_2>
     666           0 :     if (find("--"+MIMEBOUNDARY_2) == string::npos)
     667           0 :       throw SDMDataObjectReaderException("Expecting a boundary '--"+MIMEBOUNDARY_2+"' at this position");
     668             : 
     669             : 
     670           0 :     string contentLocation = getContentLocation();
     671             :     // cout << contentLocation << endl;
     672           0 :     std::regex r(" *"+sdmDataObject_.projectPath() + "desc.xml");
     673             :     
     674             :     // Extract the Subset name and the suffix number (which must be equal to 1).
     675           0 :     std::cmatch what;
     676           0 :     if (!std::regex_match(contentLocation.c_str(), what, r)) {
     677           0 :       ostringstream oss;
     678           0 :       oss << "Invalid Content-Location field '" << contentLocation <<"' in MIME header of the subset";
     679           0 :       throw SDMDataObjectReaderException(oss.str());
     680           0 :     } 
     681             : 
     682           0 :     SDMDataSubset subscan(&sdmDataObject_);
     683             : 
     684             :     // The SDMDataSubset header.
     685           0 :     processMIMESDMDataSubsetHeader(subscan);
     686             :     
     687             : 
     688             :     // Process the binary attachments.
     689           0 :     attachmentFlags.reset();
     690           0 :     integrationNum_++;
     691           0 :     while(!EOD() && !compare("--")) {
     692           0 :       processBinaryAttachment(MIMEBOUNDARY_2, subscan);
     693             :     }
     694             : 
     695           0 :     if (EOD()) throw SDMDataObjectReaderException("Unexpected end of data");
     696             :     
     697             :     // Now check if the binary attachments found are compatible with the correlation mode.
     698             :     // and if their sizes are equal to what is announced in the global header.
     699             : 
     700             :     // Start with the only mandatory attachment : autoData.
     701           0 :     if (!attachmentFlags.test(AUTODATA)) {
     702           0 :       ostringstream oss;
     703           0 :       oss << "Binary attachment 'autoData' was expected in integration #" << integrationNum_;
     704           0 :       throw SDMDataObjectReaderException(oss.str());
     705           0 :     }
     706           0 :     if (nAutoData_ != sdmDataObject_.dataStruct().autoData().size()) {
     707           0 :       ostringstream oss;
     708           0 :       oss << "Size of 'autoData' attachment (" << nAutoData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().autoData().size() << ")";
     709           0 :       throw SDMDataObjectReaderException(oss.str());
     710           0 :     }
     711             :     
     712           0 :     subscan.autoData_    = autoData_;
     713           0 :     subscan.nAutoData_   = nAutoData_; 
     714             :     
     715             : 
     716             :     // And now consider the optional attachments.
     717             : 
     718             :     // The actualDurations are optional. They may be absent.
     719           0 :     if (!attachmentFlags.test(ACTUALDURATIONS)) {
     720             :       // No actualDurations binary attachment found, ok then set everything to 0.
     721           0 :       subscan.actualDurations_  = 0;
     722           0 :       subscan.nActualDurations_ = 0;
     723             :     }
     724             :     else {
     725             :       // actualDurations found
     726             :       // Check size conformity
     727           0 :       if (nActualDurations_ != sdmDataObject_.dataStruct().actualDurations().size()) {
     728           0 :         ostringstream oss;
     729           0 :         oss << "Size of 'actualDurations' attachment (" << nActualDurations_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().actualDurations().size() << ")";
     730           0 :         throw SDMDataObjectReaderException(oss.str());
     731           0 :       } 
     732             : 
     733             :       // Set pointer and size
     734           0 :       subscan.actualDurations_ = actualDurations_;
     735           0 :       subscan.nActualDurations_ = nActualDurations_;
     736             :     }
     737             : 
     738             : 
     739             :     // The actualTimes are optional. They may be absent.
     740           0 :     if (!attachmentFlags.test(ACTUALTIMES)) {
     741             :       // No actualTimes binary attachment found, ok then set everything to 0.
     742           0 :       subscan.actualTimes_  = 0;
     743           0 :       subscan.nActualTimes_ = 0;
     744             :     }
     745             :     else {
     746             :       // actualTimes found
     747             :       // Check size conformity
     748           0 :       if (nActualTimes_ != sdmDataObject_.dataStruct().actualTimes().size()) {
     749           0 :         ostringstream oss;
     750           0 :         oss << "Size of 'actualTimes' attachment (" << nActualTimes_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().actualTimes().size() << ")";
     751           0 :         throw SDMDataObjectReaderException(oss.str());
     752           0 :       } 
     753             : 
     754             :       // Set pointer and size
     755           0 :       subscan.actualTimes_ = actualTimes_;
     756           0 :       subscan.nActualTimes_ = nActualTimes_;
     757             :     }
     758             : 
     759             : 
     760             :     // The flags are optional. They may be absent.
     761           0 :     if (!attachmentFlags.test(FLAGS)) {
     762             :       // No flags binary attachment found, ok then set everything to 0.
     763           0 :       subscan.flags_  = 0;
     764           0 :       subscan.nFlags_ = 0;
     765             :     }
     766             :     else {
     767             :       // flags found
     768             :       // Check size conformity
     769           0 :       if (nFlags_ != sdmDataObject_.dataStruct().flags().size()) {
     770           0 :         ostringstream oss;
     771           0 :         oss << "Size of 'flags' attachment (" << nFlags_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().flags().size() << ")";
     772           0 :         throw SDMDataObjectReaderException(oss.str());
     773           0 :       } 
     774             : 
     775             :       // Set pointer and size
     776           0 :       subscan.flags_ = flags_;
     777           0 :       subscan.nFlags_ = nFlags_;
     778             :     }
     779             : 
     780             :     // And finally let's check that no unexpected binary attachment was found.
     781           0 :     if (attachmentFlags.test(CROSSDATA))  {
     782           0 :       ostringstream oss;
     783           0 :       oss << "Found an unexpected attachment 'crossData' in the binary attachments.";
     784           0 :       throw SDMDataObjectReaderException(oss.str());
     785           0 :     }
     786             : 
     787             :     
     788           0 :     if (attachmentFlags.test(ZEROLAGS))  {
     789           0 :       ostringstream oss;
     790           0 :       oss << "Found an unexpected attachment 'zeroLags' in the binary attachments.";
     791           0 :       throw SDMDataObjectReaderException(oss.str());
     792           0 :     }
     793             : 
     794           0 :     sdmDataObject_.tpDataSubset(subscan);
     795             : 
     796             : 
     797           0 :     if (!compare("--\n--"+MIMEBOUNDARY_1))
     798           0 :       throw SDMDataObjectReaderException("Expecting a '--"+MIMEBOUNDARY_1+"' at the end of a data subset");
     799             :     
     800           0 :     find("--\n--"+MIMEBOUNDARY_1);    
     801           0 :   }
     802             : 
     803           0 :   void SDMDataObjectReader::processMIME() {
     804             :     //    cout << "Entering processMIME" << endl;
     805             :     // Let's find the opening boundary
     806           0 :     if (find("--"+MIMEBOUNDARY_1) == string::npos)
     807           0 :       throw SDMDataObjectReaderException("Expecting a first boundary '--"+MIMEBOUNDARY_1+"'.");
     808             : 
     809             :    // Check the Content-Location of the MIME header ...but do nothing special with it...
     810           0 :     string contentLocation=getContentLocation();
     811             :    
     812             :     // Detect SDMDataHeader.
     813           0 :     processMIMESDMDataHeader();
     814             : 
     815             :     // Do we have packed data (i.e. only one SDMDataSubset grouping all the integrations) or one integration per SDMDataSubset (i.e. per timestamp) ?
     816           0 :     if (sdmDataObject_.hasPackedData()) {
     817           0 :       processMIMESubscan();
     818             :     }
     819             :     else {
     820           0 :       processMIMEIntegrations();
     821             :     }
     822             : 
     823             :     
     824             :     // if (sdmDataObject_.isCorrelation()) {
     825             :     //   // Process integrations.
     826             :     //   processMIMEIntegrations();
     827             :     // }
     828             :     // else if (sdmDataObject_.isTP()){
     829             :     //   // cout << "TP data" << endl;
     830             :     //   if (sdmDataObject_.dimensionality() == 0) {
     831             :     //  processMIMESubscan();
     832             :     //   }
     833             :     //   else {
     834             :     //  processMIMEIntegrations();
     835             :     //   }
     836             :     // }
     837             :     // else {
     838             :     //   // cout << "Unrecognized type of binary data." << endl;
     839             :     // }
     840             :     //cout << "Exiting processMIME" << endl;
     841           0 :   }
     842             : 
     843           0 :   const SDMDataObject & SDMDataObjectReader::read(const char * buffer, unsigned long int size, bool fromFile) {
     844           0 :     if (!fromFile) read_  = MEMORY_;
     845             : 
     846             :     // Set up all sensitive pointers and sizes.
     847           0 :     data_        = (char *)buffer;
     848           0 :     dataSize_    = size;
     849           0 :     position_    = 0;
     850           0 :     endPosition_ = size;
     851             : 
     852             :     // And process the MIME message
     853           0 :     sdmDataObject_.valid_ = true;
     854           0 :     processMIME();
     855             : 
     856           0 :     sdmDataObject_.owns();
     857           0 :     return sdmDataObject_;
     858             :   }
     859             : 
     860           0 :   const SDMDataObject& SDMDataObjectReader::ref() const {
     861           0 :     if (read_ == UNKNOWN_) 
     862           0 :       throw SDMDataObjectReaderException("a reference to an SDMDataObject cannot be obtained as long as the method 'read' has not been called.");
     863           0 :     return sdmDataObject_;
     864             :   }
     865             : 
     866           0 :   const SDMDataObject* SDMDataObjectReader::ptr() const {
     867           0 :     if (read_ == UNKNOWN_) 
     868           0 :       throw SDMDataObjectReaderException("a reference to an SDMDataObject cannot be obtained as long as the method 'read' has not been called.");
     869           0 :     return &sdmDataObject_;
     870             :   }
     871             : 
     872           0 :   void SDMDataObjectReader::done() {
     873           0 :     switch (read_) {
     874           0 :     case UNKNOWN_:
     875             :     case MEMORY_:
     876           0 :       break;
     877           0 :     case FILE_:
     878           0 :       munmap((caddr_t) data_, dataSize_);
     879           0 :       close(filedes_);
     880           0 :       break;
     881             :     }
     882           0 :     sdmDataObject_.done();
     883           0 :     read_ = UNKNOWN_;
     884           0 :   }
     885             : 
     886           0 :   const SDMDataObject& SDMDataObjectReader::sdmDataObject() {
     887           0 :     return sdmDataObject_;
     888             :   }
     889             : 
     890             : 
     891           0 :   const SDMDataObject & SDMDataObjectReader::read(string filename) {
     892             : 
     893             :     struct stat fattr; // stat64 fattr;
     894             : 
     895             :     unsigned long int filesize;
     896           0 :     char* data = 0;
     897             :     // Open the file.
     898           0 :     errno = 0;
     899             : #ifdef __APPLE__
     900             :     if ( (filedes_ = open(filename.c_str(), O_RDONLY )) == -1) {
     901             : #else
     902           0 :     if ( (filedes_ = open(filename.c_str(), O_RDONLY | O_LARGEFILE)) == -1) {
     903             : #endif
     904           0 :       string message(strerror(errno));
     905           0 :       throw SDMDataObjectReaderException("Could not open file '" + filename + "'. The message was '" + message + "'");
     906           0 :     }
     907           0 :     read_ = FILE_;
     908             :     
     909             :     // Get its size.
     910           0 :     errno = 0;
     911           0 :     int status = fstat(filedes_,&fattr); // fstat64(filedes_,&fattr);
     912           0 :     if (status == -1) {
     913           0 :       string message(strerror(errno));
     914           0 :       throw SDMDataObjectReaderException("Could not retrieve size of file '" + filename + "'. The message was '" + message + "'");
     915           0 :     }
     916           0 :     filesize = fattr.st_size;
     917             : 
     918             :     // Map it to virtual memory address space.
     919           0 :     errno = 0;
     920             : 
     921           0 :     data = (char *) mmap((caddr_t)0, filesize, PROT_READ, MAP_SHARED, filedes_, (off_t)0);
     922           0 :     if ( ((unsigned long) data) == 0xffffffff) {      
     923           0 :       string message(strerror(errno));
     924           0 :       throw SDMDataObjectReaderException("Could not map file '" + filename + "' to memory. The message was '" + message + "'");
     925           0 :     }
     926             :     
     927             :     // cout << "Successfully mapped file." << endl;
     928             :     // And delegate to the other read (memory buffer) method.
     929           0 :     return read(data, filesize, true);
     930             :   }
     931             : 
     932             :   // SDMDataObjectReader::
     933             : 
     934             : } // namespace asdmbinaries
     935             : 

Generated by: LCOV version 1.16