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