diff --git a/six/modules/c++/cphd/include/cphd/BaseFileHeader.h b/six/modules/c++/cphd/include/cphd/BaseFileHeader.h index 1f62a91f95..a0fcd0c1bc 100644 --- a/six/modules/c++/cphd/include/cphd/BaseFileHeader.h +++ b/six/modules/c++/cphd/include/cphd/BaseFileHeader.h @@ -30,6 +30,8 @@ #include #include +#include "cphd/Types.h" + namespace cphd { @@ -73,7 +75,9 @@ class BaseFileHeader * \throws except::Exception if file is not CPHD */ static - std::string readVersion(io::SeekableInputStream& inStream); + std::string strReadVersion(io::SeekableInputStream& inStream); + static Version readVersion(io::SeekableInputStream& inStream); + static Version toVersion(const std::string&); /* * \func read @@ -88,7 +92,7 @@ class BaseFileHeader * \throws except::Exception if expected header entry is not found * \throws except::Exception if any header info is missing or empty */ - virtual void read(io::SeekableInputStream& inStream) = 0; + virtual void readImpl(io::SeekableInputStream& inStream) = 0; /* * \func toString diff --git a/six/modules/c++/cphd/include/cphd/CPHDReader.h b/six/modules/c++/cphd/include/cphd/CPHDReader.h index 84cc7031f2..ed47c7e091 100644 --- a/six/modules/c++/cphd/include/cphd/CPHDReader.h +++ b/six/modules/c++/cphd/include/cphd/CPHDReader.h @@ -19,9 +19,9 @@ * see . * */ +#pragma once #ifndef SIX_cphd_CPHDReader_h_INCLUDED_ #define SIX_cphd_CPHDReader_h_INCLUDED_ -#pragma once #include @@ -78,6 +78,11 @@ struct CPHDReader final std::shared_ptr logger = std::shared_ptr()); + CPHDReader(const CPHDReader&) = delete; + CPHDReader& operator=(const CPHDReader&) = delete; + CPHDReader(CPHDReader&&) = default; + CPHDReader& operator=(CPHDReader&&) = default; + //! Get parameter functions size_t getNumChannels() const { @@ -152,14 +157,6 @@ struct CPHDReader final PVPBlock mPVPBlock; //! Signal block book-keeping info read in from CPHD file std::unique_ptr mWideband; - - /* - * Read in header, metadata, supportblock, pvpblock and wideband - */ - void initialize(std::shared_ptr inStream, - size_t numThreads, - std::shared_ptr logger, - const std::vector& schemaPaths); }; } diff --git a/six/modules/c++/cphd/include/cphd/CPHDWriter.h b/six/modules/c++/cphd/include/cphd/CPHDWriter.h index 2cc73c448a..49988b826b 100644 --- a/six/modules/c++/cphd/include/cphd/CPHDWriter.h +++ b/six/modules/c++/cphd/include/cphd/CPHDWriter.h @@ -20,16 +20,19 @@ * */ +#pragma once #ifndef SIX_cphd_CPHDWriter_h_INCLUDED_ #define SIX_cphd_CPHDWriter_h_INCLUDED_ -#pragma once #include #include +#include +#include #include #include #include +#include #include @@ -126,17 +129,12 @@ struct CPHDWriter final * \param supportData (Optional) The support array data to write to disk. */ template - void write( - const PVPBlock& pvpBlock, - const T* widebandData, - const sys::ubyte* supportData = nullptr); + void write(const PVPBlock& pvpBlock, const T* widebandData, + std::span supportData); template - void write( - const PVPBlock& pvpBlock, - const T* widebandData, - const std::byte* supportData = nullptr) + void write(const PVPBlock& pvpBlock, const T* widebandData) { - write(pvpBlock, widebandData, reinterpret_cast(supportData)); + write(pvpBlock, widebandData, std::span()); } /* @@ -161,12 +159,12 @@ struct CPHDWriter final * \param id The unique identifier of the support array */ template - void writeSupportData(const T* data, + void writeSupportData(const T* data_, const std::string& id) { - writeSupportDataImpl(reinterpret_cast(data), - mMetadata.data.getSupportArrayById(id).numRows * mMetadata.data.getSupportArrayById(id).numCols, - mMetadata.data.getSupportArrayById(id).bytesPerElement); + const auto size = mMetadata.data.getSupportArrayById(id).size_bytes(); + const auto data = sys::make_span(data_, size); + writeSupportDataImpl(data, mMetadata.data.getSupportArrayById(id).bytesPerElement); } /* @@ -177,22 +175,17 @@ struct CPHDWriter final * * \param data A pointer to the start of the support array data block */ + void writeSupportData(std::span); template - void writeSupportData(const T* data) + void writeSupportData(std::span data) { - auto dataPtr = reinterpret_cast(data); - for (auto it = mMetadata.data.supportArrayMap.begin(); it != mMetadata.data.supportArrayMap.end(); ++it) - { - // Move inputstream head to offset of particular support array - mStream->seek(mHeader.getSupportBlockByteOffset() + it->second.arrayByteOffset, io::SeekableOutputStream::START); - writeSupportDataImpl(dataPtr + it->second.arrayByteOffset, - it->second.numRows * it->second.numCols, - it->second.bytesPerElement); - } - // Move inputstream head to the end of the support block after all supports have been written - mStream->seek(mHeader.getSupportBlockByteOffset() + mHeader.getSupportBlockSize(), io::SeekableOutputStream::START); + writeSupportData(std::as_bytes(data)); + } + template + void writeSupportData(const std::vector& data) + { + writeSupportData(sys::make_span(data)); } - /* * \func writePVPData @@ -264,8 +257,7 @@ struct CPHDWriter final /* * Implementation of write support data */ - void writeSupportDataImpl(const std::byte* data, - size_t numElements, size_t elementSize); + void writeSupportDataImpl(std::span, size_t elementSize); //! DataWriter object std::unique_ptr mDataWriter; @@ -273,8 +265,6 @@ struct CPHDWriter final // Book-keeping element //! metadata information const Metadata& mMetadata; - //! header information - FileHeader mHeader; //! size of each element in signal block const size_t mElementSize; //! size of scratch space for byte swapping @@ -285,6 +275,8 @@ struct CPHDWriter final const std::vector mSchemaPaths; //! Output stream contains CPHD file std::shared_ptr mStream; + //! header information + FileHeader mHeader; }; } diff --git a/six/modules/c++/cphd/include/cphd/CPHDXMLControl.h b/six/modules/c++/cphd/include/cphd/CPHDXMLControl.h index 2a6b619cd2..da0f114cff 100644 --- a/six/modules/c++/cphd/include/cphd/CPHDXMLControl.h +++ b/six/modules/c++/cphd/include/cphd/CPHDXMLControl.h @@ -145,8 +145,10 @@ class CPHDXMLControl const std::vector& schemaPaths = std::vector()); //! \return Suported version to uri mapping - static std::unordered_map getVersionUriMap(); - static void getVersionUriMap(std::map&); + static std::map getVersionUriMap(); + + // Given the URI get associated version + static Version uriToVersion(const xml::lite::Uri&); protected: logging::Logger *mLog = nullptr; @@ -178,10 +180,7 @@ class CPHDXMLControl * \param uri A string specifying CPHD uri */ std::unique_ptr - getParser(const xml::lite::Uri&) const; - - // Given the URI get associated version - Version uriToVersion(const xml::lite::Uri&) const; + getParser(Version) const; }; } diff --git a/six/modules/c++/cphd/include/cphd/CPHDXMLParser.h b/six/modules/c++/cphd/include/cphd/CPHDXMLParser.h index 6961f0f1e0..a5c1698554 100644 --- a/six/modules/c++/cphd/include/cphd/CPHDXMLParser.h +++ b/six/modules/c++/cphd/include/cphd/CPHDXMLParser.h @@ -46,9 +46,8 @@ namespace cphd * \brief This class converts a Metadata object into a CPHD XML * Document Object Model (DOM) and vise-versa. */ -class CPHDXMLParser : public six::XMLParser +struct CPHDXMLParser final : public six::XMLParser { -public: /*! * \func CPHDXMLParser * \brief Constructor @@ -58,7 +57,7 @@ class CPHDXMLParser : public six::XMLParser * \param log provide logger object * \param ownLog flag indicates if log should be deleted */ - CPHDXMLParser(const std::string& uri, + CPHDXMLParser(Version, bool addClassAttributes, logging::Logger* log = nullptr, bool ownLog = false); @@ -85,8 +84,8 @@ class CPHDXMLParser : public six::XMLParser * * \return pointer to metadata object */ - std::unique_ptr fromXML( - const xml::lite::Document* doc); + std::unique_ptr fromXML(const xml::lite::Document* doc); + Metadata fromXML(const xml::lite::Document&, Version); private: typedef xml::lite::Element* XMLElem; diff --git a/six/modules/c++/cphd/include/cphd/Data.h b/six/modules/c++/cphd/include/cphd/Data.h index ca3daca693..743d2c28cf 100644 --- a/six/modules/c++/cphd/include/cphd/Data.h +++ b/six/modules/c++/cphd/include/cphd/Data.h @@ -95,6 +95,14 @@ struct Data { return numRows * numCols * bytesPerElement; } + size_t size() const + { + return numRows * numCols; + } + size_t size_bytes() const // c.f., std::span::size_bytes() + { + return size() * bytesPerElement; + } //! Unique string that identifies this support array //! (SA_ID). diff --git a/six/modules/c++/cphd/include/cphd/DataWriter.h b/six/modules/c++/cphd/include/cphd/DataWriter.h index 3be5c21ba7..125a1c2e24 100644 --- a/six/modules/c++/cphd/include/cphd/DataWriter.h +++ b/six/modules/c++/cphd/include/cphd/DataWriter.h @@ -20,16 +20,18 @@ * */ +#pragma once #ifndef SIX_cphd_DataWriter_h_INCLUDED_ #define SIX_cphd_DataWriter_h_INCLUDED_ -#pragma once #include #include #include // std::byte +#include #include #include +#include namespace cphd { @@ -69,7 +71,13 @@ struct DataWriter * \param numElements Total number of elements in array * \param elementSize Size of each element */ - virtual void operator()(const void* data, size_t numElements, size_t elementSize) = 0; + virtual void operator()(std::span, size_t elementSize) = 0; + void operator()(const void* data_, size_t numElements, size_t elementSize) + { + const auto pData = static_cast(data_); + std::span data(pData, numElements * elementSize); + (*this)(data, elementSize); + } protected: //! Output stream of CPHD @@ -112,7 +120,12 @@ struct DataWriterLittleEndian final : public DataWriter * \param numElements Total number of elements in array * \param elementSize Size of each element */ - void operator()(const void* data, size_t numElements, size_t elementSize) override; + void operator()(std::span, size_t elementSize) override; + void operator()(const sys::ubyte* data, size_t numElements, size_t elementSize) // for existing SWIG bindings + { + DataWriter* const pThis = this; + (*pThis)(data, numElements, elementSize); + } private: // Scratch space buffer @@ -154,7 +167,12 @@ struct DataWriterBigEndian final : public DataWriter * \param numElements Total number of elements in array * \param elementSize Size of each element */ - void operator()(const void* data, size_t numElements, size_t elementSize) override; + void operator()(std::span, size_t elementSize) override; + void operator()(const sys::ubyte* data, size_t numElements, size_t elementSize) // for existing SWIG bindings + { + DataWriter* const pThis = this; + (*pThis)(data, numElements, elementSize); + } }; // Create the appropriate DataWriter instance using std::endian::native. There are fancier diff --git a/six/modules/c++/cphd/include/cphd/FileHeader.h b/six/modules/c++/cphd/include/cphd/FileHeader.h index c096cc60ae..b196571986 100644 --- a/six/modules/c++/cphd/include/cphd/FileHeader.h +++ b/six/modules/c++/cphd/include/cphd/FileHeader.h @@ -19,8 +19,9 @@ * see . * */ -#ifndef __CPHD_FILE_HEADER_H__ -#define __CPHD_FILE_HEADER_H__ +#pragma once +#ifndef SIX_cphd_FileHeader_h_INCLUDED_ +#define SIX_cphd_FileHeader_h_INCLUDED_ #include #include @@ -39,7 +40,10 @@ namespace cphd */ class FileHeader final : public BaseFileHeader { + static Version defaultVersion; public: + static Version getDefaultVersion(); + static void setDefaultVersion(Version); static const char* DEFAULT_VERSION; // `const char*` for existing Python bindings /* @@ -48,7 +52,17 @@ class FileHeader final : public BaseFileHeader * \brief Constructor * initialize default variables */ - FileHeader(); + FileHeader(Version); +#ifdef SWIGPYTHON + FileHeader() = default; + FileHeader(const FileHeader&) = default; + FileHeader& operator=(const FileHeader&) = default; +#else + FileHeader(const FileHeader&) = delete; + FileHeader& operator=(const FileHeader&) = delete; +#endif + FileHeader(FileHeader&&) = default; + FileHeader& operator=(FileHeader&&) = default; virtual ~FileHeader() { @@ -61,7 +75,8 @@ class FileHeader final : public BaseFileHeader * * \param inStream Valid input stream of CPHD file */ - void read(io::SeekableInputStream& inStream) override; + void readImpl(io::SeekableInputStream&) override; + static FileHeader read(io::SeekableInputStream&); /* * \func toString @@ -86,6 +101,7 @@ class FileHeader final : public BaseFileHeader * returns file version string */ std::string getVersion() const; + void getVersion(Version&) const; /* * \func setVersion @@ -96,7 +112,7 @@ class FileHeader final : public BaseFileHeader * ex: 1.0.0, 1.0.1 etc * */ - void setVersion(const std::string& version); + void setVersion(const std::string&); void setVersion(Version); /* @@ -234,22 +250,25 @@ class FileHeader final : public BaseFileHeader private: // File type header - std::string mVersion; + Version mVersion; // Required key-value pairs - int64_t mXmlBlockSize; - int64_t mXmlBlockByteOffset; - int64_t mPvpBlockSize; - int64_t mPvpBlockByteOffset; - int64_t mSignalBlockSize; - int64_t mSignalBlockByteOffset; + int64_t mXmlBlockSize = 0; + int64_t mXmlBlockByteOffset = 0; + int64_t mPvpBlockSize = 0; + int64_t mPvpBlockByteOffset = 0; + int64_t mSignalBlockSize = 0; + int64_t mSignalBlockByteOffset = 0; std::string mClassification; std::string mReleaseInfo; // Optional key-value pairs - int64_t mSupportBlockSize; - int64_t mSupportBlockByteOffset; + int64_t mSupportBlockSize = 0; + int64_t mSupportBlockByteOffset = 0; + + void readAfterValidVersion(io::SeekableInputStream& inStream); }; + } -#endif +#endif // SIX_cphd_FileHeader_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/Metadata.h b/six/modules/c++/cphd/include/cphd/Metadata.h index 1cca99a41a..8b1981ea59 100644 --- a/six/modules/c++/cphd/include/cphd/Metadata.h +++ b/six/modules/c++/cphd/include/cphd/Metadata.h @@ -20,8 +20,9 @@ * */ -#ifndef __CPHD_METADATA_H__ -#define __CPHD_METADATA_H__ +#pragma once +#ifndef SIX_cphd_Metadata_h_INCLUDED_ +#define SIX_cphd_Metadata_h_INCLUDED_ #include @@ -59,7 +60,18 @@ struct Metadata final : MetadataBase { //! Default constructor //! Initializes CPHD version to default version specified in FileHeader - Metadata(); + Metadata(Version); + Metadata(Data&&); +#ifdef SWIGPYTHON + Metadata() = default; + Metadata(const Metadata&) = default; + Metadata& operator=(const Metadata&) = default; +#else + Metadata(const Metadata&) = delete; + Metadata& operator=(const Metadata&) = delete; +#endif + Metadata(Metadata&&) = default; + Metadata& operator=(Metadata&&) = default; /* * Getter functions @@ -78,12 +90,10 @@ struct Metadata final : MetadataBase */ DomainType getDomainType() const override; - //! Get CPHD version + //! CPHD version std::string getVersion() const; void getVersion(Version&) const; - - //! Set CPHD version - void setVersion(const std::string& version); + void setVersion(const std::string&); void setVersion(Version); //! CollectionInfo block. Contains the general collection information @@ -161,4 +171,4 @@ struct Metadata final : MetadataBase std::ostream& operator<< (std::ostream& os, const Metadata& d); } -#endif +#endif // SIX_cphd_Metadata_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/PVP.h b/six/modules/c++/cphd/include/cphd/PVP.h index d302b60a8c..e106dd23ca 100644 --- a/six/modules/c++/cphd/include/cphd/PVP.h +++ b/six/modules/c++/cphd/include/cphd/PVP.h @@ -124,7 +124,7 @@ struct PVPType std::string mFormat; }; void setOffset(PVPType&, size_t offset); - +std::ostream& operator<< (std::ostream& os, const PVPType& p); /*! * \struct APVPType @@ -211,6 +211,12 @@ struct PerVectorParameterXYZ final PVPType param; }; +inline std::ostream& operator<<(std::ostream& os, const PerVectorParameterXYZ& v) +{ + os << v.param << "\n"; + return os; +} + /*! * \struct PerVectorParameterEB @@ -237,6 +243,12 @@ struct PerVectorParameterEB final PVPType param; }; +inline std::ostream& operator<<(std::ostream& os, const PerVectorParameterEB& v) +{ + os << v.param << "\n"; + return os; +} + /*! * \struct TxAntenna @@ -267,6 +279,13 @@ struct TxAntenna final //! TxEB PVP Structure six::XsElement txEB{ "TxEB" }; }; +inline std::ostream& operator<<(std::ostream& os, const TxAntenna& v) +{ + os << v.txACX << "\n"; + os << v.txACY << "\n"; + os << v.txEB << "\n"; + return os; +} /*! * \struct RcvAntenna @@ -297,6 +316,13 @@ struct RcvAntenna final //! RcvEB PVP Structure six::XsElement rcvEB{ "RcvEB" }; }; +inline std::ostream& operator<<(std::ostream& os, const RcvAntenna& v) +{ + os << v.rcvACX << "\n"; + os << v.rcvACY << "\n"; + os << v.rcvEB << "\n"; + return os; +} /*! * \struct Pvp @@ -597,15 +623,9 @@ struct Pvp final * Set default size and format for each parameter */ void setDefaultValues(size_t size, const std::string& format, PVPType& param); - - /* - * Initializes default size and format for parameters - */ - void initialize(); }; //! Ostream operators -std::ostream& operator<< (std::ostream& os, const PVPType& p); std::ostream& operator<< (std::ostream& os, const APVPType& a); std::ostream& operator<< (std::ostream& os, const Pvp& p); } diff --git a/six/modules/c++/cphd/include/cphd/PVPBlock.h b/six/modules/c++/cphd/include/cphd/PVPBlock.h index e8ef6a4025..52be696925 100644 --- a/six/modules/c++/cphd/include/cphd/PVPBlock.h +++ b/six/modules/c++/cphd/include/cphd/PVPBlock.h @@ -194,8 +194,7 @@ struct PVPBlock return aP.getAddedPVP(mData[channel][set].addedPVP.find(name)->second); // return AddPVPNamespace::getAddedPVP(mData[channel][set].addedPVP.find(name)->second); } - throw except::Exception(Ctxt( - "Parameter was not set")); + throw except::Exception(Ctxt("Parameter was not set")); } //! Setter functions @@ -236,11 +235,9 @@ struct PVPBlock mData[channel][set].addedPVP.find(name)->second.setValue(value); return; } - throw except::Exception(Ctxt( - "Additional parameter requested already exists")); + throw except::Exception(Ctxt("Additional parameter requested already exists")); } - throw except::Exception(Ctxt( - "Parameter was not specified in XML")); + throw except::Exception(Ctxt("Parameter was not specified in XML")); } /* @@ -251,10 +248,10 @@ struct PVPBlock * \param[out] data Will be filled with PVP data. This will * be resized and zeroed internally. */ - void getPVPdata(size_t channel, - std::vector& data) const; void getPVPdata(size_t channel, std::vector& data) const; + void getPVPdata(size_t channel, + std::vector& data) const; // for existing SWIG bindings /* * \func getPVPdata @@ -359,7 +356,7 @@ struct PVPBlock * Each channel consists of a PVP Array, * which consists of multiple sets */ - struct PVPSet + struct PVPSet final { /*! * \func PVPSet diff --git a/six/modules/c++/cphd/include/cphd/SupportBlock.h b/six/modules/c++/cphd/include/cphd/SupportBlock.h index 6f55cde1cb..7cbd41a3b0 100644 --- a/six/modules/c++/cphd/include/cphd/SupportBlock.h +++ b/six/modules/c++/cphd/include/cphd/SupportBlock.h @@ -19,15 +19,15 @@ * see . * */ +#pragma once #ifndef __CPHD_SUPPORT_BLOCK_H__ #define __CPHD_SUPPORT_BLOCK_H__ -#pragma once #include #include #include #include - +#include #include #include @@ -118,13 +118,7 @@ struct SupportBlock final void read(const std::string& id, size_t numThreads, const mem::BufferView& data) const; - void read(const std::string& id, - size_t numThreads, - std::span data) const - { - mem::BufferView data_(reinterpret_cast(data.data()), data.size()); - read(id, numThreads, data_); - } + void read(const std::string& id, size_t numThreads, std::span data) const; /* * \func read @@ -139,17 +133,8 @@ struct SupportBlock final * \param[out] data std::unique_ptr<[]> that will hold the data read from the file. */ // Same as above but allocates the memory - void read(const std::string& id, - size_t numThreads, - std::unique_ptr& data) const; - void read(const std::string& id, - size_t numThreads, - std::unique_ptr& data) const - { - std::unique_ptr data_; - read(id, numThreads, data_); - data.reset(reinterpret_cast(data_.release())); - } + std::vector read(const std::string& id, size_t numThreads) const; + void read(const std::string& id, size_t numThreads, mem::ScopedArray&) const; // for existing SWIG bindings /* * \func readAll @@ -163,22 +148,10 @@ struct SupportBlock final * \param[out] data std::unique_ptr<[]> that will hold the data read from the file. * */ - void readAll(size_t numThreads, - std::unique_ptr& data) const; - void readAll(size_t numThreads, - std::unique_ptr& data) const - { - std::unique_ptr data_; - readAll(numThreads, data_); - data.reset(reinterpret_cast(data_.release())); - } - + std::vector readAll(size_t numThreads) const; + void readAll(size_t numThreads, mem::ScopedArray&) const; // for existing SWIG bindings private: - //! Initialize mOffsets for each array - // both for uncompressed and compressed data - void initialize(); - const std::shared_ptr mInStream; cphd::Data mData; const int64_t mSupportOffset; // offset in bytes to start of SupportBlock diff --git a/six/modules/c++/cphd/include/cphd/TestDataGenerator.h b/six/modules/c++/cphd/include/cphd/TestDataGenerator.h index c61846bd28..4767dd32db 100644 --- a/six/modules/c++/cphd/include/cphd/TestDataGenerator.h +++ b/six/modules/c++/cphd/include/cphd/TestDataGenerator.h @@ -121,16 +121,22 @@ inline cphd::SignalArrayFormat getSignalArrayFormat(size_t writeDataSize) template -void setUpData(Metadata& metadata, - const types::RowCol& dims, - const std::vector& writeData) +Metadata setUpData(const types::RowCol& dims, + const std::vector& writeData, + const std::string* pSignalCompressionID = nullptr) { + Data data; + if (pSignalCompressionID != nullptr) + { + data.signalCompressionID = *pSignalCompressionID; + } const size_t numChannels = 1; for (size_t ii = 0; ii < numChannels; ++ii) { - metadata.data.channels.push_back( + data.channels.push_back( cphd::Data::Channel(dims.row, dims.col)); } + Metadata metadata(std::move(data)); if (!writeData.empty()) { @@ -157,6 +163,15 @@ void setUpData(Metadata& metadata, } setUpMetadata(metadata); + + return metadata; +} +template +Metadata setUpData(const std::string& signalCompressionID, + const types::RowCol& dims, + const std::vector& writeData) +{ + return setUpData(dims, writeData, &signalCompressionID); } } diff --git a/six/modules/c++/cphd/source/BaseFileHeader.cpp b/six/modules/c++/cphd/source/BaseFileHeader.cpp index ed9d7433a4..851f61f5b1 100644 --- a/six/modules/c++/cphd/source/BaseFileHeader.cpp +++ b/six/modules/c++/cphd/source/BaseFileHeader.cpp @@ -46,7 +46,7 @@ bool BaseFileHeader::isCPHD(io::SeekableInputStream& inStream) return (::strncmp(buf, FILE_TYPE, 4) == 0); } -std::string BaseFileHeader::readVersion(io::SeekableInputStream& inStream) +std::string BaseFileHeader::strReadVersion(io::SeekableInputStream& inStream) { char buf[128]; inStream.seek(0, io::Seekable::START); @@ -64,6 +64,28 @@ std::string BaseFileHeader::readVersion(io::SeekableInputStream& inStream) return ret; } +Version BaseFileHeader::readVersion(io::SeekableInputStream& inStream) +{ + return toVersion(strReadVersion(inStream)); +} +Version BaseFileHeader::toVersion(const std::string& strVersion) +{ + #define SIX_cphd_FileHeader_setVersion_map_entry(v) { to_string(v), v} // avoid copy/paste errors + static const std::map string_to_vesion + { + { "1.0", Version::v1_0_0}, // existing files; should be "1.0.0" + SIX_cphd_FileHeader_setVersion_map_entry(Version::v1_0_0), + SIX_cphd_FileHeader_setVersion_map_entry(Version::v1_0_1), + SIX_cphd_FileHeader_setVersion_map_entry(Version::v1_1_0), + }; + #undef SIX_cphd_FileHeader_setVersion_map_entry + const auto it = string_to_vesion.find(strVersion); + if (it != string_to_vesion.end()) + { + return it->second; + } + throw std::logic_error("Unkown 'Version' value."); +} void BaseFileHeader::tokenize(const std::string& in, const std::string& delimiter, @@ -87,8 +109,7 @@ void BaseFileHeader::blockReadHeader(io::SeekableInputStream& inStream, static const char ERROR_MSG[] = "CPHD file malformed: Header must terminate with '\\f\\n'"; - std::vector buf(blockSize + 1); - std::fill(buf.begin(), buf.end(), static_cast(0)); + std::vector buf(blockSize + 1, static_cast(0)); headerBlock.clear(); // read each block in succession diff --git a/six/modules/c++/cphd/source/ByteSwap.cpp b/six/modules/c++/cphd/source/ByteSwap.cpp index f39f096ecb..929db6be0d 100644 --- a/six/modules/c++/cphd/source/ByteSwap.cpp +++ b/six/modules/c++/cphd/source/ByteSwap.cpp @@ -251,8 +251,7 @@ void byteSwapAndPromote(const void* input, ::byteSwapAndPromote(input, dims, numThreads, output); break; default: - throw except::Exception(Ctxt( - "Unexpected element size " + std::to_string(elementSize))); + throw except::Exception(Ctxt("Unexpected element size " + std::to_string(elementSize))); } } @@ -266,20 +265,16 @@ void byteSwapAndScale(const void* input, switch (elementSize) { case 2: - ::byteSwapAndScale(input, dims, scaleFactors, numThreads, - output); + ::byteSwapAndScale(input, dims, scaleFactors, numThreads, output); break; case 4: - ::byteSwapAndScale(input, dims, scaleFactors, numThreads, - output); + ::byteSwapAndScale(input, dims, scaleFactors, numThreads, output); break; case 8: - ::byteSwapAndScale(input, dims, scaleFactors, numThreads, - output); + ::byteSwapAndScale(input, dims, scaleFactors, numThreads, output); break; default: - throw except::Exception(Ctxt( - "Unexpected element size " + std::to_string(elementSize))); + throw except::Exception(Ctxt("Unexpected element size " + std::to_string(elementSize))); } } } diff --git a/six/modules/c++/cphd/source/CPHDReader.cpp b/six/modules/c++/cphd/source/CPHDReader.cpp index 999a2712d5..40258717e3 100644 --- a/six/modules/c++/cphd/source/CPHDReader.cpp +++ b/six/modules/c++/cphd/source/CPHDReader.cpp @@ -35,38 +35,25 @@ #include #include -namespace cphd -{ -CPHDReader::CPHDReader(std::shared_ptr inStream, - size_t numThreads, - const std::vector& schemaPaths, - std::shared_ptr logger) -{ - initialize(inStream, numThreads, logger, schemaPaths); -} - -CPHDReader::CPHDReader(const std::string& fromFile, +cphd::CPHDReader::CPHDReader(const std::string& fromFile, size_t numThreads, const std::vector& schemaPaths, std::shared_ptr logger) + : CPHDReader(std::make_shared(fromFile), numThreads, schemaPaths, logger) { - initialize(std::make_shared(fromFile), - numThreads, logger, schemaPaths); } -void CPHDReader::initialize(std::shared_ptr inStream, - size_t numThreads, - std::shared_ptr logger, - const std::vector& schemaPaths_) +static cphd::Metadata fromXML(io::SeekableInputStream& inStream, + const std::vector& schemaPaths_, + std::shared_ptr logger, + const cphd::FileHeader& mFileHeader) { - mFileHeader.read(*inStream); - // Read in the XML string - inStream->seek(mFileHeader.getXMLBlockByteOffset(), io::Seekable::START); + inStream.seek(mFileHeader.getXMLBlockByteOffset(), io::Seekable::START); six::MinidomParser xmlParser; xmlParser.preserveCharacterData(true); - xmlParser.parse(*inStream, gsl::narrow(mFileHeader.getXMLBlockSize())); + xmlParser.parse(inStream, gsl::narrow(mFileHeader.getXMLBlockSize())); if (logger.get() == nullptr) { @@ -76,8 +63,16 @@ void CPHDReader::initialize(std::shared_ptr inStream, std::vector schemaPaths; std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), [](const std::string& s) { return s; }); - mMetadata = CPHDXMLControl(logger.get()).fromXML(xmlParser.getDocument(), schemaPaths); + return cphd::CPHDXMLControl(logger.get()).fromXML(xmlParser.getDocument(), schemaPaths); +} +cphd::CPHDReader::CPHDReader(std::shared_ptr inStream, + size_t numThreads, + const std::vector& schemaPaths_, + std::shared_ptr logger) + : mFileHeader(cphd::FileHeader::read(*inStream)), + mMetadata(fromXML(*inStream, schemaPaths_, logger, mFileHeader)) +{ mSupportBlock = std::make_unique(inStream, mMetadata.data, mFileHeader); // Load the PVPBlock into memory @@ -88,4 +83,3 @@ void CPHDReader::initialize(std::shared_ptr inStream, mWideband = std::make_unique(inStream, mMetadata, mFileHeader.getSignalBlockByteOffset(), mFileHeader.getSignalBlockSize()); } -} diff --git a/six/modules/c++/cphd/source/CPHDWriter.cpp b/six/modules/c++/cphd/source/CPHDWriter.cpp index aafbe4ad8c..9d649c18f6 100644 --- a/six/modules/c++/cphd/source/CPHDWriter.cpp +++ b/six/modules/c++/cphd/source/CPHDWriter.cpp @@ -39,6 +39,12 @@ namespace cphd { +static Version getVersion(const Metadata& metadata) +{ + Version retval; + metadata.getVersion(retval); + return retval; +} CPHDWriter::CPHDWriter(const Metadata& metadata, std::shared_ptr outStream, @@ -50,7 +56,8 @@ CPHDWriter::CPHDWriter(const Metadata& metadata, mScratchSpaceSize(scratchSpaceSize), mNumThreads(numThreads), mSchemaPaths(schemaPaths), - mStream(outStream) + mStream(outStream), + mHeader(getVersion(metadata)) { // Get the correct dataWriter. // The CPHD file needs to be big endian. @@ -76,9 +83,7 @@ void CPHDWriter::writeMetadata(size_t supportSize, { const auto xmlMetadata(CPHDXMLControl().toXMLString(mMetadata, mSchemaPaths)); - Version cphdVersion; - mMetadata.getVersion(cphdVersion); - mHeader.setVersion(cphdVersion); + mHeader.setVersion(getVersion(mMetadata)); // update classification and release info if (!six::Init::isUndefined( @@ -127,17 +132,35 @@ void CPHDWriter::writeCompressedCPHDDataImpl(const std::byte* data, (*mDataWriter)(data, mMetadata.data.getCompressedSignalSize(channel), 1); } -void CPHDWriter::writeSupportDataImpl(const std::byte* data, - size_t numElements, - size_t elementSize) +static auto make_span(std::span data, const cphd::Data::SupportArray& dataArray) { - (*mDataWriter)(data, numElements, elementSize); + const auto pData = data.data() + dataArray.arrayByteOffset; + return sys::make_span(pData, dataArray.size_bytes()); } +void CPHDWriter::writeSupportDataImpl(std::span data, size_t elementSize) +{ + (*mDataWriter)(data, elementSize); +} +void CPHDWriter::writeSupportData(std::span data) +{ + for (auto&& mapEntry : mMetadata.data.supportArrayMap) + { + auto&& dataArray = mapEntry.second; + + // Move inputstream head to offset of particular support array + mStream->seek(mHeader.getSupportBlockByteOffset() + dataArray.arrayByteOffset, io::SeekableOutputStream::START); + writeSupportDataImpl(make_span(data, dataArray), dataArray.bytesPerElement); + } + // Move inputstream head to the end of the support block after all supports have been written + mStream->seek(mHeader.getSupportBlockByteOffset() + mHeader.getSupportBlockSize(), io::SeekableOutputStream::START); +} + + template void CPHDWriter::write(const PVPBlock& pvpBlock, - const T* widebandData, - const sys::ubyte* supportData) + const T* widebandData, + std::span supportData) { // Write File header and metadata to file // Padding is added in writeMetadata @@ -147,7 +170,7 @@ void CPHDWriter::write(const PVPBlock& pvpBlock, // Padding is added in writeSupportData if (mMetadata.data.getNumSupportArrays() != 0) { - if (supportData == nullptr) + if (supportData.empty()) { throw except::Exception(Ctxt("SupportData is not provided")); } @@ -170,44 +193,13 @@ void CPHDWriter::write(const PVPBlock& pvpBlock, elementsWritten += numElements; } } - -// For compressed data -template void CPHDWriter::write(const PVPBlock& pvpBlock, - const sys::ubyte* widebandData, - const sys::ubyte* supportData); -template void CPHDWriter::write(const PVPBlock& pvpBlock, - const std::byte* widebandData, - const std::byte* supportData); - -template void CPHDWriter::write( - const PVPBlock& pvpBlock, - const cphd::zint8_t* widebandData, - const sys::ubyte* supportData); - -template void CPHDWriter::write( - const PVPBlock& pvpBlock, - const cphd::zint16_t* widebandData, - const sys::ubyte* supportData); - -template void CPHDWriter::write( - const PVPBlock& pvpBlock, - const cphd::zfloat* widebandData, - const sys::ubyte* supportData); - -template void CPHDWriter::write( - const PVPBlock& pvpBlock, - const cphd::zint8_t* widebandData, - const std::byte* supportData); - -template void CPHDWriter::write( - const PVPBlock& pvpBlock, - const cphd::zint16_t* widebandData, - const std::byte* supportData); - -template void CPHDWriter::write( - const PVPBlock& pvpBlock, - const cphd::zfloat* widebandData, - const std::byte* supportData); +template void CPHDWriter::write(const PVPBlock&, const std::byte* widebandData, std::span); // For compressed data +template void CPHDWriter::write(const PVPBlock&, const cphd::zint8_t* widebandData, std::span); +template void CPHDWriter::write(const PVPBlock&, const cphd::zint16_t* widebandData, std::span); +template void CPHDWriter::write(const PVPBlock&, const cphd::zfloat* widebandData, std::span); +//template void CPHDWriter::write(const PVPBlock&, const cphd::zint8_t* widebandData, std::span); +//template void CPHDWriter::write(const PVPBlock&, const cphd::zint16_t* widebandData, std::span); +//template void CPHDWriter::write(const PVPBlock&, const cphd::zfloat* widebandData, std::span); void CPHDWriter::writeMetadata(const PVPBlock& pvpBlock) { @@ -274,20 +266,18 @@ void CPHDWriter::writeCPHDData(const T* data, size_t numElements, size_t channel) { + const void* const pData = data; if (mMetadata.data.isCompressed()) { - writeCompressedCPHDDataImpl(reinterpret_cast(data), - channel); + writeCompressedCPHDDataImpl(static_cast(pData), channel); } else { if (mElementSize != sizeof(T)) { - throw except::Exception( - Ctxt("Incorrect buffer data type used for metadata!")); + throw except::Exception(Ctxt("Incorrect buffer data type used for metadata!")); } - writeCPHDDataImpl(reinterpret_cast(data), - numElements); + writeCPHDDataImpl(static_cast(pData), numElements); } } diff --git a/six/modules/c++/cphd/source/CPHDXMLControl.cpp b/six/modules/c++/cphd/source/CPHDXMLControl.cpp index 34fcd42c87..fd7d1092bd 100644 --- a/six/modules/c++/cphd/source/CPHDXMLControl.cpp +++ b/six/modules/c++/cphd/source/CPHDXMLControl.cpp @@ -105,23 +105,6 @@ std::unique_ptr CPHDXMLControl::toXML( return doc; } -static std::unordered_map makeVersionUriMap_() -{ - std::map result; - CPHDXMLControl::getVersionUriMap(result); - - std::unordered_map retval; - for (const auto& version_and_uri : result) - { - retval[to_string(version_and_uri.first)] = version_and_uri.second; - } - return retval; -} -std::unordered_map CPHDXMLControl::getVersionUriMap() // for existing code -{ - static const auto retval = makeVersionUriMap_(); - return retval; -} static std::map getVersionUriMap_() { static const std::map retval = { @@ -131,27 +114,16 @@ static std::map getVersionUriMap_() }; return retval; } -void CPHDXMLControl::getVersionUriMap(std::map& result) +std::map CPHDXMLControl::getVersionUriMap() { - result = getVersionUriMap_(); + return getVersionUriMap_(); } std::unique_ptr CPHDXMLControl::toXMLImpl(const Metadata& metadata) { Version cphdVersion; metadata.getVersion(cphdVersion); - - static const auto versionUriMap = getVersionUriMap_(); - const auto it = versionUriMap.find(cphdVersion); - if (it != versionUriMap.end()) - { - return getParser(it->second)->toXML(metadata); - } - std::ostringstream ostr; - ostr << "The version " << metadata.getVersion() << " is invalid. " - << "Check if version is valid or " - << "add a entry to versionUriMap"; - throw except::Exception(Ctxt(ostr.str())); + return getParser(cphdVersion)->toXML(metadata); } /* FROM XML */ @@ -182,10 +154,7 @@ std::unique_ptr CPHDXMLControl::fromXML(const xml::lite::Document* doc { six::XMLControl::validate(doc, schemaPaths, mLog); } - std::unique_ptr metadata = fromXMLImpl(doc); - const xml::lite::Uri uri(doc->getRootElement()->getUri()); - metadata->setVersion(uriToVersion(uri)); - return metadata; + return fromXMLImpl(doc); } Metadata CPHDXMLControl::fromXML(const xml::lite::Document& doc, const std::vector& schemaPaths) { @@ -193,22 +162,25 @@ Metadata CPHDXMLControl::fromXML(const xml::lite::Document& doc, const std::vect std::transform(schemaPaths.begin(), schemaPaths.end(), std::back_inserter(schemaPaths_), [](const std::filesystem::path& p) { return p.string(); }); auto result = fromXML(&doc, schemaPaths_); - return *(result.release()); + + auto retval = std::move(*(result.release())); + return retval; } std::unique_ptr CPHDXMLControl::fromXMLImpl(const xml::lite::Document* doc) { const xml::lite::Uri uri(doc->getRootElement()->getUri()); - return getParser(uri)->fromXML(doc); + const auto version = uriToVersion(uri); + return getParser(version)->fromXML(doc); } std::unique_ptr -CPHDXMLControl::getParser(const xml::lite::Uri& uri) const +CPHDXMLControl::getParser(Version version) const { - return std::make_unique(uri.value, false, mLog); + return std::make_unique(version, false, mLog); } -Version CPHDXMLControl::uriToVersion(const xml::lite::Uri& uri) const +Version CPHDXMLControl::uriToVersion(const xml::lite::Uri& uri) { static const auto versionUriMap = getVersionUriMap_(); for (const auto& p : versionUriMap) diff --git a/six/modules/c++/cphd/source/CPHDXMLParser.cpp b/six/modules/c++/cphd/source/CPHDXMLParser.cpp index 1ea206ba35..ba02cbddd7 100644 --- a/six/modules/c++/cphd/source/CPHDXMLParser.cpp +++ b/six/modules/c++/cphd/source/CPHDXMLParser.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #define ENFORCESPEC 0 @@ -45,12 +46,18 @@ typedef xml::lite::Element* XMLElem; namespace cphd { +static std::string strUriFromVersion(Version version) +{ + auto&& map = CPHDXMLControl::getVersionUriMap(); + return map.at(version).value; +} + CPHDXMLParser::CPHDXMLParser( - const std::string& uri, + Version version, bool addClassAttributes, logging::Logger* log, bool ownLog) : - six::XMLParser(uri, addClassAttributes, log, ownLog), + six::XMLParser(strUriFromVersion(version), addClassAttributes, log, ownLog), mCommon(getDefaultURI(), addClassAttributes, getDefaultURI(), log) { } @@ -1012,13 +1019,12 @@ XMLElem CPHDXMLParser::toXML(const MatchInformation& matchInfo, XMLElem parent) /* * FROM XML */ - -std::unique_ptr CPHDXMLParser::fromXML( - const xml::lite::Document* doc) +Metadata CPHDXMLParser::fromXML(const xml::lite::Document& doc, Version version) { - std::unique_ptr cphd(new Metadata()); + Metadata retval(version); + auto cphd = &retval; - const auto root = doc->getRootElement(); + const auto root = doc.getRootElement(); XMLElem collectionIDXML = getFirstAndOnly(root, "CollectionID"); XMLElem globalXML = getFirstAndOnly(root, "Global"); @@ -1084,7 +1090,13 @@ std::unique_ptr CPHDXMLParser::fromXML( fromXML(matchInfoXML, *(cphd->matchInfo)); } - return cphd; + return retval; +} +std::unique_ptr CPHDXMLParser::fromXML(const xml::lite::Document* doc) +{ + const auto version = CPHDXMLControl::uriToVersion(xml::lite::Uri(getDefaultURI())); + auto result = fromXML(*doc, version); + return std::make_unique(std::move(result)); } void CPHDXMLParser::fromXML(const xml::lite::Element* collectionIDXML, CollectionInformation& collectionID) diff --git a/six/modules/c++/cphd/source/DataWriter.cpp b/six/modules/c++/cphd/source/DataWriter.cpp index 9cc3a5393a..41516cb773 100644 --- a/six/modules/c++/cphd/source/DataWriter.cpp +++ b/six/modules/c++/cphd/source/DataWriter.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #undef min @@ -53,18 +54,27 @@ DataWriterLittleEndian::DataWriterLittleEndian( size_t scratchSize) : DataWriterLittleEndian(*stream, numThreads, scratchSize) { } -void DataWriterLittleEndian::operator()(const void* pData, size_t numElements, size_t elementSize) + +static auto adjust_span(std::span data, size_t dataProcessed) { - const auto data = static_cast(pData); + const auto pData = data.data() + dataProcessed; + const auto size = data.size() - dataProcessed; + return sys::make_span(pData, size); +} +void DataWriterLittleEndian::operator()(std::span pData, size_t elementSize) +{ size_t dataProcessed = 0; - const size_t dataSize = numElements * elementSize; + const auto dataSize = pData.size(); while (dataProcessed < dataSize) { const size_t dataToProcess = std::min(mScratch.size(), dataSize - dataProcessed); - memcpy(mScratch.data(), data + dataProcessed, dataToProcess); + const auto data = adjust_span(pData, dataProcessed); + const auto begin = data.begin(); + const auto end = begin + dataToProcess; + mScratch.assign(begin, end); cphd::byteSwap(mScratch.data(), elementSize, @@ -86,9 +96,9 @@ DataWriterBigEndian::DataWriterBigEndian( size_t numThreads) : DataWriterBigEndian(*stream, numThreads) { } -void DataWriterBigEndian::operator()(const void* data, size_t numElements, size_t elementSize) +void DataWriterBigEndian::operator()(std::span pData, size_t /*elementSize*/) { - mStream.write(data, numElements * elementSize); + mStream.write(pData.data(), pData.size()); } } diff --git a/six/modules/c++/cphd/source/FileHeader.cpp b/six/modules/c++/cphd/source/FileHeader.cpp index f818aaec15..933ebcebb3 100644 --- a/six/modules/c++/cphd/source/FileHeader.cpp +++ b/six/modules/c++/cphd/source/FileHeader.cpp @@ -21,6 +21,8 @@ */ #include #include +#include +#include #include #include @@ -32,27 +34,30 @@ namespace cphd { -static const char* getDefaultVersion() +Version FileHeader::defaultVersion = Version::v1_0_1; +Version FileHeader::getDefaultVersion() { - static const auto defaultVersion = to_string(Version::v1_0_1); - return defaultVersion.c_str(); + return defaultVersion; +} +void FileHeader::setDefaultVersion(Version version) +{ + defaultVersion = version; +} +static const char* getDefaultVersion_() +{ + static std::string strDefaultVersion; // returning a pointer + strDefaultVersion = to_string(FileHeader::getDefaultVersion()); + return strDefaultVersion.c_str(); } -const char* FileHeader::DEFAULT_VERSION = getDefaultVersion(); -FileHeader::FileHeader() : - mVersion(DEFAULT_VERSION), - mXmlBlockSize(0), - mXmlBlockByteOffset(0), - mPvpBlockSize(0), - mPvpBlockByteOffset(0), - mSignalBlockSize(0), - mSignalBlockByteOffset(0), - mSupportBlockSize(0), - mSupportBlockByteOffset(0) +const char* FileHeader::DEFAULT_VERSION = getDefaultVersion_(); +FileHeader::FileHeader(Version version) : mVersion(version) { + // reinitialize in case value has changed + DEFAULT_VERSION = getDefaultVersion_(); } -void FileHeader::read(io::SeekableInputStream& inStream) +FileHeader FileHeader::read(io::SeekableInputStream& inStream) { if (!isCPHD(inStream)) { @@ -60,8 +65,16 @@ void FileHeader::read(io::SeekableInputStream& inStream) } // Read mVersion first - mVersion = readVersion(inStream); - + FileHeader retval(readVersion(inStream)); + retval.readAfterValidVersion(inStream); + return retval; +} +void FileHeader::readImpl(io::SeekableInputStream&) +{ + throw std::logic_error("Should use 'static' read()"); +} +void FileHeader::readAfterValidVersion(io::SeekableInputStream& inStream) +{ // Block read the header for more efficient IO KeyValuePair headerEntry; std::string headerBlock; @@ -162,7 +175,7 @@ std::string FileHeader::toString() const // Send the values as they are, no calculating // File type - os << FILE_TYPE << "/" << mVersion << LINE_TERMINATOR; + os << FILE_TYPE << "/" << to_string(mVersion) << LINE_TERMINATOR; // Classification fields, if present if (mSupportBlockSize > 0) @@ -193,16 +206,20 @@ std::string FileHeader::toString() const std::string FileHeader::getVersion() const { - return mVersion; + return to_string(mVersion); +} +void FileHeader::getVersion(Version& version) const +{ + version = mVersion; } -void FileHeader::setVersion(const std::string& version) +void FileHeader::setVersion(Version version) { mVersion = version; } -void FileHeader::setVersion(Version version) +void FileHeader::setVersion(const std::string& strVersion) { - setVersion(to_string(version)); + setVersion(FileHeader::toVersion(strVersion)); } size_t FileHeader::set(int64_t xmlBlockSize, @@ -286,7 +303,7 @@ int64_t FileHeader::getPvpPadBytes() const std::ostream& operator<< (std::ostream& os, const FileHeader& fh) { os << "FileHeader::\n" - << " mVersion : " << fh.mVersion << "\n" + << " mVersion : " << to_string(fh.mVersion) << "\n" << " mXmlBlockSize : " << fh.mXmlBlockSize << "\n" << " mXmlBlockByteOffset : " << fh.mXmlBlockByteOffset << "\n" << " mSupportBlockSize : " << fh.mSupportBlockSize << "\n" diff --git a/six/modules/c++/cphd/source/Metadata.cpp b/six/modules/c++/cphd/source/Metadata.cpp index 542f6407bd..fd166e64ca 100644 --- a/six/modules/c++/cphd/source/Metadata.cpp +++ b/six/modules/c++/cphd/source/Metadata.cpp @@ -26,10 +26,14 @@ namespace cphd { -Metadata::Metadata() +Metadata::Metadata(Version version) { - // Default version defined in cphd::FileHeader - setVersion(FileHeader::DEFAULT_VERSION); + setVersion(version); +} +Metadata::Metadata(Data&& data) + : Metadata(FileHeader::getDefaultVersion()) // Default version defined in cphd::FileHeader +{ + this->data = std::move(data); } size_t Metadata::getNumChannels() const @@ -75,30 +79,14 @@ void Metadata::getVersion(Version& version) const { version = mVersion; } - -void Metadata::setVersion(const std::string& version) -{ - if (version == "1.0.0") - { - setVersion(Version::v1_0_0); - } - else if (version == "1.0.1") - { - setVersion(Version::v1_0_1); - } - else if (version == "1.1.0") - { - setVersion(Version::v1_1_0); - } - else - { - throw std::invalid_argument("Unknown version string: " + version); - } -} void Metadata::setVersion(Version version) { mVersion = version; } +void Metadata::setVersion(const std::string& strVersion) +{ + setVersion(FileHeader::toVersion(strVersion)); +} bool Metadata::operator==(const Metadata& other) const { diff --git a/six/modules/c++/cphd/source/PVP.cpp b/six/modules/c++/cphd/source/PVP.cpp index ab675012aa..9b65b7396d 100644 --- a/six/modules/c++/cphd/source/PVP.cpp +++ b/six/modules/c++/cphd/source/PVP.cpp @@ -41,11 +41,6 @@ APVPType::APVPType() } Pvp::Pvp() -{ - initialize(); -} - -void Pvp::initialize() { // Default size and formats for each PVP // listed in Table 11-6 CPHD1.0 Spec @@ -256,6 +251,14 @@ std::ostream& operator<< (std::ostream& os, const Pvp& p) { os << " SIGNAL : \n" << p.signal << "\n"; } + if (has_value(p.txAntenna)) + { + os << " TxAntenna : \n" << p.txAntenna << "\n"; + } + if (has_value(p.rcvAntenna)) + { + os << " RcvAntenna : \n" << p.rcvAntenna << "\n"; + } for (auto it = p.addedPVP.begin(); it != p.addedPVP.end(); ++it) { os << " Additional Parameter : " << it->second << "\n"; diff --git a/six/modules/c++/cphd/source/SupportBlock.cpp b/six/modules/c++/cphd/source/SupportBlock.cpp index 5c72f7b52c..36d2e47bc2 100644 --- a/six/modules/c++/cphd/source/SupportBlock.cpp +++ b/six/modules/c++/cphd/source/SupportBlock.cpp @@ -42,14 +42,9 @@ SupportBlock::SupportBlock(const std::string& pathname, const cphd::Data& data, int64_t startSupport, int64_t sizeSupport) : - mInStream(std::make_shared(pathname)), - mData(data), - mSupportOffset(startSupport), - mSupportSize(sizeSupport) + SupportBlock(std::make_shared(pathname), data, startSupport, sizeSupport) { - initialize(); } - SupportBlock::SupportBlock(std::shared_ptr inStream, const cphd::Data& data, int64_t startSupport, @@ -59,23 +54,18 @@ SupportBlock::SupportBlock(std::shared_ptr inStream, mSupportOffset(startSupport), mSupportSize(sizeSupport) { - initialize(); + //! Initialize mOffsets for each array both for uncompressed and compressed data + // Trusting data has the right offsets + for (auto kv : mData.supportArrayMap) + { + mOffsets[kv.first] = mSupportOffset + kv.second.arrayByteOffset; + } } SupportBlock::SupportBlock(std::shared_ptr inStream, const cphd::Data& data, const cphd::FileHeader& fileHeader): SupportBlock(inStream, data, fileHeader.getSupportBlockByteOffset(), fileHeader.getSupportBlockSize()) { - initialize(); -} - -void SupportBlock::initialize() -{ - // Trusting data has the right offsets - for (auto it = mData.supportArrayMap.begin(); it != mData.supportArrayMap.end(); ++it) - { - mOffsets[it->first] = mSupportOffset + it->second.arrayByteOffset; - } } int64_t SupportBlock::getFileOffset(const std::string& id) const @@ -89,53 +79,57 @@ int64_t SupportBlock::getFileOffset(const std::string& id) const void SupportBlock::read(const std::string& id, size_t numThreads, - const mem::BufferView& data) const + const mem::BufferView& data_) const +{ + void* pData = data_.data; + auto data = sys::make_span(pData, data_.size); + read(id, numThreads, data); +} +void SupportBlock::read(const std::string& id, size_t numThreads, std::span data) const { const size_t minSize = mData.getSupportArrayById(id).getSize(); - if (data.size < minSize) + if (data.size() < minSize) { std::ostringstream ostr; - ostr << "Need at least " << minSize << " bytes but only got " - << data.size; + ostr << "Need at least " << minSize << " bytes but only got " << data.size(); throw except::Exception(Ctxt(ostr.str())); } + // Perform the read // Compute the byte offset into this SupportArray in the CPHD file // First to the start of the first support array we're going to read int64_t inOffset = getFileOffset(id); - auto dataPtr = data.data; + auto dataPtr = data.data(); mInStream->seek(inOffset, io::FileInputStream::START); - size_t size = mData.getSupportArrayById(id).getSize(); - mInStream->read(dataPtr, size); + size_t bytes = mData.getSupportArrayById(id).size_bytes(); + mInStream->read(dataPtr, bytes); if ((std::endian::native == std::endian::little) && mData.getElementSize(id) > 1) { cphd::byteSwap(dataPtr, mData.getElementSize(id), - mData.getSupportArrayById(id).numRows * - mData.getSupportArrayById(id).numCols, + mData.getSupportArrayById(id).size(), numThreads); } } -void SupportBlock::readAll(size_t numThreads, - std::unique_ptr& data) const +std::vector SupportBlock::readAll(size_t numThreads) const { - data = std::make_unique(mSupportSize); + std::vector retval(mSupportSize); for (auto& supportArrayMapPair : mData.supportArrayMap) { const size_t bufSize = supportArrayMapPair.second.getSize(); - read(supportArrayMapPair.first, numThreads, mem::BufferView(&data[supportArrayMapPair.second.arrayByteOffset], bufSize)); + auto pData = &retval[supportArrayMapPair.second.arrayByteOffset]; + read(supportArrayMapPair.first, numThreads, sys::make_span(pData, bufSize)); } + return retval; } -void SupportBlock::read(const std::string& id, - size_t numThreads, - std::unique_ptr& data) const +std::vector SupportBlock::read(const std::string& id, size_t numThreads) const { - const size_t bufSize = mData.getSupportArrayById(id).getSize(); - data = std::make_unique(bufSize); - read(id, numThreads, mem::BufferView(data.get(), bufSize)); + std::vector retval(mData.getSupportArrayById(id).getSize()); + read(id, numThreads, sys::make_span(retval)); + return retval; } std::ostream& operator<< (std::ostream& os, const SupportBlock& d) diff --git a/six/modules/c++/cphd/tests/test_compare_cphd.cpp b/six/modules/c++/cphd/tests/test_compare_cphd.cpp index 00a072546f..4c5d929147 100644 --- a/six/modules/c++/cphd/tests/test_compare_cphd.cpp +++ b/six/modules/c++/cphd/tests/test_compare_cphd.cpp @@ -63,10 +63,19 @@ bool compareCPHDData(const std::byte* data1, return true; } -bool compareSupportData(const std::unique_ptr& data1, - const std::unique_ptr& data2, - size_t size) +bool compareSupportData(const std::vector& data1, const std::vector& data2, size_t size) { + if (data1.size() != size) + { + std::cerr << "Support data1.size()=" << data1.size() << " should be: " << size << "\n"; + return false; + } + if (data2.size() != size) + { + std::cerr << "Support data2.size()=" << data2.size() << " should be: " << size << "\n"; + return false; + } + for (size_t ii = 0; ii < size; ++ii) { if (data1[ii] != data2[ii]) @@ -178,10 +187,8 @@ bool checkCPHD(const std::string& pathname1, const std::string& pathname2, size_ } // Check support block - std::unique_ptr readPtr1; - reader1.getSupportBlock().readAll(numThreads, readPtr1); - std::unique_ptr readPtr2; - reader2.getSupportBlock().readAll(numThreads, readPtr2); + const auto readPtr1 = reader1.getSupportBlock().readAll(numThreads); + const auto readPtr2 = reader2.getSupportBlock().readAll(numThreads); if (!compareSupportData(readPtr1, readPtr2, reader1.getMetadata().data.getAllSupportSize())) { std::cerr << "SupportBlock does not match \n"; diff --git a/six/modules/c++/cphd/tests/test_round_trip.cpp b/six/modules/c++/cphd/tests/test_round_trip.cpp index f6f43c161f..e608a7ef5d 100644 --- a/six/modules/c++/cphd/tests/test_round_trip.cpp +++ b/six/modules/c++/cphd/tests/test_round_trip.cpp @@ -59,8 +59,7 @@ void testRoundTrip(const std::string& inPathname, const std::string& outPathname // Read SupportBlock const cphd::SupportBlock& supportBlock = reader.getSupportBlock(); - std::unique_ptr readPtr; - supportBlock.readAll(numThreads, readPtr); + const auto readPtr = supportBlock.readAll(numThreads); // Read PVPBlock const cphd::PVPBlock& pvpBlock = reader.getPVPBlock(); @@ -75,8 +74,7 @@ void testRoundTrip(const std::string& inPathname, const std::string& outPathname cphd::CPHDWriter writer(reader.getMetadata(), outPathname, schemaPathnames, numThreads); // Declare and allocate the wideband data storage - std::unique_ptr data; - data.reset(new std::byte[header.getSignalBlockSize()]); + const auto data = std::make_unique(header.getSignalBlockSize()); // Check if signal data is compressed if (metadata.data.isCompressed()) @@ -91,7 +89,7 @@ void testRoundTrip(const std::string& inPathname, const std::string& outPathname writer.write( pvpBlock, data.get(), - readPtr.get()); + sys::make_span(readPtr)); } else { @@ -112,19 +110,19 @@ void testRoundTrip(const std::string& inPathname, const std::string& outPathname writer.write( pvpBlock, reinterpret_cast(data.get()), - readPtr.get()); + sys::make_span(readPtr)); break; case cphd::SignalArrayFormat::CI4: writer.write( pvpBlock, reinterpret_cast(data.get()), - readPtr.get()); + sys::make_span(readPtr)); break; case cphd::SignalArrayFormat::CF8: writer.write( pvpBlock, reinterpret_cast(data.get()), - readPtr.get()); + sys::make_span(readPtr)); break; } } diff --git a/six/modules/c++/cphd/unittests/test_compressed_signal_block_round.cpp b/six/modules/c++/cphd/unittests/test_compressed_signal_block_round.cpp index a768a0c958..b897bd57d1 100644 --- a/six/modules/c++/cphd/unittests/test_compressed_signal_block_round.cpp +++ b/six/modules/c++/cphd/unittests/test_compressed_signal_block_round.cpp @@ -97,7 +97,7 @@ std::vector checkCompressedData(const std::string& pathname, const cphd::Wideband& wideband = reader.getWideband(); std::vector readData(dims.area()); - std::span data(readData.data(), readData.size()); + auto data = sys::make_span(readData); for (size_t ii = 0; ii < reader.getMetadata().data.getNumChannels(); ++ii) { wideband.read(ii, data); @@ -124,9 +124,7 @@ bool runTest(const std::vector& writeData) io::TempFile tempfile; const size_t numThreads = std::thread::hardware_concurrency(); const types::RowCol dims(128, 256); - cphd::Metadata meta = cphd::Metadata(); - meta.data.signalCompressionID = "Huffman"; - cphd::setUpData(meta, dims, writeData); + auto meta = cphd::setUpData("Huffman", dims, writeData); cphd::setPVPXML(meta.pvp); cphd::PVPBlock pvpBlock(meta.pvp, meta.data); diff --git a/six/modules/c++/cphd/unittests/test_cphd_xml_control.cpp b/six/modules/c++/cphd/unittests/test_cphd_xml_control.cpp index d1737e76c4..16ee18daab 100644 --- a/six/modules/c++/cphd/unittests/test_cphd_xml_control.cpp +++ b/six/modules/c++/cphd/unittests/test_cphd_xml_control.cpp @@ -881,27 +881,31 @@ static std::string testCPHDXMLBody() return std::string(xmlBody); } -std::string testCPHDXML(const std::string& version) +std::string testCPHDXML_(cphd::Version version) { - auto uri = cphd::CPHDXMLControl::getVersionUriMap().at(version); + const auto map = cphd::CPHDXMLControl::getVersionUriMap(); + const auto uri = map.at(version); return "\n" + testCPHDXMLBody() + "\n"; } +std::u8string testCPHDXML(cphd::Version version) +{ + return str::u8FromString(testCPHDXML_(version)); +} -void runTest(const std::string& testName, const std::string& version) +void runTest(const std::string& testName, cphd::Version version) { - auto xmlString = testCPHDXML(version); - io::StringStream cphdStream; - cphdStream.write(xmlString.c_str(), xmlString.size()); + const auto xmlString = testCPHDXML(version); + io::U8StringStream cphdStream; + cphdStream.write(xmlString); xml::lite::MinidomParser xmlParser; xmlParser.preserveCharacterData(true); xmlParser.parse(cphdStream, cphdStream.available()); - const std::unique_ptr metadata = - cphd::CPHDXMLControl().fromXML(xmlParser.getDocument()); + const auto metadata = cphd::CPHDXMLControl().fromXML(xmlParser.getDocument()); // CollectionID TEST_ASSERT_EQ(metadata->collectionID.collectorName, "Collector"); @@ -1161,8 +1165,9 @@ void runTest(const std::string& testName, const std::string& version) TEST_CASE(testVersions) { - auto versionUriMap = cphd::CPHDXMLControl::getVersionUriMap(); - for (auto version : {"1.0.0", "1.0.1", "1.1.0"}) + const auto versionUriMap = cphd::CPHDXMLControl::getVersionUriMap(); + + for (auto version : {cphd::Version::v1_0_0, cphd::Version::v1_0_1, cphd::Version::v1_1_0 }) { TEST_ASSERT_TRUE( versionUriMap.find(version) != versionUriMap.end()); @@ -1171,10 +1176,11 @@ TEST_CASE(testVersions) TEST_CASE(testReadXML) { - for (auto pair : cphd::CPHDXMLControl::getVersionUriMap()) + const auto map = cphd::CPHDXMLControl::getVersionUriMap(); + for (auto pair : map) { auto& version = pair.first; - runTest("testReadXML" + version, version); + runTest("testReadXML" + to_string(version), version); } } diff --git a/six/modules/c++/cphd/unittests/test_file_header.cpp b/six/modules/c++/cphd/unittests/test_file_header.cpp index f56058c6db..46005c57cd 100644 --- a/six/modules/c++/cphd/unittests/test_file_header.cpp +++ b/six/modules/c++/cphd/unittests/test_file_header.cpp @@ -24,7 +24,6 @@ #include #include "TestCase.h" -const char* FILE_TYPE_HEADER = "CPHD/1.0\n"; const char* FILE_HEADER_CONTENT = "CPHD/1.0\n" "XML_BLOCK_SIZE := 3\n" "XML_BLOCK_BYTE_OFFSET := 10\n" @@ -38,19 +37,29 @@ const char* FILE_HEADER_CONTENT = "CPHD/1.0\n" "RELEASE_INFO := UNRESTRICTED\n" "\f\n"; -TEST_CASE(testReadVersion) +TEST_CASE(testReadVersion1_0) { + const char* FILE_TYPE_HEADER = "CPHD/1.0\n"; + + io::ByteStream fileTypeHeader; + fileTypeHeader.write(FILE_TYPE_HEADER, strlen(FILE_TYPE_HEADER)); + TEST_ASSERT(cphd::FileHeader::readVersion(fileTypeHeader) == cphd::Version::v1_0_0); +} + +TEST_CASE(testReadVersion1_1_0) +{ + const char* FILE_TYPE_HEADER = "CPHD/1.1.0\n"; + io::ByteStream fileTypeHeader; fileTypeHeader.write(FILE_TYPE_HEADER, strlen(FILE_TYPE_HEADER)); - TEST_ASSERT_EQ(cphd::FileHeader::readVersion(fileTypeHeader), "1.0"); + TEST_ASSERT(cphd::FileHeader::readVersion(fileTypeHeader) == cphd::Version::v1_1_0); } TEST_CASE(testCanReadHeaderWithoutBreaking) { io::ByteStream fileHeaderContentWithSupport; fileHeaderContentWithSupport.write(FILE_HEADER_CONTENT, strlen(FILE_HEADER_CONTENT)); - cphd::FileHeader headerWithSupport; - headerWithSupport.read(fileHeaderContentWithSupport); + const auto headerWithSupport = cphd::FileHeader::read(fileHeaderContentWithSupport); TEST_ASSERT_EQ(headerWithSupport.getXMLBlockSize(), 3); TEST_ASSERT_EQ(headerWithSupport.getXMLBlockByteOffset(), 10); TEST_ASSERT_EQ(headerWithSupport.getSupportBlockSize(), 4); @@ -74,8 +83,7 @@ TEST_CASE(testCanReadHeaderWithoutBreaking) "RELEASE_INFO := UNRESTRICTED\n" "\f\n"; fileHeaderContentWithoutSupport.write(fileHeaderTxtNoSupport); - cphd::FileHeader headerWithoutSupport; - headerWithoutSupport.read(fileHeaderContentWithoutSupport); + const auto headerWithoutSupport = cphd::FileHeader::read(fileHeaderContentWithoutSupport); TEST_ASSERT_EQ(headerWithoutSupport.getXMLBlockSize(), 3); TEST_ASSERT_EQ(headerWithoutSupport.getXMLBlockByteOffset(), 10); TEST_ASSERT_EQ(headerWithoutSupport.getSupportBlockSize(), 0); @@ -98,7 +106,7 @@ TEST_CASE(testCanReadHeaderWithoutBreaking) "\f\n"; io::ByteStream fileHeaderContentWithoutClassification; fileHeaderContentWithoutClassification.write(fileHeaderTxtNoClass); - TEST_THROWS(cphd::FileHeader().read(fileHeaderContentWithoutClassification)); + TEST_THROWS(cphd::FileHeader::read(fileHeaderContentWithoutClassification)); std::string fileHeaderTxtInvalid = "CPHD/1.0\n" "XML_BLOCK_SIZE := foo\n" @@ -112,21 +120,19 @@ TEST_CASE(testCanReadHeaderWithoutBreaking) "\f\n"; io::ByteStream fileHeaderContentWithInvalidValue; fileHeaderContentWithInvalidValue.write(fileHeaderTxtInvalid); - TEST_THROWS(cphd::FileHeader().read(fileHeaderContentWithInvalidValue)); + TEST_THROWS(cphd::FileHeader::read(fileHeaderContentWithInvalidValue)); } TEST_CASE(testRoundTripHeader) { io::ByteStream headerContent; headerContent.write(FILE_HEADER_CONTENT, strlen(FILE_HEADER_CONTENT)); - cphd::FileHeader header; - header.read(headerContent); + const auto header = cphd::FileHeader::read(headerContent); std::string outString = header.toString(); io::ByteStream roundTrippedContent; roundTrippedContent.write(outString); - cphd::FileHeader roundTrippedHeader; - roundTrippedHeader.read(roundTrippedContent); + const auto roundTrippedHeader = cphd::FileHeader::read(roundTrippedContent); TEST_ASSERT_EQ(header.getXMLBlockSize(), roundTrippedHeader.getXMLBlockSize()); @@ -151,7 +157,8 @@ TEST_CASE(testRoundTripHeader) } TEST_MAIN( - TEST_CHECK(testReadVersion); + TEST_CHECK(testReadVersion1_0); + TEST_CHECK(testReadVersion1_1_0); TEST_CHECK(testCanReadHeaderWithoutBreaking); TEST_CHECK(testRoundTripHeader); ) diff --git a/six/modules/c++/cphd/unittests/test_pvp_block_round.cpp b/six/modules/c++/cphd/unittests/test_pvp_block_round.cpp index 93ec99c9c6..2a7673b76c 100644 --- a/six/modules/c++/cphd/unittests/test_pvp_block_round.cpp +++ b/six/modules/c++/cphd/unittests/test_pvp_block_round.cpp @@ -174,8 +174,7 @@ TEST_CASE(testPVPBlockSimple) const types::RowCol dims(128, 256); const auto writeData = generateComplexData(dims.area()); const bool scale = false; - cphd::Metadata meta = cphd::Metadata(); - cphd::setUpData(meta, dims, writeData); + auto meta = cphd::setUpData(dims, writeData); cphd::setPVPXML(meta.pvp); cphd::PVPBlock pvpBlock(meta.pvp, meta.data); std::vector addedParams; @@ -197,8 +196,7 @@ TEST_CASE(testPVPBlockOptional) const types::RowCol dims(128, 256); const auto writeData = generateComplexData(dims.area()); const bool scale = false; - cphd::Metadata meta = cphd::Metadata(); - cphd::setUpData(meta, dims, writeData); + auto meta = cphd::setUpData(dims, writeData); cphd::setPVPXML(meta.pvp); meta.pvp.setOffset(27, meta.pvp.fxN1); meta.pvp.setOffset(28, meta.pvp.fxN2); @@ -223,8 +221,7 @@ TEST_CASE(testPVPBlockAdditional) const types::RowCol dims(128, 256); const auto writeData = generateComplexData(dims.area()); const bool scale = false; - cphd::Metadata meta = cphd::Metadata(); - cphd::setUpData(meta, dims, writeData); + auto meta = cphd::setUpData(dims, writeData); cphd::setPVPXML(meta.pvp); meta.pvp.setCustomParameter(1, 27, "F8", "param1"); meta.pvp.setCustomParameter(1, 28, "F8", "param2"); diff --git a/six/modules/c++/cphd/unittests/test_read_wideband.cpp b/six/modules/c++/cphd/unittests/test_read_wideband.cpp index e1f4007c4b..a6a59a2891 100644 --- a/six/modules/c++/cphd/unittests/test_read_wideband.cpp +++ b/six/modules/c++/cphd/unittests/test_read_wideband.cpp @@ -31,13 +31,14 @@ TEST_CASE(testReadCompressedChannel) input->write("1234"); input->seek(0, io::Seekable::START); - cphd::Metadata metadata; - metadata.data.channels.resize(1); - metadata.data.channels[0].numSamples = 4; - metadata.data.channels[0].numVectors = 8; - metadata.data.signalArrayFormat = cphd::SignalArrayFormat::CI2; - metadata.data.signalCompressionID = "Test Compression"; - metadata.data.channels[0].compressedSignalSize = 4; + cphd::Data data; + data.channels.resize(1); + data.channels[0].numSamples = 4; + data.channels[0].numVectors = 8; + data.signalArrayFormat = cphd::SignalArrayFormat::CI2; + data.signalCompressionID = "Test Compression"; + data.channels[0].compressedSignalSize = 4; + const cphd::Metadata metadata(std::move(data)); cphd::Wideband wideband(input, metadata, 0, 4); @@ -57,13 +58,13 @@ TEST_CASE(testReadUncompressedChannel) input->write("12345678"); input->seek(0, io::Seekable::START); - cphd::Metadata metadata; - metadata.data.channels.resize(1); - metadata.data.channels[0].numSamples = 1; - metadata.data.channels[0].numVectors = 4; - metadata.data.signalArrayFormat = cphd::SignalArrayFormat::CI2; - metadata.data.channels[0].compressedSignalSize = - six::Init::undefined(); + cphd::Data data; + data.channels.resize(1); + data.channels[0].numSamples = 1; + data.channels[0].numVectors = 4; + data.signalArrayFormat = cphd::SignalArrayFormat::CI2; + data.channels[0].compressedSignalSize = six::Init::undefined(); + const cphd::Metadata metadata(std::move(data)); cphd::Wideband wideband(input, metadata, 0, 4); @@ -79,11 +80,12 @@ TEST_CASE(testReadUncompressedChannel) TEST_CASE(testReadChannelSubset) { - cphd::Metadata metadata; - metadata.data.channels.resize(1); - metadata.data.channels[0].numSamples = 2; - metadata.data.channels[0].numVectors = 4; - metadata.data.signalArrayFormat = cphd::SignalArrayFormat::CI2; + cphd::Data data; + data.channels.resize(1); + data.channels[0].numSamples = 2; + data.channels[0].numVectors = 4; + data.signalArrayFormat = cphd::SignalArrayFormat::CI2; + const cphd::Metadata metadata(std::move(data)); auto input = std::make_shared(); input->write("0A1B"); @@ -147,13 +149,14 @@ TEST_CASE(testCannotDoPartialReadOfCompressedChannel) input->write("1234"); input->seek(0, io::Seekable::START); - cphd::Metadata metadata; - metadata.data.channels.resize(1); - metadata.data.channels[0].numSamples = 4; - metadata.data.channels[0].numVectors = 8; - metadata.data.signalArrayFormat = cphd::SignalArrayFormat::CI2; - metadata.data.signalCompressionID = "Test Compression"; - metadata.data.channels[0].compressedSignalSize = 4; + cphd::Data data; + data.channels.resize(1); + data.channels[0].numSamples = 4; + data.channels[0].numVectors = 8; + data.signalArrayFormat = cphd::SignalArrayFormat::CI2; + data.signalCompressionID = "Test Compression"; + data.channels[0].compressedSignalSize = 4; + const cphd::Metadata metadata(std::move(data)); cphd::Wideband wideband(input, metadata, 0, 4); diff --git a/six/modules/c++/cphd/unittests/test_signal_block_round.cpp b/six/modules/c++/cphd/unittests/test_signal_block_round.cpp index 3953c8bd63..fbf83115ae 100644 --- a/six/modules/c++/cphd/unittests/test_signal_block_round.cpp +++ b/six/modules/c++/cphd/unittests/test_signal_block_round.cpp @@ -153,8 +153,7 @@ bool runTest(bool scale, const TCxVector& writeData) const types::RowCol dims(128, 128); const std::vector scaleFactors = generateScaleFactors(dims.row, scale); - cphd::Metadata meta = cphd::Metadata(); - setUpData(meta, dims, writeData); + auto meta = cphd::setUpData(dims, writeData); cphd::setPVPXML(meta.pvp); cphd::PVPBlock pvpBlock(meta.pvp, meta.data); diff --git a/six/modules/c++/cphd/unittests/test_support_block_round.cpp b/six/modules/c++/cphd/unittests/test_support_block_round.cpp index 0e075b58b3..9dbb37eec8 100644 --- a/six/modules/c++/cphd/unittests/test_support_block_round.cpp +++ b/six/modules/c++/cphd/unittests/test_support_block_round.cpp @@ -86,7 +86,7 @@ void writeSupportData(const std::string& outPathname, size_t numThreads, } cphd::CPHDWriter writer(metadata, outPathname, std::vector(), numThreads); writer.writeMetadata(pvpBlock); - writer.writeSupportData(writeData.data()); + writer.writeSupportData(writeData); writer.writePVPData(pvpBlock); } @@ -98,10 +98,8 @@ std::vector checkSupportData( cphd::CPHDReader reader(pathname, numThreads); const cphd::SupportBlock& supportBlock = reader.getSupportBlock(); - std::unique_ptr readPtr; - supportBlock.readAll(numThreads, readPtr); - - std::vector readData(readPtr.get(), readPtr.get() + reader.getMetadata().data.getAllSupportSize()); + const auto bytes = supportBlock.readAll(numThreads); + std::vector readData(bytes.data(), bytes.data() + reader.getMetadata().data.getAllSupportSize()); return readData; } @@ -134,8 +132,7 @@ bool runTest(const std::vector& writeData) { io::TempFile tempfile; const size_t numThreads = 1; - cphd::Metadata meta = cphd::Metadata(); - cphd::setUpData(meta, types::RowCol(128,256), std::vector()); + auto meta = cphd::setUpData(types::RowCol(128,256), std::vector()); setSupport(meta.data); cphd::setPVPXML(meta.pvp); cphd::PVPBlock pvpBlock(meta.pvp, meta.data); diff --git a/six/modules/c++/cphd03/include/cphd03/FileHeader.h b/six/modules/c++/cphd03/include/cphd03/FileHeader.h index 93c91f6e9b..d0568528aa 100644 --- a/six/modules/c++/cphd03/include/cphd03/FileHeader.h +++ b/six/modules/c++/cphd03/include/cphd03/FileHeader.h @@ -43,7 +43,11 @@ class FileHeader : public cphd::BaseFileHeader { } - virtual void read(io::SeekableInputStream& inStream); + void readImpl(io::SeekableInputStream&) override; + void read(io::SeekableInputStream& inStream) + { + readImpl(inStream); + } // Convert header info to string (for writing to file) // Does not include section terminator string diff --git a/six/modules/c++/cphd03/source/FileHeader.cpp b/six/modules/c++/cphd03/source/FileHeader.cpp index 2957f435d6..f0890eac79 100644 --- a/six/modules/c++/cphd03/source/FileHeader.cpp +++ b/six/modules/c++/cphd03/source/FileHeader.cpp @@ -44,7 +44,7 @@ FileHeader::FileHeader() : { } -void FileHeader::read(io::SeekableInputStream& inStream) +void FileHeader::readImpl(io::SeekableInputStream& inStream) { if (!isCPHD(inStream)) { @@ -52,7 +52,7 @@ void FileHeader::read(io::SeekableInputStream& inStream) } // Read mVersion first - mVersion = readVersion(inStream); + mVersion = strReadVersion(inStream); // Block read the header for more efficient IO KeyValuePair headerEntry; diff --git a/six/modules/c++/samples/test_dump_images.cpp b/six/modules/c++/samples/test_dump_images.cpp index 4d7b3ca0d1..28c04934d1 100644 --- a/six/modules/c++/samples/test_dump_images.cpp +++ b/six/modules/c++/samples/test_dump_images.cpp @@ -161,7 +161,7 @@ int main(int argc, char** argv) for (size_t i = 0, total = container->size(); i < total; ++i) { const six::Data* data = container->getData(i); - std::string filename = FmtX("%s_DES_%d.xml", base.string(), i); + const auto filename = FmtX("%s_DES_%d.xml", base.string(), i); const auto xmlFile = fs::path(outputDir) / filename; io::FileOutputStream xmlStream(xmlFile.string()); diff --git a/six/modules/c++/samples/test_parse_xml.cpp b/six/modules/c++/samples/test_parse_xml.cpp index 7e4d0c2a0d..582ab937da 100644 --- a/six/modules/c++/samples/test_parse_xml.cpp +++ b/six/modules/c++/samples/test_parse_xml.cpp @@ -95,7 +95,7 @@ std::vector extractXML(std::string inputFile, nitf::Off size = deReader.getSize(); const auto typeID = subheader.typeID(); - const std::string outputFile = FmtX("%s-%s%d.xml", prefix, typeID, i); + const auto outputFile = FmtX("%s-%s%d.xml", prefix, typeID, i); const auto fileName = outputDir / outputFile; { std::vector xml(size); diff --git a/six/modules/c++/scene/tests/test_scene.cpp b/six/modules/c++/scene/tests/test_scene.cpp index a37c6c9a6a..a38ea343b4 100644 --- a/six/modules/c++/scene/tests/test_scene.cpp +++ b/six/modules/c++/scene/tests/test_scene.cpp @@ -37,11 +37,7 @@ class SceneInfo { std::map::const_iterator p = mVecs.find(k); if (p == mVecs.end()) - throw except::Exception( - Ctxt( - FmtX("Key not found: %s", k.c_str()) - ) - ); + throw except::Exception(Ctxt(FmtX("Key not found: %s", k))); return p->second; } @@ -72,11 +68,7 @@ SceneInfo loadSceneInfo(std::string infoProps) std::string v = d[k].str(); std::vector toks = str::Tokenizer(v, ","); if (toks.size() != 3) - throw except::Exception( - Ctxt( - FmtX("Expected triple, received: %s", v.c_str()) - ) - ); + throw except::Exception(Ctxt(FmtX("Expected triple, received: %s", v))); Vector3 vec; vec[0] = str::toType(toks[0]); diff --git a/six/modules/c++/six.sicd/source/ComplexXMLParser.cpp b/six/modules/c++/six.sicd/source/ComplexXMLParser.cpp index 6d1e212bea..5b4777d3ea 100644 --- a/six/modules/c++/six.sicd/source/ComplexXMLParser.cpp +++ b/six/modules/c++/six.sicd/source/ComplexXMLParser.cpp @@ -832,9 +832,7 @@ XMLElem ComplexXMLParser::convertRcvChanProcToXML( } else { - throw except::Exception(Ctxt(FmtX( - "[RcvChanProc] is a manditory field in ImageFormation in %s", - strVersion.c_str()))); + throw except::Exception(Ctxt(FmtX("[RcvChanProc] is a manditory field in ImageFormation in %s", strVersion))); } } @@ -878,9 +876,7 @@ XMLElem ComplexXMLParser::convertDistortionToXML( } else { - throw except::Exception(Ctxt(FmtX( - "[Distortion] is a maditory field of ImageFormation in %s", - strVersion.c_str()))); + throw except::Exception(Ctxt(FmtX("[Distortion] is a maditory field of ImageFormation in %s", strVersion))); } } diff --git a/six/modules/c++/six.sicd/source/ComplexXMLParser10x.cpp b/six/modules/c++/six.sicd/source/ComplexXMLParser10x.cpp index ed192d7aa2..e228777e2a 100644 --- a/six/modules/c++/six.sicd/source/ComplexXMLParser10x.cpp +++ b/six/modules/c++/six.sicd/source/ComplexXMLParser10x.cpp @@ -283,9 +283,7 @@ XMLElem ComplexXMLParser10x::convertAntennaParamArrayToXML( } else { - throw except::Exception(Ctxt(FmtX( - "[Array] is a mandatory field in AntennaParams of [%s] in 1.0", - name.c_str()))); + throw except::Exception(Ctxt(FmtX("[Array] is a mandatory field in AntennaParams of [%s] in 1.0", name))); } } diff --git a/six/modules/c++/six.sidd/source/DerivedClassification.cpp b/six/modules/c++/six.sidd/source/DerivedClassification.cpp index 5c0eb865ae..dfe850632a 100644 --- a/six/modules/c++/six.sidd/source/DerivedClassification.cpp +++ b/six/modules/c++/six.sidd/source/DerivedClassification.cpp @@ -48,8 +48,7 @@ void DerivedClassification::setSecurity(const std::string& prefix, const std::string fieldKey = NITFImageInfo::generateFieldKey(NITFImageInfo::REL, prefix); - log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", - fieldKey.c_str(), releasableToStr.c_str()))); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", fieldKey, releasableToStr))); } if (!classifiedBy.empty()) @@ -58,8 +57,7 @@ void DerivedClassification::setSecurity(const std::string& prefix, std::string fieldKey = NITFImageInfo::generateFieldKey(NITFImageInfo::CAUT, prefix); - log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", - fieldKey.c_str(), classifiedBy.c_str()))); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", fieldKey, classifiedBy))); // classifiedBy attribute represents the name of the original // classification authority @@ -68,9 +66,7 @@ void DerivedClassification::setSecurity(const std::string& prefix, fieldKey = NITFImageInfo::generateFieldKey(NITFImageInfo::CATP, prefix); - log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", - fieldKey.c_str(), - classAuthorityType.c_str()))); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", fieldKey, classAuthorityType))); } if (!classificationReason.empty()) @@ -79,9 +75,7 @@ void DerivedClassification::setSecurity(const std::string& prefix, const std::string fieldKey = NITFImageInfo::generateFieldKey(NITFImageInfo::CRSN, prefix); - log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", - fieldKey.c_str(), - classificationReason.c_str()))); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", fieldKey, classificationReason))); } // By default, mark as exempt from automatic declassification @@ -96,9 +90,7 @@ void DerivedClassification::setSecurity(const std::string& prefix, const std::string fieldKey = NITFImageInfo::generateFieldKey(NITFImageInfo::DCDT, prefix); - log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", - fieldKey.c_str(), - declassDateStr.c_str()))); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", fieldKey, declassDateStr))); // Declassify on a specific date declassType = "DD"; @@ -109,11 +101,8 @@ void DerivedClassification::setSecurity(const std::string& prefix, security.getClassificationText().set(declassEvent); const std::string fieldKey = - NITFImageInfo::generateFieldKey(NITFImageInfo::CLTX, - prefix); - log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", - fieldKey.c_str(), - declassEvent.c_str()))); + NITFImageInfo::generateFieldKey(NITFImageInfo::CLTX, prefix); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", fieldKey, declassEvent))); // Declassify upon occurrence of an event declassType = "DE"; @@ -133,11 +122,8 @@ void DerivedClassification::setSecurity(const std::string& prefix, exemptedSourceType); const std::string fieldKey = - NITFImageInfo::generateFieldKey(NITFImageInfo::DCXM, - prefix); - log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", - fieldKey.c_str(), - exemptedSourceType.c_str()))); + NITFImageInfo::generateFieldKey(NITFImageInfo::DCXM, prefix); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", fieldKey, exemptedSourceType))); // Exempt from automatic declassification declassType = "X"; @@ -172,11 +158,8 @@ void DerivedClassification::setSecurity(const std::string& prefix, security.getDeclassificationExemption().set(declassExemption); const std::string fieldKey = - NITFImageInfo::generateFieldKey(NITFImageInfo::DCXM, - prefix); - log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", - fieldKey.c_str(), - declassExemption.c_str()))); + NITFImageInfo::generateFieldKey(NITFImageInfo::DCXM, prefix); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", fieldKey, declassExemption))); // Exempt from automatic declassification declassType = "X"; @@ -186,11 +169,8 @@ void DerivedClassification::setSecurity(const std::string& prefix, // Now that we've gone through all the things that could modify the // declassification type, set it security.getDeclassificationType().set(declassType); - log.debug(Ctxt(FmtX( - "Setting NITF [%s] from sicd/sidd: [%s]", - NITFImageInfo::generateFieldKey(NITFImageInfo::DCTP, - prefix).c_str(), - declassType.c_str()))); + log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]", + NITFImageInfo::generateFieldKey(NITFImageInfo::DCTP, prefix), declassType))); } } diff --git a/six/modules/c++/six.sidd/source/DerivedXMLParser.cpp b/six/modules/c++/six.sidd/source/DerivedXMLParser.cpp index 4f88c5676c..88e01b510f 100644 --- a/six/modules/c++/six.sidd/source/DerivedXMLParser.cpp +++ b/six/modules/c++/six.sidd/source/DerivedXMLParser.cpp @@ -1960,9 +1960,7 @@ XMLElem DerivedXMLParser::convertSFAGeometryToXML( } else { - throw except::InvalidArgumentException(Ctxt(FmtX( - "Invalid geo type: [%s]", - geoType.c_str()))); + throw except::InvalidArgumentException(Ctxt(FmtX("Invalid geo type: [%s]", geoType))); } return geoElem; diff --git a/six/modules/c++/six.sidd/source/GeoTIFFWriteControl.cpp b/six/modules/c++/six.sidd/source/GeoTIFFWriteControl.cpp index b25417f69e..7dae50f656 100644 --- a/six/modules/c++/six.sidd/source/GeoTIFFWriteControl.cpp +++ b/six/modules/c++/six.sidd/source/GeoTIFFWriteControl.cpp @@ -177,9 +177,7 @@ void GeoTIFFWriteControl::setupIFD(const DerivedData* data, } ifd->addEntry(tiff::KnownTags::PHOTOMETRIC_INTERPRETATION, photoInterp); - addStringArray(ifd, - "ImageDescription", - FmtX("SIDD: %s", data->getName().c_str())); + addStringArray(ifd, "ImageDescription", FmtX("SIDD: %s", data->getName())); constexpr unsigned short orientation = 1; ifd->addEntry("Orientation", orientation); diff --git a/six/modules/c++/six/include/six/Enum.h b/six/modules/c++/six/include/six/Enum.h index a4fcfff35b..b35ca0fde7 100644 --- a/six/modules/c++/six/include/six/Enum.h +++ b/six/modules/c++/six/include/six/Enum.h @@ -67,7 +67,7 @@ namespace details inline T index(const std::map& map, const std::string& v) { const auto result = nitf::details::index(map, v); - const except::InvalidFormatException ex(Ctxt(FmtX("Invalid enum value: %s", v.c_str()))); + const except::InvalidFormatException ex(Ctxt(FmtX("Invalid enum value: %s", v))); return nitf::details::value(result, ex); } template diff --git a/six/modules/c++/six/source/Utilities.cpp b/six/modules/c++/six/source/Utilities.cpp index fd12d2838a..03746abc3d 100644 --- a/six/modules/c++/six/source/Utilities.cpp +++ b/six/modules/c++/six/source/Utilities.cpp @@ -324,8 +324,7 @@ PixelType six::toType(const std::string& s) { auto p = PixelType::toType(s); if (p == PixelType::NOT_SET) - throw except::Exception( - Ctxt(FmtX("Type not understood [%s]", s.c_str()))); + throw except::Exception(Ctxt(FmtX("Type not understood [%s]", s))); return p; } diff --git a/six/modules/c++/six/source/XMLControl.cpp b/six/modules/c++/six/source/XMLControl.cpp index f049de526b..87f0120df7 100644 --- a/six/modules/c++/six/source/XMLControl.cpp +++ b/six/modules/c++/six/source/XMLControl.cpp @@ -447,5 +447,5 @@ std::string six::getSchemaPath(std::vector& schemaPaths, bool tryTo } } - throw except::IOException(Ctxt(FmtX("Directory does not exist: '%s'", schemaPath.c_str()))); + throw except::IOException(Ctxt(FmtX("Directory does not exist: '%s'", schemaPath))); }