diff --git a/CMakeLists.txt b/CMakeLists.txt index 14248e6da6..1e40449b38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -548,192 +548,193 @@ set(SIMPLNX_GENERATED_HEADERS ${SIMPLNX_EXPORT_HEADER} ) -set(SIMPLNX_SRCS - ${SIMPLNX_SOURCE_DIR}/Common/AtomicFile.cpp - ${SIMPLNX_SOURCE_DIR}/Common/RgbColor.cpp - ${SIMPLNX_SOURCE_DIR}/Common/Range.cpp - ${SIMPLNX_SOURCE_DIR}/Common/Range2D.cpp - ${SIMPLNX_SOURCE_DIR}/Common/Range3D.cpp - - ${SIMPLNX_SOURCE_DIR}/Core/Application.cpp - ${SIMPLNX_SOURCE_DIR}/Core/Preferences.cpp - - ${SIMPLNX_SOURCE_DIR}/Filter/FilterHandle.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/FilterList.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/Messaging/AbstractDataStructureMessage.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Messaging/DataAddedMessage.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Messaging/DataRemovedMessage.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Messaging/DataRenamedMessage.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Messaging/DataReparentedMessage.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/Observers/AbstractDataStructureObserver.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/Generic/DataIOCollection.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/Generic/IDataIOManager.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/Generic/CoreDataIOManager.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/DataIOManager.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/DataStructureReader.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/DataStructureWriter.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/IDataIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/IOUtilities.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/IDataStoreIO.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/AttributeMatrixIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/BaseGroupIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/DataGroupIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/EdgeGeomIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/GridMontageIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/HexahedralGeomIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/ImageGeomIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/IGeometryIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/IGridGeometryIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/INodeGeom0dIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/INodeGeom1dIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/INodeGeom2dIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/INodeGeom3dIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/QuadGeomIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/RectGridGeomIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/StringArrayIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/TetrahedralGeomIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/TriangleGeomIO.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/IO/HDF5/VertexGeomIO.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/IGeometry.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/IGridGeometry.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/INodeGeometry0D.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/INodeGeometry1D.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/INodeGeometry2D.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/INodeGeometry3D.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/EdgeGeom.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/HexahedralGeom.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/ImageGeom.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/QuadGeom.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/RectGridGeom.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/TetrahedralGeom.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/TriangleGeom.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/VertexGeom.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Geometry/LinkedGeometryData.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/Montage/AbstractMontage.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Montage/AbstractTileIndex.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Montage/GridMontage.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Montage/GridTileIndex.cpp - - ${SIMPLNX_SOURCE_DIR}/DataStructure/AttributeMatrix.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/BaseGroup.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/DataGroup.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/DataMap.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/DataObject.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/DataPath.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/DataStructure.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/INeighborList.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/LinkedPath.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/Metadata.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/NeighborList.cpp - ${SIMPLNX_SOURCE_DIR}/DataStructure/StringArray.cpp - - ${SIMPLNX_SOURCE_DIR}/Filter/AbstractParameter.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Arguments.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/ConstDataParameter.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/DataParameter.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/IFilter.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/IParameter.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/MutableDataParameter.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Output.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Parameters.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/ValueParameter.cpp - - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CreateArrayAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CreateStringArrayAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CopyArrayInstanceAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CopyDataObjectAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CreateDataGroupAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CreateImageGeometryAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CreateRectGridGeometryAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CreateNeighborListAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/DeleteDataAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/ImportH5ObjectPathsAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/ImportObjectAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/MoveDataAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/RenameDataAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/UpdateImageGeomAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CreateAttributeMatrixAction.cpp - ${SIMPLNX_SOURCE_DIR}/Filter/Actions/CreateGridMontageAction.cpp - - ${SIMPLNX_SOURCE_DIR}/Parameters/util/ReadCSVData.cpp - ${SIMPLNX_SOURCE_DIR}/Parameters/util/DynamicTableInfo.cpp - - ${SIMPLNX_SOURCE_DIR}/Pipeline/AbstractPipelineNode.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Pipeline.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/PipelineFilter.cpp - - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/AbstractPipelineMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/FilterPreflightMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/NodeAddedMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/NodeMovedMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/NodeRemovedMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/NodeStatusMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/OutputRenamedMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/PipelineFilterMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/PipelineNodeMessage.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/PipelineNodeObserver.cpp - ${SIMPLNX_SOURCE_DIR}/Pipeline/Messaging/RenamedMessage.cpp - - ${SIMPLNX_SOURCE_DIR}/Plugin/AbstractPlugin.cpp - ${SIMPLNX_SOURCE_DIR}/Plugin/PluginLoader.cpp - - ${SIMPLNX_SOURCE_DIR}/Utilities/ArrayThreshold.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/FilePathGenerator.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/FilterUtilities.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/TooltipGenerator.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/TooltipRowItem.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/DataArrayUtilities.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/DataGroupUtilities.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/MemoryUtilities.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/IParallelAlgorithm.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/ParallelDataAlgorithm.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/ParallelData2DAlgorithm.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/ParallelData3DAlgorithm.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/ParallelTaskAlgorithm.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/SegmentFeatures.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/AlignSections.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/OStreamUtilities.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/GeometryHelpers.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/GeometryUtilities.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/ColorPresetsUtilities.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/ImageRotationUtilities.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Math/GeometryMath.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Math/MatrixMath.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/SampleSurfaceMesh.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/MontageUtilities.cpp - - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/DREAM3D/Dream3dIO.cpp - - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/H5.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/H5Support.cpp - - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/AttributeIO.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/DatasetIO.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/FileIO.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/GroupIO.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/ObjectIO.cpp - - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/AttributeReader.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/DatasetReader.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/FileReader.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/GroupReader.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/ObjectReader.cpp - - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/AttributeWriter.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/DatasetWriter.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/FileWriter.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/GroupWriter.cpp - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/ObjectWriter.cpp - - ${SIMPLNX_SOURCE_DIR}/Utilities/Parsing/Text/CsvParser.cpp +set(COMPLEX_SRCS + ${COMPLEX_SOURCE_DIR}/Common/AtomicFile.cpp + ${COMPLEX_SOURCE_DIR}/Common/RgbColor.cpp + ${COMPLEX_SOURCE_DIR}/Common/Range.cpp + ${COMPLEX_SOURCE_DIR}/Common/Range2D.cpp + ${COMPLEX_SOURCE_DIR}/Common/Range3D.cpp + + ${COMPLEX_SOURCE_DIR}/Core/Application.cpp + ${COMPLEX_SOURCE_DIR}/Core/Preferences.cpp + + ${COMPLEX_SOURCE_DIR}/Filter/FilterHandle.cpp + ${COMPLEX_SOURCE_DIR}/Filter/FilterList.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/Messaging/AbstractDataStructureMessage.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Messaging/DataAddedMessage.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Messaging/DataRemovedMessage.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Messaging/DataRenamedMessage.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Messaging/DataReparentedMessage.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/Observers/AbstractDataStructureObserver.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/Generic/DataIOCollection.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/Generic/IDataIOManager.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/Generic/CoreDataIOManager.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/DataIOManager.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/DataStructureReader.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/DataStructureWriter.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/IDataIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/IOUtilities.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/IDataStoreIO.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/AttributeMatrixIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/BaseGroupIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/DataGroupIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/EdgeGeomIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/GridMontageIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/HexahedralGeomIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/ImageGeomIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/IGeometryIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/IGridGeometryIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/INodeGeom0dIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/INodeGeom1dIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/INodeGeom2dIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/INodeGeom3dIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/QuadGeomIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/RectGridGeomIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/StringArrayIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/TetrahedralGeomIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/TriangleGeomIO.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/IO/HDF5/VertexGeomIO.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/IGeometry.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/IGridGeometry.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/INodeGeometry0D.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/INodeGeometry1D.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/INodeGeometry2D.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/INodeGeometry3D.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/EdgeGeom.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/HexahedralGeom.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/ImageGeom.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/QuadGeom.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/RectGridGeom.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/TetrahedralGeom.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/TriangleGeom.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/VertexGeom.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Geometry/LinkedGeometryData.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/Montage/AbstractMontage.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Montage/AbstractTileIndex.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Montage/GridMontage.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Montage/GridTileIndex.cpp + + ${COMPLEX_SOURCE_DIR}/DataStructure/AttributeMatrix.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/BaseGroup.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/DataGroup.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/DataMap.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/DataObject.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/DataPath.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/DataStructure.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/INeighborList.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/LinkedPath.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/Metadata.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/NeighborList.cpp + ${COMPLEX_SOURCE_DIR}/DataStructure/StringArray.cpp + + ${COMPLEX_SOURCE_DIR}/Filter/AbstractParameter.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Arguments.cpp + ${COMPLEX_SOURCE_DIR}/Filter/ConstDataParameter.cpp + ${COMPLEX_SOURCE_DIR}/Filter/DataParameter.cpp + ${COMPLEX_SOURCE_DIR}/Filter/IFilter.cpp + ${COMPLEX_SOURCE_DIR}/Filter/IParameter.cpp + ${COMPLEX_SOURCE_DIR}/Filter/MutableDataParameter.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Output.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Parameters.cpp + ${COMPLEX_SOURCE_DIR}/Filter/ValueParameter.cpp + + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CreateArrayAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CreateStringArrayAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CopyArrayInstanceAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CopyDataObjectAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CreateDataGroupAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CreateImageGeometryAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CreateRectGridGeometryAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CreateNeighborListAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/DeleteDataAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/ImportH5ObjectPathsAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/ImportObjectAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/MoveDataAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/RenameDataAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/UpdateImageGeomAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CreateAttributeMatrixAction.cpp + ${COMPLEX_SOURCE_DIR}/Filter/Actions/CreateGridMontageAction.cpp + + ${COMPLEX_SOURCE_DIR}/Parameters/util/ReadCSVData.cpp + ${COMPLEX_SOURCE_DIR}/Parameters/util/DynamicTableInfo.cpp + + ${COMPLEX_SOURCE_DIR}/Pipeline/AbstractPipelineNode.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Pipeline.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/PipelineFilter.cpp + + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/AbstractPipelineMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/FilterPreflightMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/NodeAddedMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/NodeMovedMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/NodeRemovedMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/NodeStatusMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/OutputRenamedMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/PipelineFilterMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/PipelineNodeMessage.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/PipelineNodeObserver.cpp + ${COMPLEX_SOURCE_DIR}/Pipeline/Messaging/RenamedMessage.cpp + + ${COMPLEX_SOURCE_DIR}/Plugin/AbstractPlugin.cpp + ${COMPLEX_SOURCE_DIR}/Plugin/PluginLoader.cpp + + ${COMPLEX_SOURCE_DIR}/Utilities/ArrayThreshold.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/FilePathGenerator.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/FileUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/FilterUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/TooltipGenerator.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/TooltipRowItem.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/DataArrayUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/DataGroupUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/MemoryUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/IParallelAlgorithm.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/ParallelDataAlgorithm.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/ParallelData2DAlgorithm.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/ParallelData3DAlgorithm.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/ParallelTaskAlgorithm.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/SegmentFeatures.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/AlignSections.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/OStreamUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/GeometryHelpers.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/GeometryUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/ColorPresetsUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/ImageRotationUtilities.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Math/GeometryMath.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Math/MatrixMath.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/SampleSurfaceMesh.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/MontageUtilities.cpp + + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/DREAM3D/Dream3dIO.cpp + + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/H5.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/H5Support.cpp + + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/AttributeIO.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/DatasetIO.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/FileIO.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/GroupIO.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/IO/ObjectIO.cpp + + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/AttributeReader.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/DatasetReader.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/FileReader.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/GroupReader.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Readers/ObjectReader.cpp + + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/AttributeWriter.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/DatasetWriter.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/FileWriter.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/GroupWriter.cpp + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/HDF5/Writers/ObjectWriter.cpp + + ${COMPLEX_SOURCE_DIR}/Utilities/Parsing/Text/CsvParser.cpp ) # Add Core FilterParameters diff --git a/src/complex/Common/AtomicFile.cpp b/src/complex/Common/AtomicFile.cpp index d8362ba30b..56baf83100 100644 --- a/src/complex/Common/AtomicFile.cpp +++ b/src/complex/Common/AtomicFile.cpp @@ -1,7 +1,7 @@ #include "AtomicFile.hpp" -#include "complex/Utilities/FilterUtilities.hpp" #include "complex/Utilities/FileUtilities.hpp" +#include "complex/Utilities/FilterUtilities.hpp" #include @@ -45,7 +45,7 @@ AtomicFile::AtomicFile(const std::string& filename, bool autoCommit) } // Validate write permissions - auto result = ValidateDirectoryWritePermission(m_FilePath, true); + auto result = FileUtilities::ValidateDirectoryWritePermission(m_FilePath, true); if(result.invalid()) { m_Result = MergeResults(m_Result, result); @@ -77,7 +77,7 @@ AtomicFile::AtomicFile(fs::path&& filepath, bool autoCommit) } // Validate write permissions - auto result = ValidateDirectoryWritePermission(m_FilePath, true); + auto result = FileUtilities::ValidateDirectoryWritePermission(m_FilePath, true); if(result.invalid()) { m_Result = MergeResults(m_Result, result); diff --git a/src/complex/Parameters/FileSystemPathParameter.cpp b/src/complex/Parameters/FileSystemPathParameter.cpp index 28790d8c27..80c041597a 100644 --- a/src/complex/Parameters/FileSystemPathParameter.cpp +++ b/src/complex/Parameters/FileSystemPathParameter.cpp @@ -2,26 +2,16 @@ #include "complex/Common/Any.hpp" #include "complex/Common/StringLiteral.hpp" -#include "complex/Utilities/StringUtilities.hpp" #include "complex/Utilities/FileUtilities.hpp" +#include "complex/Utilities/StringUtilities.hpp" #include #include -#include #include -#include #include -#ifdef _WIN32 -#include -#define FSPP_ACCESS_FUNC_NAME _access -#else -#include -#define FSPP_ACCESS_FUNC_NAME access -#endif - namespace fs = std::filesystem; using namespace complex; @@ -159,13 +149,13 @@ Result<> FileSystemPathParameter::validatePath(const ValueType& path) const switch(m_PathType) { case complex::FileSystemPathParameter::PathType::InputFile: - return ValidateInputFile(path); + return FileUtilities::ValidateInputFile(path); case complex::FileSystemPathParameter::PathType::InputDir: - return ValidateInputDir(path); + return FileUtilities::ValidateInputDir(path); case complex::FileSystemPathParameter::PathType::OutputFile: - return ValidateOutputFile(path); + return FileUtilities::ValidateOutputFile(path); case complex::FileSystemPathParameter::PathType::OutputDir: - return ValidateOutputDir(path); + return FileUtilities::ValidateOutputDir(path); } return {}; diff --git a/src/complex/Utilities/FileUtilities.cpp b/src/complex/Utilities/FileUtilities.cpp new file mode 100644 index 0000000000..e9133964a8 --- /dev/null +++ b/src/complex/Utilities/FileUtilities.cpp @@ -0,0 +1,260 @@ +/* ============================================================================ + * Copyright (c) 2020 BlueQuartz Software, LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the names of any of the BlueQuartz Software contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include "FileUtilities.hpp" + +#include + +#include +#include +#include + +#ifdef _WIN32 +#include +#define FSPP_ACCESS_FUNC_NAME _access +#else +#include +#define FSPP_ACCESS_FUNC_NAME access +#endif + +using namespace complex; + +#ifdef _WIN32 +constexpr int k_CheckWritable = 2; +#else +constexpr int k_CheckWritable = W_OK; +#endif + +constexpr int k_HasAccess = 0; + +//----------------------------------------------------------------------------- +bool FileUtilities::HasWriteAccess(const std::string& path) +{ + return FSPP_ACCESS_FUNC_NAME(path.c_str(), k_CheckWritable) == k_HasAccess; +} + +//----------------------------------------------------------------------------- +Result<> FileUtilities::ValidateInputFile(const fs::path& path) +{ + if(!fs::exists(path)) + { + return MakeErrorResult(-2, fmt::format("File System Path '{}' does not exist", path.string())); + } + + if(!fs::is_regular_file(path)) + { + return MakeErrorResult(-3, fmt::format("File System Path '{}' is not a file", path.string())); + } + return {}; +} + +//----------------------------------------------------------------------------- +Result<> FileUtilities::ValidateInputDir(const fs::path& path) +{ + if(!fs::exists(path)) + { + return MakeErrorResult(-4, fmt::format("File System Path '{}' does not exist", path.string())); + } + if(!fs::is_directory(path)) + { + return MakeErrorResult(-5, fmt::format("File System Path '{}' is not a file", path.string())); + } + return {}; +} + +//----------------------------------------------------------------------------- +Result<> FileUtilities::ValidateDirectoryWritePermission(const fs::path& path, bool isFile) +{ + if(path.empty()) + { + return MakeErrorResult(-16, "ValidateDirectoryWritePermission() error: given path was empty."); + } + + auto checkedPath = path; + if(isFile) + { + checkedPath = checkedPath.parent_path(); + } + // We now have the parent directory. Let us see if *any* part of the path exists + + // If the path is relative, then make it absolute + if(!checkedPath.is_absolute()) + { + try + { + checkedPath = fs::absolute(checkedPath); + } catch(const std::filesystem::filesystem_error& error) + { + return MakeErrorResult(-15, fmt::format("ValidateDirectoryWritePermission() threw an error: '{}'", error.what())); + } + } + + auto rootPath = checkedPath.root_path(); + + // The idea here is to start walking up from the deepest directory and hopefully + // find an existing directory. If we get to the top if the path and we are still + // empty then: + // On unix based systems not sure if it would happen. Even if the user set a path + // to another drive that didn't exist, at some point you hit the '/' and then you + // can try to create the directories. + // On Windows the user put in a bogus drive letter which is just a hard failure + // because we can't make up a new drive letter. + while(!fs::exists(checkedPath) && checkedPath != rootPath) + { + checkedPath = checkedPath.parent_path(); + } + + if(checkedPath.empty()) + { + return MakeErrorResult(-19, "ValidateDirectoryWritePermission() resolved path was empty"); + } + + if(!fs::exists(checkedPath)) + { + return MakeErrorResult(-11, fmt::format("ValidateDirectoryWritePermission() error: The drive does not exist on this system: '{}'", checkedPath.string())); + } + + // We should be at the top of the tree with an existing directory. + if(HasWriteAccess(checkedPath.string())) + { + return {}; + } + return MakeErrorResult(-8, fmt::format("User does not have write permissions to path '{}'", path.string())); +} + +//----------------------------------------------------------------------------- +Result<> FileUtilities::ValidateOutputFile(const fs::path& path) +{ + auto result = ValidateDirectoryWritePermission(path, true); + if(result.invalid()) + { + return result; + } + if(!fs::exists(path)) + { + return MakeWarningVoidResult(-6, fmt::format("File System Path '{}' does not exist. It will be created during execution.", path.string())); + } + return {}; +} + +//----------------------------------------------------------------------------- +Result<> FileUtilities::ValidateOutputDir(const fs::path& path) +{ + auto result = ValidateDirectoryWritePermission(path, false); + if(result.invalid()) + { + return result; + } + if(!fs::exists(path)) + { + return MakeWarningVoidResult(-7, fmt::format("File System Path '{}' does not exist. It will be created during execution.", path.string())); + } + return {}; +} + +//----------------------------------------------------------------------------- +Result<> FileUtilities::ValidateCSVFile(const std::string& filePath) +{ + constexpr int64_t bufferSize = 2048; + + auto absPath = fs::absolute(filePath); + + if(!fs::exists({absPath})) + { + return MakeErrorResult(-300, fmt::format("File does not exist: {}", absPath.string())); + } + + // Obtain the file size + const size_t fileSize = fs::file_size(absPath); + + // Open the file + std::ifstream in(absPath.c_str(), std::ios_base::binary); + if(!in.is_open()) + { + return MakeErrorResult(-301, fmt::format("Could not open file for reading: {}", absPath.string())); + } + + size_t actualSize = bufferSize; + if(fileSize <= bufferSize) + { + actualSize = fileSize; + } + + // Allocate the buffer + std::vector buffer(actualSize, 0); + + // Copy the file contents into the buffer + try + { + in.read(buffer.data(), actualSize); + } catch(const std::exception& e) + { + return MakeErrorResult(-302, fmt::format("There was an error reading the data from file: {}. Exception: {}", absPath.string(), e.what())); + } + + // Check the buffer for invalid characters, tab characters, new-line characters, and carriage return characters + bool hasNewLines = false; + bool hasCarriageReturns = false; + bool hasTabs = false; + // If the first line of the file is > 2048 then this will fail! (MJ) + for(size_t i = 0; i < actualSize; i++) + { + const char currentChar = buffer[i]; + + if(currentChar < 32 && currentChar != 9 && currentChar != 10 && currentChar != 13) + { + // This is an unprintable character + return MakeErrorResult(-303, fmt::format("Unprintable characters have been detected in file: {}. Please import a different file.", absPath.string())); + } + if(currentChar == 9) + { + hasTabs = true; + } + else if(currentChar == 10) + { + hasNewLines = true; + } + else if(currentChar == 13) + { + hasCarriageReturns = true; + } + } + + if(!hasNewLines && !hasCarriageReturns && !hasTabs) + { + // This might be a binary file + return MakeErrorResult(-304, fmt::format("The file \"{}\" might be a binary file, because line-feed, tab, or carriage return characters have not been detected. Using this file may crash the " + "program or cause unexpected results. Please import a different file.", + absPath.string())); + } + + return {}; +} diff --git a/src/complex/Utilities/FileUtilities.hpp b/src/complex/Utilities/FileUtilities.hpp index 8f8e613a45..57de89d732 100644 --- a/src/complex/Utilities/FileUtilities.hpp +++ b/src/complex/Utilities/FileUtilities.hpp @@ -31,229 +31,32 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #pragma once -#include -#include -#include -#include - #include "complex/Common/Result.hpp" +#include + namespace fs = std::filesystem; -namespace complex -{ -namespace FileUtilities +namespace complex::FileUtilities { -#ifdef _WIN32 -constexpr int k_CheckWritable = 2; -#else -constexpr int k_CheckWritable = W_OK; -#endif - -constexpr StringLiteral k_PathKey = "path"; -constexpr int k_HasAccess = 0; - //----------------------------------------------------------------------------- -bool HasWriteAccess(const std::string& path) -{ - return FSPP_ACCESS_FUNC_NAME(path.c_str(), k_CheckWritable) == k_HasAccess; -} +bool HasWriteAccess(const std::string& path); //----------------------------------------------------------------------------- -Result<> ValidateInputFile(const FileSystemPathParameter::ValueType& path) -{ - if(!fs::exists(path)) - { - return MakeErrorResult(-2, fmt::format("File System Path '{}' does not exist", path.string())); - } +Result<> ValidateInputFile(const fs::path& path); - if(!fs::is_regular_file(path)) - { - return MakeErrorResult(-3, fmt::format("File System Path '{}' is not a file", path.string())); - } - return {}; -} - -//----------------------------------------------------------------------------- -Result<> ValidateInputDir(const FileSystemPathParameter::ValueType& path) -{ - if(!fs::exists(path)) - { - return MakeErrorResult(-4, fmt::format("File System Path '{}' does not exist", path.string())); - } - if(!fs::is_directory(path)) - { - return MakeErrorResult(-5, fmt::format("File System Path '{}' is not a file", path.string())); - } - return {}; -} //----------------------------------------------------------------------------- -Result<> ValidateDirectoryWritePermission(const FileSystemPathParameter::ValueType& path, bool isFile) -{ - if(path.empty()) - { - return MakeErrorResult(-16, "ValidateDirectoryWritePermission() error: given path was empty."); - } - - auto checkedPath = path; - if(isFile) - { - checkedPath = checkedPath.parent_path(); - } - // We now have the parent directory. Let us see if *any* part of the path exists - - // If the path is relative, then make it absolute - if(!checkedPath.is_absolute()) - { - try - { - checkedPath = fs::absolute(checkedPath); - } catch(const std::filesystem::filesystem_error& error) - { - return MakeErrorResult(-15, fmt::format("ValidateDirectoryWritePermission() threw an error: '{}'", error.what())); - } - } - - auto rootPath = checkedPath.root_path(); - - // The idea here is to start walking up from the deepest directory and hopefully - // find an existing directory. If we get to the top if the path and we are still - // empty then: - // On unix based systems not sure if it would happen. Even if the user set a path - // to another drive that didn't exist, at some point you hit the '/' and then you - // can try to create the directories. - // On Windows the user put in a bogus drive letter which is just a hard failure - // because we can't make up a new drive letter. - while(!fs::exists(checkedPath) && checkedPath != rootPath) - { - checkedPath = checkedPath.parent_path(); - } - - if(checkedPath.empty()) - { - return MakeErrorResult(-19, "ValidateDirectoryWritePermission() resolved path was empty"); - } - - if(!fs::exists(checkedPath)) - { - return MakeErrorResult(-11, fmt::format("ValidateDirectoryWritePermission() error: The drive does not exist on this system: '{}'", checkedPath.string())); - } - - // We should be at the top of the tree with an existing directory. - if(HasWriteAccess(checkedPath.string())) - { - return {}; - } - return MakeErrorResult(-8, fmt::format("User does not have write permissions to path '{}'", path.string())); -} +Result<> ValidateInputDir(const fs::path& path); //----------------------------------------------------------------------------- -Result<> ValidateOutputFile(const FileSystemPathParameter::ValueType& path) -{ - auto result = ValidateDirectoryWritePermission(path, true); - if(result.invalid()) - { - return result; - } - if(!fs::exists(path)) - { - return MakeWarningVoidResult(-6, fmt::format("File System Path '{}' does not exist. It will be created during execution.", path.string())); - } - return {}; -} +Result<> ValidateDirectoryWritePermission(const fs::path& path, bool isFile); //----------------------------------------------------------------------------- -Result<> ValidateOutputDir(const FileSystemPathParameter::ValueType& path) -{ - auto result = ValidateDirectoryWritePermission(path, false); - if(result.invalid()) - { - return result; - } - if(!fs::exists(path)) - { - return MakeWarningVoidResult(-7, fmt::format("File System Path '{}' does not exist. It will be created during execution.", path.string())); - } - return {}; -} +Result<> ValidateOutputFile(const fs::path& path); //----------------------------------------------------------------------------- -Result<> ValidateCSVFile(const std::string& filePath) -{ - constexpr int64_t bufferSize = 2048; - - auto absPath = fs::absolute(filePath); - - if(!fs::exists({absPath})) - { - return MakeErrorResult(-300, fmt::format("File does not exist: {}", absPath.string())); - } - - // Obtain the file size - const size_t fileSize = fs::file_size(absPath); +Result<> ValidateOutputDir(const fs::path& path); - // Open the file - std::ifstream in(absPath.c_str(), std::ios_base::binary); - if(!in.is_open()) - { - return MakeErrorResult(-301, fmt::format("Could not open file for reading: {}", absPath.string())); - } - - size_t actualSize = bufferSize; - if(fileSize <= bufferSize) - { - actualSize = fileSize; - } - - // Allocate the buffer - std::vector buffer(actualSize, 0); - - // Copy the file contents into the buffer - try - { - in.read(buffer.data(), actualSize); - } catch(const std::exception& e) - { - return MakeErrorResult(-302, fmt::format("There was an error reading the data from file: {}. Exception: {}", absPath.string(), e.what())); - } - - // Check the buffer for invalid characters, tab characters, new-line characters, and carriage return characters - bool hasNewLines = false; - bool hasCarriageReturns = false; - bool hasTabs = false; - // If the first line of the file is > 2048 then this will fail! (MJ) - for(size_t i = 0; i < actualSize; i++) - { - const char currentChar = buffer[i]; - - if(currentChar < 32 && currentChar != 9 && currentChar != 10 && currentChar != 13) - { - // This is an unprintable character - return MakeErrorResult(-303, fmt::format("Unprintable characters have been detected in file: {}. Please import a different file.", absPath.string())); - } - if(currentChar == 9) - { - hasTabs = true; - } - else if(currentChar == 10) - { - hasNewLines = true; - } - else if(currentChar == 13) - { - hasCarriageReturns = true; - } - } - - if(!hasNewLines && !hasCarriageReturns && !hasTabs) - { - // This might be a binary file - return MakeErrorResult(-304, fmt::format("The file \"{}\" might be a binary file, because line-feed, tab, or carriage return characters have not been detected. Using this file may crash the " - "program or cause unexpected results. Please import a different file.", - absPath.string())); - } - - return {}; -} -} // namespace FileUtilities -} // namespace complex +//----------------------------------------------------------------------------- +Result<> ValidateCSVFile(const std::string& filePath); +} // namespace complex::FileUtilities