• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OSGeo / gdal / 15899162844

26 Jun 2025 10:14AM UTC coverage: 71.088% (+0.004%) from 71.084%
15899162844

Pull #12623

github

web-flow
Merge c704a8392 into f5cb024d4
Pull Request #12623: gdal raster overview add: add a --overview-src option

209 of 244 new or added lines in 5 files covered. (85.66%)

96 existing lines in 44 files now uncovered.

574014 of 807474 relevant lines covered (71.09%)

250815.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.52
/ogr/ogrsf_frmts/mvt/mvt_tile.cpp
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
MVTTileLayerValue::MVTTileLayerValue() : m_nUIntValue(0)
9,467✔
29
{
30
}
9,467✔
31

32
MVTTileLayerValue::MVTTileLayerValue(const MVTTileLayerValue &oOther)
35,995✔
33
{
34
    operator=(oOther);
35,995✔
35
}
36,011✔
36

37
/************************************************************************/
38
/*                       ~MVTTileLayerValue()                           */
39
/************************************************************************/
40

41
MVTTileLayerValue::~MVTTileLayerValue()
90,765✔
42
{
43
    unset();
45,285✔
44
}
45,480✔
45

46
/************************************************************************/
47
/*                            operator=                                 */
48
/************************************************************************/
49

50
MVTTileLayerValue &MVTTileLayerValue::operator=(const MVTTileLayerValue &oOther)
35,998✔
51

52
{
53
    if (this != &oOther)
35,998✔
54
    {
55
        unset();
35,997✔
56
        m_eType = oOther.m_eType;
35,996✔
57
        if (m_eType == ValueType::STRING)
35,996✔
58
        {
59
            const size_t nSize = strlen(oOther.m_pszValue);
9,580✔
60
            m_pszValue = static_cast<char *>(CPLMalloc(1 + nSize));
9,580✔
61
            memcpy(m_pszValue, oOther.m_pszValue, nSize);
9,595✔
62
            m_pszValue[nSize] = 0;
9,595✔
63
        }
64
        else
65
        {
66
            m_nUIntValue = oOther.m_nUIntValue;
26,416✔
67
        }
68
    }
69
    return *this;
36,012✔
70
}
71

72
/************************************************************************/
73
/*                            operator<                                 */
74
/************************************************************************/
75

76
bool MVTTileLayerValue::operator<(const MVTTileLayerValue &rhs) const
54,076✔
77
{
78
    if (m_eType < rhs.m_eType)
54,076✔
79
        return false;
4,345✔
80
    if (m_eType > rhs.m_eType)
49,731✔
81
        return true;
17,484✔
82
    if (m_eType == ValueType::NONE)
32,247✔
83
        return false;
×
84
    if (m_eType == ValueType::STRING)
32,247✔
85
        return strcmp(m_pszValue, rhs.m_pszValue) < 0;
14,337✔
86
    if (m_eType == ValueType::FLOAT)
17,910✔
87
        return m_fValue < rhs.m_fValue;
98✔
88
    if (m_eType == ValueType::DOUBLE)
17,812✔
89
        return m_dfValue < rhs.m_dfValue;
9,346✔
90
    if (m_eType == ValueType::INT)
8,466✔
91
        return m_nIntValue < rhs.m_nIntValue;
×
92
    if (m_eType == ValueType::UINT)
8,466✔
93
        return m_nUIntValue < rhs.m_nUIntValue;
2,400✔
94
    if (m_eType == ValueType::SINT)
6,066✔
95
        return m_nIntValue < rhs.m_nIntValue;
84✔
96
    if (m_eType == ValueType::BOOL)
5,982✔
97
        return m_bBoolValue < rhs.m_bBoolValue;
80✔
98
    if (m_eType == ValueType::STRING_MAX_8)
5,902✔
99
        return strncmp(m_achValue, rhs.m_achValue, 8) < 0;
5,902✔
100
    CPLAssert(false);
×
101
    return false;
102
}
103

104
/************************************************************************/
105
/*                             unset()                                  */
106
/************************************************************************/
107

108
void MVTTileLayerValue::unset()
90,943✔
109
{
110
    if (m_eType == ValueType::STRING)
90,943✔
111
        CPLFree(m_pszValue);
13,311✔
112
    m_eType = ValueType::NONE;
90,947✔
113
    m_nUIntValue = 0;
90,947✔
114
}
90,947✔
115

116
/************************************************************************/
117
/*                            GetSizeMax8()                             */
118
/************************************************************************/
119

120
static size_t GetSizeMax8(const char achValue[8])
6,450✔
121
{
122
    size_t nSize = 0;
6,450✔
123
    while (nSize < 8 && achValue[nSize] != 0)
27,519✔
124
        nSize++;
21,069✔
125
    return nSize;
6,450✔
126
}
127

128
/************************************************************************/
129
/*                        setStringValue()                              */
130
/************************************************************************/
131

132
void MVTTileLayerValue::setStringValue(const std::string &osValue)
5,598✔
133
{
134
    unset();
5,598✔
135
    const size_t nSize = osValue.size();
5,598✔
136
    if (nSize <= 8)
5,598✔
137
    {
138
        m_eType = ValueType::STRING_MAX_8;
1,889✔
139
        if (nSize)
1,889✔
140
            memcpy(m_achValue, osValue.c_str(), nSize);
1,889✔
141
        if (nSize < 8)
1,889✔
142
            m_achValue[nSize] = 0;
1,781✔
143
    }
144
    else
145
    {
146
        m_eType = ValueType::STRING;
3,709✔
147
        m_pszValue = static_cast<char *>(CPLMalloc(1 + nSize));
3,709✔
148
        memcpy(m_pszValue, osValue.c_str(), nSize);
3,709✔
149
        m_pszValue[nSize] = 0;
3,709✔
150
    }
151
}
5,598✔
152

153
/************************************************************************/
154
/*                          setValue()                                  */
155
/************************************************************************/
156

157
void MVTTileLayerValue::setValue(double dfVal)
140✔
158
{
159
    if (dfVal >= 0 &&
277✔
160
        dfVal <= static_cast<double>(std::numeric_limits<GUInt64>::max()) &&
277✔
161
        dfVal == static_cast<double>(static_cast<GUInt64>(dfVal)))
137✔
162
    {
163
        setUIntValue(static_cast<GUInt64>(dfVal));
×
164
    }
165
    else if (dfVal >= static_cast<double>(std::numeric_limits<GInt64>::min()) &&
280✔
166
             dfVal < 0 &&
280✔
167
             dfVal == static_cast<double>(static_cast<GInt64>(dfVal)))
3✔
168
    {
169
        setSIntValue(static_cast<GInt64>(dfVal));
×
170
    }
171
    else if (!std::isfinite(dfVal) ||
280✔
172
             (dfVal >= -std::numeric_limits<float>::max() &&
140✔
173
              dfVal <= std::numeric_limits<float>::max() &&
140✔
174
              dfVal == static_cast<float>(dfVal)))
140✔
175
    {
176
        setFloatValue(static_cast<float>(dfVal));
6✔
177
    }
178
    else
179
    {
180
        setDoubleValue(dfVal);
134✔
181
    }
182
}
140✔
183

184
/************************************************************************/
185
/*                            getSize()                                 */
186
/************************************************************************/
187

188
size_t MVTTileLayerValue::getSize() const
24,271✔
189
{
190
    switch (m_eType)
24,271✔
191
    {
192
        case ValueType::NONE:
×
193
            return 0;
×
194
        case ValueType::STRING:
9,559✔
195
        {
196
            const size_t nSize = strlen(m_pszValue);
9,559✔
197
            return knSIZE_KEY + GetVarUIntSize(nSize) + nSize;
9,559✔
198
        }
199
        case ValueType::STRING_MAX_8:
4,843✔
200
        {
201
            const size_t nSize = GetSizeMax8(m_achValue);
4,843✔
202
            return knSIZE_KEY + GetVarUIntSize(nSize) + nSize;
4,843✔
203
        }
204
        case ValueType::FLOAT:
150✔
205
            return knSIZE_KEY + sizeof(float);
150✔
206
        case ValueType::DOUBLE:
4,718✔
207
            return knSIZE_KEY + sizeof(double);
4,718✔
208
        case ValueType::INT:
×
209
            return knSIZE_KEY + GetVarIntSize(m_nIntValue);
×
210
        case ValueType::UINT:
4,871✔
211
            return knSIZE_KEY + GetVarUIntSize(m_nUIntValue);
4,871✔
212
        case ValueType::SINT:
90✔
213
            return knSIZE_KEY + GetVarSIntSize(m_nIntValue);
90✔
214
        case ValueType::BOOL:
54✔
215
            return knSIZE_KEY + 1;
54✔
216
        default:
×
217
            return 0;
×
218
    }
219
}
220

221
/************************************************************************/
222
/*                             write()                                  */
223
/************************************************************************/
224

225
void MVTTileLayerValue::write(GByte **ppabyData) const
8,091✔
226
{
227
    GByte *pabyData = *ppabyData;
8,091✔
228

229
    switch (m_eType)
8,091✔
230
    {
231
        case ValueType::STRING:
3,188✔
232
        {
233
            const size_t nSize = strlen(m_pszValue);
3,188✔
234
            WriteVarUIntSingleByte(&pabyData,
3,188✔
235
                                   MAKE_KEY(knVALUE_STRING, WT_DATA));
236
            WriteVarUInt(&pabyData, nSize);
3,185✔
237
            memcpy(pabyData, m_pszValue, nSize);
3,179✔
238
            pabyData += nSize;
3,179✔
239
            break;
3,179✔
240
        }
241

242
        case ValueType::STRING_MAX_8:
1,616✔
243
        {
244
            const size_t nSize = GetSizeMax8(m_achValue);
1,616✔
245
            WriteVarUIntSingleByte(&pabyData,
1,612✔
246
                                   MAKE_KEY(knVALUE_STRING, WT_DATA));
247
            WriteVarUInt(&pabyData, nSize);
1,611✔
248
            if (nSize)
1,612✔
249
                memcpy(pabyData, m_achValue, nSize);
1,613✔
250
            pabyData += nSize;
1,612✔
251
            break;
1,612✔
252
        }
253

254
        case ValueType::FLOAT:
50✔
255
            WriteVarUIntSingleByte(&pabyData,
50✔
256
                                   MAKE_KEY(knVALUE_FLOAT, WT_32BIT));
257
            WriteFloat32(&pabyData, m_fValue);
50✔
258
            break;
50✔
259

260
        case ValueType::DOUBLE:
1,574✔
261
            WriteVarUIntSingleByte(&pabyData,
1,574✔
262
                                   MAKE_KEY(knVALUE_DOUBLE, WT_64BIT));
263
            WriteFloat64(&pabyData, m_dfValue);
1,573✔
264
            break;
1,570✔
265

266
        case ValueType::INT:
×
267
            WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knVALUE_INT, WT_VARINT));
×
268
            WriteVarInt(&pabyData, m_nIntValue);
×
269
            break;
×
270

271
        case ValueType::UINT:
1,623✔
272
            WriteVarUIntSingleByte(&pabyData,
1,623✔
273
                                   MAKE_KEY(knVALUE_UINT, WT_VARINT));
274
            WriteVarUInt(&pabyData, m_nUIntValue);
1,626✔
275
            break;
1,620✔
276

277
        case ValueType::SINT:
30✔
278
            WriteVarUIntSingleByte(&pabyData,
30✔
279
                                   MAKE_KEY(knVALUE_SINT, WT_VARINT));
280
            WriteVarSInt(&pabyData, m_nIntValue);
30✔
281
            break;
30✔
282

283
        case ValueType::BOOL:
18✔
284
            WriteVarUIntSingleByte(&pabyData,
18✔
285
                                   MAKE_KEY(knVALUE_BOOL, WT_VARINT));
286
            WriteVarUIntSingleByte(&pabyData, m_bBoolValue ? 1 : 0);
18✔
287
            break;
18✔
288

UNCOV
289
        default:
×
UNCOV
290
            break;
×
291
    }
292

293
    CPLAssert(pabyData == *ppabyData + getSize());
8,071✔
294
    *ppabyData = pabyData;
8,096✔
295
}
8,096✔
296

297
/************************************************************************/
298
/*                             read()                                   */
299
/************************************************************************/
300

301
bool MVTTileLayerValue::read(const GByte **ppabyData,
4,448✔
302
                             const GByte *pabyDataLimit)
303
{
304
    const GByte *pabyData = *ppabyData;
4,448✔
305

306
    try
307
    {
308
        unsigned int nKey = 0;
4,448✔
309
        if (pabyData < pabyDataLimit)
4,448✔
310
        {
311
            READ_FIELD_KEY(nKey);
4,448✔
312

313
            if (nKey == MAKE_KEY(knVALUE_STRING, WT_DATA))
4,448✔
314
            {
315
                char *pszValue = nullptr;
2,656✔
316
                READ_TEXT(pabyData, pabyDataLimit, pszValue);
2,656✔
317
                // cppcheck-suppress nullPointer
318
                setStringValue(pszValue);
2,656✔
319
                CPLFree(pszValue);
2,656✔
320
            }
321
            else if (nKey == MAKE_KEY(knVALUE_FLOAT, WT_32BIT))
1,792✔
322
            {
323
                setFloatValue(ReadFloat32(&pabyData, pabyDataLimit));
28✔
324
            }
325
            else if (nKey == MAKE_KEY(knVALUE_DOUBLE, WT_64BIT))
1,764✔
326
            {
327
                setDoubleValue(ReadFloat64(&pabyData, pabyDataLimit));
853✔
328
            }
329
            else if (nKey == MAKE_KEY(knVALUE_INT, WT_VARINT))
911✔
330
            {
331
                GIntBig nVal = 0;
×
332
                READ_VARINT64(pabyData, pabyDataLimit, nVal);
×
333
                setIntValue(nVal);
×
334
            }
335
            else if (nKey == MAKE_KEY(knVALUE_UINT, WT_VARINT))
911✔
336
            {
337
                GUIntBig nVal = 0;
881✔
338
                READ_VARUINT64(pabyData, pabyDataLimit, nVal);
881✔
339
                setUIntValue(nVal);
881✔
340
            }
341
            else if (nKey == MAKE_KEY(knVALUE_SINT, WT_VARINT))
30✔
342
            {
343
                GIntBig nVal = 0;
18✔
344
                READ_VARSINT64(pabyData, pabyDataLimit, nVal);
18✔
345
                setSIntValue(nVal);
18✔
346
            }
347
            else if (nKey == MAKE_KEY(knVALUE_BOOL, WT_VARINT))
12✔
348
            {
349
                unsigned nVal = 0;
12✔
350
                READ_VARUINT32(pabyData, pabyDataLimit, nVal);
12✔
351
                setBoolValue(nVal != 0);
12✔
352
            }
353
        }
354
        *ppabyData = pabyData;
4,448✔
355
        return true;
4,448✔
356
    }
357
    catch (const GPBException &)
×
358
    {
359
        return false;
×
360
    }
361
}
362

363
/************************************************************************/
364
/*                           MVTTileLayer()                             */
365
/************************************************************************/
366

367
MVTTileLayerFeature::MVTTileLayerFeature()
7,413✔
368
{
369
}
7,406✔
370

371
/************************************************************************/
372
/*                             setOwner()                               */
373
/************************************************************************/
374

375
void MVTTileLayerFeature::setOwner(MVTTileLayer *poOwner)
7,372✔
376
{
377
    CPLAssert(!m_poOwner);
7,372✔
378
    m_poOwner = poOwner;
7,372✔
379
    m_poOwner->invalidateCachedSize();
7,372✔
380
}
7,374✔
381

382
/************************************************************************/
383
/*                       invalidateCachedSize()                         */
384
/************************************************************************/
385

386
void MVTTileLayerFeature::invalidateCachedSize()
53,964✔
387
{
388
    m_bCachedSize = false;
53,964✔
389
    m_nCachedSize = 0;
53,964✔
390
    if (m_poOwner)
53,964✔
391
        m_poOwner->invalidateCachedSize();
41,627✔
392
}
53,927✔
393

394
/************************************************************************/
395
/*                        GetPackedArraySize()                          */
396
/************************************************************************/
397

398
static size_t GetPackedArraySize(const std::vector<GUInt32> &anVals)
10,178✔
399
{
400
    size_t nPackedSize = 0;
10,178✔
401
    for (const auto &nVal : anVals)
71,502✔
402
    {
403
        nPackedSize += GetVarUIntSize(nVal);
61,344✔
404
    }
405
    return nPackedSize;
10,180✔
406
}
407

408
/************************************************************************/
409
/*                            getSize()                                 */
410
/************************************************************************/
411

412
size_t MVTTileLayerFeature::getSize() const
9,612✔
413
{
414
    if (m_bCachedSize)
9,612✔
415
        return m_nCachedSize;
6,405✔
416
    m_bCachedSize = true;
3,207✔
417
    m_nCachedSize = 0;
3,207✔
418
    if (m_bHasId)
3,207✔
419
        m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nId);
106✔
420
    if (!m_anTags.empty())
3,207✔
421
    {
422
        size_t nPackedSize = GetPackedArraySize(m_anTags);
1,878✔
423
        m_nCachedSize += knSIZE_KEY;
1,886✔
424
        m_nCachedSize += GetVarUIntSize(nPackedSize);
1,886✔
425
        m_nCachedSize += nPackedSize;
1,884✔
426
    }
427
    if (m_bHasType)
3,203✔
428
        m_nCachedSize += knSIZE_KEY + 1;  // fixed size for m_eType
3,204✔
429
    if (!m_anGeometry.empty())
3,203✔
430
    {
431
        size_t nPackedSize = GetPackedArraySize(m_anGeometry);
3,205✔
432
        m_nCachedSize += knSIZE_KEY;
3,202✔
433
        m_nCachedSize += GetVarUIntSize(nPackedSize);
3,202✔
434
        m_nCachedSize += nPackedSize;
3,203✔
435
    }
436
    return m_nCachedSize;
3,204✔
437
}
438

439
/************************************************************************/
440
/*                        WriteUIntPackedArray()                        */
441
/************************************************************************/
442

443
static void WriteUIntPackedArray(GByte **ppabyData, int nKey,
5,089✔
444
                                 const std::vector<GUInt32> &anVals)
445
{
446
    GByte *pabyData = *ppabyData;
5,089✔
447
    const size_t nPackedSize = GetPackedArraySize(anVals);
5,089✔
448
    WriteVarUIntSingleByte(&pabyData, nKey);
5,093✔
449
    WriteVarUInt(&pabyData, nPackedSize);
5,091✔
450
    for (const auto &nVal : anVals)
35,757✔
451
    {
452
        WriteVarUInt(&pabyData, nVal);
30,664✔
453
    }
454
    *ppabyData = pabyData;
5,083✔
455
}
5,083✔
456

457
/************************************************************************/
458
/*                             write()                                  */
459
/************************************************************************/
460

461
void MVTTileLayerFeature::write(GByte **ppabyData) const
3,208✔
462
{
463
    GByte *pabyData = *ppabyData;
3,208✔
464

465
    if (m_bHasId)
3,208✔
466
    {
467
        WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knFEATURE_ID, WT_VARINT));
106✔
468
        WriteVarUInt(&pabyData, m_nId);
106✔
469
    }
470
    if (!m_anTags.empty())
3,208✔
471
    {
472
        WriteUIntPackedArray(&pabyData, MAKE_KEY(knFEATURE_TAGS, WT_DATA),
1,884✔
473
                             m_anTags);
1,884✔
474
    }
475
    if (m_bHasType)
3,206✔
476
    {
477
        WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knFEATURE_TYPE, WT_VARINT));
3,206✔
478
        WriteVarUIntSingleByte(&pabyData, static_cast<GUIntBig>(m_eType));
3,204✔
479
    }
480
    if (!m_anGeometry.empty())
3,204✔
481
    {
482
        WriteUIntPackedArray(&pabyData, MAKE_KEY(knFEATURE_GEOMETRY, WT_DATA),
3,208✔
483
                             m_anGeometry);
3,208✔
484
    }
485

486
    CPLAssert(pabyData == *ppabyData + getSize());
3,208✔
487
    *ppabyData = pabyData;
3,208✔
488
}
3,208✔
489

490
/************************************************************************/
491
/*                             read()                                   */
492
/************************************************************************/
493

494
bool MVTTileLayerFeature::read(const GByte **ppabyData,
1,700✔
495
                               const GByte *pabyDataLimit)
496
{
497
    const GByte *pabyData = *ppabyData;
1,700✔
498

499
    try
500
    {
501
        unsigned int nKey = 0;
1,700✔
502
        while (pabyData < pabyDataLimit)
6,147✔
503
        {
504
            READ_FIELD_KEY(nKey);
4,447✔
505
            if (nKey == MAKE_KEY(knFEATURE_ID, WT_VARINT))
4,447✔
506
            {
507
                GUIntBig nID = 0;
53✔
508
                READ_VARUINT64(pabyData, pabyDataLimit, nID);
53✔
509
                setId(nID);
53✔
510
            }
511
            else if (nKey == MAKE_KEY(knFEATURE_TAGS, WT_DATA))
4,394✔
512
            {
513
                unsigned int nTagsSize = 0;
994✔
514
                READ_SIZE(pabyData, pabyDataLimit, nTagsSize);
994✔
515
                const GByte *pabyDataTagsEnd = pabyData + nTagsSize;
994✔
516
                while (pabyData < pabyDataTagsEnd)
9,890✔
517
                {
518
                    unsigned int nTag = 0;
8,896✔
519
                    READ_VARUINT32(pabyData, pabyDataTagsEnd, nTag);
8,896✔
520
                    addTag(nTag);
8,896✔
521
                }
522
                pabyData = pabyDataTagsEnd;
994✔
523
            }
524
            else if (nKey == MAKE_KEY(knFEATURE_TYPE, WT_VARINT))
3,400✔
525
            {
526
                unsigned int nType = 0;
1,700✔
527
                READ_VARUINT32(pabyData, pabyDataLimit, nType);
1,700✔
528
                if (nType <= knGEOM_TYPE_POLYGON)
1,700✔
529
                    setType(static_cast<GeomType>(nType));
1,700✔
530
            }
531
            else if (nKey == MAKE_KEY(knFEATURE_GEOMETRY, WT_DATA))
1,700✔
532
            {
533
                unsigned int nGeometrySize = 0;
1,700✔
534
                READ_SIZE(pabyData, pabyDataLimit, nGeometrySize);
1,700✔
535
                const GByte *pabyDataGeometryEnd = pabyData + nGeometrySize;
1,700✔
536
                while (pabyData < pabyDataGeometryEnd)
8,988✔
537
                {
538
                    unsigned int nGeometry = 0;
7,288✔
539
                    READ_VARUINT32(pabyData, pabyDataGeometryEnd, nGeometry);
7,288✔
540
                    addGeometry(nGeometry);
7,288✔
541
                }
542
                pabyData = pabyDataGeometryEnd;
1,700✔
543
            }
544
            else
545
            {
546
                SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
×
547
            }
548
        }
549
        *ppabyData = pabyData;
1,700✔
550
        return true;
1,700✔
551
    }
552
    catch (const GPBException &)
×
553
    {
554
        return false;
×
555
    }
556
}
557

558
/************************************************************************/
559
/*                           MVTTileLayer()                             */
560
/************************************************************************/
561

562
MVTTileLayer::MVTTileLayer()
7,093✔
563
{
564
}
7,113✔
565

566
/************************************************************************/
567
/*                             setOwner()                               */
568
/************************************************************************/
569

570
void MVTTileLayer::setOwner(MVTTile *poOwner)
1,413✔
571
{
572
    CPLAssert(!m_poOwner);
1,413✔
573
    m_poOwner = poOwner;
1,413✔
574
    m_poOwner->invalidateCachedSize();
1,413✔
575
}
1,413✔
576

577
/************************************************************************/
578
/*                       invalidateCachedSize()                         */
579
/************************************************************************/
580

581
void MVTTileLayer::invalidateCachedSize()
88,986✔
582
{
583
    m_bCachedSize = false;
88,986✔
584
    m_nCachedSize = 0;
88,986✔
585
    if (m_poOwner)
88,986✔
586
        m_poOwner->invalidateCachedSize();
15,009✔
587
}
88,986✔
588

589
/************************************************************************/
590
/*                          addFeature()                                */
591
/************************************************************************/
592

593
size_t MVTTileLayer::addFeature(std::shared_ptr<MVTTileLayerFeature> poFeature)
7,371✔
594
{
595
    poFeature->setOwner(this);
7,371✔
596
    m_apoFeatures.push_back(poFeature);
7,375✔
597
    invalidateCachedSize();
7,385✔
598
    return m_apoFeatures.size() - 1;
7,378✔
599
}
600

601
/************************************************************************/
602
/*                            getSize()                                 */
603
/************************************************************************/
604

605
size_t MVTTileLayer::getSize() const
7,311✔
606
{
607
    if (m_bCachedSize)
7,311✔
608
        return m_nCachedSize;
4,355✔
609
    m_nCachedSize = knSIZE_KEY + GetTextSize(m_osName);
2,956✔
610
    for (const auto &poFeature : m_apoFeatures)
6,151✔
611
    {
612
        const size_t nFeatureSize = poFeature->getSize();
3,201✔
613
        m_nCachedSize +=
3,204✔
614
            knSIZE_KEY + GetVarUIntSize(nFeatureSize) + nFeatureSize;
3,206✔
615
    }
616
    for (const auto &osKey : m_aosKeys)
10,927✔
617
    {
618
        m_nCachedSize += knSIZE_KEY + GetTextSize(osKey);
7,961✔
619
    }
620
    for (const auto &oValue : m_aoValues)
11,037✔
621
    {
622
        const size_t nValueSize = oValue.getSize();
8,079✔
623
        m_nCachedSize += knSIZE_KEY + GetVarUIntSize(nValueSize) + nValueSize;
8,088✔
624
    }
625
    if (m_bHasExtent)
2,955✔
626
    {
627
        m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nExtent);
1,425✔
628
    }
629
    m_nCachedSize += knSIZE_KEY + GetVarUIntSize(m_nVersion);
2,955✔
630
    m_bCachedSize = true;
2,952✔
631
    return m_nCachedSize;
2,952✔
632
}
633

634
/************************************************************************/
635
/*                             write()                                  */
636
/************************************************************************/
637

638
void MVTTileLayer::write(GByte **ppabyData) const
2,929✔
639
{
640
    GByte *pabyData = *ppabyData;
2,929✔
641

642
    WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_NAME, WT_DATA));
2,929✔
643
    WriteText(&pabyData, m_osName);
2,939✔
644

645
    for (const auto &poFeature : m_apoFeatures)
6,146✔
646
    {
647
        WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_FEATURES, WT_DATA));
3,199✔
648
        WriteVarUInt(&pabyData, poFeature->getSize());
3,199✔
649
        poFeature->write(&pabyData);
3,199✔
650
    }
651

652
    for (const auto &osKey : m_aosKeys)
10,931✔
653
    {
654
        WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_KEYS, WT_DATA));
7,981✔
655
        WriteText(&pabyData, osKey);
7,983✔
656
    }
657

658
    for (const auto &oValue : m_aoValues)
11,101✔
659
    {
660
        WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_VALUES, WT_DATA));
8,098✔
661
        WriteVarUInt(&pabyData, oValue.getSize());
8,097✔
662
        oValue.write(&pabyData);
8,086✔
663
    }
664

665
    if (m_bHasExtent)
2,943✔
666
    {
667
        WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_EXTENT, WT_VARINT));
1,413✔
668
        WriteVarUInt(&pabyData, m_nExtent);
1,413✔
669
    }
670

671
    WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER_VERSION, WT_VARINT));
2,943✔
672
    WriteVarUInt(&pabyData, m_nVersion);
2,940✔
673

674
    CPLAssert(pabyData == *ppabyData + getSize());
2,942✔
675
    *ppabyData = pabyData;
2,940✔
676
}
2,940✔
677

678
/************************************************************************/
679
/*                             write()                                  */
680
/************************************************************************/
681

682
void MVTTileLayer::write(GByte *pabyData) const
1,527✔
683
{
684
    write(&pabyData);
1,527✔
685
}
1,522✔
686

687
/************************************************************************/
688
/*                             write()                                  */
689
/************************************************************************/
690

691
std::string MVTTileLayer::write() const
1,528✔
692
{
693
    std::string buffer;
1,528✔
694
    size_t nSize = getSize();
1,524✔
695
    buffer.resize(nSize);
1,529✔
696
    write(reinterpret_cast<GByte *>(&buffer[0]));
1,519✔
697
    return buffer;
1,520✔
698
}
699

700
/************************************************************************/
701
/*                             read()                                   */
702
/************************************************************************/
703

704
bool MVTTileLayer::read(const GByte **ppabyData, const GByte *pabyDataLimit)
1,700✔
705
{
706
    const GByte *pabyData = *ppabyData;
1,700✔
707

708
    try
709
    {
710
        unsigned int nKey = 0;
1,700✔
711
        while (pabyData < pabyDataLimit)
15,696✔
712
        {
713
            READ_FIELD_KEY(nKey);
13,996✔
714
            if (nKey == MAKE_KEY(knLAYER_NAME, WT_DATA))
13,996✔
715
            {
716
                char *pszLayerName = nullptr;
1,700✔
717
                READ_TEXT(pabyData, pabyDataLimit, pszLayerName);
1,700✔
718
                // cppcheck-suppress nullPointer
719
                setName(pszLayerName);
1,700✔
720
                CPLFree(pszLayerName);
1,700✔
721
            }
722
            else if (nKey == MAKE_KEY(knLAYER_FEATURES, WT_DATA))
12,296✔
723
            {
724
                unsigned int nFeatureLength = 0;
1,700✔
725
                READ_SIZE(pabyData, pabyDataLimit, nFeatureLength);
1,700✔
726
                const GByte *pabyDataFeatureEnd = pabyData + nFeatureLength;
1,700✔
727
                std::shared_ptr<MVTTileLayerFeature> poFeature(
728
                    new MVTTileLayerFeature());
1,700✔
729
                addFeature(poFeature);
1,700✔
730
                if (!poFeature->read(&pabyData, pabyDataFeatureEnd))
1,700✔
731
                    return false;
×
732
                pabyData = pabyDataFeatureEnd;
1,700✔
733
            }
734
            else if (nKey == MAKE_KEY(knLAYER_KEYS, WT_DATA))
10,596✔
735
            {
736
                char *pszKey = nullptr;
4,448✔
737
                READ_TEXT(pabyData, pabyDataLimit, pszKey);
4,448✔
738
                // cppcheck-suppress nullPointer
739
                addKey(pszKey);
4,448✔
740
                CPLFree(pszKey);
4,448✔
741
            }
742
            else if (nKey == MAKE_KEY(knLAYER_VALUES, WT_DATA))
6,148✔
743
            {
744
                unsigned int nValueLength = 0;
4,448✔
745
                READ_SIZE(pabyData, pabyDataLimit, nValueLength);
4,448✔
746
                const GByte *pabyDataValueEnd = pabyData + nValueLength;
4,448✔
747
                MVTTileLayerValue oValue;
4,448✔
748
                if (!oValue.read(&pabyData, pabyDataValueEnd))
4,448✔
749
                    return false;
×
750
                addValue(oValue);
4,448✔
751
                pabyData = pabyDataValueEnd;
4,448✔
752
            }
753
            else if (nKey == MAKE_KEY(knLAYER_EXTENT, WT_VARINT))
1,700✔
754
            {
755
                unsigned int nExtent = 0;
×
756
                READ_VARUINT32(pabyData, pabyDataLimit, nExtent);
×
757
                setExtent(nExtent);
×
758
            }
759
            else if (nKey == MAKE_KEY(knLAYER_VERSION, WT_VARINT))
1,700✔
760
            {
761
                unsigned int nVersion = 0;
1,700✔
762
                READ_VARUINT32(pabyData, pabyDataLimit, nVersion);
1,700✔
763
                setVersion(nVersion);
1,700✔
764
            }
765
            else
766
            {
767
                SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, FALSE);
×
768
            }
769
        }
770
        *ppabyData = pabyData;
1,700✔
771
        return true;
1,700✔
772
    }
773
    catch (const GPBException &)
×
774
    {
775
        return false;
×
776
    }
777
}
778

779
/************************************************************************/
780
/*                             read()                                   */
781
/************************************************************************/
782

783
bool MVTTileLayer::read(const GByte *pabyData, const GByte *pabyEnd)
1,700✔
784
{
785
    return read(&pabyData, pabyEnd);
1,700✔
786
}
787

788
/************************************************************************/
789
/*                             MVTTile()                                */
790
/************************************************************************/
791

792
MVTTile::MVTTile()
947✔
793
{
794
}
947✔
795

796
/************************************************************************/
797
/*                            addLayer()                                */
798
/************************************************************************/
799

800
void MVTTile::addLayer(std::shared_ptr<MVTTileLayer> poLayer)
1,413✔
801
{
802
    poLayer->setOwner(this);
1,413✔
803
    invalidateCachedSize();
1,413✔
804
    m_apoLayers.push_back(poLayer);
1,413✔
805
}
1,413✔
806

807
/************************************************************************/
808
/*                            getSize()                                 */
809
/************************************************************************/
810

811
size_t MVTTile::getSize() const
1,981✔
812
{
813
    if (m_bCachedSize)
1,981✔
814
        return m_nCachedSize;
997✔
815
    m_nCachedSize = 0;
984✔
816
    for (const auto &poLayer : m_apoLayers)
2,409✔
817
    {
818
        const size_t nLayerSize = poLayer->getSize();
1,425✔
819
        m_nCachedSize += knSIZE_KEY + GetVarUIntSize(nLayerSize) + nLayerSize;
1,425✔
820
    }
821
    m_bCachedSize = true;
984✔
822
    return m_nCachedSize;
984✔
823
}
824

825
/************************************************************************/
826
/*                             write()                                  */
827
/************************************************************************/
828

829
void MVTTile::write(GByte **ppabyData) const
972✔
830
{
831
    GByte *pabyData = *ppabyData;
972✔
832

833
    for (const auto &poLayer : m_apoLayers)
2,385✔
834
    {
835
        WriteVarUIntSingleByte(&pabyData, MAKE_KEY(knLAYER, WT_DATA));
1,413✔
836
        WriteVarUInt(&pabyData, poLayer->getSize());
1,413✔
837
        poLayer->write(&pabyData);
1,413✔
838
    }
839

840
    CPLAssert(pabyData == *ppabyData + getSize());
972✔
841
    *ppabyData = pabyData;
972✔
842
}
972✔
843

844
/************************************************************************/
845
/*                             write()                                  */
846
/************************************************************************/
847

848
void MVTTile::write(GByte *pabyData) const
972✔
849
{
850
    write(&pabyData);
972✔
851
}
972✔
852

853
/************************************************************************/
854
/*                             write()                                  */
855
/************************************************************************/
856

857
std::string MVTTile::write() const
972✔
858
{
859
    std::string buffer;
972✔
860
    size_t nSize = getSize();
972✔
861
    if (nSize)
972✔
862
    {
863
        buffer.resize(nSize);
972✔
864
        write(reinterpret_cast<GByte *>(&buffer[0]));
972✔
865
    }
866
    return buffer;
972✔
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
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc