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 : static constexpr const char *MULTIDIM_SUFFIX = "-multidim"; 64 : 65 : protected: 66 : friend class GDALTeeStepAlgorithmAbstract; 67 : 68 740 : GDALAbstractPipelineAlgorithm( 69 : const std::string &name, const std::string &description, 70 : const std::string &helpURL, 71 : const GDALPipelineStepAlgorithm::ConstructorOptions &options) 72 740 : : GDALPipelineStepAlgorithm( 73 : name, description, helpURL, 74 740 : ConstructorOptions(options).SetAutoOpenInputDatasets(false)) 75 : { 76 740 : } 77 : 78 : std::string m_pipeline{}; 79 : 80 : virtual GDALAlgorithmRegistry &GetStepRegistry() = 0; 81 : 82 : virtual const GDALAlgorithmRegistry &GetStepRegistry() const = 0; 83 : 84 : std::unique_ptr<GDALPipelineStepAlgorithm> 85 : GetStepAlg(const std::string &name) const; 86 : 87 : bool HasOutputString() const override; 88 : 89 : static bool IsReadSpecificArgument(const char *pszArgName); 90 : static bool IsWriteSpecificArgument(const char *pszArgName); 91 : 92 : private: 93 : friend class GDALPipelineAlgorithm; 94 : friend class GDALRasterPipelineAlgorithm; 95 : friend class GDALVectorPipelineAlgorithm; 96 : friend class GDALMdimPipelineAlgorithm; 97 : 98 : std::vector<std::unique_ptr<GDALPipelineStepAlgorithm>> m_steps{}; 99 : 100 : std::unique_ptr<GDALPipelineStepAlgorithm> m_stepOnWhichHelpIsRequested{}; 101 : 102 : bool m_bInnerPipeline = false; 103 : bool m_bExpectReadStep = true; 104 : int m_nFirstStepWithUnknownInputType = -1; 105 : 106 : enum class StepConstraint 107 : { 108 : MUST_BE, 109 : CAN_BE, 110 : CAN_NOT_BE 111 : }; 112 : 113 : StepConstraint m_eLastStepAsWrite = StepConstraint::CAN_BE; 114 : 115 : std::vector<std::unique_ptr<GDALAbstractPipelineAlgorithm>> 116 : m_apoNestedPipelines{}; 117 : 118 : // More would lead to unreadable pipelines 119 : static constexpr int MAX_NESTING_LEVEL = 3; 120 : 121 : bool 122 : CheckFirstAndLastStep(const std::vector<GDALPipelineStepAlgorithm *> &steps, 123 : bool forAutoComplete) const; 124 : 125 : static int GetInputDatasetType(const GDALPipelineStepAlgorithm *alg); 126 : 127 : bool CopyStepAlgorithmFromAnother(GDALPipelineStepAlgorithm *dst, 128 : const GDALPipelineStepAlgorithm *src, 129 : bool maybeWriteStep) const; 130 : 131 : bool ParseCommandLineArguments( 132 : const std::vector<std::string> &args, bool forAutoComplete, 133 : std::vector<std::string> *pCurArgsForAutocomplete); 134 : 135 : bool RunStep(GDALPipelineStepRunContext &ctxt) override; 136 : enum class RunStepState 137 : { 138 : PROCESSED, 139 : GO_ON, 140 : ERROR, 141 : }; 142 : RunStepState 143 : RunStepDealWithMultiProcessing(GDALPipelineStepRunContext &ctxt); 144 : RunStepState RunStepDealWithGDALGJson(); 145 : bool RunStepDealWithStepUnknownInputType(size_t i, int nCurDatasetType); 146 : bool CheckStepHasNoInputDatasetAlreadySet(size_t i, GDALDataset *poCurDS); 147 : 148 : std::string 149 : BuildNestedPipeline(GDALPipelineStepAlgorithm *curAlg, 150 : std::vector<std::string> &nestedPipelineArgs, 151 : bool forAutoComplete, 152 : std::vector<std::string> *pCurArgsForAutocomplete); 153 : 154 : bool SaveGDALGIntoFileOrString(const std::string &outFilename, 155 : std::string &outString) const; 156 : 157 : virtual std::unique_ptr<GDALAbstractPipelineAlgorithm> 158 : CreateNestedPipeline() const = 0; 159 : }; 160 : 161 : //! @endcond 162 : 163 : #endif