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  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #include "gpb.h"
30 
31 #include <limits>
32 #include <memory>
33 #include <vector>
34 
35 #include "mvt_tile.h"
36 
37 constexpr int knSIZE_KEY = 1;
38 
39 /************************************************************************/
40 /*                        MVTTileLayerValue()                           */
41 /************************************************************************/
42 
MVTTileLayerValue()43 MVTTileLayerValue::MVTTileLayerValue(): m_nUIntValue(0)
44 {
45 }
46 
MVTTileLayerValue(const MVTTileLayerValue & oOther)47 MVTTileLayerValue::MVTTileLayerValue(const MVTTileLayerValue& oOther)
48 {
49     operator=(oOther);
50 }
51 
52 /************************************************************************/
53 /*                       ~MVTTileLayerValue()                           */
54 /************************************************************************/
55 
~MVTTileLayerValue()56 MVTTileLayerValue::~MVTTileLayerValue()
57 {
58     unset();
59 }
60 
61 /************************************************************************/
62 /*                            operator=                                 */
63 /************************************************************************/
64 
operator =(const MVTTileLayerValue & oOther)65 MVTTileLayerValue& MVTTileLayerValue::operator=(
66                                             const MVTTileLayerValue& oOther)
67 
68 {
69     if( this != &oOther )
70     {
71         unset();
72         m_eType = oOther.m_eType;
73         if( m_eType == ValueType::STRING )
74         {
75             const size_t nSize = strlen(oOther.m_pszValue);
76             m_pszValue = static_cast<char*>(CPLMalloc(1 + nSize));
77             memcpy(m_pszValue, oOther.m_pszValue, nSize);
78             m_pszValue[nSize] = 0;
79         }
80         else
81         {
82             m_nUIntValue = oOther.m_nUIntValue;
83         }
84     }
85     return *this;
86 }
87 
88 /************************************************************************/
89 /*                            operator<                                 */
90 /************************************************************************/
91 
operator <(const MVTTileLayerValue & rhs) const92 bool MVTTileLayerValue::operator <(const MVTTileLayerValue& rhs) const
93 {
94     if( m_eType < rhs.m_eType )
95         return false;
96     if( m_eType > rhs.m_eType )
97         return true;
98     if( m_eType == ValueType::NONE )
99         return false;
100     if( m_eType == ValueType::STRING )
101         return strcmp( m_pszValue, rhs.m_pszValue ) < 0;
102     if( m_eType == ValueType::FLOAT )
103         return m_fValue < rhs.m_fValue;
104     if( m_eType == ValueType::DOUBLE )
105         return m_dfValue < rhs.m_dfValue;
106     if( m_eType == ValueType::INT )
107         return m_nIntValue < rhs.m_nIntValue;
108     if( m_eType == ValueType::UINT )
109         return m_nUIntValue < rhs.m_nUIntValue;
110     if( m_eType == ValueType::SINT )
111         return m_nIntValue < rhs.m_nIntValue;
112     if( m_eType == ValueType::BOOL )
113         return m_bBoolValue < rhs.m_bBoolValue;
114     if( m_eType == ValueType::STRING_MAX_8 )
115         return strncmp( m_achValue, rhs.m_achValue, 8 ) < 0;
116     CPLAssert(false);
117     return false;
118 }
119 
120 /************************************************************************/
121 /*                             unset()                                  */
122 /************************************************************************/
123 
unset()124 void MVTTileLayerValue::unset()
125 {
126     if( m_eType == ValueType::STRING )
127         CPLFree(m_pszValue);
128     m_eType = ValueType::NONE;
129     m_nUIntValue = 0;
130 }
131 
132 /************************************************************************/
133 /*                            GetSizeMax8()                             */
134 /************************************************************************/
135 
GetSizeMax8(const char achValue[8])136 static size_t GetSizeMax8(const char achValue[8])
137 {
138     size_t nSize = 0;
139     while( nSize < 8 && achValue[nSize] != 0 )
140         nSize ++;
141     return nSize;
142 }
143 
144 /************************************************************************/
145 /*                        setStringValue()                              */
146 /************************************************************************/
147 
setStringValue(const std::string & osValue)148 void MVTTileLayerValue::setStringValue(const std::string& osValue)
149 {
150     unset();
151     const size_t nSize = osValue.size();
152     if( nSize <= 8 )
153     {
154         m_eType = ValueType::STRING_MAX_8;
155         if( nSize )
156             memcpy( m_achValue, osValue.c_str(), nSize );
157         if( nSize < 8 )
158             m_achValue[nSize] = 0;
159     }
160     else
161     {
162         m_eType = ValueType::STRING;
163         m_pszValue = static_cast<char*>(CPLMalloc(1 + nSize));
164         memcpy(m_pszValue, osValue.c_str(), nSize);
165         m_pszValue[nSize] = 0;
166     }
167 }
168 
169 /************************************************************************/
170 /*                          setValue()                                  */
171 /************************************************************************/
172 
setValue(double dfVal)173 void MVTTileLayerValue::setValue(double dfVal)
174 {
175     if( dfVal >= 0 &&
176         dfVal <= static_cast<double>(std::numeric_limits<GUInt64>::max()) &&
177         dfVal == static_cast<double>(static_cast<GUInt64>(dfVal)) )
178     {
179         setUIntValue(static_cast<GUInt64>(dfVal));
180     }
181     else if( dfVal >= static_cast<double>(
182                                         std::numeric_limits<GInt64>::min()) &&
183              dfVal < 0 &&
184              dfVal == static_cast<double>(static_cast<GInt64>(dfVal)) )
185     {
186         setSIntValue(static_cast<GInt64>(dfVal));
187     }
188     else if( !CPLIsFinite(dfVal) ||
189              (dfVal >= -std::numeric_limits<float>::max() &&
190               dfVal <= std::numeric_limits<float>::max() &&
191               dfVal == static_cast<float>(dfVal)) )
192     {
193         setFloatValue( static_cast<float>(dfVal) );
194     }
195     else
196     {
197         setDoubleValue( dfVal );
198     }
199 }
200 
201 /************************************************************************/
202 /*                            getSize()                                 */
203 /************************************************************************/
204 
getSize() const205 size_t MVTTileLayerValue::getSize() const
206 {
207     switch( m_eType )
208     {
209         case ValueType::NONE: return 0;
210         case ValueType::STRING:
211         {
212             const size_t nSize = strlen(m_pszValue);
213             return knSIZE_KEY + GetVarUIntSize(nSize) + nSize;
214         }
215         case ValueType::STRING_MAX_8:
216         {
217             const size_t nSize = GetSizeMax8(m_achValue);
218             return knSIZE_KEY + GetVarUIntSize(nSize) + nSize;
219         }
220         case ValueType::FLOAT: return knSIZE_KEY + sizeof(float);
221         case ValueType::DOUBLE: return knSIZE_KEY + sizeof(double);
222         case ValueType::INT: return knSIZE_KEY + GetVarIntSize(m_nIntValue);
223         case ValueType::UINT: return knSIZE_KEY + GetVarUIntSize(m_nUIntValue);
224         case ValueType::SINT: return knSIZE_KEY + GetVarSIntSize(m_nIntValue);
225         case ValueType::BOOL: return knSIZE_KEY + 1;
226         default: return 0;
227     }
228 }
229 
230 /************************************************************************/
231 /*                             write()                                  */
232 /************************************************************************/
233 
write(GByte ** ppabyData) const234 void MVTTileLayerValue::write(GByte** ppabyData) const
235 {
236     GByte* pabyData = *ppabyData;
237 
238     switch( m_eType )
239     {
240         case ValueType::STRING:
241         {
242             const size_t nSize = strlen(m_pszValue);
243             WriteVarUIntSingleByte(&pabyData,
244                                    MAKE_KEY(knVALUE_STRING, WT_DATA));
245             WriteVarUInt(&pabyData, nSize);
246             memcpy(pabyData, m_pszValue, nSize);
247             pabyData += nSize;
248             break;
249         }
250 
251         case ValueType::STRING_MAX_8:
252         {
253             const size_t nSize = GetSizeMax8(m_achValue);
254             WriteVarUIntSingleByte(&pabyData,
255                                    MAKE_KEY(knVALUE_STRING, WT_DATA));
256             WriteVarUInt(&pabyData, nSize);
257             if( nSize )
258                 memcpy(pabyData, m_achValue, nSize);
259             pabyData += nSize;
260             break;
261         }
262 
263         case ValueType::FLOAT:
264             WriteVarUIntSingleByte(&pabyData,
265                                    MAKE_KEY(knVALUE_FLOAT, WT_32BIT));
266             WriteFloat32(&pabyData, m_fValue);
267             break;
268 
269         case ValueType::DOUBLE:
270             WriteVarUIntSingleByte(&pabyData,
271                                    MAKE_KEY(knVALUE_DOUBLE, WT_64BIT));
272             WriteFloat64(&pabyData, m_dfValue);
273             break;
274 
275         case ValueType::INT:
276             WriteVarUIntSingleByte(&pabyData,
277                                    MAKE_KEY(knVALUE_INT, WT_VARINT));
278             WriteVarInt(&pabyData, m_nIntValue);
279             break;
280 
281         case ValueType::UINT:
282             WriteVarUIntSingleByte(&pabyData,
283                                    MAKE_KEY(knVALUE_UINT, WT_VARINT));
284             WriteVarUInt(&pabyData, m_nUIntValue);
285             break;
286 
287         case ValueType::SINT:
288             WriteVarUIntSingleByte(&pabyData,
289                                    MAKE_KEY(knVALUE_SINT, WT_VARINT));
290             WriteVarSInt(&pabyData, m_nIntValue);
291             break;
292 
293         case ValueType::BOOL:
294             WriteVarUIntSingleByte(&pabyData,
295                                    MAKE_KEY(knVALUE_BOOL, WT_VARINT));
296             WriteVarUIntSingleByte(&pabyData, m_bBoolValue ? 1 : 0);
297             break;
298 
299         default:
300             break;
301     }
302 
303     CPLAssert(pabyData == *ppabyData + getSize());
304     *ppabyData = pabyData;
305 }
306 
307 /************************************************************************/
308 /*                             read()                                   */
309 /************************************************************************/
310 
read(const GByte ** ppabyData,const GByte * pabyDataLimit)311 bool MVTTileLayerValue::read(const GByte** ppabyData, const GByte* pabyDataLimit)
312 {
313     const GByte* pabyData = *ppabyData;
314 
315     try
316     {
317         unsigned int nKey = 0;
318         if( pabyData < pabyDataLimit )
319         {
320             READ_FIELD_KEY(nKey);
321 
322             if( nKey == MAKE_KEY(knVALUE_STRING, WT_DATA) )
323             {
324                 char* pszValue = nullptr;
325                 READ_TEXT(pabyData, pabyDataLimit, pszValue);
326                 // cppcheck-suppress nullPointer
327                 setStringValue(pszValue);
328                 CPLFree(pszValue);
329             }
330             else if( nKey == MAKE_KEY(knVALUE_FLOAT, WT_32BIT) )
331             {
332                 setFloatValue(ReadFloat32(&pabyData, pabyDataLimit));
333             }
334             else if( nKey == MAKE_KEY(knVALUE_DOUBLE, WT_64BIT) )
335             {
336                 setDoubleValue(ReadFloat64(&pabyData, pabyDataLimit));
337             }
338             else if( nKey == MAKE_KEY(knVALUE_INT, WT_VARINT) )
339             {
340                 GIntBig nVal = 0;
341                 READ_VARINT64(pabyData, pabyDataLimit, nVal);
342                 setIntValue(nVal);
343             }
344             else if( nKey == MAKE_KEY(knVALUE_UINT, WT_VARINT) )
345             {
346                 GUIntBig nVal = 0;
347                 READ_VARUINT64(pabyData, pabyDataLimit, nVal);
348                 setUIntValue(nVal);
349             }
350             else if( nKey == MAKE_KEY(knVALUE_SINT, WT_VARINT) )
351             {
352                 GIntBig nVal = 0;
353                 READ_VARSINT64(pabyData, pabyDataLimit, nVal);
354                 setSIntValue(nVal);
355             }
356             else if( nKey == MAKE_KEY(knVALUE_BOOL, WT_VARINT) )
357             {
358                 unsigned nVal = 0;
359                 READ_VARUINT32(pabyData, pabyDataLimit, nVal);
360                 setBoolValue(nVal != 0);
361             }
362         }
363         *ppabyData = pabyData;
364         return true;
365     }
366     catch( const GPBException& )
367     {
368         return false;
369     }
370 }
371 
372 /************************************************************************/
373 /*                           MVTTileLayer()                             */
374 /************************************************************************/
375 
MVTTileLayerFeature()376 MVTTileLayerFeature::MVTTileLayerFeature()
377 {
378 }
379 
380 /************************************************************************/
381 /*                             setOwner()                               */
382 /************************************************************************/
383 
setOwner(MVTTileLayer * poOwner)384 void MVTTileLayerFeature::setOwner(MVTTileLayer* poOwner)
385 {
386     CPLAssert( !m_poOwner );
387     m_poOwner = poOwner;
388     m_poOwner->invalidateCachedSize();
389 }
390 
391 /************************************************************************/
392 /*                       invalidateCachedSize()                         */
393 /************************************************************************/
394 
invalidateCachedSize()395 void MVTTileLayerFeature::invalidateCachedSize()
396 {
397     m_bCachedSize = false;
398     m_nCachedSize = 0;
399     if( m_poOwner )
400         m_poOwner->invalidateCachedSize();
401 }
402 
403 /************************************************************************/
404 /*                        GetPackedArraySize()                          */
405 /************************************************************************/
406 
GetPackedArraySize(const std::vector<GUInt32> & anVals)407 static size_t GetPackedArraySize(const std::vector<GUInt32>& anVals)
408 {
409     size_t nPackedSize = 0;
410     for( const auto& nVal: anVals )
411     {
412         nPackedSize += GetVarUIntSize(nVal);
413     }
414     return nPackedSize;
415 }
416 
417 /************************************************************************/
418 /*                            getSize()                                 */
419 /************************************************************************/
420 
getSize() const421 size_t MVTTileLayerFeature::getSize() const
422 {
423     if( m_bCachedSize )
424         return m_nCachedSize;
425     m_bCachedSize = true;
426     m_nCachedSize = 0;
427     if( m_bHasId )
428         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nId);
429     if( !m_anTags.empty() )
430     {
431         size_t nPackedSize = GetPackedArraySize(m_anTags);
432         m_nCachedSize += knSIZE_KEY;
433         m_nCachedSize += GetVarUIntSize(nPackedSize);
434         m_nCachedSize += nPackedSize;
435     }
436     if( m_bHasType )
437         m_nCachedSize += knSIZE_KEY + 1; // fixed size for m_eType
438     if( !m_anGeometry.empty() )
439     {
440         size_t nPackedSize = GetPackedArraySize(m_anGeometry);
441         m_nCachedSize += knSIZE_KEY;
442         m_nCachedSize += GetVarUIntSize(nPackedSize);
443         m_nCachedSize += nPackedSize;
444     }
445     return m_nCachedSize;
446 }
447 
448 /************************************************************************/
449 /*                        WriteUIntPackedArray()                        */
450 /************************************************************************/
451 
WriteUIntPackedArray(GByte ** ppabyData,int nKey,const std::vector<GUInt32> & anVals)452 static void WriteUIntPackedArray(GByte** ppabyData, int nKey,
453                                  const std::vector<GUInt32>& anVals)
454 {
455     GByte* pabyData = *ppabyData;
456     const size_t nPackedSize = GetPackedArraySize(anVals);
457     WriteVarUIntSingleByte(&pabyData, nKey);
458     WriteVarUInt(&pabyData, nPackedSize);
459     for( const auto& nVal: anVals )
460     {
461         WriteVarUInt(&pabyData, nVal);
462     }
463     *ppabyData = pabyData;
464 }
465 
466 /************************************************************************/
467 /*                             write()                                  */
468 /************************************************************************/
469 
write(GByte ** ppabyData) const470 void MVTTileLayerFeature::write(GByte** ppabyData) const
471 {
472     GByte* pabyData = *ppabyData;
473 
474     if( m_bHasId )
475     {
476         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knFEATURE_ID, WT_VARINT));
477         WriteVarUInt(&pabyData, m_nId);
478     }
479     if( !m_anTags.empty() )
480     {
481         WriteUIntPackedArray(&pabyData, MAKE_KEY(knFEATURE_TAGS, WT_DATA),
482                              m_anTags);
483     }
484     if( m_bHasType )
485     {
486         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knFEATURE_TYPE, WT_VARINT));
487         WriteVarUIntSingleByte(&pabyData, static_cast<GUIntBig>(m_eType));
488     }
489     if( !m_anGeometry.empty() )
490     {
491         WriteUIntPackedArray(&pabyData, MAKE_KEY(knFEATURE_GEOMETRY, WT_DATA),
492                              m_anGeometry);
493     }
494 
495     CPLAssert(pabyData == *ppabyData + getSize());
496     *ppabyData = pabyData;
497 }
498 
499 /************************************************************************/
500 /*                             read()                                   */
501 /************************************************************************/
502 
read(const GByte ** ppabyData,const GByte * pabyDataLimit)503 bool MVTTileLayerFeature::read(const GByte** ppabyData,
504                                const GByte* pabyDataLimit)
505 {
506     const GByte* pabyData = *ppabyData;
507 
508     try
509     {
510         unsigned int nKey = 0;
511         while( pabyData < pabyDataLimit )
512         {
513             READ_FIELD_KEY(nKey);
514             if( nKey == MAKE_KEY(knFEATURE_ID, WT_VARINT) )
515             {
516                 GUIntBig nID = 0;
517                 READ_VARUINT64(pabyData, pabyDataLimit, nID);
518                 setId(nID);
519             }
520             else if( nKey == MAKE_KEY(knFEATURE_TAGS, WT_DATA) )
521             {
522                 unsigned int nTagsSize = 0;
523                 READ_SIZE(pabyData, pabyDataLimit, nTagsSize);
524                 const GByte* pabyDataTagsEnd = pabyData + nTagsSize;
525                 while( pabyData < pabyDataTagsEnd )
526                 {
527                     unsigned int nTag = 0;
528                     READ_VARUINT32(pabyData, pabyDataTagsEnd, nTag);
529                     addTag(nTag);
530                 }
531                 pabyData = pabyDataTagsEnd;
532             }
533             else if( nKey == MAKE_KEY(knFEATURE_TYPE, WT_VARINT) )
534             {
535                 unsigned int nType = 0;
536                 READ_VARUINT32(pabyData, pabyDataLimit, nType);
537                 if( nType <= knGEOM_TYPE_POLYGON )
538                     setType(static_cast<GeomType>(nType));
539             }
540             else if( nKey == MAKE_KEY(knFEATURE_GEOMETRY, WT_DATA) )
541             {
542                 unsigned int nGeometrySize = 0;
543                 READ_SIZE(pabyData, pabyDataLimit, nGeometrySize);
544                 const GByte* pabyDataGeometryEnd = pabyData + nGeometrySize;
545                 while( pabyData < pabyDataGeometryEnd )
546                 {
547                     unsigned int nGeometry = 0;
548                     READ_VARUINT32(pabyData, pabyDataGeometryEnd, nGeometry);
549                     addGeometry(nGeometry);
550                 }
551                 pabyData = pabyDataGeometryEnd;
552             }
553             else
554             {
555                 SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
556             }
557         }
558         *ppabyData = pabyData;
559         return true;
560     }
561     catch( const GPBException& )
562     {
563         return false;
564     }
565 }
566 
567 /************************************************************************/
568 /*                           MVTTileLayer()                             */
569 /************************************************************************/
570 
MVTTileLayer()571 MVTTileLayer::MVTTileLayer()
572 {
573 }
574 
575 /************************************************************************/
576 /*                             setOwner()                               */
577 /************************************************************************/
578 
setOwner(MVTTile * poOwner)579 void MVTTileLayer::setOwner(MVTTile* poOwner)
580 {
581     CPLAssert( !m_poOwner );
582     m_poOwner = poOwner;
583     m_poOwner->invalidateCachedSize();
584 }
585 
586 /************************************************************************/
587 /*                       invalidateCachedSize()                         */
588 /************************************************************************/
589 
invalidateCachedSize()590 void MVTTileLayer::invalidateCachedSize()
591 {
592     m_bCachedSize = false;
593     m_nCachedSize = 0;
594     if( m_poOwner )
595         m_poOwner->invalidateCachedSize();
596 }
597 
598 /************************************************************************/
599 /*                          addFeature()                                */
600 /************************************************************************/
601 
addFeature(std::shared_ptr<MVTTileLayerFeature> poFeature)602 size_t MVTTileLayer::addFeature(std::shared_ptr<MVTTileLayerFeature> poFeature)
603 {
604     poFeature->setOwner(this);
605     m_apoFeatures.push_back(poFeature);
606     invalidateCachedSize();
607     return m_apoFeatures.size() - 1;
608 }
609 
610 /************************************************************************/
611 /*                            getSize()                                 */
612 /************************************************************************/
613 
getSize() const614 size_t MVTTileLayer::getSize() const
615 {
616     if( m_bCachedSize )
617         return m_nCachedSize;
618     m_nCachedSize = knSIZE_KEY + GetTextSize(m_osName);
619     for( const auto& poFeature: m_apoFeatures )
620     {
621         const size_t nFeatureSize = poFeature->getSize();
622         m_nCachedSize += knSIZE_KEY +
623                          GetVarUIntSize(nFeatureSize) + nFeatureSize;
624     }
625     for( const auto& osKey: m_aosKeys )
626     {
627         m_nCachedSize += knSIZE_KEY + GetTextSize(osKey);
628     }
629     for( const auto& oValue: m_aoValues )
630     {
631         const size_t nValueSize = oValue.getSize();
632         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(nValueSize) + nValueSize;
633     }
634     if( m_bHasExtent )
635     {
636         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nExtent);
637     }
638     m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nVersion);
639     m_bCachedSize = true;
640     return m_nCachedSize;
641 }
642 
643 /************************************************************************/
644 /*                             write()                                  */
645 /************************************************************************/
646 
write(GByte ** ppabyData) const647 void MVTTileLayer::write(GByte** ppabyData) const
648 {
649     GByte* pabyData = *ppabyData;
650 
651     WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_NAME, WT_DATA));
652     WriteText(&pabyData, m_osName);
653 
654     for( const auto& poFeature: m_apoFeatures )
655     {
656         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_FEATURES, WT_DATA));
657         WriteVarUInt(&pabyData, poFeature->getSize());
658         poFeature->write(&pabyData);
659     }
660 
661     for( const auto& osKey: m_aosKeys )
662     {
663         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_KEYS, WT_DATA));
664         WriteText(&pabyData, osKey);
665     }
666 
667     for( const auto& oValue: m_aoValues )
668     {
669         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_VALUES, WT_DATA));
670         WriteVarUInt(&pabyData, oValue.getSize());
671         oValue.write(&pabyData);
672     }
673 
674     if( m_bHasExtent )
675     {
676         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_EXTENT, WT_VARINT));
677         WriteVarUInt(&pabyData, m_nExtent);
678     }
679 
680     WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_VERSION, WT_VARINT));
681     WriteVarUInt(&pabyData, m_nVersion);
682 
683     CPLAssert(pabyData == *ppabyData + getSize());
684     *ppabyData = pabyData;
685 }
686 
687 /************************************************************************/
688 /*                             write()                                  */
689 /************************************************************************/
690 
write(GByte * pabyData) const691 void MVTTileLayer::write(GByte* pabyData) const
692 {
693     write(&pabyData);
694 }
695 
696 /************************************************************************/
697 /*                             write()                                  */
698 /************************************************************************/
699 
write() const700 std::string MVTTileLayer::write() const
701 {
702     std::string buffer;
703     size_t nSize = getSize();
704     buffer.resize(nSize);
705     write( reinterpret_cast<GByte*>(&buffer[0]) );
706     return buffer;
707 }
708 
709 /************************************************************************/
710 /*                             read()                                   */
711 /************************************************************************/
712 
read(const GByte ** ppabyData,const GByte * pabyDataLimit)713 bool MVTTileLayer::read(const GByte** ppabyData, const GByte* pabyDataLimit)
714 {
715     const GByte* pabyData = *ppabyData;
716 
717     try
718     {
719         unsigned int nKey = 0;
720         while( pabyData < pabyDataLimit )
721         {
722             READ_FIELD_KEY(nKey);
723             if( nKey == MAKE_KEY(knLAYER_NAME, WT_DATA) )
724             {
725                 char* pszLayerName = nullptr;
726                 READ_TEXT(pabyData, pabyDataLimit, pszLayerName);
727                 // cppcheck-suppress nullPointer
728                 setName(pszLayerName);
729                 CPLFree(pszLayerName);
730             }
731             else if( nKey == MAKE_KEY(knLAYER_FEATURES, WT_DATA) )
732             {
733                 unsigned int nFeatureLength = 0;
734                 READ_SIZE(pabyData, pabyDataLimit, nFeatureLength);
735                 const GByte* pabyDataFeatureEnd = pabyData + nFeatureLength;
736                 std::shared_ptr<MVTTileLayerFeature> poFeature(
737                     new MVTTileLayerFeature());
738                 addFeature(poFeature);
739                 if( !poFeature->read(&pabyData, pabyDataFeatureEnd) )
740                     return false;
741                 pabyData = pabyDataFeatureEnd;
742             }
743             else if( nKey == MAKE_KEY(knLAYER_KEYS, WT_DATA) )
744             {
745                 char* pszKey = nullptr;
746                 READ_TEXT(pabyData, pabyDataLimit, pszKey);
747                 // cppcheck-suppress nullPointer
748                 addKey(pszKey);
749                 CPLFree(pszKey);
750             }
751             else if( nKey == MAKE_KEY(knLAYER_VALUES, WT_DATA) )
752             {
753                 unsigned int nValueLength = 0;
754                 READ_SIZE(pabyData, pabyDataLimit, nValueLength);
755                 const GByte* pabyDataValueEnd = pabyData + nValueLength;
756                 MVTTileLayerValue oValue;
757                 if( !oValue.read(&pabyData, pabyDataValueEnd) )
758                     return false;
759                 addValue(oValue);
760                 pabyData = pabyDataValueEnd;
761             }
762             else if( nKey == MAKE_KEY(knLAYER_EXTENT, WT_VARINT) )
763             {
764                 unsigned int nExtent = 0;
765                 READ_VARUINT32(pabyData, pabyDataLimit, nExtent);
766                 setExtent(nExtent);
767             }
768             else if( nKey == MAKE_KEY(knLAYER_VERSION, WT_VARINT) )
769             {
770                 unsigned int nVersion = 0;
771                 READ_VARUINT32(pabyData, pabyDataLimit, nVersion);
772                 setVersion(nVersion);
773             }
774             else
775             {
776                 SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
777             }
778         }
779         *ppabyData = pabyData;
780         return true;
781     }
782     catch( const GPBException& )
783     {
784         return false;
785     }
786 }
787 
788 /************************************************************************/
789 /*                             read()                                   */
790 /************************************************************************/
791 
read(const GByte * pabyData,const GByte * pabyEnd)792 bool MVTTileLayer::read(const GByte* pabyData, const GByte* pabyEnd)
793 {
794     return read(&pabyData, pabyEnd);
795 }
796 
797 /************************************************************************/
798 /*                             MVTTile()                                */
799 /************************************************************************/
800 
MVTTile()801 MVTTile::MVTTile()
802 {
803 }
804 
805 /************************************************************************/
806 /*                            addLayer()                                */
807 /************************************************************************/
808 
addLayer(std::shared_ptr<MVTTileLayer> poLayer)809 void MVTTile::addLayer(std::shared_ptr<MVTTileLayer> poLayer)
810 {
811     poLayer->setOwner(this);
812     invalidateCachedSize();
813     m_apoLayers.push_back(poLayer);
814 }
815 
816 /************************************************************************/
817 /*                            getSize()                                 */
818 /************************************************************************/
819 
getSize() const820 size_t MVTTile::getSize() const
821 {
822     if( m_bCachedSize )
823         return m_nCachedSize;
824     m_nCachedSize = 0;
825     for( const auto& poLayer: m_apoLayers )
826     {
827         const size_t nLayerSize = poLayer->getSize();
828         m_nCachedSize += knSIZE_KEY + GetVarUIntSize(nLayerSize) + nLayerSize;
829     }
830     m_bCachedSize = true;
831     return m_nCachedSize;
832 }
833 
834 /************************************************************************/
835 /*                             write()                                  */
836 /************************************************************************/
837 
write(GByte ** ppabyData) const838 void MVTTile::write(GByte** ppabyData) const
839 {
840     GByte* pabyData = *ppabyData;
841 
842     for( const auto& poLayer: m_apoLayers )
843     {
844         WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER, WT_DATA));
845         WriteVarUInt(&pabyData, poLayer->getSize());
846         poLayer->write(&pabyData);
847     }
848 
849     CPLAssert(pabyData == *ppabyData + getSize());
850     *ppabyData = pabyData;
851 }
852 
853 /************************************************************************/
854 /*                             write()                                  */
855 /************************************************************************/
856 
write(GByte * pabyData) const857 void MVTTile::write(GByte* pabyData) const
858 {
859     write(&pabyData);
860 }
861 
862 /************************************************************************/
863 /*                             write()                                  */
864 /************************************************************************/
865 
write() const866 std::string MVTTile::write() const
867 {
868     std::string buffer;
869     size_t nSize = getSize();
870     if( nSize )
871     {
872         buffer.resize(nSize);
873         write( reinterpret_cast<GByte*>(&buffer[0]) );
874     }
875     return buffer;
876 }
877 
878 #ifdef ADD_MVT_TILE_READ
879 
880 /************************************************************************/
881 /*                             read()                                   */
882 /************************************************************************/
883 
read(const GByte ** ppabyData,const GByte * pabyDataLimit)884 bool MVTTile::read(const GByte** ppabyData, const GByte* pabyDataLimit)
885 {
886     const GByte* pabyData = *ppabyData;
887 
888     try
889     {
890         unsigned int nKey = 0;
891         while( pabyData < pabyDataLimit )
892         {
893             READ_FIELD_KEY(nKey);
894             if( nKey == MAKE_KEY(knLAYER, WT_DATA) )
895             {
896                 unsigned int nLayerSize = 0;
897                 READ_SIZE(pabyData, pabyDataLimit, nLayerSize);
898                 const GByte* pabyDataLimitLayer = pabyData + nLayerSize;
899                 std::shared_ptr<MVTTileLayer> poLayer(new MVTTileLayer());
900                 addLayer(poLayer);
901                 if( !poLayer->read(&pabyData, pabyDataLimitLayer) )
902                     return false;
903                 pabyData = pabyDataLimitLayer;
904             }
905             else
906             {
907                 SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
908             }
909         }
910         *ppabyData = pabyData;
911         return true;
912     }
913     catch( const GPBException& )
914     {
915         return false;
916     }
917 }
918 
919 /************************************************************************/
920 /*                             read()                                   */
921 /************************************************************************/
922 
read(const GByte * pabyData,const GByte * pabyEnd)923 bool MVTTile::read(const GByte* pabyData, const GByte* pabyEnd)
924 {
925     return read(&pabyData, pabyEnd);
926 }
927 
928 #endif
929