#ifndef SDMDataObjectStreamReader_CLASS #define SDMDataObjectStreamReader_CLASS #include <utility> #include <iostream> #include <sstream> #include <fstream> #include <vector> #include <map> #include <set> #include <bitset> #ifndef WITHOUT_BOOST #include <boost/algorithm/string.hpp> #endif #include <libxml/parser.h> #include <libxml/tree.h> #ifndef WITHOUT_BOOST #include "boost/filesystem/operations.hpp" #include <boost/regex.hpp> #endif #include <alma/ASDMBinaries/SDMDataObjectParser.h> #include <alma/ASDMBinaries/SDMDataObject.h> #include <alma/Enumerations/CPrimitiveDataType.h> namespace asdmbinaries { class SDMDataObjectStreamReaderException { public: SDMDataObjectStreamReaderException(); SDMDataObjectStreamReaderException(const std::string& message); const std::string& getMessage(); private: std::string message; }; class SDMDataObjectStreamReader { public: SDMDataObjectStreamReader() ; virtual ~SDMDataObjectStreamReader() ; /** * Open a file expected to contain BDF data, read and parse the global header. * On exit the first block of data (subscan, integration or subintegration) is ready to be read by the getData method. * * @throws SDMDataObjectStreamReaderException, SDMDataObjectException, SDMDataObjectParserException. */ void open(const std::string& path); /** * Returns the current position in the BDF file. * * or -1 if it fails to determine the position. * * @return an int64_t */ int64_t position(); /** * Set the read position in the BDF file. * */ void position(int64_t p); /** * Close the file containing the BDF data and releases all the memory dynamically allocated. */ void close(); /** * Returns the current position in bytes in the file of the current block of data (subscan, integration or subintegration) . * * @return a long long unsigned int. */ unsigned long long currentIntegrationStartsAt() const; /** * Returns the index of the current block of data (subscan, integration or subintegration). * The indexing is 0 based. * * @return an unsigned int. */ unsigned int currentIntegrationIndex() const; /** * Returns the title of the SDMDataObject. * @return a string. */ std::string title() const; /** * Returns the byte order of the SDMDataObject. * @return a pointer to a ByteOrder instance. */ const ByteOrder* byteOrder() const ; /** * Returns the start time. * @return a long long. */ unsigned long long startTime() const; /** * Returns the number of (sub) integrations. * @return an unsigned int. * */ unsigned int numTime() const; /** * Returns the dataOID. * @return a string. */ std::string dataOID() const; /** * Returns the UID of the ExecBlock. * @return a string. */ std::string execBlockUID() const; /** * Returns the number of the ExecBlock. * @return an unsigned int. */ unsigned int execBlockNum() const; /** * Returns the number of the scan. * @return an unsigned int. */ unsigned int scanNum() const; /** * Returns the number of the subscan. * @return an unsigned int. */ unsigned int subscanNum() const; /** * Returns the project path. * The project path is a string of the form "/<s>execBlockNum</s>/<s>scanNum</s>/<s>subscanNum</s>" */ std::string projectPath() const; /** * Returns the number of antenna. * @return an unsigned int. */ unsigned int numAntenna() const; /** * Returns the correlation mode. * @return a value from enumeration CorrelationMode. */ CorrelationModeMod::CorrelationMode correlationMode() const; /** * Returns the spectral resolution. * Due to this optional nature, the spectral resolution type is not returned directly as a literal of the enumeration * SpectralResolutionType, but as an instance of the class OptionalSpectralResolutionType. This instance can be queried to * check if the spectral resolution type information is present and if it is its value as an SpectralResolutionType literal. * * @return a value from enumeration SpectralResolutionType. */ OptionalSpectralResolutionType spectralResolutionType() const; /** * Returns the processor type. * @return a value from the enumeration ProcessorType. */ ProcessorTypeMod::ProcessorType processorType() const; /** * Returns the correlator type. * * @return a value from the enumeration CorrelatorType if processorType == CORRELATOR else an SDMDataObjectException is thrown. * @throw SDMDataException */ CorrelatorTypeMod::CorrelatorType correlatorType() const; /** * Returns true if the binary data are all packed in one subset or distributed in a sequence * of subsets (supposedly) along the time axis. * * @return a boolean */ bool hasPackedData() const; /** * Returns true if the data are total power data and false otherwise. * @return a bool. * * @note data are considered as total power data if CorrelationMode == AUTO_ONLY && SpectralResolutionType == BASEBAND_WIDE. */ bool isTP() const ; /** * Returns true if the data are WVR data and false otherwise. * @return a bool. * * @note data are considered as total power data if CorrelationMode == AUTO_ONLY && SpectralResolutionType == BASEBAND_WIDE. */ bool isWVR() const ; /** * Returns true if the data are correlator data and false otherwise. * @return a bool. * * @note data are considered as correlator data if SpectralResolutionType != BASEBAND_WIDE. */ bool isCorrelation() const; /** * Returns the structure of the data. * @returns a reference to a DataStruct. */ const SDMDataObject::DataStruct& dataStruct() const; /** * Returns true if the observation has been aborted. * This method must be used on an SDMDataObject containing correlator data,otherwise a SDMDataObjectException is thrown. * * @return a bool. * * @throw SDMDataObjectException. */ bool aborted() const; /** * Returns the time, as an unsigned long long, at which the observation has been aborted. * The returned value is significant only if the observation has been aborted, therefore the method must always be used in * conjuction with the aborted method. This method must be used on an SDMDataObject containing correlator data, * otherwise a SDMDataObjectException is thrown. * * @return an unsigned long long. * * @throw SDMDataObjectException */ unsigned long long abortTime() const; /** * Returns the reason, as a string, why the observation has been aborted. * The returned value is significant only if the observation has been aborted, therefore the method must always be used in * conjuction with the aborted method. This method must be used on an SDMDataObject containing correlator data, * otherwise a SDMDataObjectException is thrown. * * @return a string. * * @throw SDMDataObjectException */ std::string abortReason() const; /** * Returns a string representation of the global header of this SDMDataObject. * @return a string. */ std::string toString() const; /** * Returns true as long as the mark announcing the end of the sequence of (sub)integrations * is not read in the stream. */ bool hasSubset(); /* * Returns a reference to an SDMDataSubset. * This SDMDataSubset represents the (sub)integration read and parsed at the current position (see currentIntegrationIndex() * and currentIntegrationStartsAt()) in the sequence stored in the stream. * O * * @return a reference to an SDMDataSubset */ const SDMDataSubset& getSubset(); /* * Returns binary data found in the BDF file from the current location and contained in the next * nDataSubsets at maximum. * * The result is returned as a reference to a vector of SDMDataSubset. Each element of this vector * is an instance of an SDMDataSubset obtained by a sequential read of the file opened with the method open * from the current position in that file. * * The size of the resulting vector determines how many SDMDataSubsets have been actually read. * * @return const vector<SDMDataSubset>& */ const std::vector<SDMDataSubset>& nextSubsets(unsigned int nSubsets); /* * Returns all binary data found in the BDF file from the current location. * * The result is returned as a reference to a vector of SDMDataSubset. Each element of this vector * is an instance of an SDMDataSubset obtained by a sequential read of the file opened with the method open * from the current position in that file. * * @return const vector<SDMDataSubset>& */ const std::vector<SDMDataSubset>& allRemainingSubsets(); enum BINATTACHCODES {ACTUALDURATIONS=0, ACTUALTIMES=1, AUTODATA=2, FLAGS=3, CROSSDATA=4, ZEROLAGS=5}; std::bitset<6> attachmentFlags; private: // Enumerations to manage the state of an instance of SDMDataObjectStreamReader. // enum States {S_NO_BDF, S_AT_BEGINNING, S_READING, S_AT_END}; enum Transitions {T_OPEN, T_QUERY, T_TEST_END, T_READ, T_READ_NEXT, T_READ_ALL, T_CLOSE}; // Private variables unsigned long long integrationStartsAt; unsigned int integrationIndex; std::string path; std::ifstream f; States currentState; std::string currentLine; std::string boundary_1; std::string boundary_2; bool opened; std::map<std::string, int64_t> binaryPartSize; std::set<std::string> s_partNames; char* actualTimesBuffer; char* actualDurationsBuffer; char* autoDataBuffer; char* crossDataBuffer; char* flagsBuffer; char* zeroLagsBuffer; SDMDataObjectParser parser; SDMDataObject sdmDataObject; SDMDataSubset sdmDataSubset; std::vector<SDMDataSubset> remainingSubsets; std::vector<SDMDataSubset> someSubsets; // Private methods void checkState(Transitions t, const std::string& methodName) const; std::string nextLine(); std::pair<std::string, std::string> headerField2Pair(const std::string& hf); std::pair<std::string, std::string> requireHeaderField(const std::string& hf); std::string requireMIMEHeader(); std::string requireBoundaryInCT(const std::string& ctValue); void skipAsLongAsLineStartsWith(const std::string& start); void skipUntilEmptyLine(int maxSkips); std::string accumulateUntilBoundary(const std::string& boundary, int maxLines); void requireBoundary(const std::string&, int maxLines); void lookForBinaryPartSize(xmlNode* aNode); std::string requireCrossDataType(xmlNode* parent); void printElementNames(xmlNode * a_node); void requireSDMDataHeaderMIMEPart(); void requireSDMDataSubsetMIMEPart(SDMDataSubset& sdmDataSubset); void releaseMemory(SDMDataSubset & sdmDataSubset); }; } // end namespace asdmbinaries #endif