LCOV - code coverage report
Current view: top level - gcore - gdalmultidim_rat.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 170 185 91.9 %
Date: 2024-05-04 12:52:34 Functions: 23 23 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "gdal_priv.h"
      30             : #include "gdal_rat.h"
      31             : #include "gdalmultidim_priv.h"
      32             : 
      33             : /************************************************************************/
      34             : /*                 GDALRasterAttributeTableFromMDArrays()               */
      35             : /************************************************************************/
      36             : 
      37             : class GDALRasterAttributeTableFromMDArrays final
      38             :     : public GDALRasterAttributeTable
      39             : {
      40             :     const GDALRATTableType m_eTableType;
      41             :     const std::vector<std::shared_ptr<GDALMDArray>> m_apoArrays;
      42             :     const std::vector<GDALRATFieldUsage> m_aeUsages;
      43             : 
      44             :     mutable std::string m_osTmp{};
      45             : 
      46             :   public:
      47             :     GDALRasterAttributeTableFromMDArrays(
      48             :         GDALRATTableType eTableType,
      49             :         const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
      50             :         const std::vector<GDALRATFieldUsage> &aeUsages);
      51             : 
      52             :     //
      53           1 :     GDALRasterAttributeTable *Clone() const override
      54             :     {
      55             :         return new GDALRasterAttributeTableFromMDArrays(
      56           1 :             m_eTableType, m_apoArrays, m_aeUsages);
      57             :     }
      58             : 
      59             :     //
      60          36 :     int GetColumnCount() const override
      61             :     {
      62          36 :         return static_cast<int>(m_apoArrays.size());
      63             :     }
      64             : 
      65           3 :     const char *GetNameOfCol(int iCol) const override
      66             :     {
      67           3 :         if (iCol < 0 || iCol >= GetColumnCount())
      68           2 :             return nullptr;
      69           1 :         return m_apoArrays[iCol]->GetName().c_str();
      70             :     }
      71             : 
      72             :     //
      73           9 :     GDALRATFieldUsage GetUsageOfCol(int iCol) const override
      74             :     {
      75           9 :         if (iCol < 0 || iCol >= GetColumnCount() || m_aeUsages.empty())
      76           3 :             return GFU_Generic;
      77           6 :         return m_aeUsages[iCol];
      78             :     }
      79             : 
      80             :     //
      81           5 :     GDALRATFieldType GetTypeOfCol(int iCol) const override
      82             :     {
      83           5 :         if (iCol < 0 || iCol >= GetColumnCount())
      84           2 :             return GFT_Integer;
      85           3 :         switch (m_apoArrays[iCol]->GetDataType().GetNumericDataType())
      86             :         {
      87           1 :             case GDT_Int8:
      88             :             case GDT_Byte:
      89             :             case GDT_UInt16:
      90             :             case GDT_Int16:
      91             :             case GDT_Int32:
      92           1 :                 return GFT_Integer;
      93           1 :             case GDT_UInt32:
      94             :             case GDT_Int64:
      95             :             case GDT_UInt64:
      96             :             case GDT_Float32:
      97             :             case GDT_Float64:
      98           1 :                 return GFT_Real;
      99           1 :             default:
     100           1 :                 break;
     101             :         }
     102           1 :         return GFT_String;
     103             :     }
     104             : 
     105             :     //
     106           2 :     int GetColOfUsage(GDALRATFieldUsage eUsage) const override
     107             :     {
     108           2 :         const int nColCount = GetColumnCount();
     109           6 :         for (int i = 0; i < nColCount; i++)
     110             :         {
     111           5 :             if (GetUsageOfCol(i) == eUsage)
     112           1 :                 return i;
     113             :         }
     114             : 
     115           1 :         return -1;
     116             :     }
     117             : 
     118             :     //
     119          25 :     int GetRowCount() const override
     120             :     {
     121          25 :         return static_cast<int>(m_apoArrays[0]->GetDimensions()[0]->GetSize());
     122             :     }
     123             : 
     124             :     //
     125           4 :     const char *GetValueAsString(int iRow, int iField) const override
     126             :     {
     127           6 :         if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
     128           2 :             iField >= GetColumnCount())
     129           2 :             return nullptr;
     130             : 
     131           2 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
     132           2 :         const size_t count[1] = {1};
     133           2 :         const GInt64 arrayStep[1] = {1};
     134           2 :         const GPtrDiff_t bufferStride[1] = {1};
     135           2 :         char *pszStr = nullptr;
     136           2 :         void *pDstBuffer = &pszStr;
     137           4 :         if (!m_apoArrays[iField]->Read(
     138             :                 arrayStartIdx, count, arrayStep, bufferStride,
     139           4 :                 GDALExtendedDataType::CreateString(), pDstBuffer))
     140           0 :             return nullptr;
     141           2 :         if (!pszStr)
     142           0 :             return nullptr;
     143           2 :         m_osTmp = pszStr;
     144           2 :         CPLFree(pszStr);
     145           2 :         return m_osTmp.c_str();
     146             :     }
     147             : 
     148             :     //
     149           4 :     int GetValueAsInt(int iRow, int iField) const override
     150             :     {
     151           6 :         if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
     152           2 :             iField >= GetColumnCount())
     153           2 :             return 0;
     154             : 
     155           2 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
     156           2 :         const size_t count[1] = {1};
     157           2 :         const GInt64 arrayStep[1] = {1};
     158           2 :         const GPtrDiff_t bufferStride[1] = {1};
     159           2 :         int nVal = 0;
     160           2 :         void *pDstBuffer = &nVal;
     161           4 :         if (!m_apoArrays[iField]->Read(
     162             :                 arrayStartIdx, count, arrayStep, bufferStride,
     163           4 :                 GDALExtendedDataType::Create(GDT_Int32), pDstBuffer))
     164           0 :             return 0;
     165           2 :         return nVal;
     166             :     }
     167             : 
     168             :     //
     169           4 :     double GetValueAsDouble(int iRow, int iField) const override
     170             :     {
     171           6 :         if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
     172           2 :             iField >= GetColumnCount())
     173           2 :             return 0;
     174             : 
     175           2 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
     176           2 :         const size_t count[1] = {1};
     177           2 :         const GInt64 arrayStep[1] = {1};
     178           2 :         const GPtrDiff_t bufferStride[1] = {1};
     179           2 :         double dfVal = 0;
     180           2 :         void *pDstBuffer = &dfVal;
     181           4 :         if (!m_apoArrays[iField]->Read(
     182             :                 arrayStartIdx, count, arrayStep, bufferStride,
     183           4 :                 GDALExtendedDataType::Create(GDT_Float64), pDstBuffer))
     184           0 :             return 0;
     185           2 :         return dfVal;
     186             :     }
     187             : 
     188             :     //
     189           5 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     190             :                     double *pdfData) override
     191             :     {
     192           5 :         if (eRWFlag != GF_Read)
     193             :         {
     194           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     195             :                      "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
     196             :                      "eRWFlag != GF_Read not supported");
     197           0 :             return CE_Failure;
     198             :         }
     199           9 :         if (iStartRow < 0 || iLength <= 0 ||
     200           4 :             iStartRow > GetRowCount() - iLength)
     201             :         {
     202           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
     203           2 :             return CE_Failure;
     204             :         }
     205           3 :         if (iField < 0 || iField >= GetColumnCount())
     206             :         {
     207           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
     208           2 :             return CE_Failure;
     209             :         }
     210           1 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
     211           1 :         const size_t count[1] = {static_cast<size_t>(iLength)};
     212           1 :         const GInt64 arrayStep[1] = {1};
     213           1 :         const GPtrDiff_t bufferStride[1] = {1};
     214           2 :         if (!m_apoArrays[iField]->Read(
     215             :                 arrayStartIdx, count, arrayStep, bufferStride,
     216           2 :                 GDALExtendedDataType::Create(GDT_Float64), pdfData))
     217           0 :             return CE_Failure;
     218           1 :         return CE_None;
     219             :     }
     220             : 
     221             :     //
     222           5 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     223             :                     int *pnData) override
     224             :     {
     225           5 :         if (eRWFlag != GF_Read)
     226             :         {
     227           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     228             :                      "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
     229             :                      "eRWFlag != GF_Read not supported");
     230           0 :             return CE_Failure;
     231             :         }
     232           9 :         if (iStartRow < 0 || iLength <= 0 ||
     233           4 :             iStartRow > GetRowCount() - iLength)
     234             :         {
     235           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
     236           2 :             return CE_Failure;
     237             :         }
     238           3 :         if (iField < 0 || iField >= GetColumnCount())
     239             :         {
     240           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
     241           2 :             return CE_Failure;
     242             :         }
     243           1 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
     244           1 :         const size_t count[1] = {static_cast<size_t>(iLength)};
     245           1 :         const GInt64 arrayStep[1] = {1};
     246           1 :         const GPtrDiff_t bufferStride[1] = {1};
     247           2 :         if (!m_apoArrays[iField]->Read(
     248             :                 arrayStartIdx, count, arrayStep, bufferStride,
     249           2 :                 GDALExtendedDataType::Create(GDT_Int32), pnData))
     250           0 :             return CE_Failure;
     251           1 :         return CE_None;
     252             :     }
     253             : 
     254             :     //
     255           5 :     CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
     256             :                     char **papszStrList) override
     257             :     {
     258           5 :         if (eRWFlag != GF_Read)
     259             :         {
     260           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     261             :                      "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
     262             :                      "eRWFlag != GF_Read not supported");
     263           0 :             return CE_Failure;
     264             :         }
     265           9 :         if (iStartRow < 0 || iLength <= 0 ||
     266           4 :             iStartRow > GetRowCount() - iLength)
     267             :         {
     268           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
     269           2 :             return CE_Failure;
     270             :         }
     271           3 :         if (iField < 0 || iField >= GetColumnCount())
     272             :         {
     273           2 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
     274           2 :             return CE_Failure;
     275             :         }
     276           1 :         const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
     277           1 :         const size_t count[1] = {static_cast<size_t>(iLength)};
     278           1 :         const GInt64 arrayStep[1] = {1};
     279           1 :         const GPtrDiff_t bufferStride[1] = {1};
     280           2 :         if (!m_apoArrays[iField]->Read(
     281             :                 arrayStartIdx, count, arrayStep, bufferStride,
     282           2 :                 GDALExtendedDataType::CreateString(), papszStrList))
     283           0 :             return CE_Failure;
     284           1 :         return CE_None;
     285             :     }
     286             : 
     287             :     //
     288           1 :     void SetValue(int, int, const char *) override
     289             :     {
     290           1 :         CPLError(
     291             :             CE_Failure, CPLE_NotSupported,
     292             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     293           1 :     }
     294             : 
     295             :     //
     296           1 :     void SetValue(int, int, int) override
     297             :     {
     298           1 :         CPLError(
     299             :             CE_Failure, CPLE_NotSupported,
     300             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     301           1 :     }
     302             : 
     303             :     //
     304           1 :     void SetValue(int, int, double) override
     305             :     {
     306           1 :         CPLError(
     307             :             CE_Failure, CPLE_NotSupported,
     308             :             "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
     309           1 :     }
     310             : 
     311             :     //
     312           1 :     int ChangesAreWrittenToFile() override
     313             :     {
     314           1 :         return false;
     315             :     }
     316             : 
     317             :     //
     318           1 :     CPLErr SetTableType(const GDALRATTableType) override
     319             :     {
     320           1 :         CPLError(CE_Failure, CPLE_NotSupported,
     321             :                  "GDALRasterAttributeTableFromMDArrays::SetTableType(): not "
     322             :                  "supported");
     323           1 :         return CE_Failure;
     324             :     }
     325             : 
     326             :     //
     327           1 :     void RemoveStatistics() override
     328             :     {
     329           1 :     }
     330             : 
     331             :     //
     332           1 :     GDALRATTableType GetTableType() const override
     333             :     {
     334           1 :         return m_eTableType;
     335             :     }
     336             : };
     337             : 
     338             : /************************************************************************/
     339             : /*               GDALRasterAttributeTableFromMDArrays()                 */
     340             : /************************************************************************/
     341             : 
     342           3 : GDALRasterAttributeTableFromMDArrays::GDALRasterAttributeTableFromMDArrays(
     343             :     GDALRATTableType eTableType,
     344             :     const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
     345           3 :     const std::vector<GDALRATFieldUsage> &aeUsages)
     346           3 :     : m_eTableType(eTableType), m_apoArrays(apoArrays), m_aeUsages(aeUsages)
     347             : {
     348           3 : }
     349             : 
     350             : /************************************************************************/
     351             : /*             GDALCreateRasterAttributeTableFromMDArrays()             */
     352             : /************************************************************************/
     353             : 
     354             : /** Return a virtual Raster Attribute Table from several GDALMDArray's.
     355             :  *
     356             :  * All arrays must be single-dimensional and be indexed by the same dimension.
     357             :  *
     358             :  * This is the same as the C function GDALCreateRasterAttributeTableFromMDArrays().
     359             :  *
     360             :  * @param eTableType RAT table type
     361             :  * @param apoArrays Vector of GDALMDArray's (none of them should be nullptr)
     362             :  * @param aeUsages Vector of GDALRATFieldUsage (of the same size as apoArrays if non-empty), or empty vector to use defaults
     363             :  * @return a new Raster Attribute Table to free with delete, or nullptr in case of error
     364             :  * @since 3.9
     365             :  */
     366           5 : GDALRasterAttributeTable *GDALCreateRasterAttributeTableFromMDArrays(
     367             :     GDALRATTableType eTableType,
     368             :     const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
     369             :     const std::vector<GDALRATFieldUsage> &aeUsages)
     370             : {
     371           5 :     if (apoArrays.empty())
     372             :     {
     373           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     374             :                  "GDALCreateRasterAttributeTableFromMDArrays(): apoArrays "
     375             :                  "should not be empty");
     376           1 :         return nullptr;
     377             :     }
     378           4 :     if (!aeUsages.empty() && apoArrays.size() != aeUsages.size())
     379             :     {
     380           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     381             :                  "GDALCreateRasterAttributeTableFromMDArrays(): aeUsages "
     382             :                  "should be empty or have the same size as apoArrays");
     383           0 :         return nullptr;
     384             :     }
     385          11 :     for (size_t i = 0; i < apoArrays.size(); ++i)
     386             :     {
     387           9 :         if (apoArrays[i]->GetDimensionCount() != 1)
     388             :         {
     389           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     390             :                      "GDALCreateRasterAttributeTableFromMDArrays(): "
     391             :                      "apoArrays[%d] has a dimension count != 1",
     392             :                      static_cast<int>(i));
     393           1 :             return nullptr;
     394             :         }
     395          17 :         if (i > 0 && (apoArrays[i]->GetDimensions()[0]->GetFullName() !=
     396           9 :                           apoArrays[0]->GetDimensions()[0]->GetFullName() ||
     397           4 :                       apoArrays[i]->GetDimensions()[0]->GetSize() !=
     398           4 :                           apoArrays[0]->GetDimensions()[0]->GetSize()))
     399             :         {
     400           1 :             CPLError(
     401             :                 CE_Failure, CPLE_AppDefined,
     402             :                 "GDALCreateRasterAttributeTableFromMDArrays(): apoArrays[%d] "
     403             :                 "does not have the same dimension has apoArrays[0]",
     404             :                 static_cast<int>(i));
     405           1 :             return nullptr;
     406             :         }
     407             :     }
     408             :     return new GDALRasterAttributeTableFromMDArrays(eTableType, apoArrays,
     409           2 :                                                     aeUsages);
     410             : }
     411             : 
     412             : /************************************************************************/
     413             : /*             GDALCreateRasterAttributeTableFromMDArrays()             */
     414             : /************************************************************************/
     415             : 
     416             : /** Return a virtual Raster Attribute Table from several GDALMDArray's.
     417             :  *
     418             :  * All arrays must be single-dimensional and be indexed by the same dimension.
     419             :  *
     420             :  * This is the same as the C++ method GDALCreateRasterAttributeTableFromMDArrays().
     421             :  *
     422             :  * @param eTableType RAT table type
     423             :  * @param nArrays Number of elements in ahArrays parameter
     424             :  * @param ahArrays Array of nArrays GDALMDArray's (none of them should be nullptr)
     425             :  * @param paeUsages Array of nArray GDALRATFieldUsage, or nullptr to use defaults
     426             :  * @return a new Raster Attribute Table to free with GDALDestroyRasterAttributeTable(), or nullptr in case of error
     427             :  * @since 3.9
     428             :  */
     429           5 : GDALRasterAttributeTableH GDALCreateRasterAttributeTableFromMDArrays(
     430             :     GDALRATTableType eTableType, int nArrays, const GDALMDArrayH *ahArrays,
     431             :     const GDALRATFieldUsage *paeUsages)
     432             : {
     433           5 :     VALIDATE_POINTER1(ahArrays, __func__, nullptr);
     434          10 :     std::vector<std::shared_ptr<GDALMDArray>> apoArrays;
     435          10 :     std::vector<GDALRATFieldUsage> aeUsages;
     436          14 :     for (int i = 0; i < nArrays; ++i)
     437             :     {
     438           9 :         VALIDATE_POINTER1(ahArrays[i], __func__, nullptr);
     439           9 :         apoArrays.emplace_back(ahArrays[i]->m_poImpl);
     440           9 :         if (paeUsages)
     441           3 :             aeUsages.emplace_back(paeUsages[i]);
     442             :     }
     443           5 :     return GDALRasterAttributeTable::ToHandle(
     444             :         GDALCreateRasterAttributeTableFromMDArrays(eTableType, apoArrays,
     445           5 :                                                    aeUsages));
     446             : }

Generated by: LCOV version 1.14