LCOV - code coverage report
Current view: top level - frmts/kea - kearat.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 376 499 75.4 %
Date: 2024-11-21 22:18:42 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         352 : KEARasterAttributeTable::KEARasterAttributeTable(
      16         352 :     kealib::KEAAttributeTable *poKEATable, KEARasterBand *poBand)
      17             : {
      18         352 :     this->m_hMutex = CPLCreateMutex();
      19         352 :     CPLReleaseMutex(this->m_hMutex);
      20         398 :     for (size_t nColumnIndex = 0;
      21         398 :          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(sKEAField);
      35             :     }
      36         352 :     m_poKEATable = poKEATable;
      37         352 :     m_poBand = poBand;
      38         352 : }
      39             : 
      40         704 : KEARasterAttributeTable::~KEARasterAttributeTable()
      41             : {
      42             :     // can't just delete thanks to Windows
      43         352 :     kealib::KEAAttributeTable::destroyAttributeTable(m_poKEATable);
      44         352 :     CPLDestroyMutex(m_hMutex);
      45         352 :     m_hMutex = nullptr;
      46         704 : }
      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         428 : int KEARasterAttributeTable::GetRowCount() const
     293             : {
     294         428 :     return (int)m_poKEATable->getSize();
     295             : }
     296             : 
     297           7 : const char *KEARasterAttributeTable::GetValueAsString(int iRow,
     298             :                                                       int iField) const
     299             : {
     300             :     // Get ValuesIO do 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             :     // Get ValuesIO do 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             :     // Get ValuesIO do 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 : void KEARasterAttributeTable::SetValue(int iRow, int iField,
     342             :                                        const char *pszValue)
     343             : {
     344             :     // Get ValuesIO do do the work
     345           3 :     ValuesIO(GF_Write, iField, iRow, 1, const_cast<char **>(&pszValue));
     346           3 : }
     347             : 
     348           3 : void KEARasterAttributeTable::SetValue(int iRow, int iField, double dfValue)
     349             : {
     350             :     // Get ValuesIO do do the work
     351           3 :     ValuesIO(GF_Write, iField, iRow, 1, &dfValue);
     352           3 : }
     353             : 
     354          39 : void KEARasterAttributeTable::SetValue(int iRow, int iField, int nValue)
     355             : {
     356             :     // Get ValuesIO do do the work
     357          39 :     ValuesIO(GF_Write, iField, iRow, 1, &nValue);
     358          39 : }
     359             : 
     360          24 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     361             :                                          int iStartRow, int iLength,
     362             :                                          double *pdfData)
     363             : {
     364             :     /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
     365             :     {
     366             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     367             :             "Dataset not open in update mode");
     368             :         return CE_Failure;
     369             :     }*/
     370          48 :     CPLMutexHolderD(&m_hMutex);
     371             : 
     372          24 :     if (iField < 0 || iField >= (int)m_aoFields.size())
     373             :     {
     374           1 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
     375             :                  iField);
     376             : 
     377           1 :         return CE_Failure;
     378             :     }
     379             : 
     380          23 :     if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
     381             :     {
     382           2 :         CPLError(CE_Failure, CPLE_AppDefined,
     383             :                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
     384             :                  iLength);
     385             : 
     386           2 :         return CE_Failure;
     387             :     }
     388             : 
     389          21 :     switch (m_aoFields[iField].dataType)
     390             :     {
     391           2 :         case kealib::kea_att_bool:
     392             :         case kealib::kea_att_int:
     393             :         {
     394             :             // allocate space for ints
     395           2 :             int *panColData = (int *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int));
     396           2 :             if (panColData == nullptr)
     397             :             {
     398           0 :                 return CE_Failure;
     399             :             }
     400             : 
     401           2 :             if (eRWFlag == GF_Write)
     402             :             {
     403             :                 // copy the application supplied doubles to ints
     404           2 :                 for (int i = 0; i < iLength; i++)
     405           1 :                     panColData[i] = static_cast<int>(pdfData[i]);
     406             :             }
     407             : 
     408             :             // do the ValuesIO as ints
     409             :             CPLErr eVal =
     410           2 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
     411           2 :             if (eVal != CE_None)
     412             :             {
     413           0 :                 CPLFree(panColData);
     414           0 :                 return eVal;
     415             :             }
     416             : 
     417           2 :             if (eRWFlag == GF_Read)
     418             :             {
     419             :                 // copy them back to doubles
     420           2 :                 for (int i = 0; i < iLength; i++)
     421           1 :                     pdfData[i] = panColData[i];
     422             :             }
     423             : 
     424           2 :             CPLFree(panColData);
     425             :         }
     426           2 :         break;
     427          17 :         case kealib::kea_att_float:
     428             :         {
     429             :             try
     430             :             {
     431          17 :                 if (eRWFlag == GF_Read)
     432          12 :                     m_poKEATable->getFloatFields(
     433          12 :                         iStartRow, iLength, m_aoFields[iField].idx, pdfData);
     434             :                 else
     435           5 :                     m_poKEATable->setFloatFields(
     436           5 :                         iStartRow, iLength, m_aoFields[iField].idx, pdfData);
     437             :             }
     438           0 :             catch (kealib::KEAException &e)
     439             :             {
     440           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     441           0 :                          "Failed to read/write attribute table: %s", e.what());
     442           0 :                 return CE_Failure;
     443             :             }
     444             :         }
     445          17 :         break;
     446           2 :         case kealib::kea_att_string:
     447             :         {
     448             :             // allocate space for string pointers
     449             :             char **papszColData =
     450           2 :                 (char **)VSI_MALLOC2_VERBOSE(iLength, sizeof(char *));
     451           2 :             if (papszColData == nullptr)
     452             :             {
     453           0 :                 return CE_Failure;
     454             :             }
     455             : 
     456           2 :             if (eRWFlag == GF_Write)
     457             :             {
     458             :                 // copy the application supplied doubles to strings
     459           2 :                 for (int i = 0; i < iLength; i++)
     460             :                 {
     461           1 :                     osWorkingResult.Printf("%.16g", pdfData[i]);
     462           1 :                     papszColData[i] = CPLStrdup(osWorkingResult);
     463             :                 }
     464             :             }
     465             : 
     466             :             // do the ValuesIO as strings
     467             :             CPLErr eVal =
     468           2 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData);
     469           2 :             if (eVal != CE_None)
     470             :             {
     471           0 :                 if (eRWFlag == GF_Write)
     472             :                 {
     473           0 :                     for (int i = 0; i < iLength; i++)
     474           0 :                         CPLFree(papszColData[i]);
     475             :                 }
     476           0 :                 CPLFree(papszColData);
     477           0 :                 return eVal;
     478             :             }
     479             : 
     480           2 :             if (eRWFlag == GF_Read)
     481             :             {
     482             :                 // copy them back to doubles
     483           2 :                 for (int i = 0; i < iLength; i++)
     484           1 :                     pdfData[i] = CPLAtof(papszColData[i]);
     485             :             }
     486             : 
     487             :             // either we allocated them for write, or they were allocated
     488             :             // by ValuesIO on read
     489           4 :             for (int i = 0; i < iLength; i++)
     490           2 :                 CPLFree(papszColData[i]);
     491             : 
     492           2 :             CPLFree(papszColData);
     493             :         }
     494           2 :         break;
     495           0 :         default:
     496           0 :             break;
     497             :     }
     498          21 :     return CE_None;
     499             : }
     500             : 
     501          98 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     502             :                                          int iStartRow, int iLength,
     503             :                                          int *pnData)
     504             : {
     505             :     /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
     506             :     {
     507             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     508             :             "Dataset not open in update mode");
     509             :         return CE_Failure;
     510             :     }*/
     511         196 :     CPLMutexHolderD(&m_hMutex);
     512             : 
     513          98 :     if (iField < 0 || iField >= (int)m_aoFields.size())
     514             :     {
     515           1 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
     516             :                  iField);
     517             : 
     518           1 :         return CE_Failure;
     519             :     }
     520             : 
     521          97 :     if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
     522             :     {
     523           2 :         CPLError(CE_Failure, CPLE_AppDefined,
     524             :                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
     525             :                  iLength);
     526             : 
     527           2 :         return CE_Failure;
     528             :     }
     529             : 
     530          95 :     switch (m_aoFields[iField].dataType)
     531             :     {
     532           0 :         case kealib::kea_att_bool:
     533             :         {
     534             :             // need to convert to/from bools
     535             :             bool *panColData =
     536           0 :                 (bool *)VSI_MALLOC2_VERBOSE(iLength, sizeof(bool));
     537           0 :             if (panColData == nullptr)
     538             :             {
     539           0 :                 return CE_Failure;
     540             :             }
     541             : 
     542           0 :             if (eRWFlag == GF_Write)
     543             :             {
     544             :                 // copy the application supplied ints to bools
     545           0 :                 for (int i = 0; i < iLength; i++)
     546             :                 {
     547           0 :                     panColData[i] = (pnData[i] != 0);
     548             :                 }
     549             :             }
     550             : 
     551             :             try
     552             :             {
     553           0 :                 if (eRWFlag == GF_Read)
     554           0 :                     m_poKEATable->getBoolFields(
     555           0 :                         iStartRow, iLength, m_aoFields[iField].idx, panColData);
     556             :                 else
     557           0 :                     m_poKEATable->setBoolFields(
     558           0 :                         iStartRow, iLength, m_aoFields[iField].idx, panColData);
     559             :             }
     560           0 :             catch (kealib::KEAException &e)
     561             :             {
     562           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     563           0 :                          "Failed to read/write attribute table: %s", e.what());
     564           0 :                 return CE_Failure;
     565             :             }
     566             : 
     567           0 :             if (eRWFlag == GF_Read)
     568             :             {
     569             :                 // copy them back to ints
     570           0 :                 for (int i = 0; i < iLength; i++)
     571           0 :                     pnData[i] = panColData[i] ? 1 : 0;
     572             :             }
     573           0 :             CPLFree(panColData);
     574             :         }
     575           0 :         break;
     576          90 :         case kealib::kea_att_int:
     577             :         {
     578             :             // need to convert to/from int64_t
     579             :             int64_t *panColData =
     580          90 :                 (int64_t *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int64_t));
     581          90 :             if (panColData == nullptr)
     582             :             {
     583           0 :                 return CE_Failure;
     584             :             }
     585             : 
     586          90 :             if (eRWFlag == GF_Write)
     587             :             {
     588             :                 // copy the application supplied ints to int64t
     589          86 :                 for (int i = 0; i < iLength; i++)
     590          43 :                     panColData[i] = pnData[i];
     591             :             }
     592             : 
     593             :             try
     594             :             {
     595          90 :                 if (eRWFlag == GF_Read)
     596          47 :                     m_poKEATable->getIntFields(
     597          47 :                         iStartRow, iLength, m_aoFields[iField].idx, panColData);
     598             :                 else
     599          43 :                     m_poKEATable->setIntFields(
     600          43 :                         iStartRow, iLength, m_aoFields[iField].idx, panColData);
     601             :             }
     602           0 :             catch (kealib::KEAException &e)
     603             :             {
     604             :                 // fprintf(stderr,"Failed to read/write attribute table: %s %d
     605             :                 // %d %ld\n", e.what(), iStartRow, iLength,
     606             :                 // m_poKEATable->getSize() );
     607           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     608           0 :                          "Failed to read/write attribute table: %s", e.what());
     609           0 :                 return CE_Failure;
     610             :             }
     611             : 
     612          90 :             if (eRWFlag == GF_Read)
     613             :             {
     614             :                 // copy them back to ints
     615         110 :                 for (int i = 0; i < iLength; i++)
     616          63 :                     pnData[i] = static_cast<int>(panColData[i]);
     617             :             }
     618          90 :             CPLFree(panColData);
     619             :         }
     620          90 :         break;
     621           3 :         case kealib::kea_att_float:
     622             :         {
     623             :             // allocate space for doubles
     624             :             double *padfColData =
     625           3 :                 (double *)VSI_MALLOC2_VERBOSE(iLength, sizeof(double));
     626           3 :             if (padfColData == nullptr)
     627             :             {
     628           0 :                 return CE_Failure;
     629             :             }
     630             : 
     631           3 :             if (eRWFlag == GF_Write)
     632             :             {
     633             :                 // copy the application supplied ints to doubles
     634           2 :                 for (int i = 0; i < iLength; i++)
     635           1 :                     padfColData[i] = pnData[i];
     636             :             }
     637             : 
     638             :             // do the ValuesIO as doubles
     639             :             CPLErr eVal =
     640           3 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
     641           3 :             if (eVal != CE_None)
     642             :             {
     643           0 :                 CPLFree(padfColData);
     644           0 :                 return eVal;
     645             :             }
     646             : 
     647           3 :             if (eRWFlag == GF_Read)
     648             :             {
     649             :                 // copy them back to ints
     650           4 :                 for (int i = 0; i < iLength; i++)
     651           2 :                     pnData[i] = static_cast<int>(padfColData[i]);
     652             :             }
     653             : 
     654           3 :             CPLFree(padfColData);
     655             :         }
     656           3 :         break;
     657           2 :         case kealib::kea_att_string:
     658             :         {
     659             :             // allocate space for string pointers
     660             :             char **papszColData =
     661           2 :                 (char **)VSI_MALLOC2_VERBOSE(iLength, sizeof(char *));
     662           2 :             if (papszColData == nullptr)
     663             :             {
     664           0 :                 return CE_Failure;
     665             :             }
     666             : 
     667           2 :             if (eRWFlag == GF_Write)
     668             :             {
     669             :                 // copy the application supplied ints to strings
     670           2 :                 for (int i = 0; i < iLength; i++)
     671             :                 {
     672           1 :                     osWorkingResult.Printf("%d", pnData[i]);
     673           1 :                     papszColData[i] = CPLStrdup(osWorkingResult);
     674             :                 }
     675             :             }
     676             : 
     677             :             // do the ValuesIO as strings
     678             :             CPLErr eVal =
     679           2 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData);
     680           2 :             if (eVal != CE_None)
     681             :             {
     682           0 :                 if (eRWFlag == GF_Write)
     683             :                 {
     684           0 :                     for (int i = 0; i < iLength; i++)
     685           0 :                         CPLFree(papszColData[i]);
     686             :                 }
     687           0 :                 CPLFree(papszColData);
     688           0 :                 return eVal;
     689             :             }
     690             : 
     691           2 :             if (eRWFlag == GF_Read)
     692             :             {
     693             :                 // copy them back to ints
     694           2 :                 for (int i = 0; i < iLength; i++)
     695           1 :                     pnData[i] = atoi(papszColData[i]);
     696             :             }
     697             : 
     698             :             // either we allocated them for write, or they were allocated
     699             :             // by ValuesIO on read
     700           4 :             for (int i = 0; i < iLength; i++)
     701           2 :                 CPLFree(papszColData[i]);
     702             : 
     703           2 :             CPLFree(papszColData);
     704             :         }
     705           2 :         break;
     706           0 :         default:
     707           0 :             break;
     708             :     }
     709          95 :     return CE_None;
     710             : }
     711             : 
     712          18 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     713             :                                          int iStartRow, int iLength,
     714             :                                          char **papszStrList)
     715             : {
     716             :     /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
     717             :     {
     718             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     719             :             "Dataset not open in update mode");
     720             :         return CE_Failure;
     721             :     }*/
     722          36 :     CPLMutexHolderD(&m_hMutex);
     723             : 
     724          18 :     if (iField < 0 || iField >= (int)m_aoFields.size())
     725             :     {
     726           1 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
     727             :                  iField);
     728             : 
     729           1 :         return CE_Failure;
     730             :     }
     731             : 
     732          17 :     if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
     733             :     {
     734           2 :         CPLError(CE_Failure, CPLE_AppDefined,
     735             :                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
     736             :                  iLength);
     737             : 
     738           2 :         return CE_Failure;
     739             :     }
     740             : 
     741          15 :     switch (m_aoFields[iField].dataType)
     742             :     {
     743           2 :         case kealib::kea_att_bool:
     744             :         case kealib::kea_att_int:
     745             :         {
     746             :             // allocate space for ints
     747           2 :             int *panColData = (int *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int));
     748           2 :             if (panColData == nullptr)
     749             :             {
     750           0 :                 return CE_Failure;
     751             :             }
     752           2 :             if (eRWFlag == GF_Write)
     753             :             {
     754             :                 // convert user supplied strings to ints
     755           2 :                 for (int i = 0; i < iLength; i++)
     756           1 :                     panColData[i] = atoi(papszStrList[i]);
     757             :             }
     758             : 
     759             :             // call values IO to read/write ints
     760             :             CPLErr eVal =
     761           2 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
     762           2 :             if (eVal != CE_None)
     763             :             {
     764           0 :                 CPLFree(panColData);
     765           0 :                 return eVal;
     766             :             }
     767             : 
     768           2 :             if (eRWFlag == GF_Read)
     769             :             {
     770             :                 // convert ints back to strings
     771           2 :                 for (int i = 0; i < iLength; i++)
     772             :                 {
     773           1 :                     osWorkingResult.Printf("%d", panColData[i]);
     774           1 :                     papszStrList[i] = CPLStrdup(osWorkingResult);
     775             :                 }
     776             :             }
     777           2 :             CPLFree(panColData);
     778             :         }
     779           2 :         break;
     780           3 :         case kealib::kea_att_float:
     781             :         {
     782             :             // allocate space for doubles
     783             :             double *padfColData =
     784           3 :                 (double *)VSI_MALLOC2_VERBOSE(iLength, sizeof(double));
     785           3 :             if (padfColData == nullptr)
     786             :             {
     787           0 :                 return CE_Failure;
     788             :             }
     789             : 
     790           3 :             if (eRWFlag == GF_Write)
     791             :             {
     792             :                 // convert user supplied strings to doubles
     793           2 :                 for (int i = 0; i < iLength; i++)
     794           1 :                     padfColData[i] = CPLAtof(papszStrList[i]);
     795             :             }
     796             : 
     797             :             // call value IO to read/write doubles
     798             :             CPLErr eVal =
     799           3 :                 ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
     800           3 :             if (eVal != CE_None)
     801             :             {
     802           0 :                 CPLFree(padfColData);
     803           0 :                 return eVal;
     804             :             }
     805             : 
     806           3 :             if (eRWFlag == GF_Read)
     807             :             {
     808             :                 // convert doubles back to strings
     809           4 :                 for (int i = 0; i < iLength; i++)
     810             :                 {
     811           2 :                     osWorkingResult.Printf("%.16g", padfColData[i]);
     812           2 :                     papszStrList[i] = CPLStrdup(osWorkingResult);
     813             :                 }
     814             :             }
     815           3 :             CPLFree(padfColData);
     816             :         }
     817           3 :         break;
     818          10 :         case kealib::kea_att_string:
     819             :         {
     820             :             try
     821             :             {
     822          10 :                 if (eRWFlag == GF_Read)
     823             :                 {
     824          12 :                     std::vector<std::string> aStrings;
     825           6 :                     m_poKEATable->getStringFields(
     826           6 :                         iStartRow, iLength, m_aoFields[iField].idx, &aStrings);
     827           6 :                     for (std::vector<std::string>::size_type i = 0;
     828          12 :                          i < aStrings.size(); i++)
     829             :                     {
     830             :                         // Copy using CPLStrdup so user can call CPLFree
     831           6 :                         papszStrList[i] = CPLStrdup(aStrings[i].c_str());
     832             :                     }
     833             :                 }
     834             :                 else
     835             :                 {
     836             :                     // need to convert to a vector first
     837           8 :                     std::vector<std::string> aStrings;
     838           8 :                     for (int i = 0; i < iLength; i++)
     839             :                     {
     840           4 :                         aStrings.push_back(papszStrList[i]);
     841             :                     }
     842           4 :                     m_poKEATable->setStringFields(
     843           4 :                         iStartRow, iLength, m_aoFields[iField].idx, &aStrings);
     844             :                 }
     845             :             }
     846           0 :             catch (kealib::KEAException &e)
     847             :             {
     848           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     849           0 :                          "Failed to read/write attribute table: %s", e.what());
     850           0 :                 return CE_Failure;
     851             :             }
     852             :         }
     853          10 :         break;
     854           0 :         default:
     855           0 :             break;
     856             :     }
     857          15 :     return CE_None;
     858             : }
     859             : 
     860           0 : int KEARasterAttributeTable::ChangesAreWrittenToFile()
     861             : {
     862           0 :     return TRUE;
     863             : }
     864             : 
     865           5 : void KEARasterAttributeTable::SetRowCount(int iCount)
     866             : {
     867             :     /*if( this->eAccess == GA_ReadOnly )
     868             :     {
     869             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     870             :             "Dataset not open in update mode");
     871             :         return;
     872             :     }*/
     873             : 
     874           5 :     if (iCount > (int)m_poKEATable->getSize())
     875             :     {
     876           3 :         m_poKEATable->addRows(iCount - m_poKEATable->getSize());
     877             :     }
     878             :     // can't shrink
     879           5 : }
     880             : 
     881          15 : CPLErr KEARasterAttributeTable::CreateColumn(const char *pszFieldName,
     882             :                                              GDALRATFieldType eFieldType,
     883             :                                              GDALRATFieldUsage eFieldUsage)
     884             : {
     885             :     /*if( this->eAccess == GA_ReadOnly )
     886             :     {
     887             :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     888             :             "Dataset not open in update mode");
     889             :         return CE_Failure;
     890             :     }*/
     891          30 :     CPLMutexHolderD(&m_hMutex);
     892             : 
     893          15 :     const char *strUsage = "Generic";
     894          15 :     switch (eFieldUsage)
     895             :     {
     896           1 :         case GFU_PixelCount:
     897           1 :             strUsage = "PixelCount";
     898           1 :             eFieldType = GFT_Real;
     899           1 :             break;
     900           1 :         case GFU_Name:
     901           1 :             strUsage = "Name";
     902           1 :             eFieldType = GFT_String;
     903           1 :             break;
     904           3 :         case GFU_Red:
     905           3 :             strUsage = "Red";
     906           3 :             eFieldType = GFT_Integer;
     907           3 :             break;
     908           3 :         case GFU_Green:
     909           3 :             strUsage = "Green";
     910           3 :             eFieldType = GFT_Integer;
     911           3 :             break;
     912           3 :         case GFU_Blue:
     913           3 :             strUsage = "Blue";
     914           3 :             eFieldType = GFT_Integer;
     915           3 :             break;
     916           3 :         case GFU_Alpha:
     917           3 :             strUsage = "Alpha";
     918           3 :             eFieldType = GFT_Integer;
     919           3 :             break;
     920           1 :         default:
     921             :             // leave as "Generic"
     922           1 :             break;
     923             :     }
     924             : 
     925             :     try
     926             :     {
     927          15 :         if (eFieldType == GFT_Integer)
     928             :         {
     929          12 :             m_poKEATable->addAttIntField(pszFieldName, 0, strUsage);
     930             :         }
     931           3 :         else if (eFieldType == GFT_Real)
     932             :         {
     933           2 :             m_poKEATable->addAttFloatField(pszFieldName, 0, strUsage);
     934             :         }
     935             :         else
     936             :         {
     937           1 :             m_poKEATable->addAttStringField(pszFieldName, "", strUsage);
     938             :         }
     939             : 
     940             :         // assume we can just grab this now
     941          45 :         kealib::KEAATTField sKEAField = m_poKEATable->getField(pszFieldName);
     942          15 :         m_aoFields.push_back(sKEAField);
     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