LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mvt - mvt_tile.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 410 441 93.0 %
Date: 2025-12-09 00:43:28 Functions: 36 36 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  MVT Translator
       4             :  * Purpose:  Mapbox Vector Tile decoder and encoder
       5             :  * Author:   Even Rouault, Even Rouault <even dot rouault at spatialys dot com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gpb.h"
      14             : 
      15             : #include <cmath>
      16             : #include <limits>
      17             : #include <memory>
      18             : #include <vector>
      19             : 
      20             : #include "mvt_tile.h"
      21             : 
      22             : constexpr int knSIZE_KEY = 1;
      23             : 
      24             : /************************************************************************/
      25             : /*                        MVTTileLayerValue()                           */
      26             : /************************************************************************/
      27             : 
      28        9467 : MVTTileLayerValue::MVTTileLayerValue() : m_nUIntValue(0)
      29             : {
      30        9467 : }
      31             : 
      32       36021 : MVTTileLayerValue::MVTTileLayerValue(const MVTTileLayerValue &oOther)
      33             : {
      34       36021 :     operator=(oOther);
      35       36034 : }
      36             : 
      37             : /************************************************************************/
      38             : /*                       ~MVTTileLayerValue()                           */
      39             : /************************************************************************/
      40             : 
      41       90981 : MVTTileLayerValue::~MVTTileLayerValue()
      42             : {
      43       45491 :     unset();
      44       45490 : }
      45             : 
      46             : /************************************************************************/
      47             : /*                            operator=                                 */
      48             : /************************************************************************/
      49             : 
      50       36023 : MVTTileLayerValue &MVTTileLayerValue::operator=(const MVTTileLayerValue &oOther)
      51             : 
      52             : {
      53       36023 :     if (this != &oOther)
      54             :     {
      55       36024 :         unset();
      56       36026 :         m_eType = oOther.m_eType;
      57       36026 :         if (m_eType == ValueType::STRING)
      58             :         {
      59        9596 :             const size_t nSize = strlen(oOther.m_pszValue);
      60        9596 :             m_pszValue = static_cast<char *>(CPLMalloc(1 + nSize));
      61        9600 :             memcpy(m_pszValue, oOther.m_pszValue, nSize);
      62        9600 :             m_pszValue[nSize] = 0;
      63             :         }
      64             :         else
      65             :         {
      66       26430 :             m_nUIntValue = oOther.m_nUIntValue;
      67             :         }
      68             :     }
      69       36029 :     return *this;
      70             : }
      71             : 
      72             : /************************************************************************/
      73             : /*                            operator<                                 */
      74             : /************************************************************************/
      75             : 
      76       54076 : bool MVTTileLayerValue::operator<(const MVTTileLayerValue &rhs) const
      77             : {
      78       54076 :     if (m_eType < rhs.m_eType)
      79        4345 :         return false;
      80       49731 :     if (m_eType > rhs.m_eType)
      81       17484 :         return true;
      82       32247 :     if (m_eType == ValueType::NONE)
      83           0 :         return false;
      84       32247 :     if (m_eType == ValueType::STRING)
      85       14337 :         return strcmp(m_pszValue, rhs.m_pszValue) < 0;
      86       17910 :     if (m_eType == ValueType::FLOAT)
      87          98 :         return m_fValue < rhs.m_fValue;
      88       17812 :     if (m_eType == ValueType::DOUBLE)
      89        9346 :         return m_dfValue < rhs.m_dfValue;
      90        8466 :     if (m_eType == ValueType::INT)
      91           0 :         return m_nIntValue < rhs.m_nIntValue;
      92        8466 :     if (m_eType == ValueType::UINT)
      93        2400 :         return m_nUIntValue < rhs.m_nUIntValue;
      94        6066 :     if (m_eType == ValueType::SINT)
      95          84 :         return m_nIntValue < rhs.m_nIntValue;
      96        5982 :     if (m_eType == ValueType::BOOL)
      97          80 :         return m_bBoolValue < rhs.m_bBoolValue;
      98        5902 :     if (m_eType == ValueType::STRING_MAX_8)
      99        5902 :         return strncmp(m_achValue, rhs.m_achValue, 8) < 0;
     100           0 :     CPLAssert(false);
     101             :     return false;
     102             : }
     103             : 
     104             : /************************************************************************/
     105             : /*                             unset()                                  */
     106             : /************************************************************************/
     107             : 
     108       90979 : void MVTTileLayerValue::unset()
     109             : {
     110       90979 :     if (m_eType == ValueType::STRING)
     111       13316 :         CPLFree(m_pszValue);
     112       90977 :     m_eType = ValueType::NONE;
     113       90977 :     m_nUIntValue = 0;
     114       90977 : }
     115             : 
     116             : /************************************************************************/
     117             : /*                            GetSizeMax8()                             */
     118             : /************************************************************************/
     119             : 
     120        6456 : static size_t GetSizeMax8(const char achValue[8])
     121             : {
     122        6456 :     size_t nSize = 0;
     123       27554 :     while (nSize < 8 && achValue[nSize] != 0)
     124       21098 :         nSize++;
     125        6456 :     return nSize;
     126             : }
     127             : 
     128             : /************************************************************************/
     129             : /*                        setStringValue()                              */
     130             : /************************************************************************/
     131             : 
     132        5598 : void MVTTileLayerValue::setStringValue(const std::string &osValue)
     133             : {
     134        5598 :     unset();
     135        5598 :     const size_t nSize = osValue.size();
     136        5598 :     if (nSize <= 8)
     137             :     {
     138        1889 :         m_eType = ValueType::STRING_MAX_8;
     139        1889 :         if (nSize)
     140        1889 :             memcpy(m_achValue, osValue.c_str(), nSize);
     141        1889 :         if (nSize < 8)
     142        1781 :             m_achValue[nSize] = 0;
     143             :     }
     144             :     else
     145             :     {
     146        3709 :         m_eType = ValueType::STRING;
     147        3709 :         m_pszValue = static_cast<char *>(CPLMalloc(1 + nSize));
     148        3709 :         memcpy(m_pszValue, osValue.c_str(), nSize);
     149        3709 :         m_pszValue[nSize] = 0;
     150             :     }
     151        5598 : }
     152             : 
     153             : /************************************************************************/
     154             : /*                          setValue()                                  */
     155             : /************************************************************************/
     156             : 
     157         140 : void MVTTileLayerValue::setValue(double dfVal)
     158             : {
     159         277 :     if (dfVal >= 0 &&
     160         277 :         dfVal <= static_cast<double>(std::numeric_limits<GUInt64>::max()) &&
     161         137 :         dfVal == static_cast<double>(static_cast<GUInt64>(dfVal)))
     162             :     {
     163           0 :         setUIntValue(static_cast<GUInt64>(dfVal));
     164             :     }
     165         280 :     else if (dfVal >= static_cast<double>(std::numeric_limits<GInt64>::min()) &&
     166         280 :              dfVal < 0 &&
     167           3 :              dfVal == static_cast<double>(static_cast<GInt64>(dfVal)))
     168             :     {
     169           0 :         setSIntValue(static_cast<GInt64>(dfVal));
     170             :     }
     171         280 :     else if (!std::isfinite(dfVal) ||
     172         140 :              (dfVal >= -std::numeric_limits<float>::max() &&
     173         140 :               dfVal <= std::numeric_limits<float>::max() &&
     174         140 :               dfVal == static_cast<float>(dfVal)))
     175             :     {
     176           6 :         setFloatValue(static_cast<float>(dfVal));
     177             :     }
     178             :     else
     179             :     {
     180         134 :         setDoubleValue(dfVal);
     181             :     }
     182         140 : }
     183             : 
     184             : /************************************************************************/
     185             : /*                            getSize()                                 */
     186             : /************************************************************************/
     187             : 
     188       24284 : size_t MVTTileLayerValue::getSize() const
     189             : {
     190       24284 :     switch (m_eType)
     191             :     {
     192           0 :         case ValueType::NONE:
     193           0 :             return 0;
     194        9563 :         case ValueType::STRING:
     195             :         {
     196        9563 :             const size_t nSize = strlen(m_pszValue);
     197        9563 :             return knSIZE_KEY + GetVarUIntSize(nSize) + nSize;
     198             :         }
     199        4844 :         case ValueType::STRING_MAX_8:
     200             :         {
     201        4844 :             const size_t nSize = GetSizeMax8(m_achValue);
     202        4842 :             return knSIZE_KEY + GetVarUIntSize(nSize) + nSize;
     203             :         }
     204         150 :         case ValueType::FLOAT:
     205         150 :             return knSIZE_KEY + sizeof(float);
     206        4722 :         case ValueType::DOUBLE:
     207        4722 :             return knSIZE_KEY + sizeof(double);
     208           0 :         case ValueType::INT:
     209           0 :             return knSIZE_KEY + GetVarIntSize(m_nIntValue);
     210        4877 :         case ValueType::UINT:
     211        4877 :             return knSIZE_KEY + GetVarUIntSize(m_nUIntValue);
     212          86 :         case ValueType::SINT:
     213          86 :             return knSIZE_KEY + GetVarSIntSize(m_nIntValue);
     214          54 :         case ValueType::BOOL:
     215          54 :             return knSIZE_KEY + 1;
     216           0 :         default:
     217           0 :             return 0;
     218             :     }
     219             : }
     220             : 
     221             : /************************************************************************/
     222             : /*                             write()                                  */
     223             : /************************************************************************/
     224             : 
     225        8099 : void MVTTileLayerValue::write(GByte **ppabyData) const
     226             : {
     227        8099 :     GByte *pabyData = *ppabyData;
     228             : 
     229        8099 :     switch (m_eType)
     230             :     {
     231        3188 :         case ValueType::STRING:
     232             :         {
     233        3188 :             const size_t nSize = strlen(m_pszValue);
     234        3188 :             WriteVarUIntSingleByte(&pabyData,
     235             :                                    MAKE_KEY(knVALUE_STRING, WT_DATA));
     236        3189 :             WriteVarUInt(&pabyData, nSize);
     237        3188 :             memcpy(pabyData, m_pszValue, nSize);
     238        3188 :             pabyData += nSize;
     239        3188 :             break;
     240             :         }
     241             : 
     242        1612 :         case ValueType::STRING_MAX_8:
     243             :         {
     244        1612 :             const size_t nSize = GetSizeMax8(m_achValue);
     245        1616 :             WriteVarUIntSingleByte(&pabyData,
     246             :                                    MAKE_KEY(knVALUE_STRING, WT_DATA));
     247        1616 :             WriteVarUInt(&pabyData, nSize);
     248        1617 :             if (nSize)
     249        1618 :                 memcpy(pabyData, m_achValue, nSize);
     250        1617 :             pabyData += nSize;
     251        1617 :             break;
     252             :         }
     253             : 
     254          50 :         case ValueType::FLOAT:
     255          50 :             WriteVarUIntSingleByte(&pabyData,
     256             :                                    MAKE_KEY(knVALUE_FLOAT, WT_32BIT));
     257          50 :             WriteFloat32(&pabyData, m_fValue);
     258          50 :             break;
     259             : 
     260        1575 :         case ValueType::DOUBLE:
     261        1575 :             WriteVarUIntSingleByte(&pabyData,
     262             :                                    MAKE_KEY(knVALUE_DOUBLE, WT_64BIT));
     263        1576 :             WriteFloat64(&pabyData, m_dfValue);
     264        1573 :             break;
     265             : 
     266           0 :         case ValueType::INT:
     267           0 :             WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knVALUE_INT, WT_VARINT));
     268           0 :             WriteVarInt(&pabyData, m_nIntValue);
     269           0 :             break;
     270             : 
     271        1624 :         case ValueType::UINT:
     272        1624 :             WriteVarUIntSingleByte(&pabyData,
     273             :                                    MAKE_KEY(knVALUE_UINT, WT_VARINT));
     274        1625 :             WriteVarUInt(&pabyData, m_nUIntValue);
     275        1624 :             break;
     276             : 
     277          30 :         case ValueType::SINT:
     278          30 :             WriteVarUIntSingleByte(&pabyData,
     279             :                                    MAKE_KEY(knVALUE_SINT, WT_VARINT));
     280          29 :             WriteVarSInt(&pabyData, m_nIntValue);
     281          29 :             break;
     282             : 
     283          18 :         case ValueType::BOOL:
     284          18 :             WriteVarUIntSingleByte(&pabyData,
     285             :                                    MAKE_KEY(knVALUE_BOOL, WT_VARINT));
     286          18 :             WriteVarUIntSingleByte(&pabyData, m_bBoolValue ? 1 : 0);
     287          18 :             break;
     288             : 
     289           2 :         default:
     290           2 :             break;
     291             :     }
     292             : 
     293        8101 :     CPLAssert(pabyData == *ppabyData + getSize());
     294        8099 :     *ppabyData = pabyData;
     295        8099 : }
     296             : 
     297             : /************************************************************************/
     298             : /*                             read()                                   */
     299             : /************************************************************************/
     300             : 
     301        4448 : bool MVTTileLayerValue::read(const GByte **ppabyData,
     302             :                              const GByte *pabyDataLimit)
     303             : {
     304        4448 :     const GByte *pabyData = *ppabyData;
     305             : 
     306             :     try
     307             :     {
     308        4448 :         unsigned int nKey = 0;
     309        4448 :         if (pabyData < pabyDataLimit)
     310             :         {
     311        4448 :             READ_FIELD_KEY(nKey);
     312             : 
     313        4448 :             if (nKey == MAKE_KEY(knVALUE_STRING, WT_DATA))
     314             :             {
     315        2656 :                 char *pszValue = nullptr;
     316        2656 :                 READ_TEXT(pabyData, pabyDataLimit, pszValue);
     317             :                 // cppcheck-suppress nullPointer
     318        2656 :                 setStringValue(pszValue);
     319        2656 :                 CPLFree(pszValue);
     320             :             }
     321        1792 :             else if (nKey == MAKE_KEY(knVALUE_FLOAT, WT_32BIT))
     322             :             {
     323          28 :                 setFloatValue(ReadFloat32(&pabyData, pabyDataLimit));
     324             :             }
     325        1764 :             else if (nKey == MAKE_KEY(knVALUE_DOUBLE, WT_64BIT))
     326             :             {
     327         853 :                 setDoubleValue(ReadFloat64(&pabyData, pabyDataLimit));
     328             :             }
     329         911 :             else if (nKey == MAKE_KEY(knVALUE_INT, WT_VARINT))
     330             :             {
     331           0 :                 GIntBig nVal = 0;
     332           0 :                 READ_VARINT64(pabyData, pabyDataLimit, nVal);
     333           0 :                 setIntValue(nVal);
     334             :             }
     335         911 :             else if (nKey == MAKE_KEY(knVALUE_UINT, WT_VARINT))
     336             :             {
     337         881 :                 GUIntBig nVal = 0;
     338         881 :                 READ_VARUINT64(pabyData, pabyDataLimit, nVal);
     339         881 :                 setUIntValue(nVal);
     340             :             }
     341          30 :             else if (nKey == MAKE_KEY(knVALUE_SINT, WT_VARINT))
     342             :             {
     343          18 :                 GIntBig nVal = 0;
     344          18 :                 READ_VARSINT64(pabyData, pabyDataLimit, nVal);
     345          18 :                 setSIntValue(nVal);
     346             :             }
     347          12 :             else if (nKey == MAKE_KEY(knVALUE_BOOL, WT_VARINT))
     348             :             {
     349          12 :                 unsigned nVal = 0;
     350          12 :                 READ_VARUINT32(pabyData, pabyDataLimit, nVal);
     351          12 :                 setBoolValue(nVal != 0);
     352             :             }
     353             :         }
     354        4448 :         *ppabyData = pabyData;
     355        4448 :         return true;
     356             :     }
     357           0 :     catch (const GPBException &)
     358             :     {
     359           0 :         return false;
     360             :     }
     361             : }
     362             : 
     363             : /************************************************************************/
     364             : /*                           MVTTileLayer()                             */
     365             : /************************************************************************/
     366             : 
     367        7429 : MVTTileLayerFeature::MVTTileLayerFeature()
     368             : {
     369        7419 : }
     370             : 
     371             : /************************************************************************/
     372             : /*                             setOwner()                               */
     373             : /************************************************************************/
     374             : 
     375        7385 : void MVTTileLayerFeature::setOwner(MVTTileLayer *poOwner)
     376             : {
     377        7385 :     CPLAssert(!m_poOwner);
     378        7385 :     m_poOwner = poOwner;
     379        7385 :     m_poOwner->invalidateCachedSize();
     380        7388 : }
     381             : 
     382             : /************************************************************************/
     383             : /*                       invalidateCachedSize()                         */
     384             : /************************************************************************/
     385             : 
     386       61924 : void MVTTileLayerFeature::invalidateCachedSize()
     387             : {
     388       61924 :     m_bCachedSize = false;
     389       61924 :     m_nCachedSize = 0;
     390       61924 :     if (m_poOwner)
     391       49567 :         m_poOwner->invalidateCachedSize();
     392       61873 : }
     393             : 
     394             : /************************************************************************/
     395             : /*                        GetPackedArraySize()                          */
     396             : /************************************************************************/
     397             : 
     398       10197 : static size_t GetPackedArraySize(const std::vector<GUInt32> &anVals)
     399             : {
     400       10197 :     size_t nPackedSize = 0;
     401       84550 :     for (const auto &nVal : anVals)
     402             :     {
     403       74450 :         nPackedSize += GetVarUIntSize(nVal);
     404             :     }
     405       10209 :     return nPackedSize;
     406             : }
     407             : 
     408             : /************************************************************************/
     409             : /*                            getSize()                                 */
     410             : /************************************************************************/
     411             : 
     412        9644 : size_t MVTTileLayerFeature::getSize() const
     413             : {
     414        9644 :     if (m_bCachedSize)
     415        6421 :         return m_nCachedSize;
     416        3223 :     m_bCachedSize = true;
     417        3223 :     m_nCachedSize = 0;
     418        3223 :     if (m_bHasId)
     419         105 :         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nId);
     420        3223 :     if (!m_anTags.empty())
     421             :     {
     422        1879 :         size_t nPackedSize = GetPackedArraySize(m_anTags);
     423        1887 :         m_nCachedSize += knSIZE_KEY;
     424        1887 :         m_nCachedSize += GetVarUIntSize(nPackedSize);
     425        1885 :         m_nCachedSize += nPackedSize;
     426             :     }
     427        3213 :     if (m_bHasType)
     428        3204 :         m_nCachedSize += knSIZE_KEY + 1;  // fixed size for m_eType
     429        3213 :     if (!m_anGeometry.empty())
     430             :     {
     431        3214 :         size_t nPackedSize = GetPackedArraySize(m_anGeometry);
     432        3215 :         m_nCachedSize += knSIZE_KEY;
     433        3215 :         m_nCachedSize += GetVarUIntSize(nPackedSize);
     434        3217 :         m_nCachedSize += nPackedSize;
     435             :     }
     436        3218 :     return m_nCachedSize;
     437             : }
     438             : 
     439             : /************************************************************************/
     440             : /*                        WriteUIntPackedArray()                        */
     441             : /************************************************************************/
     442             : 
     443        5100 : static void WriteUIntPackedArray(GByte **ppabyData, int nKey,
     444             :                                  const std::vector<GUInt32> &anVals)
     445             : {
     446        5100 :     GByte *pabyData = *ppabyData;
     447        5100 :     const size_t nPackedSize = GetPackedArraySize(anVals);
     448        5107 :     WriteVarUIntSingleByte(&pabyData, nKey);
     449        5106 :     WriteVarUInt(&pabyData, nPackedSize);
     450       42326 :     for (const auto &nVal : anVals)
     451             :     {
     452       37229 :         WriteVarUInt(&pabyData, nVal);
     453             :     }
     454        5101 :     *ppabyData = pabyData;
     455        5101 : }
     456             : 
     457             : /************************************************************************/
     458             : /*                             write()                                  */
     459             : /************************************************************************/
     460             : 
     461        3220 : void MVTTileLayerFeature::write(GByte **ppabyData) const
     462             : {
     463        3220 :     GByte *pabyData = *ppabyData;
     464             : 
     465        3220 :     if (m_bHasId)
     466             :     {
     467         106 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knFEATURE_ID, WT_VARINT));
     468         104 :         WriteVarUInt(&pabyData, m_nId);
     469             :     }
     470        3218 :     if (!m_anTags.empty())
     471             :     {
     472        1881 :         WriteUIntPackedArray(&pabyData, MAKE_KEY(knFEATURE_TAGS, WT_DATA),
     473        1881 :                              m_anTags);
     474             :     }
     475        3213 :     if (m_bHasType)
     476             :     {
     477        3213 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knFEATURE_TYPE, WT_VARINT));
     478        3209 :         WriteVarUIntSingleByte(&pabyData, static_cast<GUIntBig>(m_eType));
     479             :     }
     480        3211 :     if (!m_anGeometry.empty())
     481             :     {
     482        3215 :         WriteUIntPackedArray(&pabyData, MAKE_KEY(knFEATURE_GEOMETRY, WT_DATA),
     483        3215 :                              m_anGeometry);
     484             :     }
     485             : 
     486        3224 :     CPLAssert(pabyData == *ppabyData + getSize());
     487        3217 :     *ppabyData = pabyData;
     488        3217 : }
     489             : 
     490             : /************************************************************************/
     491             : /*                             read()                                   */
     492             : /************************************************************************/
     493             : 
     494        1705 : bool MVTTileLayerFeature::read(const GByte **ppabyData,
     495             :                                const GByte *pabyDataLimit)
     496             : {
     497        1705 :     const GByte *pabyData = *ppabyData;
     498             : 
     499             :     try
     500             :     {
     501        1705 :         unsigned int nKey = 0;
     502        6162 :         while (pabyData < pabyDataLimit)
     503             :         {
     504        4457 :             READ_FIELD_KEY(nKey);
     505        4457 :             if (nKey == MAKE_KEY(knFEATURE_ID, WT_VARINT))
     506             :             {
     507          53 :                 GUIntBig nID = 0;
     508          53 :                 READ_VARUINT64(pabyData, pabyDataLimit, nID);
     509          53 :                 setId(nID);
     510             :             }
     511        4404 :             else if (nKey == MAKE_KEY(knFEATURE_TAGS, WT_DATA))
     512             :             {
     513         994 :                 unsigned int nTagsSize = 0;
     514         994 :                 READ_SIZE(pabyData, pabyDataLimit, nTagsSize);
     515         994 :                 const GByte *pabyDataTagsEnd = pabyData + nTagsSize;
     516        9890 :                 while (pabyData < pabyDataTagsEnd)
     517             :                 {
     518        8896 :                     unsigned int nTag = 0;
     519        8896 :                     READ_VARUINT32(pabyData, pabyDataTagsEnd, nTag);
     520        8896 :                     addTag(nTag);
     521             :                 }
     522         994 :                 pabyData = pabyDataTagsEnd;
     523             :             }
     524        3410 :             else if (nKey == MAKE_KEY(knFEATURE_TYPE, WT_VARINT))
     525             :             {
     526        1705 :                 unsigned int nType = 0;
     527        1705 :                 READ_VARUINT32(pabyData, pabyDataLimit, nType);
     528        1705 :                 if (nType <= knGEOM_TYPE_POLYGON)
     529        1705 :                     setType(static_cast<GeomType>(nType));
     530             :             }
     531        1705 :             else if (nKey == MAKE_KEY(knFEATURE_GEOMETRY, WT_DATA))
     532             :             {
     533        1705 :                 unsigned int nGeometrySize = 0;
     534        1705 :                 READ_SIZE(pabyData, pabyDataLimit, nGeometrySize);
     535        1705 :                 const GByte *pabyDataGeometryEnd = pabyData + nGeometrySize;
     536       12257 :                 while (pabyData < pabyDataGeometryEnd)
     537             :                 {
     538       10552 :                     unsigned int nGeometry = 0;
     539       10552 :                     READ_VARUINT32(pabyData, pabyDataGeometryEnd, nGeometry);
     540       10552 :                     addGeometry(nGeometry);
     541             :                 }
     542        1705 :                 pabyData = pabyDataGeometryEnd;
     543             :             }
     544             :             else
     545             :             {
     546           0 :                 SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
     547             :             }
     548             :         }
     549        1705 :         *ppabyData = pabyData;
     550        1705 :         return true;
     551             :     }
     552           0 :     catch (const GPBException &)
     553             :     {
     554           0 :         return false;
     555             :     }
     556             : }
     557             : 
     558             : /************************************************************************/
     559             : /*                           MVTTileLayer()                             */
     560             : /************************************************************************/
     561             : 
     562        7143 : MVTTileLayer::MVTTileLayer()
     563             : {
     564        7120 : }
     565             : 
     566             : /************************************************************************/
     567             : /*                             setOwner()                               */
     568             : /************************************************************************/
     569             : 
     570        1418 : void MVTTileLayer::setOwner(MVTTile *poOwner)
     571             : {
     572        1418 :     CPLAssert(!m_poOwner);
     573        1418 :     m_poOwner = poOwner;
     574        1418 :     m_poOwner->invalidateCachedSize();
     575        1418 : }
     576             : 
     577             : /************************************************************************/
     578             : /*                       invalidateCachedSize()                         */
     579             : /************************************************************************/
     580             : 
     581       96938 : void MVTTileLayer::invalidateCachedSize()
     582             : {
     583       96938 :     m_bCachedSize = false;
     584       96938 :     m_nCachedSize = 0;
     585       96938 :     if (m_poOwner)
     586       15034 :         m_poOwner->invalidateCachedSize();
     587       96938 : }
     588             : 
     589             : /************************************************************************/
     590             : /*                          addFeature()                                */
     591             : /************************************************************************/
     592             : 
     593        7399 : size_t MVTTileLayer::addFeature(std::shared_ptr<MVTTileLayerFeature> poFeature)
     594             : {
     595        7399 :     poFeature->setOwner(this);
     596        7381 :     m_apoFeatures.push_back(poFeature);
     597        7391 :     invalidateCachedSize();
     598        7381 :     return m_apoFeatures.size() - 1;
     599             : }
     600             : 
     601             : /************************************************************************/
     602             : /*                            getSize()                                 */
     603             : /************************************************************************/
     604             : 
     605        7334 : size_t MVTTileLayer::getSize() const
     606             : {
     607        7334 :     if (m_bCachedSize)
     608        4359 :         return m_nCachedSize;
     609        2975 :     m_nCachedSize = knSIZE_KEY + GetTextSize(m_osName);
     610        6179 :     for (const auto &poFeature : m_apoFeatures)
     611             :     {
     612        3212 :         const size_t nFeatureSize = poFeature->getSize();
     613        3219 :         m_nCachedSize +=
     614        3223 :             knSIZE_KEY + GetVarUIntSize(nFeatureSize) + nFeatureSize;
     615             :     }
     616       10937 :     for (const auto &osKey : m_aosKeys)
     617             :     {
     618        7972 :         m_nCachedSize += knSIZE_KEY + GetTextSize(osKey);
     619             :     }
     620       11051 :     for (const auto &oValue : m_aoValues)
     621             :     {
     622        8093 :         const size_t nValueSize = oValue.getSize();
     623        8104 :         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(nValueSize) + nValueSize;
     624             :     }
     625        2959 :     if (m_bHasExtent)
     626             :     {
     627        1430 :         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nExtent);
     628             :     }
     629        2959 :     m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nVersion);
     630        2949 :     m_bCachedSize = true;
     631        2949 :     return m_nCachedSize;
     632             : }
     633             : 
     634             : /************************************************************************/
     635             : /*                             write()                                  */
     636             : /************************************************************************/
     637             : 
     638        2934 : void MVTTileLayer::write(GByte **ppabyData) const
     639             : {
     640        2934 :     GByte *pabyData = *ppabyData;
     641             : 
     642        2934 :     WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_NAME, WT_DATA));
     643        2939 :     WriteText(&pabyData, m_osName);
     644             : 
     645        6157 :     for (const auto &poFeature : m_apoFeatures)
     646             :     {
     647        3205 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_FEATURES, WT_DATA));
     648        3205 :         WriteVarUInt(&pabyData, poFeature->getSize());
     649        3204 :         poFeature->write(&pabyData);
     650             :     }
     651             : 
     652       10925 :     for (const auto &osKey : m_aosKeys)
     653             :     {
     654        7974 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_KEYS, WT_DATA));
     655        7975 :         WriteText(&pabyData, osKey);
     656             :     }
     657             : 
     658       11047 :     for (const auto &oValue : m_aoValues)
     659             :     {
     660        8098 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_VALUES, WT_DATA));
     661        8093 :         WriteVarUInt(&pabyData, oValue.getSize());
     662        8096 :         oValue.write(&pabyData);
     663             :     }
     664             : 
     665        2950 :     if (m_bHasExtent)
     666             :     {
     667        1418 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_EXTENT, WT_VARINT));
     668        1418 :         WriteVarUInt(&pabyData, m_nExtent);
     669             :     }
     670             : 
     671        2950 :     WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_VERSION, WT_VARINT));
     672        2947 :     WriteVarUInt(&pabyData, m_nVersion);
     673             : 
     674        2941 :     CPLAssert(pabyData == *ppabyData + getSize());
     675        2945 :     *ppabyData = pabyData;
     676        2945 : }
     677             : 
     678             : /************************************************************************/
     679             : /*                             write()                                  */
     680             : /************************************************************************/
     681             : 
     682        1530 : void MVTTileLayer::write(GByte *pabyData) const
     683             : {
     684        1530 :     write(&pabyData);
     685        1520 : }
     686             : 
     687             : /************************************************************************/
     688             : /*                             write()                                  */
     689             : /************************************************************************/
     690             : 
     691        1529 : std::string MVTTileLayer::write() const
     692             : {
     693        1529 :     std::string buffer;
     694        1527 :     size_t nSize = getSize();
     695        1527 :     buffer.resize(nSize);
     696        1528 :     write(reinterpret_cast<GByte *>(&buffer[0]));
     697        1517 :     return buffer;
     698             : }
     699             : 
     700             : /************************************************************************/
     701             : /*                             read()                                   */
     702             : /************************************************************************/
     703             : 
     704        1705 : bool MVTTileLayer::read(const GByte **ppabyData, const GByte *pabyDataLimit)
     705             : {
     706        1705 :     const GByte *pabyData = *ppabyData;
     707             : 
     708             :     try
     709             :     {
     710        1705 :         unsigned int nKey = 0;
     711       15716 :         while (pabyData < pabyDataLimit)
     712             :         {
     713       14011 :             READ_FIELD_KEY(nKey);
     714       14011 :             if (nKey == MAKE_KEY(knLAYER_NAME, WT_DATA))
     715             :             {
     716        1705 :                 char *pszLayerName = nullptr;
     717        1705 :                 READ_TEXT(pabyData, pabyDataLimit, pszLayerName);
     718             :                 // cppcheck-suppress nullPointer
     719        1705 :                 setName(pszLayerName);
     720        1705 :                 CPLFree(pszLayerName);
     721             :             }
     722       12306 :             else if (nKey == MAKE_KEY(knLAYER_FEATURES, WT_DATA))
     723             :             {
     724        1705 :                 unsigned int nFeatureLength = 0;
     725        1705 :                 READ_SIZE(pabyData, pabyDataLimit, nFeatureLength);
     726        1705 :                 const GByte *pabyDataFeatureEnd = pabyData + nFeatureLength;
     727        1705 :                 auto poFeature = std::make_shared<MVTTileLayerFeature>();
     728        1705 :                 addFeature(poFeature);
     729        1705 :                 if (!poFeature->read(&pabyData, pabyDataFeatureEnd))
     730           0 :                     return false;
     731        1705 :                 pabyData = pabyDataFeatureEnd;
     732             :             }
     733       10601 :             else if (nKey == MAKE_KEY(knLAYER_KEYS, WT_DATA))
     734             :             {
     735        4448 :                 char *pszKey = nullptr;
     736        4448 :                 READ_TEXT(pabyData, pabyDataLimit, pszKey);
     737             :                 // cppcheck-suppress nullPointer
     738        4448 :                 addKey(pszKey);
     739        4448 :                 CPLFree(pszKey);
     740             :             }
     741        6153 :             else if (nKey == MAKE_KEY(knLAYER_VALUES, WT_DATA))
     742             :             {
     743        4448 :                 unsigned int nValueLength = 0;
     744        4448 :                 READ_SIZE(pabyData, pabyDataLimit, nValueLength);
     745        4448 :                 const GByte *pabyDataValueEnd = pabyData + nValueLength;
     746        4448 :                 MVTTileLayerValue oValue;
     747        4448 :                 if (!oValue.read(&pabyData, pabyDataValueEnd))
     748           0 :                     return false;
     749        4448 :                 addValue(oValue);
     750        4448 :                 pabyData = pabyDataValueEnd;
     751             :             }
     752        1705 :             else if (nKey == MAKE_KEY(knLAYER_EXTENT, WT_VARINT))
     753             :             {
     754           0 :                 unsigned int nExtent = 0;
     755           0 :                 READ_VARUINT32(pabyData, pabyDataLimit, nExtent);
     756           0 :                 setExtent(nExtent);
     757             :             }
     758        1705 :             else if (nKey == MAKE_KEY(knLAYER_VERSION, WT_VARINT))
     759             :             {
     760        1705 :                 unsigned int nVersion = 0;
     761        1705 :                 READ_VARUINT32(pabyData, pabyDataLimit, nVersion);
     762        1705 :                 setVersion(nVersion);
     763             :             }
     764             :             else
     765             :             {
     766           0 :                 SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
     767             :             }
     768             :         }
     769        1705 :         *ppabyData = pabyData;
     770        1705 :         return true;
     771             :     }
     772           0 :     catch (const GPBException &)
     773             :     {
     774           0 :         return false;
     775             :     }
     776             : }
     777             : 
     778             : /************************************************************************/
     779             : /*                             read()                                   */
     780             : /************************************************************************/
     781             : 
     782        1705 : bool MVTTileLayer::read(const GByte *pabyData, const GByte *pabyEnd)
     783             : {
     784        1705 :     return read(&pabyData, pabyEnd);
     785             : }
     786             : 
     787             : /************************************************************************/
     788             : /*                             MVTTile()                                */
     789             : /************************************************************************/
     790             : 
     791         952 : MVTTile::MVTTile()
     792             : {
     793         952 : }
     794             : 
     795             : /************************************************************************/
     796             : /*                            addLayer()                                */
     797             : /************************************************************************/
     798             : 
     799        1418 : void MVTTile::addLayer(std::shared_ptr<MVTTileLayer> poLayer)
     800             : {
     801        1418 :     poLayer->setOwner(this);
     802        1418 :     invalidateCachedSize();
     803        1418 :     m_apoLayers.push_back(poLayer);
     804        1418 : }
     805             : 
     806             : /************************************************************************/
     807             : /*                            getSize()                                 */
     808             : /************************************************************************/
     809             : 
     810        1991 : size_t MVTTile::getSize() const
     811             : {
     812        1991 :     if (m_bCachedSize)
     813        1002 :         return m_nCachedSize;
     814         989 :     m_nCachedSize = 0;
     815        2419 :     for (const auto &poLayer : m_apoLayers)
     816             :     {
     817        1430 :         const size_t nLayerSize = poLayer->getSize();
     818        1430 :         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(nLayerSize) + nLayerSize;
     819             :     }
     820         989 :     m_bCachedSize = true;
     821         989 :     return m_nCachedSize;
     822             : }
     823             : 
     824             : /************************************************************************/
     825             : /*                             write()                                  */
     826             : /************************************************************************/
     827             : 
     828         977 : void MVTTile::write(GByte **ppabyData) const
     829             : {
     830         977 :     GByte *pabyData = *ppabyData;
     831             : 
     832        2395 :     for (const auto &poLayer : m_apoLayers)
     833             :     {
     834        1418 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER, WT_DATA));
     835        1418 :         WriteVarUInt(&pabyData, poLayer->getSize());
     836        1418 :         poLayer->write(&pabyData);
     837             :     }
     838             : 
     839         977 :     CPLAssert(pabyData == *ppabyData + getSize());
     840         977 :     *ppabyData = pabyData;
     841         977 : }
     842             : 
     843             : /************************************************************************/
     844             : /*                             write()                                  */
     845             : /************************************************************************/
     846             : 
     847         977 : void MVTTile::write(GByte *pabyData) const
     848             : {
     849         977 :     write(&pabyData);
     850         977 : }
     851             : 
     852             : /************************************************************************/
     853             : /*                             write()                                  */
     854             : /************************************************************************/
     855             : 
     856         977 : std::string MVTTile::write() const
     857             : {
     858         977 :     std::string buffer;
     859         977 :     size_t nSize = getSize();
     860         977 :     if (nSize)
     861             :     {
     862         977 :         buffer.resize(nSize);
     863         977 :         write(reinterpret_cast<GByte *>(&buffer[0]));
     864             :     }
     865         977 :     return buffer;
     866             : }
     867             : 
     868             : #ifdef ADD_MVT_TILE_READ
     869             : 
     870             : /************************************************************************/
     871             : /*                             read()                                   */
     872             : /************************************************************************/
     873             : 
     874             : bool MVTTile::read(const GByte **ppabyData, const GByte *pabyDataLimit)
     875             : {
     876             :     const GByte *pabyData = *ppabyData;
     877             : 
     878             :     try
     879             :     {
     880             :         unsigned int nKey = 0;
     881             :         while (pabyData < pabyDataLimit)
     882             :         {
     883             :             READ_FIELD_KEY(nKey);
     884             :             if (nKey == MAKE_KEY(knLAYER, WT_DATA))
     885             :             {
     886             :                 unsigned int nLayerSize = 0;
     887             :                 READ_SIZE(pabyData, pabyDataLimit, nLayerSize);
     888             :                 const GByte *pabyDataLimitLayer = pabyData + nLayerSize;
     889             :                 auto poLayer = std::make_shared<MVTTileLayer>();
     890             :                 addLayer(poLayer);
     891             :                 if (!poLayer->read(&pabyData, pabyDataLimitLayer))
     892             :                     return false;
     893             :                 pabyData = pabyDataLimitLayer;
     894             :             }
     895             :             else
     896             :             {
     897             :                 SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
     898             :             }
     899             :         }
     900             :         *ppabyData = pabyData;
     901             :         return true;
     902             :     }
     903             :     catch (const GPBException &)
     904             :     {
     905             :         return false;
     906             :     }
     907             : }
     908             : 
     909             : /************************************************************************/
     910             : /*                             read()                                   */
     911             : /************************************************************************/
     912             : 
     913             : bool MVTTile::read(const GByte *pabyData, const GByte *pabyEnd)
     914             : {
     915             :     return read(&pabyData, pabyEnd);
     916             : }
     917             : 
     918             : #endif

Generated by: LCOV version 1.14