LCOV - code coverage report
Current view: top level - frmts/gdalg - gdalgdriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 105 119 88.2 %
Date: 2025-03-28 11:40:40 Functions: 15 17 88.2 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  GDAL Algorithm driver
       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 "cpl_json.h"
      14             : #include "cpl_string.h"
      15             : 
      16             : #include "gdalalgorithm.h"
      17             : #include "gdal_proxy.h"
      18             : #include "gdal_priv.h"
      19             : 
      20             : /************************************************************************/
      21             : /*                            GDALGDataset                              */
      22             : /************************************************************************/
      23             : 
      24             : class GDALGDataset final : public GDALProxyDataset
      25             : {
      26             :   public:
      27             :     GDALGDataset(std::unique_ptr<GDALAlgorithm> poAlg, GDALDataset *poDS);
      28             : 
      29             :     static int Identify(GDALOpenInfo *poOpenInfo);
      30             :     static GDALDataset *Open(GDALOpenInfo *poOpenInfo);
      31             : 
      32             :   protected:
      33           0 :     GDALDataset *RefUnderlyingDataset() const override
      34             :     {
      35           0 :         return m_poUnderlyingDS;
      36             :     }
      37             : 
      38           0 :     void UnrefUnderlyingDataset(GDALDataset *) const override
      39             :     {
      40           0 :     }
      41             : 
      42             :   private:
      43             :     std::unique_ptr<GDALAlgorithm> m_poAlg{};
      44             :     GDALDataset *m_poUnderlyingDS = nullptr;
      45             : 
      46             :     CPL_DISALLOW_COPY_ASSIGN(GDALGDataset)
      47             : 
      48           1 :     GDALDriver *GetDriver() override
      49             :     {
      50           1 :         return poDriver;
      51             :     }
      52             : 
      53           1 :     int GetLayerCount() override
      54             :     {
      55           1 :         return m_poUnderlyingDS->GetLayerCount();
      56             :     }
      57             : 
      58           1 :     OGRLayer *GetLayer(int idx) override
      59             :     {
      60           1 :         return m_poUnderlyingDS->GetLayer(idx);
      61             :     }
      62             : 
      63           1 :     OGRLayer *GetLayerByName(const char *pszName) override
      64             :     {
      65           1 :         return m_poUnderlyingDS->GetLayerByName(pszName);
      66             :     }
      67             : 
      68           1 :     OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
      69             :                          const char *pszDialect) override
      70             :     {
      71           1 :         return m_poUnderlyingDS->ExecuteSQL(pszStatement, poSpatialFilter,
      72           1 :                                             pszDialect);
      73             :     }
      74             : 
      75           1 :     void ResetReading() override
      76             :     {
      77           1 :         m_poUnderlyingDS->ResetReading();
      78           1 :     }
      79             : 
      80          11 :     OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
      81             :                                double *pdfProgressPct,
      82             :                                GDALProgressFunc pfnProgress,
      83             :                                void *pProgressData) override
      84             :     {
      85          11 :         return m_poUnderlyingDS->GetNextFeature(
      86          11 :             ppoBelongingLayer, pdfProgressPct, pfnProgress, pProgressData);
      87             :     }
      88             : 
      89           1 :     int TestCapability(const char *pszCap) override
      90             :     {
      91           1 :         return m_poUnderlyingDS->TestCapability(pszCap);
      92             :     }
      93             : };
      94             : 
      95             : /************************************************************************/
      96             : /*                          GDALGRasterBand                             */
      97             : /************************************************************************/
      98             : 
      99             : class GDALGRasterBand final : public GDALProxyRasterBand
     100             : {
     101             :   public:
     102             :     explicit GDALGRasterBand(GDALRasterBand *poUnderlyingBand);
     103             : 
     104             :   protected:
     105             :     GDALRasterBand *
     106           6 :     RefUnderlyingRasterBand(bool /* bForceOpen */) const override
     107             :     {
     108           6 :         return m_poUnderlyingBand;
     109             :     }
     110             : 
     111           6 :     void UnrefUnderlyingRasterBand(GDALRasterBand *) const override
     112             :     {
     113           6 :     }
     114             : 
     115             :   private:
     116             :     GDALRasterBand *m_poUnderlyingBand = nullptr;
     117             : 
     118             :     CPL_DISALLOW_COPY_ASSIGN(GDALGRasterBand)
     119             : };
     120             : 
     121             : /************************************************************************/
     122             : /*                      GDALGDataset::GDALGDataset()                    */
     123             : /************************************************************************/
     124             : 
     125           7 : GDALGDataset::GDALGDataset(std::unique_ptr<GDALAlgorithm> poAlg,
     126           7 :                            GDALDataset *poDS)
     127           7 :     : m_poAlg(std::move(poAlg)), m_poUnderlyingDS(poDS)
     128             : {
     129           7 :     nRasterXSize = m_poUnderlyingDS->GetRasterXSize();
     130           7 :     nRasterYSize = m_poUnderlyingDS->GetRasterYSize();
     131          13 :     for (int i = 0; i < m_poUnderlyingDS->GetRasterCount(); ++i)
     132             :     {
     133           6 :         SetBand(i + 1, std::make_unique<GDALGRasterBand>(
     134          12 :                            m_poUnderlyingDS->GetRasterBand(i + 1)));
     135             :     }
     136           7 : }
     137             : 
     138             : /************************************************************************/
     139             : /*                    GDALGRasterBand::GDALGRasterBand()                */
     140             : /************************************************************************/
     141             : 
     142           6 : GDALGRasterBand::GDALGRasterBand(GDALRasterBand *poUnderlyingBand)
     143           6 :     : m_poUnderlyingBand(poUnderlyingBand)
     144             : {
     145           6 :     nBand = poUnderlyingBand->GetBand();
     146           6 :     eDataType = poUnderlyingBand->GetRasterDataType();
     147           6 :     nRasterXSize = poUnderlyingBand->GetXSize();
     148           6 :     nRasterYSize = poUnderlyingBand->GetYSize();
     149           6 :     poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     150           6 : }
     151             : 
     152             : /************************************************************************/
     153             : /*                         GDALGDataset::Identify()                     */
     154             : /************************************************************************/
     155             : 
     156       58435 : /* static */ int GDALGDataset::Identify(GDALOpenInfo *poOpenInfo)
     157             : {
     158       68732 :     return (poOpenInfo->pabyHeader &&
     159       10297 :             strstr(reinterpret_cast<const char *>(poOpenInfo->pabyHeader),
     160      116870 :                    "\"gdal_streamed_alg\"")) ||
     161      116862 :            (strstr(poOpenInfo->pszFilename, "\"gdal_streamed_alg\""));
     162             : }
     163             : 
     164             : /************************************************************************/
     165             : /*                         GDALGDataset::Open()                         */
     166             : /************************************************************************/
     167             : 
     168          16 : /* static */ GDALDataset *GDALGDataset::Open(GDALOpenInfo *poOpenInfo)
     169             : {
     170          16 :     if (!Identify(poOpenInfo))
     171           0 :         return nullptr;
     172          32 :     CPLJSONDocument oDoc;
     173          16 :     if (poOpenInfo->pabyHeader)
     174             :     {
     175           4 :         if (!oDoc.Load(poOpenInfo->pszFilename))
     176             :         {
     177           0 :             return nullptr;
     178             :         }
     179             :     }
     180             :     else
     181             :     {
     182          24 :         if (!oDoc.LoadMemory(
     183          12 :                 reinterpret_cast<const char *>(poOpenInfo->pszFilename)))
     184             :         {
     185           0 :             return nullptr;
     186             :         }
     187             :     }
     188          16 :     if (oDoc.GetRoot().GetString("type") != "gdal_streamed_alg")
     189           0 :         return nullptr;
     190          48 :     const std::string osCommandLine = oDoc.GetRoot().GetString("command_line");
     191          16 :     if (osCommandLine.empty())
     192             :     {
     193           0 :         CPLError(CE_Failure, CPLE_AppDefined, "command_line missing");
     194           0 :         return nullptr;
     195             :     }
     196             : 
     197          32 :     const CPLStringList aosArgs(CSLTokenizeString(osCommandLine.c_str()));
     198             : 
     199          16 :     auto alg = GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate(
     200          48 :         GDALGlobalAlgorithmRegistry::ROOT_ALG_NAME);
     201             : 
     202          20 :     if (poOpenInfo->pabyHeader &&
     203          20 :         oDoc.GetRoot().GetBool("relative_paths_relative_to_this_file", true))
     204             :     {
     205          12 :         alg->SetReferencePathForRelativePaths(
     206           8 :             CPLGetPathSafe(poOpenInfo->pszFilename).c_str());
     207             :     }
     208             : 
     209          16 :     alg->SetExecutionForStreamedOutput();
     210             : 
     211          32 :     alg->SetCallPath(std::vector<std::string>{aosArgs[0]});
     212          32 :     std::vector<std::string> args;
     213         105 :     for (int i = 1; i < aosArgs.size(); ++i)
     214          89 :         args.push_back(aosArgs[i]);
     215          16 :     if (!alg->ParseCommandLineArguments(args))
     216             :     {
     217           1 :         return nullptr;
     218             :     }
     219          15 :     if (!alg->GetActualAlgorithm().SupportsStreamedOutput())
     220             :     {
     221           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     222             :                  "Algorithm %s does not support a streamed output",
     223           0 :                  alg->GetActualAlgorithm().GetName().c_str());
     224           0 :         return nullptr;
     225             :     }
     226             : 
     227          15 :     if (!alg->Run(nullptr, nullptr))
     228             :     {
     229           6 :         return nullptr;
     230             :     }
     231             : 
     232           9 :     const auto outputArg = alg->GetActualAlgorithm().GetArg("output");
     233           9 :     if (outputArg && outputArg->GetType() == GAAT_DATASET)
     234             :     {
     235           9 :         auto &val = outputArg->Get<GDALArgDatasetValue>();
     236           9 :         auto poUnderlyingDS = val.GetDatasetRef();
     237           9 :         if (poUnderlyingDS)
     238             :         {
     239           9 :             if ((poOpenInfo->nOpenFlags & GDAL_OF_RASTER) &&
     240           7 :                 !(poOpenInfo->nOpenFlags & GDAL_OF_VECTOR))
     241             :             {
     242             :                 // Don't return if asked for a raster dataset but the
     243             :                 // underlying one is not.
     244           8 :                 if (poUnderlyingDS->GetRasterCount() == 0 &&
     245           1 :                     !poUnderlyingDS->GetMetadata("SUBDATASETS"))
     246             :                 {
     247           9 :                     return nullptr;
     248             :                 }
     249             :             }
     250           2 :             else if (!(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) &&
     251           2 :                      (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR))
     252             :             {
     253             :                 // Don't return if asked for a vector dataset but the
     254             :                 // underlying one is not.
     255           2 :                 if (poUnderlyingDS->GetLayerCount() == 0)
     256             :                 {
     257           1 :                     return nullptr;
     258             :                 }
     259             :             }
     260          14 :             return std::make_unique<GDALGDataset>(std::move(alg),
     261             :                                                   poUnderlyingDS)
     262           7 :                 .release();
     263             :         }
     264             :     }
     265             : 
     266           0 :     return nullptr;
     267             : }
     268             : 
     269             : /************************************************************************/
     270             : /*                       GDALRegister_GDALG()                           */
     271             : /************************************************************************/
     272             : 
     273        1667 : void GDALRegister_GDALG()
     274             : {
     275        1667 :     if (GDALGetDriverByName("GDALG") != nullptr)
     276         282 :         return;
     277             : 
     278        2770 :     auto poDriver = std::make_unique<GDALDriver>();
     279             : 
     280        1385 :     poDriver->SetDescription("GDALG");
     281        1385 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     282        1385 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     283        1385 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     284        1385 :                               "GDAL Streamed Algorithm driver");
     285        1385 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "gdalg.json");
     286             : 
     287        1385 :     poDriver->SetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES, "YES");
     288        1385 :     poDriver->SetMetadataItem(GDAL_DCAP_CURVE_GEOMETRIES, "YES");
     289        1385 :     poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
     290             : 
     291        1385 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     292             : 
     293        1385 :     poDriver->pfnIdentify = GDALGDataset::Identify;
     294        1385 :     poDriver->pfnOpen = GDALGDataset::Open;
     295             : 
     296        1385 :     GetGDALDriverManager()->RegisterDriver(poDriver.release());
     297             : }

Generated by: LCOV version 1.14