LCOV - code coverage report
Current view: top level - gcore/multidim - gdalmultidim_attribute.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 266 284 93.7 %
Date: 2026-04-15 22:10:00 Functions: 33 40 82.5 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Name:     gdalmultidim_attribute.cpp
       4             :  * Project:  GDAL Core
       5             :  * Purpose:  Implementation of GDALIHasAttribute and GDALAttribute classes
       6             :  * Author:   Even Rouault <even.rouault at spatialys.com>
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2019, Even Rouault <even.rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "gdal_multidim.h"
      15             : 
      16             : #include <limits>
      17             : 
      18             : #if defined(__clang__) || defined(_MSC_VER)
      19             : #define COMPILER_WARNS_ABOUT_ABSTRACT_VBASE_INIT
      20             : #endif
      21             : 
      22             : /************************************************************************/
      23             : /*                         ~GDALIHasAttribute()                         */
      24             : /************************************************************************/
      25             : 
      26             : GDALIHasAttribute::~GDALIHasAttribute() = default;
      27             : 
      28             : /************************************************************************/
      29             : /*                            GetAttribute()                            */
      30             : /************************************************************************/
      31             : 
      32             : /** Return an attribute by its name.
      33             :  *
      34             :  * If the attribute does not exist, nullptr should be silently returned.
      35             :  *
      36             :  * @note Driver implementation: this method will fallback to
      37             :  * GetAttributeFromAttributes() is not explicitly implemented
      38             :  *
      39             :  * Drivers known to implement it for groups and arrays: MEM, netCDF.
      40             :  *
      41             :  * This is the same as the C function GDALGroupGetAttribute() or
      42             :  * GDALMDArrayGetAttribute().
      43             :  *
      44             :  * @param osName Attribute name
      45             :  * @return the attribute, or nullptr if it does not exist or an error occurred.
      46             :  */
      47             : std::shared_ptr<GDALAttribute>
      48       10761 : GDALIHasAttribute::GetAttribute(const std::string &osName) const
      49             : {
      50       10761 :     return GetAttributeFromAttributes(osName);
      51             : }
      52             : 
      53             : /************************************************************************/
      54             : /*                     GetAttributeFromAttributes()                     */
      55             : /************************************************************************/
      56             : 
      57             : /** Possible fallback implementation for GetAttribute() using GetAttributes().
      58             :  */
      59             : std::shared_ptr<GDALAttribute>
      60       10761 : GDALIHasAttribute::GetAttributeFromAttributes(const std::string &osName) const
      61             : {
      62       21522 :     auto attrs(GetAttributes());
      63       85196 :     for (const auto &attr : attrs)
      64             :     {
      65       83404 :         if (attr->GetName() == osName)
      66        8969 :             return attr;
      67             :     }
      68        1792 :     return nullptr;
      69             : }
      70             : 
      71             : /************************************************************************/
      72             : /*                           GetAttributes()                            */
      73             : /************************************************************************/
      74             : 
      75             : /** Return the list of attributes contained in a GDALMDArray or GDALGroup.
      76             :  *
      77             :  * If the attribute does not exist, nullptr should be silently returned.
      78             :  *
      79             :  * @note Driver implementation: optionally implemented. If implemented,
      80             :  * GetAttribute() should also be implemented.
      81             :  *
      82             :  * Drivers known to implement it for groups and arrays: MEM, netCDF.
      83             :  *
      84             :  * This is the same as the C function GDALGroupGetAttributes() or
      85             :  * GDALMDArrayGetAttributes().
      86             : 
      87             :  * @param papszOptions Driver specific options determining how attributes
      88             :  * should be retrieved. Pass nullptr for default behavior.
      89             :  *
      90             :  * @return the attributes.
      91             :  */
      92             : std::vector<std::shared_ptr<GDALAttribute>>
      93         208 : GDALIHasAttribute::GetAttributes(CPL_UNUSED CSLConstList papszOptions) const
      94             : {
      95         208 :     return {};
      96             : }
      97             : 
      98             : /************************************************************************/
      99             : /*                          CreateAttribute()                           */
     100             : /************************************************************************/
     101             : 
     102             : /** Create an attribute within a GDALMDArray or GDALGroup.
     103             :  *
     104             :  * The attribute might not be "physically" created until a value is written
     105             :  * into it.
     106             :  *
     107             :  * Optionally implemented.
     108             :  *
     109             :  * Drivers known to implement it: MEM, netCDF
     110             :  *
     111             :  * This is the same as the C function GDALGroupCreateAttribute() or
     112             :  * GDALMDArrayCreateAttribute()
     113             :  *
     114             :  * @param osName Attribute name.
     115             :  * @param anDimensions List of dimension sizes, ordered from the slowest varying
     116             :  *                     dimension first to the fastest varying dimension last.
     117             :  *                     Empty for a scalar attribute (common case)
     118             :  * @param oDataType  Attribute data type.
     119             :  * @param papszOptions Driver specific options determining how the attribute.
     120             :  * should be created.
     121             :  *
     122             :  * @return the new attribute, or nullptr if case of error
     123             :  */
     124           0 : std::shared_ptr<GDALAttribute> GDALIHasAttribute::CreateAttribute(
     125             :     CPL_UNUSED const std::string &osName,
     126             :     CPL_UNUSED const std::vector<GUInt64> &anDimensions,
     127             :     CPL_UNUSED const GDALExtendedDataType &oDataType,
     128             :     CPL_UNUSED CSLConstList papszOptions)
     129             : {
     130           0 :     CPLError(CE_Failure, CPLE_NotSupported,
     131             :              "CreateAttribute() not implemented");
     132           0 :     return nullptr;
     133             : }
     134             : 
     135             : /************************************************************************/
     136             : /*                          DeleteAttribute()                           */
     137             : /************************************************************************/
     138             : 
     139             : /** Delete an attribute from a GDALMDArray or GDALGroup.
     140             :  *
     141             :  * Optionally implemented.
     142             :  *
     143             :  * After this call, if a previously obtained instance of the deleted object
     144             :  * is still alive, no method other than for freeing it should be invoked.
     145             :  *
     146             :  * Drivers known to implement it: MEM, netCDF
     147             :  *
     148             :  * This is the same as the C function GDALGroupDeleteAttribute() or
     149             :  * GDALMDArrayDeleteAttribute()
     150             :  *
     151             :  * @param osName Attribute name.
     152             :  * @param papszOptions Driver specific options determining how the attribute.
     153             :  * should be deleted.
     154             :  *
     155             :  * @return true in case of success
     156             :  * @since GDAL 3.8
     157             :  */
     158           0 : bool GDALIHasAttribute::DeleteAttribute(CPL_UNUSED const std::string &osName,
     159             :                                         CPL_UNUSED CSLConstList papszOptions)
     160             : {
     161           0 :     CPLError(CE_Failure, CPLE_NotSupported,
     162             :              "DeleteAttribute() not implemented");
     163           0 :     return false;
     164             : }
     165             : 
     166             : /************************************************************************/
     167             : /*                           GDALAttribute()                            */
     168             : /************************************************************************/
     169             : 
     170             : //! @cond Doxygen_Suppress
     171      162248 : GDALAttribute::GDALAttribute(CPL_UNUSED const std::string &osParentName,
     172           0 :                              CPL_UNUSED const std::string &osName)
     173             : #if !defined(COMPILER_WARNS_ABOUT_ABSTRACT_VBASE_INIT)
     174      162248 :     : GDALAbstractMDArray(osParentName, osName)
     175             : #endif
     176             : {
     177      162248 : }
     178             : 
     179             : GDALAttribute::~GDALAttribute() = default;
     180             : 
     181             : //! @endcond
     182             : 
     183             : /************************************************************************/
     184             : /*                          GetDimensionSize()                          */
     185             : /************************************************************************/
     186             : 
     187             : /** Return the size of the dimensions of the attribute.
     188             :  *
     189             :  * This will be an empty array for a scalar (single value) attribute.
     190             :  *
     191             :  * This is the same as the C function GDALAttributeGetDimensionsSize().
     192             :  */
     193         791 : std::vector<GUInt64> GDALAttribute::GetDimensionsSize() const
     194             : {
     195         791 :     const auto &dims = GetDimensions();
     196         791 :     std::vector<GUInt64> ret;
     197         791 :     ret.reserve(dims.size());
     198         974 :     for (const auto &dim : dims)
     199         183 :         ret.push_back(dim->GetSize());
     200         791 :     return ret;
     201             : }
     202             : 
     203             : //! @cond Doxygen_Suppress
     204             : 
     205         206 : GDALAttributeString::GDALAttributeString(const std::string &osParentName,
     206             :                                          const std::string &osName,
     207             :                                          const std::string &osValue,
     208         206 :                                          GDALExtendedDataTypeSubType eSubType)
     209             :     : GDALAbstractMDArray(osParentName, osName),
     210             :       GDALAttribute(osParentName, osName),
     211         206 :       m_dt(GDALExtendedDataType::CreateString(0, eSubType)), m_osValue(osValue)
     212             : {
     213         206 : }
     214             : 
     215             : const std::vector<std::shared_ptr<GDALDimension>> &
     216          96 : GDALAttributeString::GetDimensions() const
     217             : {
     218          96 :     return m_dims;
     219             : }
     220             : 
     221          65 : const GDALExtendedDataType &GDALAttributeString::GetDataType() const
     222             : {
     223          65 :     return m_dt;
     224             : }
     225             : 
     226          32 : bool GDALAttributeString::IRead(const GUInt64 *, const size_t *, const GInt64 *,
     227             :                                 const GPtrDiff_t *,
     228             :                                 const GDALExtendedDataType &bufferDataType,
     229             :                                 void *pDstBuffer) const
     230             : {
     231          32 :     if (bufferDataType.GetClass() != GEDTC_STRING)
     232           0 :         return false;
     233          32 :     char *pszStr = static_cast<char *>(VSIMalloc(m_osValue.size() + 1));
     234          32 :     if (!pszStr)
     235           0 :         return false;
     236          32 :     memcpy(pszStr, m_osValue.c_str(), m_osValue.size() + 1);
     237          32 :     *static_cast<char **>(pDstBuffer) = pszStr;
     238          32 :     return true;
     239             : }
     240             : 
     241          74 : GDALAttributeNumeric::GDALAttributeNumeric(const std::string &osParentName,
     242             :                                            const std::string &osName,
     243          74 :                                            double dfValue)
     244             :     : GDALAbstractMDArray(osParentName, osName),
     245             :       GDALAttribute(osParentName, osName),
     246          74 :       m_dt(GDALExtendedDataType::Create(GDT_Float64)), m_dfValue(dfValue)
     247             : {
     248          74 : }
     249             : 
     250          27 : GDALAttributeNumeric::GDALAttributeNumeric(const std::string &osParentName,
     251             :                                            const std::string &osName,
     252          27 :                                            int nValue)
     253             :     : GDALAbstractMDArray(osParentName, osName),
     254             :       GDALAttribute(osParentName, osName),
     255          27 :       m_dt(GDALExtendedDataType::Create(GDT_Int32)), m_nValue(nValue)
     256             : {
     257          27 : }
     258             : 
     259           7 : GDALAttributeNumeric::GDALAttributeNumeric(const std::string &osParentName,
     260             :                                            const std::string &osName,
     261           7 :                                            const std::vector<GUInt32> &anValues)
     262             :     : GDALAbstractMDArray(osParentName, osName),
     263             :       GDALAttribute(osParentName, osName),
     264           7 :       m_dt(GDALExtendedDataType::Create(GDT_UInt32)), m_anValuesUInt32(anValues)
     265             : {
     266           7 :     m_dims.push_back(std::make_shared<GDALDimension>(
     267          14 :         std::string(), "dim0", std::string(), std::string(),
     268           7 :         m_anValuesUInt32.size()));
     269           7 : }
     270             : 
     271             : const std::vector<std::shared_ptr<GDALDimension>> &
     272          14 : GDALAttributeNumeric::GetDimensions() const
     273             : {
     274          14 :     return m_dims;
     275             : }
     276             : 
     277           8 : const GDALExtendedDataType &GDALAttributeNumeric::GetDataType() const
     278             : {
     279           8 :     return m_dt;
     280             : }
     281             : 
     282           4 : bool GDALAttributeNumeric::IRead(const GUInt64 *arrayStartIdx,
     283             :                                  const size_t *count, const GInt64 *arrayStep,
     284             :                                  const GPtrDiff_t *bufferStride,
     285             :                                  const GDALExtendedDataType &bufferDataType,
     286             :                                  void *pDstBuffer) const
     287             : {
     288           4 :     if (m_dims.empty())
     289             :     {
     290           3 :         if (m_dt.GetNumericDataType() == GDT_Float64)
     291           0 :             GDALExtendedDataType::CopyValue(&m_dfValue, m_dt, pDstBuffer,
     292             :                                             bufferDataType);
     293             :         else
     294             :         {
     295           3 :             CPLAssert(m_dt.GetNumericDataType() == GDT_Int32);
     296           3 :             GDALExtendedDataType::CopyValue(&m_nValue, m_dt, pDstBuffer,
     297             :                                             bufferDataType);
     298             :         }
     299             :     }
     300             :     else
     301             :     {
     302           1 :         CPLAssert(m_dt.GetNumericDataType() == GDT_UInt32);
     303           1 :         GByte *pabyDstBuffer = static_cast<GByte *>(pDstBuffer);
     304          30 :         for (size_t i = 0; i < count[0]; ++i)
     305             :         {
     306          29 :             GDALExtendedDataType::CopyValue(
     307          29 :                 &m_anValuesUInt32[static_cast<size_t>(arrayStartIdx[0] +
     308          29 :                                                       i * arrayStep[0])],
     309          29 :                 m_dt, pabyDstBuffer, bufferDataType);
     310          29 :             pabyDstBuffer += bufferDataType.GetSize() * bufferStride[0];
     311             :         }
     312             :     }
     313           4 :     return true;
     314             : }
     315             : 
     316             : //! @endcond
     317             : 
     318             : /************************************************************************/
     319             : /*                             ReadAsRaw()                              */
     320             : /************************************************************************/
     321             : 
     322             : /** Return the raw value of an attribute.
     323             :  *
     324             :  *
     325             :  * This is the same as the C function GDALAttributeReadAsRaw().
     326             :  */
     327         258 : GDALRawResult GDALAttribute::ReadAsRaw() const
     328             : {
     329         258 :     const auto nEltCount(GetTotalElementsCount());
     330         258 :     const auto &dt(GetDataType());
     331         258 :     const auto nDTSize(dt.GetSize());
     332             :     GByte *res = static_cast<GByte *>(
     333         258 :         VSI_MALLOC2_VERBOSE(static_cast<size_t>(nEltCount), nDTSize));
     334         258 :     if (!res)
     335           0 :         return GDALRawResult(nullptr, dt, 0);
     336         258 :     const auto &dims = GetDimensions();
     337         258 :     const auto nDims = GetDimensionCount();
     338         516 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     339         516 :     std::vector<size_t> count(1 + nDims);
     340         284 :     for (size_t i = 0; i < nDims; i++)
     341             :     {
     342          26 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     343             :     }
     344         258 :     if (!Read(startIdx.data(), count.data(), nullptr, nullptr, dt, &res[0],
     345         258 :               &res[0], static_cast<size_t>(nEltCount * nDTSize)))
     346             :     {
     347           0 :         VSIFree(res);
     348           0 :         return GDALRawResult(nullptr, dt, 0);
     349             :     }
     350         258 :     return GDALRawResult(res, dt, static_cast<size_t>(nEltCount));
     351             : }
     352             : 
     353             : /************************************************************************/
     354             : /*                            ReadAsString()                            */
     355             : /************************************************************************/
     356             : 
     357             : /** Return the value of an attribute as a string.
     358             :  *
     359             :  * The returned string should not be freed, and its lifetime does not
     360             :  * excess a next call to ReadAsString() on the same object, or the deletion
     361             :  * of the object itself.
     362             :  *
     363             :  * This function will only return the first element if there are several.
     364             :  *
     365             :  * This is the same as the C function GDALAttributeReadAsString()
     366             :  *
     367             :  * @return a string, or nullptr.
     368             :  */
     369        4784 : const char *GDALAttribute::ReadAsString() const
     370             : {
     371        4784 :     const auto nDims = GetDimensionCount();
     372        9568 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     373        9568 :     std::vector<size_t> count(1 + nDims, 1);
     374        4784 :     char *szRet = nullptr;
     375        4784 :     if (!Read(startIdx.data(), count.data(), nullptr, nullptr,
     376        4784 :               GDALExtendedDataType::CreateString(), &szRet, &szRet,
     377       14351 :               sizeof(szRet)) ||
     378        4783 :         szRet == nullptr)
     379             :     {
     380           5 :         return nullptr;
     381             :     }
     382        4779 :     m_osCachedVal = szRet;
     383        4779 :     CPLFree(szRet);
     384        4779 :     return m_osCachedVal.c_str();
     385             : }
     386             : 
     387             : /************************************************************************/
     388             : /*                             ReadAsInt()                              */
     389             : /************************************************************************/
     390             : 
     391             : /** Return the value of an attribute as a integer.
     392             :  *
     393             :  * This function will only return the first element if there are several.
     394             :  *
     395             :  * It can fail if its value can not be converted to integer.
     396             :  *
     397             :  * This is the same as the C function GDALAttributeReadAsInt()
     398             :  *
     399             :  * @return a integer, or INT_MIN in case of error.
     400             :  */
     401        2903 : int GDALAttribute::ReadAsInt() const
     402             : {
     403        2903 :     const auto nDims = GetDimensionCount();
     404        5806 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     405        2903 :     std::vector<size_t> count(1 + nDims, 1);
     406        2903 :     int nRet = INT_MIN;
     407        2903 :     Read(startIdx.data(), count.data(), nullptr, nullptr,
     408        5806 :          GDALExtendedDataType::Create(GDT_Int32), &nRet, &nRet, sizeof(nRet));
     409        5806 :     return nRet;
     410             : }
     411             : 
     412             : /************************************************************************/
     413             : /*                            ReadAsInt64()                             */
     414             : /************************************************************************/
     415             : 
     416             : /** Return the value of an attribute as an int64_t.
     417             :  *
     418             :  * This function will only return the first element if there are several.
     419             :  *
     420             :  * It can fail if its value can not be converted to long.
     421             :  *
     422             :  * This is the same as the C function GDALAttributeReadAsInt64()
     423             :  *
     424             :  * @return an int64_t, or INT64_MIN in case of error.
     425             :  */
     426         131 : int64_t GDALAttribute::ReadAsInt64() const
     427             : {
     428         131 :     const auto nDims = GetDimensionCount();
     429         262 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     430         131 :     std::vector<size_t> count(1 + nDims, 1);
     431         131 :     int64_t nRet = INT64_MIN;
     432         131 :     Read(startIdx.data(), count.data(), nullptr, nullptr,
     433         262 :          GDALExtendedDataType::Create(GDT_Int64), &nRet, &nRet, sizeof(nRet));
     434         262 :     return nRet;
     435             : }
     436             : 
     437             : /************************************************************************/
     438             : /*                            ReadAsDouble()                            */
     439             : /************************************************************************/
     440             : 
     441             : /** Return the value of an attribute as a double.
     442             :  *
     443             :  * This function will only return the first element if there are several.
     444             :  *
     445             :  * It can fail if its value can not be converted to double.
     446             :  *
     447             :  * This is the same as the C function GDALAttributeReadAsInt()
     448             :  *
     449             :  * @return a double value.
     450             :  */
     451        4003 : double GDALAttribute::ReadAsDouble() const
     452             : {
     453        4003 :     const auto nDims = GetDimensionCount();
     454        8006 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     455        4003 :     std::vector<size_t> count(1 + nDims, 1);
     456        4003 :     double dfRet = 0;
     457        4003 :     Read(startIdx.data(), count.data(), nullptr, nullptr,
     458        4003 :          GDALExtendedDataType::Create(GDT_Float64), &dfRet, &dfRet,
     459        4003 :          sizeof(dfRet));
     460        8006 :     return dfRet;
     461             : }
     462             : 
     463             : /************************************************************************/
     464             : /*                         ReadAsStringArray()                          */
     465             : /************************************************************************/
     466             : 
     467             : /** Return the value of an attribute as an array of strings.
     468             :  *
     469             :  * This is the same as the C function GDALAttributeReadAsStringArray()
     470             :  */
     471         224 : CPLStringList GDALAttribute::ReadAsStringArray() const
     472             : {
     473         224 :     const auto nElts = GetTotalElementsCount();
     474         224 :     if (nElts > static_cast<unsigned>(std::numeric_limits<int>::max() - 1))
     475           0 :         return CPLStringList();
     476             :     char **papszList = static_cast<char **>(
     477         224 :         VSI_CALLOC_VERBOSE(static_cast<int>(nElts) + 1, sizeof(char *)));
     478         224 :     const auto &dims = GetDimensions();
     479         224 :     const auto nDims = GetDimensionCount();
     480         448 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     481         448 :     std::vector<size_t> count(1 + nDims);
     482         356 :     for (size_t i = 0; i < nDims; i++)
     483             :     {
     484         132 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     485             :     }
     486         224 :     Read(startIdx.data(), count.data(), nullptr, nullptr,
     487         224 :          GDALExtendedDataType::CreateString(), papszList, papszList,
     488         224 :          sizeof(char *) * static_cast<int>(nElts));
     489         817 :     for (int i = 0; i < static_cast<int>(nElts); i++)
     490             :     {
     491         593 :         if (papszList[i] == nullptr)
     492          13 :             papszList[i] = CPLStrdup("");
     493             :     }
     494         224 :     return CPLStringList(papszList);
     495             : }
     496             : 
     497             : /************************************************************************/
     498             : /*                           ReadAsIntArray()                           */
     499             : /************************************************************************/
     500             : 
     501             : /** Return the value of an attribute as an array of integers.
     502             :  *
     503             :  * This is the same as the C function GDALAttributeReadAsIntArray().
     504             :  */
     505          18 : std::vector<int> GDALAttribute::ReadAsIntArray() const
     506             : {
     507          18 :     const auto nElts = GetTotalElementsCount();
     508             : #if SIZEOF_VOIDP == 4
     509             :     if (nElts > static_cast<size_t>(nElts))
     510             :         return {};
     511             : #endif
     512          18 :     std::vector<int> res(static_cast<size_t>(nElts));
     513          18 :     const auto &dims = GetDimensions();
     514          18 :     const auto nDims = GetDimensionCount();
     515          36 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     516          36 :     std::vector<size_t> count(1 + nDims);
     517          38 :     for (size_t i = 0; i < nDims; i++)
     518             :     {
     519          20 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     520             :     }
     521          18 :     Read(startIdx.data(), count.data(), nullptr, nullptr,
     522          36 :          GDALExtendedDataType::Create(GDT_Int32), &res[0], res.data(),
     523          18 :          res.size() * sizeof(res[0]));
     524          36 :     return res;
     525             : }
     526             : 
     527             : /************************************************************************/
     528             : /*                          ReadAsInt64Array()                          */
     529             : /************************************************************************/
     530             : 
     531             : /** Return the value of an attribute as an array of int64_t.
     532             :  *
     533             :  * This is the same as the C function GDALAttributeReadAsInt64Array().
     534             :  */
     535          90 : std::vector<int64_t> GDALAttribute::ReadAsInt64Array() const
     536             : {
     537          90 :     const auto nElts = GetTotalElementsCount();
     538             : #if SIZEOF_VOIDP == 4
     539             :     if (nElts > static_cast<size_t>(nElts))
     540             :         return {};
     541             : #endif
     542          90 :     std::vector<int64_t> res(static_cast<size_t>(nElts));
     543          90 :     const auto &dims = GetDimensions();
     544          90 :     const auto nDims = GetDimensionCount();
     545         180 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     546         180 :     std::vector<size_t> count(1 + nDims);
     547         180 :     for (size_t i = 0; i < nDims; i++)
     548             :     {
     549          90 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     550             :     }
     551          90 :     Read(startIdx.data(), count.data(), nullptr, nullptr,
     552         180 :          GDALExtendedDataType::Create(GDT_Int64), &res[0], res.data(),
     553          90 :          res.size() * sizeof(res[0]));
     554         180 :     return res;
     555             : }
     556             : 
     557             : /************************************************************************/
     558             : /*                         ReadAsDoubleArray()                          */
     559             : /************************************************************************/
     560             : 
     561             : /** Return the value of an attribute as an array of double.
     562             :  *
     563             :  * This is the same as the C function GDALAttributeReadAsDoubleArray().
     564             :  */
     565         123 : std::vector<double> GDALAttribute::ReadAsDoubleArray() const
     566             : {
     567         123 :     const auto nElts = GetTotalElementsCount();
     568             : #if SIZEOF_VOIDP == 4
     569             :     if (nElts > static_cast<size_t>(nElts))
     570             :         return {};
     571             : #endif
     572         123 :     std::vector<double> res(static_cast<size_t>(nElts));
     573         123 :     const auto &dims = GetDimensions();
     574         123 :     const auto nDims = GetDimensionCount();
     575         246 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     576         246 :     std::vector<size_t> count(1 + nDims);
     577         230 :     for (size_t i = 0; i < nDims; i++)
     578             :     {
     579         107 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     580             :     }
     581         123 :     Read(startIdx.data(), count.data(), nullptr, nullptr,
     582         246 :          GDALExtendedDataType::Create(GDT_Float64), &res[0], res.data(),
     583         123 :          res.size() * sizeof(res[0]));
     584         246 :     return res;
     585             : }
     586             : 
     587             : /************************************************************************/
     588             : /*                               Write()                                */
     589             : /************************************************************************/
     590             : 
     591             : /** Write an attribute from raw values expressed in GetDataType()
     592             :  *
     593             :  * The values should be provided in the type of GetDataType() and there should
     594             :  * be exactly GetTotalElementsCount() of them.
     595             :  * If GetDataType() is a string, each value should be a char* pointer.
     596             :  *
     597             :  * This is the same as the C function GDALAttributeWriteRaw().
     598             :  *
     599             :  * @param pabyValue Buffer of nLen bytes.
     600             :  * @param nLen Size of pabyValue in bytes. Should be equal to
     601             :  *             GetTotalElementsCount() * GetDataType().GetSize()
     602             :  * @return true in case of success.
     603             :  */
     604         173 : bool GDALAttribute::Write(const void *pabyValue, size_t nLen)
     605             : {
     606         173 :     if (nLen != GetTotalElementsCount() * GetDataType().GetSize())
     607             :     {
     608           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     609             :                  "Length is not of expected value");
     610           0 :         return false;
     611             :     }
     612         173 :     const auto &dims = GetDimensions();
     613         173 :     const auto nDims = GetDimensionCount();
     614         346 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     615         346 :     std::vector<size_t> count(1 + nDims);
     616         199 :     for (size_t i = 0; i < nDims; i++)
     617             :     {
     618          26 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     619             :     }
     620         173 :     return Write(startIdx.data(), count.data(), nullptr, nullptr, GetDataType(),
     621         173 :                  pabyValue, pabyValue, nLen);
     622             : }
     623             : 
     624             : /************************************************************************/
     625             : /*                               Write()                                */
     626             : /************************************************************************/
     627             : 
     628             : /** Write an attribute from a string value.
     629             :  *
     630             :  * Type conversion will be performed if needed. If the attribute contains
     631             :  * multiple values, only the first one will be updated.
     632             :  *
     633             :  * This is the same as the C function GDALAttributeWriteString().
     634             :  *
     635             :  * @param pszValue Pointer to a string.
     636             :  * @return true in case of success.
     637             :  */
     638         418 : bool GDALAttribute::Write(const char *pszValue)
     639             : {
     640         418 :     const auto nDims = GetDimensionCount();
     641         836 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     642         418 :     std::vector<size_t> count(1 + nDims, 1);
     643         418 :     return Write(startIdx.data(), count.data(), nullptr, nullptr,
     644         836 :                  GDALExtendedDataType::CreateString(), &pszValue, &pszValue,
     645         836 :                  sizeof(pszValue));
     646             : }
     647             : 
     648             : /************************************************************************/
     649             : /*                              WriteInt()                              */
     650             : /************************************************************************/
     651             : 
     652             : /** Write an attribute from a integer value.
     653             :  *
     654             :  * Type conversion will be performed if needed. If the attribute contains
     655             :  * multiple values, only the first one will be updated.
     656             :  *
     657             :  * This is the same as the C function GDALAttributeWriteInt().
     658             :  *
     659             :  * @param nVal Value.
     660             :  * @return true in case of success.
     661             :  */
     662          23 : bool GDALAttribute::WriteInt(int nVal)
     663             : {
     664          23 :     const auto nDims = GetDimensionCount();
     665          46 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     666          23 :     std::vector<size_t> count(1 + nDims, 1);
     667          23 :     return Write(startIdx.data(), count.data(), nullptr, nullptr,
     668          46 :                  GDALExtendedDataType::Create(GDT_Int32), &nVal, &nVal,
     669          46 :                  sizeof(nVal));
     670             : }
     671             : 
     672             : /************************************************************************/
     673             : /*                             WriteInt64()                             */
     674             : /************************************************************************/
     675             : 
     676             : /** Write an attribute from an int64_t value.
     677             :  *
     678             :  * Type conversion will be performed if needed. If the attribute contains
     679             :  * multiple values, only the first one will be updated.
     680             :  *
     681             :  * This is the same as the C function GDALAttributeWriteInt().
     682             :  *
     683             :  * @param nVal Value.
     684             :  * @return true in case of success.
     685             :  */
     686          14 : bool GDALAttribute::WriteInt64(int64_t nVal)
     687             : {
     688          14 :     const auto nDims = GetDimensionCount();
     689          28 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     690          14 :     std::vector<size_t> count(1 + nDims, 1);
     691          14 :     return Write(startIdx.data(), count.data(), nullptr, nullptr,
     692          28 :                  GDALExtendedDataType::Create(GDT_Int64), &nVal, &nVal,
     693          28 :                  sizeof(nVal));
     694             : }
     695             : 
     696             : /************************************************************************/
     697             : /*                               Write()                                */
     698             : /************************************************************************/
     699             : 
     700             : /** Write an attribute from a double value.
     701             :  *
     702             :  * Type conversion will be performed if needed. If the attribute contains
     703             :  * multiple values, only the first one will be updated.
     704             :  *
     705             :  * This is the same as the C function GDALAttributeWriteDouble().
     706             :  *
     707             :  * @param dfVal Value.
     708             :  * @return true in case of success.
     709             :  */
     710          40 : bool GDALAttribute::Write(double dfVal)
     711             : {
     712          40 :     const auto nDims = GetDimensionCount();
     713          80 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     714          40 :     std::vector<size_t> count(1 + nDims, 1);
     715          40 :     return Write(startIdx.data(), count.data(), nullptr, nullptr,
     716          80 :                  GDALExtendedDataType::Create(GDT_Float64), &dfVal, &dfVal,
     717          80 :                  sizeof(dfVal));
     718             : }
     719             : 
     720             : /************************************************************************/
     721             : /*                               Write()                                */
     722             : /************************************************************************/
     723             : 
     724             : /** Write an attribute from an array of strings.
     725             :  *
     726             :  * Type conversion will be performed if needed.
     727             :  *
     728             :  * Exactly GetTotalElementsCount() strings must be provided
     729             :  *
     730             :  * This is the same as the C function GDALAttributeWriteStringArray().
     731             :  *
     732             :  * @param vals Array of strings.
     733             :  * @return true in case of success.
     734             :  */
     735           9 : bool GDALAttribute::Write(CSLConstList vals)
     736             : {
     737           9 :     if (static_cast<size_t>(CSLCount(vals)) != GetTotalElementsCount())
     738             :     {
     739           1 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid number of input values");
     740           1 :         return false;
     741             :     }
     742           8 :     const auto nDims = GetDimensionCount();
     743          16 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     744           8 :     std::vector<size_t> count(1 + nDims);
     745           8 :     const auto &dims = GetDimensions();
     746          17 :     for (size_t i = 0; i < nDims; i++)
     747           9 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     748           8 :     return Write(startIdx.data(), count.data(), nullptr, nullptr,
     749           8 :                  GDALExtendedDataType::CreateString(), vals, vals,
     750          16 :                  static_cast<size_t>(GetTotalElementsCount()) * sizeof(char *));
     751             : }
     752             : 
     753             : /************************************************************************/
     754             : /*                               Write()                                */
     755             : /************************************************************************/
     756             : 
     757             : /** Write an attribute from an array of int.
     758             :  *
     759             :  * Type conversion will be performed if needed.
     760             :  *
     761             :  * Exactly GetTotalElementsCount() strings must be provided
     762             :  *
     763             :  * This is the same as the C function GDALAttributeWriteIntArray()
     764             :  *
     765             :  * @param vals Array of int.
     766             :  * @param nVals Should be equal to GetTotalElementsCount().
     767             :  * @return true in case of success.
     768             :  */
     769          12 : bool GDALAttribute::Write(const int *vals, size_t nVals)
     770             : {
     771          12 :     if (nVals != GetTotalElementsCount())
     772             :     {
     773           1 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid number of input values");
     774           1 :         return false;
     775             :     }
     776          11 :     const auto nDims = GetDimensionCount();
     777          22 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     778          11 :     std::vector<size_t> count(1 + nDims);
     779          11 :     const auto &dims = GetDimensions();
     780          22 :     for (size_t i = 0; i < nDims; i++)
     781          11 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     782          11 :     return Write(startIdx.data(), count.data(), nullptr, nullptr,
     783          11 :                  GDALExtendedDataType::Create(GDT_Int32), vals, vals,
     784          22 :                  static_cast<size_t>(GetTotalElementsCount()) * sizeof(GInt32));
     785             : }
     786             : 
     787             : /************************************************************************/
     788             : /*                               Write()                                */
     789             : /************************************************************************/
     790             : 
     791             : /** Write an attribute from an array of int64_t.
     792             :  *
     793             :  * Type conversion will be performed if needed.
     794             :  *
     795             :  * Exactly GetTotalElementsCount() strings must be provided
     796             :  *
     797             :  * This is the same as the C function GDALAttributeWriteLongArray()
     798             :  *
     799             :  * @param vals Array of int64_t.
     800             :  * @param nVals Should be equal to GetTotalElementsCount().
     801             :  * @return true in case of success.
     802             :  */
     803          13 : bool GDALAttribute::Write(const int64_t *vals, size_t nVals)
     804             : {
     805          13 :     if (nVals != GetTotalElementsCount())
     806             :     {
     807           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid number of input values");
     808           0 :         return false;
     809             :     }
     810          13 :     const auto nDims = GetDimensionCount();
     811          26 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     812          13 :     std::vector<size_t> count(1 + nDims);
     813          13 :     const auto &dims = GetDimensions();
     814          26 :     for (size_t i = 0; i < nDims; i++)
     815          13 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     816          13 :     return Write(startIdx.data(), count.data(), nullptr, nullptr,
     817          13 :                  GDALExtendedDataType::Create(GDT_Int64), vals, vals,
     818          13 :                  static_cast<size_t>(GetTotalElementsCount()) *
     819          13 :                      sizeof(int64_t));
     820             : }
     821             : 
     822             : /************************************************************************/
     823             : /*                               Write()                                */
     824             : /************************************************************************/
     825             : 
     826             : /** Write an attribute from an array of double.
     827             :  *
     828             :  * Type conversion will be performed if needed.
     829             :  *
     830             :  * Exactly GetTotalElementsCount() strings must be provided
     831             :  *
     832             :  * This is the same as the C function GDALAttributeWriteDoubleArray()
     833             :  *
     834             :  * @param vals Array of double.
     835             :  * @param nVals Should be equal to GetTotalElementsCount().
     836             :  * @return true in case of success.
     837             :  */
     838           8 : bool GDALAttribute::Write(const double *vals, size_t nVals)
     839             : {
     840           8 :     if (nVals != GetTotalElementsCount())
     841             :     {
     842           1 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid number of input values");
     843           1 :         return false;
     844             :     }
     845           7 :     const auto nDims = GetDimensionCount();
     846          14 :     std::vector<GUInt64> startIdx(1 + nDims, 0);
     847           7 :     std::vector<size_t> count(1 + nDims);
     848           7 :     const auto &dims = GetDimensions();
     849          15 :     for (size_t i = 0; i < nDims; i++)
     850           8 :         count[i] = static_cast<size_t>(dims[i]->GetSize());
     851           7 :     return Write(startIdx.data(), count.data(), nullptr, nullptr,
     852           7 :                  GDALExtendedDataType::Create(GDT_Float64), vals, vals,
     853          14 :                  static_cast<size_t>(GetTotalElementsCount()) * sizeof(double));
     854             : }

Generated by: LCOV version 1.14