LCOV - code coverage report
Current view: top level - alma/ASDMBinaries - SDMDataObjectStreamReader.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 495 0.0 %
Date: 2025-12-12 07:32:35 Functions: 0 56 0.0 %

          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

Generated by: LCOV version 1.16