Coverage Report

Created: 2025-12-31 08:30

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
3.30k
{
36
3.30k
    char szResult[MM_MAX_ID_SNY + 10];
37
3.30k
    char *pszSRS;
38
39
3.30k
    memset(hMiraMonLayer, 0, sizeof(*hMiraMonLayer));
40
3.30k
    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
3.30k
    hMiraMonLayer->ReadOrWrite = MM_READING_MODE;
47
3.30k
    strcpy(hMiraMonLayer->pszFlags, "rb");
48
49
3.30k
    hMiraMonLayer->pszSrcLayerName = CPLStrdup(pszFilename);
50
51
3.30k
    hMiraMonLayer->LayerVersion =
52
3.30k
        (char)MMGetVectorVersion(&hMiraMonLayer->TopHeader);
53
3.30k
    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
3.30k
    if (hMiraMonLayer->LayerVersion == MM_LAST_VERSION)
60
0
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
61
3.30k
    else if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
62
1.99k
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_32_BITS;
63
1.31k
    else
64
1.31k
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
65
66
3.30k
    if (hMiraMonLayer->TopHeader.aFileType[0] == 'P' &&
67
3.02k
        hMiraMonLayer->TopHeader.aFileType[1] == 'N' &&
68
339
        hMiraMonLayer->TopHeader.aFileType[2] == 'T')
69
339
    {
70
339
        if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
71
88
        {
72
88
            hMiraMonLayer->TopHeader.bIs3d = 1;
73
88
            hMiraMonLayer->eLT = MM_LayerType_Point3d;
74
88
        }
75
251
        else
76
251
            hMiraMonLayer->eLT = MM_LayerType_Point;
77
78
339
        hMiraMonLayer->bIsPoint = TRUE;
79
339
    }
80
2.96k
    else if (hMiraMonLayer->TopHeader.aFileType[0] == 'A' &&
81
277
             hMiraMonLayer->TopHeader.aFileType[1] == 'R' &&
82
277
             hMiraMonLayer->TopHeader.aFileType[2] == 'C')
83
277
    {
84
277
        if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
85
132
        {
86
132
            hMiraMonLayer->TopHeader.bIs3d = 1;
87
132
            hMiraMonLayer->eLT = MM_LayerType_Arc3d;
88
132
        }
89
145
        else
90
145
            hMiraMonLayer->eLT = MM_LayerType_Arc;
91
92
277
        hMiraMonLayer->bIsArc = TRUE;
93
277
    }
94
2.68k
    else if (hMiraMonLayer->TopHeader.aFileType[0] == 'P' &&
95
2.68k
             hMiraMonLayer->TopHeader.aFileType[1] == 'O' &&
96
2.68k
             hMiraMonLayer->TopHeader.aFileType[2] == 'L')
97
2.68k
    {
98
        // 3D
99
2.68k
        if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_3D_INFO)
100
1.22k
        {
101
1.22k
            hMiraMonLayer->TopHeader.bIs3d = 1;
102
1.22k
            hMiraMonLayer->eLT = MM_LayerType_Pol3d;
103
1.22k
        }
104
1.46k
        else
105
1.46k
            hMiraMonLayer->eLT = MM_LayerType_Pol;
106
107
2.68k
        hMiraMonLayer->bIsPolygon = TRUE;
108
109
2.68k
        if (hMiraMonLayer->TopHeader.Flag & MM_LAYER_MULTIPOLYGON)
110
1.43k
            hMiraMonLayer->TopHeader.bIsMultipolygon = 1;
111
2.68k
    }
112
113
    //hMiraMonLayer->Version = MM_VECTOR_LAYER_LAST_VERSION;
114
115
3.30k
    if (MMInitLayerByType(hMiraMonLayer))
116
2.58k
        return 1;
117
715
    hMiraMonLayer->bIsBeenInit = 1;
118
119
    // Get the basic metadata
120
715
    pszSRS = MMReturnValueFromSectionINIFile(
121
715
        hMiraMonLayer->pszMainREL_LayerName,
122
715
        "SPATIAL_REFERENCE_SYSTEM:HORIZONTAL", "HorizontalSystemIdentifier");
123
715
    if (pszSRS)
124
7
        hMiraMonLayer->pSRS = pszSRS;
125
708
    else
126
708
        hMiraMonLayer->pSRS = nullptr;
127
128
715
    if (!hMiraMonLayer->pSRS && hMiraMonLayer->bIsPolygon)
129
267
    {
130
267
        pszSRS = MMReturnValueFromSectionINIFile(
131
267
            hMiraMonLayer->MMPolygon.MMArc.pszREL_LayerName,
132
267
            "SPATIAL_REFERENCE_SYSTEM:HORIZONTAL",
133
267
            "HorizontalSystemIdentifier");
134
135
267
        hMiraMonLayer->pSRS = pszSRS;
136
267
    }
137
138
715
    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
715
    else
146
715
        hMiraMonLayer->nSRS_EPSG = 0;
147
148
715
    if (hMiraMonLayer->nSRS_EPSG == 0)
149
715
    {
150
715
        if (hMiraMonLayer->pSRS && strcmp(hMiraMonLayer->pSRS, "plane"))
151
10
        {
152
10
            CPLError(CE_Warning, CPLE_NotSupported,
153
10
                     "The MiraMon layer SRS has no equivalent "
154
10
                     "in EPSG code");
155
10
        }
156
715
    }
157
158
    // If more nNumStringToOperate is needed, it'll be increased.
159
715
    hMiraMonLayer->nNumStringToOperate = 0;
160
715
    if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, 5000))
161
0
        return 1;
162
163
715
    return 0;
164
715
}
165
166
static void MM_AdoptHeight(double *desti, const double *proposta, uint32_t flag)
167
517k
{
168
517k
    if (*proposta == MM_NODATA_COORD_Z)
169
853
        return;
170
171
516k
    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
516k
    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
516k
    else
182
516k
    {
183
        // First coordinate of this vertice
184
516k
        if (*desti == MM_NODATA_COORD_Z)
185
124k
            *desti = *proposta;
186
516k
    }
187
516k
}
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
32.1k
{
193
32.1k
    MM_N_HEIGHT_TYPE i;
194
32.1k
    MM_N_VERTICES_TYPE i_vrt;
195
32.1k
    double *pcoord_z;
196
32.1k
    MM_N_HEIGHT_TYPE n_alcada, n_h_total;
197
32.1k
    int tipus;
198
32.1k
    double *alcada = nullptr, *palcada, *palcada_i;
199
32.1k
#define MM_N_ALCADA_LOCAL 50  // Nr of local heights
200
32.1k
    double local_CinquantaAlcades[MM_N_ALCADA_LOCAL];
201
202
32.1k
    if (!pZDescription)
203
0
        return 0;
204
205
3.02M
    for (i_vrt = 0; i_vrt < n_vrt; i_vrt++)
206
2.99M
        coord_z[i_vrt] = MM_NODATA_COORD_Z;
207
208
32.1k
    if (pZDescription->nZCount == INT_MIN)
209
171
        return 0;
210
31.9k
    tipus = MM_ARC_HEIGHT_TYPE(pZDescription->nZCount);
211
31.9k
    n_alcada = MM_ARC_N_HEIGHTS(pZDescription->nZCount);
212
31.9k
    if (n_vrt == 0 || n_alcada == 0)
213
17.6k
        return 0;
214
215
14.3k
    if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
216
4.87k
    {
217
4.87k
        if (n_vrt > (unsigned)(INT_MAX / n_alcada))
218
1.18k
        {
219
1.18k
            CPLError(CE_Failure, CPLE_OutOfMemory, "Integer overflow");
220
1.18k
            return 1;
221
1.18k
        }
222
3.69k
        n_h_total = (MM_N_HEIGHT_TYPE)n_vrt * n_alcada;
223
3.69k
    }
224
9.45k
    else
225
9.45k
        n_h_total = n_alcada;
226
227
13.1k
    if (n_h_total <= MM_N_ALCADA_LOCAL)
228
1.91k
        palcada = local_CinquantaAlcades;
229
11.2k
    else
230
11.2k
    {
231
11.2k
        if (MMCheckSize_t(n_h_total, sizeof(double)))
232
5.83k
            return 1;
233
5.40k
        if (nullptr ==
234
5.40k
            (palcada = alcada = VSICalloc((size_t)n_h_total, sizeof(double))))
235
0
            return 1;
236
5.40k
    }
237
238
7.31k
    if (VSIFSeekL(pF, pZDescription->nOffsetZ, SEEK_SET))
239
0
    {
240
0
        if (alcada)
241
0
            VSIFree(alcada);
242
0
        return 1;
243
0
    }
244
7.31k
    if (n_h_total !=
245
7.31k
        (MM_N_HEIGHT_TYPE)VSIFReadL(palcada, sizeof(double), n_h_total, pF))
246
3.23k
    {
247
3.23k
        if (alcada)
248
2.46k
            VSIFree(alcada);
249
3.23k
        return 1;
250
3.23k
    }
251
252
4.08k
    if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
253
1.22k
    {
254
1.22k
        palcada_i = palcada;
255
9.91k
        for (i = 0; i < n_alcada; i++)
256
8.68k
        {
257
185k
            for (i_vrt = 0, pcoord_z = coord_z; i_vrt < n_vrt;
258
176k
                 i_vrt++, pcoord_z++, palcada_i++)
259
176k
                MM_AdoptHeight(pcoord_z, palcada_i, flag);
260
8.68k
        }
261
1.22k
    }
262
2.85k
    else
263
2.85k
    {
264
2.85k
        palcada_i = palcada;
265
2.85k
        pcoord_z = coord_z;
266
343k
        for (i = 0; i < n_alcada; i++, palcada_i++)
267
340k
            MM_AdoptHeight(pcoord_z, palcada_i, flag);
268
269
2.85k
        if (*pcoord_z != MM_NODATA_COORD_Z)
270
2.85k
        {
271
            /*Copio el mateix valor a totes les alcades.*/
272
299k
            for (i_vrt = 1, pcoord_z++; i_vrt < (size_t)n_vrt;
273
296k
                 i_vrt++, pcoord_z++)
274
296k
                *pcoord_z = *coord_z;
275
2.85k
        }
276
2.85k
    }
277
4.08k
    if (alcada)
278
2.94k
        VSIFree(alcada);
279
4.08k
    return 0;
280
7.31k
}  // 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
49.3k
{
289
49.3k
    VSILFILE *pF;
290
49.3k
    struct MM_AH *pArcHeader;
291
49.3k
    struct MiraMonArcLayer *pMMArc;
292
49.3k
    struct MM_ZD *pZDescription = nullptr;
293
294
49.3k
    if (hMiraMonLayer->bIsPolygon)
295
48.0k
        pMMArc = &hMiraMonLayer->MMPolygon.MMArc;
296
1.28k
    else
297
1.28k
        pMMArc = &hMiraMonLayer->MMArc;
298
299
49.3k
    pF = pMMArc->pF;
300
49.3k
    pArcHeader = pMMArc->pArcHeader;
301
49.3k
    if (hMiraMonLayer->TopHeader.bIs3d)
302
32.1k
        pZDescription = pMMArc->pZSection.pZDescription;
303
304
49.3k
    VSIFSeekL(pF, pArcHeader[i_elem].nOffset, SEEK_SET);
305
306
49.3k
    if (hMiraMonLayer->bIsPolygon && (VFG & MM_POL_REVERSE_ARC))  // &&
307
        //nStartVertice > 0)
308
3.19k
    {
309
3.19k
        MM_N_VERTICES_TYPE nIVertice;
310
311
        // Reading arcs vertices in an inverse order
312
3.19k
        if (MMResizeMM_POINT2DPointer(
313
3.19k
                &hMiraMonLayer->ReadFeature.pCoord,
314
3.19k
                &hMiraMonLayer->ReadFeature.nMaxpCoord,
315
3.19k
                nStartVertice + pArcHeader[i_elem].nElemCount *
316
3.19k
                                    2,  // ask for twice memory to reverse
317
3.19k
                0, 0))
318
1
            return 1;
319
320
        // Get the vertices far away from their place to be inverted later
321
3.19k
        if (pArcHeader[i_elem].nElemCount !=
322
3.19k
            VSIFReadL(hMiraMonLayer->ReadFeature.pCoord + nStartVertice +
323
3.19k
                          pArcHeader[i_elem].nElemCount,
324
3.19k
                      sizeof(*hMiraMonLayer->ReadFeature.pCoord),
325
3.19k
                      (size_t)pArcHeader[i_elem].nElemCount, pF))
326
10
        {
327
10
            return 1;
328
10
        }
329
330
3.18k
        if (hMiraMonLayer->TopHeader.bIs3d)
331
2.50k
        {
332
2.50k
            if (MMResizeDoublePointer(
333
2.50k
                    &hMiraMonLayer->ReadFeature.pZCoord,
334
2.50k
                    &hMiraMonLayer->ReadFeature.nMaxpZCoord,
335
2.50k
                    nStartVertice + pArcHeader[i_elem].nElemCount * 2, 0, 0))
336
0
                return 1;
337
338
            // +nStartVertice
339
2.50k
            MM_GetArcHeights(hMiraMonLayer->ReadFeature.pZCoord +
340
2.50k
                                 nStartVertice + pArcHeader[i_elem].nElemCount,
341
2.50k
                             pF, pArcHeader[i_elem].nElemCount,
342
2.50k
                             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
2.50k
        }
354
355
        // Reverse the vertices while putting on their place
356
302k
        for (nIVertice = 0; nIVertice < pArcHeader[i_elem].nElemCount;
357
299k
             nIVertice++)
358
299k
        {
359
299k
            memcpy(hMiraMonLayer->ReadFeature.pCoord + nStartVertice -
360
299k
                       ((nStartVertice > 0 && bAvoidFirst) ? 1 : 0) + nIVertice,
361
299k
                   hMiraMonLayer->ReadFeature.pCoord + nStartVertice +
362
299k
                       2 * pArcHeader[i_elem].nElemCount - nIVertice - 1,
363
299k
                   sizeof(*hMiraMonLayer->ReadFeature.pCoord));
364
365
299k
            if (hMiraMonLayer->TopHeader.bIs3d)
366
234k
            {
367
234k
                memcpy(hMiraMonLayer->ReadFeature.pZCoord + nStartVertice -
368
234k
                           ((nStartVertice > 0 && bAvoidFirst) ? 1 : 0) +
369
234k
                           nIVertice,
370
234k
                       hMiraMonLayer->ReadFeature.pZCoord + nStartVertice +
371
234k
                           2 * pArcHeader[i_elem].nElemCount - nIVertice - 1,
372
234k
                       sizeof(*hMiraMonLayer->ReadFeature.pZCoord));
373
234k
            }
374
299k
        }
375
3.18k
    }
376
46.1k
    else
377
46.1k
    {
378
        // Reading arcs vertices
379
46.1k
        if (MMResizeMM_POINT2DPointer(
380
46.1k
                &hMiraMonLayer->ReadFeature.pCoord,
381
46.1k
                &hMiraMonLayer->ReadFeature.nMaxpCoord,
382
46.1k
                nStartVertice + pArcHeader[i_elem].nElemCount, 0, 0))
383
104
            return 1;
384
385
46.0k
        if (pArcHeader[i_elem].nElemCount !=
386
46.0k
            VSIFReadL(hMiraMonLayer->ReadFeature.pCoord + nStartVertice -
387
46.0k
                          (bAvoidFirst ? 1 : 0),
388
46.0k
                      sizeof(*hMiraMonLayer->ReadFeature.pCoord),
389
46.0k
                      (size_t)pArcHeader[i_elem].nElemCount, pF))
390
44
        {
391
44
            return 1;
392
44
        }
393
394
46.0k
        if (hMiraMonLayer->TopHeader.bIs3d)
395
29.6k
        {
396
29.6k
            if (MMResizeDoublePointer(
397
29.6k
                    &hMiraMonLayer->ReadFeature.pZCoord,
398
29.6k
                    &hMiraMonLayer->ReadFeature.nMaxpZCoord,
399
29.6k
                    nStartVertice + pArcHeader[i_elem].nElemCount, 0, 0))
400
0
                return 1;
401
402
            // +nStartVertice
403
29.6k
            MM_GetArcHeights(hMiraMonLayer->ReadFeature.pZCoord +
404
29.6k
                                 nStartVertice - (bAvoidFirst ? 1 : 0),
405
29.6k
                             pF, pArcHeader[i_elem].nElemCount,
406
29.6k
                             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
29.6k
        }
418
46.0k
    }
419
49.2k
    hMiraMonLayer->ReadFeature.nNumpCoord =
420
49.2k
        pArcHeader[i_elem].nElemCount == 0
421
49.2k
            ? 0
422
49.2k
            : pArcHeader[i_elem].nElemCount - (bAvoidFirst ? 1 : 0);
423
424
49.2k
    return 0;
425
49.3k
}
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
467
{
432
467
    struct MM_PH *pPolHeader;
433
467
    struct MM_AH *pArcHeader;
434
467
    char *pBuffer;
435
467
    MM_POLYGON_ARCS_COUNT nIndex;
436
467
    MM_BOOLEAN bAvoidFirst;
437
467
    MM_N_VERTICES_TYPE nNAcumulVertices = 0;
438
439
    // Checking if the index of the polygon is in the correct range.
440
467
    if (i_pol >= hMiraMonLayer->TopHeader.nElemCount)
441
0
        return 1;
442
443
467
    MMResetFeatureGeometry(&hMiraMonLayer->ReadFeature);
444
467
    MMResetFeatureRecord(&hMiraMonLayer->ReadFeature);
445
467
    pPolHeader = hMiraMonLayer->MMPolygon.pPolHeader + i_pol;
446
447
    // It's accepted not having arcs in the universal polygon
448
467
    if (!pPolHeader->nArcsCount)
449
9
    {
450
9
        if (i_pol == 0)
451
0
            return 0;
452
9
        else
453
9
            return 1;
454
9
    }
455
456
458
    if (MMResizeMiraMonPolygonArcs(&hMiraMonLayer->pArcs,
457
458
                                   &hMiraMonLayer->nMaxArcs,
458
458
                                   pPolHeader->nArcsCount, 0, 0))
459
82
        return 1;
460
461
376
    if (MMInitFlush(&hMiraMonLayer->FlushPAL, hMiraMonLayer->MMPolygon.pF,
462
376
                    hMiraMonLayer->MMPolygon.nPALElementSize *
463
376
                        pPolHeader->nArcsCount,
464
376
                    &pBuffer, pPolHeader->nOffset, 0))
465
0
    {
466
0
        if (pBuffer)
467
0
            VSIFree(pBuffer);
468
0
        return 1;
469
0
    }
470
471
376
    hMiraMonLayer->FlushPAL.pBlockWhereToSaveOrRead = (void *)pBuffer;
472
376
    if (MMReadFlush(&hMiraMonLayer->FlushPAL))
473
46
    {
474
46
        if (pBuffer)
475
46
            VSIFree(pBuffer);
476
46
        return 1;
477
46
    }
478
479
330
    hMiraMonLayer->ReadFeature.nNRings = 0;
480
330
    hMiraMonLayer->ReadFeature.nNumpCoord = 0;
481
330
    if (MMResize_MM_N_VERTICES_TYPE_Pointer(
482
330
            &hMiraMonLayer->ReadFeature.pNCoordRing,
483
330
            &hMiraMonLayer->ReadFeature.nMaxpNCoordRing,
484
330
            (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10, 10))
485
0
    {
486
0
        VSIFree(pBuffer);
487
0
        return 1;
488
0
    }
489
490
330
    if (MMResizeVFGPointer(&hMiraMonLayer->ReadFeature.flag_VFG,
491
330
                           &hMiraMonLayer->ReadFeature.nMaxVFG,
492
330
                           (MM_INTERNAL_FID)pPolHeader->nArcsCount, 0,
493
330
                           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
330
    hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] =
501
330
        0;
502
59.2k
    for (nIndex = 0; nIndex < pPolHeader->nArcsCount; nIndex++)
503
59.0k
    {
504
59.0k
        hMiraMonLayer->FlushPAL.SizeOfBlockToBeSaved =
505
59.0k
            sizeof((hMiraMonLayer->pArcs + nIndex)->VFG);
506
59.0k
        hMiraMonLayer->FlushPAL.pBlockToBeSaved =
507
59.0k
            (void *)&(hMiraMonLayer->pArcs + nIndex)->VFG;
508
59.0k
        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
59.0k
        if (MMReadGUInt64DependingOnVersion(
517
59.0k
                hMiraMonLayer, &hMiraMonLayer->FlushPAL,
518
59.0k
                &((hMiraMonLayer->pArcs + nIndex)->nIArc)))
519
0
        {
520
0
            if (pBuffer)
521
0
                VSIFree(pBuffer);
522
0
            return 1;
523
0
        }
524
525
59.0k
        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
59.0k
        if ((hMiraMonLayer->pArcs + nIndex)->nIArc >=
534
59.0k
            hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount)
535
78
        {
536
78
            VSIFree(pBuffer);
537
78
            return 1;
538
78
        }
539
540
58.9k
        pArcHeader = hMiraMonLayer->MMPolygon.MMArc.pArcHeader +
541
58.9k
                     (hMiraMonLayer->pArcs + nIndex)->nIArc;
542
543
58.9k
        if (hMiraMonLayer->ReadFeature
544
58.9k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
545
58.9k
            UINT64_MAX - pArcHeader->nElemCount)
546
3
        {
547
3
            VSIFree(pBuffer);
548
3
            return 1;
549
3
        }
550
551
58.9k
        if (hMiraMonLayer->ReadFeature
552
58.9k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
553
58.9k
            UINT64_MAX - pArcHeader->nElemCount)
554
0
        {
555
0
            VSIFree(pBuffer);
556
0
            return 1;
557
0
        }
558
559
58.9k
        hMiraMonLayer->ReadFeature
560
58.9k
            .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] +=
561
58.9k
            pArcHeader->nElemCount;
562
58.9k
    }
563
248
    if (MMResizeMM_POINT2DPointer(
564
248
            &hMiraMonLayer->ReadFeature.pCoord,
565
248
            &hMiraMonLayer->ReadFeature.nMaxpCoord,
566
248
            hMiraMonLayer->ReadFeature
567
248
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings],
568
248
            0, 0))
569
8
    {
570
8
        VSIFree(pBuffer);
571
8
        return 1;
572
8
    }
573
574
240
    hMiraMonLayer->FlushPAL.CurrentOffset = 0;
575
576
    // Real work
577
240
    hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] =
578
240
        0;
579
48.2k
    for (nIndex = 0; nIndex < pPolHeader->nArcsCount; nIndex++)
580
48.0k
    {
581
48.0k
        hMiraMonLayer->FlushPAL.SizeOfBlockToBeSaved =
582
48.0k
            sizeof((hMiraMonLayer->pArcs + nIndex)->VFG);
583
48.0k
        hMiraMonLayer->FlushPAL.pBlockToBeSaved =
584
48.0k
            (void *)&(hMiraMonLayer->pArcs + nIndex)->VFG;
585
48.0k
        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
48.0k
        if (MMReadGUInt64DependingOnVersion(
594
48.0k
                hMiraMonLayer, &hMiraMonLayer->FlushPAL,
595
48.0k
                &((hMiraMonLayer->pArcs + nIndex)->nIArc)))
596
0
        {
597
0
            if (pBuffer)
598
0
                VSIFree(pBuffer);
599
0
            return 1;
600
0
        }
601
602
48.0k
        bAvoidFirst = FALSE;
603
48.0k
        if (hMiraMonLayer->ReadFeature
604
48.0k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] != 0)
605
26.8k
            bAvoidFirst = TRUE;
606
607
        // Add coordinates to hMiraMonLayer->ReadFeature.pCoord
608
48.0k
        if (MMAddStringLineCoordinates(hMiraMonLayer,
609
48.0k
                                       (hMiraMonLayer->pArcs + nIndex)->nIArc,
610
48.0k
                                       flag_z, nNAcumulVertices, bAvoidFirst,
611
48.0k
                                       (hMiraMonLayer->pArcs + nIndex)->VFG))
612
30
        {
613
30
            VSIFree(pBuffer);
614
30
            return 1;
615
30
        }
616
617
48.0k
        if (MMResize_MM_N_VERTICES_TYPE_Pointer(
618
48.0k
                &hMiraMonLayer->ReadFeature.pNCoordRing,
619
48.0k
                &hMiraMonLayer->ReadFeature.nMaxpNCoordRing,
620
48.0k
                (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10,
621
48.0k
                10))
622
0
        {
623
0
            VSIFree(pBuffer);
624
0
            return 1;
625
0
        }
626
627
48.0k
        if (hMiraMonLayer->ReadFeature
628
48.0k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] >
629
48.0k
            UINT64_MAX - hMiraMonLayer->ReadFeature.nNumpCoord)
630
0
        {
631
0
            VSIFree(pBuffer);
632
0
            return 1;
633
0
        }
634
635
48.0k
        hMiraMonLayer->ReadFeature
636
48.0k
            .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] +=
637
48.0k
            hMiraMonLayer->ReadFeature.nNumpCoord;
638
48.0k
        nNAcumulVertices += hMiraMonLayer->ReadFeature.nNumpCoord;
639
640
48.0k
        if ((hMiraMonLayer->pArcs + nIndex)->VFG & MM_POL_END_RING)
641
6.10k
        {
642
6.10k
            hMiraMonLayer->ReadFeature
643
6.10k
                .flag_VFG[hMiraMonLayer->ReadFeature.nNRings] =
644
6.10k
                (hMiraMonLayer->pArcs + nIndex)->VFG;
645
6.10k
            hMiraMonLayer->ReadFeature.nNRings++;
646
6.10k
            hMiraMonLayer->ReadFeature
647
6.10k
                .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] = 0;
648
6.10k
        }
649
48.0k
    }
650
210
    hMiraMonLayer->nNumArcs = pPolHeader->nArcsCount;
651
210
    if (pBuffer)
652
210
        VSIFree(pBuffer);
653
654
210
    return 0;
655
240
}
656
657
// Reads the geographical part of a MiraMon layer feature
658
int MMGetGeoFeatureFromVector(struct MiraMonVectLayerInfo *hMiraMonLayer,
659
                              MM_INTERNAL_FID i_elem)
660
14.5k
{
661
14.5k
    VSILFILE *pF;
662
14.5k
    struct MM_ZD *pZDescription;
663
14.5k
    uint32_t flag_z;
664
14.5k
    int num;
665
14.5k
    double cz;
666
667
14.5k
    if (hMiraMonLayer->nSelectCoordz == MM_SELECT_HIGHEST_COORDZ)
668
0
        flag_z = MM_STRING_HIGHEST_ALTITUDE;
669
14.5k
    else if (hMiraMonLayer->nSelectCoordz == MM_SELECT_LOWEST_COORDZ)
670
0
        flag_z = MM_STRING_LOWEST_ALTITUDE;
671
14.5k
    else
672
14.5k
        flag_z = 0L;
673
674
14.5k
    if (hMiraMonLayer->bIsPoint)
675
12.8k
    {
676
12.8k
        pF = hMiraMonLayer->MMPoint.pF;
677
678
        // Getting to the i-th element offset
679
12.8k
        VSIFSeekL(pF,
680
12.8k
                  hMiraMonLayer->nHeaderDiskSize +
681
12.8k
                      sizeof(MM_COORD_TYPE) * 2 * i_elem,
682
12.8k
                  SEEK_SET);
683
684
        // Reading the point
685
12.8k
        if (MMResizeMM_POINT2DPointer(&hMiraMonLayer->ReadFeature.pCoord,
686
12.8k
                                      &hMiraMonLayer->ReadFeature.nMaxpCoord,
687
12.8k
                                      hMiraMonLayer->ReadFeature.nNumpCoord, 1,
688
12.8k
                                      1))
689
0
            return 1;
690
691
12.8k
        if (1 != VSIFReadL(hMiraMonLayer->ReadFeature.pCoord,
692
12.8k
                           sizeof(MM_COORD_TYPE) * 2, 1, pF))
693
215
        {
694
215
            return 1;
695
215
        }
696
697
12.5k
        hMiraMonLayer->ReadFeature.nNRings = 1;
698
699
12.5k
        if (MMResize_MM_N_VERTICES_TYPE_Pointer(
700
12.5k
                &hMiraMonLayer->ReadFeature.pNCoordRing,
701
12.5k
                &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, 1, 0, 1))
702
0
            return 1;
703
704
12.5k
        hMiraMonLayer->ReadFeature.pNCoordRing[0] = 1;
705
706
12.5k
        if (hMiraMonLayer->TopHeader.bIs3d)
707
2.37k
        {
708
2.37k
            pZDescription =
709
2.37k
                hMiraMonLayer->MMPoint.pZSection.pZDescription + i_elem;
710
2.37k
            if (pZDescription->nZCount == INT_MIN)
711
1
                return 1;
712
2.37k
            num = MM_ARC_TOTAL_N_HEIGHTS_DISK(pZDescription->nZCount, 1);
713
714
2.37k
            if (MMResizeDoublePointer(&hMiraMonLayer->ReadFeature.pZCoord,
715
2.37k
                                      &hMiraMonLayer->ReadFeature.nMaxpZCoord,
716
2.37k
                                      1, 1, 1))
717
0
                return 1;
718
719
2.37k
            if (num == 0)
720
871
                hMiraMonLayer->ReadFeature.pZCoord[0] = MM_NODATA_COORD_Z;
721
1.50k
            else
722
1.50k
            {
723
1.50k
                if (flag_z == MM_STRING_HIGHEST_ALTITUDE)  // Max z
724
0
                    cz = pZDescription->dfBBmaxz;
725
1.50k
                else if (flag_z == MM_STRING_LOWEST_ALTITUDE)  // Min z
726
0
                    cz = pZDescription->dfBBminz;
727
1.50k
                else
728
1.50k
                {
729
                    // Reading the first z coordinate
730
1.50k
                    VSIFSeekL(pF, pZDescription->nOffsetZ, SEEK_SET);
731
1.50k
                    if ((size_t)1 !=
732
1.50k
                        VSIFReadL(&cz,
733
1.50k
                                  sizeof(*hMiraMonLayer->ReadFeature.pZCoord),
734
1.50k
                                  1, pF))
735
53
                    {
736
53
                        return 1;
737
53
                    }
738
1.50k
                }
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
1.45k
                hMiraMonLayer->ReadFeature.pZCoord[0] = cz;
745
1.45k
            }
746
2.37k
        }
747
748
12.5k
        return 0;
749
12.5k
    }
750
751
    // Stringlines
752
1.75k
    if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
753
1.28k
    {
754
1.28k
        if (MMAddStringLineCoordinates(hMiraMonLayer, i_elem, flag_z, 0, FALSE,
755
1.28k
                                       0))
756
129
            return 1;
757
758
1.15k
        if (MMResize_MM_N_VERTICES_TYPE_Pointer(
759
1.15k
                &hMiraMonLayer->ReadFeature.pNCoordRing,
760
1.15k
                &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, 1, 0, 1))
761
0
            return 1;
762
763
1.15k
        hMiraMonLayer->ReadFeature.pNCoordRing[0] =
764
1.15k
            hMiraMonLayer->ReadFeature.nNumpCoord;
765
766
1.15k
        return 0;
767
1.15k
    }
768
769
    // Polygons or multipolygons
770
467
    if (MMGetMultiPolygonCoordinates(hMiraMonLayer, i_elem, flag_z))
771
257
        return 1;
772
773
210
    return 0;
774
467
}
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
3.40k
{
781
3.40k
    const char *pszRelFile = nullptr;
782
3.40k
    struct MM_DATA_BASE_XP *pMMBDXP;
783
3.40k
    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
3.40k
    if (hMiraMonLayer->pMMBDXP)
788
267
        return 0;
789
790
3.13k
    pMMBDXP = hMiraMonLayer->pMMBDXP = VSICalloc(1, sizeof(*pMMBDXP));
791
3.13k
    if (!pMMBDXP)
792
0
        return 1;
793
794
3.13k
    if (hMiraMonLayer->bIsPoint)
795
314
    {
796
314
        hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP = pMMBDXP;
797
314
        szDBFFileName = hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName;
798
314
        pszRelFile = hMiraMonLayer->MMPoint.pszREL_LayerName;
799
314
    }
800
2.82k
    else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
801
180
    {
802
180
        hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP = pMMBDXP;
803
180
        szDBFFileName = hMiraMonLayer->MMArc.MMAdmDB.pszExtDBFLayerName;
804
180
        pszRelFile = hMiraMonLayer->MMArc.pszREL_LayerName;
805
180
    }
806
2.64k
    else if (hMiraMonLayer->bIsPolygon)
807
2.64k
    {
808
2.64k
        hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP = pMMBDXP;
809
2.64k
        szDBFFileName = hMiraMonLayer->MMPolygon.MMAdmDB.pszExtDBFLayerName;
810
2.64k
        pszRelFile = hMiraMonLayer->MMPolygon.pszREL_LayerName;
811
2.64k
    }
812
813
3.13k
    if (MM_ReadExtendedDBFHeaderFromFile(szDBFFileName, pMMBDXP, pszRelFile))
814
67
    {
815
67
        CPLError(CE_Failure, CPLE_NotSupported,
816
67
                 "Error reading the format in the DBF file %s.", szDBFFileName);
817
67
        return 1;
818
67
    }
819
820
3.07k
    fclose_and_nullify(&pMMBDXP->pfDataBase);
821
3.07k
    return 0;
822
3.13k
}
823
824
CPL_C_END  // Necessary for compiling in GDAL project