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: 408 441 92.5 %
Date: 2025-11-15 19:28:31 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       36042 : MVTTileLayerValue::MVTTileLayerValue(const MVTTileLayerValue &oOther)
      33             : {
      34       36042 :     operator=(oOther);
      35       36038 : }
      36             : 
      37             : /************************************************************************/
      38             : /*                       ~MVTTileLayerValue()                           */
      39             : /************************************************************************/
      40             : 
      41       90990 : MVTTileLayerValue::~MVTTileLayerValue()
      42             : {
      43       45492 :     unset();
      44       45498 : }
      45             : 
      46             : /************************************************************************/
      47             : /*                            operator=                                 */
      48             : /************************************************************************/
      49             : 
      50       36044 : MVTTileLayerValue &MVTTileLayerValue::operator=(const MVTTileLayerValue &oOther)
      51             : 
      52             : {
      53       36044 :     if (this != &oOther)
      54             :     {
      55       36042 :         unset();
      56       36041 :         m_eType = oOther.m_eType;
      57       36041 :         if (m_eType == ValueType::STRING)
      58             :         {
      59        9602 :             const size_t nSize = strlen(oOther.m_pszValue);
      60        9602 :             m_pszValue = static_cast<char *>(CPLMalloc(1 + nSize));
      61        9605 :             memcpy(m_pszValue, oOther.m_pszValue, nSize);
      62        9605 :             m_pszValue[nSize] = 0;
      63             :         }
      64             :         else
      65             :         {
      66       26439 :             m_nUIntValue = oOther.m_nUIntValue;
      67             :         }
      68             :     }
      69       36046 :     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       90915 : void MVTTileLayerValue::unset()
     109             : {
     110       90915 :     if (m_eType == ValueType::STRING)
     111       13318 :         CPLFree(m_pszValue);
     112       90916 :     m_eType = ValueType::NONE;
     113       90916 :     m_nUIntValue = 0;
     114       90916 : }
     115             : 
     116             : /************************************************************************/
     117             : /*                            GetSizeMax8()                             */
     118             : /************************************************************************/
     119             : 
     120        6456 : static size_t GetSizeMax8(const char achValue[8])
     121             : {
     122        6456 :     size_t nSize = 0;
     123       27575 :     while (nSize < 8 && achValue[nSize] != 0)
     124       21119 :         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       24317 : size_t MVTTileLayerValue::getSize() const
     189             : {
     190       24317 :     switch (m_eType)
     191             :     {
     192           0 :         case ValueType::NONE:
     193           0 :             return 0;
     194        9574 :         case ValueType::STRING:
     195             :         {
     196        9574 :             const size_t nSize = strlen(m_pszValue);
     197        9574 :             return knSIZE_KEY + GetVarUIntSize(nSize) + nSize;
     198             :         }
     199        4842 :         case ValueType::STRING_MAX_8:
     200             :         {
     201        4842 :             const size_t nSize = GetSizeMax8(m_achValue);
     202        4848 :             return knSIZE_KEY + GetVarUIntSize(nSize) + nSize;
     203             :         }
     204         150 :         case ValueType::FLOAT:
     205         150 :             return knSIZE_KEY + sizeof(float);
     206        4729 :         case ValueType::DOUBLE:
     207        4729 :             return knSIZE_KEY + sizeof(double);
     208           0 :         case ValueType::INT:
     209           0 :             return knSIZE_KEY + GetVarIntSize(m_nIntValue);
     210        4882 :         case ValueType::UINT:
     211        4882 :             return knSIZE_KEY + GetVarUIntSize(m_nUIntValue);
     212          90 :         case ValueType::SINT:
     213          90 :             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        8110 : void MVTTileLayerValue::write(GByte **ppabyData) const
     226             : {
     227        8110 :     GByte *pabyData = *ppabyData;
     228             : 
     229        8110 :     switch (m_eType)
     230             :     {
     231        3194 :         case ValueType::STRING:
     232             :         {
     233        3194 :             const size_t nSize = strlen(m_pszValue);
     234        3194 :             WriteVarUIntSingleByte(&pabyData,
     235             :                                    MAKE_KEY(knVALUE_STRING, WT_DATA));
     236        3194 :             WriteVarUInt(&pabyData, nSize);
     237        3193 :             memcpy(pabyData, m_pszValue, nSize);
     238        3193 :             pabyData += nSize;
     239        3193 :             break;
     240             :         }
     241             : 
     242        1616 :         case ValueType::STRING_MAX_8:
     243             :         {
     244        1616 :             const size_t nSize = GetSizeMax8(m_achValue);
     245        1614 :             WriteVarUIntSingleByte(&pabyData,
     246             :                                    MAKE_KEY(knVALUE_STRING, WT_DATA));
     247        1614 :             WriteVarUInt(&pabyData, nSize);
     248        1614 :             if (nSize)
     249        1614 :                 memcpy(pabyData, m_achValue, nSize);
     250        1614 :             pabyData += nSize;
     251        1614 :             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        1577 :         case ValueType::DOUBLE:
     261        1577 :             WriteVarUIntSingleByte(&pabyData,
     262             :                                    MAKE_KEY(knVALUE_DOUBLE, WT_64BIT));
     263        1578 :             WriteFloat64(&pabyData, m_dfValue);
     264        1575 :             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        1627 :         case ValueType::UINT:
     272        1627 :             WriteVarUIntSingleByte(&pabyData,
     273             :                                    MAKE_KEY(knVALUE_UINT, WT_VARINT));
     274        1630 :             WriteVarUInt(&pabyData, m_nUIntValue);
     275        1628 :             break;
     276             : 
     277          30 :         case ValueType::SINT:
     278          30 :             WriteVarUIntSingleByte(&pabyData,
     279             :                                    MAKE_KEY(knVALUE_SINT, WT_VARINT));
     280          30 :             WriteVarSInt(&pabyData, m_nIntValue);
     281          30 :             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           0 :         default:
     290           0 :             break;
     291             :     }
     292             : 
     293        8106 :     CPLAssert(pabyData == *ppabyData + getSize());
     294        8108 :     *ppabyData = pabyData;
     295        8108 : }
     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        7438 : MVTTileLayerFeature::MVTTileLayerFeature()
     368             : {
     369        7434 : }
     370             : 
     371             : /************************************************************************/
     372             : /*                             setOwner()                               */
     373             : /************************************************************************/
     374             : 
     375        7404 : void MVTTileLayerFeature::setOwner(MVTTileLayer *poOwner)
     376             : {
     377        7404 :     CPLAssert(!m_poOwner);
     378        7404 :     m_poOwner = poOwner;
     379        7404 :     m_poOwner->invalidateCachedSize();
     380        7407 : }
     381             : 
     382             : /************************************************************************/
     383             : /*                       invalidateCachedSize()                         */
     384             : /************************************************************************/
     385             : 
     386       61989 : void MVTTileLayerFeature::invalidateCachedSize()
     387             : {
     388       61989 :     m_bCachedSize = false;
     389       61989 :     m_nCachedSize = 0;
     390       61989 :     if (m_poOwner)
     391       49637 :         m_poOwner->invalidateCachedSize();
     392       61966 : }
     393             : 
     394             : /************************************************************************/
     395             : /*                        GetPackedArraySize()                          */
     396             : /************************************************************************/
     397             : 
     398       10203 : static size_t GetPackedArraySize(const std::vector<GUInt32> &anVals)
     399             : {
     400       10203 :     size_t nPackedSize = 0;
     401       84673 :     for (const auto &nVal : anVals)
     402             :     {
     403       74486 :         nPackedSize += GetVarUIntSize(nVal);
     404             :     }
     405       10211 :     return nPackedSize;
     406             : }
     407             : 
     408             : /************************************************************************/
     409             : /*                            getSize()                                 */
     410             : /************************************************************************/
     411             : 
     412        9658 : size_t MVTTileLayerFeature::getSize() const
     413             : {
     414        9658 :     if (m_bCachedSize)
     415        6440 :         return m_nCachedSize;
     416        3218 :     m_bCachedSize = true;
     417        3218 :     m_nCachedSize = 0;
     418        3218 :     if (m_bHasId)
     419         106 :         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nId);
     420        3218 :     if (!m_anTags.empty())
     421             :     {
     422        1887 :         size_t nPackedSize = GetPackedArraySize(m_anTags);
     423        1887 :         m_nCachedSize += knSIZE_KEY;
     424        1887 :         m_nCachedSize += GetVarUIntSize(nPackedSize);
     425        1886 :         m_nCachedSize += nPackedSize;
     426             :     }
     427        3219 :     if (m_bHasType)
     428        3218 :         m_nCachedSize += knSIZE_KEY + 1;  // fixed size for m_eType
     429        3219 :     if (!m_anGeometry.empty())
     430             :     {
     431        3220 :         size_t nPackedSize = GetPackedArraySize(m_anGeometry);
     432        3218 :         m_nCachedSize += knSIZE_KEY;
     433        3218 :         m_nCachedSize += GetVarUIntSize(nPackedSize);
     434        3217 :         m_nCachedSize += nPackedSize;
     435             :     }
     436        3217 :     return m_nCachedSize;
     437             : }
     438             : 
     439             : /************************************************************************/
     440             : /*                        WriteUIntPackedArray()                        */
     441             : /************************************************************************/
     442             : 
     443        5103 : static void WriteUIntPackedArray(GByte **ppabyData, int nKey,
     444             :                                  const std::vector<GUInt32> &anVals)
     445             : {
     446        5103 :     GByte *pabyData = *ppabyData;
     447        5103 :     const size_t nPackedSize = GetPackedArraySize(anVals);
     448        5105 :     WriteVarUIntSingleByte(&pabyData, nKey);
     449        5105 :     WriteVarUInt(&pabyData, nPackedSize);
     450       42364 :     for (const auto &nVal : anVals)
     451             :     {
     452       37248 :         WriteVarUInt(&pabyData, nVal);
     453             :     }
     454        5094 :     *ppabyData = pabyData;
     455        5094 : }
     456             : 
     457             : /************************************************************************/
     458             : /*                             write()                                  */
     459             : /************************************************************************/
     460             : 
     461        3218 : void MVTTileLayerFeature::write(GByte **ppabyData) const
     462             : {
     463        3218 :     GByte *pabyData = *ppabyData;
     464             : 
     465        3218 :     if (m_bHasId)
     466             :     {
     467         106 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knFEATURE_ID, WT_VARINT));
     468         106 :         WriteVarUInt(&pabyData, m_nId);
     469             :     }
     470        3218 :     if (!m_anTags.empty())
     471             :     {
     472        1886 :         WriteUIntPackedArray(&pabyData, MAKE_KEY(knFEATURE_TAGS, WT_DATA),
     473        1886 :                              m_anTags);
     474             :     }
     475        3219 :     if (m_bHasType)
     476             :     {
     477        3218 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knFEATURE_TYPE, WT_VARINT));
     478        3218 :         WriteVarUIntSingleByte(&pabyData, static_cast<GUIntBig>(m_eType));
     479             :     }
     480        3220 :     if (!m_anGeometry.empty())
     481             :     {
     482        3218 :         WriteUIntPackedArray(&pabyData, MAKE_KEY(knFEATURE_GEOMETRY, WT_DATA),
     483        3218 :                              m_anGeometry);
     484             :     }
     485             : 
     486        3222 :     CPLAssert(pabyData == *ppabyData + getSize());
     487        3218 :     *ppabyData = pabyData;
     488        3218 : }
     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        7152 : MVTTileLayer::MVTTileLayer()
     563             : {
     564        7138 : }
     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       97097 : void MVTTileLayer::invalidateCachedSize()
     582             : {
     583       97097 :     m_bCachedSize = false;
     584       97097 :     m_nCachedSize = 0;
     585       97097 :     if (m_poOwner)
     586       15034 :         m_poOwner->invalidateCachedSize();
     587       97097 : }
     588             : 
     589             : /************************************************************************/
     590             : /*                          addFeature()                                */
     591             : /************************************************************************/
     592             : 
     593        7410 : size_t MVTTileLayer::addFeature(std::shared_ptr<MVTTileLayerFeature> poFeature)
     594             : {
     595        7410 :     poFeature->setOwner(this);
     596        7397 :     m_apoFeatures.push_back(poFeature);
     597        7408 :     invalidateCachedSize();
     598        7403 :     return m_apoFeatures.size() - 1;
     599             : }
     600             : 
     601             : /************************************************************************/
     602             : /*                            getSize()                                 */
     603             : /************************************************************************/
     604             : 
     605        7340 : size_t MVTTileLayer::getSize() const
     606             : {
     607        7340 :     if (m_bCachedSize)
     608        4374 :         return m_nCachedSize;
     609        2966 :     m_nCachedSize = knSIZE_KEY + GetTextSize(m_osName);
     610        6189 :     for (const auto &poFeature : m_apoFeatures)
     611             :     {
     612        3220 :         const size_t nFeatureSize = poFeature->getSize();
     613        3223 :         m_nCachedSize +=
     614        3226 :             knSIZE_KEY + GetVarUIntSize(nFeatureSize) + nFeatureSize;
     615             :     }
     616       10943 :     for (const auto &osKey : m_aosKeys)
     617             :     {
     618        7983 :         m_nCachedSize += knSIZE_KEY + GetTextSize(osKey);
     619             :     }
     620       11069 :     for (const auto &oValue : m_aoValues)
     621             :     {
     622        8104 :         const size_t nValueSize = oValue.getSize();
     623        8107 :         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        2967 :     m_bCachedSize = true;
     631        2967 :     return m_nCachedSize;
     632             : }
     633             : 
     634             : /************************************************************************/
     635             : /*                             write()                                  */
     636             : /************************************************************************/
     637             : 
     638        2948 : void MVTTileLayer::write(GByte **ppabyData) const
     639             : {
     640        2948 :     GByte *pabyData = *ppabyData;
     641             : 
     642        2948 :     WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_NAME, WT_DATA));
     643        2953 :     WriteText(&pabyData, m_osName);
     644             : 
     645        6170 :     for (const auto &poFeature : m_apoFeatures)
     646             :     {
     647        3214 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_FEATURES, WT_DATA));
     648        3214 :         WriteVarUInt(&pabyData, poFeature->getSize());
     649        3215 :         poFeature->write(&pabyData);
     650             :     }
     651             : 
     652       10947 :     for (const auto &osKey : m_aosKeys)
     653             :     {
     654        7984 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_KEYS, WT_DATA));
     655        7982 :         WriteText(&pabyData, osKey);
     656             :     }
     657             : 
     658       11061 :     for (const auto &oValue : m_aoValues)
     659             :     {
     660        8111 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_VALUES, WT_DATA));
     661        8110 :         WriteVarUInt(&pabyData, oValue.getSize());
     662        8108 :         oValue.write(&pabyData);
     663             :     }
     664             : 
     665        2954 :     if (m_bHasExtent)
     666             :     {
     667        1418 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_EXTENT, WT_VARINT));
     668        1418 :         WriteVarUInt(&pabyData, m_nExtent);
     669             :     }
     670             : 
     671        2954 :     WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_VERSION, WT_VARINT));
     672        2955 :     WriteVarUInt(&pabyData, m_nVersion);
     673             : 
     674        2955 :     CPLAssert(pabyData == *ppabyData + getSize());
     675        2952 :     *ppabyData = pabyData;
     676        2952 : }
     677             : 
     678             : /************************************************************************/
     679             : /*                             write()                                  */
     680             : /************************************************************************/
     681             : 
     682        1533 : void MVTTileLayer::write(GByte *pabyData) const
     683             : {
     684        1533 :     write(&pabyData);
     685        1534 : }
     686             : 
     687             : /************************************************************************/
     688             : /*                             write()                                  */
     689             : /************************************************************************/
     690             : 
     691        1538 : std::string MVTTileLayer::write() const
     692             : {
     693        1538 :     std::string buffer;
     694        1536 :     size_t nSize = getSize();
     695        1535 :     buffer.resize(nSize);
     696        1534 :     write(reinterpret_cast<GByte *>(&buffer[0]));
     697        1532 :     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             :                 std::shared_ptr<MVTTileLayerFeature> poFeature(
     728        1705 :                     new MVTTileLayerFeature());
     729        1705 :                 addFeature(poFeature);
     730        1705 :                 if (!poFeature->read(&pabyData, pabyDataFeatureEnd))
     731           0 :                     return false;
     732        1705 :                 pabyData = pabyDataFeatureEnd;
     733             :             }
     734       10601 :             else if (nKey == MAKE_KEY(knLAYER_KEYS, WT_DATA))
     735             :             {
     736        4448 :                 char *pszKey = nullptr;
     737        4448 :                 READ_TEXT(pabyData, pabyDataLimit, pszKey);
     738             :                 // cppcheck-suppress nullPointer
     739        4448 :                 addKey(pszKey);
     740        4448 :                 CPLFree(pszKey);
     741             :             }
     742        6153 :             else if (nKey == MAKE_KEY(knLAYER_VALUES, WT_DATA))
     743             :             {
     744        4448 :                 unsigned int nValueLength = 0;
     745        4448 :                 READ_SIZE(pabyData, pabyDataLimit, nValueLength);
     746        4448 :                 const GByte *pabyDataValueEnd = pabyData + nValueLength;
     747        4448 :                 MVTTileLayerValue oValue;
     748        4448 :                 if (!oValue.read(&pabyData, pabyDataValueEnd))
     749           0 :                     return false;
     750        4448 :                 addValue(oValue);
     751        4448 :                 pabyData = pabyDataValueEnd;
     752             :             }
     753        1705 :             else if (nKey == MAKE_KEY(knLAYER_EXTENT, WT_VARINT))
     754             :             {
     755           0 :                 unsigned int nExtent = 0;
     756           0 :                 READ_VARUINT32(pabyData, pabyDataLimit, nExtent);
     757           0 :                 setExtent(nExtent);
     758             :             }
     759        1705 :             else if (nKey == MAKE_KEY(knLAYER_VERSION, WT_VARINT))
     760             :             {
     761        1705 :                 unsigned int nVersion = 0;
     762        1705 :                 READ_VARUINT32(pabyData, pabyDataLimit, nVersion);
     763        1705 :                 setVersion(nVersion);
     764             :             }
     765             :             else
     766             :             {
     767           0 :                 SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
     768             :             }
     769             :         }
     770        1705 :         *ppabyData = pabyData;
     771        1705 :         return true;
     772             :     }
     773           0 :     catch (const GPBException &)
     774             :     {
     775           0 :         return false;
     776             :     }
     777             : }
     778             : 
     779             : /************************************************************************/
     780             : /*                             read()                                   */
     781             : /************************************************************************/
     782             : 
     783        1705 : bool MVTTileLayer::read(const GByte *pabyData, const GByte *pabyEnd)
     784             : {
     785        1705 :     return read(&pabyData, pabyEnd);
     786             : }
     787             : 
     788             : /************************************************************************/
     789             : /*                             MVTTile()                                */
     790             : /************************************************************************/
     791             : 
     792         952 : MVTTile::MVTTile()
     793             : {
     794         952 : }
     795             : 
     796             : /************************************************************************/
     797             : /*                            addLayer()                                */
     798             : /************************************************************************/
     799             : 
     800        1418 : void MVTTile::addLayer(std::shared_ptr<MVTTileLayer> poLayer)
     801             : {
     802        1418 :     poLayer->setOwner(this);
     803        1418 :     invalidateCachedSize();
     804        1418 :     m_apoLayers.push_back(poLayer);
     805        1418 : }
     806             : 
     807             : /************************************************************************/
     808             : /*                            getSize()                                 */
     809             : /************************************************************************/
     810             : 
     811        1991 : size_t MVTTile::getSize() const
     812             : {
     813        1991 :     if (m_bCachedSize)
     814        1002 :         return m_nCachedSize;
     815         989 :     m_nCachedSize = 0;
     816        2419 :     for (const auto &poLayer : m_apoLayers)
     817             :     {
     818        1430 :         const size_t nLayerSize = poLayer->getSize();
     819        1430 :         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(nLayerSize) + nLayerSize;
     820             :     }
     821         989 :     m_bCachedSize = true;
     822         989 :     return m_nCachedSize;
     823             : }
     824             : 
     825             : /************************************************************************/
     826             : /*                             write()                                  */
     827             : /************************************************************************/
     828             : 
     829         977 : void MVTTile::write(GByte **ppabyData) const
     830             : {
     831         977 :     GByte *pabyData = *ppabyData;
     832             : 
     833        2395 :     for (const auto &poLayer : m_apoLayers)
     834             :     {
     835        1418 :         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER, WT_DATA));
     836        1418 :         WriteVarUInt(&pabyData, poLayer->getSize());
     837        1418 :         poLayer->write(&pabyData);
     838             :     }
     839             : 
     840         977 :     CPLAssert(pabyData == *ppabyData + getSize());
     841         977 :     *ppabyData = pabyData;
     842         977 : }
     843             : 
     844             : /************************************************************************/
     845             : /*                             write()                                  */
     846             : /************************************************************************/
     847             : 
     848         977 : void MVTTile::write(GByte *pabyData) const
     849             : {
     850         977 :     write(&pabyData);
     851         977 : }
     852             : 
     853             : /************************************************************************/
     854             : /*                             write()                                  */
     855             : /************************************************************************/
     856             : 
     857         977 : std::string MVTTile::write() const
     858             : {
     859         977 :     std::string buffer;
     860         977 :     size_t nSize = getSize();
     861         977 :     if (nSize)
     862             :     {
     863         977 :         buffer.resize(nSize);
     864         977 :         write(reinterpret_cast<GByte *>(&buffer[0]));
     865             :     }
     866         977 :     return buffer;
     867             : }
     868             : 
     869             : #ifdef ADD_MVT_TILE_READ
     870             : 
     871             : /************************************************************************/
     872             : /*                             read()                                   */
     873             : /************************************************************************/
     874             : 
     875             : bool MVTTile::read(const GByte **ppabyData, const GByte *pabyDataLimit)
     876             : {
     877             :     const GByte *pabyData = *ppabyData;
     878             : 
     879             :     try
     880             :     {
     881             :         unsigned int nKey = 0;
     882             :         while (pabyData < pabyDataLimit)
     883             :         {
     884             :             READ_FIELD_KEY(nKey);
     885             :             if (nKey == MAKE_KEY(knLAYER, WT_DATA))
     886             :             {
     887             :                 unsigned int nLayerSize = 0;
     888             :                 READ_SIZE(pabyData, pabyDataLimit, nLayerSize);
     889             :                 const GByte *pabyDataLimitLayer = pabyData + nLayerSize;
     890             :                 std::shared_ptr<MVTTileLayer> poLayer(new MVTTileLayer());
     891             :                 addLayer(poLayer);
     892             :                 if (!poLayer->read(&pabyData, pabyDataLimitLayer))
     893             :                     return false;
     894             :                 pabyData = pabyDataLimitLayer;
     895             :             }
     896             :             else
     897             :             {
     898             :                 SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
     899             :             }
     900             :         }
     901             :         *ppabyData = pabyData;
     902             :         return true;
     903             :     }
     904             :     catch (const GPBException &)
     905             :     {
     906             :         return false;
     907             :     }
     908             : }
     909             : 
     910             : /************************************************************************/
     911             : /*                             read()                                   */
     912             : /************************************************************************/
     913             : 
     914             : bool MVTTile::read(const GByte *pabyData, const GByte *pabyEnd)
     915             : {
     916             :     return read(&pabyData, pabyEnd);
     917             : }
     918             : 
     919             : #endif

Generated by: LCOV version 1.14