diff --git a/externals/coda-oss/UnitTest/UnitTest.vcxproj b/externals/coda-oss/UnitTest/UnitTest.vcxproj index 020ee7b39..d79dab6f9 100644 --- a/externals/coda-oss/UnitTest/UnitTest.vcxproj +++ b/externals/coda-oss/UnitTest/UnitTest.vcxproj @@ -23,7 +23,6 @@ DynamicLibrary true v143 - false Unicode @@ -31,7 +30,6 @@ false v143 true - false Unicode @@ -97,6 +95,7 @@ true /Zc:__cplusplus %(AdditionalOptions) AdvancedVectorExtensions2 + Speed Windows diff --git a/externals/coda-oss/modules/c++/sys/include/sys/Path.h b/externals/coda-oss/modules/c++/sys/include/sys/Path.h index d7d950202..74d78af5c 100644 --- a/externals/coda-oss/modules/c++/sys/include/sys/Path.h +++ b/externals/coda-oss/modules/c++/sys/include/sys/Path.h @@ -27,13 +27,15 @@ #include #include #include +#include #include "config/Exports.h" - #include +#include "coda_oss/span.h" #include "sys/OS.h" #include "sys/filesystem.h" +#include "sys/Span.h" /*! @@ -295,6 +297,16 @@ class CODA_OSS_API Path std::ostream& operator<<(std::ostream& os, const sys::Path& path); std::istream& operator>>(std::istream& os, sys::Path& path); + +// Convert between collections of paths as strings and sys::filesystem::path +CODA_OSS_API std::vector convertPaths(coda_oss::span); +CODA_OSS_API std::vector convertPaths(coda_oss::span); +template +inline auto convertPaths(const std::vector& paths) +{ + return convertPaths(make_span(paths)); +} + } #endif // CODA_OSS_sys_Path_h_INCLUDED_ diff --git a/externals/coda-oss/modules/c++/sys/source/AbstractOS.cpp b/externals/coda-oss/modules/c++/sys/source/AbstractOS.cpp index dd22c3786..436e12bb6 100644 --- a/externals/coda-oss/modules/c++/sys/source/AbstractOS.cpp +++ b/externals/coda-oss/modules/c++/sys/source/AbstractOS.cpp @@ -86,29 +86,14 @@ AbstractOS::search(const std::vector& searchPaths, return elementsFound; } -inline auto convert(const std::vector& paths) -{ - std::vector retval; - std::transform(paths.begin(), paths.end(), std::back_inserter(retval), - [](const fs::path& p) { return p.string(); }); - return retval; -} -inline auto convert(const std::vector& paths) -{ - std::vector retval; - std::transform(paths.begin(), paths.end(), std::back_inserter(retval), - [](const auto& p) { return p; }); - return retval; -} - std::vector AbstractOS::search( const std::vector& searchPaths, const std::string& fragment, const std::string& extension, bool recursive) const { - const auto results = search(convert(searchPaths), fragment, extension, recursive); - return convert(results); + const auto results = search(convertPaths(searchPaths), fragment, extension, recursive); + return convertPaths(results); } void AbstractOS::remove(const std::string& path) const diff --git a/externals/coda-oss/modules/c++/sys/source/Path.cpp b/externals/coda-oss/modules/c++/sys/source/Path.cpp index 4c91e6d18..99233b236 100644 --- a/externals/coda-oss/modules/c++/sys/source/Path.cpp +++ b/externals/coda-oss/modules/c++/sys/source/Path.cpp @@ -22,6 +22,7 @@ #include "sys/Path.h" #include +#include #include namespace fs = coda_oss::filesystem; @@ -849,4 +850,20 @@ std::string Path::expandEnvironmentVariables(const std::string& path, fs::file_t return expandEnvironmentVariables_(path, unused_checkIfExists, &type); } +template +inline auto convertPaths_(coda_oss::span paths, TFunc fun) +{ + std::vector retval; + std::transform(paths.begin(), paths.end(), std::back_inserter(retval), fun); + return retval; +} +std::vector convertPaths(coda_oss::span paths) +{ + return convertPaths_(paths, [](const auto& p) { return p.string(); }); } +std::vector convertPaths(coda_oss::span paths) +{ + return convertPaths_(paths, [](const auto& p) { return p; }); +} + +} \ No newline at end of file diff --git a/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/UtilitiesXerces.h b/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/UtilitiesXerces.h index ef2039123..159bbb6ea 100644 --- a/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/UtilitiesXerces.h +++ b/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/UtilitiesXerces.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "config/compiler_extensions.h" #include "config/Exports.h" @@ -409,17 +410,20 @@ struct XercesErrorHandler final : public XercesErrorHandlerInterface_T */ struct CODA_OSS_API XercesContext final { - //! Constructor XercesContext(); - - //! Destructor ~XercesContext(); + XercesContext(const XercesContext&) = delete; + XercesContext& operator=(const XercesContext&) = delete; + XercesContext(XercesContext&&) = delete; + XercesContext& operator=(XercesContext&&) = delete; + void destroy(); private: - static std::mutex mMutex; - bool mIsDestroyed; + struct Impl; + static std::shared_ptr getInstance(); + std::shared_ptr mpImpl; }; } } 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 8d5d79ba0..56e9689ae 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 @@ -89,12 +89,8 @@ struct ValidationErrorHandler final : public xercesc::DOMErrorHandler * * This class is the Xercesc schema validator */ -class CODA_OSS_API ValidatorXerces : public ValidatorInterface +struct CODA_OSS_API ValidatorXerces : public ValidatorInterface { - XercesContext mCtxt; //! this must be the first member listed - -public: - /*! * Constructor * \param schemaPaths Vector of both paths and singular schemas @@ -104,10 +100,10 @@ class CODA_OSS_API ValidatorXerces : public ValidatorInterface * input */ ValidatorXerces(const std::vector& schemaPaths, - logging::Logger* log, + logging::Logger* log = nullptr, bool recursive = true); - ValidatorXerces(const std::vector&, // fs::path -> mLegacyStringConversion = false - logging::Logger* log, + ValidatorXerces(const std::vector&, + logging::Logger* log = nullptr, bool recursive = true); ValidatorXerces(const ValidatorXerces&) = delete; @@ -133,6 +129,8 @@ class CODA_OSS_API ValidatorXerces : public ValidatorInterface static std::vector loadSchemas(const std::vector& schemaPaths, bool recursive=true); private: + XercesContext mCtxt; + bool validate_(const coda_oss::u8string& xml, const std::string& xmlID, std::vector& errors) const; diff --git a/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/XMLReaderXerces.h b/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/XMLReaderXerces.h index a808be8d8..d40aea202 100644 --- a/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/XMLReaderXerces.h +++ b/externals/coda-oss/modules/c++/xml.lite/include/xml/lite/XMLReaderXerces.h @@ -61,7 +61,7 @@ namespace lite */ class CODA_OSS_API XMLReaderXerces final : public XMLReaderInterface { - XercesContext mCtxt; //! this must be the first member listed + XercesContext mCtxt; std::unique_ptr mNative; std::unique_ptr mDriverContentHandler; std::unique_ptr mErrorHandler; diff --git a/externals/coda-oss/modules/c++/xml.lite/source/UtilitiesXerces.cpp b/externals/coda-oss/modules/c++/xml.lite/source/UtilitiesXerces.cpp index ffb0f7fd7..943eb5e5f 100644 --- a/externals/coda-oss/modules/c++/xml.lite/source/UtilitiesXerces.cpp +++ b/externals/coda-oss/modules/c++/xml.lite/source/UtilitiesXerces.cpp @@ -28,8 +28,6 @@ namespace xml { namespace lite { -std::mutex XercesContext::mMutex; - XercesLocalString::XercesLocalString(XMLCh* xmlStr) : mLocal(xmlStr) { @@ -186,8 +184,16 @@ fatalError(const SAXParseException &exception) throw except::Error(Ctxt(xex.getMessage())); } -XercesContext::XercesContext() : - mIsDestroyed(false) +/*! + * \class XercesContext::Impl + * \brief This class safely creates and destroys Xerces + */ +struct XercesContext::Impl final +{ + static std::mutex mMutex; + bool mIsDestroyed = false; + +Impl() { //! XMLPlatformUtils::Initialize is not thread safe! try @@ -203,7 +209,7 @@ XercesContext::XercesContext() : } } -XercesContext::~XercesContext() +~Impl() { try { @@ -214,7 +220,7 @@ XercesContext::~XercesContext() } } -void XercesContext::destroy() +void destroy() { // wrapping it here saves the mutex lock if (!mIsDestroyed) @@ -235,7 +241,28 @@ void XercesContext::destroy() } } } +}; +std::mutex XercesContext::Impl::mMutex; + +std::shared_ptr XercesContext::getInstance() +{ + // The one and only instance; call XMLPlatformUtils::Initialize() and XMLPlatformUtils::Terminate() just once. + static auto impl = std::make_shared(); + return impl; // increment reference count +} +XercesContext::XercesContext() : mpImpl(getInstance()) // increment reference count +{ +} +XercesContext::~XercesContext() +{ + destroy(); } +void XercesContext::destroy() +{ + mpImpl.reset(); } +} // lite +} // xml + #endif 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 3950d1242..dba996bd9 100644 --- a/externals/coda-oss/modules/c++/xml.lite/source/ValidatorXerces.cpp +++ b/externals/coda-oss/modules/c++/xml.lite/source/ValidatorXerces.cpp @@ -37,6 +37,7 @@ CODA_OSS_disable_warning(-Wshadow) CODA_OSS_disable_warning_pop #include +#include #include #include @@ -89,26 +90,11 @@ bool ValidationErrorHandler::handleError( return true; } -inline std::vector convert(const std::vector& schemaPaths) -{ - std::vector retval; - std::transform(schemaPaths.begin(), schemaPaths.end(), std::back_inserter(retval), - [](const fs::path& p) { return p.string(); }); - return retval; -} -inline auto convert(const std::vector& paths) -{ - std::vector retval; - std::transform(paths.begin(), paths.end(), std::back_inserter(retval), - [](const auto& p) { return p; }); - return retval; -} - ValidatorXerces::ValidatorXerces( const std::vector& schemaPaths, logging::Logger* log, bool recursive) : - ValidatorXerces(convert(schemaPaths), log, recursive) + ValidatorXerces(sys::convertPaths(schemaPaths), log, recursive) { } ValidatorXerces::ValidatorXerces( @@ -169,7 +155,7 @@ ValidatorXerces::ValidatorXerces( // load our schemas -- // search each directory for schemas - const auto schemas = loadSchemas(convert(schemaPaths), recursive); + const auto schemas = loadSchemas(sys::convertPaths(schemaPaths), recursive); // add the schema to the validator // add the schema to the validator @@ -179,9 +165,12 @@ ValidatorXerces::ValidatorXerces( xercesc::Grammar::SchemaGrammarType, true)) { - std::ostringstream oss; - oss << "Error: Failure to load schema " << schema; - log->warn(Ctxt(oss)); + if (log != nullptr) + { + std::ostringstream oss; + oss << "Error: Failure to load schema " << schema; + log->warn(Ctxt(oss)); + } } } 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 e35911651..b39f411fb 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 @@ -463,8 +463,8 @@ static void testValidateXmlFile_(const std::string& testName, const std::string& 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*/); + const std::vector schemaPaths{xsd.parent_path()}; + const xml::lite::Validator validator(schemaPaths); io::FileInputStream fis(path); std::vector errors; diff --git a/six/modules/c++/cphd/source/CPHDReader.cpp b/six/modules/c++/cphd/source/CPHDReader.cpp index 40258717e..8cb31fbb9 100644 --- a/six/modules/c++/cphd/source/CPHDReader.cpp +++ b/six/modules/c++/cphd/source/CPHDReader.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -60,10 +61,7 @@ static cphd::Metadata fromXML(io::SeekableInputStream& inStream, logger = std::make_shared(); } - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); - + const auto schemaPaths = sys::convertPaths(schemaPaths_); return cphd::CPHDXMLControl(logger.get()).fromXML(xmlParser.getDocument(), schemaPaths); } cphd::CPHDReader::CPHDReader(std::shared_ptr inStream, diff --git a/six/modules/c++/cphd/source/CPHDWriter.cpp b/six/modules/c++/cphd/source/CPHDWriter.cpp index 89f719332..60d0d5f7f 100644 --- a/six/modules/c++/cphd/source/CPHDWriter.cpp +++ b/six/modules/c++/cphd/source/CPHDWriter.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -62,13 +63,6 @@ CPHDWriter::CPHDWriter(const Metadata& metadata, { } -static auto transform(const std::vector& schemaPaths) -{ - std::vector retval; - std::transform(schemaPaths.begin(), schemaPaths.end(), std::back_inserter(retval), - [](const std::string& s) { return s; }); - return retval; -} CPHDWriter::CPHDWriter(const Metadata& metadata, std::shared_ptr outStream, const std::vector& schemaPaths, @@ -78,7 +72,7 @@ CPHDWriter::CPHDWriter(const Metadata& metadata, mElementSize(metadata.data.getNumBytesPerSample()), mScratchSpaceSize(scratchSpaceSize), mNumThreads(numThreads), - mSchemaPaths(transform(schemaPaths)), + mSchemaPaths(sys::convertPaths(schemaPaths)), mpSchemaPaths(&mSchemaPaths), mSharedStream(outStream), mStream(*mSharedStream), diff --git a/six/modules/c++/cphd/source/CPHDXMLControl.cpp b/six/modules/c++/cphd/source/CPHDXMLControl.cpp index f7902398d..791549005 100644 --- a/six/modules/c++/cphd/source/CPHDXMLControl.cpp +++ b/six/modules/c++/cphd/source/CPHDXMLControl.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -62,8 +63,7 @@ std::u8string CPHDXMLControl::toXMLString( std::vector schemaPaths; if (pSchemaPaths != nullptr) { - std::transform(pSchemaPaths->begin(), pSchemaPaths->end(), std::back_inserter(schemaPaths), - [](const std::filesystem::path& p) { return p.string(); }); + schemaPaths = sys::convertPaths(*pSchemaPaths); } std::unique_ptr doc(toXML(metadata, schemaPaths)); @@ -78,10 +78,7 @@ std::u8string CPHDXMLControl::toXMLString( const std::vector& schemaPaths_, bool prettyPrint) { - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); - + const auto schemaPaths = sys::convertPaths(schemaPaths_); return toXMLString(metadata, &schemaPaths, prettyPrint); } std::string CPHDXMLControl::toXMLString_( @@ -130,10 +127,7 @@ std::unique_ptr CPHDXMLControl::toXMLImpl(const Metadata& m std::unique_ptr CPHDXMLControl::fromXML(const std::string& xmlString, const std::vector& schemaPaths_) { - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); - + const auto schemaPaths = sys::convertPaths(schemaPaths_); return fromXML(str::u8FromNative(xmlString), schemaPaths); } std::unique_ptr CPHDXMLControl::fromXML(const std::u8string& xmlString, @@ -158,9 +152,7 @@ std::unique_ptr CPHDXMLControl::fromXML(const xml::lite::Document* doc } Metadata CPHDXMLControl::fromXML(const xml::lite::Document& doc, const std::vector& schemaPaths) { - std::vector schemaPaths_; - std::transform(schemaPaths.begin(), schemaPaths.end(), std::back_inserter(schemaPaths_), - [](const std::filesystem::path& p) { return p.string(); }); + const auto schemaPaths_ = sys::convertPaths(schemaPaths); auto result = fromXML(&doc, schemaPaths_); auto retval = std::move(*(result.release())); diff --git a/six/modules/c++/six.sicd/source/CropUtils.cpp b/six/modules/c++/six.sicd/source/CropUtils.cpp index 64b25cd5c..347cca5e0 100644 --- a/six/modules/c++/six.sicd/source/CropUtils.cpp +++ b/six/modules/c++/six.sicd/source/CropUtils.cpp @@ -31,6 +31,8 @@ #include #include #include +#include + #include #include #include @@ -126,8 +128,7 @@ void cropSICD(six::NITFReadControl& reader, // Write the AOI SICD out six::NITFWriteControl writer(std::move(aoiData)); const std::span image(buffer.get(), origDims.area()); - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), [](const std::string& s) { return s; }); + const auto schemaPaths = sys::convertPaths(schemaPaths_); writer.save_image(image, outPathname, schemaPaths); } diff --git a/six/modules/c++/six.sicd/source/Utilities.cpp b/six/modules/c++/six.sicd/source/Utilities.cpp index 319d62c77..5dd9e3483 100644 --- a/six/modules/c++/six.sicd/source/Utilities.cpp +++ b/six/modules/c++/six.sicd/source/Utilities.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -632,8 +633,7 @@ void Utilities::readSicd(const fs::path& sicdPathname, std::unique_ptr& complexData, std::vector& widebandData) { - std::vector schemaPaths_; - std::transform(schemaPaths.begin(), schemaPaths.end(), std::back_inserter(schemaPaths_), [](const fs::path& p) { return p.string(); }); + const auto schemaPaths_ = sys::convertPaths(schemaPaths); readSicd(sicdPathname.string(), schemaPaths_, complexData, widebandData); } ComplexImageResult Utilities::readSicd(const fs::path& sicdPathname, const std::vector& schemaPaths) @@ -1024,11 +1024,7 @@ std::unique_ptr Utilities::parseDataFromString( logging::Logger& log) { const auto xmlStr = str::u8FromNative(xmlStr_); - - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); - + const auto schemaPaths = sys::convertPaths(schemaPaths_); return parseDataFromString(xmlStr, &schemaPaths, &log); } std::unique_ptr Utilities::parseDataFromString(const std::u8string& xmlStr, @@ -1043,10 +1039,7 @@ std::u8string Utilities::toXMLString(const ComplexData& data, const std::vector& schemaPaths_, logging::Logger* logger) { - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); - + const auto schemaPaths = sys::convertPaths(schemaPaths_); return toXMLString(data, &schemaPaths, logger); } std::string Utilities::toXMLString_(const ComplexData& data, @@ -1639,8 +1632,7 @@ static void writeAsNITF(const fs::path& pathname, const std::vector writer.setLogger(logging::setupLogger("out")); const std::span image(image_, getExtent(data).area()); - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), [](const std::string& s) { return s; }); + const auto schemaPaths = sys::convertPaths(schemaPaths_); writer.save_image(image, pathname, schemaPaths); } void six::sicd::writeAsNITF(const fs::path& pathname, const std::vector& schemaPaths, const ComplexData& data, std::span image) @@ -1653,8 +1645,7 @@ void six::sicd::writeAsNITF(const fs::path& pathname, const std::vector& schemaPaths, const ComplexData& data, std::span image) { - std::vector schemaPaths_; - std::transform(schemaPaths.begin(), schemaPaths.end(), std::back_inserter(schemaPaths_), [](const fs::path& p) { return p.string(); }); + const auto schemaPaths_ = sys::convertPaths(schemaPaths); writeAsNITF(pathname, schemaPaths_, data, image); } void six::sicd::writeAsNITF(const fs::path& pathname, const std::vector& schemaPaths, const ComplexImage& image) diff --git a/six/modules/c++/six.sicd/unittests/test_valid_six.cpp b/six/modules/c++/six.sicd/unittests/test_valid_six.cpp index 456569108..03f5b0d4b 100644 --- a/six/modules/c++/six.sicd/unittests/test_valid_six.cpp +++ b/six/modules/c++/six.sicd/unittests/test_valid_six.cpp @@ -184,9 +184,7 @@ TEST_CASE(sicd_French_xml) // const auto schemaPaths = ::six::testing::getSchemaPaths(); // // // Use legacy APIs ... to test other XML processing path -// std::vector schemaPaths_; -// std::transform(schemaPaths.begin(), schemaPaths.end(), std::back_inserter(schemaPaths_), -// [](const std::filesystem::path& p) { return p.string(); }); +// const auto schemaPaths_ = sys::convertPaths(schemaPaths); // // six::sicd::NITFReadComplexXMLControl reader; // reader.setLogger(); diff --git a/six/modules/c++/six.sidd/source/Utilities.cpp b/six/modules/c++/six.sidd/source/Utilities.cpp index 8a2455db2..3cd07c034 100644 --- a/six/modules/c++/six.sidd/source/Utilities.cpp +++ b/six/modules/c++/six.sidd/source/Utilities.cpp @@ -26,6 +26,7 @@ #include #include +#include #include "six/Utilities.h" #include "six/sidd/DerivedXMLControl.h" @@ -564,10 +565,7 @@ std::unique_ptr Utilities::parseDataFromString(const std::string& x const std::vector& schemaPaths_, logging::Logger& log) { const auto xmlStr = str::u8FromNative(xmlStr_); - - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); + const auto schemaPaths = sys::convertPaths(schemaPaths_); auto result = parseDataFromString(xmlStr, &schemaPaths, &log); return std::unique_ptr(result.release()); @@ -583,10 +581,7 @@ std::unique_ptr Utilities::parseDataFromString(const std::u8string& std::u8string Utilities::toXMLString(const DerivedData& data, const std::vector& schemaPaths_, logging::Logger* logger) { - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); - + const auto schemaPaths = sys::convertPaths(schemaPaths_); return toXMLString(data, &schemaPaths, logger); } std::string Utilities::toXMLString_(const DerivedData& data, diff --git a/six/modules/c++/six/include/six/NITFWriteControl.h b/six/modules/c++/six/include/six/NITFWriteControl.h index c72806999..642bbed97 100644 --- a/six/modules/c++/six/include/six/NITFWriteControl.h +++ b/six/modules/c++/six/include/six/NITFWriteControl.h @@ -35,6 +35,7 @@ #include #include +#include #include "six/Types.h" #include "six/Container.h" @@ -573,9 +574,7 @@ template inline void save(NITFWriteControl& writeControl, std::span imageData, const std::string& outputFile, const std::vector& schemaPaths_) { - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); + const auto schemaPaths = sys::convertPaths(schemaPaths_); save(writeControl, imageData, outputFile, schemaPaths); } diff --git a/six/modules/c++/six/include/six/ReadControl.h b/six/modules/c++/six/include/six/ReadControl.h index a522c6502..570cd3fad 100644 --- a/six/modules/c++/six/include/six/ReadControl.h +++ b/six/modules/c++/six/include/six/ReadControl.h @@ -27,6 +27,10 @@ #include #include +#include +#include +#include + #include "six/Types.h" #include "six/Region.h" #include "six/Container.h" @@ -34,8 +38,6 @@ #include "six/XMLControlFactory.h" #include "six/Logger.h" #include "six/Exports.h" -#include -#include namespace six { @@ -95,7 +97,7 @@ struct SIX_SIX_API ReadControl std::vector schemaPaths_; if (pSchemaPaths != nullptr) { - std::transform(pSchemaPaths->begin(), pSchemaPaths->end(), std::back_inserter(schemaPaths_), [](const std::filesystem::path& p) { return p.string(); }); + schemaPaths_ = sys::convertPaths(*pSchemaPaths); } load(fromFile.string(), schemaPaths_); } diff --git a/six/modules/c++/six/include/six/XMLControlFactory.h b/six/modules/c++/six/include/six/XMLControlFactory.h index 9735dfe9e..78de10825 100644 --- a/six/modules/c++/six/include/six/XMLControlFactory.h +++ b/six/modules/c++/six/include/six/XMLControlFactory.h @@ -200,6 +200,13 @@ SIX_SIX_API std::u8string toValidXMLString(const Data&, //! Singleton declaration of our XMLControlRegistry SIX_SIX_API XMLControlRegistry& getXMLControlFactory(); +namespace XMLControlFactory +{ + inline auto& getInstance() + { + return getXMLControlFactory(); + } +} } diff --git a/six/modules/c++/six/source/NITFWriteControl.cpp b/six/modules/c++/six/source/NITFWriteControl.cpp index add7312eb..f92806cb9 100644 --- a/six/modules/c++/six/source/NITFWriteControl.cpp +++ b/six/modules/c++/six/source/NITFWriteControl.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -510,36 +511,29 @@ void NITFWriteControl::do_save_(const T& imageData, bool doByteSwap, bool enable } } -static std::vector convert_paths( const std::vector& schemaPaths) -{ - std::vector retval; - std::transform(schemaPaths.begin(), schemaPaths.end(), std::back_inserter(retval), - [](const std::filesystem::path& p) { return p.string(); }); - return retval; -} void NITFWriteControl::save_image(std::span imageData, nitf::IOInterface& outputFile, const std::vector& schemaPaths) { - do_save(imageData, outputFile, convert_paths(schemaPaths)); + do_save(imageData, outputFile, sys::convertPaths(schemaPaths)); } void NITFWriteControl::save_image(std::span imageData, nitf::IOInterface& outputFile, const std::vector& schemaPaths) { - do_save(imageData, outputFile, convert_paths(schemaPaths)); + do_save(imageData, outputFile, sys::convertPaths(schemaPaths)); } void NITFWriteControl::save_image(std::span imageData, nitf::IOInterface& outputFile, const std::vector& schemaPaths) { - do_save(imageData, outputFile, convert_paths(schemaPaths)); + do_save(imageData, outputFile, sys::convertPaths(schemaPaths)); } void NITFWriteControl::save_image(std::span imageData, nitf::IOInterface& outputFile, const std::vector& schemaPaths) { - do_save(imageData, outputFile, convert_paths(schemaPaths)); + do_save(imageData, outputFile, sys::convertPaths(schemaPaths)); } void NITFWriteControl::save(const BufferList& list, const std::string& outputFile, const std::vector& schemaPaths) diff --git a/six/modules/c++/six/source/Utilities.cpp b/six/modules/c++/six/source/Utilities.cpp index 2f59bf0a9..ff04dd92c 100644 --- a/six/modules/c++/six/source/Utilities.cpp +++ b/six/modules/c++/six/source/Utilities.cpp @@ -29,6 +29,8 @@ #include #include #include +#include + #include "six/Init.h" #include "six/Utilities.h" #include "six/XMLControl.h" @@ -711,10 +713,7 @@ std::unique_ptr six::parseDataFromString(const XMLControlRegistry& xmlReg, const std::vector& schemaPaths_, logging::Logger& log) { - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); - + const auto schemaPaths = sys::convertPaths(schemaPaths_); auto result = parseDataFromString(xmlReg, str::u8FromNative(xmlStr), dataType, &schemaPaths, &log); return std::unique_ptr(result.release()); } diff --git a/six/modules/c++/six/source/XMLControl.cpp b/six/modules/c++/six/source/XMLControl.cpp index 5f755caed..0b3157841 100644 --- a/six/modules/c++/six/source/XMLControl.cpp +++ b/six/modules/c++/six/source/XMLControl.cpp @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -99,15 +101,13 @@ std::vector XMLControl::loadSchemaPaths(const std::vector // a NULL pointer indicates that we don't want to validate against a schema if (pSchemaPaths != nullptr) { - std::vector paths; - std::transform(pSchemaPaths->begin(), pSchemaPaths->end(), std::back_inserter(paths), - [&](const std::filesystem::path& p) { return p.string(); }); + std::vector paths = sys::convertPaths(*pSchemaPaths); // If *pSchemaPaths is empty, this will use a default value. To avoid all validation against a schema, // pass NULL for pSchemaPaths. loadSchemaPaths(paths); - std::transform(paths.begin(), paths.end(), std::back_inserter(retval), [&](const std::string& s) { return s; }); + retval = sys::convertPaths(paths); } return retval; } @@ -182,7 +182,7 @@ static void log_any_errors_and_throw(const std::vector& schemaPaths, logging::Logger& log) + const std::vector& foundSchemas, logging::Logger& log) { xml::lite::Uri uri; rootElement.getUri(uri); @@ -195,10 +195,10 @@ static void validate_(const xml::lite::Element& rootElement, // Process schema paths one at a time. This will reduce the "noise" from XML validation failures // and could also make instantiating an xml::lite::ValidatorXerces faster. std::vector all_errors; - for (auto&& schemaPath : schemaPaths) + for (auto&& foundSchema : foundSchemas) { - const std::vector schemaPaths_{ schemaPath }; // use one path at a time - const xml::lite::ValidatorXerces validator(schemaPaths_, &log, true); // this can be expensive to create as all sub-directories might be traversed + const std::vector foundSchemas_{ { foundSchema } }; + const xml::lite::ValidatorXerces validator(foundSchemas_, &log); // validate against any specified schemas std::vector errors; @@ -215,14 +215,12 @@ static void validate_(const xml::lite::Element& rootElement, } // log any error found and throw - log_any_errors_and_throw(all_errors, schemaPaths, log); + log_any_errors_and_throw(all_errors, foundSchemas, log); } + static void validate_(const xml::lite::Document& doc, - const std::vector& paths_, logging::Logger& log) + const std::vector& foundSchemas, logging::Logger& log) { - // If the paths we have don't exist, throw - const auto paths = check_whether_paths_exist(paths_); - auto rootElement = doc.getRootElement(); if (rootElement->getUri().empty()) { @@ -230,8 +228,12 @@ static void validate_(const xml::lite::Document& doc, } // validate against any specified schemas - validate_(*rootElement, paths, log); + validate_(*rootElement, foundSchemas, log); } + +static std::vector findValidSchemaPaths(const std::vector&, logging::Logger*); +static std::vector findValidSchemaPaths(const std::vector*, logging::Logger*); + void XMLControl::validate(const xml::lite::Document* doc, const std::vector& schemaPaths, logging::Logger* log) @@ -241,45 +243,64 @@ void XMLControl::validate(const xml::lite::Document* doc, // Existing code in xml::lite requires that the Logger be non-NULL assert(log != nullptr); + // validate against any specified schemas + const auto foundSchemas = findValidSchemaPaths(schemaPaths, log); // If the paths we have don't exist, throw + validate_(*doc, foundSchemas, *log); +} +void XMLControl::validate(const xml::lite::Document& doc, + const std::vector* pSchemaPaths, + logging::Logger* log) +{ + // Existing code in xml::lite requires that the Logger be non-NULL + assert(log != nullptr); + + // validate against any specified schemas + const auto foundSchemas = findValidSchemaPaths(pSchemaPaths, log); + validate_(doc, foundSchemas, *log); +} + +static auto findValidSchemas(const std::vector& paths_) +{ + // If the paths we have don't exist, throw + const auto paths = check_whether_paths_exist(paths_); + return xml::lite::ValidatorXerces::loadSchemas(paths, true /*recursive*/); +} +static std::vector findValidSchemaPaths(const std::vector& schemaPaths, + logging::Logger* log) +{ // attempt to get the schema location from the // environment if nothing is specified std::vector paths(schemaPaths); - loadSchemaPaths(paths); + XMLControl::loadSchemaPaths(paths); if (paths.empty()) { - std::ostringstream oss; - oss << "Coudn't validate XML - no schemas paths provided " - << " and " << six::SCHEMA_PATH << " not set."; - - log->warn(oss); + if (log != nullptr) + { + std::ostringstream oss; + oss << "Coudn't validate XML - no schemas paths provided " + << " and " << six::SCHEMA_PATH << " not set."; + log->warn(oss); + } } - std::vector schemaPaths_; - std::transform(paths.begin(), paths.end(), std::back_inserter(schemaPaths_), [&](const std::string& s) { return s; }); - - // validate against any specified schemas - validate_(*doc, schemaPaths_, *log); + return findValidSchemas(sys::convertPaths(paths)); // If the paths we have don't exist, throw } -void XMLControl::validate(const xml::lite::Document& doc, - const std::vector* pSchemaPaths, +static std::vector findValidSchemaPaths(const std::vector* pSchemaPaths, logging::Logger* log) { - // Existing code in xml::lite requires that the Logger be non-NULL - assert(log != nullptr); - // attempt to get the schema location from the environment if nothing is specified - auto paths = loadSchemaPaths(pSchemaPaths); + auto paths = XMLControl::loadSchemaPaths(pSchemaPaths); if ((pSchemaPaths != nullptr) && paths.empty()) { - std::ostringstream oss; - oss << "Coudn't validate XML - no schemas paths provided " - << " and " << six::SCHEMA_PATH << " not set."; - - log->warn(oss); + if (log != nullptr) + { + std::ostringstream oss; + oss << "Coudn't validate XML - no schemas paths provided " + << " and " << six::SCHEMA_PATH << " not set."; + log->warn(oss); + } } - - // validate against any specified schemas - validate_(doc, paths, *log); + return findValidSchemas(paths); // If the paths we have don't exist, throw } std::string XMLControl::getDefaultURI(const Data& data) @@ -360,9 +381,7 @@ std::unique_ptr XMLControl::fromXMLImpl(const xml::lite::Document& doc) co Data* XMLControl::fromXML(const xml::lite::Document* doc, const std::vector& schemaPaths_) { - std::vector schemaPaths; - std::transform(schemaPaths_.begin(), schemaPaths_.end(), std::back_inserter(schemaPaths), - [](const std::string& s) { return s; }); + const auto schemaPaths = sys::convertPaths(schemaPaths_); assert(doc != nullptr); auto data = fromXML(*doc, &schemaPaths);