Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: gdal "main" command 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 "gdalalg_main.h" 14 : 15 : #include "gdal_priv.h" 16 : 17 : //! @cond Doxygen_Suppress 18 : 19 : #ifndef _ 20 : #define _(x) (x) 21 : #endif 22 : 23 : /************************************************************************/ 24 : /* GDALMainAlgorithm::GDALMainAlgorithm() */ 25 : /************************************************************************/ 26 : 27 160 : GDALMainAlgorithm::GDALMainAlgorithm() 28 160 : : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL) 29 : { 30 1280 : for (const std::string &subAlgName : 31 2720 : GDALGlobalAlgorithmRegistry::GetSingleton().GetNames()) 32 : { 33 : const auto pInfo = 34 1280 : GDALGlobalAlgorithmRegistry::GetSingleton().GetInfo(subAlgName); 35 1280 : if (pInfo) 36 1280 : RegisterSubAlgorithm(*pInfo); 37 : } 38 : 39 320 : SetCallPath({NAME}); 40 : 41 320 : AddArg("version", 0, _("Display GDAL version and exit"), &m_version) 42 160 : .SetOnlyForCLI(); 43 160 : AddArg("drivers", 0, _("Display driver list as JSON document"), &m_drivers); 44 : 45 160 : AddOutputStringArg(&m_output); 46 : 47 : m_longDescription = "'gdal <FILENAME>' can also be used as a shortcut for " 48 : "'gdal info <FILENAME>'.\n" 49 : "And 'gdal read <FILENAME> ! ...' as a shortcut for " 50 160 : "'gdal pipeline <FILENAME> ! ...'."; 51 : 52 160 : SetDisplayInJSONUsage(false); 53 160 : } 54 : 55 : /************************************************************************/ 56 : /* GDALMainAlgorithm::ParseCommandLineArguments() */ 57 : /************************************************************************/ 58 : 59 83 : bool GDALMainAlgorithm::ParseCommandLineArguments( 60 : const std::vector<std::string> &args) 61 : { 62 : // Detect shortest form of pipeline: 63 : // "gdal read in.tif ! .... ! write out.tif" 64 83 : if (args.size() >= 2 && args[0] == "read") 65 : { 66 : m_subAlg = 67 0 : GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate("pipeline"); 68 0 : if (m_subAlg) 69 : { 70 0 : bool ret = m_subAlg->ParseCommandLineArguments(args); 71 0 : if (ret) 72 : { 73 0 : m_selectedSubAlg = &(m_subAlg->GetActualAlgorithm()); 74 0 : std::vector<std::string> callPath(m_callPath); 75 0 : callPath.push_back("vector"); 76 0 : m_selectedSubAlg->SetCallPath(callPath); 77 0 : return true; 78 : } 79 0 : else if (strstr(CPLGetLastErrorMsg(), 80 0 : "has both raster and vector content")) 81 : { 82 0 : m_showUsage = false; 83 0 : return false; 84 : } 85 : } 86 : 87 0 : return GDALAlgorithm::ParseCommandLineArguments(args); 88 : } 89 86 : else if (args.size() == 1 && args[0].size() >= 2 && args[0][0] == '-' && 90 3 : args[0][1] == '-') 91 : { 92 3 : return GDALAlgorithm::ParseCommandLineArguments(args); 93 : } 94 : 95 : // Generic case: "gdal {subcommand} arguments" 96 : // where subcommand is a known subcommand 97 80 : else if (args.size() >= 1) 98 : { 99 79 : const auto nCounter = CPLGetErrorCounter(); 100 79 : if (InstantiateSubAlgorithm(args[0])) 101 76 : return GDALAlgorithm::ParseCommandLineArguments(args); 102 4 : if (CPLGetErrorCounter() == nCounter + 1 && 103 1 : strstr(CPLGetLastErrorMsg(), "Do you mean")) 104 : { 105 1 : return false; 106 : } 107 : } 108 : 109 : // Otherwise check if that is the shortest form of "gdal read mydataset" 110 : // where "read" is omitted: "gdal in.tif" 111 : { 112 : VSIStatBufL sStat; 113 7 : for (const auto &arg : args) 114 : { 115 5 : if (VSIStatL(arg.c_str(), &sStat) == 0) 116 : { 117 : m_subAlg = 118 2 : GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate( 119 1 : "info"); 120 1 : if (m_subAlg) 121 : { 122 1 : bool ret = m_subAlg->ParseCommandLineArguments(args); 123 1 : if (ret) 124 : { 125 1 : m_selectedSubAlg = &(m_subAlg->GetActualAlgorithm()); 126 1 : std::vector<std::string> callPath(m_callPath); 127 1 : callPath.push_back(m_selectedSubAlg->GetArg("layer") 128 : ? "vector" 129 : : "raster"); 130 1 : m_selectedSubAlg->SetCallPath(callPath); 131 1 : return true; 132 : } 133 0 : else if (strstr(CPLGetLastErrorMsg(), 134 0 : "has both raster and vector content")) 135 : { 136 0 : m_showUsage = false; 137 0 : return false; 138 : } 139 : } 140 : } 141 : } 142 : 143 2 : return GDALAlgorithm::ParseCommandLineArguments(args); 144 : } 145 : } 146 : 147 : /************************************************************************/ 148 : /* GDALMainAlgorithm::GetUsageForCLI() */ 149 : /************************************************************************/ 150 : 151 : std::string 152 6 : GDALMainAlgorithm::GetUsageForCLI(bool shortUsage, 153 : const UsageOptions &usageOptions) const 154 : { 155 6 : if (m_selectedSubAlg) 156 3 : return m_selectedSubAlg->GetUsageForCLI(shortUsage, usageOptions); 157 3 : if (m_showUsage) 158 3 : return GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptions); 159 0 : return std::string(); 160 : } 161 : 162 : /************************************************************************/ 163 : /* GDALMainAlgorithm::RunImpl() */ 164 : /************************************************************************/ 165 : 166 1 : bool GDALMainAlgorithm::RunImpl(GDALProgressFunc, void *) 167 : { 168 1 : if (m_drivers) 169 : { 170 1 : m_output = GDALPrintDriverList(GDAL_OF_KIND_MASK, true); 171 : } 172 1 : return true; 173 : } 174 : 175 : //! @endcond