238 lines
8.2 KiB
C++
238 lines
8.2 KiB
C++
/******************************************************************************
|
|
*
|
|
* Project: OpenGIS Simple Features Reference Implementation
|
|
* Purpose: Simple client for translating between formats.
|
|
* Author: Frank Warmerdam, warmerdam@pobox.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 1999, Frank Warmerdam
|
|
* Copyright (c) 2008-2015, Even Rouault <even dot rouault at spatialys.com>
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
****************************************************************************/
|
|
|
|
#include "cpl_port.h"
|
|
|
|
#include <cstddef>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "commonutils.h"
|
|
#include "cpl_conv.h"
|
|
#include "cpl_error.h"
|
|
#include "cpl_progress.h"
|
|
#include "cpl_string.h"
|
|
#include "gdal_version.h"
|
|
#include "gdal.h"
|
|
#include "gdal_priv.h"
|
|
#include "gdal_utils.h"
|
|
#include "gdal_utils_priv.h"
|
|
#include "ogr_api.h"
|
|
#include "ogr_core.h"
|
|
#include "ogr_p.h"
|
|
#include "ogrsf_frmts.h"
|
|
|
|
/************************************************************************/
|
|
/* Usage() */
|
|
/************************************************************************/
|
|
|
|
static void Usage()
|
|
{
|
|
fprintf(stderr, "%s\n", GDALVectorTranslateGetParserUsage().c_str());
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* main() */
|
|
/************************************************************************/
|
|
|
|
MAIN_START(nArgc, papszArgv)
|
|
{
|
|
// Check strict compilation and runtime library version as we use C++ API.
|
|
if (!GDAL_CHECK_VERSION(papszArgv[0]))
|
|
exit(1);
|
|
|
|
EarlySetConfigOptions(nArgc, papszArgv);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Register format(s). */
|
|
/* -------------------------------------------------------------------- */
|
|
OGRRegisterAll();
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Processing command line arguments. */
|
|
/* -------------------------------------------------------------------- */
|
|
GDALDatasetH hDS = nullptr;
|
|
GDALDatasetH hODS = nullptr;
|
|
bool bCloseODS = true;
|
|
GDALDatasetH hDstDS = nullptr;
|
|
int nRetCode = 1;
|
|
GDALVectorTranslateOptions *psOptions = nullptr;
|
|
GDALVectorTranslateOptionsForBinary sOptionsForBinary;
|
|
|
|
nArgc = OGRGeneralCmdLineProcessor(nArgc, &papszArgv, 0);
|
|
|
|
if (nArgc < 1)
|
|
{
|
|
papszArgv = nullptr;
|
|
nRetCode = -nArgc;
|
|
goto exit;
|
|
}
|
|
|
|
psOptions =
|
|
GDALVectorTranslateOptionsNew(papszArgv + 1, &sOptionsForBinary);
|
|
|
|
if (psOptions == nullptr)
|
|
{
|
|
if (sOptionsForBinary.bShowUsageIfError)
|
|
Usage();
|
|
goto exit;
|
|
}
|
|
|
|
if (sOptionsForBinary.osDestDataSource == "/vsistdout/")
|
|
sOptionsForBinary.bQuiet = true;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Open data source. */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
// 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
|
|
if (sOptionsForBinary.eAccessMode != ACCESS_CREATION &&
|
|
sOptionsForBinary.osDestDataSource == sOptionsForBinary.osDataSource)
|
|
{
|
|
hODS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(),
|
|
GDAL_OF_UPDATE | GDAL_OF_VECTOR,
|
|
sOptionsForBinary.aosAllowInputDrivers.List(),
|
|
sOptionsForBinary.aosOpenOptions.List(), nullptr);
|
|
|
|
GDALDriverH hDriver =
|
|
hODS != nullptr ? GDALGetDatasetDriver(hODS) : nullptr;
|
|
|
|
// Restrict to those 3 drivers. For example it is known to break with
|
|
// the PG driver due to the way it manages transactions.
|
|
if (hDriver && !(EQUAL(GDALGetDescription(hDriver), "FileGDB") ||
|
|
EQUAL(GDALGetDescription(hDriver), "SQLite") ||
|
|
EQUAL(GDALGetDescription(hDriver), "GPKG")))
|
|
{
|
|
hDS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(),
|
|
GDAL_OF_VECTOR,
|
|
sOptionsForBinary.aosAllowInputDrivers.List(),
|
|
sOptionsForBinary.aosOpenOptions.List(), nullptr);
|
|
}
|
|
else
|
|
{
|
|
hDS = hODS;
|
|
bCloseODS = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hDS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(), GDAL_OF_VECTOR,
|
|
sOptionsForBinary.aosAllowInputDrivers.List(),
|
|
sOptionsForBinary.aosOpenOptions.List(), nullptr);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Report failure */
|
|
/* -------------------------------------------------------------------- */
|
|
if (hDS == nullptr)
|
|
{
|
|
GDALDriverManager *poDM = GetGDALDriverManager();
|
|
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Unable to open datasource `%s' with the following drivers.",
|
|
sOptionsForBinary.osDataSource.c_str());
|
|
|
|
for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
|
|
{
|
|
GDALDriver *poIter = poDM->GetDriver(iDriver);
|
|
char **papszDriverMD = poIter->GetMetadata();
|
|
if (CPLTestBool(CSLFetchNameValueDef(papszDriverMD,
|
|
GDAL_DCAP_VECTOR, "FALSE")))
|
|
{
|
|
fprintf(stderr, " -> `%s'\n", poIter->GetDescription());
|
|
}
|
|
}
|
|
|
|
GDALVectorTranslateOptionsFree(psOptions);
|
|
goto exit;
|
|
}
|
|
|
|
if (hODS != nullptr && !sOptionsForBinary.osFormat.empty())
|
|
{
|
|
GDALDriverManager *poDM = GetGDALDriverManager();
|
|
|
|
GDALDriver *poDriver =
|
|
poDM->GetDriverByName(sOptionsForBinary.osFormat.c_str());
|
|
if (poDriver == nullptr)
|
|
{
|
|
fprintf(stderr, "Unable to find driver `%s'.\n",
|
|
sOptionsForBinary.osFormat.c_str());
|
|
fprintf(stderr, "The following drivers are available:\n");
|
|
|
|
for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
|
|
{
|
|
GDALDriver *poIter = poDM->GetDriver(iDriver);
|
|
char **papszDriverMD = poIter->GetMetadata();
|
|
if (CPLTestBool(CSLFetchNameValueDef(
|
|
papszDriverMD, GDAL_DCAP_VECTOR, "FALSE")) &&
|
|
(CPLTestBool(CSLFetchNameValueDef(
|
|
papszDriverMD, GDAL_DCAP_CREATE, "FALSE")) ||
|
|
CPLTestBool(CSLFetchNameValueDef(
|
|
papszDriverMD, GDAL_DCAP_CREATECOPY, "FALSE"))))
|
|
{
|
|
fprintf(stderr, " -> `%s'\n", poIter->GetDescription());
|
|
}
|
|
}
|
|
GDALVectorTranslateOptionsFree(psOptions);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if (!(sOptionsForBinary.bQuiet))
|
|
{
|
|
GDALVectorTranslateOptionsSetProgress(psOptions, GDALTermProgress,
|
|
nullptr);
|
|
}
|
|
|
|
{
|
|
// TODO(schwehr): Remove scope after removing gotos
|
|
int bUsageError = FALSE;
|
|
hDstDS = GDALVectorTranslate(sOptionsForBinary.osDestDataSource.c_str(),
|
|
hODS, 1, &hDS, psOptions, &bUsageError);
|
|
if (bUsageError)
|
|
Usage();
|
|
else
|
|
nRetCode = hDstDS ? 0 : 1;
|
|
}
|
|
|
|
GDALVectorTranslateOptionsFree(psOptions);
|
|
|
|
if (hDS)
|
|
GDALClose(hDS);
|
|
if (bCloseODS)
|
|
{
|
|
if (nRetCode == 0)
|
|
CPLErrorReset();
|
|
if (GDALClose(hDstDS) != CE_None)
|
|
nRetCode = 1;
|
|
// TODO: Below code can be removed once all drivers have implemented
|
|
// GDALDataset::Close()
|
|
if (nRetCode == 0 && CPLGetLastErrorType() == CE_Failure)
|
|
nRetCode = 1;
|
|
}
|
|
|
|
exit:
|
|
CSLDestroy(papszArgv);
|
|
GDALDestroy();
|
|
|
|
return nRetCode;
|
|
}
|
|
|
|
MAIN_END
|