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

Generated by: LCOV version 1.14