LCOV - code coverage report
Current view: top level - frmts/kea - kearat.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 373 496 75.2 %
Date: 2025-05-31 00:00:17 Functions: 22 27 81.5 %

          Line data    Source code
       1             : /*
       2             :  *  kearat.cpp
       3             :  *
       4             :  *  Created by Pete Bunting on 01/08/2012.
       5             :  *  Copyright 2012 LibKEA. All rights reserved.
       6             :  *
       7             :  *  This file is part of LibKEA.
       8             :  *
       9             :  * SPDX-License-Identifier: MIT
      10             :  *
      11             :  */
      12             : 
      13             : #include "kearat.h"
      14             : 
      15         405 : KEARasterAttributeTable::KEARasterAttributeTable(
      16         405 :     kealib::KEAAttributeTable *poKEATable, KEARasterBand *poBand)
      17             : {
      18         405 :     this->m_hMutex = CPLCreateMutex();
      19         405 :     CPLReleaseMutex(this->m_hMutex);
      20         451 :     for (size_t nColumnIndex = 0;
      21         451 :          nColumnIndex < poKEATable->getMaxGlobalColIdx(); nColumnIndex++)
      22             :     {
      23          46 :         kealib::KEAATTField sKEAField;
      24             :         try
      25             :         {
      26          46 :             sKEAField = poKEATable->getField(nColumnIndex);
      27             :         }
      28           0 :         catch (const kealib::KEAATTException &)
      29             :         {
      30             :             // pKEATable->getField raised exception because we have a missing
      31             :             // column
      32           0 :             continue;
      33             :         }
      34          46 :         m_aoFields.push_back(std::move(sKEAField));
      35             :     }
      36         405 :     m_poKEATable = poKEATable;
      37         405 :     m_poBand = poBand;
      38         405 : }
      39             : 
      40         810 : KEARasterAttributeTable::~KEARasterAttributeTable()
      41             : {
      42             :     // can't just delete thanks to Windows
      43         405 :     kealib::KEAAttributeTable::destroyAttributeTable(m_poKEATable);
      44         405 :     CPLDestroyMutex(m_hMutex);
      45         405 :     m_hMutex = nullptr;
      46         810 : }
      47             : 
      48           1 : GDALDefaultRasterAttributeTable *KEARasterAttributeTable::Clone() const
      49             : {
      50           1 :     if ((GetRowCount() * GetColumnCount()) > RAT_MAX_ELEM_FOR_CLONE)
      51           0 :         return nullptr;
      52             : 
      53             :     GDALDefaultRasterAttributeTable *poRAT =
      54           1 :         new GDALDefaultRasterAttributeTable();
      55             : 
      56           8 :     for (int iCol = 0; iCol < (int)m_aoFields.size(); iCol++)
      57             :     {
      58           7 :         CPLString sName = m_aoFields[iCol].name;
      59           7 :         CPLString sUsage = m_aoFields[iCol].usage;
      60             :         GDALRATFieldUsage eGDALUsage;
      61           7 :         if (sUsage == "PixelCount")
      62           1 :             eGDALUsage = GFU_PixelCount;
      63           6 :         else if (sUsage == "Name")
      64           1 :             eGDALUsage = GFU_Name;
      65           5 :         else if (sUsage == "Red")
      66           1 :             eGDALUsage = GFU_Red;
      67           4 :         else if (sUsage == "Green")
      68           1 :             eGDALUsage = GFU_Green;
      69           3 :         else if (sUsage == "Blue")
      70           1 :             eGDALUsage = GFU_Blue;
      71           2 :         else if (sUsage == "Alpha")
      72           1 :             eGDALUsage = GFU_Alpha;
      73             :         else
      74             :         {
      75             :             // don't recognise any other special names - generic column
      76           1 :             eGDALUsage = GFU_Generic;
      77             :         }
      78             : 
      79             :         GDALRATFieldType eGDALType;
      80           7 :         switch (m_aoFields[iCol].dataType)
      81             :         {
      82           4 :             case kealib::kea_att_bool:
      83             :             case kealib::kea_att_int:
      84           4 :                 eGDALType = GFT_Integer;
      85           4 :                 break;
      86           2 :             case kealib::kea_att_float:
      87           2 :                 eGDALType = GFT_Real;
      88           2 :                 break;
      89           1 :             case kealib::kea_att_string:
      90           1 :                 eGDALType = GFT_String;
      91           1 :                 break;
      92           0 :             default:
      93           0 :                 eGDALType = GFT_Integer;
      94           0 :                 break;
      95             :         }
      96           7 :         poRAT->CreateColumn(sName, eGDALType, eGDALUsage);
      97           7 :         poRAT->SetRowCount(static_cast<int>(m_poKEATable->getSize()));
      98             : 
      99           7 :         if (m_poKEATable->getSize() == 0)
     100           0 :             continue;
     101             : 
     102           7 :         if (eGDALType == GFT_Integer)
     103             :         {
     104           4 :             int *panColData = (int *)VSI_MALLOC2_VERBOSE(
     105             :                 sizeof(int), m_poKEATable->getSize());
     106           4 :             if (panColData == nullptr)
     107             :             {
     108           0 :                 delete poRAT;
     109           0 :                 return nullptr;
     110             :             }
     111             : 
     112           4 :             if ((const_cast<KEARasterAttributeTable *>(this))
     113           8 :                     ->ValuesIO(GF_Read, iCol, 0,
     114           4 :                                static_cast<int>(m_poKEATable->getSize()),
     115           8 :                                panColData) != CE_None)
     116             :             {
     117           0 :                 CPLFree(panColData);
     118           0 :                 delete poRAT;
     119           0 :                 return nullptr;
     120             :             }
     121             : 
     122           8 :             for (int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++)
     123             :             {
     124           4 :                 poRAT->SetValue(iRow, iCol, panColData[iRow]);
     125             :             }
     126           4 :             CPLFree(panColData);
     127             :         }
     128           7 :         if (eGDALType == GFT_Real)
     129             :         {
     130           2 :             double *padfColData = (double *)VSI_MALLOC2_VERBOSE(
     131             :                 sizeof(double), m_poKEATable->getSize());
     132           2 :             if (padfColData == nullptr)
     133             :             {
     134           0 :                 delete poRAT;
     135           0 :                 return nullptr;
     136             :             }
     137           2 :             if ((const_cast<KEARasterAttributeTable *>(this))
     138           4 :                     ->ValuesIO(GF_Read, iCol, 0,
     139           2 :                                static_cast<int>(m_poKEATable->getSize()),
     140           4 :                                padfColData) != CE_None)
     141             :             {
     142           0 :                 CPLFree(padfColData);
     143           0 :                 delete poRAT;
     144           0 :                 return nullptr;
     145             :             }
     146             : 
     147           4 :             for (int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++)
     148             :             {
     149           2 :                 poRAT->SetValue(iRow, iCol, padfColData[iRow]);
     150             :             }
     151           2 :             CPLFree(padfColData);
     152             :         }
     153           7 :         if (eGDALType == GFT_String)
     154             :         {
     155           1 :             char **papszColData = (char **)VSI_MALLOC2_VERBOSE(
     156             :                 sizeof(char *), m_poKEATable->getSize());
     157           1 :             if (papszColData == nullptr)
     158             :             {
     159           0 :                 delete poRAT;
     160           0 :                 return nullptr;
     161             :             }
     162             : 
     163           1 :             if ((const_cast<KEARasterAttributeTable *>(this))
     164           2 :                     ->ValuesIO(GF_Read, iCol, 0,
     165           1 :                                static_cast<int>(m_poKEATable->getSize()),
     166           2 :                                papszColData) != CE_None)
     167             :             {
     168           0 :                 CPLFree(papszColData);
     169           0 :                 delete poRAT;
     170           0 :                 return nullptr;
     171             :             }
     172             : 
     173           2 :             for (int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++)
     174             :             {
     175           1 :                 poRAT->SetValue(iRow, iCol, papszColData[iRow]);
     176           1 :                 CPLFree(papszColData[iRow]);
     177             :             }
     178           1 :             CPLFree(papszColData);
     179             :         }
     180             :     }
     181             : 
     182           1 :     poRAT->SetTableType(this->GetTableType());
     183             : 
     184           1 :     return poRAT;
     185             : }
     186             : 
     187          79 : int KEARasterAttributeTable::GetColumnCount() const
     188             : {
     189          79 :     return (int)m_aoFields.size();
     190             : }
     191             : 
     192          61 : const char *KEARasterAttributeTable::GetNameOfCol(int nCol) const
     193             : {
     194          61 :     if ((nCol < 0) || (nCol >= (int)m_aoFields.size()))
     195           2 :         return nullptr;
     196             : 
     197          59 :     return m_aoFields[nCol].name.c_str();
     198             : }
     199             : 
     200          43 : GDALRATFieldUsage KEARasterAttributeTable::GetUsageOfCol(int nCol) const
     201             : {
     202          43 :     if ((nCol < 0) || (nCol >= (int)m_aoFields.size()))
     203           2 :         return GFU_Generic;
     204             : 
     205             :     GDALRATFieldUsage eGDALUsage;
     206          41 :     std::string keausage = m_aoFields[nCol].usage;
     207             : 
     208          41 :     if (keausage == "PixelCount")
     209           3 :         eGDALUsage = GFU_PixelCount;
     210          38 :     else if (keausage == "Name")
     211           3 :         eGDALUsage = GFU_Name;
     212          35 :     else if (keausage == "Red")
     213           8 :         eGDALUsage = GFU_Red;
     214          27 :     else if (keausage == "Green")
     215           8 :         eGDALUsage = GFU_Green;
     216          19 :     else if (keausage == "Blue")
     217           8 :         eGDALUsage = GFU_Blue;
     218          11 :     else if (keausage == "Alpha")
     219           8 :         eGDALUsage = GFU_Alpha;
     220             :     else
     221             :     {
     222             :         // don't recognise any other special names - generic column
     223           3 :         eGDALUsage = GFU_Generic;
     224             :     }
     225             : 
     226          41 :     return eGDALUsage;
     227             : }
     228             : 
     229          44 : GDALRATFieldType KEARasterAttributeTable::GetTypeOfCol(int nCol) const
     230             : {
     231          44 :     if ((nCol < 0) || (nCol >= (int)m_aoFields.size()))
     232           2 :         return GFT_Integer;
     233             : 
     234             :     GDALRATFieldType eGDALType;
     235          42 :     switch (m_aoFields[nCol].dataType)
     236             :     {
     237          32 :         case kealib::kea_att_bool:
     238             :         case kealib::kea_att_int:
     239          32 :             eGDALType = GFT_Integer;
     240          32 :             break;
     241           7 :         case kealib::kea_att_float:
     242           7 :             eGDALType = GFT_Real;
     243           7 :             break;
     244           3 :         case kealib::kea_att_string:
     245           3 :             eGDALType = GFT_String;
     246           3 :             break;
     247           0 :         default:
     248           0 :             eGDALType = GFT_Integer;
     249           0 :             break;
     250             :     }
     251          42 :     return eGDALType;
     252             : }
     253             : 
     254           7 : int KEARasterAttributeTable::GetColOfUsage(GDALRATFieldUsage eUsage) const
     255             : {
     256             :     unsigned int i;
     257             : 
     258          14 :     std::string keausage;
     259           7 :     switch (eUsage)
     260             :     {
     261           1 :         case GFU_PixelCount:
     262           1 :             keausage = "PixelCount";
     263           1 :             break;
     264           1 :         case GFU_Name:
     265           1 :             keausage = "Name";
     266           1 :             break;
     267           1 :         case GFU_Red:
     268           1 :             keausage = "Red";
     269           1 :             break;
     270           1 :         case GFU_Green:
     271           1 :             keausage = "Green";
     272           1 :             break;
     273           1 :         case GFU_Blue:
     274           1 :             keausage = "Blue";
     275           1 :             break;
     276           1 :         case GFU_Alpha:
     277           1 :             keausage = "Alpha";
     278           1 :             break;
     279           1 :         default:
     280           1 :             keausage = "Generic";
     281           1 :             break;
     282             :     }
     283             : 
     284          28 :     for (i = 0; i < m_aoFields.size(); i++)
     285             :     {
     286          28 :         if (m_aoFields[i].usage == keausage)
     287           7 :             return i;
     288             :     }
     289           0 :     return -1;
     290             : }
     291             : 
     292         481 : int KEARasterAttributeTable::GetRowCount() const
     293             : {
     294         481 :     return (int)m_poKEATable->getSize();
     295             : }
     296             : 
     297           7 : const char *KEARasterAttributeTable::GetValueAsString(int iRow,
     298             :                                                       int iField) const
     299             : {
     300             :     /// Let ValuesIO do the work.
     301             :     char *apszStrList[1];
     302           7 :     if ((const_cast<KEARasterAttributeTable *>(this))
     303           7 :             ->ValuesIO(GF_Read, iField, iRow, 1, apszStrList) != CE_None)
     304             :     {
     305           3 :         return "";
     306             :     }
     307             : 
     308             :     const_cast<KEARasterAttributeTable *>(this)->osWorkingResult =
     309           4 :         apszStrList[0];
     310           4 :     CPLFree(apszStrList[0]);
     311             : 
     312           4 :     return osWorkingResult;
     313             : }
     314             : 
     315          31 : int KEARasterAttributeTable::GetValueAsInt(int iRow, int iField) const
     316             : {
     317             :     // Let ValuesIO do the work.
     318          31 :     int nValue = 0;
     319          31 :     if ((const_cast<KEARasterAttributeTable *>(this))
     320          31 :             ->ValuesIO(GF_Read, iField, iRow, 1, &nValue) != CE_None)
     321             :     {
     322           3 :         return 0;
     323             :     }
     324             : 
     325          28 :     return nValue;
     326             : }
     327             : 
     328           7 : double KEARasterAttributeTable::GetValueAsDouble(int iRow, int iField) const
     329             : {
     330             :     // Let ValuesIO do the work.
     331           7 :     double dfValue = 0.0;
     332           7 :     if ((const_cast<KEARasterAttributeTable *>(this))
     333           7 :             ->ValuesIO(GF_Read, iField, iRow, 1, &dfValue) != CE_None)
     334             :     {
     335           3 :         return 0;
     336             :     }
     337             : 
     338           4 :     return dfValue;
     339             : }
     340             : 
     341           3 : CPLErr KEARasterAttributeTable::SetValue(int iRow, int iField,
     342             :                                          const char *pszValue)
     343             : {
     344             :     // Let ValuesIO do the work.
     345           3 :     char *apszValues[1] = {const_cast<char *>(pszValue)};
     346           6 :     return ValuesIO(GF_Write, iField, iRow, 1, apszValues);
     347             : }
     348             : 
     349           3 : CPLErr KEARasterAttributeTable::SetValue(int iRow, int iField, double dfValue)
     350             : {
     351             :     // Let ValuesIO do the work.
     352           3 :     return ValuesIO(GF_Write, iField, iRow, 1, &dfValue);
     353             : }
     354             : 
     355          39 : CPLErr KEARasterAttributeTable::SetValue(int iRow, int iField, int nValue)
     356             : {
     357             :     // Let ValuesIO do the work.
     358          39 :     return ValuesIO(GF_Write, iField, iRow, 1, &nValue);
     359             : }
     360             : 
     361          24 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     362             :                                          int iStartRow, int iLength,
     363             :                                          double *pdfData)
     364             : {
     365             :     /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
     366             :     {
     367             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     368             :             "Dataset not open in update mode");
     369             :         return CE_Failure;
     370             :     }*/
     371          48 :     CPLMutexHolderD(&m_hMutex);
     372             : 
     373          24 :     if (iField < 0 || iField >= (int)m_aoFields.size())
     374             :     {
     375           1 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
     376             :                  iField);
     377             : 
     378           1 :         return CE_Failure;
     379             :     }
     380             : 
     381          23 :     if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
     382             :     {
     383           2 :         CPLError(CE_Failure, CPLE_AppDefined,
     384             :                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
     385             :                  iLength);
     386             : 
     387           2 :         return CE_Failure;
     388             :     }
     389             : 
     390          21 :     switch (m_aoFields[iField].dataType)
     391             :     {
     392           2 :         case kealib::kea_att_bool:
     393             :         case kealib::kea_att_int:
     394             :         {
     395             :             // allocate space for ints
     396           2 :             int *panColData = (int *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int));
     397           2 :             if (panColData == nullptr)
     398             :             {
     399           0 :                 return CE_Failure;
     400             :             }
     401             : 
     402           2 :             if (eRWFlag == GF_Write)
     403             :             {
     404             :                 // copy the application supplied doubles to ints
     405           2 :                 for (int i = 0; i < iLength; i++)
     406           1 :                     panColData[i] = static_cast<int>(pdfData[i]);
     407             :             }
     408             : 
     409             :             // do the ValuesIO as ints
     410             :             CPLErr eVal =
     411           2 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
     412           2 :             if (eVal != CE_None)
     413             :             {
     414           0 :                 CPLFree(panColData);
     415           0 :                 return eVal;
     416             :             }
     417             : 
     418           2 :             if (eRWFlag == GF_Read)
     419             :             {
     420             :                 // copy them back to doubles
     421           2 :                 for (int i = 0; i < iLength; i++)
     422           1 :                     pdfData[i] = panColData[i];
     423             :             }
     424             : 
     425           2 :             CPLFree(panColData);
     426             :         }
     427           2 :         break;
     428          17 :         case kealib::kea_att_float:
     429             :         {
     430             :             try
     431             :             {
     432          17 :                 if (eRWFlag == GF_Read)
     433          12 :                     m_poKEATable->getFloatFields(
     434          12 :                         iStartRow, iLength, m_aoFields[iField].idx, pdfData);
     435             :                 else
     436           5 :                     m_poKEATable->setFloatFields(
     437           5 :                         iStartRow, iLength, m_aoFields[iField].idx, pdfData);
     438             :             }
     439           0 :             catch (kealib::KEAException &e)
     440             :             {
     441           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     442           0 :                          "Failed to read/write attribute table: %s", e.what());
     443           0 :                 return CE_Failure;
     444             :             }
     445             :         }
     446          17 :         break;
     447           2 :         case kealib::kea_att_string:
     448             :         {
     449             :             // allocate space for string pointers
     450             :             char **papszColData =
     451           2 :                 (char **)VSI_MALLOC2_VERBOSE(iLength, sizeof(char *));
     452           2 :             if (papszColData == nullptr)
     453             :             {
     454           0 :                 return CE_Failure;
     455             :             }
     456             : 
     457           2 :             if (eRWFlag == GF_Write)
     458             :             {
     459             :                 // copy the application supplied doubles to strings
     460           2 :                 for (int i = 0; i < iLength; i++)
     461             :                 {
     462           1 :                     osWorkingResult.Printf("%.16g", pdfData[i]);
     463           1 :                     papszColData[i] = CPLStrdup(osWorkingResult);
     464             :                 }
     465             :             }
     466             : 
     467             :             // do the ValuesIO as strings
     468             :             CPLErr eVal =
     469           2 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData);
     470           2 :             if (eVal != CE_None)
     471             :             {
     472           0 :                 if (eRWFlag == GF_Write)
     473             :                 {
     474           0 :                     for (int i = 0; i < iLength; i++)
     475           0 :                         CPLFree(papszColData[i]);
     476             :                 }
     477           0 :                 CPLFree(papszColData);
     478           0 :                 return eVal;
     479             :             }
     480             : 
     481           2 :             if (eRWFlag == GF_Read)
     482             :             {
     483             :                 // copy them back to doubles
     484           2 :                 for (int i = 0; i < iLength; i++)
     485           1 :                     pdfData[i] = CPLAtof(papszColData[i]);
     486             :             }
     487             : 
     488             :             // either we allocated them for write, or they were allocated
     489             :             // by ValuesIO on read
     490           4 :             for (int i = 0; i < iLength; i++)
     491           2 :                 CPLFree(papszColData[i]);
     492             : 
     493           2 :             CPLFree(papszColData);
     494             :         }
     495           2 :         break;
     496           0 :         default:
     497           0 :             break;
     498             :     }
     499          21 :     return CE_None;
     500             : }
     501             : 
     502          98 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     503             :                                          int iStartRow, int iLength,
     504             :                                          int *pnData)
     505             : {
     506             :     /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
     507             :     {
     508             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     509             :             "Dataset not open in update mode");
     510             :         return CE_Failure;
     511             :     }*/
     512         196 :     CPLMutexHolderD(&m_hMutex);
     513             : 
     514          98 :     if (iField < 0 || iField >= (int)m_aoFields.size())
     515             :     {
     516           1 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
     517             :                  iField);
     518             : 
     519           1 :         return CE_Failure;
     520             :     }
     521             : 
     522          97 :     if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
     523             :     {
     524           2 :         CPLError(CE_Failure, CPLE_AppDefined,
     525             :                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
     526             :                  iLength);
     527             : 
     528           2 :         return CE_Failure;
     529             :     }
     530             : 
     531          95 :     switch (m_aoFields[iField].dataType)
     532             :     {
     533           0 :         case kealib::kea_att_bool:
     534             :         {
     535             :             // need to convert to/from bools
     536             :             bool *panColData =
     537           0 :                 (bool *)VSI_MALLOC2_VERBOSE(iLength, sizeof(bool));
     538           0 :             if (panColData == nullptr)
     539             :             {
     540           0 :                 return CE_Failure;
     541             :             }
     542             : 
     543           0 :             if (eRWFlag == GF_Write)
     544             :             {
     545             :                 // copy the application supplied ints to bools
     546           0 :                 for (int i = 0; i < iLength; i++)
     547             :                 {
     548           0 :                     panColData[i] = (pnData[i] != 0);
     549             :                 }
     550             :             }
     551             : 
     552             :             try
     553             :             {
     554           0 :                 if (eRWFlag == GF_Read)
     555           0 :                     m_poKEATable->getBoolFields(
     556           0 :                         iStartRow, iLength, m_aoFields[iField].idx, panColData);
     557             :                 else
     558           0 :                     m_poKEATable->setBoolFields(
     559           0 :                         iStartRow, iLength, m_aoFields[iField].idx, panColData);
     560             :             }
     561           0 :             catch (kealib::KEAException &e)
     562             :             {
     563           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     564           0 :                          "Failed to read/write attribute table: %s", e.what());
     565           0 :                 return CE_Failure;
     566             :             }
     567             : 
     568           0 :             if (eRWFlag == GF_Read)
     569             :             {
     570             :                 // copy them back to ints
     571           0 :                 for (int i = 0; i < iLength; i++)
     572           0 :                     pnData[i] = panColData[i] ? 1 : 0;
     573             :             }
     574           0 :             CPLFree(panColData);
     575             :         }
     576           0 :         break;
     577          90 :         case kealib::kea_att_int:
     578             :         {
     579             :             // need to convert to/from int64_t
     580             :             int64_t *panColData =
     581          90 :                 (int64_t *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int64_t));
     582          90 :             if (panColData == nullptr)
     583             :             {
     584           0 :                 return CE_Failure;
     585             :             }
     586             : 
     587          90 :             if (eRWFlag == GF_Write)
     588             :             {
     589             :                 // copy the application supplied ints to int64t
     590          86 :                 for (int i = 0; i < iLength; i++)
     591          43 :                     panColData[i] = pnData[i];
     592             :             }
     593             : 
     594             :             try
     595             :             {
     596          90 :                 if (eRWFlag == GF_Read)
     597          47 :                     m_poKEATable->getIntFields(
     598          47 :                         iStartRow, iLength, m_aoFields[iField].idx, panColData);
     599             :                 else
     600          43 :                     m_poKEATable->setIntFields(
     601          43 :                         iStartRow, iLength, m_aoFields[iField].idx, panColData);
     602             :             }
     603           0 :             catch (kealib::KEAException &e)
     604             :             {
     605             :                 // fprintf(stderr,"Failed to read/write attribute table: %s %d
     606             :                 // %d %ld\n", e.what(), iStartRow, iLength,
     607             :                 // m_poKEATable->getSize() );
     608           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     609           0 :                          "Failed to read/write attribute table: %s", e.what());
     610           0 :                 return CE_Failure;
     611             :             }
     612             : 
     613          90 :             if (eRWFlag == GF_Read)
     614             :             {
     615             :                 // copy them back to ints
     616         110 :                 for (int i = 0; i < iLength; i++)
     617          63 :                     pnData[i] = static_cast<int>(panColData[i]);
     618             :             }
     619          90 :             CPLFree(panColData);
     620             :         }
     621          90 :         break;
     622           3 :         case kealib::kea_att_float:
     623             :         {
     624             :             // allocate space for doubles
     625             :             double *padfColData =
     626           3 :                 (double *)VSI_MALLOC2_VERBOSE(iLength, sizeof(double));
     627           3 :             if (padfColData == nullptr)
     628             :             {
     629           0 :                 return CE_Failure;
     630             :             }
     631             : 
     632           3 :             if (eRWFlag == GF_Write)
     633             :             {
     634             :                 // copy the application supplied ints to doubles
     635           2 :                 for (int i = 0; i < iLength; i++)
     636           1 :                     padfColData[i] = pnData[i];
     637             :             }
     638             : 
     639             :             // do the ValuesIO as doubles
     640             :             CPLErr eVal =
     641           3 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
     642           3 :             if (eVal != CE_None)
     643             :             {
     644           0 :                 CPLFree(padfColData);
     645           0 :                 return eVal;
     646             :             }
     647             : 
     648           3 :             if (eRWFlag == GF_Read)
     649             :             {
     650             :                 // copy them back to ints
     651           4 :                 for (int i = 0; i < iLength; i++)
     652           2 :                     pnData[i] = static_cast<int>(padfColData[i]);
     653             :             }
     654             : 
     655           3 :             CPLFree(padfColData);
     656             :         }
     657           3 :         break;
     658           2 :         case kealib::kea_att_string:
     659             :         {
     660             :             // allocate space for string pointers
     661             :             char **papszColData =
     662           2 :                 (char **)VSI_MALLOC2_VERBOSE(iLength, sizeof(char *));
     663           2 :             if (papszColData == nullptr)
     664             :             {
     665           0 :                 return CE_Failure;
     666             :             }
     667             : 
     668           2 :             if (eRWFlag == GF_Write)
     669             :             {
     670             :                 // copy the application supplied ints to strings
     671           2 :                 for (int i = 0; i < iLength; i++)
     672             :                 {
     673           1 :                     osWorkingResult.Printf("%d", pnData[i]);
     674           1 :                     papszColData[i] = CPLStrdup(osWorkingResult);
     675             :                 }
     676             :             }
     677             : 
     678             :             // do the ValuesIO as strings
     679             :             CPLErr eVal =
     680           2 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData);
     681           2 :             if (eVal != CE_None)
     682             :             {
     683           0 :                 if (eRWFlag == GF_Write)
     684             :                 {
     685           0 :                     for (int i = 0; i < iLength; i++)
     686           0 :                         CPLFree(papszColData[i]);
     687             :                 }
     688           0 :                 CPLFree(papszColData);
     689           0 :                 return eVal;
     690             :             }
     691             : 
     692           2 :             if (eRWFlag == GF_Read)
     693             :             {
     694             :                 // copy them back to ints
     695           2 :                 for (int i = 0; i < iLength; i++)
     696           1 :                     pnData[i] = atoi(papszColData[i]);
     697             :             }
     698             : 
     699             :             // either we allocated them for write, or they were allocated
     700             :             // by ValuesIO on read
     701           4 :             for (int i = 0; i < iLength; i++)
     702           2 :                 CPLFree(papszColData[i]);
     703             : 
     704           2 :             CPLFree(papszColData);
     705             :         }
     706           2 :         break;
     707           0 :         default:
     708           0 :             break;
     709             :     }
     710          95 :     return CE_None;
     711             : }
     712             : 
     713          18 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     714             :                                          int iStartRow, int iLength,
     715             :                                          char **papszStrList)
     716             : {
     717             :     /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
     718             :     {
     719             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     720             :             "Dataset not open in update mode");
     721             :         return CE_Failure;
     722             :     }*/
     723          36 :     CPLMutexHolderD(&m_hMutex);
     724             : 
     725          18 :     if (iField < 0 || iField >= (int)m_aoFields.size())
     726             :     {
     727           1 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
     728             :                  iField);
     729             : 
     730           1 :         return CE_Failure;
     731             :     }
     732             : 
     733          17 :     if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
     734             :     {
     735           2 :         CPLError(CE_Failure, CPLE_AppDefined,
     736             :                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
     737             :                  iLength);
     738             : 
     739           2 :         return CE_Failure;
     740             :     }
     741             : 
     742          15 :     switch (m_aoFields[iField].dataType)
     743             :     {
     744           2 :         case kealib::kea_att_bool:
     745             :         case kealib::kea_att_int:
     746             :         {
     747             :             // allocate space for ints
     748           2 :             int *panColData = (int *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int));
     749           2 :             if (panColData == nullptr)
     750             :             {
     751           0 :                 return CE_Failure;
     752             :             }
     753           2 :             if (eRWFlag == GF_Write)
     754             :             {
     755             :                 // convert user supplied strings to ints
     756           2 :                 for (int i = 0; i < iLength; i++)
     757           1 :                     panColData[i] = atoi(papszStrList[i]);
     758             :             }
     759             : 
     760             :             // call values IO to read/write ints
     761             :             CPLErr eVal =
     762           2 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
     763           2 :             if (eVal != CE_None)
     764             :             {
     765           0 :                 CPLFree(panColData);
     766           0 :                 return eVal;
     767             :             }
     768             : 
     769           2 :             if (eRWFlag == GF_Read)
     770             :             {
     771             :                 // convert ints back to strings
     772           2 :                 for (int i = 0; i < iLength; i++)
     773             :                 {
     774           1 :                     osWorkingResult.Printf("%d", panColData[i]);
     775           1 :                     papszStrList[i] = CPLStrdup(osWorkingResult);
     776             :                 }
     777             :             }
     778           2 :             CPLFree(panColData);
     779             :         }
     780           2 :         break;
     781           3 :         case kealib::kea_att_float:
     782             :         {
     783             :             // allocate space for doubles
     784             :             double *padfColData =
     785           3 :                 (double *)VSI_MALLOC2_VERBOSE(iLength, sizeof(double));
     786           3 :             if (padfColData == nullptr)
     787             :             {
     788           0 :                 return CE_Failure;
     789             :             }
     790             : 
     791           3 :             if (eRWFlag == GF_Write)
     792             :             {
     793             :                 // convert user supplied strings to doubles
     794           2 :                 for (int i = 0; i < iLength; i++)
     795           1 :                     padfColData[i] = CPLAtof(papszStrList[i]);
     796             :             }
     797             : 
     798             :             // call value IO to read/write doubles
     799             :             CPLErr eVal =
     800           3 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
     801           3 :             if (eVal != CE_None)
     802             :             {
     803           0 :                 CPLFree(padfColData);
     804           0 :                 return eVal;
     805             :             }
     806             : 
     807           3 :             if (eRWFlag == GF_Read)
     808             :             {
     809             :                 // convert doubles back to strings
     810           4 :                 for (int i = 0; i < iLength; i++)
     811             :                 {
     812           2 :                     osWorkingResult.Printf("%.16g", padfColData[i]);
     813           2 :                     papszStrList[i] = CPLStrdup(osWorkingResult);
     814             :                 }
     815             :             }
     816           3 :             CPLFree(padfColData);
     817             :         }
     818           3 :         break;
     819          10 :         case kealib::kea_att_string:
     820             :         {
     821             :             try
     822             :             {
     823          10 :                 if (eRWFlag == GF_Read)
     824             :                 {
     825          12 :                     std::vector<std::string> aStrings;
     826           6 :                     m_poKEATable->getStringFields(
     827           6 :                         iStartRow, iLength, m_aoFields[iField].idx, &aStrings);
     828           6 :                     for (std::vector<std::string>::size_type i = 0;
     829          12 :                          i < aStrings.size(); i++)
     830             :                     {
     831             :                         // Copy using CPLStrdup so user can call CPLFree
     832           6 :                         papszStrList[i] = CPLStrdup(aStrings[i].c_str());
     833             :                     }
     834             :                 }
     835             :                 else
     836             :                 {
     837             :                     // need to convert to a vector first
     838           8 :                     std::vector<std::string> aStrings;
     839           8 :                     for (int i = 0; i < iLength; i++)
     840             :                     {
     841           4 :                         aStrings.push_back(papszStrList[i]);
     842             :                     }
     843           4 :                     m_poKEATable->setStringFields(
     844           4 :                         iStartRow, iLength, m_aoFields[iField].idx, &aStrings);
     845             :                 }
     846             :             }
     847           0 :             catch (kealib::KEAException &e)
     848             :             {
     849           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     850           0 :                          "Failed to read/write attribute table: %s", e.what());
     851           0 :                 return CE_Failure;
     852             :             }
     853             :         }
     854          10 :         break;
     855           0 :         default:
     856           0 :             break;
     857             :     }
     858          15 :     return CE_None;
     859             : }
     860             : 
     861           0 : int KEARasterAttributeTable::ChangesAreWrittenToFile()
     862             : {
     863           0 :     return TRUE;
     864             : }
     865             : 
     866           5 : void KEARasterAttributeTable::SetRowCount(int iCount)
     867             : {
     868             :     /*if( this->eAccess == GA_ReadOnly )
     869             :     {
     870             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     871             :             "Dataset not open in update mode");
     872             :         return;
     873             :     }*/
     874             : 
     875           5 :     if (iCount > (int)m_poKEATable->getSize())
     876             :     {
     877           3 :         m_poKEATable->addRows(iCount - m_poKEATable->getSize());
     878             :     }
     879             :     // can't shrink
     880           5 : }
     881             : 
     882          15 : CPLErr KEARasterAttributeTable::CreateColumn(const char *pszFieldName,
     883             :                                              GDALRATFieldType eFieldType,
     884             :                                              GDALRATFieldUsage eFieldUsage)
     885             : {
     886             :     /*if( this->eAccess == GA_ReadOnly )
     887             :     {
     888             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     889             :             "Dataset not open in update mode");
     890             :         return CE_Failure;
     891             :     }*/
     892          30 :     CPLMutexHolderD(&m_hMutex);
     893             : 
     894          15 :     const char *strUsage = "Generic";
     895          15 :     switch (eFieldUsage)
     896             :     {
     897           1 :         case GFU_PixelCount:
     898           1 :             strUsage = "PixelCount";
     899           1 :             eFieldType = GFT_Real;
     900           1 :             break;
     901           1 :         case GFU_Name:
     902           1 :             strUsage = "Name";
     903           1 :             eFieldType = GFT_String;
     904           1 :             break;
     905           3 :         case GFU_Red:
     906           3 :             strUsage = "Red";
     907           3 :             eFieldType = GFT_Integer;
     908           3 :             break;
     909           3 :         case GFU_Green:
     910           3 :             strUsage = "Green";
     911           3 :             eFieldType = GFT_Integer;
     912           3 :             break;
     913           3 :         case GFU_Blue:
     914           3 :             strUsage = "Blue";
     915           3 :             eFieldType = GFT_Integer;
     916           3 :             break;
     917           3 :         case GFU_Alpha:
     918           3 :             strUsage = "Alpha";
     919           3 :             eFieldType = GFT_Integer;
     920           3 :             break;
     921           1 :         default:
     922             :             // leave as "Generic"
     923           1 :             break;
     924             :     }
     925             : 
     926             :     try
     927             :     {
     928          15 :         if (eFieldType == GFT_Integer)
     929             :         {
     930          12 :             m_poKEATable->addAttIntField(pszFieldName, 0, strUsage);
     931             :         }
     932           3 :         else if (eFieldType == GFT_Real)
     933             :         {
     934           2 :             m_poKEATable->addAttFloatField(pszFieldName, 0, strUsage);
     935             :         }
     936             :         else
     937             :         {
     938           1 :             m_poKEATable->addAttStringField(pszFieldName, "", strUsage);
     939             :         }
     940             : 
     941             :         // assume we can just grab this now
     942          15 :         m_aoFields.push_back(m_poKEATable->getField(pszFieldName));
     943             :     }
     944           0 :     catch (kealib::KEAException &e)
     945             :     {
     946           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Failed to add column: %s",
     947           0 :                  e.what());
     948           0 :         return CE_Failure;
     949             :     }
     950             : 
     951          15 :     return CE_None;
     952             : }
     953             : 
     954           0 : CPLErr KEARasterAttributeTable::SetLinearBinning(double ldfRow0Min,
     955             :                                                  double ldfBinSize)
     956             : {
     957           0 :     size_t nRows = m_poKEATable->getSize();
     958             : 
     959           0 :     osWorkingResult.Printf("%.16g", ldfRow0Min);
     960           0 :     m_poBand->SetMetadataItem("STATISTICS_HISTOMIN", osWorkingResult);
     961           0 :     osWorkingResult.Printf("%.16g", (nRows - 1) * ldfBinSize + ldfRow0Min);
     962           0 :     m_poBand->SetMetadataItem("STATISTICS_HISTOMAX", osWorkingResult);
     963             : 
     964             :     // STATISTICS_HISTONUMBINS now returned by metadata
     965             : 
     966           0 :     return CE_None;
     967             : }
     968             : 
     969           0 : int KEARasterAttributeTable::GetLinearBinning(double *pdfRow0Min,
     970             :                                               double *pdfBinSize) const
     971             : {
     972           0 :     const char *pszMin = m_poBand->GetMetadataItem("STATISTICS_HISTOMIN");
     973           0 :     const char *pszMax = m_poBand->GetMetadataItem("STATISTICS_HISTOMAX");
     974           0 :     if ((pszMin == nullptr) || (pszMax == nullptr))
     975             :     {
     976           0 :         return FALSE;
     977             :     }
     978           0 :     *pdfRow0Min = atof(pszMin);
     979           0 :     *pdfBinSize = (atof(pszMax) - *pdfRow0Min) / (m_poKEATable->getSize() - 1);
     980             : 
     981           0 :     return TRUE;
     982             : }
     983             : 
     984           0 : CPLXMLNode *KEARasterAttributeTable::Serialize() const
     985             : {
     986           0 :     if ((GetRowCount() * GetColumnCount()) > RAT_MAX_ELEM_FOR_CLONE)
     987           0 :         return nullptr;
     988             : 
     989           0 :     return GDALRasterAttributeTable::Serialize();
     990             : }
     991             : 
     992           1 : GDALRATTableType KEARasterAttributeTable::GetTableType() const
     993             : {
     994           1 :     kealib::KEALayerType keaType = m_poBand->getLayerType();
     995           1 :     if (keaType == kealib::kea_continuous)
     996             :     {
     997           1 :         return GRTT_ATHEMATIC;
     998             :     }
     999             :     else
    1000             :     {
    1001           0 :         return GRTT_THEMATIC;
    1002             :     }
    1003             : }
    1004             : 
    1005             : CPLErr
    1006           0 : KEARasterAttributeTable::SetTableType(const GDALRATTableType eInTableType)
    1007             : {
    1008           0 :     kealib::KEALayerType keaType = (eInTableType == GRTT_ATHEMATIC)
    1009           0 :                                        ? kealib::kea_continuous
    1010             :                                        : kealib::kea_thematic;
    1011             :     try
    1012             :     {
    1013           0 :         m_poBand->setLayerType(keaType);
    1014           0 :         return CE_None;
    1015             :     }
    1016           0 :     catch (const kealib::KEAIOException &)
    1017             :     {
    1018           0 :         return CE_Failure;
    1019             :     }
    1020             : }

Generated by: LCOV version 1.14