Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: gdal "raster/vector pipeline" subcommand 5 : * Author: Even Rouault <even dot rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #ifndef GDALALG_ABSTRACT_PIPELINE_INCLUDED 14 : #define GDALALG_ABSTRACT_PIPELINE_INCLUDED 15 : 16 : //! @cond Doxygen_Suppress 17 : 18 : #include "cpl_json.h" 19 : 20 : #include "gdalalgorithm.h" 21 : #include "gdalpipelinestepalgorithm.h" 22 : #include "gdal_priv.h" 23 : 24 : #include <algorithm> 25 : 26 : // This is an easter egg to pay tribute to PROJ pipeline syntax 27 : // We accept "gdal vector +gdal=pipeline +step +gdal=read +input=in.tif +step +gdal=reproject +output-crs=EPSG:32632 +step +gdal=write +output=out.tif +overwrite" 28 : // as an alternative to (recommended): 29 : // "gdal vector pipeline ! read in.tif ! reproject--output-crs=EPSG:32632 ! write out.tif --overwrite" 30 : #ifndef GDAL_PIPELINE_PROJ_NOSTALGIA 31 : #define GDAL_PIPELINE_PROJ_NOSTALGIA 32 : #endif 33 : 34 : /************************************************************************/ 35 : /* GDALAbstractPipelineAlgorithm */ 36 : /************************************************************************/ 37 : 38 : class GDALAbstractPipelineAlgorithm CPL_NON_FINAL 39 : : public GDALPipelineStepAlgorithm 40 : { 41 : public: 42 : std::vector<std::string> GetAutoComplete(std::vector<std::string> &args, 43 : bool lastWordIsComplete, 44 : bool /* showAllOptions*/) override; 45 : 46 : bool Finalize() override; 47 : 48 : std::string GetUsageAsJSON() const override; 49 : 50 : bool 51 : ParseCommandLineArguments(const std::vector<std::string> &args) override; 52 : 53 2 : bool HasSteps() const 54 : { 55 2 : return !m_steps.empty(); 56 : } 57 : 58 : static constexpr const char *OPEN_NESTED_PIPELINE = "["; 59 : static constexpr const char *CLOSE_NESTED_PIPELINE = "]"; 60 : 61 : static constexpr const char *RASTER_SUFFIX = "-raster"; 62 : static constexpr const char *VECTOR_SUFFIX = "-vector"; 63 : 64 : protected: 65 : friend class GDALTeeStepAlgorithmAbstract; 66 : 67 683 : GDALAbstractPipelineAlgorithm( 68 : const std::string &name, const std::string &description, 69 : const std::string &helpURL, 70 : const GDALPipelineStepAlgorithm::ConstructorOptions &options) 71 683 : : GDALPipelineStepAlgorithm( 72 : name, description, helpURL, 73 683 : ConstructorOptions(options).SetAutoOpenInputDatasets(false)) 74 : { 75 683 : } 76 : 77 : std::string m_pipeline{}; 78 : 79 : virtual GDALAlgorithmRegistry &GetStepRegistry() = 0; 80 : 81 : virtual const GDALAlgorithmRegistry &GetStepRegistry() const = 0; 82 : 83 : std::unique_ptr<GDALPipelineStepAlgorithm> 84 : GetStepAlg(const std::string &name) const; 85 : 86 : bool HasOutputString() const override; 87 : 88 : static bool IsReadSpecificArgument(const char *pszArgName); 89 : static bool IsWriteSpecificArgument(const char *pszArgName); 90 : 91 : private: 92 : friend class GDALPipelineAlgorithm; 93 : friend class GDALRasterPipelineAlgorithm; 94 : friend class GDALVectorPipelineAlgorithm; 95 : 96 : std::vector<std::unique_ptr<GDALPipelineStepAlgorithm>> m_steps{}; 97 : 98 : std::unique_ptr<GDALPipelineStepAlgorithm> m_stepOnWhichHelpIsRequested{}; 99 : 100 : bool m_bInnerPipeline = false; 101 : bool m_bExpectReadStep = true; 102 : int m_nFirstStepWithUnknownInputType = -1; 103 : 104 : enum class StepConstraint 105 : { 106 : MUST_BE, 107 : CAN_BE, 108 : CAN_NOT_BE 109 : }; 110 : 111 : StepConstraint m_eLastStepAsWrite = StepConstraint::CAN_BE; 112 : 113 : std::vector<std::unique_ptr<GDALAbstractPipelineAlgorithm>> 114 : m_apoNestedPipelines{}; 115 : 116 : // More would lead to unreadable pipelines 117 : static constexpr int MAX_NESTING_LEVEL = 3; 118 : 119 : bool 120 : CheckFirstAndLastStep(const std::vector<GDALPipelineStepAlgorithm *> &steps, 121 : bool forAutoComplete) const; 122 : 123 : static int GetInputDatasetType(const GDALPipelineStepAlgorithm *alg); 124 : 125 : bool CopyStepAlgorithmFromAnother(GDALPipelineStepAlgorithm *dst, 126 : const GDALPipelineStepAlgorithm *src, 127 : bool maybeWriteStep) const; 128 : 129 : bool ParseCommandLineArguments( 130 : const std::vector<std::string> &args, bool forAutoComplete, 131 : std::vector<std::string> *pCurArgsForAutocomplete); 132 : 133 : bool RunStep(GDALPipelineStepRunContext &ctxt) override; 134 : enum class RunStepState 135 : { 136 : PROCESSED, 137 : GO_ON, 138 : ERROR, 139 : }; 140 : RunStepState 141 : RunStepDealWithMultiProcessing(GDALPipelineStepRunContext &ctxt); 142 : RunStepState RunStepDealWithGDALGJson(); 143 : bool RunStepDealWithStepUnknownInputType(size_t i, int nCurDatasetType); 144 : bool CheckStepHasNoInputDatasetAlreadySet(size_t i, GDALDataset *poCurDS); 145 : 146 : std::string 147 : BuildNestedPipeline(GDALPipelineStepAlgorithm *curAlg, 148 : std::vector<std::string> &nestedPipelineArgs, 149 : bool forAutoComplete, 150 : std::vector<std::string> *pCurArgsForAutocomplete); 151 : 152 : bool SaveGDALGIntoFileOrString(const std::string &outFilename, 153 : std::string &outString) const; 154 : 155 : virtual std::unique_ptr<GDALAbstractPipelineAlgorithm> 156 : CreateNestedPipeline() const = 0; 157 : }; 158 : 159 : //! @endcond 160 : 161 : #endif