13#ifndef GDALALG_TEE_INCLUDED
14#define GDALALG_TEE_INCLUDED
16#include "gdalalg_abstract_pipeline.h"
17#include "gdalalg_raster_pipeline.h"
18#include "gdalalg_vector_pipeline.h"
33class GDALTeeStepAlgorithmAbstract
36 static constexpr const char *NAME =
"tee";
37 static constexpr const char *DESCRIPTION =
38 "Pipes the input into the output stream and side nested pipelines.";
39 static constexpr const char *HELP_URL =
"/programs/gdal_pipeline.html";
41 virtual ~GDALTeeStepAlgorithmAbstract();
43 void CopyFilenameBindingsFrom(
const GDALTeeStepAlgorithmAbstract *other);
45 bool BindFilename(
const std::string &filename,
46 GDALAbstractPipelineAlgorithm *alg,
47 const std::vector<std::string> &args);
49 bool HasOutputString()
const;
52 GDALTeeStepAlgorithmAbstract() =
default;
54 std::vector<GDALArgDatasetValue> m_pipelines{};
55 std::map<std::string, std::pair<GDALAbstractPipelineAlgorithm *,
56 std::vector<std::string>>>
64template <
class BaseStepAlgorithm,
int nDatasetType>
65class GDALTeeStepAlgorithmBase
66 :
public BaseStepAlgorithm,
67 public GDALTeeStepAlgorithmAbstract
70 bool IsNativelyStreamingCompatible()
const override
75 bool CanBeMiddleStep()
const override
80 bool CanBeLastStep()
const override
85 bool GeneratesFilesFromUserInput()
const override
90 bool HasOutputString()
const override
92 return GDALTeeStepAlgorithmAbstract::HasOutputString();
96 explicit GDALTeeStepAlgorithmBase();
98 int GetInputType()
const override
103 int GetOutputType()
const override
109 bool RunStep(GDALPipelineStepRunContext &ctxt)
override;
116template <
class BaseStepAlgorithm,
int nDatasetType>
117GDALTeeStepAlgorithmBase<BaseStepAlgorithm,
118 nDatasetType>::GDALTeeStepAlgorithmBase()
119 : BaseStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
120 GDALPipelineStepAlgorithm::ConstructorOptions()
121 .SetAddDefaultArguments(false))
123 this->AddArg(
"tee-pipeline", 0, _(
"Nested pipeline"), &m_pipelines,
127 .SetMaxCount(INT_MAX)
128 .SetMetaVar(
"PIPELINE")
129 .SetPackedValuesAllowed(
false)
130 .SetDatasetInputFlags(GADV_NAME)
131 .SetDatasetOutputFlags(GADV_NAME)
132 .SetAutoOpenDataset(
false);
139template <
class BaseStepAlgorithm,
int nDatasetType>
140bool GDALTeeStepAlgorithmBase<BaseStepAlgorithm, nDatasetType>::RunStep(
141 GDALPipelineStepRunContext &ctxt)
143 auto pfnProgress = ctxt.m_pfnProgress;
144 auto pProgressData = ctxt.m_pProgressData;
146 auto poSrcDS = this->m_inputDataset[0].GetDatasetRef();
148 CPLAssert(this->m_outputDataset.GetName().empty());
149 CPLAssert(!this->m_outputDataset.GetDatasetRef());
152 std::vector<std::string> aosAttributeFilters;
153 std::vector<std::unique_ptr<OGRGeometry>> apoSpatialFilters;
154 for (
auto *poLayer : poSrcDS->GetLayers())
156 const char *pszQueryString = poLayer->GetAttrQueryString();
157 aosAttributeFilters.push_back(pszQueryString ? pszQueryString :
"");
158 const auto poSpatFilter = poLayer->GetSpatialFilter();
159 apoSpatialFilters.push_back(std::unique_ptr<OGRGeometry>(
160 poSpatFilter ? poSpatFilter->clone() :
nullptr));
164 for (
const auto &dataset : m_pipelines)
166 const auto oIter = m_oMapNameToAlg.find(dataset.GetName());
167 if (oIter == m_oMapNameToAlg.end())
170 "'%s' is not a valid nested pipeline",
171 dataset.GetName().c_str());
174 auto subAlg = oIter->second.first;
175 const auto &subAlgArgs = oIter->second.second;
177 auto &subAlgInputDatasets = subAlg->GetInputDatasets();
179 subAlgInputDatasets.resize(1);
180 subAlgInputDatasets[0].Set(poSrcDS);
182 std::unique_ptr<void,
decltype(&GDALDestroyScaledProgress)>
184 GDALCreateScaledProgress(
185 double(iTeeDS) /
static_cast<int>(m_pipelines.size()),
186 double(iTeeDS + 1) /
static_cast<int>(m_pipelines.size()),
187 pfnProgress, pProgressData),
188 GDALDestroyScaledProgress);
190 if (this->IsCalledFromCommandLine())
191 subAlg->SetCalledFromCommandLine();
193 bool ret = (subAlg->ParseCommandLineArguments(subAlgArgs) &&
194 subAlg->Run(pScaledProgress ? GDALScaledProgress :
nullptr,
195 pScaledProgress.get()) &&
198 this->m_output += subAlg->GetOutputString();
201 for (
int i = 0; i < static_cast<int>(aosAttributeFilters.size()); ++i)
203 auto poLayer = poSrcDS->GetLayer(i);
204 poLayer->SetAttributeFilter(aosAttributeFilters[i].empty()
205 ? aosAttributeFilters[i].c_str()
207 poLayer->SetSpatialFilter(apoSpatialFilters[i].get());
208 poLayer->ResetReading();
217 this->m_outputDataset.Set(poSrcDS);
225class GDALTeeRasterAlgorithm final
226 :
public GDALTeeStepAlgorithmBase<GDALRasterPipelineStepAlgorithm,
230 GDALTeeRasterAlgorithm() =
default;
232 ~GDALTeeRasterAlgorithm()
override;
239class GDALTeeVectorAlgorithm final
240 :
public GDALTeeStepAlgorithmBase<GDALVectorPipelineStepAlgorithm,
244 GDALTeeVectorAlgorithm() =
default;
246 ~GDALTeeVectorAlgorithm()
override;
#define CPLAssert(expr)
Assert on an expression.
Definition cpl_error.h:330
#define CPLE_AppDefined
Application defined error.
Definition cpl_error.h:85
Classes related to registration of format support, and opening datasets.