3987 lines
135 KiB
C++
3987 lines
135 KiB
C++
/******************************************************************************
|
|
*
|
|
* Project: GDAL
|
|
* Purpose: GDALAlgorithm class
|
|
* Author: Even Rouault <even dot rouault at spatialys.com>
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
****************************************************************************/
|
|
|
|
#include "cpl_port.h"
|
|
#include "cpl_conv.h"
|
|
#include "cpl_error.h"
|
|
#include "cpl_json.h"
|
|
|
|
#include "gdalalgorithm.h"
|
|
#include "gdal_priv.h"
|
|
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <cerrno>
|
|
#include <cstdlib>
|
|
#include <map>
|
|
|
|
#ifndef _
|
|
#define _(x) (x)
|
|
#endif
|
|
|
|
//! @cond Doxygen_Suppress
|
|
struct GDALAlgorithmArgHS
|
|
{
|
|
GDALAlgorithmArg *ptr = nullptr;
|
|
|
|
explicit GDALAlgorithmArgHS(GDALAlgorithmArg *arg) : ptr(arg)
|
|
{
|
|
}
|
|
};
|
|
|
|
//! @endcond
|
|
|
|
//! @cond Doxygen_Suppress
|
|
struct GDALArgDatasetValueHS
|
|
{
|
|
GDALArgDatasetValue val{};
|
|
GDALArgDatasetValue *ptr = nullptr;
|
|
|
|
GDALArgDatasetValueHS() : ptr(&val)
|
|
{
|
|
}
|
|
|
|
explicit GDALArgDatasetValueHS(GDALArgDatasetValue *arg) : ptr(arg)
|
|
{
|
|
}
|
|
|
|
GDALArgDatasetValueHS(const GDALArgDatasetValueHS &) = delete;
|
|
GDALArgDatasetValueHS &operator=(const GDALArgDatasetValueHS &) = delete;
|
|
};
|
|
|
|
//! @endcond
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgTypeIsList() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithmArgTypeIsList(GDALAlgorithmArgType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case GAAT_BOOLEAN:
|
|
case GAAT_STRING:
|
|
case GAAT_INTEGER:
|
|
case GAAT_REAL:
|
|
case GAAT_DATASET:
|
|
break;
|
|
|
|
case GAAT_STRING_LIST:
|
|
case GAAT_INTEGER_LIST:
|
|
case GAAT_REAL_LIST:
|
|
case GAAT_DATASET_LIST:
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgTypeName() */
|
|
/************************************************************************/
|
|
|
|
const char *GDALAlgorithmArgTypeName(GDALAlgorithmArgType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case GAAT_BOOLEAN:
|
|
break;
|
|
case GAAT_STRING:
|
|
return "string";
|
|
case GAAT_INTEGER:
|
|
return "integer";
|
|
case GAAT_REAL:
|
|
return "real";
|
|
case GAAT_DATASET:
|
|
return "dataset";
|
|
case GAAT_STRING_LIST:
|
|
return "string_list";
|
|
case GAAT_INTEGER_LIST:
|
|
return "integer_list";
|
|
case GAAT_REAL_LIST:
|
|
return "real_list";
|
|
case GAAT_DATASET_LIST:
|
|
return "dataset_list";
|
|
}
|
|
|
|
return "boolean";
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueTypeName() */
|
|
/************************************************************************/
|
|
|
|
std::string GDALArgDatasetValueTypeName(GDALArgDatasetValueType type)
|
|
{
|
|
std::string ret;
|
|
if ((type & GDAL_OF_RASTER) != 0)
|
|
ret = "raster";
|
|
if ((type & GDAL_OF_VECTOR) != 0)
|
|
{
|
|
if (!ret.empty())
|
|
{
|
|
if ((type & GDAL_OF_MULTIDIM_RASTER) != 0)
|
|
ret += ", ";
|
|
else
|
|
ret += " or ";
|
|
}
|
|
ret += "vector";
|
|
}
|
|
if ((type & GDAL_OF_MULTIDIM_RASTER) != 0)
|
|
{
|
|
if (!ret.empty())
|
|
{
|
|
ret += " or ";
|
|
}
|
|
ret += "multidimensional raster";
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgDecl() */
|
|
/************************************************************************/
|
|
|
|
// cppcheck-suppress uninitMemberVar
|
|
GDALAlgorithmArgDecl::GDALAlgorithmArgDecl(const std::string &longName,
|
|
char chShortName,
|
|
const std::string &description,
|
|
GDALAlgorithmArgType type)
|
|
: m_longName(longName),
|
|
m_shortName(chShortName ? std::string(&chShortName, 1) : std::string()),
|
|
m_description(description), m_type(type),
|
|
m_metaVar(CPLString(m_type == GAAT_BOOLEAN ? std::string() : longName)
|
|
.toupper()),
|
|
m_maxCount(GDALAlgorithmArgTypeIsList(type) ? UNBOUNDED : 1)
|
|
{
|
|
if (m_type == GAAT_BOOLEAN)
|
|
{
|
|
m_defaultValue = false;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgDecl::SetMinCount() */
|
|
/************************************************************************/
|
|
|
|
GDALAlgorithmArgDecl &GDALAlgorithmArgDecl::SetMinCount(int count)
|
|
{
|
|
if (!GDALAlgorithmArgTypeIsList(m_type))
|
|
{
|
|
CPLError(CE_Failure, CPLE_NotSupported,
|
|
"SetMinCount() illegal on scalar argument '%s'",
|
|
GetName().c_str());
|
|
}
|
|
else
|
|
{
|
|
m_minCount = count;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgDecl::SetMaxCount() */
|
|
/************************************************************************/
|
|
|
|
GDALAlgorithmArgDecl &GDALAlgorithmArgDecl::SetMaxCount(int count)
|
|
{
|
|
if (!GDALAlgorithmArgTypeIsList(m_type))
|
|
{
|
|
CPLError(CE_Failure, CPLE_NotSupported,
|
|
"SetMaxCount() illegal on scalar argument '%s'",
|
|
GetName().c_str());
|
|
}
|
|
else
|
|
{
|
|
m_maxCount = count;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArg::Set() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithmArg::Set(bool value)
|
|
{
|
|
if (m_decl.GetType() != GAAT_BOOLEAN)
|
|
{
|
|
CPLError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(bool) on argument '%s' of type %s is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
return SetInternal(value);
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(const std::string &value)
|
|
{
|
|
if (m_decl.GetType() != GAAT_STRING)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(std::string) on argument '%s' of type %s is not "
|
|
"supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
|
|
std::string newValue(value);
|
|
if (m_decl.IsReadFromFileAtSyntaxAllowed() && !value.empty() &&
|
|
value.front() == '@')
|
|
{
|
|
GByte *pabyData = nullptr;
|
|
if (VSIIngestFile(nullptr, value.c_str() + 1, &pabyData, nullptr,
|
|
1024 * 1024))
|
|
{
|
|
// Remove UTF-8 BOM
|
|
size_t offset = 0;
|
|
if (pabyData[0] == 0xEF && pabyData[1] == 0xBB &&
|
|
pabyData[2] == 0xBF)
|
|
{
|
|
offset = 3;
|
|
}
|
|
newValue = reinterpret_cast<const char *>(pabyData + offset);
|
|
VSIFree(pabyData);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (m_decl.IsRemoveSQLCommentsEnabled())
|
|
newValue = CPLRemoveSQLComments(newValue);
|
|
|
|
return SetInternal(newValue);
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(int value)
|
|
{
|
|
if (m_decl.GetType() == GAAT_REAL)
|
|
{
|
|
return Set(static_cast<double>(value));
|
|
}
|
|
if (m_decl.GetType() != GAAT_INTEGER)
|
|
{
|
|
CPLError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(int) on argument '%s' of type %s is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
return SetInternal(value);
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(double value)
|
|
{
|
|
if (m_decl.GetType() != GAAT_REAL)
|
|
{
|
|
CPLError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(double) on argument '%s' of type %s is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
return SetInternal(value);
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(GDALDataset *ds, bool owned)
|
|
{
|
|
if (m_decl.GetType() != GAAT_DATASET)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(GDALDataset*, bool) on argument '%s' of type %s "
|
|
"is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
auto &val = *std::get<GDALArgDatasetValue *>(m_value);
|
|
if (val.GetInputFlags() == GADV_NAME && val.GetOutputFlags() == GADV_OBJECT)
|
|
{
|
|
CPLError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Dataset object '%s' is created by algorithm and cannot be set "
|
|
"as an input.",
|
|
GetName().c_str());
|
|
return false;
|
|
}
|
|
m_explicitlySet = true;
|
|
val.Set(ds, owned);
|
|
return RunAllActions();
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(std::unique_ptr<GDALDataset> ds)
|
|
{
|
|
if (m_decl.GetType() != GAAT_DATASET)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(GDALDataset*, bool) on argument '%s' of type %s "
|
|
"is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
auto &val = *std::get<GDALArgDatasetValue *>(m_value);
|
|
if (val.GetInputFlags() == GADV_NAME && val.GetOutputFlags() == GADV_OBJECT)
|
|
{
|
|
CPLError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Dataset object '%s' is created by algorithm and cannot be set "
|
|
"as an input.",
|
|
GetName().c_str());
|
|
return false;
|
|
}
|
|
m_explicitlySet = true;
|
|
val.Set(std::move(ds));
|
|
return RunAllActions();
|
|
}
|
|
|
|
bool GDALAlgorithmArg::SetDatasetName(const std::string &name)
|
|
{
|
|
if (m_decl.GetType() != GAAT_DATASET)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling SetDatasetName() on argument '%s' of type %s is "
|
|
"not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
m_explicitlySet = true;
|
|
std::get<GDALArgDatasetValue *>(m_value)->Set(name);
|
|
return RunAllActions();
|
|
}
|
|
|
|
bool GDALAlgorithmArg::SetFrom(const GDALArgDatasetValue &other)
|
|
{
|
|
if (m_decl.GetType() != GAAT_DATASET)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling SetFrom() on argument '%s' of type %s is "
|
|
"not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
m_explicitlySet = true;
|
|
std::get<GDALArgDatasetValue *>(m_value)->SetFrom(other);
|
|
return RunAllActions();
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(const std::vector<std::string> &value)
|
|
{
|
|
if (m_decl.GetType() != GAAT_STRING_LIST)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(const std::vector<std::string> &) on argument "
|
|
"'%s' of type %s is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
return SetInternal(value);
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(const std::vector<int> &value)
|
|
{
|
|
if (m_decl.GetType() != GAAT_INTEGER_LIST)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(const std::vector<int> &) on argument '%s' of "
|
|
"type %s is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
return SetInternal(value);
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(const std::vector<double> &value)
|
|
{
|
|
if (m_decl.GetType() != GAAT_REAL_LIST)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(const std::vector<double> &) on argument '%s' of "
|
|
"type %s is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
return SetInternal(value);
|
|
}
|
|
|
|
bool GDALAlgorithmArg::Set(std::vector<GDALArgDatasetValue> &&value)
|
|
{
|
|
if (m_decl.GetType() != GAAT_DATASET_LIST)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling Set(const std::vector<GDALArgDatasetValue> &&) on "
|
|
"argument '%s' of type %s is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()));
|
|
return false;
|
|
}
|
|
m_explicitlySet = true;
|
|
*std::get<std::vector<GDALArgDatasetValue> *>(m_value) = std::move(value);
|
|
return RunAllActions();
|
|
}
|
|
|
|
bool GDALAlgorithmArg::SetFrom(const GDALAlgorithmArg &other)
|
|
{
|
|
if (m_decl.GetType() != other.GetType())
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Calling SetFrom() on argument '%s' of type %s whereas "
|
|
"other argument type is %s is not supported",
|
|
GetName().c_str(), GDALAlgorithmArgTypeName(m_decl.GetType()),
|
|
GDALAlgorithmArgTypeName(other.GetType()));
|
|
return false;
|
|
}
|
|
|
|
switch (m_decl.GetType())
|
|
{
|
|
case GAAT_BOOLEAN:
|
|
*std::get<bool *>(m_value) = *std::get<bool *>(other.m_value);
|
|
break;
|
|
case GAAT_STRING:
|
|
*std::get<std::string *>(m_value) =
|
|
*std::get<std::string *>(other.m_value);
|
|
break;
|
|
case GAAT_INTEGER:
|
|
*std::get<int *>(m_value) = *std::get<int *>(other.m_value);
|
|
break;
|
|
case GAAT_REAL:
|
|
*std::get<double *>(m_value) = *std::get<double *>(other.m_value);
|
|
break;
|
|
case GAAT_DATASET:
|
|
return SetFrom(other.Get<GDALArgDatasetValue>());
|
|
case GAAT_STRING_LIST:
|
|
*std::get<std::vector<std::string> *>(m_value) =
|
|
*std::get<std::vector<std::string> *>(other.m_value);
|
|
break;
|
|
case GAAT_INTEGER_LIST:
|
|
*std::get<std::vector<int> *>(m_value) =
|
|
*std::get<std::vector<int> *>(other.m_value);
|
|
break;
|
|
case GAAT_REAL_LIST:
|
|
*std::get<std::vector<double> *>(m_value) =
|
|
*std::get<std::vector<double> *>(other.m_value);
|
|
break;
|
|
case GAAT_DATASET_LIST:
|
|
{
|
|
std::get<std::vector<GDALArgDatasetValue> *>(m_value)->clear();
|
|
for (const auto &val :
|
|
*std::get<std::vector<GDALArgDatasetValue> *>(other.m_value))
|
|
{
|
|
GDALArgDatasetValue v;
|
|
v.SetFrom(val);
|
|
std::get<std::vector<GDALArgDatasetValue> *>(m_value)
|
|
->push_back(std::move(v));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
m_explicitlySet = true;
|
|
return RunAllActions();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArg::RunAllActions() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithmArg::RunAllActions()
|
|
{
|
|
if (!RunValidationActions())
|
|
return false;
|
|
RunActions();
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArg::RunActions() */
|
|
/************************************************************************/
|
|
|
|
void GDALAlgorithmArg::RunActions()
|
|
{
|
|
for (const auto &f : m_actions)
|
|
f();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArg::RunValidationActions() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithmArg::RunValidationActions()
|
|
{
|
|
for (const auto &f : m_validationActions)
|
|
{
|
|
if (!f())
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALInConstructionAlgorithmArg::AddAlias() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALInConstructionAlgorithmArg::AddAlias(const std::string &alias)
|
|
{
|
|
m_decl.AddAlias(alias);
|
|
if (m_owner)
|
|
m_owner->AddAliasFor(this, alias);
|
|
return *this;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALInConstructionAlgorithmArg::AddHiddenAlias() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALInConstructionAlgorithmArg::AddHiddenAlias(const std::string &alias)
|
|
{
|
|
m_decl.AddHiddenAlias(alias);
|
|
if (m_owner)
|
|
m_owner->AddAliasFor(this, alias);
|
|
return *this;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALInConstructionAlgorithmArg::SetPositional() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &GDALInConstructionAlgorithmArg::SetPositional()
|
|
{
|
|
m_decl.SetPositional();
|
|
if (m_owner)
|
|
m_owner->SetPositional(this);
|
|
return *this;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue::GDALArgDatasetValue() */
|
|
/************************************************************************/
|
|
|
|
GDALArgDatasetValue::GDALArgDatasetValue(GDALDataset *poDS, bool owned)
|
|
: m_poDS(poDS), m_owned(owned),
|
|
m_name(m_poDS ? m_poDS->GetDescription() : std::string()), m_nameSet(true)
|
|
{
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue::GDALArgDatasetValue() */
|
|
/************************************************************************/
|
|
|
|
GDALArgDatasetValue::GDALArgDatasetValue(std::unique_ptr<GDALDataset> poDS)
|
|
: m_poDS(poDS.release()), m_owned(true),
|
|
m_name(m_poDS ? m_poDS->GetDescription() : std::string()), m_nameSet(true)
|
|
{
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue::Set() */
|
|
/************************************************************************/
|
|
|
|
void GDALArgDatasetValue::Set(const std::string &name)
|
|
{
|
|
Close();
|
|
m_name = name;
|
|
m_nameSet = true;
|
|
if (m_ownerArg)
|
|
m_ownerArg->NotifyValueSet();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue::Set() */
|
|
/************************************************************************/
|
|
|
|
void GDALArgDatasetValue::Set(std::unique_ptr<GDALDataset> poDS)
|
|
{
|
|
Close();
|
|
m_poDS = poDS.release();
|
|
m_owned = true;
|
|
m_name = m_poDS ? m_poDS->GetDescription() : std::string();
|
|
m_nameSet = true;
|
|
if (m_ownerArg)
|
|
m_ownerArg->NotifyValueSet();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue::Set() */
|
|
/************************************************************************/
|
|
|
|
void GDALArgDatasetValue::Set(GDALDataset *poDS, bool owned)
|
|
{
|
|
Close();
|
|
m_poDS = poDS;
|
|
m_owned = owned;
|
|
m_name = m_poDS ? m_poDS->GetDescription() : std::string();
|
|
m_nameSet = true;
|
|
if (m_ownerArg)
|
|
m_ownerArg->NotifyValueSet();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue::~GDALArgDatasetValue() */
|
|
/************************************************************************/
|
|
|
|
GDALArgDatasetValue::~GDALArgDatasetValue()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue::Close() */
|
|
/************************************************************************/
|
|
|
|
bool GDALArgDatasetValue::Close()
|
|
{
|
|
bool ret = true;
|
|
if (m_owned && m_poDS)
|
|
{
|
|
ret = m_poDS->Close() == CE_None;
|
|
delete m_poDS;
|
|
}
|
|
m_poDS = nullptr;
|
|
return ret;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue::operator=() */
|
|
/************************************************************************/
|
|
|
|
GDALArgDatasetValue &GDALArgDatasetValue::operator=(GDALArgDatasetValue &&other)
|
|
{
|
|
Close();
|
|
m_poDS = other.m_poDS;
|
|
m_owned = other.m_owned;
|
|
m_name = other.m_name;
|
|
m_nameSet = other.m_nameSet;
|
|
m_type = other.m_type;
|
|
m_inputFlags = other.m_inputFlags;
|
|
m_outputFlags = other.m_outputFlags;
|
|
other.m_poDS = nullptr;
|
|
other.m_owned = false;
|
|
other.m_name.clear();
|
|
other.m_nameSet = false;
|
|
return *this;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValue(GDALArgDatasetValue &&other) */
|
|
/************************************************************************/
|
|
|
|
GDALArgDatasetValue::GDALArgDatasetValue(GDALArgDatasetValue &&other)
|
|
: m_poDS(other.m_poDS), m_owned(other.m_owned), m_name(other.m_name),
|
|
m_nameSet(other.m_nameSet), m_type(other.m_type),
|
|
m_inputFlags(other.m_inputFlags), m_outputFlags(other.m_outputFlags)
|
|
{
|
|
other.m_poDS = nullptr;
|
|
other.m_owned = false;
|
|
other.m_name.clear();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::GDALAlgorithm() */
|
|
/************************************************************************/
|
|
|
|
GDALAlgorithm::GDALAlgorithm(const std::string &name,
|
|
const std::string &description,
|
|
const std::string &helpURL)
|
|
: m_name(name), m_description(description), m_helpURL(helpURL),
|
|
m_helpFullURL(!m_helpURL.empty() && m_helpURL[0] == '/'
|
|
? "https://gdal.org" + m_helpURL
|
|
: m_helpURL)
|
|
{
|
|
AddArg("help", 'h', _("Display help message and exit"), &m_helpRequested)
|
|
.SetOnlyForCLI()
|
|
.SetCategory(GAAC_COMMON)
|
|
.AddAction([this]() { m_specialActionRequested = true; });
|
|
AddArg("json-usage", 0, _("Display usage as JSON document and exit"),
|
|
&m_JSONUsageRequested)
|
|
.SetOnlyForCLI()
|
|
.SetCategory(GAAC_COMMON)
|
|
.AddAction([this]() { m_specialActionRequested = true; });
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::~GDALAlgorithm() */
|
|
/************************************************************************/
|
|
|
|
GDALAlgorithm::~GDALAlgorithm() = default;
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::ParseArgument() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithm::ParseArgument(
|
|
GDALAlgorithmArg *arg, const std::string &name, const std::string &value,
|
|
std::map<
|
|
GDALAlgorithmArg *,
|
|
std::variant<std::vector<std::string>, std::vector<int>,
|
|
std::vector<double>, std::vector<GDALArgDatasetValue>>>
|
|
&inConstructionValues)
|
|
{
|
|
const bool isListArg = GDALAlgorithmArgTypeIsList(arg->GetType());
|
|
if (arg->IsExplicitlySet() && !isListArg)
|
|
{
|
|
// Hack for "gdal info" to be able to pass an opened raster dataset
|
|
// by "gdal raster info" to the "gdal vector info" algorithm.
|
|
if (arg->SkipIfAlreadySet())
|
|
{
|
|
arg->SetSkipIfAlreadySet(false);
|
|
return true;
|
|
}
|
|
|
|
ReportError(CE_Failure, CPLE_IllegalArg,
|
|
"Argument '%s' has already been specified.", name.c_str());
|
|
return false;
|
|
}
|
|
|
|
if (!arg->GetRepeatedArgAllowed() &&
|
|
cpl::contains(inConstructionValues, arg))
|
|
{
|
|
ReportError(CE_Failure, CPLE_IllegalArg,
|
|
"Argument '%s' has already been specified.", name.c_str());
|
|
return false;
|
|
}
|
|
|
|
switch (arg->GetType())
|
|
{
|
|
case GAAT_BOOLEAN:
|
|
{
|
|
if (value.empty() || value == "true")
|
|
return arg->Set(true);
|
|
else if (value == "false")
|
|
return arg->Set(false);
|
|
else
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_IllegalArg,
|
|
"Invalid value '%s' for boolean argument '%s'. Should be "
|
|
"'true' or 'false'.",
|
|
value.c_str(), name.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
case GAAT_STRING:
|
|
{
|
|
const auto &choices = arg->GetChoices();
|
|
if (!choices.empty() && std::find(choices.begin(), choices.end(),
|
|
value) == choices.end())
|
|
{
|
|
std::string expected;
|
|
for (const auto &choice : choices)
|
|
{
|
|
if (!expected.empty())
|
|
expected += ", ";
|
|
expected += '\'';
|
|
expected += choice;
|
|
expected += '\'';
|
|
}
|
|
ReportError(
|
|
CE_Failure, CPLE_IllegalArg,
|
|
"Invalid value '%s' for string argument '%s'. Should be "
|
|
"one among %s.",
|
|
value.c_str(), name.c_str(), expected.c_str());
|
|
return false;
|
|
}
|
|
|
|
return arg->Set(value);
|
|
}
|
|
|
|
case GAAT_INTEGER:
|
|
{
|
|
errno = 0;
|
|
char *endptr = nullptr;
|
|
const auto val = std::strtol(value.c_str(), &endptr, 10);
|
|
if (errno == 0 && endptr &&
|
|
endptr == value.c_str() + value.size() && val >= INT_MIN &&
|
|
val <= INT_MAX)
|
|
{
|
|
return arg->Set(static_cast<int>(val));
|
|
}
|
|
else
|
|
{
|
|
ReportError(CE_Failure, CPLE_IllegalArg,
|
|
"Expected integer value for argument '%s', "
|
|
"but got '%s'.",
|
|
name.c_str(), value.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
case GAAT_REAL:
|
|
{
|
|
char *endptr = nullptr;
|
|
double dfValue = CPLStrtod(value.c_str(), &endptr);
|
|
if (endptr != value.c_str() + value.size())
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_IllegalArg,
|
|
"Expected real value for argument '%s', but got '%s'.",
|
|
name.c_str(), value.c_str());
|
|
return false;
|
|
}
|
|
return arg->Set(dfValue);
|
|
}
|
|
|
|
case GAAT_DATASET:
|
|
{
|
|
return arg->SetDatasetName(value);
|
|
}
|
|
|
|
case GAAT_STRING_LIST:
|
|
{
|
|
const CPLStringList aosTokens(
|
|
arg->GetPackedValuesAllowed()
|
|
? CSLTokenizeString2(value.c_str(), ",", CSLT_HONOURSTRINGS)
|
|
: CSLAddString(nullptr, value.c_str()));
|
|
if (!cpl::contains(inConstructionValues, arg))
|
|
{
|
|
inConstructionValues[arg] = std::vector<std::string>();
|
|
}
|
|
auto &valueVector =
|
|
std::get<std::vector<std::string>>(inConstructionValues[arg]);
|
|
const auto &choices = arg->GetChoices();
|
|
for (const char *v : aosTokens)
|
|
{
|
|
if (!choices.empty() &&
|
|
std::find(choices.begin(), choices.end(), v) ==
|
|
choices.end())
|
|
{
|
|
std::string expected;
|
|
for (const auto &choice : choices)
|
|
{
|
|
if (!expected.empty())
|
|
expected += ", ";
|
|
expected += '\'';
|
|
expected += choice;
|
|
expected += '\'';
|
|
}
|
|
ReportError(CE_Failure, CPLE_IllegalArg,
|
|
"Invalid value '%s' for string argument '%s'. "
|
|
"Should be "
|
|
"one among %s.",
|
|
v, name.c_str(), expected.c_str());
|
|
return false;
|
|
}
|
|
|
|
valueVector.push_back(v);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case GAAT_INTEGER_LIST:
|
|
{
|
|
const CPLStringList aosTokens(
|
|
arg->GetPackedValuesAllowed()
|
|
? CSLTokenizeString2(value.c_str(), ",", CSLT_HONOURSTRINGS)
|
|
: CSLAddString(nullptr, value.c_str()));
|
|
if (!cpl::contains(inConstructionValues, arg))
|
|
{
|
|
inConstructionValues[arg] = std::vector<int>();
|
|
}
|
|
auto &valueVector =
|
|
std::get<std::vector<int>>(inConstructionValues[arg]);
|
|
for (const char *v : aosTokens)
|
|
{
|
|
errno = 0;
|
|
char *endptr = nullptr;
|
|
const auto val = std::strtol(v, &endptr, 10);
|
|
if (errno == 0 && endptr && endptr == v + strlen(v) &&
|
|
val >= INT_MIN && val <= INT_MAX)
|
|
{
|
|
valueVector.push_back(static_cast<int>(val));
|
|
}
|
|
else
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_IllegalArg,
|
|
"Expected list of integer value for argument '%s', "
|
|
"but got '%s'.",
|
|
name.c_str(), value.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case GAAT_REAL_LIST:
|
|
{
|
|
const CPLStringList aosTokens(
|
|
arg->GetPackedValuesAllowed()
|
|
? CSLTokenizeString2(value.c_str(), ",", CSLT_HONOURSTRINGS)
|
|
: CSLAddString(nullptr, value.c_str()));
|
|
if (!cpl::contains(inConstructionValues, arg))
|
|
{
|
|
inConstructionValues[arg] = std::vector<double>();
|
|
}
|
|
auto &valueVector =
|
|
std::get<std::vector<double>>(inConstructionValues[arg]);
|
|
for (const char *v : aosTokens)
|
|
{
|
|
char *endptr = nullptr;
|
|
double dfValue = CPLStrtod(v, &endptr);
|
|
if (endptr != v + strlen(v))
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_IllegalArg,
|
|
"Expected list of real value for argument '%s', "
|
|
"but got '%s'.",
|
|
name.c_str(), value.c_str());
|
|
return false;
|
|
}
|
|
valueVector.push_back(dfValue);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case GAAT_DATASET_LIST:
|
|
{
|
|
const CPLStringList aosTokens(
|
|
CSLTokenizeString2(value.c_str(), ",", CSLT_HONOURSTRINGS));
|
|
if (!cpl::contains(inConstructionValues, arg))
|
|
{
|
|
inConstructionValues[arg] = std::vector<GDALArgDatasetValue>();
|
|
}
|
|
auto &valueVector = std::get<std::vector<GDALArgDatasetValue>>(
|
|
inConstructionValues[arg]);
|
|
for (const char *v : aosTokens)
|
|
{
|
|
valueVector.push_back(GDALArgDatasetValue(v));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::ParseCommandLineArguments() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithm::ParseCommandLineArguments(
|
|
const std::vector<std::string> &args)
|
|
{
|
|
if (m_parsedSubStringAlreadyCalled)
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"ParseCommandLineArguments() can only be called once per "
|
|
"instance.");
|
|
return false;
|
|
}
|
|
m_parsedSubStringAlreadyCalled = true;
|
|
|
|
// AWS like syntax supported too (not advertized)
|
|
if (args.size() == 1 && args[0] == "help")
|
|
{
|
|
auto arg = GetArg("help");
|
|
assert(arg);
|
|
arg->Set(true);
|
|
arg->RunActions();
|
|
return true;
|
|
}
|
|
|
|
if (HasSubAlgorithms())
|
|
{
|
|
if (args.empty())
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined, "Missing %s name.",
|
|
m_callPath.size() == 1 ? "command" : "subcommand");
|
|
return false;
|
|
}
|
|
if (!args[0].empty() && args[0][0] == '-')
|
|
{
|
|
// go on argument parsing
|
|
}
|
|
else
|
|
{
|
|
m_shortCutAlg = InstantiateSubAlgorithm(args[0]);
|
|
if (m_shortCutAlg)
|
|
{
|
|
m_selectedSubAlg = m_shortCutAlg.get();
|
|
bool bRet = m_selectedSubAlg->ParseCommandLineArguments(
|
|
std::vector<std::string>(args.begin() + 1, args.end()));
|
|
m_selectedSubAlg->PropagateSpecialActionTo(this);
|
|
return bRet;
|
|
}
|
|
else
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Unknown command: '%s'", args[0].c_str());
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::map<
|
|
GDALAlgorithmArg *,
|
|
std::variant<std::vector<std::string>, std::vector<int>,
|
|
std::vector<double>, std::vector<GDALArgDatasetValue>>>
|
|
inConstructionValues;
|
|
|
|
std::vector<std::string> lArgs(args);
|
|
for (size_t i = 0; i < lArgs.size(); /* incremented in loop */)
|
|
{
|
|
const auto &strArg = lArgs[i];
|
|
GDALAlgorithmArg *arg = nullptr;
|
|
std::string name;
|
|
std::string value;
|
|
bool hasValue = false;
|
|
if (strArg.size() >= 2 && strArg[0] == '-' && strArg[1] == '-')
|
|
{
|
|
const auto equalPos = strArg.find('=');
|
|
name = (equalPos != std::string::npos) ? strArg.substr(0, equalPos)
|
|
: strArg;
|
|
auto iterArg = m_mapLongNameToArg.find(name.substr(2));
|
|
if (iterArg == m_mapLongNameToArg.end())
|
|
{
|
|
ReportError(CE_Failure, CPLE_IllegalArg,
|
|
"Long name option '%s' is unknown.", name.c_str());
|
|
return false;
|
|
}
|
|
arg = iterArg->second;
|
|
if (equalPos != std::string::npos)
|
|
{
|
|
hasValue = true;
|
|
value = strArg.substr(equalPos + 1);
|
|
}
|
|
}
|
|
else if (strArg.size() >= 2 && strArg[0] == '-')
|
|
{
|
|
if (strArg.size() != 2)
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_IllegalArg,
|
|
"Option '%s' not recognized. Should be either a long "
|
|
"option or a one-letter short option.",
|
|
strArg.c_str());
|
|
return false;
|
|
}
|
|
name = strArg;
|
|
auto iterArg = m_mapShortNameToArg.find(name.substr(1));
|
|
if (iterArg == m_mapShortNameToArg.end())
|
|
{
|
|
ReportError(CE_Failure, CPLE_IllegalArg,
|
|
"Short name option '%s' is unknown.", name.c_str());
|
|
return false;
|
|
}
|
|
arg = iterArg->second;
|
|
}
|
|
else
|
|
{
|
|
++i;
|
|
continue;
|
|
}
|
|
assert(arg);
|
|
|
|
if (arg->GetType() == GAAT_BOOLEAN)
|
|
{
|
|
if (!hasValue)
|
|
{
|
|
hasValue = true;
|
|
value = "true";
|
|
}
|
|
}
|
|
|
|
if (!hasValue)
|
|
{
|
|
if (i + 1 == lArgs.size())
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_IllegalArg,
|
|
"Expected value for argument '%s', but ran short of tokens",
|
|
name.c_str());
|
|
return false;
|
|
}
|
|
value = lArgs[i + 1];
|
|
lArgs.erase(lArgs.begin() + i + 1);
|
|
}
|
|
|
|
if (!ParseArgument(arg, name, value, inConstructionValues))
|
|
return false;
|
|
|
|
lArgs.erase(lArgs.begin() + i);
|
|
}
|
|
|
|
if (m_specialActionRequested)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
size_t i = 0;
|
|
size_t iCurPosArg = 0;
|
|
while (i < lArgs.size() && iCurPosArg < m_positionalArgs.size())
|
|
{
|
|
GDALAlgorithmArg *arg = m_positionalArgs[iCurPosArg];
|
|
while (arg->IsExplicitlySet())
|
|
{
|
|
++iCurPosArg;
|
|
if (iCurPosArg == m_positionalArgs.size())
|
|
break;
|
|
arg = m_positionalArgs[iCurPosArg];
|
|
}
|
|
if (iCurPosArg == m_positionalArgs.size())
|
|
{
|
|
break;
|
|
}
|
|
if (GDALAlgorithmArgTypeIsList(arg->GetType()) &&
|
|
arg->GetMinCount() != arg->GetMaxCount())
|
|
{
|
|
if (iCurPosArg == 0)
|
|
{
|
|
size_t nCountAtEnd = 0;
|
|
for (size_t j = 1; j < m_positionalArgs.size(); j++)
|
|
{
|
|
const auto *otherArg = m_positionalArgs[j];
|
|
if (GDALAlgorithmArgTypeIsList(otherArg->GetType()))
|
|
{
|
|
if (otherArg->GetMinCount() != otherArg->GetMaxCount())
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Ambiguity in definition of positional "
|
|
"argument "
|
|
"'%s' given it has a varying number of values, "
|
|
"but follows argument '%s' which also has a "
|
|
"varying number of values",
|
|
otherArg->GetName().c_str(),
|
|
arg->GetName().c_str());
|
|
return false;
|
|
}
|
|
nCountAtEnd += otherArg->GetMinCount();
|
|
}
|
|
else
|
|
{
|
|
if (!otherArg->IsRequired())
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Ambiguity in definition of positional "
|
|
"argument "
|
|
"'%s', given it is not required but follows "
|
|
"argument '%s' which has a varying number of "
|
|
"values",
|
|
otherArg->GetName().c_str(),
|
|
arg->GetName().c_str());
|
|
return false;
|
|
}
|
|
nCountAtEnd++;
|
|
}
|
|
}
|
|
if (lArgs.size() < nCountAtEnd)
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Not enough positional values.");
|
|
return false;
|
|
}
|
|
for (; i < lArgs.size() - nCountAtEnd; ++i)
|
|
{
|
|
if (!ParseArgument(arg, arg->GetName().c_str(), lArgs[i],
|
|
inConstructionValues))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else if (iCurPosArg == m_positionalArgs.size() - 1)
|
|
{
|
|
for (; i < lArgs.size(); ++i)
|
|
{
|
|
if (!ParseArgument(arg, arg->GetName().c_str(), lArgs[i],
|
|
inConstructionValues))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Ambiguity in definition of positional arguments: "
|
|
"arguments with varying number of values must be "
|
|
"first or last one.");
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (lArgs.size() - i < static_cast<size_t>(arg->GetMaxCount()))
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Not enough positional values.");
|
|
return false;
|
|
}
|
|
const size_t iMax = i + arg->GetMaxCount();
|
|
for (; i < iMax; ++i)
|
|
{
|
|
if (!ParseArgument(arg, arg->GetName().c_str(), lArgs[i],
|
|
inConstructionValues))
|
|
return false;
|
|
}
|
|
}
|
|
++iCurPosArg;
|
|
}
|
|
|
|
if (i < lArgs.size())
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Positional values starting at '%s' are not expected.",
|
|
lArgs[i].c_str());
|
|
return false;
|
|
}
|
|
if (iCurPosArg < m_positionalArgs.size() &&
|
|
(GDALAlgorithmArgTypeIsList(m_positionalArgs[iCurPosArg]->GetType())
|
|
? m_positionalArgs[iCurPosArg]->GetMinCount() > 0
|
|
: m_positionalArgs[iCurPosArg]->IsRequired()))
|
|
{
|
|
while (iCurPosArg < m_positionalArgs.size() &&
|
|
m_positionalArgs[iCurPosArg]->IsExplicitlySet())
|
|
{
|
|
++iCurPosArg;
|
|
}
|
|
if (iCurPosArg < m_positionalArgs.size())
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Positional arguments starting at '%s' have not been "
|
|
"specified.",
|
|
m_positionalArgs[iCurPosArg]->GetMetaVar().c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (auto &[arg, value] : inConstructionValues)
|
|
{
|
|
if (arg->GetType() == GAAT_STRING_LIST)
|
|
{
|
|
if (!arg->Set(std::get<std::vector<std::string>>(
|
|
inConstructionValues[arg])))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (arg->GetType() == GAAT_INTEGER_LIST)
|
|
{
|
|
if (!arg->Set(
|
|
std::get<std::vector<int>>(inConstructionValues[arg])))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (arg->GetType() == GAAT_REAL_LIST)
|
|
{
|
|
if (!arg->Set(
|
|
std::get<std::vector<double>>(inConstructionValues[arg])))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (arg->GetType() == GAAT_DATASET_LIST)
|
|
{
|
|
if (!arg->Set(std::move(std::get<std::vector<GDALArgDatasetValue>>(
|
|
inConstructionValues[arg]))))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return m_skipValidationInParseCommandLine || ValidateArguments();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::ReportError() */
|
|
/************************************************************************/
|
|
|
|
//! @cond Doxygen_Suppress
|
|
void GDALAlgorithm::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
|
|
const char *fmt, ...) const
|
|
{
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
CPLError(eErrClass, err_no, "%s",
|
|
std::string(m_name)
|
|
.append(": ")
|
|
.append(CPLString().vPrintf(fmt, args))
|
|
.c_str());
|
|
va_end(args);
|
|
}
|
|
|
|
//! @endcond
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::ProcessDatasetArg() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithm::ProcessDatasetArg(GDALAlgorithmArg *arg,
|
|
GDALAlgorithm *algForOutput)
|
|
{
|
|
bool ret = true;
|
|
|
|
const auto updateArg = algForOutput->GetArg(GDAL_ARG_NAME_UPDATE);
|
|
const bool update = (updateArg && updateArg->GetType() == GAAT_BOOLEAN &&
|
|
updateArg->Get<bool>());
|
|
const auto overwriteArg = algForOutput->GetArg("overwrite");
|
|
const bool overwrite =
|
|
(arg->IsOutput() && overwriteArg &&
|
|
overwriteArg->GetType() == GAAT_BOOLEAN && overwriteArg->Get<bool>());
|
|
auto outputArg = algForOutput->GetArg(GDAL_ARG_NAME_OUTPUT);
|
|
auto &val = arg->Get<GDALArgDatasetValue>();
|
|
if (!val.GetDataset() && !val.IsNameSet())
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Argument '%s' has no dataset object or dataset name.",
|
|
arg->GetName().c_str());
|
|
ret = false;
|
|
}
|
|
else if (!val.GetDataset() &&
|
|
(!arg->IsOutput() || (arg == outputArg && update && !overwrite)))
|
|
{
|
|
int flags = val.GetType();
|
|
bool assignToOutputArg = false;
|
|
|
|
// Check if input and output parameters point to the same
|
|
// filename (for vector datasets)
|
|
if (arg->GetName() == GDAL_ARG_NAME_INPUT && update && !overwrite &&
|
|
outputArg && outputArg->GetType() == GAAT_DATASET)
|
|
{
|
|
auto &outputVal = outputArg->Get<GDALArgDatasetValue>();
|
|
if (!outputVal.GetDataset() &&
|
|
outputVal.GetName() == val.GetName() &&
|
|
(outputVal.GetInputFlags() & GADV_OBJECT) != 0)
|
|
{
|
|
assignToOutputArg = true;
|
|
flags |= GDAL_OF_UPDATE | GDAL_OF_VERBOSE_ERROR;
|
|
}
|
|
}
|
|
|
|
if (!arg->IsOutput() || val.GetInputFlags() == GADV_NAME)
|
|
flags |= GDAL_OF_VERBOSE_ERROR;
|
|
if ((arg == outputArg || !outputArg) && update)
|
|
flags |= GDAL_OF_UPDATE | GDAL_OF_VERBOSE_ERROR;
|
|
|
|
CPLStringList aosOpenOptions;
|
|
CPLStringList aosAllowedDrivers;
|
|
if (arg->GetName() == GDAL_ARG_NAME_INPUT)
|
|
{
|
|
const auto ooArg = GetArg("open-option");
|
|
if (ooArg && ooArg->GetType() == GAAT_STRING_LIST)
|
|
aosOpenOptions =
|
|
CPLStringList(ooArg->Get<std::vector<std::string>>());
|
|
|
|
const auto ifArg = GetArg("input-format");
|
|
if (ifArg && ifArg->GetType() == GAAT_STRING_LIST)
|
|
aosAllowedDrivers =
|
|
CPLStringList(ifArg->Get<std::vector<std::string>>());
|
|
}
|
|
|
|
auto poDS = std::unique_ptr<GDALDataset>(
|
|
GDALDataset::Open(val.GetName().c_str(), flags,
|
|
aosAllowedDrivers.List(), aosOpenOptions.List()));
|
|
if (poDS)
|
|
{
|
|
if (assignToOutputArg)
|
|
{
|
|
// Avoid opening twice the same datasource if it is both
|
|
// the input and output.
|
|
// Known to cause problems with at least FGdb, SQLite
|
|
// and GPKG drivers. See #4270
|
|
// Restrict to those 3 drivers. For example it is known
|
|
// to break with the PG driver due to the way it
|
|
// manages transactions.
|
|
auto poDriver = poDS->GetDriver();
|
|
if (poDriver && (EQUAL(poDriver->GetDescription(), "FileGDB") ||
|
|
EQUAL(poDriver->GetDescription(), "SQLite") ||
|
|
EQUAL(poDriver->GetDescription(), "GPKG")))
|
|
{
|
|
outputArg->Get<GDALArgDatasetValue>().Set(poDS.get(),
|
|
false);
|
|
}
|
|
}
|
|
val.Set(std::move(poDS));
|
|
}
|
|
else
|
|
{
|
|
ret = false;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::ValidateArguments() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithm::ValidateArguments()
|
|
{
|
|
if (m_selectedSubAlg)
|
|
return m_selectedSubAlg->ValidateArguments();
|
|
|
|
if (m_specialActionRequested)
|
|
return true;
|
|
|
|
bool ret = true;
|
|
std::map<std::string, std::string> mutualExclusionGroupUsed;
|
|
for (auto &arg : m_args)
|
|
{
|
|
// Check mutually exclusive arguments
|
|
if (arg->IsExplicitlySet())
|
|
{
|
|
const auto &mutualExclusionGroup = arg->GetMutualExclusionGroup();
|
|
if (!mutualExclusionGroup.empty())
|
|
{
|
|
auto oIter =
|
|
mutualExclusionGroupUsed.find(mutualExclusionGroup);
|
|
if (oIter != mutualExclusionGroupUsed.end())
|
|
{
|
|
ret = false;
|
|
ReportError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Argument '%s' is mutually exclusive with '%s'.",
|
|
arg->GetName().c_str(), oIter->second.c_str());
|
|
}
|
|
else
|
|
{
|
|
mutualExclusionGroupUsed[mutualExclusionGroup] =
|
|
arg->GetName();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (arg->IsRequired() && !arg->IsExplicitlySet() &&
|
|
!arg->HasDefaultValue())
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Required argument '%s' has not been specified.",
|
|
arg->GetName().c_str());
|
|
ret = false;
|
|
}
|
|
else if (arg->IsExplicitlySet() && arg->GetType() == GAAT_DATASET)
|
|
{
|
|
if (!ProcessDatasetArg(arg.get(), this))
|
|
ret = false;
|
|
}
|
|
else if (arg->IsExplicitlySet() &&
|
|
GDALAlgorithmArgTypeIsList(arg->GetType()))
|
|
{
|
|
int valueCount = 0;
|
|
if (arg->GetType() == GAAT_STRING_LIST)
|
|
{
|
|
valueCount = static_cast<int>(
|
|
arg->Get<std::vector<std::string>>().size());
|
|
}
|
|
else if (arg->GetType() == GAAT_INTEGER_LIST)
|
|
{
|
|
valueCount =
|
|
static_cast<int>(arg->Get<std::vector<int>>().size());
|
|
}
|
|
else if (arg->GetType() == GAAT_REAL_LIST)
|
|
{
|
|
valueCount =
|
|
static_cast<int>(arg->Get<std::vector<double>>().size());
|
|
}
|
|
else if (arg->GetType() == GAAT_DATASET_LIST)
|
|
{
|
|
valueCount = static_cast<int>(
|
|
arg->Get<std::vector<GDALArgDatasetValue>>().size());
|
|
}
|
|
|
|
if (valueCount != arg->GetMinCount() &&
|
|
arg->GetMinCount() == arg->GetMaxCount())
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"%d value(s) have been specified for argument '%s', "
|
|
"whereas exactly %d were expected.",
|
|
valueCount, arg->GetName().c_str(), arg->GetMinCount());
|
|
ret = false;
|
|
}
|
|
else if (valueCount < arg->GetMinCount())
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Only %d value(s) have been specified for argument '%s', "
|
|
"whereas at least %d were expected.",
|
|
valueCount, arg->GetName().c_str(), arg->GetMinCount());
|
|
ret = false;
|
|
}
|
|
else if (valueCount > arg->GetMaxCount())
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"%d values have been specified for argument '%s', "
|
|
"whereas at most %d were expected.",
|
|
valueCount, arg->GetName().c_str(),
|
|
arg->GetMaxCount());
|
|
ret = false;
|
|
}
|
|
}
|
|
|
|
if (arg->IsExplicitlySet() && arg->GetType() == GAAT_DATASET_LIST)
|
|
{
|
|
auto &listVal = arg->Get<std::vector<GDALArgDatasetValue>>();
|
|
for (auto &val : listVal)
|
|
{
|
|
if (!val.GetDataset() && val.GetName().empty())
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Argument '%s' has no dataset object or dataset name.",
|
|
arg->GetName().c_str());
|
|
ret = false;
|
|
}
|
|
else if (!val.GetDataset())
|
|
{
|
|
int flags = val.GetType() | GDAL_OF_VERBOSE_ERROR;
|
|
|
|
CPLStringList aosOpenOptions;
|
|
CPLStringList aosAllowedDrivers;
|
|
if (arg->GetName() == GDAL_ARG_NAME_INPUT)
|
|
{
|
|
const auto ooArg = GetArg("open-option");
|
|
if (ooArg && ooArg->GetType() == GAAT_STRING_LIST)
|
|
{
|
|
aosOpenOptions = CPLStringList(
|
|
ooArg->Get<std::vector<std::string>>());
|
|
}
|
|
|
|
const auto ifArg = GetArg("input-format");
|
|
if (ifArg && ifArg->GetType() == GAAT_STRING_LIST)
|
|
{
|
|
aosAllowedDrivers = CPLStringList(
|
|
ifArg->Get<std::vector<std::string>>());
|
|
}
|
|
|
|
const auto updateArg = GetArg(GDAL_ARG_NAME_UPDATE);
|
|
if (updateArg && updateArg->GetType() == GAAT_BOOLEAN &&
|
|
updateArg->Get<bool>())
|
|
{
|
|
flags |= GDAL_OF_UPDATE;
|
|
}
|
|
}
|
|
|
|
auto poDS = std::unique_ptr<GDALDataset>(GDALDataset::Open(
|
|
val.GetName().c_str(), flags, aosAllowedDrivers.List(),
|
|
aosOpenOptions.List()));
|
|
if (poDS)
|
|
{
|
|
val.Set(std::move(poDS));
|
|
}
|
|
else
|
|
{
|
|
ret = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddAliasFor() */
|
|
/************************************************************************/
|
|
|
|
//! @cond Doxygen_Suppress
|
|
void GDALAlgorithm::AddAliasFor(GDALInConstructionAlgorithmArg *arg,
|
|
const std::string &alias)
|
|
{
|
|
if (cpl::contains(m_mapLongNameToArg, alias))
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined, "Name '%s' already declared.",
|
|
alias.c_str());
|
|
}
|
|
else
|
|
{
|
|
m_mapLongNameToArg[alias] = arg;
|
|
}
|
|
}
|
|
|
|
//! @endcond
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::SetPositional() */
|
|
/************************************************************************/
|
|
|
|
//! @cond Doxygen_Suppress
|
|
void GDALAlgorithm::SetPositional(GDALInConstructionAlgorithmArg *arg)
|
|
{
|
|
CPLAssert(std::find(m_positionalArgs.begin(), m_positionalArgs.end(),
|
|
arg) == m_positionalArgs.end());
|
|
m_positionalArgs.push_back(arg);
|
|
}
|
|
|
|
//! @endcond
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(std::unique_ptr<GDALInConstructionAlgorithmArg> arg)
|
|
{
|
|
auto argRaw = arg.get();
|
|
const auto &longName = argRaw->GetName();
|
|
if (!longName.empty())
|
|
{
|
|
if (longName[0] == '-')
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Long name '%s' should not start with '-'",
|
|
longName.c_str());
|
|
}
|
|
if (longName.find('=') != std::string::npos)
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Long name '%s' should not contain a '=' character",
|
|
longName.c_str());
|
|
}
|
|
if (cpl::contains(m_mapLongNameToArg, longName))
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Long name '%s' already declared", longName.c_str());
|
|
}
|
|
m_mapLongNameToArg[longName] = argRaw;
|
|
}
|
|
const auto &shortName = argRaw->GetShortName();
|
|
if (!shortName.empty())
|
|
{
|
|
if (shortName.size() != 1 ||
|
|
!((shortName[0] >= 'a' && shortName[0] <= 'z') ||
|
|
(shortName[0] >= 'A' && shortName[0] <= 'Z') ||
|
|
(shortName[0] >= '0' && shortName[0] <= '9')))
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Short name '%s' should be a single letter or digit",
|
|
shortName.c_str());
|
|
}
|
|
if (cpl::contains(m_mapShortNameToArg, shortName))
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Short name '%s' already declared", shortName.c_str());
|
|
}
|
|
m_mapShortNameToArg[shortName] = argRaw;
|
|
}
|
|
m_args.emplace_back(std::move(arg));
|
|
return *(
|
|
static_cast<GDALInConstructionAlgorithmArg *>(m_args.back().get()));
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage, bool *pValue)
|
|
{
|
|
return AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage, GAAT_BOOLEAN),
|
|
pValue));
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage, std::string *pValue)
|
|
{
|
|
return AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage, GAAT_STRING),
|
|
pValue));
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage, int *pValue)
|
|
{
|
|
return AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage, GAAT_INTEGER),
|
|
pValue));
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage, double *pValue)
|
|
{
|
|
return AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage, GAAT_REAL),
|
|
pValue));
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage,
|
|
GDALArgDatasetValue *pValue, GDALArgDatasetValueType type)
|
|
{
|
|
pValue->SetType(type);
|
|
auto &arg = AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage, GAAT_DATASET),
|
|
pValue));
|
|
pValue->SetOwnerArgument(&arg);
|
|
return arg;
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage,
|
|
std::vector<std::string> *pValue)
|
|
{
|
|
return AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage,
|
|
GAAT_STRING_LIST),
|
|
pValue));
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage, std::vector<int> *pValue)
|
|
{
|
|
return AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage,
|
|
GAAT_INTEGER_LIST),
|
|
pValue));
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage,
|
|
std::vector<double> *pValue)
|
|
{
|
|
return AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage,
|
|
GAAT_REAL_LIST),
|
|
pValue));
|
|
}
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddArg(const std::string &longName, char chShortName,
|
|
const std::string &helpMessage,
|
|
std::vector<GDALArgDatasetValue> *pValue,
|
|
GDALArgDatasetValueType)
|
|
{
|
|
// FIXME
|
|
// pValue->SetType(type);
|
|
return AddArg(std::make_unique<GDALInConstructionAlgorithmArg>(
|
|
this,
|
|
GDALAlgorithmArgDecl(longName, chShortName, helpMessage,
|
|
GAAT_DATASET_LIST),
|
|
pValue));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddInputDatasetArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddInputDatasetArg(GDALArgDatasetValue *pValue,
|
|
GDALArgDatasetValueType type,
|
|
bool positionalAndRequired)
|
|
{
|
|
auto &arg = AddArg(GDAL_ARG_NAME_INPUT, 'i',
|
|
CPLSPrintf("Input %s dataset",
|
|
GDALArgDatasetValueTypeName(type).c_str()),
|
|
pValue, type);
|
|
if (positionalAndRequired)
|
|
arg.SetPositional().SetRequired();
|
|
return arg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddInputDatasetArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddInputDatasetArg(std::vector<GDALArgDatasetValue> *pValue,
|
|
GDALArgDatasetValueType type,
|
|
bool positionalAndRequired)
|
|
{
|
|
auto &arg = AddArg(GDAL_ARG_NAME_INPUT, 'i',
|
|
CPLSPrintf("Input %s datasets",
|
|
GDALArgDatasetValueTypeName(type).c_str()),
|
|
pValue, type);
|
|
if (positionalAndRequired)
|
|
arg.SetPositional().SetRequired();
|
|
return arg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddOutputDatasetArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddOutputDatasetArg(GDALArgDatasetValue *pValue,
|
|
GDALArgDatasetValueType type,
|
|
bool positionalAndRequired)
|
|
{
|
|
pValue->SetInputFlags(GADV_NAME);
|
|
pValue->SetOutputFlags(GADV_OBJECT);
|
|
auto &arg = AddArg(GDAL_ARG_NAME_OUTPUT, 'o',
|
|
CPLSPrintf("Output %s dataset",
|
|
GDALArgDatasetValueTypeName(type).c_str()),
|
|
pValue, type)
|
|
.SetIsInput(true)
|
|
.SetIsOutput(true);
|
|
if (positionalAndRequired)
|
|
arg.SetPositional().SetRequired();
|
|
return arg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddOverwriteArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &GDALAlgorithm::AddOverwriteArg(bool *pValue)
|
|
{
|
|
return AddArg("overwrite", 0,
|
|
_("Whether overwriting existing output is allowed"), pValue)
|
|
.SetDefault(false);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddUpdateArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &GDALAlgorithm::AddUpdateArg(bool *pValue)
|
|
{
|
|
return AddArg(GDAL_ARG_NAME_UPDATE, 0,
|
|
_("Whether to open existing dataset in update mode"), pValue)
|
|
.SetDefault(false);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddOpenOptionsArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddOpenOptionsArg(std::vector<std::string> *pValue)
|
|
{
|
|
return AddArg("open-option", 0, _("Open options"), pValue)
|
|
.AddAlias("oo")
|
|
.SetMetaVar("KEY=VALUE")
|
|
.SetCategory(GAAC_ADVANCED);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ValidateFormat() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithm::ValidateFormat(const GDALAlgorithmArg &arg) const
|
|
{
|
|
if (arg.GetChoices().empty())
|
|
{
|
|
const auto Validate = [this, &arg](const std::string &val)
|
|
{
|
|
auto hDriver = GDALGetDriverByName(val.c_str());
|
|
if (!hDriver)
|
|
{
|
|
ReportError(CE_Failure, CPLE_AppDefined,
|
|
"Invalid value for argument '%s'. Driver '%s' does "
|
|
"not exist",
|
|
arg.GetName().c_str(), val.c_str());
|
|
return false;
|
|
}
|
|
|
|
const auto caps = arg.GetMetadataItem(GAAMDI_REQUIRED_CAPABILITIES);
|
|
if (caps)
|
|
{
|
|
for (const std::string &cap : *caps)
|
|
{
|
|
if (!GDALGetMetadataItem(hDriver, cap.c_str(), nullptr))
|
|
{
|
|
if (cap == GDAL_DCAP_CREATECOPY &&
|
|
std::find(caps->begin(), caps->end(),
|
|
GDAL_DCAP_RASTER) != caps->end() &&
|
|
GDALGetMetadataItem(hDriver, GDAL_DCAP_RASTER,
|
|
nullptr) &&
|
|
GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE,
|
|
nullptr))
|
|
{
|
|
// if it supports Create, it supports CreateCopy
|
|
}
|
|
else
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Invalid value for argument '%s'. Driver '%s' "
|
|
"does "
|
|
"not expose the required '%s' capability.",
|
|
arg.GetName().c_str(), val.c_str(),
|
|
cap.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
if (arg.GetType() == GAAT_STRING)
|
|
{
|
|
return Validate(arg.Get<std::string>());
|
|
}
|
|
else if (arg.GetType() == GAAT_STRING_LIST)
|
|
{
|
|
for (const auto &val : arg.Get<std::vector<std::string>>())
|
|
{
|
|
if (!Validate(val))
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddInputFormatsArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddInputFormatsArg(std::vector<std::string> *pValue)
|
|
{
|
|
auto &arg = AddArg("input-format", 0, _("Input formats"), pValue)
|
|
.AddAlias("if")
|
|
.SetCategory(GAAC_ADVANCED);
|
|
arg.AddValidationAction([this, &arg]() { return ValidateFormat(arg); });
|
|
return arg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddOutputFormatArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddOutputFormatArg(std::string *pValue)
|
|
{
|
|
auto &arg = AddArg("output-format", 'f', _("Output format"), pValue)
|
|
.AddAlias("of")
|
|
.AddAlias("format");
|
|
arg.AddValidationAction([this, &arg]() { return ValidateFormat(arg); });
|
|
return arg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddOutputStringArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddOutputStringArg(std::string *pValue)
|
|
{
|
|
return AddArg("output-string", 0,
|
|
_("Output string, in which the result is placed"), pValue)
|
|
.SetHiddenForCLI()
|
|
.SetIsInput(false)
|
|
.SetIsOutput(true);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddLayerNameArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddLayerNameArg(std::string *pValue)
|
|
{
|
|
return AddArg("layer", 'l', _("Layer name"), pValue);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddLayerNameArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddLayerNameArg(std::vector<std::string> *pValue)
|
|
{
|
|
return AddArg("layer", 'l', _("Layer name"), pValue);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ValidateKeyValue() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithm::ValidateKeyValue(const GDALAlgorithmArg &arg) const
|
|
{
|
|
const auto Validate = [this, &arg](const std::string &val)
|
|
{
|
|
if (val.find('=') == std::string::npos)
|
|
{
|
|
ReportError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"Invalid value for argument '%s'. <KEY>=<VALUE> expected",
|
|
arg.GetName().c_str());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
if (arg.GetType() == GAAT_STRING)
|
|
{
|
|
return Validate(arg.Get<std::string>());
|
|
}
|
|
else if (arg.GetType() == GAAT_STRING_LIST)
|
|
{
|
|
for (const auto &val : arg.Get<std::vector<std::string>>())
|
|
{
|
|
if (!Validate(val))
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddCreationOptionsArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddCreationOptionsArg(std::vector<std::string> *pValue)
|
|
{
|
|
auto &arg = AddArg("creation-option", 0, _("Creation option"), pValue)
|
|
.AddAlias("co")
|
|
.SetMetaVar("<KEY>=<VALUE>");
|
|
arg.AddValidationAction([this, &arg]() { return ValidateKeyValue(arg); });
|
|
return arg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddLayerCreationOptionsArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &
|
|
GDALAlgorithm::AddLayerCreationOptionsArg(std::vector<std::string> *pValue)
|
|
{
|
|
auto &arg =
|
|
AddArg("layer-creation-option", 0, _("Layer creation option"), pValue)
|
|
.AddAlias("lco")
|
|
.SetMetaVar("<KEY>=<VALUE>");
|
|
arg.AddValidationAction([this, &arg]() { return ValidateKeyValue(arg); });
|
|
return arg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::AddProgressArg() */
|
|
/************************************************************************/
|
|
|
|
GDALInConstructionAlgorithmArg &GDALAlgorithm::AddProgressArg()
|
|
{
|
|
return AddArg("progress", 0, _("Display progress bar"),
|
|
&m_progressBarRequested)
|
|
.SetOnlyForCLI()
|
|
.SetCategory(GAAC_COMMON);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::Run() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithm::Run(GDALProgressFunc pfnProgress, void *pProgressData)
|
|
{
|
|
if (m_selectedSubAlg)
|
|
return m_selectedSubAlg->Run(pfnProgress, pProgressData);
|
|
|
|
if (m_helpRequested)
|
|
{
|
|
printf("%s", GetUsageForCLI(false).c_str()); /*ok*/
|
|
return true;
|
|
}
|
|
|
|
if (m_JSONUsageRequested)
|
|
{
|
|
printf("%s", GetUsageAsJSON().c_str()); /*ok*/
|
|
return true;
|
|
}
|
|
|
|
return ValidateArguments() && RunImpl(pfnProgress, pProgressData);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::Finalize() */
|
|
/************************************************************************/
|
|
|
|
bool GDALAlgorithm::Finalize()
|
|
{
|
|
if (m_selectedSubAlg)
|
|
return m_selectedSubAlg->Finalize();
|
|
|
|
bool ret = true;
|
|
for (auto &arg : m_args)
|
|
{
|
|
if (arg->GetType() == GAAT_DATASET)
|
|
{
|
|
ret = arg->Get<GDALArgDatasetValue>().Close() && ret;
|
|
}
|
|
else if (arg->GetType() == GAAT_DATASET_LIST)
|
|
{
|
|
for (auto &ds : arg->Get<std::vector<GDALArgDatasetValue>>())
|
|
{
|
|
ret = ds.Close() && ret;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::GetArgNamesForCLI() */
|
|
/************************************************************************/
|
|
|
|
std::pair<std::vector<std::pair<GDALAlgorithmArg *, std::string>>, size_t>
|
|
GDALAlgorithm::GetArgNamesForCLI() const
|
|
{
|
|
std::vector<std::pair<GDALAlgorithmArg *, std::string>> options;
|
|
|
|
size_t maxOptLen = 0;
|
|
for (const auto &arg : m_args)
|
|
{
|
|
if (arg->IsHiddenForCLI())
|
|
continue;
|
|
std::string opt;
|
|
bool addComma = false;
|
|
if (!arg->GetShortName().empty())
|
|
{
|
|
opt += '-';
|
|
opt += arg->GetShortName();
|
|
addComma = true;
|
|
}
|
|
for (const std::string &alias : arg->GetAliases())
|
|
{
|
|
if (addComma)
|
|
opt += ", ";
|
|
opt += "--";
|
|
opt += alias;
|
|
addComma = true;
|
|
}
|
|
if (!arg->GetName().empty())
|
|
{
|
|
if (addComma)
|
|
opt += ", ";
|
|
opt += "--";
|
|
opt += arg->GetName();
|
|
}
|
|
const auto &metaVar = arg->GetMetaVar();
|
|
if (!metaVar.empty())
|
|
{
|
|
opt += ' ';
|
|
if (metaVar.front() != '<')
|
|
opt += '<';
|
|
opt += metaVar;
|
|
if (metaVar.back() != '>')
|
|
opt += '>';
|
|
}
|
|
maxOptLen = std::max(maxOptLen, opt.size());
|
|
options.emplace_back(arg.get(), opt);
|
|
}
|
|
|
|
return std::make_pair(std::move(options), maxOptLen);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::GetUsageForCLI() */
|
|
/************************************************************************/
|
|
|
|
std::string
|
|
GDALAlgorithm::GetUsageForCLI(bool shortUsage,
|
|
const UsageOptions &usageOptions) const
|
|
{
|
|
if (m_selectedSubAlg)
|
|
return m_selectedSubAlg->GetUsageForCLI(shortUsage, usageOptions);
|
|
|
|
std::string osRet(usageOptions.isPipelineStep ? "*" : "Usage:");
|
|
std::string osPath;
|
|
for (const std::string &s : m_callPath)
|
|
{
|
|
if (!osPath.empty())
|
|
osPath += ' ';
|
|
osPath += s;
|
|
}
|
|
osRet += ' ';
|
|
osRet += osPath;
|
|
|
|
bool hasNonPositionals = false;
|
|
|
|
if (HasSubAlgorithms())
|
|
{
|
|
if (m_callPath.size() == 1)
|
|
{
|
|
osRet += " <COMMAND>\n";
|
|
osRet += "where <COMMAND> is one of:\n";
|
|
}
|
|
else
|
|
{
|
|
osRet += " <SUBCOMMAND>\n";
|
|
osRet += "where <SUBCOMMAND> is one of:\n";
|
|
}
|
|
size_t maxNameLen = 0;
|
|
for (const auto &subAlgName : GetSubAlgorithmNames())
|
|
{
|
|
maxNameLen = std::max(maxNameLen, subAlgName.size());
|
|
}
|
|
for (const auto &subAlgName : GetSubAlgorithmNames())
|
|
{
|
|
auto subAlg = InstantiateSubAlgorithm(subAlgName);
|
|
assert(subAlg);
|
|
const std::string &name(subAlg->GetName());
|
|
osRet += " - ";
|
|
osRet += name;
|
|
osRet += ": ";
|
|
osRet.append(maxNameLen - name.size(), ' ');
|
|
osRet += subAlg->GetDescription();
|
|
if (!subAlg->m_aliases.empty())
|
|
{
|
|
bool first = true;
|
|
for (const auto &alias : subAlg->GetAliases())
|
|
{
|
|
if (alias == GDALAlgorithmRegistry::HIDDEN_ALIAS_SEPARATOR)
|
|
break;
|
|
if (first)
|
|
osRet += " (alias: ";
|
|
else
|
|
osRet += ", ";
|
|
osRet += alias;
|
|
first = false;
|
|
}
|
|
if (!first)
|
|
{
|
|
osRet += ')';
|
|
}
|
|
}
|
|
osRet += '\n';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (const auto &arg : m_args)
|
|
{
|
|
if (!arg->IsHiddenForCLI() && !arg->IsPositional())
|
|
hasNonPositionals = true;
|
|
}
|
|
|
|
if (!m_args.empty())
|
|
{
|
|
if (hasNonPositionals)
|
|
osRet += " [OPTIONS]";
|
|
for (const auto *arg : m_positionalArgs)
|
|
{
|
|
osRet += " <";
|
|
osRet += arg->GetMetaVar();
|
|
osRet += '>';
|
|
}
|
|
}
|
|
|
|
const size_t nLenFirstLine = osRet.size();
|
|
osRet += '\n';
|
|
if (usageOptions.isPipelineStep)
|
|
{
|
|
osRet.append(nLenFirstLine, '-');
|
|
osRet += '\n';
|
|
}
|
|
|
|
if (shortUsage)
|
|
{
|
|
osRet += "Try '";
|
|
osRet += osPath;
|
|
osRet += " --help' for help.\n";
|
|
return osRet;
|
|
}
|
|
|
|
osRet += '\n';
|
|
osRet += m_description;
|
|
osRet += '\n';
|
|
}
|
|
|
|
if (!m_args.empty())
|
|
{
|
|
std::vector<std::pair<GDALAlgorithmArg *, std::string>> options;
|
|
size_t maxOptLen;
|
|
std::tie(options, maxOptLen) = GetArgNamesForCLI();
|
|
if (usageOptions.maxOptLen)
|
|
maxOptLen = usageOptions.maxOptLen;
|
|
|
|
const auto OutputArg =
|
|
[this, maxOptLen, &osRet](const GDALAlgorithmArg *arg,
|
|
const std::string &opt)
|
|
{
|
|
osRet += " ";
|
|
osRet += opt;
|
|
osRet += " ";
|
|
osRet.append(maxOptLen - opt.size(), ' ');
|
|
osRet += arg->GetDescription();
|
|
|
|
const auto &choices = arg->GetChoices();
|
|
if (!choices.empty())
|
|
{
|
|
osRet += ". ";
|
|
osRet += arg->GetMetaVar();
|
|
osRet += '=';
|
|
bool firstChoice = true;
|
|
for (const auto &choice : choices)
|
|
{
|
|
if (!firstChoice)
|
|
osRet += '|';
|
|
osRet += choice;
|
|
firstChoice = false;
|
|
}
|
|
}
|
|
|
|
if (arg->GetType() == GAAT_DATASET)
|
|
{
|
|
auto &val = arg->Get<GDALArgDatasetValue>();
|
|
if (val.GetInputFlags() == GADV_NAME &&
|
|
val.GetOutputFlags() == GADV_OBJECT)
|
|
{
|
|
osRet += " (created by algorithm)";
|
|
}
|
|
}
|
|
|
|
if (arg->GetType() == GAAT_STRING && arg->HasDefaultValue())
|
|
{
|
|
osRet += " (default: ";
|
|
osRet += arg->GetDefault<std::string>();
|
|
osRet += ')';
|
|
}
|
|
else if (arg->GetType() == GAAT_BOOLEAN && arg->HasDefaultValue())
|
|
{
|
|
if (arg->GetDefault<bool>())
|
|
osRet += " (default: true)";
|
|
}
|
|
else if (arg->GetType() == GAAT_INTEGER && arg->HasDefaultValue())
|
|
{
|
|
osRet += " (default: ";
|
|
osRet += CPLSPrintf("%d", arg->GetDefault<int>());
|
|
osRet += ')';
|
|
}
|
|
else if (arg->GetType() == GAAT_REAL && arg->HasDefaultValue())
|
|
{
|
|
osRet += " (default: ";
|
|
osRet += CPLSPrintf("%g", arg->GetDefault<double>());
|
|
osRet += ')';
|
|
}
|
|
|
|
if (arg->GetDisplayHintAboutRepetition())
|
|
{
|
|
if (arg->GetMinCount() > 0 &&
|
|
arg->GetMinCount() == arg->GetMaxCount())
|
|
{
|
|
osRet += CPLSPrintf(" [%d values]", arg->GetMaxCount());
|
|
}
|
|
else if (arg->GetMinCount() > 0 &&
|
|
arg->GetMaxCount() < GDALAlgorithmArgDecl::UNBOUNDED)
|
|
{
|
|
osRet += CPLSPrintf(" [%d..%d values]", arg->GetMinCount(),
|
|
arg->GetMaxCount());
|
|
}
|
|
else if (arg->GetMinCount() > 0)
|
|
{
|
|
osRet += CPLSPrintf(" [%d.. values]", arg->GetMinCount());
|
|
}
|
|
else if (arg->GetMaxCount() > 1)
|
|
{
|
|
osRet += " [may be repeated]";
|
|
}
|
|
}
|
|
|
|
if (arg->IsRequired())
|
|
{
|
|
osRet += " [required]";
|
|
}
|
|
|
|
osRet += '\n';
|
|
|
|
const auto &mutualExclusionGroup = arg->GetMutualExclusionGroup();
|
|
if (!mutualExclusionGroup.empty())
|
|
{
|
|
std::string otherArgs;
|
|
for (const auto &otherArg : m_args)
|
|
{
|
|
if (otherArg->IsHiddenForCLI() || otherArg.get() == arg)
|
|
continue;
|
|
if (otherArg->GetMutualExclusionGroup() ==
|
|
mutualExclusionGroup)
|
|
{
|
|
if (!otherArgs.empty())
|
|
otherArgs += ", ";
|
|
otherArgs += "--";
|
|
otherArgs += otherArg->GetName();
|
|
}
|
|
}
|
|
if (!otherArgs.empty())
|
|
{
|
|
osRet += " ";
|
|
osRet += " ";
|
|
osRet.append(maxOptLen, ' ');
|
|
osRet += "Mutually exclusive with ";
|
|
osRet += otherArgs;
|
|
osRet += '\n';
|
|
}
|
|
}
|
|
};
|
|
|
|
if (!m_positionalArgs.empty())
|
|
{
|
|
osRet += "\nPositional arguments:\n";
|
|
for (const auto &[arg, opt] : options)
|
|
{
|
|
if (arg->IsPositional())
|
|
OutputArg(arg, opt);
|
|
}
|
|
}
|
|
|
|
if (hasNonPositionals)
|
|
{
|
|
bool hasCommon = false;
|
|
bool hasBase = false;
|
|
bool hasAdvanced = false;
|
|
bool hasEsoteric = false;
|
|
std::vector<std::string> categories;
|
|
for (const auto &iter : options)
|
|
{
|
|
const auto &arg = iter.first;
|
|
if (!arg->IsPositional())
|
|
{
|
|
const auto &category = arg->GetCategory();
|
|
if (category == GAAC_COMMON)
|
|
{
|
|
hasCommon = true;
|
|
}
|
|
else if (category == GAAC_BASE)
|
|
{
|
|
hasBase = true;
|
|
}
|
|
else if (category == GAAC_ADVANCED)
|
|
{
|
|
hasAdvanced = true;
|
|
}
|
|
else if (category == GAAC_ESOTERIC)
|
|
{
|
|
hasEsoteric = true;
|
|
}
|
|
else if (std::find(categories.begin(), categories.end(),
|
|
category) == categories.end())
|
|
{
|
|
categories.push_back(category);
|
|
}
|
|
}
|
|
}
|
|
if (hasAdvanced)
|
|
categories.insert(categories.begin(), GAAC_ADVANCED);
|
|
if (hasBase)
|
|
categories.insert(categories.begin(), GAAC_BASE);
|
|
if (hasCommon && !usageOptions.isPipelineStep)
|
|
categories.insert(categories.begin(), GAAC_COMMON);
|
|
if (hasEsoteric)
|
|
categories.push_back(GAAC_ESOTERIC);
|
|
|
|
for (const auto &category : categories)
|
|
{
|
|
osRet += "\n";
|
|
if (category != GAAC_BASE)
|
|
{
|
|
osRet += category;
|
|
osRet += ' ';
|
|
}
|
|
osRet += "Options:\n";
|
|
for (const auto &[arg, opt] : options)
|
|
{
|
|
if (!arg->IsPositional() && arg->GetCategory() == category)
|
|
OutputArg(arg, opt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!m_longDescription.empty())
|
|
{
|
|
osRet += '\n';
|
|
osRet += m_longDescription;
|
|
osRet += '\n';
|
|
}
|
|
|
|
if (!m_helpURL.empty())
|
|
{
|
|
osRet += "\nFor more details, consult ";
|
|
osRet += GetHelpFullURL();
|
|
osRet += '\n';
|
|
}
|
|
|
|
return osRet;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithm::GetUsageAsJSON() */
|
|
/************************************************************************/
|
|
|
|
std::string GDALAlgorithm::GetUsageAsJSON() const
|
|
{
|
|
CPLJSONDocument oDoc;
|
|
auto oRoot = oDoc.GetRoot();
|
|
|
|
if (m_displayInJSONUsage)
|
|
{
|
|
oRoot.Add("name", m_name);
|
|
CPLJSONArray jFullPath;
|
|
for (const std::string &s : m_callPath)
|
|
{
|
|
jFullPath.Add(s);
|
|
}
|
|
oRoot.Add("full_path", jFullPath);
|
|
}
|
|
|
|
oRoot.Add("description", m_description);
|
|
if (!m_helpURL.empty())
|
|
{
|
|
oRoot.Add("short_url", m_helpURL);
|
|
oRoot.Add("url", GetHelpFullURL());
|
|
}
|
|
|
|
CPLJSONArray jSubAlgorithms;
|
|
for (const auto &subAlgName : GetSubAlgorithmNames())
|
|
{
|
|
auto subAlg = InstantiateSubAlgorithm(subAlgName);
|
|
assert(subAlg);
|
|
if (subAlg->m_displayInJSONUsage)
|
|
{
|
|
CPLJSONDocument oSubDoc;
|
|
oSubDoc.LoadMemory(subAlg->GetUsageAsJSON());
|
|
jSubAlgorithms.Add(oSubDoc.GetRoot());
|
|
}
|
|
}
|
|
oRoot.Add("sub_algorithms", jSubAlgorithms);
|
|
|
|
const auto ProcessArg = [](const GDALAlgorithmArg *arg)
|
|
{
|
|
CPLJSONObject jArg;
|
|
jArg.Add("name", arg->GetName());
|
|
jArg.Add("type", GDALAlgorithmArgTypeName(arg->GetType()));
|
|
jArg.Add("description", arg->GetDescription());
|
|
const auto &choices = arg->GetChoices();
|
|
if (!choices.empty())
|
|
{
|
|
CPLJSONArray jChoices;
|
|
for (const auto &choice : choices)
|
|
jChoices.Add(choice);
|
|
jArg.Add("choices", jChoices);
|
|
}
|
|
if (arg->HasDefaultValue())
|
|
{
|
|
switch (arg->GetType())
|
|
{
|
|
case GAAT_BOOLEAN:
|
|
jArg.Add("default", arg->GetDefault<bool>());
|
|
break;
|
|
case GAAT_STRING:
|
|
jArg.Add("default", arg->GetDefault<std::string>());
|
|
break;
|
|
case GAAT_INTEGER:
|
|
jArg.Add("default", arg->GetDefault<int>());
|
|
break;
|
|
case GAAT_REAL:
|
|
jArg.Add("default", arg->GetDefault<double>());
|
|
break;
|
|
case GAAT_DATASET:
|
|
case GAAT_STRING_LIST:
|
|
case GAAT_INTEGER_LIST:
|
|
case GAAT_REAL_LIST:
|
|
case GAAT_DATASET_LIST:
|
|
CPLError(CE_Warning, CPLE_AppDefined,
|
|
"Unhandled default value for arg %s",
|
|
arg->GetName().c_str());
|
|
break;
|
|
}
|
|
}
|
|
jArg.Add("required", arg->IsRequired());
|
|
if (GDALAlgorithmArgTypeIsList(arg->GetType()))
|
|
{
|
|
jArg.Add("packed_values_allowed", arg->GetPackedValuesAllowed());
|
|
jArg.Add("repeated_arg_allowed", arg->GetRepeatedArgAllowed());
|
|
jArg.Add("min_count", arg->GetMinCount());
|
|
jArg.Add("max_count", arg->GetMaxCount());
|
|
}
|
|
jArg.Add("category", arg->GetCategory());
|
|
|
|
if (arg->GetType() == GAAT_DATASET)
|
|
{
|
|
const auto &val = arg->Get<GDALArgDatasetValue>();
|
|
{
|
|
CPLJSONArray jAr;
|
|
if (val.GetType() & GDAL_OF_RASTER)
|
|
jAr.Add("raster");
|
|
if (val.GetType() & GDAL_OF_VECTOR)
|
|
jAr.Add("vector");
|
|
if (val.GetType() & GDAL_OF_MULTIDIM_RASTER)
|
|
jAr.Add("muldim_raster");
|
|
jArg.Add("dataset_type", jAr);
|
|
}
|
|
|
|
const auto GetFlags = [](int flags)
|
|
{
|
|
CPLJSONArray jAr;
|
|
if (flags & GADV_NAME)
|
|
jAr.Add("name");
|
|
if (flags & GADV_OBJECT)
|
|
jAr.Add("dataset");
|
|
return jAr;
|
|
};
|
|
|
|
if (arg->IsInput())
|
|
{
|
|
jArg.Add("input_flags", GetFlags(val.GetInputFlags()));
|
|
}
|
|
if (arg->IsOutput())
|
|
{
|
|
jArg.Add("output_flags", GetFlags(val.GetOutputFlags()));
|
|
}
|
|
}
|
|
|
|
const auto &mutualExclusionGroup = arg->GetMutualExclusionGroup();
|
|
if (!mutualExclusionGroup.empty())
|
|
{
|
|
jArg.Add("mutual_exclusion_group", mutualExclusionGroup);
|
|
}
|
|
|
|
const auto &metadata = arg->GetMetadata();
|
|
if (!metadata.empty())
|
|
{
|
|
CPLJSONObject jMetadata;
|
|
for (const auto &[key, values] : metadata)
|
|
{
|
|
CPLJSONArray jValue;
|
|
for (const auto &value : values)
|
|
jValue.Add(value);
|
|
jMetadata.Add(key, jValue);
|
|
}
|
|
jArg.Add("metadata", jMetadata);
|
|
}
|
|
|
|
return jArg;
|
|
};
|
|
|
|
{
|
|
CPLJSONArray jArgs;
|
|
for (const auto &arg : m_args)
|
|
{
|
|
if (!arg->IsOnlyForCLI() && arg->IsInput() && !arg->IsOutput())
|
|
jArgs.Add(ProcessArg(arg.get()));
|
|
}
|
|
oRoot.Add("input_arguments", jArgs);
|
|
}
|
|
|
|
{
|
|
CPLJSONArray jArgs;
|
|
for (const auto &arg : m_args)
|
|
{
|
|
if (!arg->IsOnlyForCLI() && !arg->IsInput() && arg->IsOutput())
|
|
jArgs.Add(ProcessArg(arg.get()));
|
|
}
|
|
oRoot.Add("output_arguments", jArgs);
|
|
}
|
|
|
|
{
|
|
CPLJSONArray jArgs;
|
|
for (const auto &arg : m_args)
|
|
{
|
|
if (!arg->IsOnlyForCLI() && arg->IsInput() && arg->IsOutput())
|
|
jArgs.Add(ProcessArg(arg.get()));
|
|
}
|
|
oRoot.Add("input_output_arguments", jArgs);
|
|
}
|
|
|
|
return oDoc.SaveAsString();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmRelease() */
|
|
/************************************************************************/
|
|
|
|
/** Release a handle to an algorithm.
|
|
*
|
|
* @since 3.11
|
|
*/
|
|
void GDALAlgorithmRelease(GDALAlgorithmH hAlg)
|
|
{
|
|
delete hAlg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetName() */
|
|
/************************************************************************/
|
|
|
|
/** Return the algorithm name.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return algorithm name whose lifetime is bound to hAlg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmGetName(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
return hAlg->ptr->GetName().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetDescription() */
|
|
/************************************************************************/
|
|
|
|
/** Return the algorithm (short) description.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return algorithm description whose lifetime is bound to hAlg and which must
|
|
* not be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmGetDescription(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
return hAlg->ptr->GetDescription().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetLongDescription() */
|
|
/************************************************************************/
|
|
|
|
/** Return the algorithm (longer) description.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return algorithm description whose lifetime is bound to hAlg and which must
|
|
* not be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmGetLongDescription(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
return hAlg->ptr->GetLongDescription().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetHelpFullURL() */
|
|
/************************************************************************/
|
|
|
|
/** Return the algorithm full URL.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return algorithm URL whose lifetime is bound to hAlg and which must
|
|
* not be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmGetHelpFullURL(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
return hAlg->ptr->GetHelpFullURL().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmHasSubAlgorithms() */
|
|
/************************************************************************/
|
|
|
|
/** Return whether the algorithm has sub-algorithms.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmHasSubAlgorithms(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, false);
|
|
return hAlg->ptr->HasSubAlgorithms();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetSubAlgorithmNames() */
|
|
/************************************************************************/
|
|
|
|
/** Get the names of registered algorithms.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return a NULL terminated list of names, which must be destroyed with
|
|
* CSLDestroy()
|
|
* @since 3.11
|
|
*/
|
|
char **GDALAlgorithmGetSubAlgorithmNames(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
return CPLStringList(hAlg->ptr->GetSubAlgorithmNames()).StealList();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmInstantiateSubAlgorithm() */
|
|
/************************************************************************/
|
|
|
|
/** Instantiate an algorithm by its name (or its alias).
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @param pszSubAlgName Algorithm name. Must NOT be null.
|
|
* @return an handle to the algorithm (to be freed with GDALAlgorithmRelease),
|
|
* or NULL if the algorithm does not exist or another error occurred.
|
|
* @since 3.11
|
|
*/
|
|
GDALAlgorithmH GDALAlgorithmInstantiateSubAlgorithm(GDALAlgorithmH hAlg,
|
|
const char *pszSubAlgName)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
VALIDATE_POINTER1(pszSubAlgName, __func__, nullptr);
|
|
auto subAlg = hAlg->ptr->InstantiateSubAlgorithm(pszSubAlgName);
|
|
return subAlg
|
|
? std::make_unique<GDALAlgorithmHS>(std::move(subAlg)).release()
|
|
: nullptr;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmParseCommandLineArguments() */
|
|
/************************************************************************/
|
|
|
|
/** Parse a command line argument, which does not include the algorithm
|
|
* name, to set the value of corresponding arguments.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @param papszArgs NULL-terminated list of arguments, not including the algorithm name.
|
|
* @return true if successful, false otherwise
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmParseCommandLineArguments(GDALAlgorithmH hAlg,
|
|
CSLConstList papszArgs)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, false);
|
|
return hAlg->ptr->ParseCommandLineArguments(CPLStringList(papszArgs));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetActualAlgorithm() */
|
|
/************************************************************************/
|
|
|
|
/** Return the actual algorithm that is going to be invoked, when the
|
|
* current algorithm has sub-algorithms.
|
|
*
|
|
* Only valid after GDALAlgorithmParseCommandLineArguments() has been called.
|
|
*
|
|
* Note that the lifetime of the returned algorithm does not exceed the one of
|
|
* the hAlg instance that owns it.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return an handle to the algorithm (to be freed with GDALAlgorithmRelease).
|
|
* @since 3.11
|
|
*/
|
|
GDALAlgorithmH GDALAlgorithmGetActualAlgorithm(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
return GDALAlgorithmHS::FromRef(hAlg->ptr->GetActualAlgorithm()).release();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmRun() */
|
|
/************************************************************************/
|
|
|
|
/** Execute the algorithm, starting with ValidateArguments() and then
|
|
* calling RunImpl().
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @param pfnProgress Progress callback. May be null.
|
|
* @param pProgressData Progress callback user data. May be null.
|
|
* @return true if successful, false otherwise
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmRun(GDALAlgorithmH hAlg, GDALProgressFunc pfnProgress,
|
|
void *pProgressData)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, false);
|
|
return hAlg->ptr->Run(pfnProgress, pProgressData);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmFinalize() */
|
|
/************************************************************************/
|
|
|
|
/** Complete any pending actions, and return the final status.
|
|
* This is typically useful for algorithm that generate an output dataset.
|
|
*
|
|
* Note that this function does *NOT* release memory associated with the
|
|
* algorithm. GDALAlgorithmRelease() must still be called afterwards.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return true if successful, false otherwise
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmFinalize(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, false);
|
|
return hAlg->ptr->Finalize();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetUsageAsJSON() */
|
|
/************************************************************************/
|
|
|
|
/** Return the usage of the algorithm as a JSON-serialized string.
|
|
*
|
|
* This can be used to dynamically generate interfaces to algorithms.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return a string that must be freed with CPLFree()
|
|
* @since 3.11
|
|
*/
|
|
char *GDALAlgorithmGetUsageAsJSON(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
return CPLStrdup(hAlg->ptr->GetUsageAsJSON().c_str());
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetArgNames() */
|
|
/************************************************************************/
|
|
|
|
/** Return the list of available argument names.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @return a NULL terminated list of names, which must be destroyed with
|
|
* CSLDestroy()
|
|
* @since 3.11
|
|
*/
|
|
char **GDALAlgorithmGetArgNames(GDALAlgorithmH hAlg)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
CPLStringList list;
|
|
for (const auto &arg : hAlg->ptr->GetArgs())
|
|
list.AddString(arg->GetName().c_str());
|
|
return list.StealList();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmGetArg() */
|
|
/************************************************************************/
|
|
|
|
/** Return an argument from its name.
|
|
*
|
|
* The lifetime of the returned object does not exceed the one of hAlg.
|
|
*
|
|
* @param hAlg Handle to an algorithm. Must NOT be null.
|
|
* @param pszArgName Argument name. Must NOT be null.
|
|
* @return an argument that must be released with GDALAlgorithmArgRelease(),
|
|
* or nullptr in case of error
|
|
* @since 3.11
|
|
*/
|
|
GDALAlgorithmArgH GDALAlgorithmGetArg(GDALAlgorithmH hAlg,
|
|
const char *pszArgName)
|
|
{
|
|
VALIDATE_POINTER1(hAlg, __func__, nullptr);
|
|
VALIDATE_POINTER1(pszArgName, __func__, nullptr);
|
|
auto arg = hAlg->ptr->GetArg(pszArgName);
|
|
if (!arg)
|
|
return nullptr;
|
|
return std::make_unique<GDALAlgorithmArgHS>(arg).release();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgRelease() */
|
|
/************************************************************************/
|
|
|
|
/** Release a handle to an argument.
|
|
*
|
|
* @since 3.11
|
|
*/
|
|
void GDALAlgorithmArgRelease(GDALAlgorithmArgH hArg)
|
|
{
|
|
delete hArg;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetName() */
|
|
/************************************************************************/
|
|
|
|
/** Return the name of an argument.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return argument name whose lifetime is bound to hArg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmArgGetName(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
return hArg->ptr->GetName().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetType() */
|
|
/************************************************************************/
|
|
|
|
/** Get the type of an argument
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
GDALAlgorithmArgType GDALAlgorithmArgGetType(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, GAAT_STRING);
|
|
return hArg->ptr->GetType();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetDescription() */
|
|
/************************************************************************/
|
|
|
|
/** Return the description of an argument.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return argument descriptioin whose lifetime is bound to hArg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmArgGetDescription(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
return hArg->ptr->GetDescription().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetShortName() */
|
|
/************************************************************************/
|
|
|
|
/** Return the short name, or empty string if there is none
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return short name whose lifetime is bound to hArg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmArgGetShortName(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
return hArg->ptr->GetShortName().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAliases() */
|
|
/************************************************************************/
|
|
|
|
/** Return the aliases (potentially none)
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return a NULL terminated list of names, which must be destroyed with
|
|
* CSLDestroy()
|
|
|
|
* @since 3.11
|
|
*/
|
|
char **GDALAlgorithmArgGetAliases(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
return CPLStringList(hArg->ptr->GetAliases()).StealList();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetMetaVar() */
|
|
/************************************************************************/
|
|
|
|
/** Return the "meta-var" hint.
|
|
*
|
|
* By default, the meta-var value is the long name of the argument in
|
|
* upper case.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return meta-var hint whose lifetime is bound to hArg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmArgGetMetaVar(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
return hArg->ptr->GetMetaVar().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetCategory() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument category
|
|
*
|
|
* GAAC_COMMON, GAAC_BASE, GAAC_ADVANCED, GAAC_ESOTERIC or a custom category.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return category whose lifetime is bound to hArg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmArgGetCategory(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
return hArg->ptr->GetCategory().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgIsPositional() */
|
|
/************************************************************************/
|
|
|
|
/** Return if the argument is a positional one.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgIsPositional(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->IsPositional();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgIsRequired() */
|
|
/************************************************************************/
|
|
|
|
/** Return whether the argument is required. Defaults to false.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgIsRequired(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->IsRequired();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetMinCount() */
|
|
/************************************************************************/
|
|
|
|
/** Return the minimum number of values for the argument.
|
|
*
|
|
* Defaults to 0.
|
|
* Only applies to list type of arguments.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
int GDALAlgorithmArgGetMinCount(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, 0);
|
|
return hArg->ptr->GetMinCount();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetMaxCount() */
|
|
/************************************************************************/
|
|
|
|
/** Return the maximum number of values for the argument.
|
|
*
|
|
* Defaults to 1 for scalar types, and INT_MAX for list types.
|
|
* Only applies to list type of arguments.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
int GDALAlgorithmArgGetMaxCount(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, 0);
|
|
return hArg->ptr->GetMaxCount();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetPackedValuesAllowed() */
|
|
/************************************************************************/
|
|
|
|
/** Return whether, for list type of arguments, several values, space
|
|
* separated, may be specified. That is "--foo=bar,baz".
|
|
* The default is true.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgGetPackedValuesAllowed(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->GetPackedValuesAllowed();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetRepeatedArgAllowed() */
|
|
/************************************************************************/
|
|
|
|
/** Return whether, for list type of arguments, the argument may be
|
|
* repeated. That is "--foo=bar --foo=baz".
|
|
* The default is true.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgGetRepeatedArgAllowed(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->GetRepeatedArgAllowed();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetChoices() */
|
|
/************************************************************************/
|
|
|
|
/** Return the allowed values (as strings) for the argument.
|
|
*
|
|
* Only honored for GAAT_STRING and GAAT_STRING_LIST types.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return a NULL terminated list of names, which must be destroyed with
|
|
* CSLDestroy()
|
|
|
|
* @since 3.11
|
|
*/
|
|
char **GDALAlgorithmArgGetChoices(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
return CPLStringList(hArg->ptr->GetChoices()).StealList();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgIsExplicitlySet() */
|
|
/************************************************************************/
|
|
|
|
/** Return whether the argument value has been explicitly set with Set()
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgIsExplicitlySet(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->IsExplicitlySet();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgHasDefaultValue() */
|
|
/************************************************************************/
|
|
|
|
/** Return if the argument has a declared default value.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgHasDefaultValue(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->HasDefaultValue();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgIsHiddenForCLI() */
|
|
/************************************************************************/
|
|
|
|
/** Return whether the argument must not be mentioned in CLI usage.
|
|
*
|
|
* For example, "output-value" for "gdal raster info", which is only
|
|
* meant when the algorithm is used from a non-CLI context.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgIsHiddenForCLI(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->IsHiddenForCLI();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgIsOnlyForCLI() */
|
|
/************************************************************************/
|
|
|
|
/** Return whether the argument is only for CLI usage.
|
|
*
|
|
* For example "--help"
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgIsOnlyForCLI(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->IsOnlyForCLI();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgIsInput() */
|
|
/************************************************************************/
|
|
|
|
/** Indicate whether the value of the argument is read-only during the
|
|
* execution of the algorithm.
|
|
*
|
|
* Default is true.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgIsInput(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->IsInput();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgIsOutput() */
|
|
/************************************************************************/
|
|
|
|
/** Return whether (at least part of) the value of the argument is set
|
|
* during the execution of the algorithm.
|
|
*
|
|
* For example, "output-value" for "gdal raster info"
|
|
* Default is false.
|
|
* An argument may return both IsInput() and IsOutput() as true.
|
|
* For example the "gdal raster convert" algorithm consumes the dataset
|
|
* name of its "output" argument, and sets the dataset object during its
|
|
* execution.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgIsOutput(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->IsOutput();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetMutualExclusionGroup() */
|
|
/************************************************************************/
|
|
|
|
/** Return the name of the mutual exclusion group to which this argument
|
|
* belongs to.
|
|
*
|
|
* Or empty string if it does not belong to any exclusion group.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return string whose lifetime is bound to hArg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmArgGetMutualExclusionGroup(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
return hArg->ptr->GetMutualExclusionGroup().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAsBoolean() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument value as a boolean.
|
|
*
|
|
* Must only be called on arguments whose type is GAAT_BOOLEAN.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgGetAsBoolean(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
if (hArg->ptr->GetType() != GAAT_BOOLEAN)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"%s must only be called on arguments of type GAAT_BOOLEAN",
|
|
__func__);
|
|
return false;
|
|
}
|
|
return hArg->ptr->Get<bool>();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAsBoolean() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument value as a string.
|
|
*
|
|
* Must only be called on arguments whose type is GAAT_STRING.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return string whose lifetime is bound to hArg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALAlgorithmArgGetAsString(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
if (hArg->ptr->GetType() != GAAT_STRING)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"%s must only be called on arguments of type GAAT_STRING",
|
|
__func__);
|
|
return nullptr;
|
|
}
|
|
return hArg->ptr->Get<std::string>().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAsDatasetValue() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument value as a GDALArgDatasetValueH.
|
|
*
|
|
* Must only be called on arguments whose type is GAAT_DATASET
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return handle to a GDALArgDatasetValue that must be released with
|
|
* GDALArgDatasetValueRelease(). The lifetime of that handle does not exceed
|
|
* the one of hArg.
|
|
* @since 3.11
|
|
*/
|
|
GDALArgDatasetValueH GDALAlgorithmArgGetAsDatasetValue(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
if (hArg->ptr->GetType() != GAAT_DATASET)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"%s must only be called on arguments of type GAAT_DATASET",
|
|
__func__);
|
|
return nullptr;
|
|
}
|
|
return std::make_unique<GDALArgDatasetValueHS>(
|
|
&(hArg->ptr->Get<GDALArgDatasetValue>()))
|
|
.release();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAsInteger() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument value as a integer.
|
|
*
|
|
* Must only be called on arguments whose type is GAAT_INTEGER
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
int GDALAlgorithmArgGetAsInteger(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, 0);
|
|
if (hArg->ptr->GetType() != GAAT_INTEGER)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"%s must only be called on arguments of type GAAT_INTEGER",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
return hArg->ptr->Get<int>();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAsDouble() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument value as a double.
|
|
*
|
|
* Must only be called on arguments whose type is GAAT_REAL
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
double GDALAlgorithmArgGetAsDouble(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, 0);
|
|
if (hArg->ptr->GetType() != GAAT_REAL)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"%s must only be called on arguments of type GAAT_REAL",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
return hArg->ptr->Get<double>();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAsStringList() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument value as a double.
|
|
*
|
|
* Must only be called on arguments whose type is GAAT_STRING_LIST.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @return a NULL terminated list of names, which must be destroyed with
|
|
* CSLDestroy()
|
|
|
|
* @since 3.11
|
|
*/
|
|
char **GDALAlgorithmArgGetAsStringList(GDALAlgorithmArgH hArg)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
if (hArg->ptr->GetType() != GAAT_STRING_LIST)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"%s must only be called on arguments of type GAAT_STRING_LIST",
|
|
__func__);
|
|
return nullptr;
|
|
}
|
|
return CPLStringList(hArg->ptr->Get<std::vector<std::string>>())
|
|
.StealList();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAsIntegerList() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument value as a integer.
|
|
*
|
|
* Must only be called on arguments whose type is GAAT_INTEGER
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param[out] pnCount Pointer to the number of values in the list. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
const int *GDALAlgorithmArgGetAsIntegerList(GDALAlgorithmArgH hArg,
|
|
size_t *pnCount)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
VALIDATE_POINTER1(pnCount, __func__, nullptr);
|
|
if (hArg->ptr->GetType() != GAAT_INTEGER_LIST)
|
|
{
|
|
CPLError(
|
|
CE_Failure, CPLE_AppDefined,
|
|
"%s must only be called on arguments of type GAAT_INTEGER_LIST",
|
|
__func__);
|
|
*pnCount = 0;
|
|
return nullptr;
|
|
}
|
|
const auto &val = hArg->ptr->Get<std::vector<int>>();
|
|
*pnCount = val.size();
|
|
return val.data();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgGetAsDoubleList() */
|
|
/************************************************************************/
|
|
|
|
/** Return the argument value as a integer.
|
|
*
|
|
* Must only be called on arguments whose type is GAAT_INTEGER
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param[out] pnCount Pointer to the number of values in the list. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
const double *GDALAlgorithmArgGetAsDoubleList(GDALAlgorithmArgH hArg,
|
|
size_t *pnCount)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, nullptr);
|
|
VALIDATE_POINTER1(pnCount, __func__, nullptr);
|
|
if (hArg->ptr->GetType() != GAAT_REAL_LIST)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"%s must only be called on arguments of type GAAT_REAL_LIST",
|
|
__func__);
|
|
*pnCount = 0;
|
|
return nullptr;
|
|
}
|
|
const auto &val = hArg->ptr->Get<std::vector<double>>();
|
|
*pnCount = val.size();
|
|
return val.data();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetAsBoolean() */
|
|
/************************************************************************/
|
|
|
|
/** Set the value for a GAAT_BOOLEAN argument.
|
|
*
|
|
* It cannot be called several times for a given argument.
|
|
* Validation checks and other actions are run.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param value value.
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmArgSetAsBoolean(GDALAlgorithmArgH hArg, bool value)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(value);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetAsString() */
|
|
/************************************************************************/
|
|
|
|
/** Set the value for a GAAT_STRING argument.
|
|
*
|
|
* It cannot be called several times for a given argument.
|
|
* Validation checks and other actions are run.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param value value (may be null)
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmArgSetAsString(GDALAlgorithmArgH hArg, const char *value)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(value ? value : "");
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetAsInteger() */
|
|
/************************************************************************/
|
|
|
|
/** Set the value for a GAAT_INTEGER (or GAAT_REAL) argument.
|
|
*
|
|
* It cannot be called several times for a given argument.
|
|
* Validation checks and other actions are run.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param value value.
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmArgSetAsInteger(GDALAlgorithmArgH hArg, int value)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(value);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetAsDouble() */
|
|
/************************************************************************/
|
|
|
|
/** Set the value for a GAAT_REAL argument.
|
|
*
|
|
* It cannot be called several times for a given argument.
|
|
* Validation checks and other actions are run.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param value value.
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmArgSetAsDouble(GDALAlgorithmArgH hArg, double value)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(value);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetAsDatasetValue() */
|
|
/************************************************************************/
|
|
|
|
/** Set the value for a GAAT_DATASET argument.
|
|
*
|
|
* It cannot be called several times for a given argument.
|
|
* Validation checks and other actions are run.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param value Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgSetAsDatasetValue(GDALAlgorithmArgH hArg,
|
|
GDALArgDatasetValueH value)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
VALIDATE_POINTER1(value, __func__, false);
|
|
return hArg->ptr->SetFrom(*(value->ptr));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetDatasetWithoutOwnership() */
|
|
/************************************************************************/
|
|
|
|
/** Set dataset object, but without transferring ownership to hArg.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param hDS Dataset object. May be null.
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmArgSetDatasetWithoutOwnership(GDALAlgorithmArgH hArg,
|
|
GDALDatasetH hDS)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(GDALDataset::FromHandle(hDS), false);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetDatasetWithOwnership() */
|
|
/************************************************************************/
|
|
|
|
/** Set dataset object, and transfer its ownership to hArg.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param hDS Dataset object. May be null.
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmArgSetDatasetWithOwnership(GDALAlgorithmArgH hArg,
|
|
GDALDatasetH hDS)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(GDALDataset::FromHandle(hDS), false);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetAsStringList() */
|
|
/************************************************************************/
|
|
|
|
/** Set the value for a GAAT_STRING_LIST argument.
|
|
*
|
|
* It cannot be called several times for a given argument.
|
|
* Validation checks and other actions are run.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param value value (may be null)
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
|
|
bool GDALAlgorithmArgSetAsStringList(GDALAlgorithmArgH hArg, CSLConstList value)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(
|
|
static_cast<std::vector<std::string>>(CPLStringList(value)));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetAsIntegerList() */
|
|
/************************************************************************/
|
|
|
|
/** Set the value for a GAAT_INTEGER_LIST argument.
|
|
*
|
|
* It cannot be called several times for a given argument.
|
|
* Validation checks and other actions are run.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param nCount Number of values in pnValues.
|
|
* @param pnValues Pointer to an array of integer values of size nCount.
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgSetAsIntegerList(GDALAlgorithmArgH hArg, size_t nCount,
|
|
const int *pnValues)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(std::vector<int>(pnValues, pnValues + nCount));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALAlgorithmArgSetAsDoubleList() */
|
|
/************************************************************************/
|
|
|
|
/** Set the value for a GAAT_REAL_LIST argument.
|
|
*
|
|
* It cannot be called several times for a given argument.
|
|
* Validation checks and other actions are run.
|
|
*
|
|
* @param hArg Handle to an argument. Must NOT be null.
|
|
* @param nCount Number of values in pnValues.
|
|
* @param pnValues Pointer to an array of double values of size nCount.
|
|
* @return true if success.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALAlgorithmArgSetAsDoubleList(GDALAlgorithmArgH hArg, size_t nCount,
|
|
const double *pnValues)
|
|
{
|
|
VALIDATE_POINTER1(hArg, __func__, false);
|
|
return hArg->ptr->Set(std::vector<double>(pnValues, pnValues + nCount));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueCreate() */
|
|
/************************************************************************/
|
|
|
|
/** Instantiate an empty GDALArgDatasetValue
|
|
*
|
|
* @return new handle to free with GDALArgDatasetValueRelease()
|
|
* @since 3.11
|
|
*/
|
|
GDALArgDatasetValueH GDALArgDatasetValueCreate()
|
|
{
|
|
return std::make_unique<GDALArgDatasetValueHS>().release();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueRelease() */
|
|
/************************************************************************/
|
|
|
|
/** Release a handle to a GDALArgDatasetValue
|
|
*
|
|
* @since 3.11
|
|
*/
|
|
void GDALArgDatasetValueRelease(GDALArgDatasetValueH hValue)
|
|
{
|
|
delete hValue;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueGetName() */
|
|
/************************************************************************/
|
|
|
|
/** Return the name component of the GDALArgDatasetValue
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @return string whose lifetime is bound to hAlg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
const char *GDALArgDatasetValueGetName(GDALArgDatasetValueH hValue)
|
|
{
|
|
VALIDATE_POINTER1(hValue, __func__, nullptr);
|
|
return hValue->ptr->GetName().c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueGetDataset() */
|
|
/************************************************************************/
|
|
|
|
/** Return the dataset component of the GDALArgDatasetValue
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
GDALDatasetH GDALArgDatasetValueGetDataset(GDALArgDatasetValueH hValue)
|
|
{
|
|
VALIDATE_POINTER1(hValue, __func__, nullptr);
|
|
return GDALDataset::ToHandle(hValue->ptr->GetDataset());
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueIsDatasetOwned() */
|
|
/************************************************************************/
|
|
|
|
/** Returns whether the dataset object referenced in this object is owned
|
|
* by this object (and thus released by it when it is destroyed).
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
bool GDALArgDatasetValueIsDatasetOwned(GDALArgDatasetValueH hValue)
|
|
{
|
|
VALIDATE_POINTER1(hValue, __func__, false);
|
|
return hValue->ptr->IsOwned();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueGetType() */
|
|
/************************************************************************/
|
|
|
|
/** Get which type of dataset is allowed / generated.
|
|
*
|
|
* Binary-or combination of GDAL_OF_RASTER, GDAL_OF_VECTOR and
|
|
* GDAL_OF_MULTIDIM_RASTER.
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @since 3.11
|
|
*/
|
|
GDALArgDatasetValueType GDALArgDatasetValueGetType(GDALArgDatasetValueH hValue)
|
|
{
|
|
VALIDATE_POINTER1(hValue, __func__, 0);
|
|
return hValue->ptr->GetType();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueGetInputFlags() */
|
|
/************************************************************************/
|
|
|
|
/** Indicates which components among name and dataset are accepted as
|
|
* input, when this argument serves as an input.
|
|
*
|
|
* If the GADV_NAME bit is set, it indicates a dataset name is accepted as
|
|
* input.
|
|
* If the GADV_OBJECT bit is set, it indicates a dataset object is
|
|
* accepted as input.
|
|
* If both bits are set, the algorithm can accept either a name or a dataset
|
|
* object.
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @return string whose lifetime is bound to hAlg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
int GDALArgDatasetValueGetInputFlags(GDALArgDatasetValueH hValue)
|
|
{
|
|
VALIDATE_POINTER1(hValue, __func__, 0);
|
|
return hValue->ptr->GetInputFlags();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueGetOutputFlags() */
|
|
/************************************************************************/
|
|
|
|
/** Indicates which components among name and dataset are modified,
|
|
* when this argument serves as an output.
|
|
*
|
|
* If the GADV_NAME bit is set, it indicates a dataset name is generated as
|
|
* output (that is the algorithm will generate the name. Rarely used).
|
|
* If the GADV_OBJECT bit is set, it indicates a dataset object is
|
|
* generated as output, and available for use after the algorithm has
|
|
* completed.
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @return string whose lifetime is bound to hAlg and which must not
|
|
* be freed.
|
|
* @since 3.11
|
|
*/
|
|
int GDALArgDatasetValueGetOutputFlags(GDALArgDatasetValueH hValue)
|
|
{
|
|
VALIDATE_POINTER1(hValue, __func__, 0);
|
|
return hValue->ptr->GetOutputFlags();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueSetName() */
|
|
/************************************************************************/
|
|
|
|
/** Set dataset name
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @param pszName Dataset name. May be null.
|
|
* @since 3.11
|
|
*/
|
|
|
|
void GDALArgDatasetValueSetName(GDALArgDatasetValueH hValue,
|
|
const char *pszName)
|
|
{
|
|
VALIDATE_POINTER0(hValue, __func__);
|
|
hValue->ptr->Set(pszName ? pszName : "");
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueSetDatasetWithoutOwnership() */
|
|
/************************************************************************/
|
|
|
|
/** Set dataset object, but without transferring ownership to hValue.
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @param hDS Dataset object. May be null.
|
|
* @since 3.11
|
|
*/
|
|
|
|
void GDALArgDatasetValueSetDatasetWithoutOwnership(GDALArgDatasetValueH hValue,
|
|
GDALDatasetH hDS)
|
|
{
|
|
VALIDATE_POINTER0(hValue, __func__);
|
|
hValue->ptr->Set(GDALDataset::FromHandle(hDS), false);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALArgDatasetValueSetDatasetWithOwnership() */
|
|
/************************************************************************/
|
|
|
|
/** Set dataset object, and transfer its ownership to hValue.
|
|
*
|
|
* @param hValue Handle to a GDALArgDatasetValue. Must NOT be null.
|
|
* @param hDS Dataset object. May be null.
|
|
* @since 3.11
|
|
*/
|
|
|
|
void GDALArgDatasetValueSetDatasetWithOwnership(GDALArgDatasetValueH hValue,
|
|
GDALDatasetH hDS)
|
|
{
|
|
VALIDATE_POINTER0(hValue, __func__);
|
|
hValue->ptr->Set(GDALDataset::FromHandle(hDS), true);
|
|
}
|