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