Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/miramon/mm_rdlayr.c
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  C API to read a MiraMon layer
5
 * Author:   Abel Pau, a.pau@creaf.uab.cat, based on the MiraMon codes,
6
 *           mainly written by Xavier Pons, Joan Maso (correctly written
7
 *           "Mas0xF3"), Abel Pau, Nuria Julia (N0xFAria Juli0xE0),
8
 *           Xavier Calaf, Lluis (Llu0xEDs) Pesquer and Alaitz Zabala, from
9
 *           CREAF and Universitat Autonoma (Aut0xF2noma) de Barcelona.
10
 *           For a complete list of contributors:
11
 *           https://www.miramon.cat/eng/QuiSom.htm
12
 ******************************************************************************
13
 * Copyright (c) 2024, Xavier Pons
14
 *
15
 * SPDX-License-Identifier: MIT
16
 ****************************************************************************/
17
18
#include "ogr_api.h"  // For CPL_C_START
19
#include "mm_wrlayr.h"
20
#include "mm_wrlayr.h"  // For MMReadHeader()
21
#include "../../../frmts/miramon_common/mm_gdal_functions.h"
22
#include "../../../frmts/miramon_common/mm_gdal_constants.h"
23
#include "mm_rdlayr.h"
24
25
CPL_C_START  // Necessary for compiling in GDAL project
26
27
    /* -------------------------------------------------------------------- */
28
    /*      Reading MiraMon format file functions                           */
29
    /* -------------------------------------------------------------------- */
30
31
    // Initializes a MiraMon vector layer for reading
32
    int
33
    MMInitLayerToRead(struct MiraMonVectLayerInfo *hMiraMonLayer,
34
                      VSILFILE *m_fp, const char *pszFilename)
35
1.44k
{
36
1.44k
    char szResult[MM_MAX_ID_SNY + 10];
37
1.44k
    char *pszSRS;
38
39
1.44k
    memset(hMiraMonLayer, 0, sizeof(*hMiraMonLayer));
40
1.44k
    if (MMReadHeader(m_fp, &hMiraMonLayer->TopHeader))
41
2
    {
42
2
        CPLError(CE_Failure, CPLE_NoWriteAccess,
43
2
                 "Error reading header of file %s", pszFilename);
44
2
        return 1;
45
2
    }
46
1.43k
    hMiraMonLayer->ReadOrWrite = MM_READING_MODE;
47
1.43k
    strcpy(hMiraMonLayer->pszFlags, "rb");
48
49
1.43k
    hMiraMonLayer->pszSrcLayerName = CPLStrdup(pszFilename);
50
51
1.43k
    hMiraMonLayer->LayerVersion =
52
1.43k
        (char)MMGetVectorVersion(&hMiraMonLayer->TopHeader);
53
1.43k
    if (hMiraMonLayer->LayerVersion == MM_UNKNOWN_VERSION)
54
0
    {
55
0
        CPLError(CE_Failure, CPLE_NotSupported,
56
0
                 "MiraMon version file unknown.");
57
0
        return 1;
58
0
    }
59
1.43k
    if (hMiraMonLayer->LayerVersion == MM_LAST_VERSION)
60
0
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
61
1.43k
    else if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
62
791
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_32_BITS;
63
647
    else
64
647
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
65
66
1.43k
    if (hMiraMonLayer->TopHeader.aFileType[0] == 'P' &&
67
1.34k
        hMiraMonLayer->TopHeader.aFileType[1] == 'N' &&
68
194
        hMiraMonLayer->TopHeader.aFileType[2] == 'T')
69
194
    {
70
194
        if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
71
48
        {
72
48
            hMiraMonLayer->TopHeader.bIs3d = 1;
73
48
            hMiraMonLayer->eLT = MM_LayerType_Point3d;
74
48
        }
75
146
        else
76
146
            hMiraMonLayer->eLT = MM_LayerType_Point;
77
78
194
        hMiraMonLayer->bIsPoint = TRUE;
79
194
    }
80
1.24k
    else if (hMiraMonLayer->TopHeader.aFileType[0] == 'A' &&
81
89
             hMiraMonLayer->TopHeader.aFileType[1] == 'R' &&
82
89
             hMiraMonLayer->TopHeader.aFileType[2] == 'C')
83
89
    {
84
89
        if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
85
63
        {
86
63
            hMiraMonLayer->TopHeader.bIs3d = 1;
87
63
            hMiraMonLayer->eLT = MM_LayerType_Arc3d;
88
63
        }
89
26
        else
90
26
            hMiraMonLayer->eLT = MM_LayerType_Arc;
91
92
89
        hMiraMonLayer->bIsArc = TRUE;
93
89
    }
94
1.15k
    else if (hMiraMonLayer->TopHeader.aFileType[0] == 'P' &&
95
1.15k
             hMiraMonLayer->TopHeader.aFileType[1] == 'O' &&
96
1.15k
             hMiraMonLayer->TopHeader.aFileType[2] == 'L')
97
1.15k
    {
98
        // 3D
99
1.15k
        if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
100
470
        {
101
470
            hMiraMonLayer->TopHeader.bIs3d = 1;
102
470
            hMiraMonLayer->eLT = MM_LayerType_Pol3d;
103
470
        }
104
685
        else
105
685
            hMiraMonLayer->eLT = MM_LayerType_Pol;
106
107
1.15k
        hMiraMonLayer->bIsPolygon = TRUE;
108
109
1.15k
        if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_MULTIPOLYGON)
110
534
            hMiraMonLayer->TopHeader.bIsMultipolygon = 1;
111
1.15k
    }
112
113
    //hMiraMonLayer->Version = MM_VECTOR_LAYER_LAST_VERSION;
114
115
1.43k
    if (MMInitLayerByType(hMiraMonLayer))
116
1.13k
        return 1;
117
307
    hMiraMonLayer->bIsBeenInit = 1;
118
119
    // Get the basic metadata
120
307
    pszSRS = MMReturnValueFromSectionINIFile(
121
307
        hMiraMonLayer->pszMainREL_LayerName,
122
307
        "SPATIAL_REFERENCE_SYSTEM:HORIZONTAL", "HorizontalSystemIdentifier");
123
307
    if (pszSRS)
124
1
        hMiraMonLayer->pSRS = pszSRS;
125
306
    else
126
306
        hMiraMonLayer->pSRS = nullptr;
127
128
307
    if (!hMiraMonLayer->pSRS && hMiraMonLayer->bIsPolygon)
129
99
    {
130
99
        pszSRS = MMReturnValueFromSectionINIFile(
131
99
            hMiraMonLayer->MMPolygon.MMArc.pszREL_LayerName,
132
99
            "SPATIAL_REFERENCE_SYSTEM:HORIZONTAL",
133
99
            "HorizontalSystemIdentifier");
134
135
99
        hMiraMonLayer->pSRS = pszSRS;
136
99
    }
137
138
307
    if (!ReturnEPSGCodeSRSFromMMIDSRS(hMiraMonLayer->pSRS, szResult))
139
0
    {
140
0
        if (MMIsEmptyString(szResult))
141
0
            hMiraMonLayer->nSRS_EPSG = 0;
142
0
        else
143
0
            hMiraMonLayer->nSRS_EPSG = atoi(szResult);
144
0
    }
145
307
    else
146
307
        hMiraMonLayer->nSRS_EPSG = 0;
147
148
307
    if (hMiraMonLayer->nSRS_EPSG == 0)
149
307
    {
150
307
        if (hMiraMonLayer->pSRS && strcmp(hMiraMonLayer->pSRS, "plane"))
151
1
        {
152
1
            CPLError(CE_Warning, CPLE_NotSupported,
153
1
                     "The MiraMon layer SRS has no equivalent "
154
1
                     "in EPSG code");
155
1
        }
156
307
    }
157
158
    // If more nNumStringToOperate is needed, it'll be increased.
159
307
    hMiraMonLayer->nNumStringToOperate = 0;
160
307
    if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, 5000))
161
0
        return 1;
162
163
307
    return 0;
164
307
}
165
166
static void MM_AdoptHeight(double *desti, const double *proposta, uint32_t flag)
167
10.1M
{
168
10.1M
    if (*proposta == MM_NODATA_COORD_Z)
169
76
        return;
170
171
10.1M
    if (flag & MM_STRING_HIGHEST_ALTITUDE)
172
0
    {
173
0
        if (*desti == MM_NODATA_COORD_Z || *desti < *proposta)
174
0
            *desti = *proposta;
175
0
    }
176
10.1M
    else if (flag & MM_STRING_LOWEST_ALTITUDE)
177
0
    {
178
0
        if (*desti == MM_NODATA_COORD_Z || *desti > *proposta)
179
0
            *desti = *proposta;
180
0
    }
181
10.1M
    else
182
10.1M
    {
183
        // First coordinate of this vertice
184
10.1M
        if (*desti == MM_NODATA_COORD_Z)
185
205k
            *desti = *proposta;
186
10.1M
    }
187
10.1M
}
188
189
static int MM_GetArcHeights(double *coord_z, VSILFILE *pF,
190
                            MM_N_VERTICES_TYPE n_vrt,
191
                            struct MM_ZD *pZDescription, uint32_t flag)
192
29.2k
{
193
29.2k
    MM_N_HEIGHT_TYPE i;
194
29.2k
    MM_N_VERTICES_TYPE i_vrt;
195
29.2k
    double *pcoord_z;
196
29.2k
    MM_N_HEIGHT_TYPE n_alcada, n_h_total;
197
29.2k
    int tipus;
198
29.2k
    double *alcada = nullptr, *palcada, *palcada_i;
199
29.2k
#define MM_N_ALCADA_LOCAL 50  // Nr of local heights
200
29.2k
    double local_CinquantaAlcades[MM_N_ALCADA_LOCAL];
201
202
29.2k
    if (!pZDescription)
203
0
        return 0;
204
205
1.49M
    for (i_vrt = 0; i_vrt < n_vrt; i_vrt++)
206
1.46M
        coord_z[i_vrt] = MM_NODATA_COORD_Z;
207
208
29.2k
    if (pZDescription->nZCount == INT_MIN)
209
64
        return 0;
210
29.1k
    tipus = MM_ARC_HEIGHT_TYPE(pZDescription->nZCount);
211
29.1k
    n_alcada = MM_ARC_N_HEIGHTS(pZDescription->nZCount);
212
29.1k
    if (n_vrt == 0 || n_alcada == 0)
213
14.4k
        return 0;
214
215
14.6k
    if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
216
13.3k
    {
217
13.3k
        if (n_vrt > (unsigned)(INT_MAX / n_alcada))
218
297
        {
219
297
            CPLError(CE_Failure, CPLE_OutOfMemory, "Integer overflow");
220
297
            return 1;
221
297
        }
222
13.0k
        n_h_total = (MM_N_HEIGHT_TYPE)n_vrt * n_alcada;
223
13.0k
    }
224
1.34k
    else
225
1.34k
        n_h_total = n_alcada;
226
227
14.3k
    if (n_h_total <= MM_N_ALCADA_LOCAL)
228
11
        palcada = local_CinquantaAlcades;
229
14.3k
    else
230
14.3k
    {
231
14.3k
        if (MMCheckSize_t(n_h_total, sizeof(double)))
232
1.43k
            return 1;
233
12.9k
        if (nullptr ==
234
12.9k
            (palcada = alcada = VSICalloc((size_t)n_h_total, sizeof(double))))
235
0
            return 1;
236
12.9k
    }
237
238
12.9k
    if (VSIFSeekL(pF, pZDescription->nOffsetZ, SEEK_SET))
239
0
    {
240
0
        if (alcada)
241
0
            VSIFree(alcada);
242
0
        return 1;
243
0
    }
244
12.9k
    if (n_h_total !=
245
12.9k
        (MM_N_HEIGHT_TYPE)VSIFReadL(palcada, sizeof(double), n_h_total, pF))
246
44
    {
247
44
        if (alcada)
248
40
            VSIFree(alcada);
249
44
        return 1;
250
44
    }
251
252
12.9k
    if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
253
12.6k
    {
254
12.6k
        palcada_i = palcada;
255
811k
        for (i = 0; i < n_alcada; i++)
256
798k
        {
257
10.9M
            for (i_vrt = 0, pcoord_z = coord_z; i_vrt < n_vrt;
258
10.1M
                 i_vrt++, pcoord_z++, palcada_i++)
259
10.1M
                MM_AdoptHeight(pcoord_z, palcada_i, flag);
260
798k
        }
261
12.6k
    }
262
280
    else
263
280
    {
264
280
        palcada_i = palcada;
265
280
        pcoord_z = coord_z;
266
45.9k
        for (i = 0; i < n_alcada; i++, palcada_i++)
267
45.7k
            MM_AdoptHeight(pcoord_z, palcada_i, flag);
268
269
280
        if (*pcoord_z != MM_NODATA_COORD_Z)
270
280
        {
271
            /*Copio el mateix valor a totes les alcades.*/
272
40.4k
            for (i_vrt = 1, pcoord_z++; i_vrt < (size_t)n_vrt;
273
40.1k
                 i_vrt++, pcoord_z++)
274
40.1k
                *pcoord_z = *coord_z;
275
280
        }
276
280
    }
277
12.9k
    if (alcada)
278
12.9k
        VSIFree(alcada);
279
12.9k
    return 0;
280
12.9k
}  // End of MM_GetArcHeights()
281
282
// Reads stringline coordinates and puts them in a buffer
283
static int
284
MMAddStringLineCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer,
285
                           MM_INTERNAL_FID i_elem, uint32_t flag_z,
286
                           MM_N_VERTICES_TYPE nStartVertice,
287
                           MM_BOOLEAN bAvoidFirst, unsigned char VFG)
288
55.5k
{
289
55.5k
    VSILFILE *pF;
290
55.5k
    struct MM_AH *pArcHeader;
291
55.5k
    struct MiraMonArcLayer *pMMArc;
292
55.5k
    struct MM_ZD *pZDescription = nullptr;
293
294
55.5k
    if (hMiraMonLayer->bIsPolygon)
295
54.3k
        pMMArc = &hMiraMonLayer->MMPolygon.MMArc;
296
1.14k
    else
297
1.14k
        pMMArc = &hMiraMonLayer->MMArc;
298
299
55.5k
    pF = pMMArc->pF;
300
55.5k
    pArcHeader = pMMArc->pArcHeader;
301
55.5k
    if (hMiraMonLayer->TopHeader.bIs3d)
302
29.2k
        pZDescription = pMMArc->pZSection.pZDescription;
303
304
55.5k
    VSIFSeekL(pF, pArcHeader[i_elem].nOffset, SEEK_SET);
305
306
55.5k
    if (hMiraMonLayer->bIsPolygon && (VFG & MM_POL_REVERSE_ARC))  // &&
307
        //nStartVertice > 0)
308
839
    {
309
839
        MM_N_VERTICES_TYPE nIVertice;
310
311
        // Reading arcs vertices in an inverse order
312
839
        if (MMResizeMM_POINT2DPointer(
313
839
                &hMiraMonLayer->ReadFeature.pCoord,
314
839
                &hMiraMonLayer->ReadFeature.nMaxpCoord,
315
839
                nStartVertice + pArcHeader[i_elem].nElemCount *
316
839
                                    2,  // ask for twice memory to reverse
317
839
                0, 0))
318
0
            return 1;
319
320
        // Get the vertices far away from their place to be inverted later
321
839
        if (pArcHeader[i_elem].nElemCount !=
322
839
            VSIFReadL(hMiraMonLayer->ReadFeature.pCoord + nStartVertice +
323
839
                          pArcHeader[i_elem].nElemCount,
324
839
                      sizeof(*hMiraMonLayer->ReadFeature.pCoord),
325
839
                      (size_t)pArcHeader[i_elem].nElemCount, pF))
326
2
        {
327
2
            return 1;
328
2
        }
329
330
837
        if (hMiraMonLayer->TopHeader.bIs3d)
331
511
        {
332
511
            if (MMResizeDoublePointer(
333
511
                    &hMiraMonLayer->ReadFeature.pZCoord,
334
511
                    &hMiraMonLayer->ReadFeature.nMaxpZCoord,
335
511
                    nStartVertice + pArcHeader[i_elem].nElemCount * 2, 0, 0))
336
0
                return 1;
337
338
            // +nStartVertice
339
511
            MM_GetArcHeights(hMiraMonLayer->ReadFeature.pZCoord +
340
511
                                 nStartVertice + pArcHeader[i_elem].nElemCount,
341
511
                             pF, pArcHeader[i_elem].nElemCount,
342
511
                             pZDescription + i_elem, flag_z);
343
344
            // If there is a value for Z-nodata in GDAL this lines can be uncommented
345
            // and MM_GDAL_NODATA_COORD_Z can be defined
346
            /*if(!DOUBLES_DIFERENTS_DJ(punts_z[k], MM_NODATA_COORD_Z))
347
            {
348
                MM_N_VERTICES_TYPE nIVertice;
349
                for(nIVertice=0; nIVertice<pArcHeader[i_elem].nElemCount; nIVertice++)
350
                    hMiraMonLayer->ReadFeature.pZCoord[nIVertice]=MM_GDAL_NODATA_COORD_Z;
351
            }
352
            */
353
511
        }
354
355
        // Reverse the vertices while putting on their place
356
85.4k
        for (nIVertice = 0; nIVertice < pArcHeader[i_elem].nElemCount;
357
84.6k
             nIVertice++)
358
84.6k
        {
359
84.6k
            memcpy(hMiraMonLayer->ReadFeature.pCoord + nStartVertice -
360
84.6k
                       ((nStartVertice > 0 && bAvoidFirst) ? 1 : 0) + nIVertice,
361
84.6k
                   hMiraMonLayer->ReadFeature.pCoord + nStartVertice +
362
84.6k
                       2 * pArcHeader[i_elem].nElemCount - nIVertice - 1,
363
84.6k
                   sizeof(*hMiraMonLayer->ReadFeature.pCoord));
364
365
84.6k
            if (hMiraMonLayer->TopHeader.bIs3d)
366
60.5k
            {
367
60.5k
                memcpy(hMiraMonLayer->ReadFeature.pZCoord + nStartVertice -
368
60.5k
                           ((nStartVertice > 0 && bAvoidFirst) ? 1 : 0) +
369
60.5k
                           nIVertice,
370
60.5k
                       hMiraMonLayer->ReadFeature.pZCoord + nStartVertice +
371
60.5k
                           2 * pArcHeader[i_elem].nElemCount - nIVertice - 1,
372
60.5k
                       sizeof(*hMiraMonLayer->ReadFeature.pZCoord));
373
60.5k
            }
374
84.6k
        }
375
837
    }
376
54.6k
    else
377
54.6k
    {
378
        // Reading arcs vertices
379
54.6k
        if (MMResizeMM_POINT2DPointer(
380
54.6k
                &hMiraMonLayer->ReadFeature.pCoord,
381
54.6k
                &hMiraMonLayer->ReadFeature.nMaxpCoord,
382
54.6k
                nStartVertice + pArcHeader[i_elem].nElemCount, 0, 0))
383
19
            return 1;
384
385
54.6k
        if (pArcHeader[i_elem].nElemCount !=
386
54.6k
            VSIFReadL(hMiraMonLayer->ReadFeature.pCoord + nStartVertice -
387
54.6k
                          (bAvoidFirst ? 1 : 0),
388
54.6k
                      sizeof(*hMiraMonLayer->ReadFeature.pCoord),
389
54.6k
                      (size_t)pArcHeader[i_elem].nElemCount, pF))
390
14
        {
391
14
            return 1;
392
14
        }
393
394
54.6k
        if (hMiraMonLayer->TopHeader.bIs3d)
395
28.7k
        {
396
28.7k
            if (MMResizeDoublePointer(
397
28.7k
                    &hMiraMonLayer->ReadFeature.pZCoord,
398
28.7k
                    &hMiraMonLayer->ReadFeature.nMaxpZCoord,
399
28.7k
                    nStartVertice + pArcHeader[i_elem].nElemCount, 0, 0))
400
0
                return 1;
401
402
            // +nStartVertice
403
28.7k
            MM_GetArcHeights(hMiraMonLayer->ReadFeature.pZCoord +
404
28.7k
                                 nStartVertice - (bAvoidFirst ? 1 : 0),
405
28.7k
                             pF, pArcHeader[i_elem].nElemCount,
406
28.7k
                             pZDescription + i_elem, flag_z);
407
408
            // If there is a value for Z-nodata in GDAL this lines can be uncommented
409
            // and MM_GDAL_NODATA_COORD_Z can be defined
410
            /*if(!DOUBLES_DIFERENTS_DJ(punts_z[k], MM_NODATA_COORD_Z))
411
            {
412
                MM_N_VERTICES_TYPE nIVertice;
413
                for(nIVertice=0; nIVertice<pArcHeader[i_elem].nElemCount; nIVertice++)
414
                    hMiraMonLayer->ReadFeature.pZCoord[nIVertice]=MM_GDAL_NODATA_COORD_Z;
415
            }
416
            */
417
28.7k
        }
418
54.6k
    }
419
55.4k
    hMiraMonLayer->ReadFeature.nNumpCoord =
420
55.4k
        pArcHeader[i_elem].nElemCount == 0
421
55.4k
            ? 0
422
55.4k
            : pArcHeader[i_elem].nElemCount - (bAvoidFirst ? 1 : 0);
423
424
55.4k
    return 0;
425
55.5k
}
426
427
// Reads Polygon coordinates and puts them in a buffer
428
static int
429
MMGetMultiPolygonCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer,
430
                             MM_INTERNAL_FID i_pol, uint32_t flag_z)
431
131
{
432
131
    struct MM_PH *pPolHeader;
433
131
    struct MM_AH *pArcHeader;
434
131
    char *pBuffer;
435
131
    MM_POLYGON_ARCS_COUNT nIndex;
436
131
    MM_BOOLEAN bAvoidFirst;
437
131
    MM_N_VERTICES_TYPE nNAcumulVertices = 0;
438
439
    // Checking if the index of the polygon is in the correct range.
440
131
    if (i_pol >= hMiraMonLayer->TopHeader.nElemCount)
441
0
        return 1;
442
443
131
    MMResetFeatureGeometry(&hMiraMonLayer->ReadFeature);
444
131
    MMResetFeatureRecord(&hMiraMonLayer->ReadFeature);
445
131
    pPolHeader = hMiraMonLayer->MMPolygon.pPolHeader + i_pol;
446
447
    // It's accepted not having arcs in the universal polygon
448
131
    if (!pPolHeader->nArcsCount)
449
0
    {
450
0
        if (i_pol == 0)
451
0
            return 0;
452
0
        else
453
0
            return 1;
454
0
    }
455
456
131
    if (MMResizeMiraMonPolygonArcs(&hMiraMonLayer->pArcs,
457
131
                                   &hMiraMonLayer->nMaxArcs,
458
131
                                   pPolHeader->nArcsCount, 0, 0))
459
33
        return 1;
460
461
98
    if (MMInitFlush(&hMiraMonLayer->FlushPAL, hMiraMonLayer->MMPolygon.pF,
462
98
                    hMiraMonLayer->MMPolygon.nPALElementSize *
463
98
                        pPolHeader->nArcsCount,
464
98
                    &pBuffer, pPolHeader->nOffset, 0))
465
0
    {
466
0
        if (pBuffer)
467
0
            VSIFree(pBuffer);
468
0
        return 1;
469
0
    }
470
471
98
    hMiraMonLayer->FlushPAL.pBlockWhereToSaveOrRead = (void *)pBuffer;
472
98
    if (MMReadFlush(&hMiraMonLayer->FlushPAL))
473
14
    {
474
14
        if (pBuffer)
475
14
            VSIFree(pBuffer);
476
14
        return 1;
477
14
    }
478
479
84
    hMiraMonLayer->ReadFeature.nNRings = 0;
480
84
    hMiraMonLayer->ReadFeature.nNumpCoord = 0;
481
84
    if (MMResize_MM_N_VERTICES_TYPE_Pointer(
482
84
            &hMiraMonLayer->ReadFeature.pNCoordRing,
483
84
            &hMiraMonLayer->ReadFeature.nMaxpNCoordRing,
484
84
            (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10, 10))
485
0
    {
486
0
        VSIFree(pBuffer);
487
0
        return 1;
488
0
    }
489
490
84
    if (MMResizeVFGPointer(&hMiraMonLayer->ReadFeature.flag_VFG,
491
84
                           &hMiraMonLayer->ReadFeature.nMaxVFG,
492
84
                           (MM_INTERNAL_FID)pPolHeader->nArcsCount, 0,
493
84
                           0))  // Perhaps more memory than needed
494
0
    {
495
0
        VSIFree(pBuffer);
496
0
        return 1;
497
0
    }
498
499
    // Preparing memory for all coordinates
500
84
    hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] =
501
84
        0;
502
67.5k
    for (nIndex = 0; nIndex < pPolHeader->nArcsCount; nIndex++)
503
67.5k
    {
504
67.5k
        hMiraMonLayer->FlushPAL.SizeOfBlockToBeSaved =
505
67.5k
            sizeof((hMiraMonLayer->pArcs + nIndex)->VFG);
506
67.5k
        hMiraMonLayer->FlushPAL.pBlockToBeSaved =
507
67.5k
            (void *)&(hMiraMonLayer->pArcs + nIndex)->VFG;
508
67.5k
        if (MMReadBlockFromBuffer(&hMiraMonLayer->FlushPAL))
509
0
        {
510
0
            if (pBuffer)
511
0
                VSIFree(pBuffer);
512
0
            return 1;
513
0
        }
514
515
        // Arc index
516
67.5k
        if (MMReadGUInt64DependingOnVersion(
517
67.5k
                hMiraMonLayer, &hMiraMonLayer->FlushPAL,
518
67.5k
                &((hMiraMonLayer->pArcs + nIndex)->nIArc)))
519
0
        {
520
0
            if (pBuffer)
521
0
                VSIFree(pBuffer);
522
0
            return 1;
523
0
        }
524
525
67.5k
        if (hMiraMonLayer->MMPolygon.MMArc.pArcHeader == nullptr)
526
1
        {
527
1
            if (pBuffer)
528
1
                VSIFree(pBuffer);
529
1
            return 1;
530
1
        }
531
532
        // Checking if the index of the arc is in the correct range.
533
67.5k
        if ((hMiraMonLayer->pArcs + nIndex)->nIArc >=
534
67.5k
            hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount)
535
34
        {
536
34
            VSIFree(pBuffer);
537
34
            return 1;
538
34
        }
539
540
67.5k
        pArcHeader = hMiraMonLayer->MMPolygon.MMArc.pArcHeader +
541
67.5k
                     (hMiraMonLayer->pArcs + nIndex)->nIArc;
542
543
67.5k
        if (hMiraMonLayer->ReadFeature
544
67.5k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
545
67.5k
            UINT64_MAX - pArcHeader->nElemCount)
546
1
        {
547
1
            VSIFree(pBuffer);
548
1
            return 1;
549
1
        }
550
551
67.5k
        if (hMiraMonLayer->ReadFeature
552
67.5k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
553
67.5k
            UINT64_MAX - pArcHeader->nElemCount)
554
0
        {
555
0
            VSIFree(pBuffer);
556
0
            return 1;
557
0
        }
558
559
67.5k
        hMiraMonLayer->ReadFeature
560
67.5k
            .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] +=
561
67.5k
            pArcHeader->nElemCount;
562
67.5k
    }
563
48
    if (MMResizeMM_POINT2DPointer(
564
48
            &hMiraMonLayer->ReadFeature.pCoord,
565
48
            &hMiraMonLayer->ReadFeature.nMaxpCoord,
566
48
            hMiraMonLayer->ReadFeature
567
48
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings],
568
48
            0, 0))
569
4
    {
570
4
        VSIFree(pBuffer);
571
4
        return 1;
572
4
    }
573
574
44
    hMiraMonLayer->FlushPAL.CurrentOffset = 0;
575
576
    // Real work
577
44
    hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] =
578
44
        0;
579
54.4k
    for (nIndex = 0; nIndex < pPolHeader->nArcsCount; nIndex++)
580
54.3k
    {
581
54.3k
        hMiraMonLayer->FlushPAL.SizeOfBlockToBeSaved =
582
54.3k
            sizeof((hMiraMonLayer->pArcs + nIndex)->VFG);
583
54.3k
        hMiraMonLayer->FlushPAL.pBlockToBeSaved =
584
54.3k
            (void *)&(hMiraMonLayer->pArcs + nIndex)->VFG;
585
54.3k
        if (MMReadBlockFromBuffer(&hMiraMonLayer->FlushPAL))
586
0
        {
587
0
            if (pBuffer)
588
0
                VSIFree(pBuffer);
589
0
            return 1;
590
0
        }
591
592
        // Arc index
593
54.3k
        if (MMReadGUInt64DependingOnVersion(
594
54.3k
                hMiraMonLayer, &hMiraMonLayer->FlushPAL,
595
54.3k
                &((hMiraMonLayer->pArcs + nIndex)->nIArc)))
596
0
        {
597
0
            if (pBuffer)
598
0
                VSIFree(pBuffer);
599
0
            return 1;
600
0
        }
601
602
54.3k
        bAvoidFirst = FALSE;
603
54.3k
        if (hMiraMonLayer->ReadFeature
604
54.3k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] != 0)
605
39.2k
            bAvoidFirst = TRUE;
606
607
        // Add coordinates to hMiraMonLayer->ReadFeature.pCoord
608
54.3k
        if (MMAddStringLineCoordinates(hMiraMonLayer,
609
54.3k
                                       (hMiraMonLayer->pArcs + nIndex)->nIArc,
610
54.3k
                                       flag_z, nNAcumulVertices, bAvoidFirst,
611
54.3k
                                       (hMiraMonLayer->pArcs + nIndex)->VFG))
612
5
        {
613
5
            VSIFree(pBuffer);
614
5
            return 1;
615
5
        }
616
617
54.3k
        if (MMResize_MM_N_VERTICES_TYPE_Pointer(
618
54.3k
                &hMiraMonLayer->ReadFeature.pNCoordRing,
619
54.3k
                &hMiraMonLayer->ReadFeature.nMaxpNCoordRing,
620
54.3k
                (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10,
621
54.3k
                10))
622
0
        {
623
0
            VSIFree(pBuffer);
624
0
            return 1;
625
0
        }
626
627
54.3k
        if (hMiraMonLayer->ReadFeature
628
54.3k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
629
54.3k
            UINT64_MAX - hMiraMonLayer->ReadFeature.nNumpCoord)
630
0
        {
631
0
            VSIFree(pBuffer);
632
0
            return 1;
633
0
        }
634
635
54.3k
        hMiraMonLayer->ReadFeature
636
54.3k
            .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] +=
637
54.3k
            hMiraMonLayer->ReadFeature.nNumpCoord;
638
54.3k
        nNAcumulVertices += hMiraMonLayer->ReadFeature.nNumpCoord;
639
640
54.3k
        if ((hMiraMonLayer->pArcs + nIndex)->VFG & MM_POL_END_RING)
641
2.02k
        {
642
2.02k
            hMiraMonLayer->ReadFeature
643
2.02k
                .flag_VFG[hMiraMonLayer->ReadFeature.nNRings] =
644
2.02k
                (hMiraMonLayer->pArcs + nIndex)->VFG;
645
2.02k
            hMiraMonLayer->ReadFeature.nNRings++;
646
2.02k
            hMiraMonLayer->ReadFeature
647
2.02k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] = 0;
648
2.02k
        }
649
54.3k
    }
650
39
    hMiraMonLayer->nNumArcs = pPolHeader->nArcsCount;
651
39
    if (pBuffer)
652
39
        VSIFree(pBuffer);
653
654
39
    return 0;
655
44
}
656
657
// Reads the geographical part of a MiraMon layer feature
658
int MMGetGeoFeatureFromVector(struct MiraMonVectLayerInfo *hMiraMonLayer,
659
                              MM_INTERNAL_FID i_elem)
660
8.09k
{
661
8.09k
    VSILFILE *pF;
662
8.09k
    struct MM_ZD *pZDescription;
663
8.09k
    uint32_t flag_z;
664
8.09k
    int num;
665
8.09k
    double cz;
666
667
8.09k
    if (hMiraMonLayer->nSelectCoordz == MM_SELECT_HIGHEST_COORDZ)
668
0
        flag_z = MM_STRING_HIGHEST_ALTITUDE;
669
8.09k
    else if (hMiraMonLayer->nSelectCoordz == MM_SELECT_LOWEST_COORDZ)
670
0
        flag_z = MM_STRING_LOWEST_ALTITUDE;
671
8.09k
    else
672
8.09k
        flag_z = 0L;
673
674
8.09k
    if (hMiraMonLayer->bIsPoint)
675
6.81k
    {
676
6.81k
        pF = hMiraMonLayer->MMPoint.pF;
677
678
        // Getting to the i-th element offset
679
6.81k
        VSIFSeekL(pF,
680
6.81k
                  hMiraMonLayer->nHeaderDiskSize +
681
6.81k
                      sizeof(MM_COORD_TYPE) * 2 * i_elem,
682
6.81k
                  SEEK_SET);
683
684
        // Reading the point
685
6.81k
        if (MMResizeMM_POINT2DPointer(&hMiraMonLayer->ReadFeature.pCoord,
686
6.81k
                                      &hMiraMonLayer->ReadFeature.nMaxpCoord,
687
6.81k
                                      hMiraMonLayer->ReadFeature.nNumpCoord, 1,
688
6.81k
                                      1))
689
0
            return 1;
690
691
6.81k
        if (1 != VSIFReadL(hMiraMonLayer->ReadFeature.pCoord,
692
6.81k
                           sizeof(MM_COORD_TYPE) * 2, 1, pF))
693
121
        {
694
121
            return 1;
695
121
        }
696
697
6.69k
        hMiraMonLayer->ReadFeature.nNRings = 1;
698
699
6.69k
        if (MMResize_MM_N_VERTICES_TYPE_Pointer(
700
6.69k
                &hMiraMonLayer->ReadFeature.pNCoordRing,
701
6.69k
                &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, 1, 0, 1))
702
0
            return 1;
703
704
6.69k
        hMiraMonLayer->ReadFeature.pNCoordRing[0] = 1;
705
706
6.69k
        if (hMiraMonLayer->TopHeader.bIs3d)
707
1.23k
        {
708
1.23k
            pZDescription =
709
1.23k
                hMiraMonLayer->MMPoint.pZSection.pZDescription + i_elem;
710
1.23k
            if (pZDescription->nZCount == INT_MIN)
711
1
                return 1;
712
1.23k
            num = MM_ARC_TOTAL_N_HEIGHTS_DISK(pZDescription->nZCount, 1);
713
714
1.23k
            if (MMResizeDoublePointer(&hMiraMonLayer->ReadFeature.pZCoord,
715
1.23k
                                      &hMiraMonLayer->ReadFeature.nMaxpZCoord,
716
1.23k
                                      1, 1, 1))
717
0
                return 1;
718
719
1.23k
            if (num == 0)
720
597
                hMiraMonLayer->ReadFeature.pZCoord[0] = MM_NODATA_COORD_Z;
721
637
            else
722
637
            {
723
637
                if (flag_z == MM_STRING_HIGHEST_ALTITUDE)  // Max z
724
0
                    cz = pZDescription->dfBBmaxz;
725
637
                else if (flag_z == MM_STRING_LOWEST_ALTITUDE)  // Min z
726
0
                    cz = pZDescription->dfBBminz;
727
637
                else
728
637
                {
729
                    // Reading the first z coordinate
730
637
                    VSIFSeekL(pF, pZDescription->nOffsetZ, SEEK_SET);
731
637
                    if ((size_t)1 !=
732
637
                        VSIFReadL(&cz,
733
637
                                  sizeof(*hMiraMonLayer->ReadFeature.pZCoord),
734
637
                                  1, pF))
735
29
                    {
736
29
                        return 1;
737
29
                    }
738
637
                }
739
                // If there is a value for Z-nodata in GDAL this lines can be uncommented
740
                // and MM_GDAL_NODATA_COORD_Z can be defined
741
                /*if(!DOUBLES_DIFERENTS_DJ(cz, MM_NODATA_COORD_Z))
742
                    hMiraMonLayer->ReadFeature.pZCoord[0]=MM_GDAL_NODATA_COORD_Z;
743
                else */
744
608
                hMiraMonLayer->ReadFeature.pZCoord[0] = cz;
745
608
            }
746
1.23k
        }
747
748
6.66k
        return 0;
749
6.69k
    }
750
751
    // Stringlines
752
1.27k
    if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
753
1.14k
    {
754
1.14k
        if (MMAddStringLineCoordinates(hMiraMonLayer, i_elem, flag_z, 0, FALSE,
755
1.14k
                                       0))
756
30
            return 1;
757
758
1.11k
        if (MMResize_MM_N_VERTICES_TYPE_Pointer(
759
1.11k
                &hMiraMonLayer->ReadFeature.pNCoordRing,
760
1.11k
                &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, 1, 0, 1))
761
0
            return 1;
762
763
1.11k
        hMiraMonLayer->ReadFeature.pNCoordRing[0] =
764
1.11k
            hMiraMonLayer->ReadFeature.nNumpCoord;
765
766
1.11k
        return 0;
767
1.11k
    }
768
769
    // Polygons or multipolygons
770
131
    if (MMGetMultiPolygonCoordinates(hMiraMonLayer, i_elem, flag_z))
771
92
        return 1;
772
773
39
    return 0;
774
131
}
775
776
// Reads the header of a MiraMon DBF
777
// Please read the format at this link:
778
// https://www.miramon.cat/new_note/usa/notes/DBF_estesa.pdf
779
int MM_ReadExtendedDBFHeader(struct MiraMonVectLayerInfo *hMiraMonLayer)
780
1.47k
{
781
1.47k
    const char *pszRelFile = nullptr;
782
1.47k
    struct MM_DATA_BASE_XP *pMMBDXP;
783
1.47k
    const char *szDBFFileName = nullptr;
784
785
    // If read don't read again. It happens when Polygon reads
786
    // the database and then in initArc() it's read again.
787
1.47k
    if (hMiraMonLayer->pMMBDXP)
788
99
        return 0;
789
790
1.37k
    pMMBDXP = hMiraMonLayer->pMMBDXP = VSICalloc(1, sizeof(*pMMBDXP));
791
1.37k
    if (!pMMBDXP)
792
0
        return 1;
793
794
1.37k
    if (hMiraMonLayer->bIsPoint)
795
178
    {
796
178
        hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP = pMMBDXP;
797
178
        szDBFFileName = hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName;
798
178
        pszRelFile = hMiraMonLayer->MMPoint.pszREL_LayerName;
799
178
    }
800
1.19k
    else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
801
55
    {
802
55
        hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP = pMMBDXP;
803
55
        szDBFFileName = hMiraMonLayer->MMArc.MMAdmDB.pszExtDBFLayerName;
804
55
        pszRelFile = hMiraMonLayer->MMArc.pszREL_LayerName;
805
55
    }
806
1.14k
    else if (hMiraMonLayer->bIsPolygon)
807
1.14k
    {
808
1.14k
        hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP = pMMBDXP;
809
1.14k
        szDBFFileName = hMiraMonLayer->MMPolygon.MMAdmDB.pszExtDBFLayerName;
810
1.14k
        pszRelFile = hMiraMonLayer->MMPolygon.pszREL_LayerName;
811
1.14k
    }
812
813
1.37k
    if (MM_ReadExtendedDBFHeaderFromFile(szDBFFileName, pMMBDXP, pszRelFile))
814
37
    {
815
37
        CPLError(CE_Failure, CPLE_NotSupported,
816
37
                 "Error reading the format in the DBF file %s.", szDBFFileName);
817
37
        return 1;
818
37
    }
819
820
1.33k
    fclose_and_nullify(&pMMBDXP->pfDataBase);
821
1.33k
    return 0;
822
1.37k
}
823
824
CPL_C_END  // Necessary for compiling in GDAL project