Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: gdal "mdim info" subcommand 5 : * Author: Even Rouault <even dot rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "gdalalg_mdim_info.h" 14 : 15 : #include "cpl_conv.h" 16 : #include "gdal_priv.h" 17 : #include "gdal_utils.h" 18 : 19 : //! @cond Doxygen_Suppress 20 : 21 : #ifndef _ 22 : #define _(x) (x) 23 : #endif 24 : 25 : /************************************************************************/ 26 : /* GDALMdimInfoAlgorithm::GDALMdimInfoAlgorithm() */ 27 : /************************************************************************/ 28 : 29 58 : GDALMdimInfoAlgorithm::GDALMdimInfoAlgorithm(bool standaloneStep, 30 58 : bool openForMixedRasterVector) 31 : : GDALMdimPipelineStepAlgorithm( 32 : NAME, DESCRIPTION, HELP_URL, 33 0 : ConstructorOptions() 34 58 : .SetStandaloneStep(standaloneStep) 35 58 : .SetInputDatasetMaxCount(1) 36 58 : .SetAddDefaultArguments(false) 37 116 : .SetInputDatasetHelpMsg(_("Input multidimensional dataset")) 38 174 : .SetInputDatasetAlias("dataset")) 39 : { 40 58 : if (standaloneStep) 41 : { 42 56 : AddMdimInputArgs(openForMixedRasterVector, 43 : /* hiddenForCLI = */ false, 44 : /* acceptRaster = */ false); 45 : } 46 : else 47 : { 48 2 : AddMdimHiddenInputDatasetArg(); 49 : } 50 : 51 58 : AddOutputFormatArg(&m_format).SetChoices("json", "text"); 52 : AddArg("summary", 0, 53 : _("Report only group and array hierarchy, without detailed " 54 : "information on attributes or dimensions."), 55 116 : &m_summary) 56 58 : .SetMutualExclusionGroup("structure_detailed"); 57 : AddArg( 58 : "detailed", 0, 59 : _("Most verbose output. Report attribute data types and array values."), 60 116 : &m_detailed) 61 58 : .SetMutualExclusionGroup("structure_detailed"); 62 : AddArrayNameArg(&m_array, _("Name of the array, used to restrict the " 63 58 : "output to the specified array.")); 64 : 65 : AddArg("limit", 0, 66 : _("Number of values in each dimension that is used to limit the " 67 : "display of array values."), 68 58 : &m_limit); 69 : { 70 : auto &arg = AddArg("array-option", 0, 71 : _("Option passed to GDALGroup::GetMDArrayNames() to " 72 : "filter reported arrays."), 73 116 : &m_arrayOptions) 74 116 : .SetMetaVar("<KEY>=<VALUE>") 75 58 : .SetPackedValuesAllowed(false); 76 3 : arg.AddValidationAction([this, &arg]() 77 61 : { return ParseAndValidateKeyValue(arg); }); 78 : 79 : arg.SetAutoCompleteFunction( 80 6 : [this](const std::string ¤tValue) 81 : { 82 2 : std::vector<std::string> ret; 83 2 : if (m_inputDataset.size() == 1) 84 : { 85 2 : if (auto poDS = 86 : std::unique_ptr<GDALDataset>(GDALDataset::Open( 87 2 : m_inputDataset[0].GetName().c_str(), 88 : GDAL_OF_MULTIDIM_RASTER, nullptr, nullptr, 89 4 : nullptr))) 90 : { 91 1 : if (auto poDriver = poDS->GetDriver()) 92 : { 93 1 : if (const char *pszXML = poDriver->GetMetadataItem( 94 1 : GDAL_DMD_MULTIDIM_ARRAY_OPENOPTIONLIST)) 95 : { 96 1 : AddOptionsSuggestions(pszXML, 0, currentValue, 97 : ret); 98 : } 99 : } 100 : } 101 : } 102 : 103 2 : return ret; 104 58 : }); 105 : } 106 58 : AddArg("stats", 0, _("Read and display image statistics."), &m_stats); 107 : 108 58 : AddOutputStringArg(&m_output); 109 58 : AddStdoutArg(&m_stdout); 110 58 : } 111 : 112 : /************************************************************************/ 113 : /* GDALMdimInfoAlgorithm::RunStep() */ 114 : /************************************************************************/ 115 : 116 10 : bool GDALMdimInfoAlgorithm::RunStep(GDALPipelineStepRunContext &) 117 : { 118 10 : CPLAssert(m_inputDataset.size() == 1); 119 10 : auto poSrcDS = m_inputDataset[0].GetDatasetRef(); 120 10 : CPLAssert(poSrcDS); 121 : 122 10 : if (m_format.empty()) 123 5 : m_format = IsCalledFromCommandLine() ? "text" : "json"; 124 : 125 10 : CPLStringList aosOptions; 126 : 127 10 : aosOptions.AddString("-format"); 128 10 : aosOptions.AddString(m_format); 129 10 : if (m_stdout) 130 3 : aosOptions.AddString("-stdout"); 131 10 : if (m_summary) 132 2 : aosOptions.AddString("-summary"); 133 8 : else if (m_detailed) 134 3 : aosOptions.AddString("-detailed"); 135 10 : if (m_stats) 136 2 : aosOptions.AddString("-stats"); 137 10 : if (m_limit > 0) 138 : { 139 1 : aosOptions.AddString("-limit"); 140 1 : aosOptions.AddString(CPLSPrintf("%d", m_limit)); 141 : } 142 10 : if (!m_array.empty()) 143 : { 144 3 : aosOptions.AddString("-array"); 145 3 : aosOptions.AddString(m_array.c_str()); 146 : } 147 11 : for (const std::string &opt : m_arrayOptions) 148 : { 149 1 : aosOptions.AddString("-arrayoption"); 150 1 : aosOptions.AddString(opt.c_str()); 151 : } 152 : 153 10 : GDALDatasetH hDS = GDALDataset::ToHandle(poSrcDS); 154 : GDALMultiDimInfoOptions *psOptions = 155 10 : GDALMultiDimInfoOptionsNew(aosOptions.List(), nullptr); 156 10 : char *ret = GDALMultiDimInfo(hDS, psOptions); 157 10 : GDALMultiDimInfoOptionsFree(psOptions); 158 10 : const bool bOK = ret != nullptr; 159 10 : if (ret && !m_stdout) 160 : { 161 7 : m_output = ret; 162 : } 163 10 : CPLFree(ret); 164 : 165 20 : return bOK; 166 : } 167 : 168 : GDALMdimInfoAlgorithmStandalone::~GDALMdimInfoAlgorithmStandalone() = default; 169 : 170 : //! @endcond