Skip to content

Commit c1df1ac

Browse files
authored
Merge pull request #11303 from rouault/rfc104
Candidate implementation for RFC 104: Adding a "gdal" front-end command line interface
2 parents ebded33 + 671d2e6 commit c1df1ac

File tree

83 files changed

+16108
-70
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+16108
-70
lines changed

apps/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ add_library(
66
commonutils.h
77
gdal_utils.h
88
gdalargumentparser.cpp
9+
gdalalg_convert.cpp
10+
gdalalg_info.cpp
11+
gdalalg_main.cpp
12+
gdalalg_pipeline.cpp
13+
gdalalg_raster.cpp
14+
gdalalg_raster_info.cpp
15+
gdalalg_raster_convert.cpp
16+
gdalalg_vector.cpp
17+
gdalalg_vector_info.cpp
18+
gdalalg_vector_convert.cpp
19+
gdalalg_vector_pipeline.cpp
20+
gdalalg_vector_read.cpp
21+
gdalalg_vector_filter.cpp
22+
gdalalg_vector_reproject.cpp
23+
gdalalg_vector_write.cpp
924
gdalinfo_lib.cpp
1025
gdalbuildvrt_lib.cpp
1126
gdal_grid_lib.cpp
@@ -49,6 +64,7 @@ target_public_header(TARGET ${GDAL_LIB_TARGET_NAME} HEADERS gdal_utils.h)
4964

5065
if (BUILD_APPS)
5166
# Default Apps
67+
add_executable(gdal gdal_utils_priv.h gdal.cpp)
5268
add_executable(gdalinfo gdal_utils_priv.h gdalinfo_bin.cpp)
5369
add_executable(gdalbuildvrt gdal_utils_priv.h gdalbuildvrt_bin.cpp)
5470
add_executable(gdaladdo gdal_utils_priv.h gdaladdo.cpp)
@@ -89,6 +105,7 @@ if (BUILD_APPS)
89105
add_dependencies(utils_common generate_gdal_version_h)
90106

91107
set(APPS_TARGETS
108+
gdal
92109
gdalinfo
93110
gdalbuildvrt
94111
gdaladdo

apps/commonutils.cpp

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -154,53 +154,6 @@ void GDALRemoveBOM(GByte *pabyData)
154154
}
155155
}
156156

157-
/************************************************************************/
158-
/* GDALRemoveSQLComments() */
159-
/************************************************************************/
160-
161-
std::string GDALRemoveSQLComments(const std::string &osInput)
162-
{
163-
const CPLStringList aosLines(
164-
CSLTokenizeStringComplex(osInput.c_str(), "\r\n", FALSE, FALSE));
165-
std::string osSQL;
166-
for (const char *pszLine : aosLines)
167-
{
168-
char chQuote = 0;
169-
int i = 0;
170-
for (; pszLine[i] != '\0'; ++i)
171-
{
172-
if (chQuote)
173-
{
174-
if (pszLine[i] == chQuote)
175-
{
176-
if (pszLine[i + 1] == chQuote)
177-
{
178-
i++;
179-
}
180-
else
181-
{
182-
chQuote = 0;
183-
}
184-
}
185-
}
186-
else if (pszLine[i] == '\'' || pszLine[i] == '"')
187-
{
188-
chQuote = pszLine[i];
189-
}
190-
else if (pszLine[i] == '-' && pszLine[i + 1] == '-')
191-
{
192-
break;
193-
}
194-
}
195-
if (i > 0)
196-
{
197-
osSQL.append(pszLine, i);
198-
}
199-
osSQL += ' ';
200-
}
201-
return osSQL;
202-
}
203-
204157
/************************************************************************/
205158
/* ArgIsNumeric() */
206159
/************************************************************************/

apps/commonutils.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ std::vector<std::string> CPL_DLL
9393
GetOutputDriversFor(const char *pszDestFilename, int nFlagRasterVector);
9494
CPLString CPL_DLL GetOutputDriverForRaster(const char *pszDestFilename);
9595
void GDALRemoveBOM(GByte *pabyData);
96-
std::string GDALRemoveSQLComments(const std::string &osInput);
9796

9897
int ArgIsNumeric(const char *pszArg);
9998

apps/gdal.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/******************************************************************************
2+
*
3+
* Project: GDAL
4+
* Purpose: CLI front-end
5+
* Author: Even Rouault <even dot rouault at spatialys.com>
6+
*
7+
******************************************************************************
8+
* Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
9+
*
10+
* SPDX-License-Identifier: MIT
11+
****************************************************************************/
12+
13+
#include "gdalalgorithm.h"
14+
#include "commonutils.h"
15+
16+
#include "gdal.h"
17+
18+
#include <cassert>
19+
20+
/************************************************************************/
21+
/* main() */
22+
/************************************************************************/
23+
24+
MAIN_START(argc, argv)
25+
{
26+
EarlySetConfigOptions(argc, argv);
27+
28+
/* -------------------------------------------------------------------- */
29+
/* Register standard GDAL drivers, and process generic GDAL */
30+
/* command options. */
31+
/* -------------------------------------------------------------------- */
32+
33+
GDALAllRegister();
34+
argc = GDALGeneralCmdLineProcessor(
35+
argc, &argv, GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER);
36+
if (argc < 1)
37+
return (-argc);
38+
39+
auto alg = GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate(
40+
GDALGlobalAlgorithmRegistry::ROOT_ALG_NAME);
41+
assert(alg);
42+
alg->SetCallPath(std::vector<std::string>{argv[0]});
43+
std::vector<std::string> args;
44+
for (int i = 1; i < argc; ++i)
45+
args.push_back(argv[i]);
46+
CSLDestroy(argv);
47+
48+
if (!alg->ParseCommandLineArguments(args))
49+
{
50+
fprintf(stderr, "%s", alg->GetUsageForCLI(true).c_str());
51+
return 1;
52+
}
53+
54+
{
55+
const auto stdoutArg = alg->GetActualAlgorithm().GetArg("stdout");
56+
if (stdoutArg && stdoutArg->GetType() == GAAT_BOOLEAN)
57+
stdoutArg->Set(true);
58+
}
59+
60+
GDALProgressFunc pfnProgress =
61+
alg->IsProgressBarRequested() ? GDALTermProgress : nullptr;
62+
void *pProgressData = nullptr;
63+
64+
int ret = 0;
65+
if (alg->Run(pfnProgress, pProgressData) && alg->Finalize())
66+
{
67+
const auto outputArg =
68+
alg->GetActualAlgorithm().GetArg("output-string");
69+
if (outputArg && outputArg->GetType() == GAAT_STRING &&
70+
outputArg->IsOutput())
71+
{
72+
printf("%s", outputArg->Get<std::string>().c_str());
73+
}
74+
}
75+
else
76+
{
77+
ret = 1;
78+
}
79+
80+
return ret;
81+
}
82+
83+
MAIN_END

apps/gdal_rasterize_lib.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ GDALRasterizeOptionsGetParser(GDALRasterizeOptions *psOptions,
186186
char *pszSQLStatement =
187187
reinterpret_cast<char *>(pabyRet);
188188
psOptions->osSQL = CPLStrdup(
189-
GDALRemoveSQLComments(pszSQLStatement).c_str());
189+
CPLRemoveSQLComments(pszSQLStatement).c_str());
190190
VSIFree(pszSQLStatement);
191191
}
192192
})

apps/gdal_translate_lib.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,9 @@ struct GDALTranslateOptions
301301
/*! overview level of source file to be used */
302302
int nOvLevel = OVR_LEVEL_AUTO;
303303

304+
/*! set to true to prevent overwriting existing dataset */
305+
bool bNoOverwrite = false;
306+
304307
GDALTranslateOptions() = default;
305308
~GDALTranslateOptions();
306309
GDALTranslateOptions *Clone() const;
@@ -1106,6 +1109,29 @@ GDALDatasetH GDALTranslate(const char *pszDest, GDALDatasetH hSrcDataset,
11061109
"@QUIET_DELETE_ON_CREATE_COPY", "NO");
11071110
}
11081111

1112+
if (psOptions->bNoOverwrite && !EQUAL(pszDest, ""))
1113+
{
1114+
VSIStatBufL sStat;
1115+
if (VSIStatL(pszDest, &sStat) == 0)
1116+
{
1117+
CPLError(CE_Failure, CPLE_AppDefined,
1118+
"File '%s' already exists. Specify the --overwrite "
1119+
"option to overwrite it.",
1120+
pszDest);
1121+
GDALTranslateOptionsFree(psOptions);
1122+
return nullptr;
1123+
}
1124+
else if (std::unique_ptr<GDALDataset>(GDALDataset::Open(pszDest)))
1125+
{
1126+
CPLError(CE_Failure, CPLE_AppDefined,
1127+
"Dataset '%s' already exists. Specify the --overwrite "
1128+
"option to overwrite it.",
1129+
pszDest);
1130+
GDALTranslateOptionsFree(psOptions);
1131+
return nullptr;
1132+
}
1133+
}
1134+
11091135
GDALDriver::FromHandle(hDriver)->QuietDeleteForCreateCopy(pszDest,
11101136
poSrcDS);
11111137

@@ -3127,6 +3153,11 @@ GDALTranslateOptionsGetParser(GDALTranslateOptions *psOptions,
31273153
.hidden()
31283154
.store_into(psOptions->nLimitOutSize);
31293155

3156+
// Undocumented option used by gdal raster convert
3157+
argParser->add_argument("--no-overwrite")
3158+
.store_into(psOptions->bNoOverwrite)
3159+
.hidden();
3160+
31303161
if (psOptionsForBinary)
31313162
{
31323163
argParser->add_argument("input_file")

apps/gdalalg_convert.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/******************************************************************************
2+
*
3+
* Project: GDAL
4+
* Purpose: gdal "convert" subcommand
5+
* Author: Even Rouault <even dot rouault at spatialys.com>
6+
*
7+
******************************************************************************
8+
* Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
9+
*
10+
* SPDX-License-Identifier: MIT
11+
****************************************************************************/
12+
13+
#include "cpl_error.h"
14+
#include "gdalalgorithm.h"
15+
#include "gdalalg_raster_convert.h"
16+
#include "gdalalg_vector_convert.h"
17+
#include "gdalalg_dispatcher.h"
18+
#include "gdal_priv.h"
19+
20+
/************************************************************************/
21+
/* GDALConvertAlgorithm */
22+
/************************************************************************/
23+
24+
class GDALConvertAlgorithm
25+
: public GDALDispatcherAlgorithm<GDALRasterConvertAlgorithm,
26+
GDALVectorConvertAlgorithm>
27+
{
28+
public:
29+
static constexpr const char *NAME = "convert";
30+
static constexpr const char *DESCRIPTION =
31+
"Convert a dataset (shortcut for 'gdal raster convert' or "
32+
"'gdal vector convert').";
33+
static constexpr const char *HELP_URL = ""; // TODO
34+
35+
static std::vector<std::string> GetAliases()
36+
{
37+
return {};
38+
}
39+
40+
GDALConvertAlgorithm()
41+
: GDALDispatcherAlgorithm(NAME, DESCRIPTION, HELP_URL)
42+
{
43+
// only for the help message
44+
AddProgressArg();
45+
AddOutputFormatArg(&m_format);
46+
AddInputDatasetArg(&m_inputDataset);
47+
AddOutputDatasetArg(&m_outputDataset);
48+
49+
m_longDescription = "For all options, run 'gdal raster convert --help' "
50+
"or 'gdal vector convert --help'";
51+
}
52+
53+
private:
54+
std::string m_format{};
55+
GDALArgDatasetValue m_inputDataset{};
56+
GDALArgDatasetValue m_outputDataset{};
57+
};
58+
59+
GDAL_STATIC_REGISTER_ALG(GDALConvertAlgorithm);

0 commit comments

Comments
 (0)