LCOV - code coverage report
Current view: top level - gcore - gdalmultidim_rat.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 205 222 92.3 %
Date: 2026-02-21 16:21:44 Functions: 32 32 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * Name:     gdalmultidim_rat.cpp
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  GDALCreateRasterAttributeTableFromMDArrays() implementation
       5             :  * Author:   Even Rouault <even.rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2023, Even Rouault <even.rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdal_priv.h"
      14             : #include "gdal_rat.h"
      15             : #include "gdalmultidim_priv.h"
      16             : 
      17             : /************************************************************************/
      18             : /*                GDALRasterAttributeTableFromMDArrays()                */
      19             : /************************************************************************/
      20             : 
      21             : class GDALRasterAttributeTableFromMDArrays final
      22             :     : public GDALRasterAttributeTable
      23             : {
      24             :     const GDALRATTableType m_eTableType;
      25             :     const std::vector<std::shared_ptr<GDALMDArray>> m_apoArrays;
      26             :     const std::vector<GDALRATFieldUsage> m_aeUsages;
      27             : 
      28             :     mutable std::string m_osTmp{};
      29             :     mutable std::vector<GByte> m_abyWKB{};
      30             : 
      31             :   public:
      32             :     GDALRasterAttributeTableFromMDArrays(
      33             :         GDALRATTableType eTableType,
      34             :         const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
      35             :         const std::vector<GDALRATFieldUsage> &aeUsages);
      36             : 
      37             :     //
      38             :     GDALRasterAttributeTable *Clone() const override;
      39             : 
      40             :     //
      41          41 :     int GetColumnCount() const override
      42             :     {
      43          41 :         return static_cast<int>(m_apoArrays.size());
      44             :     }
      45             : 
      46           3 :     const char *GetNameOfCol(int iCol) const override
      47             :     {
      48           3 :         if (iCol < 0 || iCol >= GetColumnCount())
      49           2 :             return nullptr;
      50           1 :         return m_apoArrays[iCol]->GetName().c_str();
      51             :     }
      52             : 
      53             :     //
      54           9 :     GDALRATFieldUsage GetUsageOfCol(int iCol) const override
      55             :     {
      56           9 :         if (iCol < 0 || iCol >= GetColumnCount() || m_aeUsages.empty())
      57           3 :             return GFU_Generic;
      58           6 :         return m_aeUsages[iCol];
      59             :     }
      60             : 
      61             :     //
      62           5 :     GDALRATFieldType GetTypeOfCol(int iCol) const override
      63             :     {
      64           5 :         if (iCol < 0 || iCol >= GetColumnCount())
      65           2 :             return GFT_Integer;
      66           3 :         switch (m_apoArrays[iCol]->GetDataType().GetNumericDataType())
      67             :         {
      68           1 :             case GDT_Int8:
      69             :             case GDT_UInt8:
      70             :             case GDT_UInt16:
      71             :             case GDT_Int16:
      72             :             case GDT_Int32:
      73           1 :                 return GFT_Integer;
      74           1 :             case GDT_UInt32:
      75             :             case GDT_Int64:
      76             :             case GDT_UInt64:
      77             :             case GDT_Float16:
      78             :             case GDT_Float32:
      79             :             case GDT_Float64:
      80           1 :                 return GFT_Real;
      81           1 :             default:
      82           1 :                 break;
      83             :         }
      84           1 :         return GFT_String;
      85             :     }
      86             : 
      87             :     //
      88           2 :     int GetColOfUsage(GDALRATFieldUsage eUsage) const override
      89             :     {
      90           2 :         const int nColCount = GetColumnCount();
      91           6 :         for (int i = 0; i < nColCount; i++)
      92             :         {
      93           5 :             if (GetUsageOfCol(i) == eUsage)
      94           1 :                 return i;
      95             :         }
      96             : 
      97           1 :         return -1;
      98             :     }
      99             : 
     100             :     //
     101          32 :     int GetRowCount() const override
     102             :     {
     103          32 :         return static_cast<int>(m_apoArrays[0]->GetDimensions()[0]->GetSize());
     104             :     }
     105             : 
     106             :     //
     107           4 :     const char *GetValueAsString(int iRow, int iField) const override
     108             :     {
     109           6 :         if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
     110           2 :             iField >= GetColumnCount())
     111           2 :             return nullptr;
     112             : 
     113           2 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
     114           2 :         const size_t count[1] = {1};
     115           2 :         const GInt64 arrayStep[1] = {1};
     116           2 :         const GPtrDiff_t bufferStride[1] = {1};
     117           2 :         char *pszStr = nullptr;
     118           2 :         void *pDstBuffer = &pszStr;
     119           4 :         if (!m_apoArrays[iField]->Read(
     120             :                 arrayStartIdx, count, arrayStep, bufferStride,
     121           4 :                 GDALExtendedDataType::CreateString(), pDstBuffer))
     122           0 :             return nullptr;
     123             :         // cppcheck-suppress knownConditionTrueFalse
     124           2 :         if (!pszStr)
     125           0 :             return nullptr;
     126           2 :         m_osTmp = pszStr;
     127           2 :         CPLFree(pszStr);
     128           2 :         return m_osTmp.c_str();
     129             :     }
     130             : 
     131             :     //
     132           4 :     int GetValueAsInt(int iRow, int iField) const override
     133             :     {
     134           6 :         if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
     135           2 :             iField >= GetColumnCount())
     136           2 :             return 0;
     137             : 
     138           2 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
     139           2 :         const size_t count[1] = {1};
     140           2 :         const GInt64 arrayStep[1] = {1};
     141           2 :         const GPtrDiff_t bufferStride[1] = {1};
     142           2 :         int nVal = 0;
     143           2 :         void *pDstBuffer = &nVal;
     144           4 :         if (!m_apoArrays[iField]->Read(
     145             :                 arrayStartIdx, count, arrayStep, bufferStride,
     146           4 :                 GDALExtendedDataType::Create(GDT_Int32), pDstBuffer))
     147           0 :             return 0;
     148           2 :         return nVal;
     149             :     }
     150             : 
     151             :     //
     152           4 :     double GetValueAsDouble(int iRow, int iField) const override
     153             :     {
     154           6 :         if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
     155           2 :             iField >= GetColumnCount())
     156           2 :             return 0;
     157             : 
     158           2 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
     159           2 :         const size_t count[1] = {1};
     160           2 :         const GInt64 arrayStep[1] = {1};
     161           2 :         const GPtrDiff_t bufferStride[1] = {1};
     162           2 :         double dfVal = 0;
     163           2 :         void *pDstBuffer = &dfVal;
     164           4 :         if (!m_apoArrays[iField]->Read(
     165             :                 arrayStartIdx, count, arrayStep, bufferStride,
     166           4 :                 GDALExtendedDataType::Create(GDT_Float64), pDstBuffer))
     167           0 :             return 0;
     168           2 :         return dfVal;
     169             :     }
     170             : 
     171             :     //
     172           1 :     bool GetValueAsBoolean(int iRow, int iField) const override
     173             :     {
     174             :         // Let ValuesIO do the work.
     175           1 :         bool bValue = false;
     176           1 :         if (const_cast<GDALRasterAttributeTableFromMDArrays *>(this)->ValuesIO(
     177           1 :                 GF_Read, iField, iRow, 1, &bValue) != CE_None)
     178             :         {
     179           0 :             return false;
     180             :         }
     181             : 
     182           1 :         return bValue;
     183             :     }
     184             : 
     185             :     //
     186           1 :     GDALRATDateTime GetValueAsDateTime(int iRow, int iField) const override
     187             :     {
     188             :         // Let ValuesIO do the work.
     189           1 :         GDALRATDateTime dt;
     190           1 :         const_cast<GDALRasterAttributeTableFromMDArrays *>(this)->ValuesIO(
     191             :             GF_Read, iField, iRow, 1, &dt);
     192           1 :         return dt;
     193             :     }
     194             : 
     195             :     //
     196           1 :     const GByte *GetValueAsWKBGeometry(int iRow, int iField,
     197             :                                        size_t &nWKBSize) const override
     198             :     {
     199             :         // Let ValuesIO do the work.
     200           1 :         GByte *pabyWKB = nullptr;
     201           1 :         nWKBSize = 0;
     202           1 :         const_cast<GDALRasterAttributeTableFromMDArrays *>(this)->ValuesIO(
     203             :             GF_Read, iField, iRow, 1, &pabyWKB, &nWKBSize);
     204           1 :         if (pabyWKB)
     205           0 :             m_abyWKB.assign(pabyWKB, pabyWKB + nWKBSize);
     206           1 :         CPLFree(pabyWKB);
     207           1 :         return pabyWKB ? m_abyWKB.data() : nullptr;
     208             :     }
     209             : 
     210             :     //
     211           5 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     212             :                     double *pdfData) override
     213             :     {
     214           5 :         if (eRWFlag != GF_Read)
     215             :         {
     216           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     217             :                      "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
     218             :                      "eRWFlag != GF_Read not supported");
     219           0 :             return CE_Failure;
     220             :         }
     221           9 :         if (iStartRow < 0 || iLength <= 0 ||
     222           4 :             iStartRow > GetRowCount() - iLength)
     223             :         {
     224           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
     225           2 :             return CE_Failure;
     226             :         }
     227           3 :         if (iField < 0 || iField >= GetColumnCount())
     228             :         {
     229           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
     230           2 :             return CE_Failure;
     231             :         }
     232           1 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
     233           1 :         const size_t count[1] = {static_cast<size_t>(iLength)};
     234           1 :         const GInt64 arrayStep[1] = {1};
     235           1 :         const GPtrDiff_t bufferStride[1] = {1};
     236           2 :         if (!m_apoArrays[iField]->Read(
     237             :                 arrayStartIdx, count, arrayStep, bufferStride,
     238           2 :                 GDALExtendedDataType::Create(GDT_Float64), pdfData))
     239           0 :             return CE_Failure;
     240           1 :         return CE_None;
     241             :     }
     242             : 
     243             :     //
     244          10 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     245             :                     int *pnData) override
     246             :     {
     247          10 :         if (eRWFlag != GF_Read)
     248             :         {
     249           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     250             :                      "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
     251             :                      "eRWFlag != GF_Read not supported");
     252           0 :             return CE_Failure;
     253             :         }
     254          18 :         if (iStartRow < 0 || iLength <= 0 ||
     255           8 :             iStartRow > GetRowCount() - iLength)
     256             :         {
     257           4 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
     258           4 :             return CE_Failure;
     259             :         }
     260           6 :         if (iField < 0 || iField >= GetColumnCount())
     261             :         {
     262           4 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
     263           4 :             return CE_Failure;
     264             :         }
     265           2 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
     266           2 :         const size_t count[1] = {static_cast<size_t>(iLength)};
     267           2 :         const GInt64 arrayStep[1] = {1};
     268           2 :         const GPtrDiff_t bufferStride[1] = {1};
     269           4 :         if (!m_apoArrays[iField]->Read(
     270             :                 arrayStartIdx, count, arrayStep, bufferStride,
     271           4 :                 GDALExtendedDataType::Create(GDT_Int32), pnData))
     272           0 :             return CE_Failure;
     273           2 :         return CE_None;
     274             :     }
     275             : 
     276             :     //
     277           7 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     278             :                     char **papszStrList) override
     279             :     {
     280           7 :         if (eRWFlag != GF_Read)
     281             :         {
     282           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     283             :                      "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
     284             :                      "eRWFlag != GF_Read not supported");
     285           0 :             return CE_Failure;
     286             :         }
     287          13 :         if (iStartRow < 0 || iLength <= 0 ||
     288           6 :             iStartRow > GetRowCount() - iLength)
     289             :         {
     290           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
     291           2 :             return CE_Failure;
     292             :         }
     293           5 :         if (iField < 0 || iField >= GetColumnCount())
     294             :         {
     295           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
     296           2 :             return CE_Failure;
     297             :         }
     298           3 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
     299           3 :         const size_t count[1] = {static_cast<size_t>(iLength)};
     300           3 :         const GInt64 arrayStep[1] = {1};
     301           3 :         const GPtrDiff_t bufferStride[1] = {1};
     302           6 :         if (!m_apoArrays[iField]->Read(
     303             :                 arrayStartIdx, count, arrayStep, bufferStride,
     304           6 :                 GDALExtendedDataType::CreateString(), papszStrList))
     305           0 :             return CE_Failure;
     306           3 :         return CE_None;
     307             :     }
     308             : 
     309             :     //
     310           5 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     311             :                     bool *pbData) override
     312             :     {
     313           5 :         return ValuesIOBooleanFromIntoInt(eRWFlag, iField, iStartRow, iLength,
     314           5 :                                           pbData);
     315             :     }
     316             : 
     317             :     //
     318           1 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     319             :                     GDALRATDateTime *psDateTime) override
     320             :     {
     321           1 :         return ValuesIODateTimeFromIntoString(eRWFlag, iField, iStartRow,
     322           1 :                                               iLength, psDateTime);
     323             :     }
     324             : 
     325             :     //
     326           1 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     327             :                     GByte **ppabyWKB, size_t *pnWKBSize) override
     328             :     {
     329           1 :         return ValuesIOWKBGeometryFromIntoString(eRWFlag, iField, iStartRow,
     330           1 :                                                  iLength, ppabyWKB, pnWKBSize);
     331             :     }
     332             : 
     333             :     //
     334           1 :     CPLErr SetValue(int, int, const char *) override
     335             :     {
     336           1 :         CPLError(
     337             :             CE_Failure, CPLE_NotSupported,
     338             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     339           1 :         return CE_Failure;
     340             :     }
     341             : 
     342             :     //
     343           1 :     CPLErr SetValue(int, int, int) override
     344             :     {
     345           1 :         CPLError(
     346             :             CE_Failure, CPLE_NotSupported,
     347             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     348           1 :         return CE_Failure;
     349             :     }
     350             : 
     351             :     //
     352           1 :     CPLErr SetValue(int, int, double) override
     353             :     {
     354           1 :         CPLError(
     355             :             CE_Failure, CPLE_NotSupported,
     356             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     357           1 :         return CE_Failure;
     358             :     }
     359             : 
     360             :     //
     361           1 :     CPLErr SetValue(int, int, bool) override
     362             :     {
     363           1 :         CPLError(
     364             :             CE_Failure, CPLE_NotSupported,
     365             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     366           1 :         return CE_Failure;
     367             :     }
     368             : 
     369             :     //
     370           1 :     CPLErr SetValue(int, int, const GDALRATDateTime &) override
     371             :     {
     372           1 :         CPLError(
     373             :             CE_Failure, CPLE_NotSupported,
     374             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     375           1 :         return CE_Failure;
     376             :     }
     377             : 
     378             :     //
     379           1 :     CPLErr SetValue(int, int, const void *, size_t) override
     380             :     {
     381           1 :         CPLError(
     382             :             CE_Failure, CPLE_NotSupported,
     383             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     384           1 :         return CE_Failure;
     385             :     }
     386             : 
     387             :     //
     388           1 :     int ChangesAreWrittenToFile() override
     389             :     {
     390           1 :         return false;
     391             :     }
     392             : 
     393             :     //
     394           1 :     CPLErr SetTableType(const GDALRATTableType) override
     395             :     {
     396           1 :         CPLError(CE_Failure, CPLE_NotSupported,
     397             :                  "GDALRasterAttributeTableFromMDArrays::SetTableType(): not "
     398             :                  "supported");
     399           1 :         return CE_Failure;
     400             :     }
     401             : 
     402             :     //
     403           1 :     void RemoveStatistics() override
     404             :     {
     405           1 :     }
     406             : 
     407             :     //
     408           1 :     GDALRATTableType GetTableType() const override
     409             :     {
     410           1 :         return m_eTableType;
     411             :     }
     412             : };
     413             : 
     414             : //
     415           1 : GDALRasterAttributeTable *GDALRasterAttributeTableFromMDArrays::Clone() const
     416             : {
     417           1 :     return new GDALRasterAttributeTableFromMDArrays(m_eTableType, m_apoArrays,
     418           1 :                                                     m_aeUsages);
     419             : }
     420             : 
     421             : /************************************************************************/
     422             : /*                GDALRasterAttributeTableFromMDArrays()                */
     423             : /************************************************************************/
     424             : 
     425           3 : GDALRasterAttributeTableFromMDArrays::GDALRasterAttributeTableFromMDArrays(
     426             :     GDALRATTableType eTableType,
     427             :     const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
     428           3 :     const std::vector<GDALRATFieldUsage> &aeUsages)
     429           3 :     : m_eTableType(eTableType), m_apoArrays(apoArrays), m_aeUsages(aeUsages)
     430             : {
     431           3 : }
     432             : 
     433             : /************************************************************************/
     434             : /*             GDALCreateRasterAttributeTableFromMDArrays()             */
     435             : /************************************************************************/
     436             : 
     437             : /** Return a virtual Raster Attribute Table from several GDALMDArray's.
     438             :  *
     439             :  * All arrays must be single-dimensional and be indexed by the same dimension.
     440             :  *
     441             :  * This is the same as the C function GDALCreateRasterAttributeTableFromMDArrays().
     442             :  *
     443             :  * @param eTableType RAT table type
     444             :  * @param apoArrays Vector of GDALMDArray's (none of them should be nullptr)
     445             :  * @param aeUsages Vector of GDALRATFieldUsage (of the same size as apoArrays if non-empty), or empty vector to use defaults
     446             :  * @return a new Raster Attribute Table to free with delete, or nullptr in case of error
     447             :  * @since 3.9
     448             :  */
     449           5 : GDALRasterAttributeTable *GDALCreateRasterAttributeTableFromMDArrays(
     450             :     GDALRATTableType eTableType,
     451             :     const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
     452             :     const std::vector<GDALRATFieldUsage> &aeUsages)
     453             : {
     454           5 :     if (apoArrays.empty())
     455             :     {
     456           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     457             :                  "GDALCreateRasterAttributeTableFromMDArrays(): apoArrays "
     458             :                  "should not be empty");
     459           1 :         return nullptr;
     460             :     }
     461           4 :     if (!aeUsages.empty() && apoArrays.size() != aeUsages.size())
     462             :     {
     463           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     464             :                  "GDALCreateRasterAttributeTableFromMDArrays(): aeUsages "
     465             :                  "should be empty or have the same size as apoArrays");
     466           0 :         return nullptr;
     467             :     }
     468          11 :     for (size_t i = 0; i < apoArrays.size(); ++i)
     469             :     {
     470           9 :         if (apoArrays[i]->GetDimensionCount() != 1)
     471             :         {
     472           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     473             :                      "GDALCreateRasterAttributeTableFromMDArrays(): "
     474             :                      "apoArrays[%d] has a dimension count != 1",
     475             :                      static_cast<int>(i));
     476           1 :             return nullptr;
     477             :         }
     478          17 :         if (i > 0 && (apoArrays[i]->GetDimensions()[0]->GetFullName() !=
     479           9 :                           apoArrays[0]->GetDimensions()[0]->GetFullName() ||
     480           4 :                       apoArrays[i]->GetDimensions()[0]->GetSize() !=
     481           4 :                           apoArrays[0]->GetDimensions()[0]->GetSize()))
     482             :         {
     483           1 :             CPLError(
     484             :                 CE_Failure, CPLE_AppDefined,
     485             :                 "GDALCreateRasterAttributeTableFromMDArrays(): apoArrays[%d] "
     486             :                 "does not have the same dimension has apoArrays[0]",
     487             :                 static_cast<int>(i));
     488           1 :             return nullptr;
     489             :         }
     490             :     }
     491             :     return new GDALRasterAttributeTableFromMDArrays(eTableType, apoArrays,
     492           2 :                                                     aeUsages);
     493             : }
     494             : 
     495             : /************************************************************************/
     496             : /*             GDALCreateRasterAttributeTableFromMDArrays()             */
     497             : /************************************************************************/
     498             : 
     499             : /** Return a virtual Raster Attribute Table from several GDALMDArray's.
     500             :  *
     501             :  * All arrays must be single-dimensional and be indexed by the same dimension.
     502             :  *
     503             :  * This is the same as the C++ method GDALCreateRasterAttributeTableFromMDArrays().
     504             :  *
     505             :  * @param eTableType RAT table type
     506             :  * @param nArrays Number of elements in ahArrays parameter
     507             :  * @param ahArrays Array of nArrays GDALMDArray's (none of them should be nullptr)
     508             :  * @param paeUsages Array of nArray GDALRATFieldUsage, or nullptr to use defaults
     509             :  * @return a new Raster Attribute Table to free with GDALDestroyRasterAttributeTable(), or nullptr in case of error
     510             :  * @since 3.9
     511             :  */
     512           5 : GDALRasterAttributeTableH GDALCreateRasterAttributeTableFromMDArrays(
     513             :     GDALRATTableType eTableType, int nArrays, const GDALMDArrayH *ahArrays,
     514             :     const GDALRATFieldUsage *paeUsages)
     515             : {
     516           5 :     VALIDATE_POINTER1(ahArrays, __func__, nullptr);
     517          10 :     std::vector<std::shared_ptr<GDALMDArray>> apoArrays;
     518          10 :     std::vector<GDALRATFieldUsage> aeUsages;
     519          14 :     for (int i = 0; i < nArrays; ++i)
     520             :     {
     521           9 :         VALIDATE_POINTER1(ahArrays[i], __func__, nullptr);
     522           9 :         apoArrays.emplace_back(ahArrays[i]->m_poImpl);
     523           9 :         if (paeUsages)
     524           3 :             aeUsages.emplace_back(paeUsages[i]);
     525             :     }
     526           5 :     return GDALRasterAttributeTable::ToHandle(
     527             :         GDALCreateRasterAttributeTableFromMDArrays(eTableType, apoArrays,
     528           5 :                                                    aeUsages));
     529             : }

Generated by: LCOV version 1.14