diff --git a/externals/coda-oss/ReleaseNotes.md b/externals/coda-oss/ReleaseNotes.md index f473ce0160..bf8f97f3af 100644 --- a/externals/coda-oss/ReleaseNotes.md +++ b/externals/coda-oss/ReleaseNotes.md @@ -11,12 +11,18 @@ ``` # coda-oss Release Notes -## [Release 2023-??-??](https://github.com/mdaus/coda-oss/releases/tag/2023-??-??) +## [Release 2023-06-05](https://github.com/mdaus/coda-oss/releases/tag/2023-06-05) * *zlib* updated to [1.2.13](https://github.com/madler/zlib/releases/tag/v1.2.13). * new `mem::ComplexView` class to make it easier to process complex data stored in parallel. * adjust compiler flags for clean *CMake* builds. * wrap common "file open" routines (e.g., `fopen()`) to support `sys::expandEnvironmentVariables()`. * add header-only [HighFive](https://github.com/BlueBrain/HighFive) HDF5-wrapper library. +* Added a handful of [HighFive](https://github.com/BlueBrain/HighFive) utility routines. +* `mt::transform_async()` removed, it doesn't match C++17 techniques.' +* Revamp `sys::byteSwap()` for improved type-safety and + [better performance](https://devblogs.microsoft.com/cppblog/a-tour-of-4-msvc-backend-improvements/). + * Added case-insensitive string comparison utilties: `str::eq()` and `str::ne()`; + `xml::lite::Uri`s compare case-insensitive. ## [Release 2022-12-14](https://github.com/mdaus/coda-oss/releases/tag/2022-12-14) * removed remaining vestiges of `std::auto_ptr`, provide `mem::AutoPtr` for the tiny handful of diff --git a/externals/coda-oss/modules/c++/cli/source/ArgumentParser.cpp b/externals/coda-oss/modules/c++/cli/source/ArgumentParser.cpp index b2d47fab92..2a31bda458 100644 --- a/externals/coda-oss/modules/c++/cli/source/ArgumentParser.cpp +++ b/externals/coda-oss/modules/c++/cli/source/ArgumentParser.cpp @@ -294,6 +294,7 @@ std::unique_ptr cli::ArgumentParser::parse(const std::string& prog std::map longOptionsFlags; std::vector positionalArgs; + positionalArgs.reserve(mArgs.size()); for (auto& arg_ : mArgs) { cli::Argument* arg = arg_.get(); @@ -336,6 +337,7 @@ std::unique_ptr cli::ArgumentParser::parse(const std::string& prog } std::vector < std::string > explodedArgs; + explodedArgs.reserve(args.size()); // next, check for combined short options for (size_t i = 0, s = args.size(); i < s; ++i) { diff --git a/externals/coda-oss/modules/c++/coda-oss-lite.vcxproj b/externals/coda-oss/modules/c++/coda-oss-lite.vcxproj index d5e4e5cf81..2baf272d84 100644 --- a/externals/coda-oss/modules/c++/coda-oss-lite.vcxproj +++ b/externals/coda-oss/modules/c++/coda-oss-lite.vcxproj @@ -232,6 +232,7 @@ + diff --git a/externals/coda-oss/modules/c++/coda-oss-lite.vcxproj.filters b/externals/coda-oss/modules/c++/coda-oss-lite.vcxproj.filters index a8119ff835..1e84491f23 100644 --- a/externals/coda-oss/modules/c++/coda-oss-lite.vcxproj.filters +++ b/externals/coda-oss/modules/c++/coda-oss-lite.vcxproj.filters @@ -747,6 +747,9 @@ sys + + sys + diff --git a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/bit.h b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/bit.h index 32ef77862e..271935ab0a 100644 --- a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/bit.h +++ b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/bit.h @@ -18,9 +18,9 @@ * License along with this program; If not, http://www.gnu.org/licenses/. * */ +#pragma once #ifndef CODA_OSS_coda_oss_bit_h_INCLUDED_ #define CODA_OSS_coda_oss_bit_h_INCLUDED_ -#pragma once #include #include @@ -58,28 +58,28 @@ namespace coda_oss #if defined(_MSC_VER) // These routines should generate a single instruction; see // https://devblogs.microsoft.com/cppblog/a-tour-of-4-msvc-backend-improvements/ - inline uint16_t byteswap(uint16_t val) + inline uint16_t byteswap(uint16_t val) noexcept { return _byteswap_ushort(val); } - inline uint32_t byteswap(uint32_t val) + inline uint32_t byteswap(uint32_t val) noexcept { return _byteswap_ulong(val); } - inline uint64_t byteswap(uint64_t val) + inline uint64_t byteswap(uint64_t val) noexcept { return _byteswap_uint64(val); } #elif defined(__GNUC__) - inline uint16_t byteswap(uint16_t val) + inline uint16_t byteswap(uint16_t val) noexcept { return bswap_16(val); } - inline uint32_t byteswap(uint32_t val) + inline uint32_t byteswap(uint32_t val) noexcept { return bswap_32(val); } - inline uint64_t byteswap(uint64_t val) + inline uint64_t byteswap(uint64_t val) noexcept { return bswap_64(val); } diff --git a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/span.h b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/span.h index b225f35fe1..6aff3b5d5a 100644 --- a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/span.h +++ b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/span.h @@ -19,9 +19,13 @@ * see . * */ +#pragma once #ifndef CODA_OSS_coda_oss_span_h_INCLUDED_ #define CODA_OSS_coda_oss_span_h_INCLUDED_ -#pragma once + +#include + +#include #include "coda_oss/namespace_.h" #include "coda_oss/span_.h" @@ -41,21 +45,32 @@ namespace coda_oss // https://en.cppreference.com/w/cpp/container/span/as_bytes template -span as_bytes(span s) noexcept +inline auto as_bytes(span s) noexcept { - const void* const p = s.data(); - return span(static_cast(p), s.size_bytes()); + // https://en.cppreference.com/w/cpp/types/is_trivially_copyable "... serialized to/from binary files ..." + static_assert(std::is_trivially_copyable::value, "must be 'trivially' copyable."); + + const void* const p_ = s.data(); + auto const p = static_cast(p_); + return span(p, s.size_bytes()); } template -span as_bytes(span s) noexcept +inline auto as_bytes(span s) noexcept { - return as_bytes(span(s.data(), s.size())); + const span s_(s.data(), s.size()); + return as_bytes(s_); } template -span as_writable_bytes(span s) noexcept +inline span as_writable_bytes(span s) noexcept { - void* const p = s.data(); - return span(static_cast(p), s.size_bytes()); + // https://en.cppreference.com/w/cpp/types/is_trivially_copyable "... serialized to/from binary files ..." + static_assert(std::is_trivially_copyable::value, "must be 'trivially' copyable."); + + static_assert(!std::is_const::value, "T cannot be 'const'"); + + void* const p_ = s.data(); + auto const p = static_cast(p_); + return span(p, s.size_bytes()); } } diff --git a/externals/coda-oss/modules/c++/config/include/config/Version.h b/externals/coda-oss/modules/c++/config/include/config/Version.h index bcb4979bdc..69944fc0b8 100644 --- a/externals/coda-oss/modules/c++/config/include/config/Version.h +++ b/externals/coda-oss/modules/c++/config/include/config/Version.h @@ -42,12 +42,12 @@ static_assert(CODA_OSS_MAKE_VERSION_MMPB(9999, 9999, 9999, 9999) <= UINT64_MAX, // Do this ala C++ ... we don't currently have major/minor/patch //#define CODA_OSS_VERSION_ 20210910L // c.f. __cplusplus -#define CODA_OSS_VERSION_ 2022 ## 0012 ## 0014 ## 0000 ## L +#define CODA_OSS_VERSION_ 2023 ## 0006 ## 0005 ## 0000 ## L // Use the same macros other projects might want to use; overkill for us. -#define CODA_OSS_VERSION_MAJOR 2022 -#define CODA_OSS_VERSION_MINOR 12 -#define CODA_OSS_VERSION_PATCH 14 +#define CODA_OSS_VERSION_MAJOR 2023 +#define CODA_OSS_VERSION_MINOR 6 +#define CODA_OSS_VERSION_PATCH 5 #define CODA_OSS_VERSION_BUILD 0 #define CODA_OSS_VERSION CODA_OSS_MAKE_VERSION_MMPB(CODA_OSS_VERSION_MAJOR, CODA_OSS_VERSION_MINOR, CODA_OSS_VERSION_PATCH, CODA_OSS_VERSION_BUILD) diff --git a/externals/coda-oss/modules/c++/mt/include/mt/RequestQueue.h b/externals/coda-oss/modules/c++/mt/include/mt/RequestQueue.h index cb0d8201c7..ad33a53a14 100644 --- a/externals/coda-oss/modules/c++/mt/include/mt/RequestQueue.h +++ b/externals/coda-oss/modules/c++/mt/include/mt/RequestQueue.h @@ -97,13 +97,13 @@ struct RequestQueue } // Check to see if its empty - inline bool isEmpty() + bool isEmpty() const { - return (mRequestQueue.size() == 0); + return mRequestQueue.empty(); } // Check the length - inline int length() + int length() const { return mRequestQueue.size(); } diff --git a/externals/coda-oss/modules/c++/net/source/URL.cpp b/externals/coda-oss/modules/c++/net/source/URL.cpp index 881a4b8547..8791e0c6bd 100644 --- a/externals/coda-oss/modules/c++/net/source/URL.cpp +++ b/externals/coda-oss/modules/c++/net/source/URL.cpp @@ -161,7 +161,7 @@ bool net::URLParams::contains(std::string key) const net::URLParams::ParamValues& net::URLParams::get(std::string key) { net::URLParams::Params::iterator it = mParams.find(key); - if (it == mParams.end() || it->second.size() == 0) + if (it == mParams.end() || it->second.empty()) throw except::NoSuchKeyException(Ctxt(key)); return it->second; } @@ -169,14 +169,14 @@ net::URLParams::ParamValues& net::URLParams::get(std::string key) const net::URLParams::ParamValues& net::URLParams::get(std::string key) const { net::URLParams::Params::const_iterator it = mParams.find(key); - if (it == mParams.end() || it->second.size() == 0) + if (it == mParams.end() || it->second.empty()) throw except::NoSuchKeyException(Ctxt(key)); return it->second; } std::string net::URLParams::getFirst(std::string key) const { net::URLParams::Params::const_iterator it = mParams.find(key); - if (it == mParams.end() || it->second.size() == 0) + if (it == mParams.end() || it->second.empty()) throw except::NoSuchKeyException(Ctxt(key)); return it->second.front(); } diff --git a/externals/coda-oss/modules/c++/polygon/include/polygon/Intersections.h b/externals/coda-oss/modules/c++/polygon/include/polygon/Intersections.h index 7b63b69b84..d73ac1f6d0 100644 --- a/externals/coda-oss/modules/c++/polygon/include/polygon/Intersections.h +++ b/externals/coda-oss/modules/c++/polygon/include/polygon/Intersections.h @@ -27,6 +27,7 @@ #include #include +#include namespace polygon { @@ -47,14 +48,13 @@ namespace polygon * square will have 1 pixel of its top edge missing. */ template -class Intersections +struct Intersections final { -public: /*! * \class Intersection * \brief Represents an intersection */ - struct Intersection + struct Intersection final { //! First (inclusive) column size_t first; @@ -63,7 +63,7 @@ class Intersections size_t last; //! \return Number of columns - size_t length() const + size_t length() const noexcept { return last - first + 1; } @@ -172,11 +172,10 @@ class Intersections types::RowCol offset) { std::vector > shiftedPoints(points); - for (size_t ii = 0; ii < shiftedPoints.size(); ++ii) + for (auto&& shiftedPoint : shiftedPoints) { // Get the polygon points with respect to the offset - shiftedPoints[ii].row -= offset.row; - shiftedPoints[ii].col -= offset.col; + shiftedPoint -= offset; // TODO: The original implementation did this (plus subtracted 0.5 // from each row and col which we're not doing here). @@ -184,7 +183,7 @@ class Intersections // right on a row, we skip drawing some rows // (test_draw_polygon will illustrate this). I wonder if we // could tweak the sl0 and sl1 logic to avoid this. - PointT& rowPoint(shiftedPoints[ii].row); + PointT& rowPoint(shiftedPoint.row); if (std::floor(rowPoint) == rowPoint) { // Add small amount to move it off the scan line @@ -195,7 +194,7 @@ class Intersections // We need to get all scanline intersections of polygon edges mIntersections.resize(dims.row); - const sys::SSize_T lastRow = static_cast(dims.row) - 1; + const auto lastRow = gsl::narrow(dims.row) - 1; for (size_t ii = 0; ii < shiftedPoints.size(); ++ii) { @@ -256,9 +255,9 @@ class Intersections // that situation. for (sys::SSize_T row = sl0; row <= sl1; ++row) { - const PointT delt = row - r0; - const PointT sli = c0 + delt * dcdr; - mIntersections[row].push_back(sli); + const auto delt = static_cast(row) - r0; + const auto sli = c0 + delt * dcdr; + mIntersections[gsl::narrow(row)].push_back(sli); } } @@ -273,6 +272,12 @@ class Intersections } } } + + // `const` member data means copy/move must be implemented + Intersections(const Intersections&) = delete; + Intersections& operator=(const Intersections&) = delete; + Intersections(Intersections&&) = delete; + Intersections& operator=(Intersections&&) = delete; private: const types::RowCol mDims; diff --git a/externals/coda-oss/modules/c++/sio.lite/source/FileHeader.cpp b/externals/coda-oss/modules/c++/sio.lite/source/FileHeader.cpp index f0bf8d77fd..8a7c8a40fc 100644 --- a/externals/coda-oss/modules/c++/sio.lite/source/FileHeader.cpp +++ b/externals/coda-oss/modules/c++/sio.lite/source/FileHeader.cpp @@ -204,6 +204,7 @@ void sio::lite::FileHeader::addUserData(const std::string& field, void sio::lite::FileHeader::addUserData(const std::string& field, int data) { std::vector vec; + vec.reserve(sizeof(int)); char* cData = (char*)&data; for (int i = 0, size = sizeof(int); i < size; ++i) vec.push_back((sys::byte)cData[i]); diff --git a/externals/coda-oss/modules/c++/str/include/str/Format.h b/externals/coda-oss/modules/c++/str/include/str/Format.h index b6a6be4263..2409438076 100644 --- a/externals/coda-oss/modules/c++/str/include/str/Format.h +++ b/externals/coda-oss/modules/c++/str/include/str/Format.h @@ -47,7 +47,7 @@ struct CODA_OSS_API Format final return mString; } - operator std::string& () + operator std::string& () noexcept { return mString; } diff --git a/externals/coda-oss/modules/c++/str/include/str/Manip.h b/externals/coda-oss/modules/c++/str/include/str/Manip.h index 9da33183ff..1f97ac941e 100644 --- a/externals/coda-oss/modules/c++/str/include/str/Manip.h +++ b/externals/coda-oss/modules/c++/str/include/str/Manip.h @@ -194,9 +194,9 @@ inline std::string join(const std::vector& toks, const std::string& with) if (toks.empty()) return ""; - const auto len = static_cast(toks.size()); + const auto len = toks.size(); std::ostringstream oss; - int i = 0; + size_t i = 0; for (; i < len - 1; i++) { oss << str::toString(toks[i]) << with; diff --git a/externals/coda-oss/modules/c++/str/include/str/Tokenizer.h b/externals/coda-oss/modules/c++/str/include/str/Tokenizer.h index baa5028574..4433b1fdc4 100644 --- a/externals/coda-oss/modules/c++/str/include/str/Tokenizer.h +++ b/externals/coda-oss/modules/c++/str/include/str/Tokenizer.h @@ -65,7 +65,7 @@ class Tokenizer * Method to return the resultant vector * \return The vector that was created by the tokenizer */ - operator Tokenizer::Tokens& () + operator Tokenizer::Tokens& () noexcept { return vec; } diff --git a/externals/coda-oss/modules/c++/sys/include/sys/AtomicCounterCpp11.h b/externals/coda-oss/modules/c++/sys/include/sys/AtomicCounterCpp11.h index 79979f2835..ce785869fe 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/AtomicCounterCpp11.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/AtomicCounterCpp11.h @@ -39,24 +39,24 @@ struct AtomicCounterImplCpp11 final { using ValueType = size_t ; - explicit AtomicCounterImplCpp11(ValueType initialValue) : + explicit AtomicCounterImplCpp11(ValueType initialValue) noexcept : mValue(initialValue) { } - ValueType getThenIncrement() + ValueType getThenIncrement() noexcept { // https://en.cppreference.com/w/cpp/atomic/atomic/fetch_add return mValue.fetch_add(1); } - ValueType getThenDecrement() + ValueType getThenDecrement() noexcept { // https://en.cppreference.com/w/cpp/atomic/atomic/fetch_sub return mValue.fetch_sub(1); } - ValueType get() const + ValueType get() const noexcept { // https://en.cppreference.com/w/cpp/atomic/atomic/load return mValue.load(); diff --git a/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h b/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h index d8145dcced..6b135288d8 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h @@ -21,20 +21,24 @@ * */ +#pragma once #ifndef CODA_OSS_sys_ByteSwap_h_INCLUDED_ #define CODA_OSS_sys_ByteSwap_h_INCLUDED_ -#pragma once #include #include #include #include +#include +#include +#include #include "config/Exports.h" #include "ByteSwapValue.h" #include "Runnable.h" +#include "SysInt.h" namespace sys { @@ -50,6 +54,90 @@ namespace sys coda_oss::span CODA_OSS_API byteSwap(coda_oss::spanbuffer, size_t elemSize); void CODA_OSS_API byteSwap(void* buffer, size_t elemSize, size_t numElems); +// If the caller has given us bytes, assume she knows what she's doing; i.e., don't check sizeof(T) +template +inline void byteSwap_(TByte* buffer, size_t elemSize, size_t numElems) +{ + void* const buffer_ = buffer; + byteSwap(buffer_, elemSize, numElems); +} +inline void byteSwap(coda_oss::byte* buffer, size_t elemSize, size_t numElems) +{ + return byteSwap_(buffer, elemSize, numElems); +} +inline void byteSwap(byte* buffer, size_t elemSize, size_t numElems) +{ + return byteSwap_(buffer, elemSize, numElems); +} +inline void byteSwap(ubyte* buffer, size_t elemSize, size_t numElems) +{ + return byteSwap_(buffer, elemSize, numElems); +} + +namespace details +{ +template +inline void check_elemSize(size_t elemSize) +{ + static_assert(is_byte_swappable(), "T should not be a 'struct'"); + if (sizeof(T) != elemSize) + { + throw std::invalid_argument("'elemSize' != sizeof(T)"); + } +} + +// Repackage into a span; the size is 2* because for byte-swapping +// we want to look at this as an array of `T`, not `std::complex`. +template +inline auto make_span(coda_oss::span> s) +{ + const void* const p_ = s.data(); + auto const p = static_cast(p_); + const auto sz = s.size() * 2; // real and imag + return sys::make_span(p, sz); +} +template +inline auto make_span(coda_oss::span> s) +{ + void* const p_ = s.data(); + auto const p = static_cast(p_); + const auto sz = s.size() * 2; // real and imag + return sys::make_span(p, sz); +} + +} + +// Otherwise, we can sanity-check the `elemSize` parameter +template +inline void byteSwap(T* buffer, size_t elemSize, size_t numElems) +{ + details::check_elemSize(elemSize); + void* const buffer_ = buffer; + byteSwap(buffer_, elemSize, numElems); +} +template +inline void byteSwap(std::complex* buffer, size_t elemSize, size_t numElems) // dont't want `T` as `std::complex<...>` +{ + details::check_elemSize(elemSize); + void* const buffer_ = buffer; + byteSwap(buffer_, elemSize, numElems); +} + +template +inline auto byteSwap(coda_oss::span buffer) +{ + static_assert(!std::is_const::value, "T cannot be 'const'"); + static_assert(details::is_byte_swappable(), "T should not be a 'struct'"); + return byteSwap(as_writable_bytes(buffer), sizeof(T)); +} + +// Take care of treating std::complex as T[] +template +inline auto byteSwap(coda_oss::span> buffer) +{ + return byteSwap(details::make_span(buffer)); +} + /*! * Swap bytes into output buffer. Note that a complex pixel * is equivalent to two floats so elemSize and numElems @@ -64,9 +152,101 @@ coda_oss::span CODA_OSS_API byteSwap(coda_oss::span outputBuffer); void CODA_OSS_API byteSwap(const void* buffer, size_t elemSize, size_t numElems, void* outputBuffer); +// If the caller has given us bytes, assume she knows what she's doing; i.e., don't check sizeof(T) +template +inline void byteSwap_(const TByte* buffer, size_t elemSize, size_t numElems, U* outputBuffer) +{ + const void* const buffer_ = buffer; + void* const outputBuffer_ = outputBuffer; + byteSwap(buffer_, elemSize, numElems, outputBuffer_); +} +template +inline void byteSwap(const coda_oss::byte* buffer, size_t elemSize, size_t numElems, U* outputBuffer) +{ + byteSwap_(buffer, elemSize, numElems, outputBuffer); +} +template +inline void byteSwap(const byte* buffer, size_t elemSize, size_t numElems, U* outputBuffer) +{ + byteSwap_(buffer, elemSize, numElems, outputBuffer); +} +template +inline void byteSwap(const ubyte* buffer, size_t elemSize, size_t numElems, U* outputBuffer) +{ + byteSwap_(buffer, elemSize, numElems, outputBuffer); +} + +// Otherwise, we can sanity-check the `elemSize` parameter +template +inline void byteSwap(const T* buffer, size_t elemSize, size_t numElems, U* outputBuffer) +{ + details::check_elemSize(elemSize); + const void* const buffer_ = buffer; + void* const outputBuffer_ = outputBuffer; + byteSwap(buffer_, elemSize, numElems, outputBuffer_); +} +template +inline void byteSwap(const std::complex* buffer, size_t elemSize, size_t numElems, U* outputBuffer) // dont't want `T` as `std::complex<...>` +{ + details::check_elemSize(elemSize); + const void* const buffer_ = buffer; + void* const outputBuffer_ = outputBuffer; + byteSwap(buffer_, elemSize, numElems, outputBuffer_); +} + +template +inline auto byteSwap(coda_oss::span buffer, coda_oss::span outputBuffer) +{ + static_assert(details::is_byte_swappable(), "T should not be a 'struct'"); + return byteSwap(as_bytes(buffer), sizeof(T), outputBuffer); +} +// Take care of treating std::complex as T[] +template +inline auto byteSwap(coda_oss::span> buffer, coda_oss::span outputBuffer) +{ + return byteSwap(details::make_span(buffer), outputBuffer); +} + +template +inline auto byteSwap(coda_oss::span buffer) +{ + std::vector retval(buffer.size_bytes()); + std::ignore = byteSwap(buffer, make_span(retval)); + return retval; +} +// Take care of treating std::complex as T[] +template +inline auto byteSwap(coda_oss::span> buffer) +{ + return byteSwap(details::make_span(buffer)); +} + +// With buffer byte-swap now in place, we can safely byte-swap std::complex. +// This signature is from ByteSwapValue.h +template +inline auto byteSwapValue(std::complex z) +{ + // C++ mandates that `std::complex` be the same as `T cx[2]`; that is + // the structure is contiguous. https://en.cppreference.com/w/cpp/numeric/complex + const auto& z_ = reinterpret_cast(z); + return byteSwap(make_span(z_)); +} +template +inline auto byteSwap(std::complex val) +{ + const auto bytes = byteSwapValue(val); + assert(bytes.size() == sizeof(val)); + + const void* const pBytes = bytes.data(); + auto const pRetVal = static_cast*>(pBytes); + return *pRetVal; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + struct ByteSwapRunnable final : public sys::Runnable { - ByteSwapRunnable(void* buffer, size_t elemSize, size_t startElement, size_t numElements) : + ByteSwapRunnable(void* buffer, size_t elemSize, size_t startElement, size_t numElements) noexcept : mBuffer(static_cast(buffer) + startElement * elemSize), mElemSize(elemSize), mNumElements(numElements) { @@ -90,7 +270,7 @@ struct ByteSwapRunnable final : public sys::Runnable struct ByteSwapCopyRunnable final : public sys::Runnable { - ByteSwapCopyRunnable(const void* buffer, size_t elemSize, size_t startElement, size_t numElements, void* outputBuffer) : + ByteSwapCopyRunnable(const void* buffer, size_t elemSize, size_t startElement, size_t numElements, void* outputBuffer) noexcept : mBuffer(static_cast(buffer) + startElement * elemSize), mElemSize(elemSize), mNumElements(numElements), mOutputBuffer(static_cast(outputBuffer) + startElement * elemSize) diff --git a/externals/coda-oss/modules/c++/sys/include/sys/ByteSwapValue.h b/externals/coda-oss/modules/c++/sys/include/sys/ByteSwapValue.h index 57cffe3f3b..c36c4428e4 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/ByteSwapValue.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/ByteSwapValue.h @@ -21,9 +21,9 @@ * */ +#pragma once #ifndef CODA_OSS_sys_ByteSwapValue_h_INCLUDED_ #define CODA_OSS_sys_ByteSwapValue_h_INCLUDED_ -#pragma once #include #include @@ -37,19 +37,12 @@ #include #include #include +#include #include "config/Exports.h" #include "Span.h" -#include -#include -#include -#include -#include -#include -#include - namespace sys { /*! @@ -65,6 +58,20 @@ namespace sys namespace details { + // "cast" a single value to bytes + template + inline auto as_bytes(const T& v) noexcept + { + static_assert(!std::is_compound::value, "T cannot be a 'struct'"); + return sys::as_bytes(&v, 1); + } + template + inline auto as_writable_bytes(T& v) noexcept + { + static_assert(!std::is_compound::value, "T cannot be a 'struct'"); + return sys::as_writable_bytes(&v, 1); + } + template inline auto swapUIntBytes(coda_oss::span inBytes, coda_oss::span outBytes, std::nothrow_t) noexcept @@ -81,7 +88,7 @@ namespace sys *pOut = coda_oss::byteswap(*pIn); // at long last, swap the bytes // Give the raw byte-swapped bytes back to the caller for easy serialization - return as_bytes(pOut); + return as_bytes(*pOut); } template inline auto swapUIntBytes(coda_oss::span inBytes, coda_oss::span outBytes) @@ -136,33 +143,32 @@ namespace sys * Returns the raw byte-swapped bytes for easy serialization. */ template - inline auto swapBytes(coda_oss::span inBytes, coda_oss::span outBytes) + inline auto byteSwapValue(coda_oss::span inBytes, coda_oss::span outBytes) { static_assert(details::is_byte_swappable(), "T should not be a 'struct'"); return details::swapBytes(inBytes, outBytes); } template - inline auto swapBytes(T in, coda_oss::span outBytes) + inline auto byteSwapValue(T in, coda_oss::span outBytes) { - return swapBytes(as_bytes(in), outBytes); + return byteSwapValue(details::as_bytes(in), outBytes); } template - inline auto swapBytes(T in) + inline auto byteSwapValue(T in) { - std::vector retval; - retval.resize(sizeof(T)); - std::ignore = swapBytes(in, make_span(retval)); + std::vector retval(sizeof(T)); + std::ignore = byteSwapValue(in, make_span(retval)); return retval; } // Reverse the above: turn `span` back to T after byte-swapping template - inline auto swapBytes(coda_oss::span in) + inline auto byteSwapValue(coda_oss::span in) { // Don't want to cast the swapped bytes in `in` to T* as they might not be valid; // e.g., a byte-swapped `float` could be garbage. T retval; - swapBytes(in, as_writable_bytes(retval)); + byteSwapValue(in, details::as_writable_bytes(retval)); return retval; } @@ -189,7 +195,7 @@ namespace sys template inline T byteSwap(T val) { T out; - std::ignore = swapBytes(val, as_writable_bytes(out)); + std::ignore = byteSwapValue(val, details::as_writable_bytes(out)); return out; } } diff --git a/externals/coda-oss/modules/c++/sys/include/sys/ConditionVarInterface.h b/externals/coda-oss/modules/c++/sys/include/sys/ConditionVarInterface.h index 96172c8bcb..8d6f762f50 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/ConditionVarInterface.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/ConditionVarInterface.h @@ -68,8 +68,8 @@ struct CODA_OSS_API ConditionVarInterface * a lock, but this class will STILL delete it. * */ - explicit ConditionVarInterface(Mutex *, bool = false) {} - explicit ConditionVarInterface(Mutex&) { } + explicit ConditionVarInterface(Mutex *, bool = false) noexcept {} + explicit ConditionVarInterface(Mutex&) noexcept { } virtual ~ConditionVarInterface() = default; diff --git a/externals/coda-oss/modules/c++/sys/include/sys/Conf.h b/externals/coda-oss/modules/c++/sys/include/sys/Conf.h index df36708bb4..111e5f9c86 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/Conf.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/Conf.h @@ -76,7 +76,7 @@ #include "str/Format.h" #include "sys/TimeStamp.h" #include "sys/ByteSwap.h" - +#include "sys/SysInt.h" /* Dance around the compiler to figure out */ /* if we have access to function macro... */ @@ -105,22 +105,6 @@ # define NativeLayer_func__ "" #endif - -namespace sys -{ - typedef char byte; - typedef unsigned char ubyte; - typedef uint8_t Uint8_T; - typedef uint16_t Uint16_T; - typedef uint32_t Uint32_T; - typedef uint64_t Uint64_T; - typedef size_t Size_T; - typedef int8_t Int8_T; - typedef int16_t Int16_T; - typedef int32_t Int32_T; - typedef int64_t Int64_T; -} - #ifdef _WIN32 # include # include @@ -247,7 +231,7 @@ namespace sys * * \param p A pointer to the data allocated using alignedAlloc */ - inline void alignedFree(void* p) + inline void alignedFree(void* p) noexcept { #ifdef _WIN32 _aligned_free(p); diff --git a/externals/coda-oss/modules/c++/sys/include/sys/DateTime.h b/externals/coda-oss/modules/c++/sys/include/sys/DateTime.h index 5ca7db4459..d238eda6d1 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/DateTime.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/DateTime.h @@ -155,32 +155,32 @@ class CODA_OSS_API DateTime * @return true if comparison holds, false otherwise. */ //@{ - bool operator<(const DateTime& rhs) const + bool operator<(const DateTime& rhs) const noexcept { return (mTimeInMillis < rhs.mTimeInMillis); } - bool operator<=(const DateTime& rhs) const + bool operator<=(const DateTime& rhs) const noexcept { return (mTimeInMillis <= rhs.mTimeInMillis); } - bool operator>(const DateTime& rhs) const + bool operator>(const DateTime& rhs) const noexcept { return (mTimeInMillis > rhs.mTimeInMillis); } - bool operator>=(const DateTime& rhs) const + bool operator>=(const DateTime& rhs) const noexcept { return (mTimeInMillis >= rhs.mTimeInMillis); } - bool operator==(const DateTime& rhs) const + bool operator==(const DateTime& rhs) const noexcept { return (mTimeInMillis == rhs.mTimeInMillis); } - bool operator!=(const DateTime& rhs) const + bool operator!=(const DateTime& rhs) const noexcept { return !operator==(rhs); } diff --git a/externals/coda-oss/modules/c++/sys/include/sys/Err.h b/externals/coda-oss/modules/c++/sys/include/sys/Err.h index c7163f35bd..4c3b37c509 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/Err.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/Err.h @@ -62,7 +62,7 @@ struct CODA_OSS_API Err * Copy constructor * \param err The err to take */ - Err(const Err& err) + Err(const Err& err) noexcept { mErrId = err.getErrID(); } @@ -82,7 +82,7 @@ struct CODA_OSS_API Err * Assignment operator * \param err The err to take */ - Err& operator=(const Err& err) + Err& operator=(const Err& err) noexcept { if (&err != this) { @@ -115,7 +115,7 @@ struct CODA_OSS_API Err //! Return the last error virtual int getLast() const; - int getErrID() const { return mErrId; } + int getErrID() const noexcept { return mErrId; } protected: @@ -158,7 +158,7 @@ struct SocketErr : public Err * \param err The err to take * */ - SocketErr& operator=(const SocketErr& err) + SocketErr& operator=(const SocketErr& err) noexcept { if (&err != this) { diff --git a/externals/coda-oss/modules/c++/sys/include/sys/LocalDateTime.h b/externals/coda-oss/modules/c++/sys/include/sys/LocalDateTime.h index 5effbcaa69..a264d92738 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/LocalDateTime.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/LocalDateTime.h @@ -78,7 +78,7 @@ class CODA_OSS_API LocalDateTime : public DateTime LocalDateTime(const std::string& time, const std::string& format); //! Return the Daylight Savings Time flag (true = on, false = off) - bool getDST() const { return mDST == 1; } + bool getDST() const noexcept { return mDST == 1; } //! Set the Daylight Savings Time flag (true = on, false = off) void setDST(bool isDST); diff --git a/externals/coda-oss/modules/c++/sys/include/sys/MutexCpp11.h b/externals/coda-oss/modules/c++/sys/include/sys/MutexCpp11.h index b95738d349..e10ff54205 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/MutexCpp11.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/MutexCpp11.h @@ -66,7 +66,7 @@ struct MutexCpp11 final : public MutexInterface * Return the type name. This function is essentially free, * because it is static RTTI. */ - const char* getNativeType() const + const char* getNativeType() const noexcept { return typeid(mNative).name(); } diff --git a/externals/coda-oss/modules/c++/sys/include/sys/MutexWin32.h b/externals/coda-oss/modules/c++/sys/include/sys/MutexWin32.h index adc3ac2d38..aa6b4906a3 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/MutexWin32.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/MutexWin32.h @@ -64,7 +64,7 @@ class CODA_OSS_API MutexWin32 : public MutexInterface * Return the type name. This function is essentially free, * because it is static RTTI. */ - const char* getNativeType() const + const char* getNativeType() const noexcept { return typeid(mNative).name(); } diff --git a/externals/coda-oss/modules/c++/sys/include/sys/OSWin32.h b/externals/coda-oss/modules/c++/sys/include/sys/OSWin32.h index 3b7dcd3ced..7fc5fdf972 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/OSWin32.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/OSWin32.h @@ -59,7 +59,7 @@ struct CODA_OSS_API OSWin32 final : public AbstractOS * For unix it will be one slash / * \return The path delimiter */ - virtual const char* getDelimiter() const + const char* getDelimiter() const noexcept override { return "\\"; } diff --git a/externals/coda-oss/modules/c++/sys/include/sys/Span.h b/externals/coda-oss/modules/c++/sys/include/sys/Span.h index 23b72d02c1..bf24e81c7e 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/Span.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/Span.h @@ -21,14 +21,15 @@ * */ +#pragma once #ifndef CODA_OSS_sys_Span_h_INCLUDED_ #define CODA_OSS_sys_Span_h_INCLUDED_ -#pragma once #include #include #include #include +#include namespace sys // not "mem", it depends on sys. { @@ -128,6 +129,22 @@ inline auto make_span(T (&a)[N]) noexcept // Calling as_bytes() or as_writable_bytes() requires a span, which as // noted above is a nuisance to create w/o C++17 +template +inline auto as_bytes(coda_oss::span s) noexcept +{ + return coda_oss::as_bytes(s); +} +template +inline auto as_bytes(coda_oss::span s) noexcept +{ + return coda_oss::as_bytes(s); +} +template +inline auto as_writable_bytes(coda_oss::span s) noexcept +{ + return coda_oss::as_writable_bytes(s); +} + template inline auto as_bytes(const T* ptr, size_t sz) noexcept { @@ -136,6 +153,7 @@ inline auto as_bytes(const T* ptr, size_t sz) noexcept template inline auto as_writable_bytes(T* ptr, size_t sz) noexcept { + static_assert(!std::is_const::value, "T cannot be 'const'"); return coda_oss::as_writable_bytes(make_writable_span(ptr, sz)); } @@ -172,17 +190,5 @@ inline auto as_writable_bytes(T (&a)[N]) noexcept return as_writable_bytes(a, N); } -// "cast" a single value to bytes -template -inline auto as_bytes(const T& v) noexcept -{ - return as_bytes(&v, 1); -} -template -inline auto as_writable_bytes(T& v) noexcept -{ - return as_writable_bytes(&v, 1); -} - } #endif // CODA_OSS_sys_Span_h_INCLUDED_ diff --git a/externals/coda-oss/modules/c++/sys/include/sys/SysInt.h b/externals/coda-oss/modules/c++/sys/include/sys/SysInt.h new file mode 100644 index 0000000000..a25f76d1fa --- /dev/null +++ b/externals/coda-oss/modules/c++/sys/include/sys/SysInt.h @@ -0,0 +1,45 @@ +/* ========================================================================= + * This file is part of sys-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2014, MDA Information Systems LLC + * (C) Copyright 2023, Maxar Technologies, Inc. + * + * sys-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#pragma once +#ifndef CODA_OSS_sys_SysInt_h_INCLUDED_ +#define CODA_OSS_sys_SysInt_h_INCLUDED_ + +#include + +namespace sys +{ + typedef char byte; + typedef unsigned char ubyte; + typedef uint8_t Uint8_T; + typedef uint16_t Uint16_T; + typedef uint32_t Uint32_T; + typedef uint64_t Uint64_T; + typedef size_t Size_T; + typedef int8_t Int8_T; + typedef int16_t Int16_T; + typedef int32_t Int32_T; + typedef int64_t Int64_T; +} + +#endif // CODA_OSS_sys_SysInt_h_INCLUDED_ diff --git a/externals/coda-oss/modules/c++/sys/include/sys/TimeStamp.h b/externals/coda-oss/modules/c++/sys/include/sys/TimeStamp.h index 8d8c72281f..a04207938b 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/TimeStamp.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/TimeStamp.h @@ -54,7 +54,7 @@ struct TimeStamp final * \param is24HourTime Optional specifier for military time */ TimeStamp() = default; - TimeStamp(bool is24HourTime) : m24HourTime(is24HourTime) + TimeStamp(bool is24HourTime) noexcept : m24HourTime(is24HourTime) { } ~TimeStamp() = default; @@ -84,7 +84,7 @@ struct TimeStamp final * Sets up string in desired format * \return The string format for printing */ - const char* getFormat() const + const char* getFormat() const noexcept { if (m24HourTime) { diff --git a/externals/coda-oss/modules/c++/sys/source/Conf.cpp b/externals/coda-oss/modules/c++/sys/source/Conf.cpp index bf29dd69ba..326b3cac71 100644 --- a/externals/coda-oss/modules/c++/sys/source/Conf.cpp +++ b/externals/coda-oss/modules/c++/sys/source/Conf.cpp @@ -132,40 +132,42 @@ bool sys::isLittleEndianSystem() * \param numElems */ template -inline void byteSwap_n_(void *buffer_, size_t numElems) +inline auto byteSwap(coda_oss::span buffer) { static_assert(std::is_unsigned::value, "TUInt must be 'unsigned'"); - const auto buffer = sys::make_span(buffer_, numElems); - assert(buffer.size_bytes() == sizeof(TUInt) * numElems); - for (auto& v : buffer) { v = sys::byteSwap(v); } + return sys::as_bytes(buffer); } template -inline void byteSwap_n(void *buffer, size_t elemSize, size_t numElems) +inline auto byteSwap_n_(coda_oss::span buffer_) +{ + const auto buffer = sys::make_span(buffer_.data(), buffer_.size_bytes() / sizeof(TUInt)); + assert(buffer.size_bytes() == buffer_.size_bytes()); + return byteSwap(buffer); +} +template +inline auto byteSwap_n(coda_oss::span buffer, size_t elemSize) { if (sizeof(TUInt) != elemSize) { throw std::invalid_argument("'elemSize' != sizeof(TUInt)"); } - byteSwap_n_(buffer, numElems); + return byteSwap_n_(buffer); } -void sys::byteSwap(void* buffer, size_t elemSize, size_t numElems) +static coda_oss::span byteSwap(coda_oss::span buffer, size_t elemSize, size_t numElems) { - if ((buffer == nullptr) || (elemSize < 2) || (numElems == 0)) - return; - switch (elemSize) { - case sizeof(uint16_t): return byteSwap_n(buffer, elemSize, numElems); - case sizeof(uint32_t): return byteSwap_n(buffer, elemSize, numElems); - case sizeof(uint64_t): return byteSwap_n(buffer, elemSize, numElems); + case sizeof(uint16_t): return byteSwap_n(buffer, elemSize); + case sizeof(uint32_t): return byteSwap_n(buffer, elemSize); + case sizeof(uint64_t): return byteSwap_n(buffer, elemSize); default: break; } - - auto const bufferPtr = static_cast(buffer); + + auto const bufferPtr = buffer.data(); const auto half = elemSize >> 1; size_t offset = 0, innerOff = 0, innerSwap = 0; for (size_t i = 0; i < numElems; ++i, offset += elemSize) @@ -178,10 +180,21 @@ void sys::byteSwap(void* buffer, size_t elemSize, size_t numElems) std::swap(bufferPtr[innerOff], bufferPtr[innerSwap]); } } + + return sys::make_const_span(buffer); +} +void sys::byteSwap(void* buffer_, size_t elemSize, size_t numElems) +{ + if ((buffer_ == nullptr) || (elemSize < 2) || (numElems == 0)) + return; + + auto const pBytes = static_cast(buffer_); + const coda_oss::span buffer(pBytes, elemSize * numElems); + std::ignore = ::byteSwap(buffer, elemSize, numElems); } coda_oss::span sys::byteSwap(coda_oss::span buffer, size_t elemSize) { - if ((buffer.size() == 0) || (elemSize < 2)) + if ((buffer.empty()) || (elemSize < 2)) return sys::make_const_span(buffer); size_t const numElems = buffer.size() / elemSize; @@ -189,9 +202,8 @@ coda_oss::span sys::byteSwap(coda_oss::span sys::byteSwap(coda_oss::span -inline void byteSwap_n_(const void *buffer_, size_t numElems, void *outputBuffer_) +inline auto byteSwap_n_(coda_oss::span buffer, coda_oss::span outputBuffer_) { static_assert(std::is_unsigned::value, "TUInt must be 'unsigned'"); - const auto buffer = sys::make_span(buffer_, numElems); - assert(buffer.size_bytes() == sizeof(TUInt) * numElems); - const auto outputBuffer = sys::make_span(outputBuffer_, numElems); + assert(buffer.size_bytes() == outputBuffer_.size()); + void* pOutputBuffer = outputBuffer_.data(); + const auto outputBuffer = sys::make_span(pOutputBuffer, buffer.size()); + assert(buffer.size_bytes() == outputBuffer.size_bytes()); const auto byteSwap = [](const auto& v) { return sys::byteSwap(v); }; std::transform(buffer.begin(), buffer.end(), outputBuffer.begin(), byteSwap); + + return sys::as_bytes(outputBuffer); } template -inline void byteSwap_n(const void *buffer, size_t elemSize, size_t numElems, void *outputBuffer) +inline auto byteSwap_n(coda_oss::span buffer_, size_t elemSize, coda_oss::span outputBuffer) { if (sizeof(TUInt) != elemSize) { throw std::invalid_argument("'elemSize' != sizeof(TUInt)"); } - byteSwap_n_(buffer, numElems, outputBuffer); + + const auto buffer = sys::make_span(buffer_.data(), buffer_.size_bytes() / sizeof(TUInt)); + assert(buffer.size_bytes() == buffer_.size_bytes()); + return byteSwap_n_(buffer, outputBuffer); } -void sys::byteSwap(const void* buffer, size_t elemSize, size_t numElems, void* outputBuffer) -{ - if ((numElems == 0) || (buffer == nullptr) || (outputBuffer == nullptr)) - { - return; - } +static auto byteSwap(coda_oss::span buffer, + size_t elemSize, size_t numElems, + coda_oss::span outputBuffer) +{ + auto const bufferPtr = buffer.data(); + auto const outputBufferPtr = outputBuffer.data(); switch (elemSize) { - case 1: std::ignore = memcpy(outputBuffer, buffer, elemSize * numElems); return; - case 2: return byteSwap_n(buffer, elemSize, numElems, outputBuffer); - case 4: return byteSwap_n(buffer, elemSize, numElems, outputBuffer); - case 8: return byteSwap_n(buffer, elemSize, numElems, outputBuffer); + case 1: + { + std::ignore = memcpy(outputBufferPtr, bufferPtr, elemSize * numElems); + return sys::make_const_span(outputBuffer); + } + case 2: return byteSwap_n(buffer, elemSize, outputBuffer); + case 4: return byteSwap_n(buffer, elemSize, outputBuffer); + case 8: return byteSwap_n(buffer, elemSize, outputBuffer); default: break; } - auto const bufferPtr = static_cast(buffer); - auto const outputBufferPtr = static_cast(outputBuffer); - const auto half = elemSize >> 1; size_t offset = 0; for (size_t ii = 0; ii < numElems; ++ii, offset += elemSize) @@ -257,11 +276,29 @@ void sys::byteSwap(const void* buffer, size_t elemSize, size_t numElems, void* o outputBufferPtr[innerSwap] = bufferPtr[innerOff]; } } + + return sys::make_const_span(outputBuffer); +} + +void sys::byteSwap(const void* buffer_, size_t elemSize, size_t numElems, void* outputBuffer_) +{ + if ((numElems == 0) || (buffer_ == nullptr) || (outputBuffer_ == nullptr)) + { + return; + } + + auto const pBytes = static_cast(buffer_); + const coda_oss::span buffer(pBytes, elemSize * numElems); + + auto const pOutputBytes = static_cast(outputBuffer_); + const coda_oss::span outputBuffer(pOutputBytes, elemSize * numElems); + + std::ignore = ::byteSwap(buffer, elemSize, numElems, outputBuffer); } coda_oss::span sys::byteSwap(coda_oss::span buffer, size_t elemSize, coda_oss::span outputBuffer) { - if ((buffer.size() == 0) || (outputBuffer.size() == 0)) + if ((buffer.empty()) || (outputBuffer.empty())) { return sys::make_const_span(outputBuffer); } @@ -273,14 +310,16 @@ coda_oss::span sys::byteSwap(coda_oss::span)"); + + // If these values are byte-swapped, they could be bogus. + const void* const pValue1_ = &(values1[ii]); + const void* const pSwappedValue2_ = &(swappedValues2[ii]); + + auto const pValue1 = static_cast(pValue1_); + auto const pSwappedValue2 = static_cast(pSwappedValue2_); + + TEST_ASSERT_EQ(*pValue1, *pSwappedValue2); + } +} + +template +inline std::span as_span(const std::vector& bytes) +{ + const void* const pBytes_ = bytes.data(); + auto const p = static_cast(pBytes_); + const auto sz = bytes.size() / sizeof(T); + return sys::make_span(p, sz); +} + +TEST_CASE(testByteSwap) +{ + constexpr size_t NUM_PIXELS = 10000; + const auto origValues = make_origValues(NUM_PIXELS); + const auto origValues_ = sys::make_span(origValues); + + auto values1(origValues); + sys::byteSwap(sys::make_span(values1)); + + // Byte swap into output buffer + std::vector swappedValues2(origValues.size()); + sys::byteSwap(origValues_, sys::as_writable_bytes(swappedValues2)); + + // std::vector returned + const auto swappedValues3_ = sys::byteSwap(origValues_); + const auto swappedValues3 = as_span(swappedValues3_); + + // Everything should match + for (size_t ii = 0; ii < NUM_PIXELS; ++ii) + { + TEST_ASSERT_EQ(values1[ii], swappedValues2[ii]); + TEST_ASSERT_EQ(values1[ii], swappedValues3[ii]); + } +} + // 0xnn is an `int` which can't be used to initialize std::byte w/o a cast #define CODA_OSS_define_byte(v) constexpr static std::byte v = static_cast(0 ## v) CODA_OSS_define_byte(x00); @@ -131,6 +201,16 @@ static constexpr std::byte four_bytes[]{x00, x11, xEE, xFF}; static constexpr std::byte eight_bytes[]{x00, x11, x22, x33, xCC, xDD, xEE, xFF}; static constexpr std::byte sixteen_bytes[]{x00, x11, x22, x33, x44, x55, x66, x77, x88, x99, xAA, xBB, xCC, xDD, xEE, xFF}; +template +static void test_assert_eq_swapped(const std::string& testName, size_t sz, + const TByteSpanLike1& pValueBytes, const TByteSpanLike2& pResultBytes) +{ + for (size_t i = 0, j = sz; i < sz && j > 0; i++, j--) + { + TEST_ASSERT(pResultBytes[i] == pValueBytes[j - 1]); + } +} + template static void testByteSwapValues_(const std::string& testName, const void* pBytes) { @@ -141,10 +221,7 @@ static void testByteSwapValues_(const std::string& testName, const void* pBytes) const void* pResult_ = &swap; auto const pResultBytes = static_cast(pResult_); auto const pValueBytes = static_cast(pBytes); - for (size_t i = 0, j = sizeof(TUInt); i < sizeof(TUInt) && j > 0; i++, j--) - { - TEST_ASSERT(pResultBytes[i] == pValueBytes[j-1]); - } + test_assert_eq_swapped(testName, sizeof(TUInt), pResultBytes, pValueBytes); swap = sys::byteSwap(swap); // swap back TEST_ASSERT_EQ(*pUInt, swap); @@ -155,12 +232,9 @@ static void testByteSwapValues_(const std::string& testName, const void* pBytes) sys::byteSwap(&swap, sizeof(TUInt), 1); // swap back TEST_ASSERT_EQ(*pUInt, swap); - const auto resultBytes = sys::swapBytes(*pUInt); + const auto resultBytes = sys::byteSwapValue(*pUInt); TEST_ASSERT_EQ(resultBytes.size(), sizeof(TUInt)); - for (size_t i = 0, j = sizeof(TUInt); i < sizeof(TUInt) && j > 0; i++, j--) - { - TEST_ASSERT(resultBytes[i] == pValueBytes[j - 1]); - } + test_assert_eq_swapped(testName, sizeof(TUInt), resultBytes.data(), pValueBytes); } TEST_CASE(testByteSwapValues) { @@ -169,65 +243,45 @@ TEST_CASE(testByteSwapValues) testByteSwapValues_(testName, eight_bytes); } +TEST_CASE(testByteSwapCxValue) +{ + using value_type = std::complex; + const value_type cx{3.14f, -31.4f}; // using raw bytes can lean to `nan`s + auto const pValue = &cx; + + auto swap = sys::byteSwap(*pValue); + TEST_ASSERT_NOT_EQ(*pValue, swap); // technically a bit goofy as the bits may not represent `T`s + + swap = sys::byteSwap(swap); // swap back + TEST_ASSERT_EQ(*pValue, swap); +} + TEST_CASE(testByteSwap12) { // test a goofy element size - static constexpr std::byte twelve_bytes[]{ + constexpr std::byte twelve_bytes[]{ x00, x11, x22, x33, x44, x55, x99, xAA, xBB, xDD, xEE, xFF}; const auto pValueBytes = sys::as_bytes(twelve_bytes); + constexpr auto extent_twelve_bytes = std::extent::value; - std::vector swappedValues(12); + std::vector swappedValues(extent_twelve_bytes); auto pResultBytes = sys::make_span(swappedValues); auto elemSize = 12; auto numElements = swappedValues.size() / elemSize; sys::byteSwap(twelve_bytes, elemSize, numElements, pResultBytes.data()); - TEST_ASSERT(pResultBytes[0] == pValueBytes[11]); - TEST_ASSERT(pResultBytes[1] == pValueBytes[10]); - TEST_ASSERT(pResultBytes[2] == pValueBytes[9]); - TEST_ASSERT(pResultBytes[3] == pValueBytes[8]); - TEST_ASSERT(pResultBytes[4] == pValueBytes[7]); - TEST_ASSERT(pResultBytes[5] == pValueBytes[6]); - TEST_ASSERT(pResultBytes[6] == pValueBytes[5]); - TEST_ASSERT(pResultBytes[7] == pValueBytes[4]); - TEST_ASSERT(pResultBytes[8] == pValueBytes[3]); - TEST_ASSERT(pResultBytes[9] == pValueBytes[2]); - TEST_ASSERT(pResultBytes[10] == pValueBytes[1]); - TEST_ASSERT(pResultBytes[11] == pValueBytes[0]); + test_assert_eq_swapped(testName, elemSize, pResultBytes, pValueBytes); // swap as a SINGLE 12-byte value - const auto result = sys::details::swapBytes<12>(pValueBytes, pResultBytes); - TEST_ASSERT(result[0] == pValueBytes[11]); - TEST_ASSERT(result[1] == pValueBytes[10]); - TEST_ASSERT(result[2] == pValueBytes[9]); - TEST_ASSERT(result[3] == pValueBytes[8]); - TEST_ASSERT(result[4] == pValueBytes[7]); - TEST_ASSERT(result[5] == pValueBytes[6]); - TEST_ASSERT(result[6] == pValueBytes[5]); - TEST_ASSERT(result[7] == pValueBytes[4]); - TEST_ASSERT(result[8] == pValueBytes[3]); - TEST_ASSERT(result[9] == pValueBytes[2]); - TEST_ASSERT(result[10] == pValueBytes[1]); - TEST_ASSERT(result[11] == pValueBytes[0]); - + const auto result = sys::details::swapBytes(pValueBytes, pResultBytes); + test_assert_eq_swapped(testName, elemSize, result, pValueBytes); elemSize = 6; // note that an ODD size doesn't work correctly numElements = swappedValues.size() / elemSize; sys::byteSwap(twelve_bytes, elemSize, numElements, swappedValues.data()); - TEST_ASSERT(pResultBytes[0] == pValueBytes[5]); - TEST_ASSERT(pResultBytes[1] == pValueBytes[4]); - TEST_ASSERT(pResultBytes[2] == pValueBytes[3]); - TEST_ASSERT(pResultBytes[3] == pValueBytes[2]); - TEST_ASSERT(pResultBytes[4] == pValueBytes[1]); - TEST_ASSERT(pResultBytes[5] == pValueBytes[0]); - - TEST_ASSERT(pResultBytes[6] == pValueBytes[11]); - TEST_ASSERT(pResultBytes[7] == pValueBytes[10]); - TEST_ASSERT(pResultBytes[8] == pValueBytes[9]); - TEST_ASSERT(pResultBytes[9] == pValueBytes[8]); - TEST_ASSERT(pResultBytes[10] == pValueBytes[7]); - TEST_ASSERT(pResultBytes[11] == pValueBytes[6]); + test_assert_eq_swapped(testName, elemSize, &(pResultBytes[0]), &(pValueBytes[0])); + test_assert_eq_swapped(testName, elemSize, &(pResultBytes[6]), &(pValueBytes[6])); sys::byteSwap(swappedValues.data(), elemSize, numElements); // swap back for (size_t i = 0; i < swappedValues.size(); i++) @@ -240,7 +294,7 @@ template static inline void six_byteSwap(const void* in, T& out) { auto const inBytes = sys::make_span(in, sizeof(T)); - out = sys::swapBytes(inBytes); + out = sys::byteSwapValue(inBytes); } TEST_CASE(testSixByteSwap) { @@ -256,8 +310,11 @@ TEST_CASE(testSixByteSwap) TEST_MAIN( TEST_CHECK(testEndianness); + TEST_CHECK(testByteSwapV); + TEST_CHECK(testByteSwapCxV); TEST_CHECK(testByteSwap); TEST_CHECK(testByteSwapValues); + TEST_CHECK(testByteSwapCxValue); TEST_CHECK(testByteSwap12); TEST_CHECK(testSixByteSwap); ) diff --git a/externals/coda-oss/modules/c++/tiff/include/tiff/GenericType.h b/externals/coda-oss/modules/c++/tiff/include/tiff/GenericType.h index 9d5a994ea8..5e9787f00e 100644 --- a/externals/coda-oss/modules/c++/tiff/include/tiff/GenericType.h +++ b/externals/coda-oss/modules/c++/tiff/include/tiff/GenericType.h @@ -112,7 +112,8 @@ template class Gene *****************************************************************/ GenericType(const unsigned char *data) { - mData = *((Data_T *)data); + const void* const pData = data; + mData = *(static_cast(pData)); } //! Deconstructor diff --git a/externals/coda-oss/modules/c++/tiff/source/ImageWriter.cpp b/externals/coda-oss/modules/c++/tiff/source/ImageWriter.cpp index ed89e6da93..284ffd52f0 100644 --- a/externals/coda-oss/modules/c++/tiff/source/ImageWriter.cpp +++ b/externals/coda-oss/modules/c++/tiff/source/ImageWriter.cpp @@ -230,20 +230,20 @@ void tiff::ImageWriter::validate() void tiff::ImageWriter::initTiles() { - sys::Uint32_T root = (sys::Uint32_T)sqrt((double)mIdealChunkSize + const sys::Uint32_T root = (sys::Uint32_T)sqrt((double)mIdealChunkSize / (double)mIFD.getElementSize()); - sys::Uint32_T ceiling = (sys::Uint32_T)ceil(((double)root) / 16); - sys::Uint32_T tileSize = ceiling * 16; + const sys::Uint32_T ceiling = (sys::Uint32_T)ceil(((double)root) / 16); + const sys::Uint32_T tileSize = ceiling * 16; mIFD.addEntry("TileWidth", (sys::Uint32_T) tileSize); mIFD.addEntry("TileLength", (sys::Uint32_T) tileSize); auto fileOffset = mOutput->tell(); - sys::Uint32_T tilesAcross = (mIFD.getImageWidth() + tileSize - 1) + const sys::Uint32_T tilesAcross = (mIFD.getImageWidth() + tileSize - 1) / tileSize; - sys::Uint32_T tilesDown = (mIFD.getImageLength() + tileSize - 1) / tileSize; + const sys::Uint32_T tilesDown = (mIFD.getImageLength() + tileSize - 1) / tileSize; - unsigned short elementSize = mIFD.getElementSize(); + const unsigned short elementSize = mIFD.getElementSize(); mIFD.addEntry("TileByteCounts"); mIFD.addEntry("TileOffsets"); @@ -251,7 +251,7 @@ void tiff::ImageWriter::initTiles() { for (sys::Uint32_T x = 0; x < tilesAcross; ++x) { - sys::Uint32_T byteCount = tileSize * tileSize * elementSize; + const sys::Uint32_T byteCount = tileSize * tileSize * elementSize; mIFD.addEntryValue("TileOffsets", (sys::Uint32_T) fileOffset); mIFD.addEntryValue("TileByteCounts", (sys::Uint32_T) byteCount); fileOffset += byteCount; diff --git a/externals/coda-oss/modules/c++/tiff/source/Utils.cpp b/externals/coda-oss/modules/c++/tiff/source/Utils.cpp index 9467a08d48..59de597e3b 100644 --- a/externals/coda-oss/modules/c++/tiff/source/Utils.cpp +++ b/externals/coda-oss/modules/c++/tiff/source/Utils.cpp @@ -83,10 +83,10 @@ tiff::IFD* tiff::Utils::createGeoTiffIFD(tiff::IFD* ifd) tiff::IFD* geoIFD = new tiff::IFD; tiff::IFDEntry *geoDir = (*ifd)["GeoKeyDirectoryTag"]; - tiff::IFDEntry *doubleParams = + tiff::IFDEntry* const doubleParams = ifd->exists("GeoDoubleParamsTag") ? (*ifd)["GeoDoubleParamsTag"] : NULL; - tiff::IFDEntry *asciiParams = + tiff::IFDEntry* const asciiParams = ifd->exists("GeoAsciiParamsTag") ? (*ifd)["GeoAsciiParamsTag"] : NULL; diff --git a/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/ValidatorXerces.h b/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/ValidatorXerces.h index 224b54fd01..3cdde68844 100644 --- a/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/ValidatorXerces.h +++ b/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/ValidatorXerces.h @@ -114,10 +114,9 @@ class ValidatorXerces : public ValidatorInterface ValidatorXerces(const std::vector& schemaPaths, logging::Logger* log, bool recursive = true); - ValidatorXerces(const std::vector&, + ValidatorXerces(const std::vector&, // fs::path -> mLegacyStringConversion = false logging::Logger* log, bool recursive = true); - ValidatorXerces(const coda_oss::filesystem::path&, logging::Logger&); ValidatorXerces(const ValidatorXerces&) = delete; ValidatorXerces& operator=(const ValidatorXerces&) = delete; @@ -142,15 +141,11 @@ class ValidatorXerces : public ValidatorInterface static std::vector loadSchemas(const std::vector& schemaPaths, bool recursive=true); private: - void initialize(); // easier than chaining constructors w/existing code - bool validate_(const coda_oss::u8string& xml, const std::string& xmlID, std::vector& errors) const; - void loadGrammar(const coda_oss::filesystem::path&, logging::Logger&); std::unique_ptr mSchemaPool; - std::unique_ptr mErrorHandler; std::unique_ptr mValidator; diff --git a/externals/coda-oss/modules/c++/xml.lite/source/Element.cpp b/externals/coda-oss/modules/c++/xml.lite/source/Element.cpp index 1513003f71..ddb7177d81 100644 --- a/externals/coda-oss/modules/c++/xml.lite/source/Element.cpp +++ b/externals/coda-oss/modules/c++/xml.lite/source/Element.cpp @@ -111,6 +111,7 @@ void xml::lite::Element::getElementsByTagName(const QName& n, std::vectorgetUri() == uri && mChildren[i]->getLocalName() @@ -163,6 +164,7 @@ void xml::lite::Element::getElementsByTagName(const std::string& localName, std::vector& elements, bool recurse) const { + elements.reserve(mChildren.size()); for (unsigned int i = 0; i < mChildren.size(); i++) { if (mChildren[i]->getLocalName() == localName) @@ -192,6 +194,7 @@ void xml::lite::Element::getElementsByTagNameNS(const std::string& qname, std::vector& elements, bool recurse) const { + elements.reserve(mChildren.size()); for (unsigned int i = 0; i < mChildren.size(); i++) { if (mChildren[i]->mName.toString() == qname) diff --git a/externals/coda-oss/modules/c++/xml.lite/source/NamespaceStack.cpp b/externals/coda-oss/modules/c++/xml.lite/source/NamespaceStack.cpp index 4ab0471120..998b41ba53 100644 --- a/externals/coda-oss/modules/c++/xml.lite/source/NamespaceStack.cpp +++ b/externals/coda-oss/modules/c++/xml.lite/source/NamespaceStack.cpp @@ -64,6 +64,7 @@ void xml::lite::NamespaceStack::getMapping(const std::string& prefix, Uri& resul void xml::lite::NamespaceStack:: getAllPrefixes(std::vector& allPrefixes) const { + allPrefixes.reserve(mMappingStack.size()); for (unsigned int i = 0; i < mMappingStack.size(); i++) { allPrefixes.push_back(mMappingStack[i].first); diff --git a/externals/coda-oss/modules/c++/xml.lite/source/ValidatorXerces.cpp b/externals/coda-oss/modules/c++/xml.lite/source/ValidatorXerces.cpp index fe75d84e12..7e794d4e4b 100644 --- a/externals/coda-oss/modules/c++/xml.lite/source/ValidatorXerces.cpp +++ b/externals/coda-oss/modules/c++/xml.lite/source/ValidatorXerces.cpp @@ -111,36 +111,7 @@ ValidatorXerces::ValidatorXerces( bool recursive) : ValidatorInterface(schemaPaths, log, recursive) { - initialize(); - - // load our schemas -- - // search each directory for schemas - const auto schemas = loadSchemas(convert(schemaPaths), recursive); - - // add the schema to the validator - for (auto&& schema : schemas) - { - loadGrammar(schema, *log); - } - - //! no additional schemas will be loaded after this point! - mSchemaPool->lockPool(); -} -ValidatorXerces::ValidatorXerces(const coda_oss::filesystem::path& schema, logging::Logger& log) : - ValidatorXerces(std::vector{schema}, &log, false /*recursive*/) -{ - initialize(); - - // add the schema to the validator - loadGrammar(schema, log); - - //! no additional schemas will be loaded after this point! - mSchemaPool->lockPool(); -} - -void ValidatorXerces::initialize() - { - // add each schema into a grammar pool -- + // add each schema into a grammar pool -- // this allows reuse mSchemaPool.reset( new xercesc::XMLGrammarPoolImpl( @@ -189,20 +160,28 @@ void ValidatorXerces::initialize() new ValidationErrorHandler()); config->setParameter(xercesc::XMLUni::fgDOMErrorHandler, mErrorHandler.get()); -} - void ValidatorXerces::loadGrammar(const coda_oss::filesystem::path& schema, logging::Logger& log) -{ - // add the schema to the validator - if (!mValidator->loadGrammar(schema.c_str(), - xercesc::Grammar::SchemaGrammarType, - true)) - { - std::ostringstream oss; - oss << "Error: Failure to load schema " << schema; - log.warn(Ctxt(oss.str())); - } - } + // load our schemas -- + // search each directory for schemas + const auto schemas = loadSchemas(convert(schemaPaths), recursive); + + // add the schema to the validator + // add the schema to the validator + for (auto&& schema : schemas) + { + if (!mValidator->loadGrammar(schema.c_str(), + xercesc::Grammar::SchemaGrammarType, + true)) + { + std::ostringstream oss; + oss << "Error: Failure to load schema " << schema; + log->warn(Ctxt(oss.str())); + } + } + + //! no additional schemas will be loaded after this point! + mSchemaPool->lockPool(); +} std::vector ValidatorXerces::loadSchemas(const std::vector& schemaPaths, bool recursive) { diff --git a/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlparser.cpp b/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlparser.cpp index b6d443bd55..6a4ff8bf18 100644 --- a/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlparser.cpp +++ b/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlparser.cpp @@ -417,11 +417,14 @@ TEST_CASE(testReadEmbeddedXml) } template -static void testValidateXmlFile_(const std::string& testName, - const xml::lite::Validator& validator, const std::string& xmlFile, TStringStream* pStringStream) +static void testValidateXmlFile_(const std::string& testName, const std::string& xmlFile, TStringStream* pStringStream) { + static const auto xsd = find_unittest_file("doc.xsd"); const auto path = find_unittest_file(xmlFile); + const std::vector schemaPaths{xsd.parent_path()}; // fs::path -> new string-conversion code + const xml::lite::Validator validator(schemaPaths, nullptr /*log*/); + io::FileInputStream fis(path); std::vector errors; const auto result = (pStringStream == nullptr) ? validator.validate(fis, path.string() /*xmlID*/, errors) : @@ -432,18 +435,7 @@ static void testValidateXmlFile_(const std::string& testName, } TEST_ASSERT_FALSE(result); TEST_ASSERT_TRUE(errors.empty()); - -} -template -static void testValidateXmlFile_(const std::string& testName, const std::string& xmlFile, TStringStream* pStringStream) -{ - static const auto xsd = find_unittest_file("doc.xsd"); - const std::vector schemaPaths{xsd.parent_path()}; // fs::path -> new string-conversion code - const xml::lite::Validator validator(schemaPaths, nullptr /*log*/); - - testValidateXmlFile_(testName, validator, xmlFile, pStringStream); } - static void testValidateXmlFile(const std::string& testName, const std::string& xmlFile) { testValidateXmlFile_(testName, xmlFile, nullptr /*pStringStream*/); @@ -471,42 +463,6 @@ TEST_CASE(testValidateXmlFile) testValidateXmlFile(testName, "encoding_windows-1252.xml", io::W1252StringStream()); } -template -static void testValidateXmlFile_XSD_(const std::string& testName, const std::string& xmlFile, TStringStream* pStringStream) -{ - static const auto xsd = find_unittest_file("doc.xsd"); - logging::Logger log; - const xml::lite::Validator validator(xsd, log); - testValidateXmlFile_(testName, validator, xmlFile, pStringStream); -} -static void testValidateXmlFile_XSD(const std::string& testName, const std::string& xmlFile) -{ - testValidateXmlFile_XSD_(testName, xmlFile, nullptr /*pStringStream*/); -} -template -static void testValidateXmlFile_XSD(const std::string& testName, const std::string& xmlFile, TStringStream&& oss) -{ - testValidateXmlFile_XSD_(testName, xmlFile, &oss); -} -TEST_CASE(testValidateXmlFile_XSD) -{ - // Validate using a single XSD - testValidateXmlFile_XSD(testName, "ascii.xml"); - testValidateXmlFile_XSD(testName, "ascii_encoding_utf-8.xml"); - - // legacy validate() API, new string conversion - testValidateXmlFile_XSD(testName, "utf-8.xml"); - testValidateXmlFile_XSD(testName, "encoding_utf-8.xml"); - testValidateXmlFile_XSD(testName, "encoding_windows-1252.xml"); - testValidateXmlFile_XSD(testName, "windows-1252.xml"); - - // new validate() API - testValidateXmlFile_XSD(testName, "utf-8.xml", io::U8StringStream()); - testValidateXmlFile_XSD(testName, "encoding_utf-8.xml", io::U8StringStream()); - testValidateXmlFile_XSD(testName, "windows-1252.xml", io::W1252StringStream()); - testValidateXmlFile_XSD(testName, "encoding_windows-1252.xml", io::W1252StringStream()); -} - int main(int, char**) { TEST_CHECK(testXmlParseSimple); @@ -525,5 +481,4 @@ int main(int, char**) TEST_CHECK(testReadEmbeddedXml); TEST_CHECK(testValidateXmlFile); - TEST_CHECK(testValidateXmlFile_XSD); } diff --git a/externals/nitro/ReleaseNotes.md b/externals/nitro/ReleaseNotes.md index 3446ae82f6..c158869648 100644 --- a/externals/nitro/ReleaseNotes.md +++ b/externals/nitro/ReleaseNotes.md @@ -1,5 +1,11 @@ # NITRO (NITF i/o) Release Notes +## [Version 2.11.3](https://github.com/mdaus/nitro/releases/tag/NITRO-2.11.3); June 5, 2023 +* [coda-oss](https://github.com/mdaus/coda-oss) release [2023-06-05](https://github.com/mdaus/coda-oss/releases/tag/2023-06-05) +* Fix display of [certain TREs](https://github.com/mdaus/nitro/issues/529). +* Adjust compiler flags for clean *CMake* builds. +* Implement `DecompressionInterface::adapterFreeBlock()` to fix decompression. + ## [Version 2.11.2](https://github.com/mdaus/nitro/releases/tag/NITRO-2.11.2); December 14, 2022 * [coda-oss](https://github.com/mdaus/coda-oss) release [2022-12-14](https://github.com/mdaus/coda-oss/releases/tag/2022-12-14) * Further work at getting unittests to work better when included elsewhere (e.g., SIX) as **externals**. @@ -20,7 +26,7 @@ except that C++14 is now required. [master](https://github.com/mdaus/nitro/tree * [coda-oss](https://github.com/mdaus/coda-oss) release [2022-08-30](https://github.com/mdaus/coda-oss/releases/tag/2022-08-30) * Build JPEG decompression as a plug-in. * tweak unittests so they run in SIX. -* Final C++11 release 🤞🏻; future releases will be C++14 from [main](https://github.com/mdaus/nitro/tree/main). +* ~~Final C++11 release 🤞🏻; future releases will be C++14 from [main](https://github.com/mdaus/nitro/tree/main).~~ ## [Version 2.10.11](https://github.com/mdaus/nitro/releases/tag/NITRO-2.10.11); August 2, 2022 * [coda-oss](https://github.com/mdaus/coda-oss) release [2022-08-02](https://github.com/mdaus/coda-oss/releases/tag/2022-08-02) diff --git a/externals/nitro/modules/c++/nitf/include/nitf/Version.hpp b/externals/nitro/modules/c++/nitf/include/nitf/Version.hpp index 25b401c9a7..094ad93d75 100644 --- a/externals/nitro/modules/c++/nitf/include/nitf/Version.hpp +++ b/externals/nitro/modules/c++/nitf/include/nitf/Version.hpp @@ -36,9 +36,10 @@ // 2.11.0 August 30, 2022 (C++14) // 2.11.1 November 4, 2022 // 2.11.2 December 14, 2022 + // 2.11.3 June 5, 2023 #define NITF_VERSION_MAJOR 2 #define NITF_VERSION_MINOR 11 -#define NITF_VERSION_PATCH 2 +#define NITF_VERSION_PATCH 3 #define NITF_VERSION_BUILD 0 #define NITF_VERSION CODA_OSS_MAKE_VERSION_MMPB(NITF_VERSION_MAJOR, NITF_VERSION_MINOR, NITF_VERSION_PATCH, NITF_VERSION_BUILD) diff --git a/externals/nitro/modules/c/nrt/include/nrt/Version.h b/externals/nitro/modules/c/nrt/include/nrt/Version.h index feea215eb5..ffce796775 100644 --- a/externals/nitro/modules/c/nrt/include/nrt/Version.h +++ b/externals/nitro/modules/c/nrt/include/nrt/Version.h @@ -1,5 +1,5 @@ #pragma once #if !defined(NRT_LIB_VERSION) -#define NRT_LIB_VERSION "2.11.2" +#define NRT_LIB_VERSION "2.11.3" #endif diff --git a/six/modules/c++/cphd/source/ByteSwap.cpp b/six/modules/c++/cphd/source/ByteSwap.cpp index 241d3dd987..4f69666ed6 100644 --- a/six/modules/c++/cphd/source/ByteSwap.cpp +++ b/six/modules/c++/cphd/source/ByteSwap.cpp @@ -46,7 +46,7 @@ template inline void byteSwap(const void* in, T& out) { auto const inBytes = sys::make_span(in, sizeof(T)); - out = sys::swapBytes(inBytes); + out = sys::byteSwapValue(inBytes); } inline const std::byte* calc_offset(const void* input_, size_t offset) diff --git a/six/modules/c++/six/include/six/Data.h b/six/modules/c++/six/include/six/Data.h index 1c004fbeac..d22e212db1 100644 --- a/six/modules/c++/six/include/six/Data.h +++ b/six/modules/c++/six/include/six/Data.h @@ -84,7 +84,21 @@ struct Data template bool convertPixels(std::span from, std::span to, ptrdiff_t cutoff = -1) const { - return convertPixels_(std::as_bytes(from), std::as_writable_bytes(to), cutoff); + // coda-oss checks to be sure T and U are trivially_copyable. While this is + // correct (converting something else to bytes doesn't make sense), existing + // code didn't have that check. + // + // TODO: use std::as_bytes() directly + + const void* const pFrom = from.data(); + auto const pFromBytes = static_cast(pFrom); + const std::span fromBytes(pFromBytes, from.size_bytes()); + + void* const pTo = to.data(); + auto const pToBytes = static_cast(pTo); + const std::span toBytes(pToBytes, to.size_bytes()); + + return convertPixels_(fromBytes, toBytes, cutoff); } /*! diff --git a/six/modules/c++/six/include/six/Utilities.h b/six/modules/c++/six/include/six/Utilities.h index 36658b443f..ce7ab873a1 100644 --- a/six/modules/c++/six/include/six/Utilities.h +++ b/six/modules/c++/six/include/six/Utilities.h @@ -320,23 +320,35 @@ std::string findSchemaPath(const std::string& progname); template inline std::span as_bytes(std::span buffer) { - return std::as_bytes(buffer); + // coda-oss checks to be sure T is trivially_copyable. While this is + // correct (converting something else to bytes doesn't make sense), existing + // code didn't have that check. + const void* const pData = buffer.data(); + auto const pBytes = static_cast(pData); + return std::span(pBytes, buffer.size_bytes()); // TODO: use std::as_bytes } template inline std::span as_bytes(const std::vector& buffer) { - return sys::as_bytes(buffer); + const auto s = sys::make_span(buffer); + return six::as_bytes(s); } template -inline std::span as_writable_bytes(std::vector& buffer) +inline std::span as_writable_bytes(std::span& buffer) { - return sys::as_writable_bytes(buffer); + // coda-oss checks to be sure T is trivially_copyable. While this is + // correct (converting something else to bytes doesn't make sense), existing + // code didn't have that check. + void* const pData = buffer.data(); + auto const pBytes = static_cast(pData); + return std::span(pBytes, buffer.size_bytes()); // TODO: use std::as_writable_bytes } template -inline std::span as_writable_bytes(std::span& buffer) +inline std::span as_writable_bytes(std::vector& buffer) { - return std::as_writable_bytes(buffer); + const auto s = sys::make_span(buffer); + return as_writable_bytes(s); } namespace testing