diff --git a/externals/coda-oss/ReleaseNotes.md b/externals/coda-oss/ReleaseNotes.md index c54bdadcb..a5dd83e18 100644 --- a/externals/coda-oss/ReleaseNotes.md +++ b/externals/coda-oss/ReleaseNotes.md @@ -11,6 +11,12 @@ ``` # coda-oss Release Notes +## [Release 202?-??-??](https://github.com/mdaus/coda-oss/releases/tag/202?-??-??) +* New `sys::OS::getSIMDInstructionSet()` utility routine; SSE2 is required (default with 64-bit builds). +* `types::ComplexInteger` to work-around `std::complex` no longer being [valid C++](https://en.cppreference.com/w/cpp/numeric/complex). +* Another round of reducing various compiler warnings (of note: `NULL` -> `nullptr`). +* Some suport for [`std::numbers`](https://en.cppreference.com/w/cpp/header/numbers) from C++20. + ## [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. 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 6b135288d..4e26fb37d 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h @@ -35,6 +35,7 @@ #include #include "config/Exports.h" +#include "types/Complex.h" #include "ByteSwapValue.h" #include "Runnable.h" @@ -88,23 +89,50 @@ inline void check_elemSize(size_t elemSize) // 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) +template +inline auto make_cx_span(coda_oss::span s) { + using value_type = typename TComplex::value_type; // i.e., T from std::complex const void* const p_ = s.data(); - auto const p = static_cast(p_); + 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) +template +inline auto make_cx_span(coda_oss::span s) { + using value_type = typename TComplex::value_type; // i.e., T from std::complex void* const p_ = s.data(); - auto const p = static_cast(p_); + 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) +{ + static_assert(std::is_floating_point::value, "std::complex should use floating-point"); + return make_cx_span(s); +} +template +inline auto make_span(coda_oss::span> s) +{ + static_assert(std::is_floating_point::value, "std::complex should use floating-point"); + return make_cx_span(s); +} + +// Support our own complex type too :-(; it's used (too much) in SIX. +template +inline auto make_span(coda_oss::span> s) +{ + return make_cx_span(s); +} +template +inline auto make_span(coda_oss::span> s) +{ + return make_cx_span(s); +} + } // Otherwise, we can sanity-check the `elemSize` parameter @@ -115,13 +143,28 @@ inline void byteSwap(T* buffer, size_t elemSize, size_t numElems) 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<...>` +namespace details { - details::check_elemSize(elemSize); +template +inline void byteSwapCx(TComplex* buffer, size_t elemSize, size_t numElems) // dont't want `T` as `std::complex<...>` +{ + using value_type = typename TComplex::value_type; // i.e., T from std::complex + 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<...>` +{ + static_assert(std::is_floating_point::value, "std::complex should use floating-point"); + details::byteSwapCx(buffer, elemSize, numElems); +} +template +inline void byteSwap(types::Complex* buffer, size_t elemSize, size_t numElems) // dont't want `T` as `std::complex<...>` +{ + details::byteSwapCx(buffer, elemSize, numElems); +} template inline auto byteSwap(coda_oss::span buffer) @@ -137,6 +180,11 @@ inline auto byteSwap(coda_oss::span> buffer) { return byteSwap(details::make_span(buffer)); } +template +inline auto byteSwap(coda_oss::span> buffer) +{ + return byteSwap(details::make_span(buffer)); +} /*! * Swap bytes into output buffer. Note that a complex pixel @@ -185,14 +233,29 @@ inline void byteSwap(const T* buffer, size_t elemSize, size_t numElems, U* outpu 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<...>` +namespace details { - details::check_elemSize(elemSize); +template +inline void byteSwapCx(const TComplex* buffer, size_t elemSize, size_t numElems, U* outputBuffer) // dont't want `T` as `std::complex<...>` +{ + using value_type = typename TComplex::value_type; // i.e., T from std::complex + 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<...>` +{ + static_assert(std::is_floating_point::value, "std::complex should use floating-point"); + details::byteSwapCx(buffer, elemSize, numElems, outputBuffer); +} +template +inline void byteSwap(const types::Complex* buffer, size_t elemSize, size_t numElems, U* outputBuffer) // dont't want `T` as `std::complex<...>` +{ + details::byteSwapCx(buffer, elemSize, numElems, outputBuffer); +} template inline auto byteSwap(coda_oss::span buffer, coda_oss::span outputBuffer) @@ -206,6 +269,11 @@ inline auto byteSwap(coda_oss::span> buffer, coda_oss::spa { return byteSwap(details::make_span(buffer), outputBuffer); } +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) @@ -220,27 +288,62 @@ inline auto byteSwap(coda_oss::span> buffer) { return byteSwap(details::make_span(buffer)); } +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) +namespace details { +template +inline auto byteSwapCxValue(TComplex z) +{ + using value_type = typename TComplex::value_type; // i.e., T from std::complex + // 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_)); + const auto& z_ = reinterpret_cast(z); + return byteSwap(sys::make_span(z_)); } -template -inline auto byteSwap(std::complex val) +} +template +inline auto byteSwapValue(std::complex z) +{ + static_assert(std::is_floating_point::value, "std::complex should use floating-point"); + return details::byteSwapCxValue(z); +} +template +inline auto byteSwapValue(types::Complex z) +{ + return details::byteSwapCxValue(z); +} +namespace details +{ +template +inline auto byteSwapCx(TComplex val) { const auto bytes = byteSwapValue(val); assert(bytes.size() == sizeof(val)); const void* const pBytes = bytes.data(); - auto const pRetVal = static_cast*>(pBytes); + auto const pRetVal = static_cast(pBytes); return *pRetVal; } +} +template +inline auto byteSwap(std::complex val) +{ + return details::byteSwapCx(val); +} +template +inline auto byteSwap(types::Complex val) +{ + return details::byteSwapCx(val); +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/externals/coda-oss/modules/c++/sys/unittests/test_byte_swap.cpp b/externals/coda-oss/modules/c++/sys/unittests/test_byte_swap.cpp index 2d784428b..51591a3b7 100644 --- a/externals/coda-oss/modules/c++/sys/unittests/test_byte_swap.cpp +++ b/externals/coda-oss/modules/c++/sys/unittests/test_byte_swap.cpp @@ -245,15 +245,43 @@ TEST_CASE(testByteSwapValues) 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; + { + 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 + 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); + swap = sys::byteSwap(swap); // swap back + TEST_ASSERT_EQ(*pValue, swap); + } + { + using value_type = types::Complex; + const void* const pValue_ = four_bytes; // two int16_t + auto const pValue = static_cast(pValue_); + + auto swap = sys::byteSwap(*pValue); + TEST_ASSERT_NOT_EQ(*pValue, swap); + + // .real() and .imag() are swapped individually + const void* const pSwap_ = &swap; + auto pSwapBytes = static_cast(pSwap_); + TEST_ASSERT(four_bytes[0] == pSwapBytes[1]); + TEST_ASSERT(four_bytes[1] == pSwapBytes[0]); + TEST_ASSERT(four_bytes[2] == pSwapBytes[3]); + TEST_ASSERT(four_bytes[3] == pSwapBytes[2]); + + swap = sys::byteSwap(swap); // swap back + TEST_ASSERT_EQ(*pValue, swap); + + auto buffer = std::as_writable_bytes(sys::make_span(&swap, 1)); + sys::byteSwap(sys::make_span(pValue, 1), buffer); + TEST_ASSERT(four_bytes[0] == buffer[1]); + TEST_ASSERT(four_bytes[1] == buffer[0]); + TEST_ASSERT(four_bytes[2] == buffer[3]); + TEST_ASSERT(four_bytes[3] == buffer[2]); + } } TEST_CASE(testByteSwap12) diff --git a/modules/c++/nitf/unittests/test_hash_table_1++.cpp b/modules/c++/nitf/unittests/test_hash_table_1++.cpp index 8f382d942..c13fbd5ae 100644 --- a/modules/c++/nitf/unittests/test_hash_table_1++.cpp +++ b/modules/c++/nitf/unittests/test_hash_table_1++.cpp @@ -151,8 +151,6 @@ TEST_CASE(test_hash_table_iterator) } TEST_MAIN( - (void)argc; - (void)argv; TEST_CHECK(test_hash_table_1); TEST_CHECK(test_hash_table_iterator); -) \ No newline at end of file +) diff --git a/modules/c++/nitf/unittests/test_load_plugins.cpp b/modules/c++/nitf/unittests/test_load_plugins.cpp index 4aaee43ca..c94707f56 100644 --- a/modules/c++/nitf/unittests/test_load_plugins.cpp +++ b/modules/c++/nitf/unittests/test_load_plugins.cpp @@ -30,32 +30,28 @@ #include "TestCase.h" -static void load_plugin(const std::string& testName, const char* tre) +static void retrieveTREHandler(const std::string& testName, const char* tre) { nitf_Error error; - auto reg = nitf::PluginRegistry::getInstance(error); + auto const reg = nitf::PluginRegistry::getInstance(error); TEST_ASSERT(reg != nullptr); - nitf::HashTable::print(*(reg->treHandlers)); + //nitf::HashTable::print(*(reg->treHandlers)); int bad = 0; - auto test_main_ = - nitf::PluginRegistry::retrieveTREHandler(*reg, - tre, - bad, - error); + auto const test_main_ = nitf::PluginRegistry::retrieveTREHandler(*reg, tre, bad, error); TEST_ASSERT_EQ(0, bad); TEST_ASSERT(test_main_ != nullptr); } -static const std::vector& all_plugins() +static const auto& all_TREs() { - static const std::vector all_plugins_ + static const std::vector retval { #if _MSC_VER && NITRO_PCH // only build a handful in Visual Studio - "ACCHZB", "ACCPOB", "ACFTA", "AIMIDB", "CSCRNA", "ENGRDA", "HISTOA", "JITCID", "PTPRAA", "RPFHDR", + "ACCHZB", "ACCPOB", "ACFTA", "AIMIDB", "CSCRNA", "CSEXRB", "ENGRDA", "HISTOA", "JITCID", "PTPRAA", "RPFHDR", #else "ACCHZB", "BANDSB", "CSDIDA", "GEOLOB", "JITCID", "NBLOCA", "PIAPEB", "REGPTB", "RSMIDA", "STEROB", "ACCPOB", "BCKGDA", "CSEPHA", "GEOPSB", "MAPLOB", "OBJCTA", "PIAPRC", "RPC00B", "RSMPCA", "STREOB", @@ -69,59 +65,59 @@ static const std::vector& all_plugins() "BANDSA", "CSCRNA", "EXPLTB", "J2KLRA", "MTIRPB", "PIAPEA", "PTPRAA", "RSMGIA", "STDIDC", #endif }; - return all_plugins_; + return retval; } -TEST_CASE(test_load_all_plugins_C) +TEST_CASE(test_retrieveTREHandler) { - nitf::Test::setNitfPluginPath(); - - for (const auto& tre : all_plugins()) + for (const auto& tre : all_TREs()) { - load_plugin(testName, tre.c_str()); + retrieveTREHandler(testName, tre.c_str()); } } TEST_CASE(test_load_PTPRAA) { - nitf::Test::setNitfPluginPath(); - load_plugin(testName, "PTPRAA"); + retrieveTREHandler(testName, "PTPRAA"); } TEST_CASE(test_load_ENGRDA) { - nitf::Test::setNitfPluginPath(); - load_plugin(testName, "ENGRDA"); + retrieveTREHandler(testName, "ENGRDA"); } -static void loadPlugin(const std::string& testName, const std::string& path) -{ - try - { -#ifdef _WIN32 - // need the full path to load on Linux - nitf::PluginRegistry::loadPlugin(path); -#endif - TEST_SUCCESS; - } - catch (const nitf::NITFException& ex) - { - TEST_FAIL_MSG(ex.toString()); - } -} -TEST_CASE(test_load_all_plugins) +TEST_CASE(test_load_all_TREs) { - nitf::Test::setNitfPluginPath(); + const nitf::TRE tre("ACCPOB"); - for (const auto& tre : all_plugins()) + for (const auto& tre : all_TREs()) { - loadPlugin(testName, tre); + // TREs are quite the same thing as an arbitrary "plug in;" the underlying + // infrastructure is all built on shared-libraries/DLLs, but details differ. + // + // As a result, we can't expect loadPlugin() will "just work" on a TRE name. + // Unfortunately, the behavior is different on Windows and Linux. :-( + #if _WIN32 + // Keep this around for now as it works ... but it's not necessarily correct. + // Mostly an excuse to exercise more code. + try + { + nitf::PluginRegistry::loadPlugin(tre); + } + catch (const nitf::NITFException& ex) + { + TEST_FAIL_MSG(ex.toString()); + } + #endif // _WIN32 + TEST_ASSERT(nitf::PluginRegistry::treHandlerExists(tre)); } } TEST_MAIN( + nitf::Test::setNitfPluginPath(); + TEST_CHECK(test_load_PTPRAA); - TEST_CHECK(test_load_ENGRDA); - TEST_CHECK(test_load_all_plugins_C); - TEST_CHECK(test_load_all_plugins); + TEST_CHECK(test_load_ENGRDA); + TEST_CHECK(test_retrieveTREHandler); + TEST_CHECK(test_load_all_TREs); ) \ No newline at end of file diff --git a/modules/c++/nitf/unittests/test_tre_create++.cpp b/modules/c++/nitf/unittests/test_tre_create++.cpp index 9ffe05000..bc3f884fc 100644 --- a/modules/c++/nitf/unittests/test_tre_create++.cpp +++ b/modules/c++/nitf/unittests/test_tre_create++.cpp @@ -7,8 +7,6 @@ TEST_CASE(test_tre_create_329) { - nitf::Test::setNitfPluginPath(); - // https://github.com/mdaus/nitro/issues/329 nitf::TRE tre("HISTOA", "HISTOA"); // allocates fields SYSTEM .. NEVENTS @@ -21,8 +19,6 @@ TEST_CASE(test_tre_create_329) TEST_CASE(test_tre_clone_329) { - nitf::Test::setNitfPluginPath(); - // https://github.com/mdaus/nitro/issues/329 const std::string rd = "begin1020030004ABCDEFend"; @@ -43,6 +39,8 @@ TEST_CASE(test_tre_clone_329) } TEST_MAIN( + nitf::Test::setNitfPluginPath(); + TEST_CHECK(test_tre_create_329); TEST_CHECK(test_tre_clone_329); ) diff --git a/modules/c++/nitf/unittests/test_tre_mods++.cpp b/modules/c++/nitf/unittests/test_tre_mods++.cpp index 8eb85006b..1c2b4a870 100644 --- a/modules/c++/nitf/unittests/test_tre_mods++.cpp +++ b/modules/c++/nitf/unittests/test_tre_mods++.cpp @@ -159,8 +159,6 @@ struct /*namespace*/ TREs TEST_CASE(setFields) { - nitf::Test::setNitfPluginPath(); - // create an ACFTA TRE nitf::TRE tre("ACFTA"); @@ -180,8 +178,6 @@ TEST_CASE(setFields) TEST_CASE(setBinaryFields) { - nitf::Test::setNitfPluginPath(); - nitf::TRE tre("RPFHDR"); const int value = 123; tre.setField("LOCSEC", value); @@ -193,8 +189,6 @@ TEST_CASE(setBinaryFields) TEST_CASE(cloneTRE) { - nitf::Test::setNitfPluginPath(); - nitf::TRE tre("JITCID"); tre.setField("FILCMT", "fyi"); @@ -208,8 +202,6 @@ TEST_CASE(cloneTRE) TEST_CASE(basicIteration) { - nitf::Test::setNitfPluginPath(); - nitf::TRE tre("ACCPOB"); // The entire TRE is one loop, and we haven't told it @@ -237,8 +229,6 @@ TEST_CASE(basicIteration) TEST_CASE(use_ENGRDA) { - nitf::Test::setNitfPluginPath(); - nitf::TRE engrda("ENGRDA", "ENGRDA"); engrda.setField("RESRC", "HSS"); @@ -263,8 +253,6 @@ TEST_CASE(use_ENGRDA) TEST_CASE(use_ENGRDA_typed_fields) { - nitf::Test::setNitfPluginPath(); - nitf::TRE engrda("ENGRDA", "ENGRDA"); nitf::TREField_BCS_A<20> RESRC(engrda, "RESRC"); @@ -297,8 +285,6 @@ TEST_CASE(use_ENGRDA_typed_fields) TEST_CASE(use_typed_ENGRDA) { - nitf::Test::setNitfPluginPath(); - TREs::ENGRDA engrda; // nitf::TRE engrda("ENGRDA", "ENGRDA"); engrda.RESRC = "HSS"; // engrda.setField("RESRC", "HSS"); @@ -347,8 +333,6 @@ TEST_CASE(use_typed_ENGRDA) TEST_CASE(use_CSEXRB_typed_fields) { - nitf::Test::setNitfPluginPath(); - nitf::TRE tre("CSEXRB", "CSEXRB"); constexpr auto length = 12; @@ -362,8 +346,6 @@ TEST_CASE(use_CSEXRB_typed_fields) TEST_CASE(populateWhileIterating) { - nitf::Test::setNitfPluginPath(); - nitf::TRE tre("ACCPOB"); size_t numFields = 0; for (auto it = tre.begin(); it != tre.end(); ++it) @@ -388,8 +370,6 @@ TEST_CASE(populateWhileIterating) TEST_CASE(overflowingNumericFields) { - nitf::Test::setNitfPluginPath(); - nitf::TRE tre("CSCRNA"); // This field has a length of 9, so check that it's properly @@ -418,6 +398,8 @@ TEST_CASE(overflowingNumericFields) } TEST_MAIN( + nitf::Test::setNitfPluginPath(); + TEST_CHECK(setFields); TEST_CHECK(setBinaryFields); TEST_CHECK(cloneTRE); diff --git a/modules/c++/nitf/unittests/test_tre_mods.cpp b/modules/c++/nitf/unittests/test_tre_mods.cpp index be2517963..5bee638c7 100644 --- a/modules/c++/nitf/unittests/test_tre_mods.cpp +++ b/modules/c++/nitf/unittests/test_tre_mods.cpp @@ -26,8 +26,6 @@ TEST_CASE(testNestedMod) { - nitf::Test::setNitfPluginPath(); - nitf_Error error; NITF_BOOL exists; nitf_TRE* tre = nitf_TRE_construct("ACCHZB", NULL, &error); @@ -61,8 +59,6 @@ TEST_CASE(testNestedMod) TEST_CASE(testIncompleteCondMod) { - nitf::Test::setNitfPluginPath(); - nitf_Error error; NITF_BOOL exists; nitf_TRE* tre = nitf_TRE_construct("ACCPOB", NULL, &error); @@ -89,8 +85,6 @@ TEST_CASE(testIncompleteCondMod) TEST_CASE(testClone) { - nitf::Test::setNitfPluginPath(); - NITF_BOOL exists; nitf_TRE* dolly; /* used for clone */ nitf_Field* clonedField = NULL; @@ -116,8 +110,6 @@ TEST_CASE(testClone) TEST_CASE(testBasicMod) { - nitf::Test::setNitfPluginPath(); - /* construct a tre */ NITF_BOOL exists; nitf_Error error; @@ -147,8 +139,6 @@ TEST_CASE(testBasicMod) TEST_CASE(testSize) { - nitf::Test::setNitfPluginPath(); - nitf_Error error; int treLength; nitf_TRE* tre = nitf_TRE_construct("AIMIDB", NULL, &error); @@ -163,8 +153,6 @@ TEST_CASE(testSize) TEST_CASE(iterateUnfilled) { - nitf::Test::setNitfPluginPath(); - nitf_Error error; nitf_TRECursor cursor; nitf_TRE* tre = nitf_TRE_construct("ACCPOB", NULL, &error); @@ -186,8 +174,6 @@ TEST_CASE(iterateUnfilled) TEST_CASE(populateThenIterate) { - nitf::Test::setNitfPluginPath(); - nitf_Error error; nitf_TRECursor cursor; nitf_TRE* tre = nitf_TRE_construct("ACCPOB", NULL, &error); @@ -214,8 +200,6 @@ TEST_CASE(populateThenIterate) TEST_CASE(populateWhileIterating) { - nitf::Test::setNitfPluginPath(); - nitf_Error error; nitf_TRECursor cursor; nitf_TRE* tre = nitf_TRE_construct("ACCPOB", NULL, &error); @@ -247,6 +231,8 @@ TEST_CASE(populateWhileIterating) } TEST_MAIN( + nitf::Test::setNitfPluginPath(); + TEST_CHECK(testClone); TEST_CHECK(testSize); TEST_CHECK(testBasicMod); diff --git a/modules/c++/nitf/unittests/test_writer_3++.cpp b/modules/c++/nitf/unittests/test_writer_3++.cpp index d2955dd26..e68dd3d37 100644 --- a/modules/c++/nitf/unittests/test_writer_3++.cpp +++ b/modules/c++/nitf/unittests/test_writer_3++.cpp @@ -28,6 +28,7 @@ #include #include +#include #include "TestCase.h" @@ -268,4 +269,4 @@ TEST_CASE(test_buffered_write_) TEST_MAIN( TEST_CHECK(test_writer_3_); TEST_CHECK(test_buffered_write_); - ) \ No newline at end of file + ) diff --git a/modules/c/nitf/source/BandInfo.c b/modules/c/nitf/source/BandInfo.c index c70ee3f1c..685c5ac33 100644 --- a/modules/c/nitf/source/BandInfo.c +++ b/modules/c/nitf/source/BandInfo.c @@ -80,7 +80,7 @@ NITFAPI(void) nitf_BandInfo_destruct(nitf_BandInfo ** info) _NITF_DESTRUCT_FIELD(&(*info), NITF_NLUTS); _NITF_DESTRUCT_FIELD(&(*info), NITF_NELUT); - if (&(*info)->lut) + if ((*info)->lut) { nitf_LookupTable_destruct(&(*info)->lut); }