Coverage Report

Created: 2026-05-16 08:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/miramon/mm_wrlayr.c
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  C API to create 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 "mm_wrlayr.h"
19
#include "../../../frmts/miramon_common/mm_gdal_functions.h"
20
#include "../../../frmts/miramon_common/mm_gdal_constants.h"
21
#include "mm_rdlayr.h"    // For MM_ReadExtendedDBFHeader()
22
#include "gdal.h"         // For GDALDatasetH
23
#include "ogr_srs_api.h"  // For OSRGetAuthorityCode
24
#include "cpl_string.h"   // For CPL_ENC_UTF8
25
26
CPL_C_START  // Necessary for compiling in GDAL project
27
28
/* -------------------------------------------------------------------- */
29
/*      COMING FROM mm_gdal_functions.c/h but only used here            */
30
/* -------------------------------------------------------------------- */
31
// MiraMon feature table descriptors
32
397k
#define MM_MAX_IDENTIFIER_SIZE 50
33
12.0k
#define MM_a_WITH_GRAVE 224
34
12.0k
#define MM_a_WITH_ACUTE 225
35
12.0k
#define MM_e_WITH_GRAVE 232
36
12.0k
#define MM_e_WITH_ACUTE 233
37
96.2k
#define MM_i_WITH_ACUTE 237
38
#define MM_o_WITH_GRAVE 242
39
#define MM_o_WITH_ACUTE 243
40
48.1k
#define MM_u_WITH_ACUTE 250
41
42
12.0k
#define MM_A_WITH_GRAVE 192
43
12.0k
#define MM_A_WITH_ACUTE 193
44
#define MM_E_WITH_GRAVE 200
45
#define MM_E_WITH_ACUTE 201
46
#define MM_I_WITH_ACUTE 205
47
#define MM_O_WITH_GRAVE 210
48
#define MM_O_WITH_ACUTE 211
49
#define MM_U_WITH_ACUTE 218
50
51
    // In case of diaeresis use "_WITH_DIAERESIS"
52
    // In case of cedilla use "_WITH_CEDILLA"
53
    // In case of tilde use "_WITH_TILDE"
54
    // In case of middle dot use "_MIDDLE_DOT"
55
56
    char szInternalGraphicIdentifierEng[MM_MAX_IDENTIFIER_SIZE];
57
char szInternalGraphicIdentifierCat[MM_MAX_IDENTIFIER_SIZE];
58
char szInternalGraphicIdentifierSpa[MM_MAX_IDENTIFIER_SIZE];
59
60
char szNumberOfVerticesEng[MM_MAX_IDENTIFIER_SIZE];
61
char szNumberOfVerticesCat[MM_MAX_IDENTIFIER_SIZE];
62
char szNumberOfVerticesSpa[MM_MAX_IDENTIFIER_SIZE];
63
64
char szLengthOfAarcEng[MM_MAX_IDENTIFIER_SIZE];
65
char szLengthOfAarcCat[MM_MAX_IDENTIFIER_SIZE];
66
char szLengthOfAarcSpa[MM_MAX_IDENTIFIER_SIZE];
67
68
char szInitialNodeEng[MM_MAX_IDENTIFIER_SIZE];
69
char szInitialNodeCat[MM_MAX_IDENTIFIER_SIZE];
70
char szInitialNodeSpa[MM_MAX_IDENTIFIER_SIZE];
71
72
char szFinalNodeEng[MM_MAX_IDENTIFIER_SIZE];
73
char szFinalNodeCat[MM_MAX_IDENTIFIER_SIZE];
74
char szFinalNodeSpa[MM_MAX_IDENTIFIER_SIZE];
75
76
char szNumberOfArcsToNodeEng[MM_MAX_IDENTIFIER_SIZE];
77
char szNumberOfArcsToNodeCat[MM_MAX_IDENTIFIER_SIZE];
78
char szNumberOfArcsToNodeSpa[MM_MAX_IDENTIFIER_SIZE];
79
80
char szNodeTypeEng[MM_MAX_IDENTIFIER_SIZE];
81
char szNodeTypeCat[MM_MAX_IDENTIFIER_SIZE];
82
char szNodeTypeSpa[MM_MAX_IDENTIFIER_SIZE];
83
84
char szPerimeterOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE];
85
char szPerimeterOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE];
86
char szPerimeterOfThePolygonSpa[MM_MAX_IDENTIFIER_SIZE];
87
88
char szAreaOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE];
89
char szAreaOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE];
90
char szAreaOfThePolygonSpa[MM_MAX_IDENTIFIER_SIZE];
91
92
char szNumberOfArcsEng[MM_MAX_IDENTIFIER_SIZE];
93
char szNumberOfArcsCat[MM_MAX_IDENTIFIER_SIZE];
94
char szNumberOfArcsSpa[MM_MAX_IDENTIFIER_SIZE];
95
96
char szNumberOfElementaryPolygonsEng[MM_MAX_IDENTIFIER_SIZE];
97
char szNumberOfElementaryPolygonsCat[MM_MAX_IDENTIFIER_SIZE];
98
char szNumberOfElementaryPolygonsSpa[MM_MAX_IDENTIFIER_SIZE];
99
100
void MM_FillFieldDescriptorByLanguage(void);
101
102
/* -------------------------------------------------------------------- */
103
/*      Header Functions                                                */
104
/* -------------------------------------------------------------------- */
105
int MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo);
106
void MMInitBoundingBox(struct MMBoundingBox *dfBB);
107
int MMWriteAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
108
                        MM_FILE_OFFSET DiskOffset);
109
int MMWriteNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
110
                         MM_FILE_OFFSET DiskOffset);
111
int MMWritePHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
112
                            MM_FILE_OFFSET DiskOffset);
113
int MMAppendIntegerDependingOnVersion(
114
    struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo,
115
    uint32_t *nUL32, GUInt64 nUI64);
116
int MMMoveFromFileToFile(VSILFILE *pSrcFile, VSILFILE *pDestFile,
117
                         MM_FILE_OFFSET *nOffset);
118
int MMResizeZSectionDescrPointer(struct MM_ZD **pZDescription, GUInt64 *nMax,
119
                                 GUInt64 nNum, GUInt64 nIncr,
120
                                 GUInt64 nProposedMax);
121
int MMResizeArcHeaderPointer(struct MM_AH **pArcHeader, GUInt64 *nMax,
122
                             GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax);
123
int MMResizeNodeHeaderPointer(struct MM_NH **pNodeHeader, GUInt64 *nMax,
124
                              GUInt64 nNum, GUInt64 nIncr,
125
                              GUInt64 nProposedMax);
126
int MMResizePolHeaderPointer(struct MM_PH **pPolHeader, GUInt64 *nMax,
127
                             GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax);
128
void MMUpdateBoundingBoxXY(struct MMBoundingBox *dfBB,
129
                           struct MM_POINT_2D *pCoord);
130
void MMUpdateBoundingBox(struct MMBoundingBox *dfBBToBeAct,
131
                         struct MMBoundingBox *dfBBWithData);
132
int MMCheckVersionFor3DOffset(struct MiraMonVectLayerInfo *hMiraMonLayer,
133
                              MM_INTERNAL_FID nElemCount,
134
                              MM_FILE_OFFSET nOffsetAL,
135
                              MM_FILE_OFFSET nZLOffset);
136
int MMCheckVersionOffset(struct MiraMonVectLayerInfo *hMiraMonLayer,
137
                         MM_FILE_OFFSET OffsetToCheck);
138
int MMCheckVersionForFID(struct MiraMonVectLayerInfo *hMiraMonLayer,
139
                         MM_INTERNAL_FID FID);
140
141
// Extended DBF functions
142
int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
143
                 struct MM_POINT_2D *pFirstCoord);
144
int MMAddDBFRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
145
                         struct MiraMonFeature *hMMFeature);
146
int MMAddPointRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
147
                           struct MiraMonFeature *hMMFeature,
148
                           MM_INTERNAL_FID nElemCount);
149
int MMAddArcRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
150
                         struct MiraMonFeature *hMMFeature,
151
                         MM_INTERNAL_FID nElemCount, struct MM_AH *pArcHeader);
152
int MMAddNodeRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
153
                          MM_INTERNAL_FID nElemCount,
154
                          struct MM_NH *pNodeHeader);
155
int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
156
                             struct MiraMonFeature *hMMFeature,
157
                             MM_INTERNAL_FID nElemCount,
158
                             MM_N_VERTICES_TYPE nVerticesCount,
159
                             struct MM_PH *pPolHeader);
160
int MMCloseMMBD_XP(struct MiraMonVectLayerInfo *hMiraMonLayer);
161
void MMDestroyMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer);
162
163
/* -------------------------------------------------------------------- */
164
/*      Layer Functions: Version                                         */
165
/* -------------------------------------------------------------------- */
166
int MMGetVectorVersion(struct MM_TH *pTopHeader)
167
5.79k
{
168
5.79k
    if ((pTopHeader->aLayerVersion[0] == ' ' ||
169
0
         pTopHeader->aLayerVersion[0] == '0') &&
170
5.79k
        pTopHeader->aLayerVersion[1] == '1' &&
171
4.09k
        pTopHeader->aLayerSubVersion == '1')
172
4.09k
        return MM_32BITS_VERSION;
173
174
1.70k
    if ((pTopHeader->aLayerVersion[0] == ' ' ||
175
0
         pTopHeader->aLayerVersion[0] == '0') &&
176
1.70k
        pTopHeader->aLayerVersion[1] == '2' &&
177
1.70k
        pTopHeader->aLayerSubVersion == '0')
178
1.70k
        return MM_64BITS_VERSION;
179
180
0
    return MM_UNKNOWN_VERSION;
181
1.70k
}
182
183
static void MMSet1_1Version(struct MM_TH *pTopHeader)
184
13.0k
{
185
13.0k
    pTopHeader->aLayerVersion[0] = ' ';
186
13.0k
    pTopHeader->aLayerVersion[1] = '1';
187
13.0k
    pTopHeader->aLayerSubVersion = '1';
188
13.0k
}
189
190
static void MMSet2_0Version(struct MM_TH *pTopHeader)
191
265
{
192
265
    pTopHeader->aLayerVersion[0] = ' ';
193
265
    pTopHeader->aLayerVersion[1] = '2';
194
265
    pTopHeader->aLayerSubVersion = '0';
195
265
}
196
197
/* -------------------------------------------------------------------- */
198
/*      Layer Functions: Header                                         */
199
/* -------------------------------------------------------------------- */
200
int MMReadHeader(VSILFILE *pF, struct MM_TH *pMMHeader)
201
5.58k
{
202
5.58k
    char dot;
203
5.58k
    uint32_t NCount;
204
5.58k
    int32_t reservat4 = 0L;
205
206
5.58k
    pMMHeader->Flag = 0x0;
207
5.58k
    if (VSIFSeekL(pF, 0, SEEK_SET))
208
0
        return 1;
209
5.58k
    if (VSIFReadL(pMMHeader->aFileType, 1, 3, pF) != 3)
210
1
        return 1;
211
5.58k
    if (VSIFReadL(pMMHeader->aLayerVersion, 1, 2, pF) != 2)
212
0
        return 1;
213
5.58k
    if (VSIFReadL(&dot, 1, 1, pF) != 1)
214
0
        return 1;
215
5.58k
    if (VSIFReadL(&pMMHeader->aLayerSubVersion, 1, 1, pF) != 1)
216
1
        return 1;
217
5.58k
    if (VSIFReadL(&pMMHeader->Flag, sizeof(pMMHeader->Flag), 1, pF) != 1)
218
1
        return 1;
219
5.58k
    if (VSIFReadL(&pMMHeader->hBB.dfMinX, sizeof(pMMHeader->hBB.dfMinX), 1,
220
5.58k
                  pF) != 1)
221
2
        return 1;
222
5.58k
    if (VSIFReadL(&pMMHeader->hBB.dfMaxX, sizeof(pMMHeader->hBB.dfMaxX), 1,
223
5.58k
                  pF) != 1)
224
1
        return 1;
225
5.58k
    if (VSIFReadL(&pMMHeader->hBB.dfMinY, sizeof(pMMHeader->hBB.dfMinY), 1,
226
5.58k
                  pF) != 1)
227
0
        return 1;
228
5.58k
    if (VSIFReadL(&pMMHeader->hBB.dfMaxY, sizeof(pMMHeader->hBB.dfMaxY), 1,
229
5.58k
                  pF) != 1)
230
2
        return 1;
231
5.58k
    if (pMMHeader->aLayerVersion[0] == ' ' &&
232
5.57k
        pMMHeader->aLayerVersion[1] == '1')
233
4.01k
    {
234
4.01k
        if (VSIFReadL(&NCount, sizeof(NCount), 1, pF) != 1)
235
0
            return 1;
236
237
4.01k
        pMMHeader->nElemCount = (MM_INTERNAL_FID)NCount;
238
239
4.01k
        if (VSIFReadL(&reservat4, 4, 1, pF) != 1)
240
0
            return 1;
241
4.01k
    }
242
1.56k
    else if (pMMHeader->aLayerVersion[0] == ' ' &&
243
1.55k
             pMMHeader->aLayerVersion[1] == '2')
244
1.55k
    {
245
1.55k
        if (VSIFReadL(&(pMMHeader->nElemCount), sizeof(pMMHeader->nElemCount),
246
1.55k
                      1, pF) != 1)
247
0
            return 1;
248
249
1.55k
        if (VSIFReadL(&reservat4, 4, 1, pF) != 1)
250
0
            return 1;
251
1.55k
        if (VSIFReadL(&reservat4, 4, 1, pF) != 1)
252
0
            return 1;
253
1.55k
    }
254
255
5.58k
    if (pMMHeader->Flag & MM_LAYER_3D_INFO)
256
2.34k
        pMMHeader->bIs3d = 1;
257
258
5.58k
    if (pMMHeader->Flag & MM_LAYER_MULTIPOLYGON)
259
2.74k
        pMMHeader->bIsMultipolygon = 1;
260
261
5.58k
    return 0;
262
5.58k
}
263
264
static int MMWriteHeader(VSILFILE *pF, struct MM_TH *pMMHeader)
265
1.18k
{
266
1.18k
    char dot = '.';
267
1.18k
    uint32_t NCount;
268
1.18k
    int32_t reservat4 = 0L;
269
1.18k
    MM_INTERNAL_FID nNumber1 = 1, nNumber0 = 0;
270
271
1.18k
    if (!pF)
272
0
        return 0;
273
274
1.18k
    pMMHeader->Flag = MM_CREATED_USING_MIRAMON;  // Created from MiraMon
275
1.18k
    if (pMMHeader->bIs3d)
276
567
        pMMHeader->Flag |= MM_LAYER_3D_INFO;  // 3D
277
278
1.18k
    if (pMMHeader->bIsMultipolygon)
279
0
        pMMHeader->Flag |= MM_LAYER_MULTIPOLYGON;  // Multipolygon.
280
281
1.18k
    if (pMMHeader->aFileType[0] == 'P' && pMMHeader->aFileType[1] == 'O' &&
282
157
        pMMHeader->aFileType[2] == 'L')
283
157
        pMMHeader->Flag |= MM_BIT_5_ON;  // Explicital polygons
284
285
1.18k
    if (VSIFSeekL(pF, 0, SEEK_SET))
286
0
        return 1;
287
1.18k
    if (VSIFWriteL(pMMHeader->aFileType, 1, 3, pF) != 3)
288
10
        return 1;
289
1.17k
    if (VSIFWriteL(pMMHeader->aLayerVersion, 1, 2, pF) != 2)
290
0
        return 1;
291
1.17k
    if (VSIFWriteL(&dot, 1, 1, pF) != 1)
292
0
        return 1;
293
1.17k
    if (VSIFWriteL(&pMMHeader->aLayerSubVersion, 1, 1, pF) != 1)
294
0
        return 1;
295
1.17k
    if (VSIFWriteL(&pMMHeader->Flag, sizeof(pMMHeader->Flag), 1, pF) != 1)
296
0
        return 1;
297
1.17k
    if (VSIFWriteL(&pMMHeader->hBB.dfMinX, sizeof(pMMHeader->hBB.dfMinX), 1,
298
1.17k
                   pF) != 1)
299
0
        return 1;
300
1.17k
    if (VSIFWriteL(&pMMHeader->hBB.dfMaxX, sizeof(pMMHeader->hBB.dfMaxX), 1,
301
1.17k
                   pF) != 1)
302
0
        return 1;
303
1.17k
    if (VSIFWriteL(&pMMHeader->hBB.dfMinY, sizeof(pMMHeader->hBB.dfMinY), 1,
304
1.17k
                   pF) != 1)
305
0
        return 1;
306
1.17k
    if (VSIFWriteL(&pMMHeader->hBB.dfMaxY, sizeof(pMMHeader->hBB.dfMaxY), 1,
307
1.17k
                   pF) != 1)
308
0
        return 1;
309
1.17k
    if (pMMHeader->aLayerVersion[0] == ' ' &&
310
1.17k
        pMMHeader->aLayerVersion[1] == '1')
311
1.17k
    {
312
1.17k
        NCount = (uint32_t)pMMHeader->nElemCount;
313
1.17k
        if (VSIFWriteL(&NCount, sizeof(NCount), 1, pF) != 1)
314
0
            return 1;
315
316
1.17k
        if (VSIFWriteL(&reservat4, 4, 1, pF) != 1)
317
0
            return 1;
318
1.17k
    }
319
0
    else if (pMMHeader->aLayerVersion[0] == ' ' &&
320
0
             pMMHeader->aLayerVersion[1] == '2')
321
0
    {
322
0
        if (VSIFWriteL(&(pMMHeader->nElemCount), sizeof(pMMHeader->nElemCount),
323
0
                       1, pF) != 1)
324
0
            return 1;
325
326
        // Next part of the file (don't apply for the moment)
327
0
        if (VSIFWriteL(&nNumber1, sizeof(nNumber1), 1, pF) != 1)
328
0
            return 1;
329
0
        if (VSIFWriteL(&nNumber0, sizeof(nNumber0), 1, pF) != 1)
330
0
            return 1;
331
332
        // Reserved bytes
333
0
        if (VSIFWriteL(&reservat4, 4, 1, pF) != 1)
334
0
            return 1;
335
0
        if (VSIFWriteL(&reservat4, 4, 1, pF) != 1)
336
0
            return 1;
337
0
    }
338
1.17k
    return 0;
339
1.17k
}
340
341
/* -------------------------------------------------------------------- */
342
/*      Layer Functions: Z section                                      */
343
/* -------------------------------------------------------------------- */
344
int MMReadZSection(struct MiraMonVectLayerInfo *hMiraMonLayer, VSILFILE *pF,
345
                   struct MM_ZSection *pZSection)
346
363
{
347
363
    int32_t reservat4 = 0L;
348
349
363
    if (!hMiraMonLayer)
350
0
        return 1;
351
352
363
    if (hMiraMonLayer->bIsPoint)
353
101
    {
354
101
        if (MMCheckSize_t(hMiraMonLayer->TopHeader.nElemCount, MM_SIZE_OF_TL))
355
0
            return 1;
356
101
        if (hMiraMonLayer->TopHeader.nElemCount * MM_SIZE_OF_TL >
357
101
            UINT64_MAX - hMiraMonLayer->nHeaderDiskSize)
358
0
            return 1;
359
101
        pZSection->ZSectionOffset =
360
101
            hMiraMonLayer->nHeaderDiskSize +
361
101
            hMiraMonLayer->TopHeader.nElemCount * MM_SIZE_OF_TL;
362
101
    }
363
262
    else if (hMiraMonLayer->bIsArc && !(hMiraMonLayer->bIsPolygon) &&
364
100
             hMiraMonLayer->TopHeader.nElemCount > 0)
365
100
    {
366
100
        const struct MM_AH *pArcHeader =
367
100
            &(hMiraMonLayer->MMArc
368
100
                  .pArcHeader[hMiraMonLayer->TopHeader.nElemCount - 1]);
369
100
        if (MMCheckSize_t(pArcHeader->nElemCount, MM_SIZE_OF_COORDINATE))
370
2
            return 1;
371
98
        if (pArcHeader->nElemCount * MM_SIZE_OF_COORDINATE >
372
98
            UINT64_MAX - pArcHeader->nOffset)
373
0
            return 1;
374
        // Z section begins just after last coordinate of the last arc
375
98
        pZSection->ZSectionOffset =
376
98
            pArcHeader->nOffset +
377
98
            pArcHeader->nElemCount * MM_SIZE_OF_COORDINATE;
378
98
    }
379
162
    else if (hMiraMonLayer->bIsPolygon &&
380
162
             hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount > 0)
381
160
    {
382
160
        const struct MM_AH *pArcHeader =
383
160
            &(hMiraMonLayer->MMPolygon.MMArc
384
160
                  .pArcHeader[hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount -
385
160
                              1]);
386
160
        if (MMCheckSize_t(pArcHeader->nElemCount, MM_SIZE_OF_COORDINATE))
387
1
            return 1;
388
159
        if (pArcHeader->nElemCount * MM_SIZE_OF_COORDINATE >
389
159
            UINT64_MAX - pArcHeader->nOffset)
390
2
            return 1;
391
        // Z section begins just after last coordinate of the last arc
392
157
        pZSection->ZSectionOffset =
393
157
            pArcHeader->nOffset +
394
157
            pArcHeader->nElemCount * MM_SIZE_OF_COORDINATE;
395
157
    }
396
2
    else
397
2
        return 1;
398
399
356
    if (pF)
400
356
    {
401
356
        if (VSIFSeekL(pF, pZSection->ZSectionOffset, SEEK_SET))
402
0
            return 1;
403
404
356
        if (VSIFReadL(&reservat4, 4, 1, pF) != 1)
405
59
            return 1;
406
297
        pZSection->ZSectionOffset += 4;
407
297
        if (VSIFReadL(&reservat4, 4, 1, pF) != 1)
408
1
            return 1;
409
296
        pZSection->ZSectionOffset += 4;
410
296
        if (VSIFReadL(&reservat4, 4, 1, pF) != 1)
411
0
            return 1;
412
296
        pZSection->ZSectionOffset += 4;
413
296
        if (VSIFReadL(&reservat4, 4, 1, pF) != 1)
414
1
            return 1;
415
295
        pZSection->ZSectionOffset += 4;
416
417
295
        if (VSIFReadL(&pZSection->ZHeader.dfBBminz,
418
295
                      sizeof(pZSection->ZHeader.dfBBminz), 1, pF) != 1)
419
1
            return 1;
420
294
        pZSection->ZSectionOffset += sizeof(pZSection->ZHeader.dfBBminz);
421
422
294
        if (VSIFReadL(&pZSection->ZHeader.dfBBmaxz,
423
294
                      sizeof(pZSection->ZHeader.dfBBmaxz), 1, pF) != 1)
424
1
            return 1;
425
293
        pZSection->ZSectionOffset += sizeof(pZSection->ZHeader.dfBBmaxz);
426
293
    }
427
293
    return 0;
428
356
}
429
430
static int MMWriteZSection(VSILFILE *pF, struct MM_ZSection *pZSection)
431
186
{
432
186
    int32_t reservat4 = 0L;
433
434
186
    if (VSIFSeekL(pF, pZSection->ZSectionOffset, SEEK_SET))
435
0
        return 1;
436
437
186
    if (VSIFWriteL(&reservat4, 4, 1, pF) != 1)
438
0
        return 1;
439
186
    if (VSIFWriteL(&reservat4, 4, 1, pF) != 1)
440
0
        return 1;
441
186
    if (VSIFWriteL(&reservat4, 4, 1, pF) != 1)
442
0
        return 1;
443
186
    if (VSIFWriteL(&reservat4, 4, 1, pF) != 1)
444
0
        return 1;
445
446
186
    pZSection->ZSectionOffset += 16;
447
448
186
    if (VSIFWriteL(&pZSection->ZHeader.dfBBminz,
449
186
                   sizeof(pZSection->ZHeader.dfBBminz), 1, pF) != 1)
450
0
        return 1;
451
186
    pZSection->ZSectionOffset += sizeof(pZSection->ZHeader.dfBBminz);
452
186
    if (VSIFWriteL(&pZSection->ZHeader.dfBBmaxz,
453
186
                   sizeof(pZSection->ZHeader.dfBBmaxz), 1, pF) != 1)
454
0
        return 1;
455
186
    pZSection->ZSectionOffset += sizeof(pZSection->ZHeader.dfBBmaxz);
456
186
    return 0;
457
186
}
458
459
int MMReadZDescriptionHeaders(struct MiraMonVectLayerInfo *hMiraMonLayer,
460
                              VSILFILE *pF, MM_INTERNAL_FID nElements,
461
                              struct MM_ZSection *pZSection)
462
293
{
463
293
    struct MM_FLUSH_INFO FlushTMP;
464
293
    char *pBuffer = nullptr;
465
293
    MM_INTERNAL_FID nIndex = 0;
466
293
    MM_FILE_OFFSET nBlockSize;
467
293
    struct MM_ZD *pZDescription;
468
469
293
    if (!hMiraMonLayer)
470
0
        return 1;
471
472
293
    if (!pZSection)
473
0
        return 1;
474
475
293
    if (!nElements)
476
2
        return 0;  // No elements to read
477
478
291
    pZDescription = pZSection->pZDescription;
479
480
291
    nBlockSize = nElements * pZSection->nZDDiskSize;
481
482
291
    if (MMInitFlush(&FlushTMP, pF, nBlockSize, &pBuffer,
483
291
                    pZSection->ZSectionOffset, 0))
484
0
    {
485
0
        if (pBuffer)
486
0
            VSIFree(pBuffer);
487
0
        return 1;
488
0
    }
489
490
291
    FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
491
291
    if (MMReadFlush(&FlushTMP))
492
13
    {
493
13
        if (pBuffer)
494
13
            VSIFree(pBuffer);
495
13
        return 1;
496
13
    }
497
498
9.00k
    for (nIndex = 0; nIndex < nElements; nIndex++)
499
8.72k
    {
500
8.72k
        FlushTMP.SizeOfBlockToBeSaved =
501
8.72k
            sizeof((pZDescription + nIndex)->dfBBminz);
502
8.72k
        FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->dfBBminz;
503
8.72k
        if (MMReadBlockFromBuffer(&FlushTMP))
504
0
        {
505
0
            if (pBuffer)
506
0
                VSIFree(pBuffer);
507
0
            return 1;
508
0
        }
509
510
8.72k
        FlushTMP.SizeOfBlockToBeSaved =
511
8.72k
            sizeof((pZDescription + nIndex)->dfBBmaxz);
512
8.72k
        FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->dfBBmaxz;
513
8.72k
        if (MMReadBlockFromBuffer(&FlushTMP))
514
0
        {
515
0
            if (pBuffer)
516
0
                VSIFree(pBuffer);
517
0
            return 1;
518
0
        }
519
520
8.72k
        FlushTMP.SizeOfBlockToBeSaved =
521
8.72k
            sizeof((pZDescription + nIndex)->nZCount);
522
8.72k
        FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->nZCount;
523
8.72k
        if (MMReadBlockFromBuffer(&FlushTMP))
524
0
        {
525
0
            if (pBuffer)
526
0
                VSIFree(pBuffer);
527
0
            return 1;
528
0
        }
529
530
8.72k
        if (hMiraMonLayer->LayerVersion == MM_64BITS_VERSION)
531
5.76k
        {
532
5.76k
            FlushTMP.SizeOfBlockToBeSaved = 4;
533
5.76k
            FlushTMP.pBlockToBeSaved = (void *)nullptr;
534
5.76k
            if (MMReadBlockFromBuffer(&FlushTMP))
535
0
            {
536
0
                if (pBuffer)
537
0
                    VSIFree(pBuffer);
538
0
                return 1;
539
0
            }
540
5.76k
        }
541
542
8.72k
        if (MMReadOffsetDependingOnVersion(hMiraMonLayer, &FlushTMP,
543
8.72k
                                           &(pZDescription + nIndex)->nOffsetZ))
544
0
        {
545
0
            if (pBuffer)
546
0
                VSIFree(pBuffer);
547
0
            return 1;
548
0
        }
549
8.72k
    }
550
278
    if (pBuffer)
551
278
        VSIFree(pBuffer);
552
553
278
    return 0;
554
278
}
555
556
static int
557
MMWriteZDescriptionHeaders(struct MiraMonVectLayerInfo *hMiraMonLayer,
558
                           VSILFILE *pF, MM_INTERNAL_FID nElements,
559
                           struct MM_ZSection *pZSection)
560
186
{
561
186
    struct MM_FLUSH_INFO FlushTMP;
562
186
    char *pBuffer = nullptr;
563
186
    uint32_t nUL32;
564
186
    MM_INTERNAL_FID nIndex = 0;
565
186
    MM_FILE_OFFSET nOffsetDiff;
566
186
    struct MM_ZD *pZDescription;
567
568
186
    if (!hMiraMonLayer)
569
0
        return 1;
570
571
186
    if (!pF)
572
0
        return 1;
573
574
186
    if (!pZSection)
575
0
        return 1;
576
577
186
    pZDescription = pZSection->pZDescription;
578
579
186
    nOffsetDiff =
580
186
        pZSection->ZSectionOffset + nElements * pZSection->nZDDiskSize;
581
582
186
    if (MMInitFlush(&FlushTMP, pF, MM_1MB, &pBuffer, pZSection->ZSectionOffset,
583
186
                    0))
584
0
    {
585
0
        if (pBuffer)
586
0
            VSIFree(pBuffer);
587
0
        return 1;
588
0
    }
589
590
186
    FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
591
2.13k
    for (nIndex = 0; nIndex < nElements; nIndex++)
592
1.94k
    {
593
1.94k
        FlushTMP.SizeOfBlockToBeSaved =
594
1.94k
            sizeof((pZDescription + nIndex)->dfBBminz);
595
1.94k
        FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->dfBBminz;
596
1.94k
        if (MMAppendBlockToBuffer(&FlushTMP))
597
0
        {
598
0
            if (pBuffer)
599
0
                VSIFree(pBuffer);
600
0
            return 1;
601
0
        }
602
603
1.94k
        FlushTMP.SizeOfBlockToBeSaved =
604
1.94k
            sizeof((pZDescription + nIndex)->dfBBmaxz);
605
1.94k
        FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->dfBBmaxz;
606
1.94k
        if (MMAppendBlockToBuffer(&FlushTMP))
607
0
        {
608
0
            if (pBuffer)
609
0
                VSIFree(pBuffer);
610
0
            return 1;
611
0
        }
612
613
1.94k
        FlushTMP.SizeOfBlockToBeSaved =
614
1.94k
            sizeof((pZDescription + nIndex)->nZCount);
615
1.94k
        FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->nZCount;
616
1.94k
        if (MMAppendBlockToBuffer(&FlushTMP))
617
0
        {
618
0
            if (pBuffer)
619
0
                VSIFree(pBuffer);
620
0
            return 1;
621
0
        }
622
623
1.94k
        if (hMiraMonLayer->LayerVersion == MM_64BITS_VERSION)
624
0
        {
625
0
            FlushTMP.SizeOfBlockToBeSaved = 4;
626
0
            FlushTMP.pBlockToBeSaved = (void *)nullptr;
627
0
            if (MMAppendBlockToBuffer(&FlushTMP))
628
0
            {
629
0
                if (pBuffer)
630
0
                    VSIFree(pBuffer);
631
0
                return 1;
632
0
            }
633
0
        }
634
635
        // Overflow?
636
1.94k
        if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION &&
637
1.94k
            (pZDescription + nIndex)->nOffsetZ >
638
1.94k
                MAXIMUM_OFFSET_IN_2GB_VECTORS - nOffsetDiff)
639
0
        {
640
0
            CPLError(CE_Failure, CPLE_OpenFailed, "Offset Overflow in V1.1");
641
0
            return 1;
642
0
        }
643
644
1.94k
        if (MMAppendIntegerDependingOnVersion(
645
1.94k
                hMiraMonLayer, &FlushTMP, &nUL32,
646
1.94k
                (pZDescription + nIndex)->nOffsetZ + nOffsetDiff))
647
0
        {
648
0
            if (pBuffer)
649
0
                VSIFree(pBuffer);
650
0
            return 1;
651
0
        }
652
1.94k
    }
653
186
    FlushTMP.SizeOfBlockToBeSaved = 0;
654
186
    if (MMAppendBlockToBuffer(&FlushTMP))
655
0
    {
656
0
        if (pBuffer)
657
0
            VSIFree(pBuffer);
658
0
        return 1;
659
0
    }
660
186
    pZSection->ZSectionOffset += FlushTMP.TotalSavedBytes;
661
662
186
    if (pBuffer)
663
186
        VSIFree(pBuffer);
664
665
186
    return 0;
666
186
}
667
668
static void MMDestroyZSectionDescription(struct MM_ZSection *pZSection)
669
5.78k
{
670
5.78k
    if (pZSection->pZL)
671
654
    {
672
654
        VSIFree(pZSection->pZL);
673
654
        pZSection->pZL = nullptr;
674
654
    }
675
676
5.78k
    if (pZSection->pZDescription)
677
1.01k
    {
678
1.01k
        VSIFree(pZSection->pZDescription);
679
1.01k
        pZSection->pZDescription = nullptr;
680
1.01k
    }
681
5.78k
}
682
683
static int MMInitZSectionDescription(struct MM_ZSection *pZSection)
684
1.01k
{
685
1.01k
    if (MMCheckSize_t(pZSection->nMaxZDescription,
686
1.01k
                      sizeof(*pZSection->pZDescription)))
687
0
        return 1;
688
689
1.01k
    if (!pZSection->nMaxZDescription)
690
5
    {
691
5
        pZSection->pZDescription = nullptr;
692
5
        return 0;  // No elements to read (or write)
693
5
    }
694
695
1.01k
    pZSection->pZDescription = (struct MM_ZD *)VSICalloc(
696
1.01k
        (size_t)pZSection->nMaxZDescription, sizeof(*pZSection->pZDescription));
697
1.01k
    if (!pZSection->pZDescription)
698
0
        return 1;
699
1.01k
    return 0;
700
1.01k
}
701
702
static int MMInitZSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer,
703
                               VSILFILE *pF3d, struct MM_ZSection *pZSection)
704
1.01k
{
705
1.01k
    if (!hMiraMonLayer)
706
0
        return 1;
707
708
    // Zsection
709
1.01k
    if (!hMiraMonLayer->TopHeader.bIs3d)
710
0
    {
711
0
        pZSection->pZDescription = nullptr;
712
0
        return 0;
713
0
    }
714
715
1.01k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
716
654
    {
717
654
        pZSection->ZHeader.dfBBminz = STATISTICAL_UNDEF_VALUE;
718
654
        pZSection->ZHeader.dfBBmaxz = -STATISTICAL_UNDEF_VALUE;
719
654
    }
720
721
    // ZH
722
1.01k
    pZSection->ZHeader.nMyDiskSize = 32;
723
1.01k
    pZSection->ZSectionOffset = 0;
724
725
    // ZD
726
1.01k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
727
654
    {
728
654
        pZSection->nMaxZDescription =
729
654
            MM_FIRST_NUMBER_OF_VERTICES * sizeof(double);
730
654
        if (MMInitZSectionDescription(pZSection))
731
0
            return 1;
732
654
    }
733
363
    else
734
363
    {
735
363
        if (hMiraMonLayer->bIsPolygon)
736
162
        {
737
162
            if (MMCheckSize_t(hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount,
738
162
                              sizeof(double)))
739
0
                return 1;
740
741
162
            pZSection->nMaxZDescription =
742
162
                hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount *
743
162
                sizeof(double);
744
162
        }
745
201
        else
746
201
        {
747
201
            if (MMCheckSize_t(hMiraMonLayer->TopHeader.nElemCount,
748
201
                              sizeof(double)))
749
0
                return 1;
750
751
201
            pZSection->nMaxZDescription =
752
201
                hMiraMonLayer->TopHeader.nElemCount * sizeof(double);
753
201
        }
754
363
        if (MMInitZSectionDescription(pZSection))
755
0
            return 1;
756
363
    }
757
758
1.01k
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
759
912
        pZSection->nZDDiskSize = MM_SIZE_OF_ZD_32_BITS;
760
105
    else
761
105
        pZSection->nZDDiskSize = MM_SIZE_OF_ZD_64_BITS;
762
763
1.01k
    pZSection->ZDOffset = 0;
764
765
    // ZL
766
1.01k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
767
654
    {
768
654
        if (MMInitFlush(&pZSection->FlushZL, pF3d, MM_1MB, &pZSection->pZL, 0,
769
654
                        sizeof(double)))
770
0
            return 1;
771
654
    }
772
1.01k
    return 0;
773
1.01k
}
774
775
/* -------------------------------------------------------------------- */
776
/*      Layer Functions: Extensions                                     */
777
/* -------------------------------------------------------------------- */
778
779
/* Find the last occurrence of pszFinalPart in pszName
780
    and changes it by pszNewPart.
781
782
    Examples of desired behavior
783
    AA.pnt -> AAT.rel
784
    AA.nod -> N.~idx
785
    AA.nod -> N.dbf
786
    AA.nod -> N.rel
787
*/
788
789
static int MMChangeFinalPartOfTheName(char *pszName, size_t nMaxSizeOfName,
790
                                      const char *pszFinalPart,
791
                                      const char *pszNewPart)
792
11.3k
{
793
11.3k
    char *pAux, *pszWhereToFind, *pszLastFound = nullptr;
794
11.3k
    ;
795
796
11.3k
    if (!pszName || !pszFinalPart || !pszNewPart)
797
0
        return 0;
798
11.3k
    if (MMIsEmptyString(pszName) || MMIsEmptyString(pszFinalPart) ||
799
11.3k
        MMIsEmptyString(pszNewPart))
800
0
        return 0;
801
802
11.3k
    if (strlen(pszName) - strlen(pszFinalPart) + strlen(pszNewPart) >=
803
11.3k
        nMaxSizeOfName)
804
0
        return 1;  // It's not possible to change the final part
805
806
    // It's the implementation on windows of the linux strrstr()
807
    // pszLastFound = strrstr(pszWhereToFind, pszFinalPart);
808
11.3k
    pszWhereToFind = pszName;
809
22.6k
    while (nullptr != (pAux = MM_stristr(pszWhereToFind, pszFinalPart)))
810
11.3k
    {
811
11.3k
        pszLastFound = pAux;
812
11.3k
        pszWhereToFind = pAux + strlen(pAux);
813
11.3k
    }
814
815
11.3k
    if (!pszLastFound)
816
2
        return 1;  // Not found not changed
817
818
11.3k
    memcpy(pszLastFound, pszNewPart, strlen(pszNewPart));
819
820
11.3k
    return 0;
821
11.3k
}
822
823
/* -------------------------------------------------------------------- */
824
/*      Layer Functions: initializing MiraMon layers                    */
825
/* -------------------------------------------------------------------- */
826
static int MMInitPointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
827
679
{
828
679
    if (!hMiraMonLayer)
829
0
        return 1;
830
831
679
    hMiraMonLayer->bIsPoint = 1;
832
833
679
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
834
285
    {
835
        // Geometrical part
836
        // Init header structure
837
285
        hMiraMonLayer->TopHeader.nElemCount = 0;
838
285
        MMInitBoundingBox(&hMiraMonLayer->TopHeader.hBB);
839
840
285
        hMiraMonLayer->TopHeader.bIs3d = 1;  // Read description of bRealIs3d
841
285
        hMiraMonLayer->TopHeader.aFileType[0] = 'P';
842
285
        hMiraMonLayer->TopHeader.aFileType[1] = 'N';
843
285
        hMiraMonLayer->TopHeader.aFileType[2] = 'T';
844
845
        // Opening the binary file where sections TH, TL[...] and ZH-ZD[...]-ZL[...]
846
        // are going to be written.
847
848
285
        snprintf(hMiraMonLayer->MMPoint.pszLayerName,
849
285
                 sizeof(hMiraMonLayer->MMPoint.pszLayerName), "%s.pnt",
850
285
                 hMiraMonLayer->pszSrcLayerName);
851
285
    }
852
679
    if (nullptr == (hMiraMonLayer->MMPoint.pF =
853
679
                        VSIFOpenL(hMiraMonLayer->MMPoint.pszLayerName,
854
679
                                  hMiraMonLayer->pszFlags)))
855
0
    {
856
0
        CPLError(CE_Failure, CPLE_OpenFailed,
857
0
                 "Error MMPoint.pF: Cannot open file %s.",
858
0
                 hMiraMonLayer->MMPoint.pszLayerName);
859
0
        return 1;
860
0
    }
861
679
    VSIFSeekL(hMiraMonLayer->MMPoint.pF, 0, SEEK_SET);
862
863
679
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
864
285
    {
865
        // TL
866
285
        snprintf(hMiraMonLayer->MMPoint.pszTLName,
867
285
                 sizeof(hMiraMonLayer->MMPoint.pszTLName), "%sT.~xy",
868
285
                 hMiraMonLayer->pszSrcLayerName);
869
870
285
        if (nullptr == (hMiraMonLayer->MMPoint.pFTL =
871
285
                            VSIFOpenL(hMiraMonLayer->MMPoint.pszTLName,
872
285
                                      hMiraMonLayer->pszFlags)))
873
0
        {
874
0
            CPLError(CE_Failure, CPLE_OpenFailed,
875
0
                     "Error MMPoint.pFTL: Cannot open file %s.",
876
0
                     hMiraMonLayer->MMPoint.pszTLName);
877
0
            return 1;
878
0
        }
879
285
        VSIFSeekL(hMiraMonLayer->MMPoint.pFTL, 0, SEEK_SET);
880
881
285
        if (MMInitFlush(&hMiraMonLayer->MMPoint.FlushTL,
882
285
                        hMiraMonLayer->MMPoint.pFTL, MM_1MB,
883
285
                        &hMiraMonLayer->MMPoint.pTL, 0, MM_SIZE_OF_TL))
884
0
            return 1;
885
886
        // 3D part
887
285
        if (hMiraMonLayer->TopHeader.bIs3d)
888
285
        {
889
285
            snprintf(hMiraMonLayer->MMPoint.psz3DLayerName,
890
285
                     sizeof(hMiraMonLayer->MMPoint.psz3DLayerName), "%sT.~z",
891
285
                     hMiraMonLayer->pszSrcLayerName);
892
893
285
            if (nullptr == (hMiraMonLayer->MMPoint.pF3d =
894
285
                                VSIFOpenL(hMiraMonLayer->MMPoint.psz3DLayerName,
895
285
                                          hMiraMonLayer->pszFlags)))
896
0
            {
897
0
                CPLError(CE_Failure, CPLE_OpenFailed,
898
0
                         "Error MMPoint.pF3d: Cannot open file %s.",
899
0
                         hMiraMonLayer->MMPoint.psz3DLayerName);
900
0
                return 1;
901
0
            }
902
285
            VSIFSeekL(hMiraMonLayer->MMPoint.pF3d, 0, SEEK_SET);
903
285
        }
904
285
    }
905
    // Zsection
906
679
    if (hMiraMonLayer->TopHeader.bIs3d)
907
386
    {
908
386
        if (MMInitZSectionLayer(hMiraMonLayer, hMiraMonLayer->MMPoint.pF3d,
909
386
                                &hMiraMonLayer->MMPoint.pZSection))
910
0
            return 1;
911
912
386
        if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
913
101
        {
914
101
            if (MMReadZSection(hMiraMonLayer, hMiraMonLayer->MMPoint.pF,
915
101
                               &hMiraMonLayer->MMPoint.pZSection))
916
9
                return 1;
917
918
92
            if (MMReadZDescriptionHeaders(hMiraMonLayer,
919
92
                                          hMiraMonLayer->MMPoint.pF,
920
92
                                          hMiraMonLayer->TopHeader.nElemCount,
921
92
                                          &hMiraMonLayer->MMPoint.pZSection))
922
13
                return 1;
923
92
        }
924
386
    }
925
926
    // MiraMon metadata
927
657
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
928
285
    {
929
285
        snprintf(hMiraMonLayer->MMPoint.pszREL_LayerName,
930
285
                 sizeof(hMiraMonLayer->MMPoint.pszREL_LayerName), "%sT.rel",
931
285
                 hMiraMonLayer->pszSrcLayerName);
932
285
    }
933
372
    else
934
372
    {
935
372
        CPLStrlcpy(hMiraMonLayer->MMPoint.pszREL_LayerName,
936
372
                   hMiraMonLayer->pszSrcLayerName,
937
372
                   sizeof(hMiraMonLayer->MMPoint.pszREL_LayerName));
938
372
        if (MMChangeFinalPartOfTheName(hMiraMonLayer->MMPoint.pszREL_LayerName,
939
372
                                       MM_CPL_PATH_BUF_SIZE, ".pnt", "T.rel"))
940
1
            return 1;
941
372
    }
942
943
656
    hMiraMonLayer->pszMainREL_LayerName =
944
656
        hMiraMonLayer->MMPoint.pszREL_LayerName;
945
946
656
    if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
947
371
    {
948
        // This file has to exist and be the appropriate version.
949
371
        if (MMCheck_REL_FILE(hMiraMonLayer->MMPoint.pszREL_LayerName))
950
6
            return 1;
951
371
    }
952
953
    // MIRAMON DATA BASE
954
    // Creating the DBF file name
955
650
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
956
285
    {
957
285
        snprintf(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName,
958
285
                 sizeof(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName),
959
285
                 "%sT.dbf", hMiraMonLayer->pszSrcLayerName);
960
285
    }
961
365
    else
962
365
    {
963
365
        CPLStrlcpy(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName,
964
365
                   hMiraMonLayer->pszSrcLayerName,
965
365
                   sizeof(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName));
966
967
365
        if (MMChangeFinalPartOfTheName(
968
365
                hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName,
969
365
                MM_CPL_PATH_BUF_SIZE, ".pnt", "T.dbf"))
970
0
            return 1;
971
365
    }
972
973
650
    if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
974
365
    {
975
365
        if (MM_ReadExtendedDBFHeader(hMiraMonLayer))
976
24
            return 1;
977
365
    }
978
979
626
    return 0;
980
650
}
981
982
static int MMInitNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
983
866
{
984
866
    struct MiraMonArcLayer *pMMArcLayer;
985
986
866
    if (!hMiraMonLayer)
987
0
        return 1;
988
989
866
    if (hMiraMonLayer->bIsPolygon)
990
422
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
991
444
    else
992
444
        pMMArcLayer = &hMiraMonLayer->MMArc;
993
994
866
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
995
369
    {
996
        // Init header structure
997
369
        pMMArcLayer->TopNodeHeader.aFileType[0] = 'N';
998
369
        pMMArcLayer->TopNodeHeader.aFileType[1] = 'O';
999
369
        pMMArcLayer->TopNodeHeader.aFileType[2] = 'D';
1000
1001
369
        pMMArcLayer->TopNodeHeader.bIs3d = 1;  // Read description of bRealIs3d
1002
369
        MMInitBoundingBox(&pMMArcLayer->TopNodeHeader.hBB);
1003
369
    }
1004
1005
    // Opening the binary file where sections TH, NH and NL[...]
1006
    // are going to be written.
1007
866
    strcpy(pMMArcLayer->MMNode.pszLayerName, pMMArcLayer->pszLayerName);
1008
866
    CPLStrlcpy(pMMArcLayer->MMNode.pszLayerName,
1009
866
               CPLResetExtension(pMMArcLayer->MMNode.pszLayerName, "nod"),
1010
866
               sizeof(pMMArcLayer->MMNode.pszLayerName));
1011
1012
866
    if (nullptr ==
1013
866
        (pMMArcLayer->MMNode.pF = VSIFOpenL(pMMArcLayer->MMNode.pszLayerName,
1014
866
                                            hMiraMonLayer->pszFlags)))
1015
2
    {
1016
1017
2
        CPLError(CE_Failure, CPLE_OpenFailed,
1018
2
                 "Error MMNode.pF: Cannot open file %s.",
1019
2
                 pMMArcLayer->MMNode.pszLayerName);
1020
2
        return 1;
1021
2
    }
1022
864
    VSIFSeekL(pMMArcLayer->MMNode.pF, 0, SEEK_SET);
1023
1024
864
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1025
369
    {
1026
        // Node Header
1027
369
        pMMArcLayer->MMNode.nMaxNodeHeader = MM_FIRST_NUMBER_OF_NODES;
1028
369
        if (MMCheckSize_t(pMMArcLayer->MMNode.nMaxNodeHeader,
1029
369
                          sizeof(*pMMArcLayer->MMNode.pNodeHeader)))
1030
0
            return 1;
1031
1032
369
        if (!pMMArcLayer->MMNode.nMaxNodeHeader)
1033
0
        {
1034
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
1035
0
                     "Error in MiraMon "
1036
0
                     "driver: no nodes to write?");
1037
0
            return 1;
1038
0
        }
1039
1040
369
        if (nullptr ==
1041
369
            (pMMArcLayer->MMNode.pNodeHeader = (struct MM_NH *)VSICalloc(
1042
369
                 (size_t)pMMArcLayer->MMNode.nMaxNodeHeader,
1043
369
                 sizeof(*pMMArcLayer->MMNode.pNodeHeader))))
1044
0
        {
1045
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
1046
0
                     "Memory error in MiraMon "
1047
0
                     "driver (MMInitNodeLayer())");
1048
0
            return 1;
1049
0
        }
1050
1051
369
        if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
1052
369
            pMMArcLayer->MMNode.nSizeNodeHeader = MM_SIZE_OF_NH_32BITS;
1053
0
        else
1054
0
            pMMArcLayer->MMNode.nSizeNodeHeader = MM_SIZE_OF_NH_64BITS;
1055
1056
        // NL Section
1057
369
        strcpy(pMMArcLayer->MMNode.pszNLName, pMMArcLayer->MMNode.pszLayerName);
1058
369
        if (MMChangeFinalPartOfTheName(pMMArcLayer->MMNode.pszNLName,
1059
369
                                       MM_CPL_PATH_BUF_SIZE, ".nod", "N.~idx"))
1060
0
            return 1;
1061
1062
369
        if (nullptr ==
1063
369
            (pMMArcLayer->MMNode.pFNL = VSIFOpenL(pMMArcLayer->MMNode.pszNLName,
1064
369
                                                  hMiraMonLayer->pszFlags)))
1065
0
        {
1066
1067
0
            CPLError(CE_Failure, CPLE_OpenFailed,
1068
0
                     "Error MMNode.pFNL: Cannot open file %s.",
1069
0
                     pMMArcLayer->MMNode.pszNLName);
1070
0
            return 1;
1071
0
        }
1072
369
        VSIFSeekL(pMMArcLayer->MMNode.pFNL, 0, SEEK_SET);
1073
1074
369
        if (MMInitFlush(&pMMArcLayer->MMNode.FlushNL, pMMArcLayer->MMNode.pFNL,
1075
369
                        MM_1MB, &pMMArcLayer->MMNode.pNL, 0, 0))
1076
0
            return 1;
1077
1078
        // Creating the DBF file name
1079
369
        strcpy(pMMArcLayer->MMNode.MMAdmDB.pszExtDBFLayerName,
1080
369
               pMMArcLayer->MMNode.pszLayerName);
1081
369
        if (MMChangeFinalPartOfTheName(
1082
369
                pMMArcLayer->MMNode.MMAdmDB.pszExtDBFLayerName,
1083
369
                MM_CPL_PATH_BUF_SIZE, ".nod", "N.dbf"))
1084
0
            return 1;
1085
1086
        // MiraMon metadata
1087
369
        strcpy(pMMArcLayer->MMNode.pszREL_LayerName,
1088
369
               pMMArcLayer->MMNode.pszLayerName);
1089
369
        if (MMChangeFinalPartOfTheName(pMMArcLayer->MMNode.pszREL_LayerName,
1090
369
                                       MM_CPL_PATH_BUF_SIZE, ".nod", "N.rel"))
1091
0
            return 1;
1092
369
    }
1093
864
    return 0;
1094
864
}
1095
1096
static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
1097
970
{
1098
970
    struct MiraMonArcLayer *pMMArcLayer;
1099
970
    struct MM_TH *pArcTopHeader;
1100
1101
970
    if (!hMiraMonLayer)
1102
0
        return 1;
1103
1104
970
    if (hMiraMonLayer->bIsPolygon)
1105
457
    {
1106
457
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
1107
457
        pArcTopHeader = &hMiraMonLayer->MMPolygon.TopArcHeader;
1108
457
    }
1109
513
    else
1110
513
    {
1111
513
        pMMArcLayer = &hMiraMonLayer->MMArc;
1112
513
        pArcTopHeader = &hMiraMonLayer->TopHeader;
1113
513
    }
1114
1115
    // Init header structure
1116
970
    hMiraMonLayer->bIsArc = 1;
1117
1118
970
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1119
369
    {
1120
369
        pArcTopHeader->bIs3d = 1;  // Read description of bRealIs3d
1121
369
        MMInitBoundingBox(&pArcTopHeader->hBB);
1122
1123
369
        pArcTopHeader->aFileType[0] = 'A';
1124
369
        pArcTopHeader->aFileType[1] = 'R';
1125
369
        pArcTopHeader->aFileType[2] = 'C';
1126
1127
369
        if (hMiraMonLayer->bIsPolygon)
1128
157
        {
1129
157
            snprintf(pMMArcLayer->pszLayerName,
1130
157
                     sizeof(pMMArcLayer->pszLayerName), "%s_bound.arc",
1131
157
                     hMiraMonLayer->pszSrcLayerName);
1132
157
        }
1133
212
        else
1134
212
        {
1135
212
            snprintf(pMMArcLayer->pszLayerName,
1136
212
                     sizeof(pMMArcLayer->pszLayerName), "%s.arc",
1137
212
                     hMiraMonLayer->pszSrcLayerName);
1138
212
        }
1139
369
    }
1140
1141
970
    if (nullptr == (pMMArcLayer->pF = VSIFOpenL(pMMArcLayer->pszLayerName,
1142
970
                                                hMiraMonLayer->pszFlags)))
1143
0
    {
1144
0
        CPLError(CE_Failure, CPLE_OpenFailed,
1145
0
                 "Error pMMArcLayer->pF: Cannot open file %s.",
1146
0
                 pMMArcLayer->pszLayerName);
1147
0
        return 1;
1148
0
    }
1149
1150
970
    if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE &&
1151
601
        hMiraMonLayer->bIsPolygon)
1152
300
    {
1153
300
        VSIFSeekL(pMMArcLayer->pF, 0, SEEK_SET);
1154
300
        if (MMReadHeader(pMMArcLayer->pF,
1155
300
                         &hMiraMonLayer->MMPolygon.TopArcHeader))
1156
0
        {
1157
0
            CPLError(CE_Failure, CPLE_NotSupported,
1158
0
                     "Error reading the format in file %s.",
1159
0
                     pMMArcLayer->pszLayerName);
1160
0
            return 1;
1161
0
        }
1162
        // 3D information is in arcs file
1163
300
        hMiraMonLayer->TopHeader.bIs3d =
1164
300
            hMiraMonLayer->MMPolygon.TopArcHeader.bIs3d;
1165
300
    }
1166
1167
    // AH
1168
970
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
1169
719
        pMMArcLayer->nSizeArcHeader = MM_SIZE_OF_AH_32BITS;
1170
251
    else
1171
251
        pMMArcLayer->nSizeArcHeader = MM_SIZE_OF_AH_64BITS;
1172
1173
970
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1174
369
        pMMArcLayer->nMaxArcHeader = MM_FIRST_NUMBER_OF_ARCS;
1175
601
    else
1176
601
        pMMArcLayer->nMaxArcHeader = pArcTopHeader->nElemCount;
1177
1178
970
    if (pMMArcLayer->nMaxArcHeader)
1179
934
    {
1180
934
        if (MMCheckSize_t(pMMArcLayer->nMaxArcHeader,
1181
934
                          sizeof(*pMMArcLayer->pArcHeader)))
1182
5
            return 1;
1183
929
        if (nullptr == (pMMArcLayer->pArcHeader = (struct MM_AH *)VSICalloc(
1184
929
                            (size_t)pMMArcLayer->nMaxArcHeader,
1185
929
                            sizeof(*pMMArcLayer->pArcHeader))))
1186
0
        {
1187
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
1188
0
                     "Memory error in MiraMon "
1189
0
                     "driver (MMInitArcLayer())");
1190
0
            return 1;
1191
0
        }
1192
929
        if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
1193
560
        {
1194
560
            if (MMReadAHArcSection(hMiraMonLayer))
1195
9
            {
1196
9
                CPLError(CE_Failure, CPLE_NotSupported,
1197
9
                         "Error reading the format in file %s.",
1198
9
                         pMMArcLayer->pszLayerName);
1199
9
                return 1;
1200
9
            }
1201
560
        }
1202
929
    }
1203
36
    else
1204
36
        pMMArcLayer->pArcHeader = nullptr;
1205
1206
    // AL
1207
956
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1208
369
    {
1209
369
        pMMArcLayer->nALElementSize = MM_SIZE_OF_AL;
1210
1211
369
        if (hMiraMonLayer->bIsPolygon)
1212
157
        {
1213
157
            snprintf(pMMArcLayer->pszALName, sizeof(pMMArcLayer->pszALName),
1214
157
                     "%s_boundA.~xy", hMiraMonLayer->pszSrcLayerName);
1215
157
        }
1216
212
        else
1217
212
        {
1218
212
            snprintf(pMMArcLayer->pszALName, sizeof(pMMArcLayer->pszALName),
1219
212
                     "%sA.~xy", hMiraMonLayer->pszSrcLayerName);
1220
212
        }
1221
1222
369
        if (nullptr == (pMMArcLayer->pFAL = VSIFOpenL(pMMArcLayer->pszALName,
1223
369
                                                      hMiraMonLayer->pszFlags)))
1224
0
        {
1225
0
            CPLError(CE_Failure, CPLE_OpenFailed,
1226
0
                     "Error pMMArcLayer->pFAL: Cannot open file %s.",
1227
0
                     pMMArcLayer->pszALName);
1228
0
            return 1;
1229
0
        }
1230
369
        VSIFSeekL(pMMArcLayer->pFAL, 0, SEEK_SET);
1231
1232
369
        if (MMInitFlush(&pMMArcLayer->FlushAL, pMMArcLayer->pFAL, MM_1MB,
1233
369
                        &pMMArcLayer->pAL, 0, 0))
1234
0
            return 1;
1235
369
    }
1236
1237
    // 3D
1238
956
    if (pArcTopHeader->bIs3d)
1239
631
    {
1240
631
        if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1241
369
        {
1242
369
            if (hMiraMonLayer->bIsPolygon)
1243
157
            {
1244
157
                snprintf(pMMArcLayer->psz3DLayerName,
1245
157
                         sizeof(pMMArcLayer->psz3DLayerName), "%s_boundA.~z",
1246
157
                         hMiraMonLayer->pszSrcLayerName);
1247
157
            }
1248
212
            else
1249
212
            {
1250
212
                snprintf(pMMArcLayer->psz3DLayerName,
1251
212
                         sizeof(pMMArcLayer->psz3DLayerName), "%sA.~z",
1252
212
                         hMiraMonLayer->pszSrcLayerName);
1253
212
            }
1254
1255
369
            if (nullptr ==
1256
369
                (pMMArcLayer->pF3d = VSIFOpenL(pMMArcLayer->psz3DLayerName,
1257
369
                                               hMiraMonLayer->pszFlags)))
1258
0
            {
1259
0
                CPLError(CE_Failure, CPLE_OpenFailed,
1260
0
                         "Error pMMArcLayer->pF3d: Cannot open file %s.",
1261
0
                         pMMArcLayer->psz3DLayerName);
1262
0
                return 1;
1263
0
            }
1264
369
            VSIFSeekL(pMMArcLayer->pF3d, 0, SEEK_SET);
1265
369
        }
1266
1267
631
        if (MMInitZSectionLayer(hMiraMonLayer, pMMArcLayer->pF3d,
1268
631
                                &pMMArcLayer->pZSection))
1269
0
        {
1270
0
            CPLError(CE_Failure, CPLE_NotSupported,
1271
0
                     "Error reading the format in file %s %d.",
1272
0
                     pMMArcLayer->pszLayerName, 6);
1273
0
            return 1;
1274
0
        }
1275
1276
631
        if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
1277
262
        {
1278
262
            if (MMReadZSection(hMiraMonLayer, pMMArcLayer->pF,
1279
262
                               &pMMArcLayer->pZSection))
1280
61
            {
1281
61
                CPLError(CE_Failure, CPLE_NotSupported,
1282
61
                         "Error reading the format in file %s.",
1283
61
                         pMMArcLayer->pszLayerName);
1284
61
                return 1;
1285
61
            }
1286
1287
201
            if (MMReadZDescriptionHeaders(hMiraMonLayer, pMMArcLayer->pF,
1288
201
                                          pArcTopHeader->nElemCount,
1289
201
                                          &pMMArcLayer->pZSection))
1290
0
            {
1291
0
                CPLError(CE_Failure, CPLE_NotSupported,
1292
0
                         "Error reading the format in file %s.",
1293
0
                         pMMArcLayer->pszLayerName);
1294
0
                return 1;
1295
0
            }
1296
201
        }
1297
631
    }
1298
    // MiraMon metadata
1299
895
    if (hMiraMonLayer->bIsPolygon)
1300
424
    {
1301
424
        if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1302
157
        {
1303
157
            snprintf(pMMArcLayer->pszREL_LayerName,
1304
157
                     sizeof(pMMArcLayer->pszREL_LayerName), "%s_boundA.rel",
1305
157
                     hMiraMonLayer->pszSrcLayerName);
1306
157
        }
1307
267
        else
1308
267
        {
1309
267
            strcpy(pMMArcLayer->pszREL_LayerName, pMMArcLayer->pszLayerName);
1310
267
            if (MMChangeFinalPartOfTheName(pMMArcLayer->pszREL_LayerName,
1311
267
                                           MM_CPL_PATH_BUF_SIZE, ".arc",
1312
267
                                           "A.rel"))
1313
0
                return 1;
1314
267
        }
1315
424
    }
1316
471
    else
1317
471
    {
1318
471
        if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1319
212
        {
1320
212
            snprintf(pMMArcLayer->pszREL_LayerName,
1321
212
                     sizeof(pMMArcLayer->pszREL_LayerName), "%sA.rel",
1322
212
                     hMiraMonLayer->pszSrcLayerName);
1323
212
        }
1324
259
        else
1325
259
        {
1326
259
            CPLStrlcpy(pMMArcLayer->pszREL_LayerName,
1327
259
                       hMiraMonLayer->pszSrcLayerName,
1328
259
                       sizeof(pMMArcLayer->pszREL_LayerName));
1329
259
            if (MMChangeFinalPartOfTheName(pMMArcLayer->pszREL_LayerName,
1330
259
                                           MM_CPL_PATH_BUF_SIZE, ".arc",
1331
259
                                           "A.rel"))
1332
1
                return 1;
1333
259
        }
1334
471
    }
1335
1336
894
    if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
1337
525
    {
1338
        // This file has to exist and be the appropriate version.
1339
525
        if (MMCheck_REL_FILE(pMMArcLayer->pszREL_LayerName))
1340
4
            return 1;
1341
525
    }
1342
1343
890
    if (!hMiraMonLayer->bIsPolygon)
1344
468
        hMiraMonLayer->pszMainREL_LayerName = pMMArcLayer->pszREL_LayerName;
1345
1346
    // MIRAMON DATA BASE
1347
    // Creating the DBF file name
1348
890
    if (hMiraMonLayer->bIsPolygon)
1349
422
    {
1350
422
        if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1351
157
        {
1352
157
            snprintf(pMMArcLayer->MMAdmDB.pszExtDBFLayerName,
1353
157
                     sizeof(pMMArcLayer->MMAdmDB.pszExtDBFLayerName),
1354
157
                     "%s_boundA.dbf", hMiraMonLayer->pszSrcLayerName);
1355
157
        }
1356
265
        else
1357
265
        {
1358
265
            strcpy(pMMArcLayer->MMAdmDB.pszExtDBFLayerName,
1359
265
                   pMMArcLayer->pszLayerName);
1360
265
            if (MMChangeFinalPartOfTheName(
1361
265
                    pMMArcLayer->MMAdmDB.pszExtDBFLayerName,
1362
265
                    MM_CPL_PATH_BUF_SIZE, ".arc", "A.dbf"))
1363
0
                return 1;
1364
265
        }
1365
422
    }
1366
468
    else
1367
468
    {
1368
468
        if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1369
212
        {
1370
212
            snprintf(pMMArcLayer->MMAdmDB.pszExtDBFLayerName,
1371
212
                     sizeof(pMMArcLayer->MMAdmDB.pszExtDBFLayerName), "%sA.dbf",
1372
212
                     hMiraMonLayer->pszSrcLayerName);
1373
212
        }
1374
256
        else
1375
256
        {
1376
256
            CPLStrlcpy(pMMArcLayer->MMAdmDB.pszExtDBFLayerName,
1377
256
                       hMiraMonLayer->pszSrcLayerName,
1378
256
                       sizeof(pMMArcLayer->MMAdmDB.pszExtDBFLayerName));
1379
256
            if (MMChangeFinalPartOfTheName(
1380
256
                    pMMArcLayer->MMAdmDB.pszExtDBFLayerName,
1381
256
                    MM_CPL_PATH_BUF_SIZE, ".arc", "A.dbf"))
1382
0
                return 1;
1383
256
        }
1384
468
    }
1385
1386
890
    if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
1387
521
    {
1388
521
        if (MM_ReadExtendedDBFHeader(hMiraMonLayer))
1389
24
            return 1;
1390
521
    }
1391
1392
    // Node part
1393
866
    if (MMInitNodeLayer(hMiraMonLayer))
1394
2
        return 1;
1395
864
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
1396
664
        MMSet1_1Version(&pMMArcLayer->TopNodeHeader);
1397
200
    else
1398
200
        MMSet2_0Version(&pMMArcLayer->TopNodeHeader);
1399
1400
864
    return 0;
1401
866
}
1402
1403
static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
1404
4.41k
{
1405
4.41k
    struct MiraMonPolygonLayer *pMMPolygonLayer;
1406
1407
4.41k
    if (!hMiraMonLayer)
1408
0
        return 1;
1409
1410
4.41k
    pMMPolygonLayer = &hMiraMonLayer->MMPolygon;
1411
1412
    // Init header structure
1413
4.41k
    hMiraMonLayer->bIsPolygon = 1;
1414
1415
4.41k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1416
157
    {
1417
157
        hMiraMonLayer->TopHeader.bIs3d = 1;  // Read description of bRealIs3d
1418
157
        MMInitBoundingBox(&hMiraMonLayer->TopHeader.hBB);
1419
1420
157
        hMiraMonLayer->TopHeader.aFileType[0] = 'P';
1421
157
        hMiraMonLayer->TopHeader.aFileType[1] = 'O';
1422
157
        hMiraMonLayer->TopHeader.aFileType[2] = 'L';
1423
1424
157
        snprintf(pMMPolygonLayer->pszLayerName,
1425
157
                 sizeof(pMMPolygonLayer->pszLayerName), "%s.pol",
1426
157
                 hMiraMonLayer->pszSrcLayerName);
1427
157
    }
1428
1429
4.41k
    if (nullptr ==
1430
4.41k
        (pMMPolygonLayer->pF =
1431
4.41k
             VSIFOpenL(pMMPolygonLayer->pszLayerName, hMiraMonLayer->pszFlags)))
1432
0
    {
1433
0
        CPLError(CE_Failure, CPLE_OpenFailed,
1434
0
                 "Error pMMPolygonLayer->pF: Cannot open file %s.",
1435
0
                 pMMPolygonLayer->pszLayerName);
1436
0
        return 1;
1437
0
    }
1438
1439
    // PS
1440
4.41k
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
1441
3.28k
        pMMPolygonLayer->nPSElementSize = MM_SIZE_OF_PS_32BITS;
1442
1.12k
    else
1443
1.12k
        pMMPolygonLayer->nPSElementSize = MM_SIZE_OF_PS_64BITS;
1444
1445
4.41k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1446
157
    {
1447
157
        snprintf(pMMPolygonLayer->pszPSName, sizeof(pMMPolygonLayer->pszPSName),
1448
157
                 "%sP.~PS", hMiraMonLayer->pszSrcLayerName);
1449
1450
157
        if (nullptr ==
1451
157
            (pMMPolygonLayer->pFPS = VSIFOpenL(pMMPolygonLayer->pszPSName,
1452
157
                                               hMiraMonLayer->pszFlags)))
1453
0
        {
1454
0
            CPLError(CE_Failure, CPLE_OpenFailed,
1455
0
                     "Error pMMPolygonLayer->pFPS: Cannot open file %s.",
1456
0
                     pMMPolygonLayer->pszPSName);
1457
0
            return 1;
1458
0
        }
1459
157
        VSIFSeekL(pMMPolygonLayer->pFPS, 0, SEEK_SET);
1460
1461
157
        if (MMInitFlush(&pMMPolygonLayer->FlushPS, pMMPolygonLayer->pFPS,
1462
157
                        MM_1MB, &pMMPolygonLayer->pPS, 0,
1463
157
                        pMMPolygonLayer->nPSElementSize))
1464
0
            return 1;
1465
157
    }
1466
1467
    // PH
1468
4.41k
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
1469
3.28k
        pMMPolygonLayer->nPHElementSize = MM_SIZE_OF_PH_32BITS;
1470
1.12k
    else
1471
1.12k
        pMMPolygonLayer->nPHElementSize = MM_SIZE_OF_PH_64BITS;
1472
1473
4.41k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1474
157
        pMMPolygonLayer->nMaxPolHeader = MM_FIRST_NUMBER_OF_POLYGONS + 1;
1475
4.26k
    else
1476
4.26k
        pMMPolygonLayer->nMaxPolHeader = hMiraMonLayer->TopHeader.nElemCount;
1477
1478
4.41k
    if (pMMPolygonLayer->nMaxPolHeader)
1479
4.06k
    {
1480
4.06k
        if (MMCheckSize_t(pMMPolygonLayer->nMaxPolHeader,
1481
4.06k
                          sizeof(*pMMPolygonLayer->pPolHeader)))
1482
18
            return 1;
1483
4.04k
        if (nullptr == (pMMPolygonLayer->pPolHeader = (struct MM_PH *)VSICalloc(
1484
4.04k
                            (size_t)pMMPolygonLayer->nMaxPolHeader,
1485
4.04k
                            sizeof(*pMMPolygonLayer->pPolHeader))))
1486
0
        {
1487
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
1488
0
                     "Memory error in MiraMon "
1489
0
                     "driver (MMInitPolygonLayer())");
1490
0
            return 1;
1491
0
        }
1492
4.04k
    }
1493
353
    else
1494
353
        pMMPolygonLayer->pPolHeader = nullptr;
1495
1496
    // PAL
1497
4.39k
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
1498
3.27k
        pMMPolygonLayer->nPALElementSize = MM_SIZE_OF_PAL_32BITS;
1499
1.12k
    else
1500
1.12k
        pMMPolygonLayer->nPALElementSize = MM_SIZE_OF_PAL_64BITS;
1501
1502
4.39k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1503
157
    {
1504
        // Universal polygon.
1505
157
        memset(pMMPolygonLayer->pPolHeader, 0,
1506
157
               sizeof(*pMMPolygonLayer->pPolHeader));
1507
157
        hMiraMonLayer->TopHeader.nElemCount = 1;
1508
1509
        // PAL
1510
157
        snprintf(pMMPolygonLayer->pszPALName,
1511
157
                 sizeof(pMMPolygonLayer->pszPALName), "%sP.~idx",
1512
157
                 hMiraMonLayer->pszSrcLayerName);
1513
1514
157
        if (nullptr ==
1515
157
            (pMMPolygonLayer->pFPAL = VSIFOpenL(pMMPolygonLayer->pszPALName,
1516
157
                                                hMiraMonLayer->pszFlags)))
1517
0
        {
1518
0
            CPLError(CE_Failure, CPLE_OpenFailed,
1519
0
                     "Error pMMPolygonLayer->pFPAL: Cannot open file %s.",
1520
0
                     pMMPolygonLayer->pszPALName);
1521
0
            return 1;
1522
0
        }
1523
157
        VSIFSeekL(pMMPolygonLayer->pFPAL, 0, SEEK_SET);
1524
1525
157
        if (MMInitFlush(&pMMPolygonLayer->FlushPAL, pMMPolygonLayer->pFPAL,
1526
157
                        MM_1MB, &pMMPolygonLayer->pPAL, 0, 0))
1527
0
            return 1;
1528
157
    }
1529
1530
    // MiraMon metadata
1531
1532
4.39k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1533
157
    {
1534
157
        snprintf(hMiraMonLayer->MMPolygon.pszREL_LayerName,
1535
157
                 sizeof(hMiraMonLayer->MMPolygon.pszREL_LayerName), "%sP.rel",
1536
157
                 hMiraMonLayer->pszSrcLayerName);
1537
157
    }
1538
4.24k
    else
1539
4.24k
    {
1540
4.24k
        CPLStrlcpy(hMiraMonLayer->MMPolygon.pszREL_LayerName,
1541
4.24k
                   hMiraMonLayer->pszSrcLayerName,
1542
4.24k
                   sizeof(hMiraMonLayer->MMPolygon.pszREL_LayerName));
1543
1544
4.24k
        if (MMChangeFinalPartOfTheName(
1545
4.24k
                hMiraMonLayer->MMPolygon.pszREL_LayerName, MM_CPL_PATH_BUF_SIZE,
1546
4.24k
                ".pol", "P.rel"))
1547
0
            return 1;
1548
4.24k
    }
1549
1550
4.39k
    if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
1551
4.24k
    {
1552
        // This file has to exist and be the appropriate version.
1553
4.24k
        if (MMCheck_REL_FILE(hMiraMonLayer->MMPolygon.pszREL_LayerName))
1554
37
            return 1;
1555
4.24k
    }
1556
1557
4.36k
    hMiraMonLayer->pszMainREL_LayerName =
1558
4.36k
        hMiraMonLayer->MMPolygon.pszREL_LayerName;
1559
1560
    // MIRAMON DATA BASE
1561
4.36k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1562
157
    {
1563
157
        snprintf(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName,
1564
157
                 sizeof(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName), "%sP.dbf",
1565
157
                 hMiraMonLayer->pszSrcLayerName);
1566
157
    }
1567
4.20k
    else
1568
4.20k
    {
1569
4.20k
        CPLStrlcpy(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName,
1570
4.20k
                   hMiraMonLayer->pszSrcLayerName,
1571
4.20k
                   sizeof(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName));
1572
4.20k
        if (MMChangeFinalPartOfTheName(
1573
4.20k
                pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName,
1574
4.20k
                MM_CPL_PATH_BUF_SIZE, ".pol", "P.dbf"))
1575
0
            return 1;
1576
4.20k
    }
1577
1578
4.36k
    if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
1579
4.20k
    {
1580
4.20k
        if (MM_ReadExtendedDBFHeader(hMiraMonLayer))
1581
36
            return 1;
1582
4.20k
    }
1583
1584
4.32k
    return 0;
1585
4.36k
}
1586
1587
// The map file must be written in ANSI encoding; therefore, some
1588
// conversions are performed for strings that may originally
1589
// be in UTF-8.
1590
1591
int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer)
1592
7.68k
{
1593
7.68k
    char *pszSrcLayerNameCP1252;
1594
1595
7.68k
    if (!hMiraMonLayer)
1596
0
        return 1;
1597
1598
7.68k
    pszSrcLayerNameCP1252 = CPLRecode(
1599
7.68k
        CPLGetBasename(hMiraMonLayer->pszSrcLayerName), CPL_ENC_UTF8, "CP1252");
1600
1601
7.68k
    if (hMiraMonLayer->eLT == MM_LayerType_Point ||
1602
7.18k
        hMiraMonLayer->eLT == MM_LayerType_Point3d)
1603
679
    {
1604
679
        if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1605
285
        {
1606
285
            snprintf(hMiraMonLayer->MMPoint.pszLayerName,
1607
285
                     sizeof(hMiraMonLayer->MMPoint.pszLayerName), "%s.pnt",
1608
285
                     hMiraMonLayer->pszSrcLayerName);
1609
285
        }
1610
394
        else
1611
394
        {
1612
394
            CPLStrlcpy(hMiraMonLayer->MMPoint.pszLayerName,
1613
394
                       hMiraMonLayer->pszSrcLayerName,
1614
394
                       sizeof(hMiraMonLayer->MMPoint.pszLayerName));
1615
394
        }
1616
679
        if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap)
1617
0
        {
1618
1619
0
            hMiraMonLayer->MMMap->nNumberOfLayers++;
1620
0
            VSIFPrintfL(hMiraMonLayer->MMMap->fMMMap, "[VECTOR_%d]\n",
1621
0
                        hMiraMonLayer->MMMap->nNumberOfLayers);
1622
1623
0
            VSIFPrintfL(hMiraMonLayer->MMMap->fMMMap, "Fitxer=%s.pnt\n",
1624
0
                        pszSrcLayerNameCP1252
1625
0
                            ? pszSrcLayerNameCP1252
1626
0
                            : CPLGetBasename(hMiraMonLayer->pszSrcLayerName));
1627
0
        }
1628
1629
679
        if (MMInitPointLayer(hMiraMonLayer))
1630
53
        {
1631
            // Error specified inside the function
1632
53
            CPLFree(pszSrcLayerNameCP1252);
1633
53
            return 1;
1634
53
        }
1635
626
        CPLFree(pszSrcLayerNameCP1252);
1636
626
        return 0;
1637
679
    }
1638
7.00k
    if (hMiraMonLayer->eLT == MM_LayerType_Arc ||
1639
6.62k
        hMiraMonLayer->eLT == MM_LayerType_Arc3d)
1640
513
    {
1641
513
        struct MiraMonArcLayer *pMMArcLayer = &hMiraMonLayer->MMArc;
1642
1643
513
        if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1644
212
        {
1645
212
            snprintf(pMMArcLayer->pszLayerName,
1646
212
                     sizeof(pMMArcLayer->pszLayerName), "%s.arc",
1647
212
                     hMiraMonLayer->pszSrcLayerName);
1648
212
        }
1649
301
        else
1650
301
        {
1651
301
            CPLStrlcpy(pMMArcLayer->pszLayerName,
1652
301
                       hMiraMonLayer->pszSrcLayerName,
1653
301
                       sizeof(pMMArcLayer->pszLayerName));
1654
301
        }
1655
1656
513
        if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap)
1657
0
        {
1658
0
            hMiraMonLayer->MMMap->nNumberOfLayers++;
1659
0
            VSIFPrintfL(hMiraMonLayer->MMMap->fMMMap, "[VECTOR_%d]\n",
1660
0
                        hMiraMonLayer->MMMap->nNumberOfLayers);
1661
0
            VSIFPrintfL(hMiraMonLayer->MMMap->fMMMap, "Fitxer=%s.arc\n",
1662
0
                        pszSrcLayerNameCP1252
1663
0
                            ? pszSrcLayerNameCP1252
1664
0
                            : CPLGetBasename(hMiraMonLayer->pszSrcLayerName));
1665
0
        }
1666
1667
513
        if (MMInitArcLayer(hMiraMonLayer))
1668
71
        {
1669
            // Error specified inside the function
1670
71
            CPLFree(pszSrcLayerNameCP1252);
1671
71
            return 1;
1672
71
        }
1673
442
        CPLFree(pszSrcLayerNameCP1252);
1674
442
        return 0;
1675
513
    }
1676
6.48k
    if (hMiraMonLayer->eLT == MM_LayerType_Pol ||
1677
3.87k
        hMiraMonLayer->eLT == MM_LayerType_Pol3d)
1678
4.41k
    {
1679
4.41k
        struct MiraMonPolygonLayer *pMMPolygonLayer = &hMiraMonLayer->MMPolygon;
1680
1681
4.41k
        if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1682
157
        {
1683
157
            snprintf(pMMPolygonLayer->pszLayerName,
1684
157
                     sizeof(pMMPolygonLayer->pszLayerName), "%s.pol",
1685
157
                     hMiraMonLayer->pszSrcLayerName);
1686
157
        }
1687
4.26k
        else
1688
4.26k
        {
1689
4.26k
            CPLStrlcpy(pMMPolygonLayer->pszLayerName,
1690
4.26k
                       hMiraMonLayer->pszSrcLayerName,
1691
4.26k
                       sizeof(pMMPolygonLayer->pszLayerName));
1692
4.26k
        }
1693
1694
4.41k
        if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap)
1695
0
        {
1696
0
            hMiraMonLayer->MMMap->nNumberOfLayers++;
1697
0
            VSIFPrintfL(hMiraMonLayer->MMMap->fMMMap, "[VECTOR_%d]\n",
1698
0
                        hMiraMonLayer->MMMap->nNumberOfLayers);
1699
0
            VSIFPrintfL(hMiraMonLayer->MMMap->fMMMap, "Fitxer=%s.pol\n",
1700
0
                        pszSrcLayerNameCP1252
1701
0
                            ? pszSrcLayerNameCP1252
1702
0
                            : CPLGetBasename(hMiraMonLayer->pszSrcLayerName));
1703
0
        }
1704
1705
4.41k
        if (MMInitPolygonLayer(hMiraMonLayer))
1706
91
        {
1707
            // Error specified inside the function
1708
91
            CPLFree(pszSrcLayerNameCP1252);
1709
91
            return 1;
1710
91
        }
1711
1712
4.32k
        if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE)
1713
4.16k
        {
1714
4.16k
            char *pszArcLayerName;
1715
4.16k
            const char *pszExt;
1716
            // StringLine associated to the polygon
1717
4.16k
            pszArcLayerName = MMReturnValueFromSectionINIFile(
1718
4.16k
                pMMPolygonLayer->pszREL_LayerName,
1719
4.16k
                SECTION_OVVW_ASPECTES_TECNICS, KEY_ArcSource);
1720
4.16k
            if (pszArcLayerName)
1721
4.14k
            {
1722
4.14k
                MM_RemoveInitial_and_FinalQuotationMarks(pszArcLayerName);
1723
1724
                // If extension is not specified ".arc" will be used
1725
4.14k
                pszExt = CPLGetExtension(pszArcLayerName);
1726
4.14k
                if (MMIsEmptyString(pszExt))
1727
2.58k
                {
1728
2.58k
                    char *pszArcLayerNameAux =
1729
2.58k
                        VSICalloc(1, strlen(pszArcLayerName) + 5);
1730
2.58k
                    if (!pszArcLayerNameAux)
1731
0
                    {
1732
0
                        CPLError(CE_Failure, CPLE_OutOfMemory,
1733
0
                                 "Memory error in MiraMon "
1734
0
                                 "driver (MMInitLayerByType())");
1735
0
                        VSIFree(pszArcLayerName);
1736
0
                        CPLFree(pszSrcLayerNameCP1252);
1737
0
                        return 1;
1738
0
                    }
1739
2.58k
                    snprintf(pszArcLayerNameAux, strlen(pszArcLayerName) + 5,
1740
2.58k
                             "%s.arc", pszArcLayerName);
1741
1742
2.58k
                    VSIFree(pszArcLayerName);
1743
2.58k
                    pszArcLayerName = pszArcLayerNameAux;
1744
2.58k
                }
1745
1746
4.14k
                CPLStrlcpy(
1747
4.14k
                    pMMPolygonLayer->MMArc.pszLayerName,
1748
4.14k
                    CPLFormFilename(CPLGetPath(hMiraMonLayer->pszSrcLayerName),
1749
4.14k
                                    pszArcLayerName, ""),
1750
4.14k
                    sizeof(pMMPolygonLayer->MMArc.pszLayerName));
1751
1752
4.14k
                VSIFree(pszArcLayerName);
1753
4.14k
            }
1754
22
            else
1755
22
            {
1756
                // There is no arc layer on the metada file
1757
22
                CPLError(CE_Failure, CPLE_OpenFailed,
1758
22
                         "Error reading the ARC file in the metadata file %s.",
1759
22
                         pMMPolygonLayer->pszREL_LayerName);
1760
22
                CPLFree(pszSrcLayerNameCP1252);
1761
22
                return 1;
1762
22
            }
1763
1764
4.14k
            if (nullptr == (hMiraMonLayer->MMPolygon.MMArc.pF =
1765
4.14k
                                VSIFOpenL(pMMPolygonLayer->MMArc.pszLayerName,
1766
4.14k
                                          hMiraMonLayer->pszFlags)))
1767
3.81k
            {
1768
3.81k
                CPLError(CE_Failure, CPLE_OpenFailed,
1769
3.81k
                         "Error pMMPolygonLayer.MMArc.pF: Cannot open file %s.",
1770
3.81k
                         pMMPolygonLayer->MMArc.pszLayerName);
1771
3.81k
                CPLFree(pszSrcLayerNameCP1252);
1772
3.81k
                return 1;
1773
3.81k
            }
1774
1775
329
            if (MMReadHeader(hMiraMonLayer->MMPolygon.MMArc.pF,
1776
329
                             &hMiraMonLayer->MMPolygon.TopArcHeader))
1777
3
            {
1778
3
                CPLError(CE_Failure, CPLE_NotSupported,
1779
3
                         "Error reading the format in file %s.",
1780
3
                         pMMPolygonLayer->MMArc.pszLayerName);
1781
3
                CPLFree(pszSrcLayerNameCP1252);
1782
3
                return 1;
1783
3
            }
1784
1785
326
            if (MMReadPHPolygonSection(hMiraMonLayer))
1786
26
            {
1787
26
                CPLError(CE_Failure, CPLE_NotSupported,
1788
26
                         "Error reading the format in file %s.",
1789
26
                         pMMPolygonLayer->MMArc.pszLayerName);
1790
26
                CPLFree(pszSrcLayerNameCP1252);
1791
26
                return 1;
1792
26
            }
1793
1794
300
            fclose_and_nullify(&hMiraMonLayer->MMPolygon.MMArc.pF);
1795
300
        }
1796
157
        else
1797
157
        {
1798
            // Creating the stringLine file associated to the polygon
1799
157
            snprintf(pMMPolygonLayer->MMArc.pszLayerName,
1800
157
                     sizeof(pMMPolygonLayer->MMArc.pszLayerName), "%s.arc",
1801
157
                     hMiraMonLayer->pszSrcLayerName);
1802
157
        }
1803
1804
457
        if (MMInitArcLayer(hMiraMonLayer))
1805
35
        {
1806
            // Error specified inside the function
1807
35
            CPLFree(pszSrcLayerNameCP1252);
1808
35
            return 1;
1809
35
        }
1810
1811
        // Polygon is 3D if Arc is 3D, by definition.
1812
422
        hMiraMonLayer->TopHeader.bIs3d =
1813
422
            hMiraMonLayer->MMPolygon.TopArcHeader.bIs3d;
1814
1815
422
        if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
1816
357
            MMSet1_1Version(&pMMPolygonLayer->TopArcHeader);
1817
65
        else
1818
65
            MMSet2_0Version(&pMMPolygonLayer->TopArcHeader);
1819
422
    }
1820
2.07k
    else if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1821
2.07k
    {
1822
        // Trying to get DBF information
1823
2.07k
        snprintf(hMiraMonLayer->MMAdmDBWriting.pszExtDBFLayerName,
1824
2.07k
                 sizeof(hMiraMonLayer->MMAdmDBWriting.pszExtDBFLayerName),
1825
2.07k
                 "%s.dbf", hMiraMonLayer->pszSrcLayerName);
1826
2.07k
    }
1827
1828
2.49k
    CPLFree(pszSrcLayerNameCP1252);
1829
2.49k
    return 0;
1830
6.48k
}
1831
1832
int MMInitLayer(struct MiraMonVectLayerInfo *hMiraMonLayer,
1833
                const char *pzFileName, int LayerVersion, char nMMRecode,
1834
                char nMMLanguage, struct MiraMonDataBase *pLayerDB,
1835
                MM_BOOLEAN ReadOrWrite, struct MiraMonVectMapInfo *MMMap)
1836
12.0k
{
1837
12.0k
    if (!hMiraMonLayer)
1838
0
        return 1;
1839
1840
    // Some variables must be initialized
1841
12.0k
    MM_FillFieldDescriptorByLanguage();
1842
1843
12.0k
    memset(hMiraMonLayer, 0, sizeof(*hMiraMonLayer));
1844
1845
    //hMiraMonLayer->Version = MM_VECTOR_LAYER_LAST_VERSION;
1846
1847
12.0k
    hMiraMonLayer->ReadOrWrite = ReadOrWrite;
1848
12.0k
    hMiraMonLayer->MMMap = MMMap;
1849
1850
    // Don't free in destructor
1851
12.0k
    hMiraMonLayer->pLayerDB = pLayerDB;
1852
1853
    // Opening mode
1854
12.0k
    strcpy(hMiraMonLayer->pszFlags, "wb+");
1855
1856
12.0k
    if (LayerVersion == MM_UNKNOWN_VERSION)
1857
0
    {
1858
0
        CPLError(CE_Failure, CPLE_NotSupported,
1859
0
                 "Unknown version in MiraMon driver.");
1860
0
        return 1;
1861
0
    }
1862
12.0k
    if (LayerVersion == MM_LAST_VERSION)
1863
0
    {
1864
0
        MMSet1_1Version(&hMiraMonLayer->TopHeader);
1865
0
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
1866
0
        hMiraMonLayer->LayerVersion = MM_64BITS_VERSION;
1867
0
    }
1868
12.0k
    else if (LayerVersion == MM_32BITS_VERSION)
1869
12.0k
    {
1870
12.0k
        MMSet1_1Version(&hMiraMonLayer->TopHeader);
1871
12.0k
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_32_BITS;
1872
12.0k
        hMiraMonLayer->LayerVersion = MM_32BITS_VERSION;
1873
12.0k
    }
1874
0
    else
1875
0
    {
1876
0
        MMSet2_0Version(&hMiraMonLayer->TopHeader);
1877
0
        hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS;
1878
0
        hMiraMonLayer->LayerVersion = MM_64BITS_VERSION;
1879
0
    }
1880
1881
12.0k
    hMiraMonLayer->pszSrcLayerName = CPLStrdup(pzFileName);
1882
12.0k
    hMiraMonLayer->szLayerTitle = CPLStrdup(CPLGetFilename(pzFileName));
1883
1884
12.0k
    if (!hMiraMonLayer->bIsBeenInit &&
1885
12.0k
        hMiraMonLayer->eLT != MM_LayerType_Unknown)
1886
0
    {
1887
0
        if (MMInitLayerByType(hMiraMonLayer))
1888
0
        {
1889
            // Error specified inside the function
1890
0
            return 1;
1891
0
        }
1892
0
        hMiraMonLayer->bIsBeenInit = 1;
1893
0
    }
1894
1895
    // If more nNumStringToOperate is needed, it'll be increased.
1896
12.0k
    hMiraMonLayer->nNumStringToOperate = 0;
1897
12.0k
    if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, 500))
1898
0
    {
1899
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
1900
0
                 "Memory error in MiraMon "
1901
0
                 "driver (MMInitLayer())");
1902
0
        return 1;
1903
0
    }
1904
1905
12.0k
    hMiraMonLayer->nMMLanguage = nMMLanguage;
1906
1907
12.0k
    if (nMMRecode == MM_RECODE_UTF8)
1908
0
        hMiraMonLayer->nCharSet = MM_JOC_CARAC_UTF8_DBF;
1909
12.0k
    else  //if(nMMRecode==MM_RECODE_ANSI)
1910
12.0k
        hMiraMonLayer->nCharSet = MM_JOC_CARAC_ANSI_DBASE;
1911
12.0k
    return 0;
1912
12.0k
}
1913
1914
/* -------------------------------------------------------------------- */
1915
/*      Layer Functions: Closing MiraMon layers                         */
1916
/* -------------------------------------------------------------------- */
1917
static int MMClose3DSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer,
1918
                                 MM_INTERNAL_FID nElements, VSILFILE *pF,
1919
                                 VSILFILE **pF3d, const char *pszF3d,
1920
                                 struct MM_ZSection *pZSection,
1921
                                 MM_FILE_OFFSET FinalOffset)
1922
650
{
1923
650
    int ret_code = 1;
1924
650
    if (!hMiraMonLayer)
1925
0
        return 1;
1926
1927
    // Avoid closing when it has no sense. But it's not an error.
1928
    // Just return elegantly.
1929
650
    if (!pF || !pF3d || !(*pF3d) || !pszF3d || !pZSection)
1930
0
        return 0;
1931
1932
650
    if (hMiraMonLayer->bIsReal3d)
1933
186
    {
1934
186
        pZSection->ZSectionOffset = FinalOffset;
1935
186
        if (MMWriteZSection(pF, pZSection))
1936
0
            goto end_label;
1937
1938
        // Header 3D. Writes it after header
1939
186
        if (MMWriteZDescriptionHeaders(hMiraMonLayer, pF, nElements, pZSection))
1940
0
            goto end_label;
1941
1942
        // ZL section
1943
186
        pZSection->FlushZL.SizeOfBlockToBeSaved = 0;
1944
186
        if (MMAppendBlockToBuffer(&pZSection->FlushZL))
1945
0
            goto end_label;
1946
1947
186
        if (MMMoveFromFileToFile(*pF3d, pF, &pZSection->ZSectionOffset))
1948
0
            goto end_label;
1949
186
    }
1950
1951
650
    ret_code = 0;
1952
650
end_label:
1953
650
    fclose_and_nullify(pF3d);
1954
650
    if (pszF3d && *pszF3d != '\0')
1955
650
        VSIUnlink(pszF3d);
1956
1957
650
    return ret_code;
1958
650
}
1959
1960
static int MMClosePointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
1961
679
{
1962
679
    int ret_code = 1;
1963
679
    if (!hMiraMonLayer)
1964
0
        return 1;
1965
1966
679
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
1967
285
    {
1968
285
        hMiraMonLayer->nFinalElemCount = hMiraMonLayer->TopHeader.nElemCount;
1969
285
        hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d;
1970
1971
285
        if (MMWriteHeader(hMiraMonLayer->MMPoint.pF, &hMiraMonLayer->TopHeader))
1972
0
        {
1973
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
1974
0
                     hMiraMonLayer->MMPoint.pszLayerName);
1975
0
            goto end_label;
1976
0
        }
1977
285
        hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize;
1978
1979
        // TL Section
1980
285
        hMiraMonLayer->MMPoint.FlushTL.SizeOfBlockToBeSaved = 0;
1981
285
        if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL))
1982
0
        {
1983
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
1984
0
                     hMiraMonLayer->MMPoint.pszLayerName);
1985
0
            goto end_label;
1986
0
        }
1987
285
        if (MMMoveFromFileToFile(hMiraMonLayer->MMPoint.pFTL,
1988
285
                                 hMiraMonLayer->MMPoint.pF,
1989
285
                                 &hMiraMonLayer->OffsetCheck))
1990
0
        {
1991
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
1992
0
                     hMiraMonLayer->MMPoint.pszLayerName);
1993
0
            goto end_label;
1994
0
        }
1995
1996
285
        fclose_and_nullify(&hMiraMonLayer->MMPoint.pFTL);
1997
1998
285
        if (*hMiraMonLayer->MMPoint.pszTLName != '\0')
1999
285
            VSIUnlink(hMiraMonLayer->MMPoint.pszTLName);
2000
2001
285
        if (MMClose3DSectionLayer(
2002
285
                hMiraMonLayer, hMiraMonLayer->TopHeader.nElemCount,
2003
285
                hMiraMonLayer->MMPoint.pF, &hMiraMonLayer->MMPoint.pF3d,
2004
285
                hMiraMonLayer->MMPoint.psz3DLayerName,
2005
285
                &hMiraMonLayer->MMPoint.pZSection, hMiraMonLayer->OffsetCheck))
2006
0
        {
2007
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2008
0
                     hMiraMonLayer->MMPoint.pszLayerName);
2009
0
            goto end_label;
2010
0
        }
2011
285
    }
2012
2013
679
    ret_code = 0;
2014
679
end_label:
2015
679
    fclose_and_nullify(&hMiraMonLayer->MMPoint.pF);
2016
679
    fclose_and_nullify(&hMiraMonLayer->MMPoint.pF3d);
2017
679
    return ret_code;
2018
679
}
2019
2020
static int MMCloseNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2021
4.93k
{
2022
4.93k
    int ret_code = 1;
2023
4.93k
    struct MiraMonArcLayer *pMMArcLayer;
2024
2025
4.93k
    if (!hMiraMonLayer)
2026
0
        return 1;
2027
2028
4.93k
    if (hMiraMonLayer->bIsPolygon)
2029
4.41k
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
2030
513
    else
2031
513
        pMMArcLayer = &hMiraMonLayer->MMArc;
2032
2033
4.93k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
2034
369
    {
2035
369
        hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d;
2036
2037
369
        if (MMWriteHeader(pMMArcLayer->MMNode.pF, &pMMArcLayer->TopNodeHeader))
2038
4
            goto end_label;
2039
365
        hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize;
2040
2041
        // NH Section
2042
365
        if (MMWriteNHNodeSection(hMiraMonLayer, hMiraMonLayer->nHeaderDiskSize))
2043
0
            goto end_label;
2044
2045
        // NL Section
2046
365
        pMMArcLayer->MMNode.FlushNL.SizeOfBlockToBeSaved = 0;
2047
365
        if (MMAppendBlockToBuffer(&pMMArcLayer->MMNode.FlushNL))
2048
0
            goto end_label;
2049
365
        if (MMMoveFromFileToFile(pMMArcLayer->MMNode.pFNL,
2050
365
                                 pMMArcLayer->MMNode.pF,
2051
365
                                 &hMiraMonLayer->OffsetCheck))
2052
0
            goto end_label;
2053
2054
365
        fclose_and_nullify(&pMMArcLayer->MMNode.pFNL);
2055
365
        if (*pMMArcLayer->MMNode.pszNLName != '\0')
2056
365
            VSIUnlink(pMMArcLayer->MMNode.pszNLName);
2057
365
    }
2058
2059
4.92k
    ret_code = 0;
2060
4.93k
end_label:
2061
4.93k
    fclose_and_nullify(&pMMArcLayer->MMNode.pFNL);
2062
2063
4.93k
    fclose_and_nullify(&pMMArcLayer->MMNode.pF);
2064
2065
4.93k
    return ret_code;
2066
4.92k
}
2067
2068
static int MMCloseArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2069
4.93k
{
2070
4.93k
    int ret_code = 0;
2071
4.93k
    struct MiraMonArcLayer *pMMArcLayer;
2072
4.93k
    struct MM_TH *pArcTopHeader;
2073
2074
4.93k
    if (!hMiraMonLayer)
2075
0
        return 1;
2076
2077
4.93k
    if (hMiraMonLayer->bIsPolygon)
2078
4.41k
    {
2079
4.41k
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
2080
4.41k
        pArcTopHeader = &hMiraMonLayer->MMPolygon.TopArcHeader;
2081
4.41k
    }
2082
513
    else
2083
513
    {
2084
513
        pMMArcLayer = &hMiraMonLayer->MMArc;
2085
513
        pArcTopHeader = &hMiraMonLayer->TopHeader;
2086
513
    }
2087
2088
4.93k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
2089
369
    {
2090
369
        hMiraMonLayer->nFinalElemCount = pArcTopHeader->nElemCount;
2091
369
        pArcTopHeader->bIs3d = hMiraMonLayer->bIsReal3d;
2092
2093
369
        if (MMWriteHeader(pMMArcLayer->pF, pArcTopHeader))
2094
4
        {
2095
4
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2096
4
                     pMMArcLayer->pszLayerName);
2097
4
            goto end_label;
2098
4
        }
2099
365
        hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize;
2100
2101
        // AH Section
2102
365
        if (MMWriteAHArcSection(hMiraMonLayer, hMiraMonLayer->OffsetCheck))
2103
0
        {
2104
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2105
0
                     pMMArcLayer->pszLayerName);
2106
0
            goto end_label;
2107
0
        }
2108
2109
        // AL Section
2110
365
        pMMArcLayer->FlushAL.SizeOfBlockToBeSaved = 0;
2111
365
        if (MMAppendBlockToBuffer(&pMMArcLayer->FlushAL))
2112
0
        {
2113
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2114
0
                     pMMArcLayer->pszLayerName);
2115
0
            goto end_label;
2116
0
        }
2117
365
        if (MMMoveFromFileToFile(pMMArcLayer->pFAL, pMMArcLayer->pF,
2118
365
                                 &hMiraMonLayer->OffsetCheck))
2119
0
        {
2120
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2121
0
                     pMMArcLayer->pszLayerName);
2122
0
            goto end_label;
2123
0
        }
2124
365
        fclose_and_nullify(&pMMArcLayer->pFAL);
2125
2126
365
        if (*pMMArcLayer->pszALName != '\0')
2127
365
            VSIUnlink(pMMArcLayer->pszALName);
2128
2129
        // 3D Section
2130
365
        if (MMClose3DSectionLayer(
2131
365
                hMiraMonLayer, pArcTopHeader->nElemCount, pMMArcLayer->pF,
2132
365
                &pMMArcLayer->pF3d, pMMArcLayer->psz3DLayerName,
2133
365
                &pMMArcLayer->pZSection, hMiraMonLayer->OffsetCheck))
2134
0
        {
2135
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2136
0
                     pMMArcLayer->pszLayerName);
2137
0
            goto end_label;
2138
0
        }
2139
365
    }
2140
2141
4.92k
    ret_code = 0;
2142
4.93k
end_label:
2143
4.93k
    fclose_and_nullify(&pMMArcLayer->pF);
2144
4.93k
    fclose_and_nullify(&pMMArcLayer->pF3d);
2145
2146
4.93k
    fclose_and_nullify(&pMMArcLayer->pFAL);
2147
2148
4.93k
    if (MMCloseNodeLayer(hMiraMonLayer))
2149
4
        ret_code = 1;
2150
2151
4.93k
    return ret_code;
2152
4.92k
}
2153
2154
static int MMClosePolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2155
4.41k
{
2156
4.41k
    int ret_code = 0;
2157
4.41k
    struct MiraMonPolygonLayer *pMMPolygonLayer;
2158
2159
4.41k
    if (!hMiraMonLayer)
2160
0
        return 1;
2161
2162
4.41k
    pMMPolygonLayer = &hMiraMonLayer->MMPolygon;
2163
2164
4.41k
    MMCloseArcLayer(hMiraMonLayer);
2165
2166
4.41k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
2167
157
    {
2168
157
        hMiraMonLayer->nFinalElemCount = hMiraMonLayer->TopHeader.nElemCount;
2169
157
        hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d;
2170
2171
157
        if (MMWriteHeader(pMMPolygonLayer->pF, &hMiraMonLayer->TopHeader))
2172
2
        {
2173
2
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2174
2
                     pMMPolygonLayer->pszLayerName);
2175
2
            goto end_label;
2176
2
        }
2177
155
        hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize;
2178
2179
        // PS Section
2180
155
        pMMPolygonLayer->FlushPS.SizeOfBlockToBeSaved = 0;
2181
155
        if (MMAppendBlockToBuffer(&pMMPolygonLayer->FlushPS))
2182
0
        {
2183
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2184
0
                     pMMPolygonLayer->pszLayerName);
2185
0
            goto end_label;
2186
0
        }
2187
155
        if (MMMoveFromFileToFile(pMMPolygonLayer->pFPS, pMMPolygonLayer->pF,
2188
155
                                 &hMiraMonLayer->OffsetCheck))
2189
0
        {
2190
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2191
0
                     pMMPolygonLayer->pszLayerName);
2192
0
            goto end_label;
2193
0
        }
2194
2195
155
        fclose_and_nullify(&pMMPolygonLayer->pFPS);
2196
155
        if (*pMMPolygonLayer->pszPSName != '\0')
2197
155
            VSIUnlink(pMMPolygonLayer->pszPSName);
2198
2199
        // AH Section
2200
155
        if (MMWritePHPolygonSection(hMiraMonLayer, hMiraMonLayer->OffsetCheck))
2201
0
        {
2202
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2203
0
                     pMMPolygonLayer->pszLayerName);
2204
0
            goto end_label;
2205
0
        }
2206
2207
        // PAL Section
2208
155
        pMMPolygonLayer->FlushPAL.SizeOfBlockToBeSaved = 0;
2209
155
        if (MMAppendBlockToBuffer(&pMMPolygonLayer->FlushPAL))
2210
0
        {
2211
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2212
0
                     pMMPolygonLayer->pszLayerName);
2213
0
            goto end_label;
2214
0
        }
2215
155
        if (MMMoveFromFileToFile(pMMPolygonLayer->pFPAL, pMMPolygonLayer->pF,
2216
155
                                 &hMiraMonLayer->OffsetCheck))
2217
0
        {
2218
0
            CPLError(CE_Failure, CPLE_NoWriteAccess, "Error writing to file %s",
2219
0
                     pMMPolygonLayer->pszLayerName);
2220
0
            goto end_label;
2221
0
        }
2222
155
        fclose_and_nullify(&pMMPolygonLayer->pFPAL);
2223
2224
155
        if (*pMMPolygonLayer->pszPALName != '\0')
2225
155
            VSIUnlink(pMMPolygonLayer->pszPALName);
2226
155
    }
2227
2228
4.41k
    ret_code = 0;
2229
2230
4.41k
end_label:
2231
4.41k
    fclose_and_nullify(&pMMPolygonLayer->pF);
2232
4.41k
    fclose_and_nullify(&pMMPolygonLayer->pFPS);
2233
4.41k
    fclose_and_nullify(&pMMPolygonLayer->pFPAL);
2234
2235
4.41k
    return ret_code;
2236
4.41k
}
2237
2238
int MMCloseLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2239
7.68k
{
2240
7.68k
    int ret_code = 0;
2241
    //CheckMMVectorLayerVersion(hMiraMonLayer, 1)
2242
2243
7.68k
    if (!hMiraMonLayer)
2244
0
        return 0;
2245
2246
7.68k
    if (hMiraMonLayer->bIsPoint)
2247
679
    {
2248
679
        ret_code = MMClosePointLayer(hMiraMonLayer);
2249
679
    }
2250
7.00k
    else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
2251
513
    {
2252
513
        ret_code = MMCloseArcLayer(hMiraMonLayer);
2253
513
    }
2254
6.49k
    else if (hMiraMonLayer->bIsPolygon)
2255
4.41k
    {
2256
4.41k
        ret_code = MMClosePolygonLayer(hMiraMonLayer);
2257
4.41k
    }
2258
2.07k
    else if (hMiraMonLayer->bIsDBF)
2259
2.07k
    {
2260
        // If no geometry, remove all created files
2261
2.07k
        if (hMiraMonLayer->pszSrcLayerName)
2262
2.07k
            VSIUnlink(hMiraMonLayer->pszSrcLayerName);
2263
2.07k
        if (hMiraMonLayer->szLayerTitle)
2264
2.07k
            VSIUnlink(hMiraMonLayer->szLayerTitle);
2265
2.07k
    }
2266
2267
    // MiraMon metadata files
2268
7.68k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
2269
2.72k
    {
2270
2.72k
        if (MMWriteVectorMetadata(hMiraMonLayer))
2271
0
        {
2272
0
            CPLError(CE_Failure, CPLE_NoWriteAccess,
2273
0
                     "Some error writing in metadata file of the layer");
2274
0
            ret_code = 1;
2275
0
        }
2276
2.72k
    }
2277
2278
    // MiraMon database files
2279
7.68k
    if (MMCloseMMBD_XP(hMiraMonLayer))
2280
176
    {
2281
176
        CPLError(CE_Failure, CPLE_NoWriteAccess,
2282
176
                 "Some error writing in DBF file of the layer");
2283
176
        ret_code = 1;
2284
176
    }
2285
7.68k
    return ret_code;
2286
7.68k
}
2287
2288
/* -------------------------------------------------------------------- */
2289
/*      Layer Functions: Destroying (allocated memory)                  */
2290
/* -------------------------------------------------------------------- */
2291
static void MMDestroyMMAdmDB(struct MMAdmDatabase *pMMAdmDB)
2292
15.2k
{
2293
15.2k
    if (pMMAdmDB->pRecList)
2294
756
    {
2295
756
        VSIFree(pMMAdmDB->pRecList);
2296
756
        pMMAdmDB->pRecList = nullptr;
2297
756
    }
2298
2299
15.2k
    if (pMMAdmDB->szRecordOnCourse)
2300
756
    {
2301
756
        VSIFree(pMMAdmDB->szRecordOnCourse);
2302
756
        pMMAdmDB->szRecordOnCourse = nullptr;
2303
756
        pMMAdmDB->nNumRecordOnCourse = 0;
2304
756
    }
2305
15.2k
}
2306
2307
static int MMDestroyPointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2308
764
{
2309
764
    if (!hMiraMonLayer)
2310
0
        return 1;
2311
2312
764
    if (hMiraMonLayer->MMPoint.pTL)
2313
285
    {
2314
285
        VSIFree(hMiraMonLayer->MMPoint.pTL);
2315
285
        hMiraMonLayer->MMPoint.pTL = nullptr;
2316
285
    }
2317
2318
764
    MMDestroyZSectionDescription(&hMiraMonLayer->MMPoint.pZSection);
2319
764
    MMDestroyMMAdmDB(&hMiraMonLayer->MMPoint.MMAdmDB);
2320
2321
764
    return 0;
2322
764
}
2323
2324
static int MMDestroyNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2325
5.02k
{
2326
5.02k
    struct MiraMonArcLayer *pMMArcLayer;
2327
2328
5.02k
    if (!hMiraMonLayer)
2329
0
        return 1;
2330
2331
5.02k
    if (hMiraMonLayer->bIsPolygon)
2332
4.45k
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
2333
568
    else
2334
568
        pMMArcLayer = &hMiraMonLayer->MMArc;
2335
2336
5.02k
    if (pMMArcLayer->MMNode.pNL)
2337
369
    {
2338
369
        VSIFree(pMMArcLayer->MMNode.pNL);
2339
369
        pMMArcLayer->MMNode.pNL = nullptr;
2340
369
    }
2341
2342
5.02k
    if (pMMArcLayer->MMNode.pNodeHeader)
2343
369
    {
2344
369
        VSIFree(pMMArcLayer->MMNode.pNodeHeader);
2345
369
        pMMArcLayer->MMNode.pNodeHeader = nullptr;
2346
369
    }
2347
2348
5.02k
    MMDestroyMMAdmDB(&hMiraMonLayer->MMArc.MMNode.MMAdmDB);
2349
5.02k
    return 0;
2350
5.02k
}
2351
2352
static int MMDestroyArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2353
5.02k
{
2354
5.02k
    struct MiraMonArcLayer *pMMArcLayer;
2355
2356
5.02k
    if (!hMiraMonLayer)
2357
0
        return 1;
2358
2359
5.02k
    if (hMiraMonLayer->bIsPolygon)
2360
4.45k
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
2361
568
    else
2362
568
        pMMArcLayer = &hMiraMonLayer->MMArc;
2363
2364
5.02k
    if (pMMArcLayer->pAL)
2365
369
    {
2366
369
        VSIFree(pMMArcLayer->pAL);
2367
369
        pMMArcLayer->pAL = nullptr;
2368
369
    }
2369
5.02k
    if (pMMArcLayer->pArcHeader)
2370
929
    {
2371
929
        VSIFree(pMMArcLayer->pArcHeader);
2372
929
        pMMArcLayer->pArcHeader = nullptr;
2373
929
    }
2374
2375
5.02k
    MMDestroyZSectionDescription(&pMMArcLayer->pZSection);
2376
5.02k
    MMDestroyMMAdmDB(&pMMArcLayer->MMAdmDB);
2377
2378
5.02k
    MMDestroyNodeLayer(hMiraMonLayer);
2379
5.02k
    return 0;
2380
5.02k
}
2381
2382
static int MMDestroyPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2383
4.45k
{
2384
4.45k
    struct MiraMonPolygonLayer *pMMPolygonLayer;
2385
2386
4.45k
    if (!hMiraMonLayer)
2387
0
        return 1;
2388
2389
4.45k
    pMMPolygonLayer = &hMiraMonLayer->MMPolygon;
2390
2391
4.45k
    MMDestroyArcLayer(hMiraMonLayer);
2392
2393
4.45k
    if (pMMPolygonLayer->pPAL)
2394
157
    {
2395
157
        VSIFree(pMMPolygonLayer->pPAL);
2396
157
        pMMPolygonLayer->pPAL = nullptr;
2397
157
    }
2398
2399
4.45k
    if (pMMPolygonLayer->pPS)
2400
157
    {
2401
157
        VSIFree(pMMPolygonLayer->pPS);
2402
157
        pMMPolygonLayer->pPS = nullptr;
2403
157
    }
2404
2405
4.45k
    if (pMMPolygonLayer->pPolHeader)
2406
4.04k
    {
2407
4.04k
        VSIFree(pMMPolygonLayer->pPolHeader);
2408
4.04k
        pMMPolygonLayer->pPolHeader = nullptr;
2409
4.04k
    }
2410
2411
4.45k
    MMDestroyMMAdmDB(&pMMPolygonLayer->MMAdmDB);
2412
2413
4.45k
    return 0;
2414
4.45k
}
2415
2416
int MMDestroyLayer(struct MiraMonVectLayerInfo *hMiraMonLayer)
2417
32.0k
{
2418
    //CheckMMVectorLayerVersion(hMiraMonLayer, 1)
2419
2420
32.0k
    if (!hMiraMonLayer)
2421
0
        return 1;
2422
2423
32.0k
    if (hMiraMonLayer->bIsPoint)
2424
764
        MMDestroyPointLayer(hMiraMonLayer);
2425
31.2k
    else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
2426
568
        MMDestroyArcLayer(hMiraMonLayer);
2427
30.7k
    else if (hMiraMonLayer->bIsPolygon)
2428
4.45k
        MMDestroyPolygonLayer(hMiraMonLayer);
2429
2430
32.0k
    if (hMiraMonLayer->pszSrcLayerName)
2431
16.9k
    {
2432
16.9k
        VSIFree(hMiraMonLayer->pszSrcLayerName);
2433
16.9k
        hMiraMonLayer->pszSrcLayerName = nullptr;
2434
16.9k
    }
2435
32.0k
    if (hMiraMonLayer->szLayerTitle)
2436
12.0k
    {
2437
12.0k
        VSIFree(hMiraMonLayer->szLayerTitle);
2438
12.0k
        hMiraMonLayer->szLayerTitle = nullptr;
2439
12.0k
    }
2440
32.0k
    if (hMiraMonLayer->pSRS)
2441
369
    {
2442
369
        VSIFree(hMiraMonLayer->pSRS);
2443
369
        hMiraMonLayer->pSRS = nullptr;
2444
369
    }
2445
2446
32.0k
    if (hMiraMonLayer->pZUnit)
2447
144
    {
2448
144
        VSIFree(hMiraMonLayer->pZUnit);
2449
144
        hMiraMonLayer->pZUnit = nullptr;
2450
144
    }
2451
2452
32.0k
    if (hMiraMonLayer->pMultRecordIndex)
2453
404
    {
2454
404
        VSIFree(hMiraMonLayer->pMultRecordIndex);
2455
404
        hMiraMonLayer->pMultRecordIndex = nullptr;
2456
404
    }
2457
2458
32.0k
    if (hMiraMonLayer->ReadFeature.pNCoordRing)
2459
649
    {
2460
649
        free(hMiraMonLayer->ReadFeature.pNCoordRing);
2461
649
        hMiraMonLayer->ReadFeature.pNCoordRing = nullptr;
2462
649
    }
2463
32.0k
    if (hMiraMonLayer->ReadFeature.pCoord)
2464
617
    {
2465
617
        free(hMiraMonLayer->ReadFeature.pCoord);
2466
617
        hMiraMonLayer->ReadFeature.pCoord = nullptr;
2467
617
    }
2468
32.0k
    if (hMiraMonLayer->ReadFeature.pZCoord)
2469
238
    {
2470
238
        free(hMiraMonLayer->ReadFeature.pZCoord);
2471
238
        hMiraMonLayer->ReadFeature.pZCoord = nullptr;
2472
238
    }
2473
32.0k
    if (hMiraMonLayer->ReadFeature.pRecords)
2474
0
    {
2475
0
        free(hMiraMonLayer->ReadFeature.pRecords);
2476
0
        hMiraMonLayer->ReadFeature.pRecords = nullptr;
2477
0
    }
2478
32.0k
    if (hMiraMonLayer->ReadFeature.flag_VFG)
2479
214
    {
2480
214
        free(hMiraMonLayer->ReadFeature.flag_VFG);
2481
214
        hMiraMonLayer->ReadFeature.flag_VFG = nullptr;
2482
214
    }
2483
2484
32.0k
    if (hMiraMonLayer->pArcs)
2485
236
    {
2486
236
        VSIFree(hMiraMonLayer->pArcs);
2487
236
        hMiraMonLayer->pArcs = nullptr;
2488
236
    }
2489
2490
32.0k
    if (hMiraMonLayer->szStringToOperate)
2491
12.3k
    {
2492
12.3k
        VSIFree(hMiraMonLayer->szStringToOperate);
2493
12.3k
        hMiraMonLayer->szStringToOperate = nullptr;
2494
12.3k
        hMiraMonLayer->nNumStringToOperate = 0;
2495
12.3k
    }
2496
2497
32.0k
    if (hMiraMonLayer->pLayerDB)
2498
2.67k
    {
2499
2.67k
        if (hMiraMonLayer->pLayerDB->pFields)
2500
2.67k
        {
2501
2.67k
            VSIFree(hMiraMonLayer->pLayerDB->pFields);
2502
2.67k
            hMiraMonLayer->pLayerDB->pFields = nullptr;
2503
2.67k
        }
2504
2.67k
        VSIFree(hMiraMonLayer->pLayerDB);
2505
2.67k
        hMiraMonLayer->pLayerDB = nullptr;
2506
2.67k
    }
2507
2508
    // Destroys all database objects
2509
32.0k
    MMDestroyMMDB(hMiraMonLayer);
2510
2511
32.0k
    return 0;
2512
32.0k
}
2513
2514
/* -------------------------------------------------------------------- */
2515
/*      Flush Layer Functions                                           */
2516
/* -------------------------------------------------------------------- */
2517
2518
// Initializes a MM_FLUSH_INFO structure, which is used for buffering
2519
// data before writing it to a file.
2520
int MMInitFlush(struct MM_FLUSH_INFO *pFlush, VSILFILE *pF, GUInt64 nBlockSize,
2521
                char **pBuffer, MM_FILE_OFFSET DiskOffsetWhereToFlush,
2522
                GInt32 nMyDiskSize)
2523
7.18k
{
2524
7.18k
    memset(pFlush, 0, sizeof(*pFlush));
2525
7.18k
    *pBuffer = nullptr;
2526
2527
7.18k
    pFlush->nMyDiskSize = nMyDiskSize;
2528
7.18k
    pFlush->pF = pF;
2529
7.18k
    pFlush->nBlockSize = nBlockSize;
2530
7.18k
    pFlush->nNumBytes = 0;
2531
7.18k
    if (MMCheckSize_t(nBlockSize, 1))
2532
0
        return 1;
2533
2534
7.18k
    if (!nBlockSize)
2535
1
    {
2536
1
        CPLError(CE_Failure, CPLE_OutOfMemory,
2537
1
                 "Error in MiraMon "
2538
1
                 "driver: MMInitFlush() with no bytes to process");
2539
1
        return 1;
2540
1
    }
2541
2542
7.17k
    if (nullptr == (*pBuffer = (char *)VSICalloc(1, (size_t)nBlockSize)))
2543
0
    {
2544
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
2545
0
                 "Memory error in MiraMon "
2546
0
                 "driver (MMInitFlush())");
2547
0
        return 1;
2548
0
    }
2549
7.17k
    pFlush->OffsetWhereToFlush = DiskOffsetWhereToFlush;
2550
7.17k
    pFlush->CurrentOffset = 0;
2551
7.17k
    return 0;
2552
7.17k
}
2553
2554
// Reads data from a file into a buffer.
2555
int MMReadFlush(struct MM_FLUSH_INFO *pFlush)
2556
1.53k
{
2557
1.53k
    VSIFSeekL(pFlush->pF, pFlush->OffsetWhereToFlush, SEEK_SET);
2558
1.53k
    if (pFlush->nBlockSize !=
2559
1.53k
        (GUInt64)(VSIFReadL(pFlush->pBlockWhereToSaveOrRead, 1,
2560
1.53k
                            (size_t)pFlush->nBlockSize, pFlush->pF)))
2561
107
        return 1;
2562
1.43k
    return 0;
2563
1.53k
}
2564
2565
// Flushes data from a buffer to a disk file.
2566
static int MMFlushToDisk(struct MM_FLUSH_INFO *FlushInfo)
2567
15.3k
{
2568
15.3k
    if (!FlushInfo->nNumBytes)
2569
4.54k
        return 0;
2570
    // Just flush to the disk at the correct place.
2571
10.8k
    VSIFSeekL(FlushInfo->pF, FlushInfo->OffsetWhereToFlush, SEEK_SET);
2572
2573
10.8k
    if (FlushInfo->nNumBytes !=
2574
10.8k
        (GUInt64)VSIFWriteL(FlushInfo->pBlockWhereToSaveOrRead, 1,
2575
10.8k
                            (size_t)FlushInfo->nNumBytes, FlushInfo->pF))
2576
0
        return 1;
2577
10.8k
    FlushInfo->OffsetWhereToFlush += FlushInfo->nNumBytes;
2578
10.8k
    FlushInfo->NTimesFlushed++;
2579
10.8k
    FlushInfo->TotalSavedBytes += FlushInfo->nNumBytes;
2580
10.8k
    FlushInfo->nNumBytes = 0;
2581
2582
10.8k
    return 0;
2583
10.8k
}
2584
2585
// Reads a block of data from a buffer in memory
2586
int MMReadBlockFromBuffer(struct MM_FLUSH_INFO *FlushInfo)
2587
578k
{
2588
578k
    if (!FlushInfo->SizeOfBlockToBeSaved)
2589
0
        return 0;
2590
2591
578k
    if (FlushInfo->pBlockToBeSaved)
2592
573k
    {
2593
573k
        memcpy(FlushInfo->pBlockToBeSaved,
2594
573k
               (void *)((char *)FlushInfo->pBlockWhereToSaveOrRead +
2595
573k
                        FlushInfo->CurrentOffset),
2596
573k
               FlushInfo->SizeOfBlockToBeSaved);
2597
573k
    }
2598
578k
    FlushInfo->CurrentOffset += FlushInfo->SizeOfBlockToBeSaved;
2599
2600
578k
    return 0;
2601
578k
}
2602
2603
// Appends a block of data to a buffer in memory, which is
2604
// used for later flushing to disk.
2605
int MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo)
2606
436k
{
2607
436k
    if (FlushInfo->SizeOfBlockToBeSaved)
2608
422k
    {
2609
        // If all the block itself does not fit to the buffer,
2610
        // then all the block is written directly to the disk
2611
422k
        if (FlushInfo->nNumBytes == 0 &&
2612
11.0k
            FlushInfo->SizeOfBlockToBeSaved >= FlushInfo->nBlockSize)
2613
0
        {
2614
0
            if (MMFlushToDisk(FlushInfo))
2615
0
                return 1;
2616
0
            return 0;
2617
0
        }
2618
2619
        // There is space in FlushInfo->pBlockWhereToSaveOrRead?
2620
422k
        if (FlushInfo->nNumBytes + FlushInfo->SizeOfBlockToBeSaved <=
2621
422k
            FlushInfo->nBlockSize)
2622
421k
        {
2623
421k
            if (FlushInfo->pBlockToBeSaved)
2624
412k
            {
2625
412k
                memcpy((void *)((char *)FlushInfo->pBlockWhereToSaveOrRead +
2626
412k
                                FlushInfo->nNumBytes),
2627
412k
                       FlushInfo->pBlockToBeSaved,
2628
412k
                       FlushInfo->SizeOfBlockToBeSaved);
2629
412k
            }
2630
9.08k
            else  // Add zero characters
2631
9.08k
            {
2632
9.08k
                char zero_caracters[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2633
9.08k
                memcpy((char *)FlushInfo->pBlockWhereToSaveOrRead +
2634
9.08k
                           FlushInfo->nNumBytes,
2635
9.08k
                       zero_caracters, FlushInfo->SizeOfBlockToBeSaved);
2636
9.08k
            }
2637
2638
421k
            FlushInfo->nNumBytes += FlushInfo->SizeOfBlockToBeSaved;
2639
421k
        }
2640
1.16k
        else
2641
1.16k
        {
2642
            // Empty the buffer
2643
1.16k
            if (MMFlushToDisk(FlushInfo))
2644
0
                return 1;
2645
            // Append the pendant bytes
2646
1.16k
            if (MMAppendBlockToBuffer(FlushInfo))
2647
0
                return 1;
2648
1.16k
        }
2649
422k
        return 0;
2650
422k
    }
2651
    // Just flush to the disc.
2652
14.2k
    return MMFlushToDisk(FlushInfo);
2653
436k
}
2654
2655
// Copy the contents of a temporary file to a final file.
2656
// Used everywhere when closing layers.
2657
int MMMoveFromFileToFile(VSILFILE *pSrcFile, VSILFILE *pDestFile,
2658
                         MM_FILE_OFFSET *pnOffset)
2659
1.51k
{
2660
1.51k
    size_t bufferSize = 1024 * 1024;  // 1 MB buffer;
2661
1.51k
    unsigned char *buffer;
2662
1.51k
    size_t bytesRead, bytesWritten;
2663
2664
1.51k
    if (!pSrcFile || !pDestFile || !pnOffset)
2665
0
        return 0;
2666
2667
1.51k
    buffer = (unsigned char *)VSICalloc(1, bufferSize);
2668
2669
1.51k
    if (!buffer)
2670
0
        return 1;
2671
2672
1.51k
    VSIFSeekL(pSrcFile, 0, SEEK_SET);
2673
1.51k
    VSIFSeekL(pDestFile, *pnOffset, SEEK_SET);
2674
2.53k
    while ((bytesRead = VSIFReadL(buffer, sizeof(unsigned char), bufferSize,
2675
2.53k
                                  pSrcFile)) > 0)
2676
1.02k
    {
2677
1.02k
        bytesWritten =
2678
1.02k
            VSIFWriteL(buffer, sizeof(unsigned char), bytesRead, pDestFile);
2679
1.02k
        if (bytesWritten != bytesRead)
2680
0
        {
2681
0
            VSIFree(buffer);
2682
0
            return 1;
2683
0
        }
2684
1.02k
        (*pnOffset) += bytesWritten;
2685
1.02k
    }
2686
1.51k
    VSIFree(buffer);
2687
1.51k
    return 0;
2688
1.51k
}
2689
2690
/* -------------------------------------------------------------------- */
2691
/*      Layer: Offsets and variables types managing                     */
2692
/* -------------------------------------------------------------------- */
2693
2694
// Alineation described in format documents.
2695
static void MMGetOffsetAlignedTo8(MM_FILE_OFFSET *Offset)
2696
4.81k
{
2697
4.81k
    MM_FILE_OFFSET reajust;
2698
2699
4.81k
    if ((*Offset) % 8L)
2700
4.81k
    {
2701
4.81k
        reajust = 8 - ((*Offset) % 8L);
2702
4.81k
        (*Offset) += reajust;
2703
4.81k
    }
2704
4.81k
}
2705
2706
// Reading integers depending on the version being read.
2707
int MMReadGUInt64DependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer,
2708
                                    struct MM_FLUSH_INFO *FlushInfo,
2709
                                    GUInt64 *pnUI64)
2710
254k
{
2711
254k
    uint32_t nUL32;
2712
2713
254k
    if (!hMiraMonLayer)
2714
0
        return 1;
2715
2716
254k
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
2717
241k
    {
2718
241k
        FlushInfo->pBlockToBeSaved = (void *)&nUL32;
2719
241k
        FlushInfo->SizeOfBlockToBeSaved = sizeof(nUL32);
2720
241k
        if (MMReadBlockFromBuffer(FlushInfo))
2721
0
        {
2722
0
            FlushInfo->pBlockToBeSaved = nullptr;
2723
0
            return 1;
2724
0
        }
2725
241k
        *pnUI64 = (GUInt64)nUL32;
2726
241k
    }
2727
12.7k
    else
2728
12.7k
    {
2729
12.7k
        FlushInfo->pBlockToBeSaved = (void *)pnUI64;
2730
12.7k
        FlushInfo->SizeOfBlockToBeSaved = sizeof(*pnUI64);
2731
12.7k
        if (MMReadBlockFromBuffer(FlushInfo))
2732
0
        {
2733
0
            FlushInfo->pBlockToBeSaved = nullptr;
2734
0
            return 1;
2735
0
        }
2736
12.7k
    }
2737
254k
    FlushInfo->pBlockToBeSaved = nullptr;
2738
254k
    return 0;
2739
254k
}
2740
2741
// Reading offsets depending on the version is being read.
2742
int MMReadOffsetDependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer,
2743
                                   struct MM_FLUSH_INFO *FlushInfo,
2744
                                   MM_FILE_OFFSET *pnUI64)
2745
17.4k
{
2746
17.4k
    uint32_t nUL32;
2747
2748
17.4k
    if (!hMiraMonLayer)
2749
0
        return 1;
2750
2751
17.4k
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
2752
8.21k
    {
2753
8.21k
        FlushInfo->pBlockToBeSaved = (void *)&nUL32;
2754
8.21k
        FlushInfo->SizeOfBlockToBeSaved = sizeof(nUL32);
2755
8.21k
        if (MMReadBlockFromBuffer(FlushInfo))
2756
0
        {
2757
0
            FlushInfo->pBlockToBeSaved = nullptr;
2758
0
            return 1;
2759
0
        }
2760
8.21k
        *pnUI64 = (MM_FILE_OFFSET)nUL32;
2761
8.21k
    }
2762
9.23k
    else
2763
9.23k
    {
2764
9.23k
        FlushInfo->pBlockToBeSaved = (void *)pnUI64;
2765
9.23k
        FlushInfo->SizeOfBlockToBeSaved = sizeof(*pnUI64);
2766
9.23k
        if (MMReadBlockFromBuffer(FlushInfo))
2767
0
        {
2768
0
            FlushInfo->pBlockToBeSaved = nullptr;
2769
0
            return 1;
2770
0
        }
2771
9.23k
    }
2772
17.4k
    FlushInfo->pBlockToBeSaved = nullptr;
2773
17.4k
    return 0;
2774
17.4k
}
2775
2776
// Appending integers depending on the version.
2777
int MMAppendIntegerDependingOnVersion(
2778
    struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo,
2779
    uint32_t *nUL32, GUInt64 nUI64)
2780
27.8k
{
2781
27.8k
    int result;
2782
2783
27.8k
    if (!hMiraMonLayer)
2784
0
        return 1;
2785
2786
27.8k
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
2787
27.8k
    {
2788
27.8k
        *nUL32 = (uint32_t)nUI64;
2789
27.8k
        FlushInfo->SizeOfBlockToBeSaved = sizeof(*nUL32);
2790
27.8k
        hMiraMonLayer->OffsetCheck += FlushInfo->SizeOfBlockToBeSaved;
2791
27.8k
        FlushInfo->pBlockToBeSaved = (void *)nUL32;
2792
27.8k
    }
2793
0
    else
2794
0
    {
2795
0
        FlushInfo->SizeOfBlockToBeSaved = sizeof(nUI64);
2796
0
        hMiraMonLayer->OffsetCheck += FlushInfo->SizeOfBlockToBeSaved;
2797
0
        FlushInfo->pBlockToBeSaved = (void *)&nUI64;
2798
0
    }
2799
27.8k
    result = MMAppendBlockToBuffer(FlushInfo);
2800
27.8k
    FlushInfo->pBlockToBeSaved = nullptr;
2801
27.8k
    return result;
2802
27.8k
}
2803
2804
/* -------------------------------------------------------------------- */
2805
/*      Layer: Reading and writing layer sections                       */
2806
/*      This code follows the specifications of the following document: */
2807
/*             https://www.miramon.cat/new_note/eng/notes/   \          */
2808
/*              FormatFitxersTopologicsMiraMon.pdf                      */
2809
/* -------------------------------------------------------------------- */
2810
int MMReadAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer)
2811
560
{
2812
560
    MM_INTERNAL_FID iElem, nElem;
2813
560
    struct MM_FLUSH_INFO FlushTMP;
2814
560
    char *pBuffer = nullptr;
2815
560
    MM_FILE_OFFSET nBlockSize;
2816
560
    struct MiraMonArcLayer *pMMArcLayer;
2817
560
    MM_N_VERTICES_TYPE nElementCount;
2818
2819
560
    if (!hMiraMonLayer)
2820
0
        return 1;
2821
2822
560
    if (hMiraMonLayer->bIsPolygon)
2823
293
    {
2824
293
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
2825
293
        nElem = hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount;
2826
293
    }
2827
267
    else
2828
267
    {
2829
267
        pMMArcLayer = &hMiraMonLayer->MMArc;
2830
267
        nElem = hMiraMonLayer->TopHeader.nElemCount;
2831
267
    }
2832
2833
560
    if (MMCheckSize_t(nElem, pMMArcLayer->nSizeArcHeader))
2834
0
    {
2835
0
        return 1;
2836
0
    }
2837
2838
560
    nBlockSize = nElem * (pMMArcLayer->nSizeArcHeader);
2839
2840
560
    if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, nBlockSize, &pBuffer,
2841
560
                    hMiraMonLayer->nHeaderDiskSize, 0))
2842
0
    {
2843
0
        if (pBuffer)
2844
0
            VSIFree(pBuffer);
2845
0
        return 1;
2846
0
    }
2847
560
    FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
2848
560
    if (MMReadFlush(&FlushTMP))
2849
9
    {
2850
9
        if (pBuffer)
2851
9
            VSIFree(pBuffer);
2852
9
        return 1;
2853
9
    }
2854
2855
5.99k
    for (iElem = 0; iElem < nElem; iElem++)
2856
5.44k
    {
2857
        // Bounding box
2858
5.44k
        FlushTMP.pBlockToBeSaved =
2859
5.44k
            (void *)&(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX);
2860
5.44k
        FlushTMP.SizeOfBlockToBeSaved =
2861
5.44k
            sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX);
2862
5.44k
        if (MMReadBlockFromBuffer(&FlushTMP))
2863
0
        {
2864
0
            if (pBuffer)
2865
0
                VSIFree(pBuffer);
2866
0
            return 1;
2867
0
        }
2868
5.44k
        FlushTMP.pBlockToBeSaved =
2869
5.44k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX;
2870
5.44k
        FlushTMP.SizeOfBlockToBeSaved =
2871
5.44k
            sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX);
2872
5.44k
        if (MMReadBlockFromBuffer(&FlushTMP))
2873
0
        {
2874
0
            if (pBuffer)
2875
0
                VSIFree(pBuffer);
2876
0
            return 1;
2877
0
        }
2878
5.44k
        FlushTMP.pBlockToBeSaved =
2879
5.44k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY;
2880
5.44k
        FlushTMP.SizeOfBlockToBeSaved =
2881
5.44k
            sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY);
2882
5.44k
        if (MMReadBlockFromBuffer(&FlushTMP))
2883
0
        {
2884
0
            if (pBuffer)
2885
0
                VSIFree(pBuffer);
2886
0
            return 1;
2887
0
        }
2888
5.44k
        FlushTMP.pBlockToBeSaved =
2889
5.44k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY;
2890
5.44k
        FlushTMP.SizeOfBlockToBeSaved =
2891
5.44k
            sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY);
2892
5.44k
        if (MMReadBlockFromBuffer(&FlushTMP))
2893
0
        {
2894
0
            if (pBuffer)
2895
0
                VSIFree(pBuffer);
2896
0
            return 1;
2897
0
        }
2898
2899
        // Element count: number of vertices of the arc
2900
5.44k
        nElementCount = pMMArcLayer->pArcHeader[iElem].nElemCount;
2901
5.44k
        if (MMReadGUInt64DependingOnVersion(hMiraMonLayer, &FlushTMP,
2902
5.44k
                                            &nElementCount))
2903
0
        {
2904
0
            if (pBuffer)
2905
0
                VSIFree(pBuffer);
2906
0
            return 1;
2907
0
        }
2908
5.44k
        pMMArcLayer->pArcHeader[iElem].nElemCount = nElementCount;
2909
2910
        // Offset: offset of the first vertice of the arc
2911
5.44k
        if (MMReadOffsetDependingOnVersion(
2912
5.44k
                hMiraMonLayer, &FlushTMP,
2913
5.44k
                &pMMArcLayer->pArcHeader[iElem].nOffset))
2914
0
        {
2915
0
            if (pBuffer)
2916
0
                VSIFree(pBuffer);
2917
0
            return 1;
2918
0
        }
2919
        // First node: first node of the arc
2920
5.44k
        if (MMReadGUInt64DependingOnVersion(
2921
5.44k
                hMiraMonLayer, &FlushTMP,
2922
5.44k
                &pMMArcLayer->pArcHeader[iElem].nFirstIdNode))
2923
0
        {
2924
0
            if (pBuffer)
2925
0
                VSIFree(pBuffer);
2926
0
            return 1;
2927
0
        }
2928
        // Last node: first node of the arc
2929
5.44k
        if (MMReadGUInt64DependingOnVersion(
2930
5.44k
                hMiraMonLayer, &FlushTMP,
2931
5.44k
                &pMMArcLayer->pArcHeader[iElem].nLastIdNode))
2932
0
        {
2933
0
            if (pBuffer)
2934
0
                VSIFree(pBuffer);
2935
0
            return 1;
2936
0
        }
2937
        // Length of the arc
2938
5.44k
        FlushTMP.pBlockToBeSaved =
2939
5.44k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfLength;
2940
5.44k
        FlushTMP.SizeOfBlockToBeSaved =
2941
5.44k
            sizeof(pMMArcLayer->pArcHeader[iElem].dfLength);
2942
5.44k
        if (MMReadBlockFromBuffer(&FlushTMP))
2943
0
        {
2944
0
            if (pBuffer)
2945
0
                VSIFree(pBuffer);
2946
0
            return 1;
2947
0
        }
2948
5.44k
    }
2949
2950
551
    if (pBuffer)
2951
551
        VSIFree(pBuffer);
2952
551
    return 0;
2953
551
}
2954
2955
int MMWriteAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
2956
                        MM_FILE_OFFSET DiskOffset)
2957
365
{
2958
365
    MM_INTERNAL_FID iElem;
2959
365
    struct MM_FLUSH_INFO FlushTMP;
2960
365
    char *pBuffer = nullptr;
2961
365
    uint32_t nUL32;
2962
365
    MM_FILE_OFFSET nOffsetDiff;
2963
365
    struct MiraMonArcLayer *pMMArcLayer;
2964
2965
365
    if (!hMiraMonLayer)
2966
0
        return 1;
2967
2968
365
    if (hMiraMonLayer->bIsPolygon)
2969
155
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
2970
210
    else
2971
210
        pMMArcLayer = &hMiraMonLayer->MMArc;
2972
2973
365
    nOffsetDiff =
2974
365
        hMiraMonLayer->nHeaderDiskSize +
2975
365
        hMiraMonLayer->nFinalElemCount * (pMMArcLayer->nSizeArcHeader);
2976
2977
365
    if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, MM_1MB, &pBuffer, DiskOffset,
2978
365
                    0))
2979
0
    {
2980
0
        if (pBuffer)
2981
0
            VSIFree(pBuffer);
2982
0
        return 1;
2983
0
    }
2984
2985
365
    FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
2986
2.95k
    for (iElem = 0; iElem < hMiraMonLayer->nFinalElemCount; iElem++)
2987
2.58k
    {
2988
        // Bounding box
2989
2.58k
        FlushTMP.SizeOfBlockToBeSaved =
2990
2.58k
            sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX);
2991
2.58k
        FlushTMP.pBlockToBeSaved =
2992
2.58k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX;
2993
2.58k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
2994
2.58k
        if (MMAppendBlockToBuffer(&FlushTMP))
2995
0
        {
2996
0
            if (pBuffer)
2997
0
                VSIFree(pBuffer);
2998
0
            return 1;
2999
0
        }
3000
2.58k
        FlushTMP.pBlockToBeSaved =
3001
2.58k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX;
3002
2.58k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3003
2.58k
        if (MMAppendBlockToBuffer(&FlushTMP))
3004
0
        {
3005
0
            if (pBuffer)
3006
0
                VSIFree(pBuffer);
3007
0
            return 1;
3008
0
        }
3009
2.58k
        FlushTMP.pBlockToBeSaved =
3010
2.58k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY;
3011
2.58k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3012
2.58k
        if (MMAppendBlockToBuffer(&FlushTMP))
3013
0
        {
3014
0
            if (pBuffer)
3015
0
                VSIFree(pBuffer);
3016
0
            return 1;
3017
0
        }
3018
2.58k
        FlushTMP.pBlockToBeSaved =
3019
2.58k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY;
3020
2.58k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3021
2.58k
        if (MMAppendBlockToBuffer(&FlushTMP))
3022
0
        {
3023
0
            if (pBuffer)
3024
0
                VSIFree(pBuffer);
3025
0
            return 1;
3026
0
        }
3027
3028
        // Element count: number of vertices of the arc
3029
2.58k
        if (MMAppendIntegerDependingOnVersion(
3030
2.58k
                hMiraMonLayer, &FlushTMP, &nUL32,
3031
2.58k
                pMMArcLayer->pArcHeader[iElem].nElemCount))
3032
0
        {
3033
0
            if (pBuffer)
3034
0
                VSIFree(pBuffer);
3035
0
            return 1;
3036
0
        }
3037
3038
        // Offset: offset of the first vertice of the arc
3039
2.58k
        if (MMAppendIntegerDependingOnVersion(
3040
2.58k
                hMiraMonLayer, &FlushTMP, &nUL32,
3041
2.58k
                pMMArcLayer->pArcHeader[iElem].nOffset + nOffsetDiff))
3042
0
        {
3043
0
            if (pBuffer)
3044
0
                VSIFree(pBuffer);
3045
0
            return 1;
3046
0
        }
3047
        // First node: first node of the arc
3048
2.58k
        if (MMAppendIntegerDependingOnVersion(
3049
2.58k
                hMiraMonLayer, &FlushTMP, &nUL32,
3050
2.58k
                pMMArcLayer->pArcHeader[iElem].nFirstIdNode))
3051
0
        {
3052
0
            if (pBuffer)
3053
0
                VSIFree(pBuffer);
3054
0
            return 1;
3055
0
        }
3056
        // Last node: first node of the arc
3057
2.58k
        if (MMAppendIntegerDependingOnVersion(
3058
2.58k
                hMiraMonLayer, &FlushTMP, &nUL32,
3059
2.58k
                pMMArcLayer->pArcHeader[iElem].nLastIdNode))
3060
0
        {
3061
0
            if (pBuffer)
3062
0
                VSIFree(pBuffer);
3063
0
            return 1;
3064
0
        }
3065
        // Length of the arc
3066
2.58k
        FlushTMP.SizeOfBlockToBeSaved =
3067
2.58k
            sizeof(pMMArcLayer->pArcHeader[iElem].dfLength);
3068
2.58k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3069
2.58k
        FlushTMP.pBlockToBeSaved =
3070
2.58k
            (void *)&pMMArcLayer->pArcHeader[iElem].dfLength;
3071
2.58k
        if (MMAppendBlockToBuffer(&FlushTMP))
3072
0
        {
3073
0
            if (pBuffer)
3074
0
                VSIFree(pBuffer);
3075
0
            return 1;
3076
0
        }
3077
2.58k
    }
3078
365
    FlushTMP.SizeOfBlockToBeSaved = 0;
3079
365
    if (MMAppendBlockToBuffer(&FlushTMP))
3080
0
    {
3081
0
        if (pBuffer)
3082
0
            VSIFree(pBuffer);
3083
0
        return 1;
3084
0
    }
3085
3086
365
    if (pBuffer)
3087
365
        VSIFree(pBuffer);
3088
365
    return 0;
3089
365
}
3090
3091
#ifdef JUST_IN_CASE_WE_NEED_IT_SOMEDAY
3092
static int MMReadNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer)
3093
{
3094
    MM_INTERNAL_FID iElem, nElem;
3095
    struct MM_FLUSH_INFO FlushTMP;
3096
    char *pBuffer = nullptr;
3097
    MM_FILE_OFFSET nBlockSize;
3098
    struct MiraMonArcLayer *pMMArcLayer;
3099
3100
    if (hMiraMonLayer->bIsPolygon)
3101
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
3102
    else
3103
        pMMArcLayer = &hMiraMonLayer->MMArc;
3104
3105
    nElem = pMMArcLayer->TopNodeHeader.nElemCount;
3106
3107
    nBlockSize = nElem * pMMArcLayer->MMNode.nSizeNodeHeader;
3108
3109
    if (MMInitFlush(&FlushTMP, pMMArcLayer->MMNode.pF, nBlockSize, &pBuffer,
3110
                    hMiraMonLayer->nHeaderDiskSize, 0))
3111
    {
3112
        if (pBuffer)
3113
            VSIFree(pBuffer);
3114
        return 1;
3115
    }
3116
3117
    FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
3118
    if (MMReadFlush(&FlushTMP))
3119
    {
3120
        if (pBuffer)
3121
            VSIFree(pBuffer);
3122
        return 1;
3123
    }
3124
3125
    for (iElem = 0; iElem < nElem; iElem++)
3126
    {
3127
        // Arcs count
3128
        FlushTMP.pBlockToBeSaved =
3129
            (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount;
3130
        FlushTMP.SizeOfBlockToBeSaved =
3131
            sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount);
3132
        if (MMReadBlockFromBuffer(&FlushTMP))
3133
        {
3134
            if (pBuffer)
3135
                VSIFree(pBuffer);
3136
            return 1;
3137
        }
3138
        // Node type
3139
        FlushTMP.pBlockToBeSaved =
3140
            (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType;
3141
        FlushTMP.SizeOfBlockToBeSaved =
3142
            sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType);
3143
        if (MMReadBlockFromBuffer(&FlushTMP))
3144
        {
3145
            if (pBuffer)
3146
                VSIFree(pBuffer);
3147
            return 1;
3148
        }
3149
        FlushTMP.SizeOfBlockToBeSaved = 1;
3150
        FlushTMP.pBlockToBeSaved = (void *)nullptr;
3151
        if (MMReadBlockFromBuffer(&FlushTMP))
3152
        {
3153
            if (pBuffer)
3154
                VSIFree(pBuffer);
3155
            return 1;
3156
        }
3157
3158
        // Offset: offset of the first arc to the node
3159
        if (MMReadOffsetDependingOnVersion(
3160
                hMiraMonLayer, &FlushTMP,
3161
                &pMMArcLayer->MMNode.pNodeHeader[iElem].nOffset))
3162
        {
3163
            if (pBuffer)
3164
                VSIFree(pBuffer);
3165
            return 1;
3166
        }
3167
    }
3168
3169
    if (pBuffer)
3170
        VSIFree(pBuffer);
3171
    return 0;
3172
}
3173
#endif  // JUST_IN_CASE_WE_NEED_IT_SOMEDAY
3174
3175
int MMWriteNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
3176
                         MM_FILE_OFFSET DiskOffset)
3177
365
{
3178
365
    MM_INTERNAL_FID iElem;
3179
365
    struct MM_FLUSH_INFO FlushTMP;
3180
365
    char *pBuffer = nullptr;
3181
365
    uint32_t nUL32;
3182
365
    MM_FILE_OFFSET nOffsetDiff;
3183
365
    struct MiraMonArcLayer *pMMArcLayer;
3184
3185
365
    if (!hMiraMonLayer)
3186
0
        return 1;
3187
3188
365
    if (hMiraMonLayer->bIsPolygon)
3189
155
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
3190
210
    else
3191
210
        pMMArcLayer = &hMiraMonLayer->MMArc;
3192
3193
365
    nOffsetDiff = hMiraMonLayer->nHeaderDiskSize +
3194
365
                  (pMMArcLayer->TopNodeHeader.nElemCount *
3195
365
                   pMMArcLayer->MMNode.nSizeNodeHeader);
3196
3197
365
    if (MMInitFlush(&FlushTMP, pMMArcLayer->MMNode.pF, MM_1MB, &pBuffer,
3198
365
                    DiskOffset, 0))
3199
0
    {
3200
0
        if (pBuffer)
3201
0
            VSIFree(pBuffer);
3202
0
        return 1;
3203
0
    }
3204
3205
365
    FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
3206
4.63k
    for (iElem = 0; iElem < pMMArcLayer->TopNodeHeader.nElemCount; iElem++)
3207
4.27k
    {
3208
        // Arcs count
3209
4.27k
        FlushTMP.SizeOfBlockToBeSaved =
3210
4.27k
            sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount);
3211
4.27k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3212
4.27k
        FlushTMP.pBlockToBeSaved =
3213
4.27k
            (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount;
3214
4.27k
        if (MMAppendBlockToBuffer(&FlushTMP))
3215
0
        {
3216
0
            if (pBuffer)
3217
0
                VSIFree(pBuffer);
3218
0
            return 1;
3219
0
        }
3220
        // Node type
3221
4.27k
        FlushTMP.SizeOfBlockToBeSaved =
3222
4.27k
            sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType);
3223
4.27k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3224
4.27k
        FlushTMP.pBlockToBeSaved =
3225
4.27k
            (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType;
3226
4.27k
        if (MMAppendBlockToBuffer(&FlushTMP))
3227
0
        {
3228
0
            if (pBuffer)
3229
0
                VSIFree(pBuffer);
3230
0
            return 1;
3231
0
        }
3232
4.27k
        FlushTMP.SizeOfBlockToBeSaved = 1;
3233
4.27k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3234
4.27k
        FlushTMP.pBlockToBeSaved = (void *)nullptr;
3235
4.27k
        if (MMAppendBlockToBuffer(&FlushTMP))
3236
0
        {
3237
0
            if (pBuffer)
3238
0
                VSIFree(pBuffer);
3239
0
            return 1;
3240
0
        }
3241
3242
        // Offset: offset of the first arc to the node
3243
4.27k
        if (MMAppendIntegerDependingOnVersion(
3244
4.27k
                hMiraMonLayer, &FlushTMP, &nUL32,
3245
4.27k
                pMMArcLayer->MMNode.pNodeHeader[iElem].nOffset + nOffsetDiff))
3246
0
        {
3247
0
            if (pBuffer)
3248
0
                VSIFree(pBuffer);
3249
0
            return 1;
3250
0
        }
3251
4.27k
    }
3252
365
    FlushTMP.SizeOfBlockToBeSaved = 0;
3253
365
    if (MMAppendBlockToBuffer(&FlushTMP))
3254
0
    {
3255
0
        if (pBuffer)
3256
0
            VSIFree(pBuffer);
3257
0
        return 1;
3258
0
    }
3259
3260
365
    if (pBuffer)
3261
365
        VSIFree(pBuffer);
3262
365
    return 0;
3263
365
}
3264
3265
int MMReadPHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer)
3266
326
{
3267
326
    MM_INTERNAL_FID iElem;
3268
326
    struct MM_FLUSH_INFO FlushTMP;
3269
326
    char *pBuffer = nullptr;
3270
326
    MM_FILE_OFFSET nBlockSize;
3271
326
    struct MiraMonPolygonLayer *pMMPolygonLayer;
3272
3273
326
    if (!hMiraMonLayer)
3274
0
        return 1;
3275
3276
326
    pMMPolygonLayer = &hMiraMonLayer->MMPolygon;
3277
3278
326
    if (MMCheckSize_t(hMiraMonLayer->TopHeader.nElemCount,
3279
326
                      pMMPolygonLayer->nPHElementSize) ||
3280
326
        MMCheckSize_t(hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount,
3281
326
                      hMiraMonLayer->MMPolygon.nPSElementSize))
3282
1
    {
3283
1
        return 1;
3284
1
    }
3285
325
    nBlockSize =
3286
325
        hMiraMonLayer->TopHeader.nElemCount * (pMMPolygonLayer->nPHElementSize);
3287
3288
325
    if (MMInitFlush(&FlushTMP, pMMPolygonLayer->pF, nBlockSize, &pBuffer,
3289
325
                    hMiraMonLayer->nHeaderDiskSize +
3290
325
                        (hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount *
3291
325
                         hMiraMonLayer->MMPolygon.nPSElementSize),
3292
325
                    0))
3293
1
    {
3294
1
        if (pBuffer)
3295
0
            VSIFree(pBuffer);
3296
1
        return 1;
3297
1
    }
3298
324
    FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
3299
324
    if (MMReadFlush(&FlushTMP))
3300
24
    {
3301
24
        if (pBuffer)
3302
24
            VSIFree(pBuffer);
3303
24
        return 1;
3304
24
    }
3305
3306
3.57k
    for (iElem = 0; iElem < hMiraMonLayer->TopHeader.nElemCount; iElem++)
3307
3.27k
    {
3308
        // Bounding box
3309
3.27k
        FlushTMP.pBlockToBeSaved =
3310
3.27k
            (void *)&(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX);
3311
3.27k
        FlushTMP.SizeOfBlockToBeSaved =
3312
3.27k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX);
3313
3.27k
        if (MMReadBlockFromBuffer(&FlushTMP))
3314
0
        {
3315
0
            if (pBuffer)
3316
0
                VSIFree(pBuffer);
3317
0
            return 1;
3318
0
        }
3319
3.27k
        FlushTMP.pBlockToBeSaved =
3320
3.27k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX;
3321
3.27k
        FlushTMP.SizeOfBlockToBeSaved =
3322
3.27k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX);
3323
3.27k
        if (MMReadBlockFromBuffer(&FlushTMP))
3324
0
        {
3325
0
            if (pBuffer)
3326
0
                VSIFree(pBuffer);
3327
0
            return 1;
3328
0
        }
3329
3.27k
        FlushTMP.pBlockToBeSaved =
3330
3.27k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY;
3331
3.27k
        FlushTMP.SizeOfBlockToBeSaved =
3332
3.27k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY);
3333
3.27k
        if (MMReadBlockFromBuffer(&FlushTMP))
3334
0
        {
3335
0
            if (pBuffer)
3336
0
                VSIFree(pBuffer);
3337
0
            return 1;
3338
0
        }
3339
3.27k
        FlushTMP.pBlockToBeSaved =
3340
3.27k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY;
3341
3.27k
        FlushTMP.SizeOfBlockToBeSaved =
3342
3.27k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY);
3343
3.27k
        if (MMReadBlockFromBuffer(&FlushTMP))
3344
0
        {
3345
0
            if (pBuffer)
3346
0
                VSIFree(pBuffer);
3347
0
            return 1;
3348
0
        }
3349
3350
        // Arcs count: number of arcs of the polygon
3351
3.27k
        if (MMReadGUInt64DependingOnVersion(
3352
3.27k
                hMiraMonLayer, &FlushTMP,
3353
3.27k
                &pMMPolygonLayer->pPolHeader[iElem].nArcsCount))
3354
0
        {
3355
0
            if (pBuffer)
3356
0
                VSIFree(pBuffer);
3357
0
            return 1;
3358
0
        }
3359
3360
        // External arcs count: number of external arcs of the polygon
3361
3.27k
        if (MMReadGUInt64DependingOnVersion(
3362
3.27k
                hMiraMonLayer, &FlushTMP,
3363
3.27k
                &pMMPolygonLayer->pPolHeader[iElem].nExternalRingsCount))
3364
0
        {
3365
0
            if (pBuffer)
3366
0
                VSIFree(pBuffer);
3367
0
            return 1;
3368
0
        }
3369
3370
        // Rings count: number of rings of the polygon
3371
3.27k
        if (MMReadGUInt64DependingOnVersion(
3372
3.27k
                hMiraMonLayer, &FlushTMP,
3373
3.27k
                &pMMPolygonLayer->pPolHeader[iElem].nRingsCount))
3374
0
        {
3375
0
            if (pBuffer)
3376
0
                VSIFree(pBuffer);
3377
0
            return 1;
3378
0
        }
3379
3380
        // Offset: offset of the first vertex of the arc
3381
3.27k
        if (MMReadOffsetDependingOnVersion(
3382
3.27k
                hMiraMonLayer, &FlushTMP,
3383
3.27k
                &pMMPolygonLayer->pPolHeader[iElem].nOffset))
3384
0
        {
3385
0
            if (pBuffer)
3386
0
                VSIFree(pBuffer);
3387
0
            return 1;
3388
0
        }
3389
3390
        // Perimeter of the arc
3391
3.27k
        FlushTMP.SizeOfBlockToBeSaved =
3392
3.27k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfPerimeter);
3393
3.27k
        FlushTMP.pBlockToBeSaved =
3394
3.27k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfPerimeter;
3395
3.27k
        if (MMReadBlockFromBuffer(&FlushTMP))
3396
0
        {
3397
0
            if (pBuffer)
3398
0
                VSIFree(pBuffer);
3399
0
            return 1;
3400
0
        }
3401
3402
        // Area of the arc
3403
3.27k
        FlushTMP.SizeOfBlockToBeSaved =
3404
3.27k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfArea);
3405
3.27k
        FlushTMP.pBlockToBeSaved =
3406
3.27k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfArea;
3407
3.27k
        if (MMReadBlockFromBuffer(&FlushTMP))
3408
0
        {
3409
0
            if (pBuffer)
3410
0
                VSIFree(pBuffer);
3411
0
            return 1;
3412
0
        }
3413
3.27k
    }
3414
3415
300
    if (pBuffer)
3416
300
        VSIFree(pBuffer);
3417
300
    return 0;
3418
300
}
3419
3420
int MMWritePHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
3421
                            MM_FILE_OFFSET DiskOffset)
3422
155
{
3423
155
    MM_INTERNAL_FID iElem;
3424
155
    struct MM_FLUSH_INFO FlushTMP;
3425
155
    char *pBuffer = nullptr;
3426
155
    uint32_t nUL32;
3427
155
    MM_FILE_OFFSET nOffsetDiff;
3428
155
    struct MiraMonPolygonLayer *pMMPolygonLayer;
3429
3430
155
    if (!hMiraMonLayer)
3431
0
        return 1;
3432
3433
155
    pMMPolygonLayer = &hMiraMonLayer->MMPolygon;
3434
3435
155
    if (!pMMPolygonLayer->pF)
3436
0
        return 0;
3437
3438
155
    if (!hMiraMonLayer->nFinalElemCount)
3439
0
        return 0;
3440
3441
155
    nOffsetDiff = DiskOffset + hMiraMonLayer->TopHeader.nElemCount *
3442
155
                                   (pMMPolygonLayer->nPHElementSize);
3443
3444
155
    if (MMInitFlush(&FlushTMP, pMMPolygonLayer->pF, MM_1MB, &pBuffer,
3445
155
                    DiskOffset, 0))
3446
0
    {
3447
0
        if (pBuffer)
3448
0
            VSIFree(pBuffer);
3449
0
        return 1;
3450
0
    }
3451
3452
155
    FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
3453
1.23k
    for (iElem = 0; iElem < hMiraMonLayer->nFinalElemCount; iElem++)
3454
1.08k
    {
3455
        // Bounding box
3456
1.08k
        FlushTMP.SizeOfBlockToBeSaved =
3457
1.08k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX);
3458
1.08k
        FlushTMP.pBlockToBeSaved =
3459
1.08k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX;
3460
1.08k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3461
1.08k
        if (MMAppendBlockToBuffer(&FlushTMP))
3462
0
        {
3463
0
            if (pBuffer)
3464
0
                VSIFree(pBuffer);
3465
0
            return 1;
3466
0
        }
3467
1.08k
        FlushTMP.pBlockToBeSaved =
3468
1.08k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX;
3469
1.08k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3470
1.08k
        if (MMAppendBlockToBuffer(&FlushTMP))
3471
0
        {
3472
0
            if (pBuffer)
3473
0
                VSIFree(pBuffer);
3474
0
            return 1;
3475
0
        }
3476
1.08k
        FlushTMP.pBlockToBeSaved =
3477
1.08k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY;
3478
1.08k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3479
1.08k
        if (MMAppendBlockToBuffer(&FlushTMP))
3480
0
        {
3481
0
            if (pBuffer)
3482
0
                VSIFree(pBuffer);
3483
0
            return 1;
3484
0
        }
3485
1.08k
        FlushTMP.pBlockToBeSaved =
3486
1.08k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY;
3487
1.08k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3488
1.08k
        if (MMAppendBlockToBuffer(&FlushTMP))
3489
0
        {
3490
0
            if (pBuffer)
3491
0
                VSIFree(pBuffer);
3492
0
            return 1;
3493
0
        }
3494
3495
        // Arcs count: number of the arcs of the polygon
3496
1.08k
        if (MMAppendIntegerDependingOnVersion(
3497
1.08k
                hMiraMonLayer, &FlushTMP, &nUL32,
3498
1.08k
                pMMPolygonLayer->pPolHeader[iElem].nArcsCount))
3499
0
        {
3500
0
            if (pBuffer)
3501
0
                VSIFree(pBuffer);
3502
0
            return 1;
3503
0
        }
3504
3505
        // External arcs count: number of external arcs of the polygon
3506
1.08k
        if (MMAppendIntegerDependingOnVersion(
3507
1.08k
                hMiraMonLayer, &FlushTMP, &nUL32,
3508
1.08k
                pMMPolygonLayer->pPolHeader[iElem].nExternalRingsCount))
3509
0
        {
3510
0
            if (pBuffer)
3511
0
                VSIFree(pBuffer);
3512
0
            return 1;
3513
0
        }
3514
3515
        // Rings count: number of rings of the polygon
3516
1.08k
        if (MMAppendIntegerDependingOnVersion(
3517
1.08k
                hMiraMonLayer, &FlushTMP, &nUL32,
3518
1.08k
                pMMPolygonLayer->pPolHeader[iElem].nRingsCount))
3519
0
        {
3520
0
            if (pBuffer)
3521
0
                VSIFree(pBuffer);
3522
0
            return 1;
3523
0
        }
3524
3525
        // Offset: offset of the first vertex of the arc
3526
1.08k
        if (MMAppendIntegerDependingOnVersion(
3527
1.08k
                hMiraMonLayer, &FlushTMP, &nUL32,
3528
1.08k
                pMMPolygonLayer->pPolHeader[iElem].nOffset + nOffsetDiff))
3529
0
        {
3530
0
            if (pBuffer)
3531
0
                VSIFree(pBuffer);
3532
0
            return 1;
3533
0
        }
3534
3535
        // Perimeter of the arc
3536
1.08k
        FlushTMP.SizeOfBlockToBeSaved =
3537
1.08k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfPerimeter);
3538
1.08k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3539
1.08k
        FlushTMP.pBlockToBeSaved =
3540
1.08k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfPerimeter;
3541
1.08k
        if (MMAppendBlockToBuffer(&FlushTMP))
3542
0
        {
3543
0
            if (pBuffer)
3544
0
                VSIFree(pBuffer);
3545
0
            return 1;
3546
0
        }
3547
3548
        // Area of the arc
3549
1.08k
        FlushTMP.SizeOfBlockToBeSaved =
3550
1.08k
            sizeof(pMMPolygonLayer->pPolHeader[iElem].dfArea);
3551
1.08k
        hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3552
1.08k
        FlushTMP.pBlockToBeSaved =
3553
1.08k
            (void *)&pMMPolygonLayer->pPolHeader[iElem].dfArea;
3554
1.08k
        if (MMAppendBlockToBuffer(&FlushTMP))
3555
0
        {
3556
0
            if (pBuffer)
3557
0
                VSIFree(pBuffer);
3558
0
            return 1;
3559
0
        }
3560
1.08k
    }
3561
155
    FlushTMP.SizeOfBlockToBeSaved = 0;
3562
155
    if (MMAppendBlockToBuffer(&FlushTMP))
3563
0
    {
3564
0
        if (pBuffer)
3565
0
            VSIFree(pBuffer);
3566
0
        return 1;
3567
0
    }
3568
3569
155
    if (pBuffer)
3570
155
        VSIFree(pBuffer);
3571
155
    return 0;
3572
155
}
3573
3574
/* -------------------------------------------------------------------- */
3575
/*      Feature Functions                                               */
3576
/* -------------------------------------------------------------------- */
3577
int MMInitFeature(struct MiraMonFeature *hMMFeature)
3578
3.00k
{
3579
3.00k
    memset(hMMFeature, 0, sizeof(*hMMFeature));
3580
3581
3.00k
    hMMFeature->nMaxMRecords = MM_INIT_NUMBER_OF_RECORDS;
3582
3.00k
    if (MMCheckSize_t(hMMFeature->nMaxMRecords,
3583
3.00k
                      sizeof(*(hMMFeature->pRecords))))
3584
0
        return 1;
3585
3586
3.00k
    if (!hMMFeature->nMaxMRecords)
3587
0
        return 0;  // No elements nothing to do.
3588
3589
3.00k
    if ((hMMFeature->pRecords = VSICalloc((size_t)hMMFeature->nMaxMRecords,
3590
3.00k
                                          sizeof(*(hMMFeature->pRecords)))) ==
3591
3.00k
        nullptr)
3592
0
        return 1;
3593
3594
3.00k
    hMMFeature->pRecords[0].nMaxField = MM_INIT_NUMBER_OF_FIELDS;
3595
3.00k
    hMMFeature->pRecords[0].nNumField = 0;
3596
3.00k
    if (MMCheckSize_t(hMMFeature->pRecords[0].nMaxField,
3597
3.00k
                      sizeof(*(hMMFeature->pRecords[0].pField))))
3598
0
        return 1;
3599
3.00k
    if (nullptr == (hMMFeature->pRecords[0].pField =
3600
3.00k
                        VSICalloc((size_t)hMMFeature->pRecords[0].nMaxField,
3601
3.00k
                                  sizeof(*(hMMFeature->pRecords[0].pField)))))
3602
0
        return 1;
3603
3604
3.00k
    return 0;
3605
3.00k
}
3606
3607
// Conserves all allocated memory but resets the information
3608
void MMResetFeatureGeometry(struct MiraMonFeature *hMMFeature)
3609
415k
{
3610
415k
    if (hMMFeature->pNCoordRing)
3611
176k
    {
3612
176k
        memset(hMMFeature->pNCoordRing, 0,
3613
176k
               (size_t)hMMFeature->nMaxpNCoordRing *
3614
176k
                   sizeof(*(hMMFeature->pNCoordRing)));
3615
176k
    }
3616
415k
    if (hMMFeature->pCoord)
3617
176k
    {
3618
176k
        memset(hMMFeature->pCoord, 0,
3619
176k
               (size_t)hMMFeature->nMaxpCoord * sizeof(*(hMMFeature->pCoord)));
3620
176k
    }
3621
415k
    hMMFeature->nICoord = 0;
3622
415k
    if (hMMFeature->pZCoord)
3623
176k
    {
3624
176k
        memset(hMMFeature->pZCoord, 0,
3625
176k
               (size_t)hMMFeature->nMaxpZCoord *
3626
176k
                   sizeof(*(hMMFeature->pZCoord)));
3627
176k
    }
3628
415k
    hMMFeature->nNRings = 0;
3629
415k
    hMMFeature->nIRing = 0;
3630
3631
415k
    if (hMMFeature->flag_VFG)
3632
80.8k
    {
3633
80.8k
        memset(hMMFeature->flag_VFG, 0,
3634
80.8k
               (size_t)hMMFeature->nMaxVFG * sizeof(*(hMMFeature->flag_VFG)));
3635
80.8k
    }
3636
415k
}
3637
3638
// Preserves all allocated memory but initializes it to zero.
3639
void MMResetFeatureRecord(struct MiraMonFeature *hMMFeature)
3640
415k
{
3641
415k
    MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord;
3642
415k
    MM_EXT_DBF_N_FIELDS nIField;
3643
3644
415k
    if (!hMMFeature->pRecords)
3645
460
        return;
3646
3647
830k
    for (nIRecord = 0; nIRecord < hMMFeature->nMaxMRecords; nIRecord++)
3648
415k
    {
3649
415k
        if (!hMMFeature->pRecords[nIRecord].pField)
3650
0
            continue;
3651
8.94M
        for (nIField = 0; nIField < hMMFeature->pRecords[nIRecord].nMaxField;
3652
8.52M
             nIField++)
3653
8.52M
        {
3654
8.52M
            if (hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue)
3655
1.27M
                *(hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue) =
3656
1.27M
                    '\0';
3657
8.52M
            hMMFeature->pRecords[nIRecord].pField[nIField].bIsValid = 0;
3658
8.52M
        }
3659
415k
        hMMFeature->pRecords[nIRecord].nNumField = 0;
3660
415k
    }
3661
415k
    hMMFeature->nNumMRecords = 0;
3662
415k
}
3663
3664
// Destroys all allocated memory
3665
void MMDestroyFeature(struct MiraMonFeature *hMMFeature)
3666
7.96k
{
3667
7.96k
    if (hMMFeature->pCoord)
3668
358
    {
3669
358
        VSIFree(hMMFeature->pCoord);
3670
358
        hMMFeature->pCoord = nullptr;
3671
358
    }
3672
7.96k
    if (hMMFeature->pZCoord)
3673
358
    {
3674
358
        VSIFree(hMMFeature->pZCoord);
3675
358
        hMMFeature->pZCoord = nullptr;
3676
358
    }
3677
7.96k
    if (hMMFeature->pNCoordRing)
3678
358
    {
3679
358
        VSIFree(hMMFeature->pNCoordRing);
3680
358
        hMMFeature->pNCoordRing = nullptr;
3681
358
    }
3682
3683
7.96k
    if (hMMFeature->flag_VFG)
3684
102
    {
3685
102
        VSIFree(hMMFeature->flag_VFG);
3686
102
        hMMFeature->flag_VFG = nullptr;
3687
102
    }
3688
3689
7.96k
    if (hMMFeature->pRecords)
3690
3.00k
    {
3691
3.00k
        MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord;
3692
3.00k
        MM_EXT_DBF_N_FIELDS nIField;
3693
3694
6.01k
        for (nIRecord = 0; nIRecord < hMMFeature->nMaxMRecords; nIRecord++)
3695
3.00k
        {
3696
3.00k
            if (!hMMFeature->pRecords[nIRecord].pField)
3697
0
                continue;
3698
3.00k
            for (nIField = 0;
3699
99.2k
                 nIField < hMMFeature->pRecords[nIRecord].nMaxField; nIField++)
3700
96.2k
            {
3701
96.2k
                if (hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue)
3702
45.2k
                    VSIFree(hMMFeature->pRecords[nIRecord]
3703
45.2k
                                .pField[nIField]
3704
45.2k
                                .pDinValue);
3705
96.2k
            }
3706
3.00k
            VSIFree(hMMFeature->pRecords[nIRecord].pField);
3707
3.00k
        }
3708
3.00k
        VSIFree(hMMFeature->pRecords);
3709
3.00k
        hMMFeature->pRecords = nullptr;
3710
3.00k
    }
3711
3712
7.96k
    hMMFeature->nNRings = 0;
3713
7.96k
    hMMFeature->nNumMRecords = 0;
3714
7.96k
    hMMFeature->nMaxMRecords = 0;
3715
7.96k
}
3716
3717
// Creates a MiraMon polygon, multipolygon, or linestring (arc) feature.
3718
static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer,
3719
                                   struct MiraMonFeature *hMMFeature)
3720
4.83k
{
3721
4.83k
    double *pZ = nullptr;
3722
4.83k
    struct MM_POINT_2D *pCoord, *pCoordReal;
3723
4.83k
    MM_POLYGON_RINGS_COUNT nIPart;
3724
4.83k
    MM_N_VERTICES_TYPE nIVertice;
3725
4.83k
    double dtempx, dtempy;
3726
4.83k
    MM_POLYGON_RINGS_COUNT nExternalRingsCount;
3727
4.83k
    struct MM_PH *pCurrentPolHeader = nullptr;
3728
4.83k
    struct MM_AH *pCurrentArcHeader;
3729
    // To access how many points have been stored in the last stringline
3730
4.83k
    struct MM_AH *pLastArcHeader = nullptr;
3731
4.83k
    struct MM_NH *pCurrentNodeHeader, *pCurrentNodeHeaderPlus1 = nullptr;
3732
4.83k
    uint32_t UnsignedLongNumber;
3733
4.83k
    struct MiraMonArcLayer *pMMArc;
3734
4.83k
    struct MiraMonNodeLayer *pMMNode;
3735
4.83k
    struct MM_TH *pArcTopHeader;
3736
4.83k
    struct MM_TH *pNodeTopHeader;
3737
4.83k
    char VFG = 0;
3738
4.83k
    MM_FILE_OFFSET nOffsetTmp;
3739
4.83k
    struct MM_ZD *pZDesc = nullptr;
3740
4.83k
    struct MM_FLUSH_INFO *pFlushAL, *pFlushNL, *pFlushZL, *pFlushPS, *pFlushPAL;
3741
4.83k
    MM_N_VERTICES_TYPE nPolVertices = 0;
3742
4.83k
    MM_BOOLEAN bReverseArc;
3743
4.83k
    int prevCoord = -1;
3744
4.83k
    MM_BOOLEAN bPolZeroJustCreated = FALSE;
3745
3746
4.83k
    if (!hMiraMonLayer)
3747
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
3748
3749
4.83k
    if (!hMMFeature)
3750
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
3751
3752
    // Setting pointer to 3D structure (if exists).
3753
4.83k
    if (hMiraMonLayer->TopHeader.bIs3d)
3754
4.83k
        pZ = hMMFeature->pZCoord;
3755
3756
    // Setting pointers to arc/node structures.
3757
4.83k
    if (hMiraMonLayer->bIsPolygon)
3758
1.70k
    {
3759
1.70k
        pMMArc = &hMiraMonLayer->MMPolygon.MMArc;
3760
1.70k
        pArcTopHeader = &hMiraMonLayer->MMPolygon.TopArcHeader;
3761
3762
1.70k
        pMMNode = &hMiraMonLayer->MMPolygon.MMArc.MMNode;
3763
1.70k
        pNodeTopHeader = &hMiraMonLayer->MMPolygon.MMArc.TopNodeHeader;
3764
1.70k
    }
3765
3.13k
    else
3766
3.13k
    {
3767
3.13k
        pMMArc = &hMiraMonLayer->MMArc;
3768
3.13k
        pArcTopHeader = &hMiraMonLayer->TopHeader;
3769
3770
3.13k
        pMMNode = &hMiraMonLayer->MMArc.MMNode;
3771
3.13k
        pNodeTopHeader = &hMiraMonLayer->MMArc.TopNodeHeader;
3772
3.13k
    }
3773
3774
    // Setting pointers to polygon structures
3775
4.83k
    if (hMiraMonLayer->bIsPolygon)
3776
1.70k
    {
3777
1.70k
        if (MMResizePolHeaderPointer(&hMiraMonLayer->MMPolygon.pPolHeader,
3778
1.70k
                                     &hMiraMonLayer->MMPolygon.nMaxPolHeader,
3779
1.70k
                                     hMiraMonLayer->TopHeader.nElemCount,
3780
1.70k
                                     MM_INCR_NUMBER_OF_POLYGONS, 0))
3781
0
        {
3782
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
3783
0
                     "Memory error in MiraMon "
3784
0
                     "driver (MMResizePolHeaderPointer())");
3785
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
3786
0
        }
3787
3788
1.70k
        pCurrentPolHeader = hMiraMonLayer->MMPolygon.pPolHeader +
3789
1.70k
                            hMiraMonLayer->TopHeader.nElemCount;
3790
1.70k
        MMInitBoundingBox(&pCurrentPolHeader->dfBB);
3791
3792
1.70k
        pCurrentPolHeader->dfPerimeter = 0;
3793
1.70k
        pCurrentPolHeader->dfArea = 0L;
3794
1.70k
    }
3795
3796
    // Setting flushes to all sections described in
3797
    // format specifications document.
3798
4.83k
    pFlushAL = &pMMArc->FlushAL;
3799
4.83k
    pFlushNL = &pMMNode->FlushNL;
3800
4.83k
    pFlushZL = &pMMArc->pZSection.FlushZL;
3801
4.83k
    pFlushPS = &hMiraMonLayer->MMPolygon.FlushPS;
3802
4.83k
    pFlushPAL = &hMiraMonLayer->MMPolygon.FlushPAL;
3803
3804
4.83k
    pFlushNL->pBlockWhereToSaveOrRead = (void *)pMMNode->pNL;
3805
4.83k
    pFlushAL->pBlockWhereToSaveOrRead = (void *)pMMArc->pAL;
3806
4.83k
    if (hMiraMonLayer->TopHeader.bIs3d)
3807
4.83k
        pFlushZL->pBlockWhereToSaveOrRead = (void *)pMMArc->pZSection.pZL;
3808
4.83k
    if (hMiraMonLayer->bIsPolygon)
3809
1.70k
    {
3810
1.70k
        pFlushPS->pBlockWhereToSaveOrRead =
3811
1.70k
            (void *)hMiraMonLayer->MMPolygon.pPS;
3812
1.70k
        pFlushPAL->pBlockWhereToSaveOrRead =
3813
1.70k
            (void *)hMiraMonLayer->MMPolygon.pPAL;
3814
1.70k
    }
3815
3816
    // Creation of the MiraMon extended database
3817
4.83k
    if (!hMiraMonLayer->bIsPolygon)
3818
3.13k
    {
3819
3.13k
        if (hMiraMonLayer->TopHeader.nElemCount == 0)
3820
1.61k
        {
3821
1.61k
            CPLDebugOnly("MiraMon", "Creating MiraMon database");
3822
1.61k
            if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord))
3823
1.45k
                return MM_FATAL_ERROR_WRITING_FEATURES;
3824
157
            CPLDebugOnly("MiraMon", "MiraMon database created. "
3825
157
                                    "Creating features...");
3826
157
        }
3827
3.13k
    }
3828
1.70k
    else
3829
1.70k
    {  // Universal polygon has been created
3830
1.70k
        if (hMiraMonLayer->TopHeader.nElemCount == 1)
3831
880
        {
3832
880
            CPLDebugOnly("MiraMon", "Creating MiraMon database");
3833
880
            if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord))
3834
721
                return MM_FATAL_ERROR_WRITING_FEATURES;
3835
159
            CPLDebugOnly("MiraMon", "MiraMon database created. "
3836
159
                                    "Creating features...");
3837
3838
            // Universal polygon have a record with ID_GRAFIC=0 and blancs
3839
159
            if (MMAddPolygonRecordToMMDB(hMiraMonLayer, nullptr, 0, 0, nullptr))
3840
0
            {
3841
                // Rare case where polygon zero creates the database
3842
                // but some error occurs in the creation of the polygon zero.
3843
                // The database must be destroyed and created again
3844
                // next time the polygon zero is created.
3845
0
                MMCloseMMBD_XP(hMiraMonLayer);
3846
0
                MMDestroyMMDB(hMiraMonLayer);
3847
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
3848
0
            }
3849
159
            bPolZeroJustCreated = TRUE;
3850
159
        }
3851
1.70k
    }
3852
3853
    // Checking if its possible continue writing the file due
3854
    // to version limitations.
3855
2.66k
    if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
3856
2.66k
    {
3857
2.66k
        MM_FILE_OFFSET nNodeOffset, nArcOffset;
3858
2.66k
        MM_INTERNAL_FID nArcElemCount, nNodeElemCount;
3859
2.66k
        GInt32 nLastZCount = 0;
3860
2.66k
        MM_FILE_OFFSET nLastOffsetZ = 0;
3861
2.66k
        MM_INTERNAL_FID nLastElemCount = 0;
3862
2.66k
        nNodeOffset = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
3863
2.66k
        nArcOffset = pMMArc->nOffsetArc;
3864
3865
2.66k
        nArcElemCount = pArcTopHeader->nElemCount;
3866
2.66k
        nNodeElemCount = pNodeTopHeader->nElemCount;
3867
5.24k
        for (nIPart = 0; nIPart < hMMFeature->nNRings; nIPart++,
3868
2.58k
            nArcElemCount++,
3869
2.58k
            nNodeElemCount += (hMiraMonLayer->bIsPolygon ? 1 : 2))
3870
2.58k
        {
3871
            // There is space for the element that is going to be written?
3872
            // Polygon or arc
3873
2.58k
            if (MMCheckVersionForFID(hMiraMonLayer,
3874
2.58k
                                     hMiraMonLayer->TopHeader.nElemCount))
3875
0
            {
3876
0
                CPLError(CE_Failure, CPLE_NotSupported,
3877
0
                         "Error in MMCheckVersionForFID() (1)");
3878
0
                return MM_STOP_WRITING_FEATURES;
3879
0
            }
3880
3881
            // Arc if there is no polygon
3882
2.58k
            if (MMCheckVersionForFID(hMiraMonLayer, nArcElemCount))
3883
0
            {
3884
0
                CPLError(CE_Failure, CPLE_NotSupported,
3885
0
                         "Error in MMCheckVersionForFID() (2)");
3886
0
                return MM_STOP_WRITING_FEATURES;
3887
0
            }
3888
3889
            // Nodes
3890
2.58k
            if (MMCheckVersionForFID(hMiraMonLayer, nNodeElemCount))
3891
0
            {
3892
0
                CPLError(CE_Failure, CPLE_NotSupported,
3893
0
                         "Error in MMCheckVersionForFID() (3)");
3894
0
                return MM_STOP_WRITING_FEATURES;
3895
0
            }
3896
3897
            // There is space for the last node(s) that is(are) going to be written?
3898
2.58k
            if (!hMiraMonLayer->bIsPolygon)
3899
1.68k
            {
3900
1.68k
                if (MMCheckVersionForFID(hMiraMonLayer, nNodeElemCount + 1))
3901
0
                {
3902
0
                    CPLError(CE_Failure, CPLE_NotSupported,
3903
0
                             "Error in MMCheckVersionForFID() (4)");
3904
0
                    return MM_STOP_WRITING_FEATURES;
3905
0
                }
3906
1.68k
            }
3907
3908
            // Checking offsets
3909
            // AL: check the last point
3910
2.58k
            if (MMCheckVersionOffset(hMiraMonLayer, nArcOffset))
3911
0
            {
3912
0
                CPLDebugOnly("MiraMon", "Error in MMCheckVersionOffset() (0)");
3913
0
                return MM_STOP_WRITING_FEATURES;
3914
0
            }
3915
            // Setting next offset
3916
2.58k
            nArcOffset +=
3917
2.58k
                (hMMFeature->pNCoordRing[nIPart]) * pMMArc->nALElementSize;
3918
3919
            // NL: check the last node
3920
2.58k
            if (hMiraMonLayer->bIsPolygon)
3921
906
                nNodeOffset += (hMMFeature->nNRings) * MM_SIZE_OF_NL_32BITS;
3922
1.68k
            else
3923
1.68k
                nNodeOffset += (2 * hMMFeature->nNRings) * MM_SIZE_OF_NL_32BITS;
3924
3925
2.58k
            if (MMCheckVersionOffset(hMiraMonLayer, nNodeOffset))
3926
0
            {
3927
0
                CPLDebugOnly("MiraMon", "Error in MMCheckVersionOffset() (1)");
3928
0
                return MM_STOP_WRITING_FEATURES;
3929
0
            }
3930
            // Setting next offset
3931
2.58k
            nNodeOffset += MM_SIZE_OF_NL_32BITS;
3932
3933
2.58k
            if (!hMiraMonLayer->bIsPolygon)
3934
1.68k
            {
3935
1.68k
                if (MMCheckVersionOffset(hMiraMonLayer, nNodeOffset))
3936
0
                {
3937
0
                    CPLDebugOnly("MiraMon",
3938
0
                                 "Error in MMCheckVersionOffset() (2)");
3939
0
                    return MM_STOP_WRITING_FEATURES;
3940
0
                }
3941
                // Setting next offset
3942
1.68k
                nNodeOffset += MM_SIZE_OF_NL_32BITS;
3943
1.68k
            }
3944
3945
            // Where 3D part is going to start
3946
2.58k
            if (hMiraMonLayer->TopHeader.bIs3d)
3947
2.58k
            {
3948
2.58k
                if (nArcElemCount == 0)
3949
238
                {
3950
238
                    if (MMCheckVersionFor3DOffset(hMiraMonLayer,
3951
238
                                                  nArcElemCount + 1, 0, 0))
3952
0
                        return MM_STOP_WRITING_FEATURES;
3953
238
                }
3954
2.35k
                else
3955
2.35k
                {
3956
2.35k
                    pZDesc = pMMArc->pZSection.pZDescription;
3957
2.35k
                    if (!pZDesc)
3958
0
                    {
3959
0
                        CPLError(CE_Failure, CPLE_ObjectNull,
3960
0
                                 "Error: pZDescription should not be nullptr");
3961
0
                        return MM_STOP_WRITING_FEATURES;
3962
0
                    }
3963
3964
2.35k
                    if (nIPart == 0)
3965
1.98k
                    {
3966
1.98k
                        nLastZCount = pZDesc[nArcElemCount - 1].nZCount;
3967
1.98k
                        nLastOffsetZ = pZDesc[nArcElemCount - 1].nOffsetZ;
3968
1.98k
                    }
3969
3970
2.35k
                    if (nLastZCount < 0)
3971
2.29k
                    {
3972
                        // One altitude was written on last element
3973
2.29k
                        if (MMCheckVersionFor3DOffset(
3974
2.29k
                                hMiraMonLayer, nArcElemCount + 1, nArcOffset,
3975
2.29k
                                nLastOffsetZ + sizeof(*pZ)))
3976
0
                            return MM_STOP_WRITING_FEATURES;
3977
3978
                        // For the next iteration in this multipart feature
3979
2.29k
                        nLastOffsetZ += sizeof(*pZ);
3980
2.29k
                    }
3981
59
                    else
3982
59
                    {
3983
                        // One for each vertice altitude was written on last element
3984
59
                        if (nIPart == 0)
3985
14
                        {
3986
14
                            nLastElemCount = (pMMArc->pArcHeader +
3987
14
                                              pArcTopHeader->nElemCount - 1)
3988
14
                                                 ->nElemCount;
3989
14
                        }
3990
45
                        else
3991
45
                        {
3992
45
                            nLastElemCount += hMMFeature->pNCoordRing[nIPart];
3993
45
                        }
3994
3995
59
                        if (MMCheckVersionFor3DOffset(
3996
59
                                hMiraMonLayer, nArcElemCount + 1, nArcOffset,
3997
59
                                nLastOffsetZ + sizeof(*pZ) * nLastElemCount))
3998
0
                            return MM_STOP_WRITING_FEATURES;
3999
4000
                        // For the next iteration in this multipart feature
4001
59
                        nLastOffsetZ += sizeof(*pZ) * nLastElemCount;
4002
59
                    }
4003
2.35k
                }
4004
2.58k
            }
4005
2.58k
        }
4006
2.66k
    }
4007
4008
    // Going through parts of the feature.
4009
2.66k
    nExternalRingsCount = 0;
4010
2.66k
    pCoord = hMMFeature->pCoord;
4011
4012
2.66k
    if (!pCoord)
4013
51
    {
4014
51
        if (bPolZeroJustCreated)
4015
51
        {
4016
            // Rare case where polygon zero creates the database
4017
            // but some error occurs in the creation of the polygon zero.
4018
            // The database must be destroyed and created again
4019
            // next time the polygon zero is created.
4020
51
            MMCloseMMBD_XP(hMiraMonLayer);
4021
51
            MMDestroyMMDB(hMiraMonLayer);
4022
51
        }
4023
51
        return MM_FATAL_ERROR_WRITING_FEATURES;
4024
51
    }
4025
4026
    // Doing real job
4027
5.19k
    for (nIPart = 0; nIPart < hMMFeature->nNRings; nIPart++,
4028
2.58k
        pArcTopHeader->nElemCount++,
4029
2.58k
        pNodeTopHeader->nElemCount += (hMiraMonLayer->bIsPolygon ? 1 : 2))
4030
2.58k
    {
4031
        // Resize structures if necessary
4032
2.58k
        if (MMResizeArcHeaderPointer(
4033
2.58k
                &pMMArc->pArcHeader, &pMMArc->nMaxArcHeader,
4034
2.58k
                pArcTopHeader->nElemCount + 1, MM_INCR_NUMBER_OF_ARCS, 0))
4035
0
        {
4036
0
            CPLDebugOnly("MiraMon", "Error in MMResizeArcHeaderPointer()");
4037
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
4038
0
                     "Memory error in MiraMon "
4039
0
                     "driver (MMCreateFeaturePolOrArc())");
4040
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
4041
0
        }
4042
2.58k
        if (MMResizeNodeHeaderPointer(
4043
2.58k
                &pMMNode->pNodeHeader, &pMMNode->nMaxNodeHeader,
4044
2.58k
                hMiraMonLayer->bIsPolygon ? pNodeTopHeader->nElemCount + 1
4045
2.58k
                                          : pNodeTopHeader->nElemCount + 2,
4046
2.58k
                MM_INCR_NUMBER_OF_NODES, 0))
4047
0
        {
4048
0
            CPLDebugOnly("MiraMon", "Error in MMResizeNodeHeaderPointer()");
4049
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
4050
0
                     "Memory error in MiraMon "
4051
0
                     "driver (MMCreateFeaturePolOrArc())");
4052
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
4053
0
        }
4054
4055
2.58k
        if (hMiraMonLayer->TopHeader.bIs3d)
4056
2.58k
        {
4057
2.58k
            if (MMResizeZSectionDescrPointer(
4058
2.58k
                    &pMMArc->pZSection.pZDescription,
4059
2.58k
                    &pMMArc->pZSection.nMaxZDescription, pMMArc->nMaxArcHeader,
4060
2.58k
                    MM_INCR_NUMBER_OF_ARCS, 0))
4061
0
            {
4062
0
                CPLDebugOnly("MiraMon",
4063
0
                             "Error in MMResizeZSectionDescrPointer()");
4064
0
                CPLError(CE_Failure, CPLE_OutOfMemory,
4065
0
                         "Memory error in MiraMon "
4066
0
                         "driver (MMCreateFeaturePolOrArc())");
4067
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4068
0
            }
4069
2.58k
            pZDesc = pMMArc->pZSection.pZDescription;
4070
2.58k
        }
4071
4072
        // Setting pointers to current headers
4073
2.58k
        pCurrentArcHeader = pMMArc->pArcHeader + pArcTopHeader->nElemCount;
4074
2.58k
        MMInitBoundingBox(&pCurrentArcHeader->dfBB);
4075
4076
2.58k
        pCurrentNodeHeader = pMMNode->pNodeHeader + pNodeTopHeader->nElemCount;
4077
2.58k
        if (!hMiraMonLayer->bIsPolygon)
4078
1.68k
            pCurrentNodeHeaderPlus1 = pCurrentNodeHeader + 1;
4079
4080
        // Initializing feature information (section AH/PH)
4081
2.58k
        pCurrentArcHeader->nElemCount = hMMFeature->pNCoordRing[nIPart];
4082
2.58k
        pCurrentArcHeader->dfLength = 0.0;
4083
2.58k
        pCurrentArcHeader->nOffset =
4084
2.58k
            pFlushAL->TotalSavedBytes + pFlushAL->nNumBytes;
4085
4086
        // Dumping vertices and calculating stuff that
4087
        // MiraMon needs (longitude/perimeter, area)
4088
2.58k
        bReverseArc = FALSE;
4089
2.58k
        if (hMiraMonLayer->bIsPolygon)
4090
906
        {
4091
906
            VFG = hMMFeature->flag_VFG[nIPart];
4092
906
            bReverseArc = (VFG & MM_ROTATE_ARC) ? TRUE : FALSE;
4093
906
        }
4094
4095
2.58k
        if (bReverseArc)
4096
326
        {
4097
326
            prevCoord = 1;  // to find previous coordinate
4098
326
            pCoordReal = pCoord + pCurrentArcHeader->nElemCount - 1;
4099
326
        }
4100
2.26k
        else
4101
2.26k
        {
4102
2.26k
            prevCoord = -1;  // to find previous coordinate
4103
2.26k
            pCoordReal = pCoord;
4104
2.26k
        }
4105
4106
9.85k
        for (nIVertice = 0; nIVertice < pCurrentArcHeader->nElemCount;
4107
7.26k
             nIVertice++, (bReverseArc) ? pCoordReal-- : pCoordReal++)
4108
7.26k
        {
4109
            // Writing the arc in the normal way
4110
7.26k
            pFlushAL->SizeOfBlockToBeSaved = sizeof(pCoordReal->dfX);
4111
7.26k
            pFlushAL->pBlockToBeSaved = (void *)&(pCoord + nIVertice)->dfX;
4112
7.26k
            if (MMAppendBlockToBuffer(pFlushAL))
4113
0
            {
4114
0
                CPLDebugOnly("MiraMon", "Error in MMAppendBlockToBuffer() (1)");
4115
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4116
0
            }
4117
4118
7.26k
            pFlushAL->pBlockToBeSaved = (void *)&(pCoord + nIVertice)->dfY;
4119
7.26k
            if (MMAppendBlockToBuffer(pFlushAL))
4120
0
            {
4121
0
                CPLDebugOnly("MiraMon", "Error in MMAppendBlockToBuffer() (2)");
4122
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4123
0
            }
4124
4125
            // Calculating stuff using the inverse coordinates if it's needed
4126
7.26k
            MMUpdateBoundingBoxXY(&pCurrentArcHeader->dfBB, pCoordReal);
4127
7.26k
            if (nIVertice == 0 ||
4128
6.39k
                nIVertice == pCurrentArcHeader->nElemCount - 1)
4129
1.57k
                MMUpdateBoundingBoxXY(&pNodeTopHeader->hBB, pCoordReal);
4130
7.26k
            if (nIVertice > 0)
4131
6.39k
            {
4132
6.39k
                dtempx = pCoordReal->dfX - (pCoordReal + prevCoord)->dfX;
4133
6.39k
                dtempy = pCoordReal->dfY - (pCoordReal + prevCoord)->dfY;
4134
6.39k
                pCurrentArcHeader->dfLength +=
4135
6.39k
                    sqrt(dtempx * dtempx + dtempy * dtempy);
4136
6.39k
                if (hMiraMonLayer->bIsPolygon && pCurrentPolHeader)
4137
483
                {
4138
483
                    pCurrentPolHeader->dfArea +=
4139
483
                        (pCoordReal->dfX * (pCoordReal + prevCoord)->dfY -
4140
483
                         (pCoordReal + prevCoord)->dfX * pCoordReal->dfY);
4141
483
                }
4142
6.39k
            }
4143
7.26k
        }
4144
2.58k
        if (bReverseArc)
4145
326
            pCoord = pCoordReal + pCurrentArcHeader->nElemCount + 1;
4146
2.26k
        else
4147
2.26k
            pCoord += pCurrentArcHeader->nElemCount;
4148
4149
2.58k
        nPolVertices += pCurrentArcHeader->nElemCount;
4150
4151
        // Updating bounding boxes
4152
2.58k
        MMUpdateBoundingBox(&pArcTopHeader->hBB, &pCurrentArcHeader->dfBB);
4153
2.58k
        if (hMiraMonLayer->bIsPolygon)
4154
906
            MMUpdateBoundingBox(&hMiraMonLayer->TopHeader.hBB,
4155
906
                                &pCurrentArcHeader->dfBB);
4156
4157
2.58k
        pMMArc->nOffsetArc +=
4158
2.58k
            (pCurrentArcHeader->nElemCount) * pMMArc->nALElementSize;
4159
4160
2.58k
        pCurrentArcHeader->nFirstIdNode = (2 * pArcTopHeader->nElemCount);
4161
2.58k
        if (hMiraMonLayer->bIsPolygon)
4162
906
        {
4163
906
            pCurrentArcHeader->nFirstIdNode = pArcTopHeader->nElemCount;
4164
906
            pCurrentArcHeader->nLastIdNode = pArcTopHeader->nElemCount;
4165
906
        }
4166
1.68k
        else
4167
1.68k
        {
4168
1.68k
            pCurrentArcHeader->nFirstIdNode = (2 * pArcTopHeader->nElemCount);
4169
1.68k
            pCurrentArcHeader->nLastIdNode =
4170
1.68k
                (2 * pArcTopHeader->nElemCount + 1);
4171
1.68k
        }
4172
2.58k
        if (MMAddArcRecordToMMDB(hMiraMonLayer, hMMFeature,
4173
2.58k
                                 pArcTopHeader->nElemCount, pCurrentArcHeader))
4174
0
        {
4175
0
            CPLDebugOnly("MiraMon", "Error in MMAddArcRecordToMMDB()");
4176
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
4177
0
        }
4178
4179
        // Node Stuff: writing NL section
4180
2.58k
        pCurrentNodeHeader->nArcsCount = 1;
4181
2.58k
        if (hMiraMonLayer->bIsPolygon)
4182
906
            pCurrentNodeHeader->cNodeType = MM_RING_NODE;
4183
1.68k
        else
4184
1.68k
            pCurrentNodeHeader->cNodeType = MM_FINAL_NODE;
4185
4186
2.58k
        pCurrentNodeHeader->nOffset =
4187
2.58k
            pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
4188
2.58k
        if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushNL,
4189
2.58k
                                              &UnsignedLongNumber,
4190
2.58k
                                              pArcTopHeader->nElemCount))
4191
0
        {
4192
0
            CPLDebugOnly("MiraMon",
4193
0
                         "Error in MMAppendIntegerDependingOnVersion()");
4194
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
4195
0
        }
4196
4197
        // 8bytes alignment
4198
2.58k
        nOffsetTmp = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
4199
2.58k
        MMGetOffsetAlignedTo8(&nOffsetTmp);
4200
2.58k
        if (nOffsetTmp != pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes)
4201
2.58k
        {
4202
2.58k
            pFlushNL->SizeOfBlockToBeSaved =
4203
2.58k
                (size_t)(nOffsetTmp -
4204
2.58k
                         (pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes));
4205
2.58k
            pFlushNL->pBlockToBeSaved = (void *)nullptr;
4206
2.58k
            if (MMAppendBlockToBuffer(pFlushNL))
4207
0
            {
4208
0
                CPLDebugOnly("MiraMon", "Error in MMAppendBlockToBuffer() (3)");
4209
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4210
0
            }
4211
2.58k
        }
4212
2.58k
        if (MMAddNodeRecordToMMDB(hMiraMonLayer, pNodeTopHeader->nElemCount,
4213
2.58k
                                  pCurrentNodeHeader))
4214
0
        {
4215
0
            CPLDebugOnly("MiraMon", "Error in MMAddNodeRecordToMMDB()");
4216
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
4217
0
        }
4218
4219
2.58k
        if (!hMiraMonLayer->bIsPolygon)
4220
1.68k
        {
4221
1.68k
            pCurrentNodeHeaderPlus1->nArcsCount = 1;
4222
1.68k
            if (hMiraMonLayer->bIsPolygon)
4223
0
                pCurrentNodeHeaderPlus1->cNodeType = MM_RING_NODE;
4224
1.68k
            else
4225
1.68k
                pCurrentNodeHeaderPlus1->cNodeType = MM_FINAL_NODE;
4226
4227
1.68k
            pCurrentNodeHeaderPlus1->nOffset =
4228
1.68k
                pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
4229
4230
1.68k
            if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushNL,
4231
1.68k
                                                  &UnsignedLongNumber,
4232
1.68k
                                                  pArcTopHeader->nElemCount))
4233
0
            {
4234
0
                CPLDebugOnly("MiraMon",
4235
0
                             "Error in MMAppendIntegerDependingOnVersion()");
4236
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4237
0
            }
4238
4239
            // 8bytes alignment
4240
1.68k
            nOffsetTmp = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
4241
1.68k
            MMGetOffsetAlignedTo8(&nOffsetTmp);
4242
1.68k
            if (nOffsetTmp != pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes)
4243
1.68k
            {
4244
1.68k
                pFlushNL->SizeOfBlockToBeSaved =
4245
1.68k
                    (size_t)(nOffsetTmp -
4246
1.68k
                             (pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes));
4247
1.68k
                pFlushNL->pBlockToBeSaved = (void *)nullptr;
4248
1.68k
                if (MMAppendBlockToBuffer(pFlushNL))
4249
0
                {
4250
0
                    CPLDebugOnly("MiraMon", "Error in MMAppendBlockToBuffer()");
4251
0
                    return MM_FATAL_ERROR_WRITING_FEATURES;
4252
0
                }
4253
1.68k
            }
4254
1.68k
            if (MMAddNodeRecordToMMDB(hMiraMonLayer,
4255
1.68k
                                      pNodeTopHeader->nElemCount + 1,
4256
1.68k
                                      pCurrentNodeHeaderPlus1))
4257
0
            {
4258
0
                CPLDebugOnly("MiraMon", "Error in MMAddNodeRecordToMMDB()");
4259
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4260
0
            }
4261
1.68k
        }
4262
4263
        // 3D stuff
4264
2.58k
        if (hMiraMonLayer->TopHeader.bIs3d && pZDesc)
4265
2.58k
        {
4266
2.58k
            pZDesc[pArcTopHeader->nElemCount].dfBBminz =
4267
2.58k
                STATISTICAL_UNDEF_VALUE;
4268
2.58k
            pZDesc[pArcTopHeader->nElemCount].dfBBmaxz =
4269
2.58k
                -STATISTICAL_UNDEF_VALUE;
4270
4271
            // Number of arc altitudes. If the number of altitudes is
4272
            // positive this indicates the number of altitudes for
4273
            // each vertex of the arc, and all the altitudes of the
4274
            // vertex 0 are written first, then those of the vertex 1,
4275
            // etc. If the number of altitudes is negative this
4276
            // indicates the number of arc altitudes, understanding
4277
            // that all the vertices have the same altitude (it is
4278
            // the case of a contour line, for example).
4279
4280
2.62k
            for (nIVertice = 0; nIVertice < pCurrentArcHeader->nElemCount;
4281
2.58k
                 nIVertice++, pZ++)
4282
898
            {
4283
898
                pFlushZL->SizeOfBlockToBeSaved = sizeof(*pZ);
4284
898
                pFlushZL->pBlockToBeSaved = (void *)pZ;
4285
898
                if (MMAppendBlockToBuffer(pFlushZL))
4286
0
                {
4287
0
                    CPLDebugOnly("MiraMon", "Error in MMAppendBlockToBuffer()");
4288
0
                    return MM_FATAL_ERROR_WRITING_FEATURES;
4289
0
                }
4290
4291
898
                if (pZDesc[pArcTopHeader->nElemCount].dfBBminz > *pZ)
4292
893
                    pZDesc[pArcTopHeader->nElemCount].dfBBminz = *pZ;
4293
898
                if (pZDesc[pArcTopHeader->nElemCount].dfBBmaxz < *pZ)
4294
875
                    pZDesc[pArcTopHeader->nElemCount].dfBBmaxz = *pZ;
4295
4296
898
                if (pMMArc->pZSection.ZHeader.dfBBminz > *pZ)
4297
172
                    pMMArc->pZSection.ZHeader.dfBBminz = *pZ;
4298
898
                if (pMMArc->pZSection.ZHeader.dfBBmaxz < *pZ)
4299
198
                    pMMArc->pZSection.ZHeader.dfBBmaxz = *pZ;
4300
4301
                // Only one altitude (the same for all vertices) is written
4302
898
                if (hMMFeature->bAllZHaveSameValue)
4303
858
                    break;
4304
898
            }
4305
2.58k
            if (hMMFeature->bAllZHaveSameValue)
4306
2.57k
            {
4307
                // Same altitude for all vertices
4308
2.57k
                pZDesc[pArcTopHeader->nElemCount].nZCount = -1;
4309
2.57k
            }
4310
16
            else
4311
16
            {
4312
                // One different altitude for each vertice
4313
16
                pZDesc[pArcTopHeader->nElemCount].nZCount = 1;
4314
16
            }
4315
4316
2.58k
            if (pArcTopHeader->nElemCount == 0)
4317
238
                pZDesc[pArcTopHeader->nElemCount].nOffsetZ = 0;
4318
2.35k
            else
4319
2.35k
            {
4320
2.35k
                if (pZDesc[pArcTopHeader->nElemCount - 1].nZCount < 0)
4321
2.33k
                {
4322
2.33k
                    pZDesc[pArcTopHeader->nElemCount].nOffsetZ =
4323
2.33k
                        pZDesc[pArcTopHeader->nElemCount - 1].nOffsetZ +
4324
2.33k
                        sizeof(*pZ);
4325
2.33k
                }
4326
16
                else
4327
16
                {
4328
16
                    pLastArcHeader =
4329
16
                        pMMArc->pArcHeader + pArcTopHeader->nElemCount - 1;
4330
4331
16
                    pZDesc[pArcTopHeader->nElemCount].nOffsetZ =
4332
16
                        pZDesc[pArcTopHeader->nElemCount - 1].nOffsetZ +
4333
16
                        sizeof(*pZ) * (pLastArcHeader->nElemCount);
4334
16
                }
4335
2.35k
            }
4336
2.58k
        }
4337
4338
        // Exclusive polygon stuff
4339
2.58k
        if (hMiraMonLayer->bIsPolygon && pCurrentPolHeader)
4340
906
        {
4341
            // PS SECTION
4342
906
            if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushPS,
4343
906
                                                  &UnsignedLongNumber, 0))
4344
0
            {
4345
0
                CPLDebugOnly("MiraMon",
4346
0
                             "Error in MMAppendIntegerDependingOnVersion()");
4347
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4348
0
            }
4349
4350
906
            if (MMAppendIntegerDependingOnVersion(
4351
906
                    hMiraMonLayer, pFlushPS, &UnsignedLongNumber,
4352
906
                    hMiraMonLayer->TopHeader.nElemCount))
4353
0
            {
4354
0
                CPLDebugOnly("MiraMon",
4355
0
                             "Error in MMAppendIntegerDependingOnVersion()");
4356
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4357
0
            }
4358
4359
            // PAL SECTION
4360
            // Vertices of rings defining
4361
            // holes in polygons are in a counterclockwise direction.
4362
            // Holes are at the end of all external rings that contain the holes!!
4363
906
            if (VFG & MM_EXTERIOR_ARC_SIDE)
4364
542
                nExternalRingsCount++;
4365
4366
906
            pCurrentPolHeader->nArcsCount++;
4367
            //(MM_POLYGON_ARCS_COUNT)hMMFeature->nNRings;
4368
906
            if (VFG & MM_EXTERIOR_ARC_SIDE)
4369
542
                pCurrentPolHeader
4370
542
                    ->nExternalRingsCount++;  //= nExternalRingsCount;
4371
4372
906
            if (VFG & MM_END_ARC_IN_RING)
4373
906
                pCurrentPolHeader->nRingsCount++;  //= hMMFeature->nNRings;
4374
906
            if (nIPart == 0)
4375
542
            {
4376
542
                pCurrentPolHeader->nOffset =
4377
542
                    pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes;
4378
542
            }
4379
4380
906
            if (nIPart == hMMFeature->nNRings - 1)
4381
542
                pCurrentPolHeader->dfArea /= 2;
4382
4383
906
            pFlushPAL->SizeOfBlockToBeSaved = 1;
4384
906
            pFlushPAL->pBlockToBeSaved = (void *)&VFG;
4385
906
            if (MMAppendBlockToBuffer(pFlushPAL))
4386
0
            {
4387
0
                CPLDebugOnly("MiraMon", "Error in MMAppendBlockToBuffer()");
4388
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4389
0
            }
4390
4391
906
            if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushPAL,
4392
906
                                                  &UnsignedLongNumber,
4393
906
                                                  pArcTopHeader->nElemCount))
4394
0
            {
4395
0
                CPLDebugOnly("MiraMon",
4396
0
                             "Error in MMAppendIntegerDependingOnVersion()");
4397
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4398
0
            }
4399
4400
            // 8bytes alignment
4401
906
            if (nIPart == hMMFeature->nNRings - 1)
4402
542
            {
4403
542
                nOffsetTmp = pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes;
4404
542
                MMGetOffsetAlignedTo8(&nOffsetTmp);
4405
4406
542
                if (nOffsetTmp !=
4407
542
                    pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes)
4408
542
                {
4409
542
                    pFlushPAL->SizeOfBlockToBeSaved =
4410
542
                        (size_t)(nOffsetTmp - (pFlushPAL->TotalSavedBytes +
4411
542
                                               pFlushPAL->nNumBytes));
4412
542
                    pFlushPAL->pBlockToBeSaved = (void *)nullptr;
4413
542
                    if (MMAppendBlockToBuffer(pFlushPAL))
4414
0
                    {
4415
0
                        CPLDebugOnly("MiraMon",
4416
0
                                     "Error in MMAppendBlockToBuffer()");
4417
0
                        return MM_FATAL_ERROR_WRITING_FEATURES;
4418
0
                    }
4419
542
                }
4420
542
            }
4421
4422
906
            MMUpdateBoundingBox(&pCurrentPolHeader->dfBB,
4423
906
                                &pCurrentArcHeader->dfBB);
4424
906
            pCurrentPolHeader->dfPerimeter += pCurrentArcHeader->dfLength;
4425
906
        }
4426
2.58k
    }
4427
4428
    // Updating element count and if the polygon is multipart.
4429
    // MiraMon does not accept multipoints or multilines, only multipolygons.
4430
2.61k
    if (hMiraMonLayer->bIsPolygon)
4431
928
    {
4432
928
        if (MMAddPolygonRecordToMMDB(hMiraMonLayer, hMMFeature,
4433
928
                                     hMiraMonLayer->TopHeader.nElemCount,
4434
928
                                     nPolVertices, pCurrentPolHeader))
4435
0
        {
4436
0
            CPLDebugOnly("MiraMon", "Error in MMAddPolygonRecordToMMDB()");
4437
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
4438
0
        }
4439
928
        hMiraMonLayer->TopHeader.nElemCount++;
4440
4441
928
        if (nExternalRingsCount > 1)
4442
0
            hMiraMonLayer->TopHeader.bIsMultipolygon = TRUE;
4443
928
    }
4444
4445
2.61k
    return MM_CONTINUE_WRITING_FEATURES;
4446
2.61k
}  // End of de MMCreateFeaturePolOrArc()
4447
4448
// Creates a MiraMon DBF record when not associated with a geometric feature.
4449
static int MMCreateRecordDBF(struct MiraMonVectLayerInfo *hMiraMonLayer,
4450
                             struct MiraMonFeature *hMMFeature)
4451
407k
{
4452
407k
    int result;
4453
4454
407k
    if (!hMiraMonLayer)
4455
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
4456
4457
407k
    if (hMiraMonLayer->TopHeader.nElemCount == 0)
4458
92.8k
    {
4459
92.8k
        if (MMCreateMMDB(hMiraMonLayer, nullptr))
4460
91.2k
        {
4461
91.2k
            MMDestroyMMDB(hMiraMonLayer);
4462
91.2k
            return MM_FATAL_ERROR_WRITING_FEATURES;
4463
91.2k
        }
4464
92.8k
    }
4465
4466
316k
    result = MMAddDBFRecordToMMDB(hMiraMonLayer, hMMFeature);
4467
316k
    if (result == MM_FATAL_ERROR_WRITING_FEATURES ||
4468
316k
        result == MM_STOP_WRITING_FEATURES)
4469
0
        return result;
4470
4471
    // Everything OK.
4472
316k
    return MM_CONTINUE_WRITING_FEATURES;
4473
316k
}  // End of de MMCreateRecordDBF()
4474
4475
// Creates a MiraMon point feature.
4476
static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer,
4477
                                struct MiraMonFeature *hMMFeature)
4478
2.91k
{
4479
2.91k
    double *pZ = nullptr;
4480
2.91k
    struct MM_POINT_2D *pCoord;
4481
2.91k
    MM_POLYGON_RINGS_COUNT nIPart;
4482
2.91k
    MM_N_VERTICES_TYPE nIVertice, nCoord;
4483
2.91k
    struct MM_ZD *pZDescription = nullptr;
4484
2.91k
    MM_INTERNAL_FID nElemCount;
4485
2.91k
    int result;
4486
4487
2.91k
    if (!hMiraMonLayer)
4488
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
4489
4490
2.91k
    if (!hMMFeature)
4491
0
        return MM_STOP_WRITING_FEATURES;
4492
4493
2.91k
    if (hMiraMonLayer->TopHeader.bIs3d)
4494
2.91k
        pZ = hMMFeature->pZCoord;
4495
4496
2.91k
    nElemCount = hMiraMonLayer->TopHeader.nElemCount;
4497
4.44k
    for (nIPart = 0, pCoord = hMMFeature->pCoord; nIPart < hMMFeature->nNRings;
4498
2.91k
         nIPart++, nElemCount++)
4499
2.91k
    {
4500
2.91k
        nCoord = hMMFeature->pNCoordRing[nIPart];
4501
4502
        // Checking if its possible continue writing the file due
4503
        // to version limitations.
4504
2.91k
        if (MMCheckVersionForFID(hMiraMonLayer,
4505
2.91k
                                 hMiraMonLayer->TopHeader.nElemCount + nCoord))
4506
0
        {
4507
0
            CPLError(CE_Failure, CPLE_NotSupported,
4508
0
                     "Error in MMCheckVersionForFID() (5)");
4509
0
            return MM_STOP_WRITING_FEATURES;
4510
0
        }
4511
4512
2.91k
        if (hMiraMonLayer->TopHeader.bIs3d)
4513
2.91k
        {
4514
2.91k
            if (nElemCount == 0)
4515
1.59k
            {
4516
1.59k
                if (MMCheckVersionFor3DOffset(hMiraMonLayer, (nElemCount + 1),
4517
1.59k
                                              0, 0))
4518
0
                    return MM_STOP_WRITING_FEATURES;
4519
1.59k
            }
4520
1.32k
            else
4521
1.32k
            {
4522
1.32k
                pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription;
4523
1.32k
                if (!pZDescription)
4524
0
                {
4525
0
                    CPLError(CE_Failure, CPLE_ObjectNull,
4526
0
                             "Error: pZDescription should not be nullptr");
4527
0
                    return MM_STOP_WRITING_FEATURES;
4528
0
                }
4529
4530
1.32k
                if (MMCheckVersionFor3DOffset(
4531
1.32k
                        hMiraMonLayer, nElemCount + 1, 0,
4532
1.32k
                        pZDescription[nElemCount - 1].nOffsetZ + sizeof(*pZ)))
4533
0
                    return MM_STOP_WRITING_FEATURES;
4534
1.32k
            }
4535
2.91k
        }
4536
4537
        // Doing real job
4538
        // Memory issues
4539
2.91k
        if (hMiraMonLayer->TopHeader.bIs3d && pZ)
4540
2.91k
        {
4541
2.91k
            if (MMResizeZSectionDescrPointer(
4542
2.91k
                    &hMiraMonLayer->MMPoint.pZSection.pZDescription,
4543
2.91k
                    &hMiraMonLayer->MMPoint.pZSection.nMaxZDescription,
4544
2.91k
                    nElemCount, MM_INCR_NUMBER_OF_POINTS, 0))
4545
0
            {
4546
0
                CPLError(CE_Failure, CPLE_OutOfMemory,
4547
0
                         "Memory error in MiraMon "
4548
0
                         "driver (MMCreateFeaturePoint())");
4549
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4550
0
            }
4551
4552
2.91k
            pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription;
4553
2.91k
            if (!pZDescription)
4554
0
            {
4555
0
                CPLError(CE_Failure, CPLE_ObjectNull,
4556
0
                         "Error: pZDescription should not be nullptr");
4557
0
                return MM_STOP_WRITING_FEATURES;
4558
0
            }
4559
4560
2.91k
            pZDescription[nElemCount].dfBBminz = *pZ;
4561
2.91k
            pZDescription[nElemCount].dfBBmaxz = *pZ;
4562
4563
2.91k
            if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz > *pZ)
4564
345
                hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz = *pZ;
4565
2.91k
            if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz < *pZ)
4566
359
                hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz = *pZ;
4567
4568
            // Specification ask for a negative number.
4569
2.91k
            pZDescription[nElemCount].nZCount = -1;
4570
2.91k
            if (nElemCount == 0)
4571
1.59k
                pZDescription[nElemCount].nOffsetZ = 0;
4572
1.32k
            else
4573
1.32k
                pZDescription[nElemCount].nOffsetZ =
4574
1.32k
                    pZDescription[nElemCount - 1].nOffsetZ + sizeof(*pZ);
4575
2.91k
        }
4576
4577
        // Flush settings
4578
2.91k
        hMiraMonLayer->MMPoint.FlushTL.pBlockWhereToSaveOrRead =
4579
2.91k
            (void *)hMiraMonLayer->MMPoint.pTL;
4580
2.91k
        if (hMiraMonLayer->TopHeader.bIs3d)
4581
2.91k
            hMiraMonLayer->MMPoint.pZSection.FlushZL.pBlockWhereToSaveOrRead =
4582
2.91k
                (void *)hMiraMonLayer->MMPoint.pZSection.pZL;
4583
4584
        // Dump point or points (MiraMon does not have multiple points)
4585
5.83k
        for (nIVertice = 0; nIVertice < nCoord; nIVertice++, pCoord++)
4586
2.91k
        {
4587
            // Updating the bounding box of the layer
4588
2.91k
            MMUpdateBoundingBoxXY(&hMiraMonLayer->TopHeader.hBB, pCoord);
4589
4590
            // Adding the point at the memory block
4591
2.91k
            hMiraMonLayer->MMPoint.FlushTL.SizeOfBlockToBeSaved =
4592
2.91k
                sizeof(pCoord->dfX);
4593
2.91k
            hMiraMonLayer->MMPoint.FlushTL.pBlockToBeSaved =
4594
2.91k
                (void *)&pCoord->dfX;
4595
2.91k
            if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL))
4596
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4597
2.91k
            hMiraMonLayer->MMPoint.FlushTL.pBlockToBeSaved =
4598
2.91k
                (void *)&pCoord->dfY;
4599
2.91k
            if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL))
4600
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
4601
4602
            // Adding the 3D part, if exists, at the memory block
4603
2.91k
            if (hMiraMonLayer->TopHeader.bIs3d && pZ)
4604
2.91k
            {
4605
2.91k
                hMiraMonLayer->MMPoint.pZSection.FlushZL.SizeOfBlockToBeSaved =
4606
2.91k
                    sizeof(*pZ);
4607
2.91k
                hMiraMonLayer->MMPoint.pZSection.FlushZL.pBlockToBeSaved =
4608
2.91k
                    (void *)pZ;
4609
2.91k
                if (MMAppendBlockToBuffer(
4610
2.91k
                        &hMiraMonLayer->MMPoint.pZSection.FlushZL))
4611
0
                    return MM_FATAL_ERROR_WRITING_FEATURES;
4612
4613
2.91k
                if (!pZDescription)
4614
0
                {
4615
0
                    CPLError(CE_Failure, CPLE_ObjectNull,
4616
0
                             "Error: pZDescription should not be nullptr");
4617
0
                    return MM_STOP_WRITING_FEATURES;
4618
0
                }
4619
4620
2.91k
                if (pZDescription[nElemCount].dfBBminz > *pZ)
4621
0
                    pZDescription[nElemCount].dfBBminz = *pZ;
4622
2.91k
                if (pZDescription[nElemCount].dfBBmaxz < *pZ)
4623
0
                    pZDescription[nElemCount].dfBBmaxz = *pZ;
4624
4625
2.91k
                if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz > *pZ)
4626
0
                    hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz = *pZ;
4627
2.91k
                if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz < *pZ)
4628
0
                    hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz = *pZ;
4629
4630
2.91k
                pZ++;
4631
2.91k
            }
4632
2.91k
        }
4633
4634
2.91k
        if (hMiraMonLayer->TopHeader.nElemCount == 0)
4635
1.59k
        {
4636
1.59k
            if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord))
4637
1.39k
                return MM_FATAL_ERROR_WRITING_FEATURES;
4638
1.59k
        }
4639
4640
1.52k
        result = MMAddPointRecordToMMDB(hMiraMonLayer, hMMFeature, nElemCount);
4641
1.52k
        if (result == MM_FATAL_ERROR_WRITING_FEATURES ||
4642
1.52k
            result == MM_STOP_WRITING_FEATURES)
4643
0
            return result;
4644
1.52k
    }
4645
    // Updating nElemCount at the header of the layer
4646
1.52k
    hMiraMonLayer->TopHeader.nElemCount = nElemCount;
4647
4648
    // Everything OK.
4649
1.52k
    return MM_CONTINUE_WRITING_FEATURES;
4650
2.91k
}  // End of de MMCreateFeaturePoint()
4651
4652
// Checks whether a given Feature ID (FID) exceeds the maximum allowed
4653
// index for 2 GB vectors in a specific MiraMon layer.
4654
int MMCheckVersionForFID(struct MiraMonVectLayerInfo *hMiraMonLayer,
4655
                         MM_INTERNAL_FID FID)
4656
21.8k
{
4657
21.8k
    if (!hMiraMonLayer)
4658
0
        return 1;
4659
4660
21.8k
    if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION)
4661
0
        return 0;
4662
4663
21.8k
    if (FID >= MAXIMUM_OBJECT_INDEX_IN_2GB_VECTORS)
4664
0
        return 1;
4665
21.8k
    return 0;
4666
21.8k
}
4667
4668
// Checks whether a given offset exceeds the maximum allowed
4669
// index for 2 GB vectors in a specific MiraMon layer.
4670
int MMCheckVersionOffset(struct MiraMonVectLayerInfo *hMiraMonLayer,
4671
                         MM_FILE_OFFSET OffsetToCheck)
4672
6.85k
{
4673
6.85k
    if (!hMiraMonLayer)
4674
0
        return 1;
4675
4676
    // Checking if the final version is 1.1 or 2.0
4677
6.85k
    if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION)
4678
0
        return 0;
4679
4680
    // User decided that if necessary, output version can be 2.0
4681
6.85k
    if (OffsetToCheck < MAXIMUM_OFFSET_IN_2GB_VECTORS)
4682
6.85k
        return 0;
4683
4684
0
    return 1;
4685
6.85k
}
4686
4687
// Checks whether a given offset in 3D section exceeds the maximum allowed
4688
// index for 2 GB vectors in a specific MiraMon layer.
4689
int MMCheckVersionFor3DOffset(struct MiraMonVectLayerInfo *hMiraMonLayer,
4690
                              MM_INTERNAL_FID nElemCount,
4691
                              MM_FILE_OFFSET nOffsetAL,
4692
                              MM_FILE_OFFSET nZLOffset)
4693
5.50k
{
4694
5.50k
    MM_FILE_OFFSET LastOffset;
4695
4696
5.50k
    if (!hMiraMonLayer)
4697
0
        return 1;
4698
4699
    // Checking if the final version is 1.1 or 2.0
4700
5.50k
    if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION)
4701
0
        return 0;
4702
4703
    // User decided that if necessary, output version can be 2.0
4704
5.50k
    if (hMiraMonLayer->bIsPoint)
4705
2.91k
        LastOffset = MM_HEADER_SIZE_32_BITS + nElemCount * MM_SIZE_OF_TL;
4706
2.58k
    else  // Arc case
4707
2.58k
    {
4708
2.58k
        LastOffset = MM_HEADER_SIZE_32_BITS +
4709
2.58k
                     nElemCount * MM_SIZE_OF_AH_32BITS + +nOffsetAL;
4710
2.58k
    }
4711
4712
5.50k
    LastOffset += MM_SIZE_OF_ZH;
4713
5.50k
    LastOffset += nElemCount * MM_SIZE_OF_ZD_32_BITS;
4714
5.50k
    LastOffset += nZLOffset;
4715
4716
5.50k
    if (LastOffset < MAXIMUM_OFFSET_IN_2GB_VECTORS)
4717
5.50k
        return 0;
4718
4719
0
    return 1;
4720
5.50k
}
4721
4722
// Adds a feature in a MiraMon layer.
4723
int MMAddFeature(struct MiraMonVectLayerInfo *hMiraMonLayer,
4724
                 struct MiraMonFeature *hMiraMonFeature)
4725
415k
{
4726
415k
    int re;
4727
415k
    MM_INTERNAL_FID previousFID = 0;
4728
4729
415k
    if (!hMiraMonLayer)
4730
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
4731
4732
415k
    if (!hMiraMonLayer->bIsBeenInit)
4733
114
    {
4734
114
        if (MMInitLayerByType(hMiraMonLayer))
4735
0
        {
4736
0
            CPLDebugOnly("MiraMon", "Error in MMInitLayerByType()");
4737
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
4738
0
        }
4739
114
        hMiraMonLayer->bIsBeenInit = 1;
4740
114
    }
4741
4742
415k
    if (hMiraMonFeature)
4743
415k
        previousFID = hMiraMonLayer->TopHeader.nElemCount;
4744
4745
415k
    if (hMiraMonLayer->bIsPoint)
4746
2.91k
    {
4747
2.91k
        re = MMCreateFeaturePoint(hMiraMonLayer, hMiraMonFeature);
4748
2.91k
        if (hMiraMonFeature)
4749
2.91k
        {
4750
2.91k
            hMiraMonFeature->nReadFeatures =
4751
2.91k
                hMiraMonLayer->TopHeader.nElemCount - previousFID;
4752
2.91k
        }
4753
2.91k
        return re;
4754
2.91k
    }
4755
412k
    if (hMiraMonLayer->bIsArc || hMiraMonLayer->bIsPolygon)
4756
4.83k
    {
4757
4.83k
        re = MMCreateFeaturePolOrArc(hMiraMonLayer, hMiraMonFeature);
4758
4.83k
        if (hMiraMonFeature)
4759
4.83k
        {
4760
4.83k
            hMiraMonFeature->nReadFeatures =
4761
4.83k
                hMiraMonLayer->TopHeader.nElemCount - previousFID;
4762
4.83k
        }
4763
4.83k
        return re;
4764
4.83k
    }
4765
407k
    if (hMiraMonLayer->bIsDBF)
4766
407k
    {
4767
        // Adding a record to DBF file
4768
407k
        re = MMCreateRecordDBF(hMiraMonLayer, hMiraMonFeature);
4769
407k
        if (hMiraMonFeature)
4770
407k
        {
4771
407k
            hMiraMonFeature->nReadFeatures =
4772
407k
                hMiraMonLayer->TopHeader.nElemCount - previousFID;
4773
407k
        }
4774
407k
        return re;
4775
407k
    }
4776
4777
0
    return MM_CONTINUE_WRITING_FEATURES;
4778
407k
}
4779
4780
/* -------------------------------------------------------------------- */
4781
/*      Tools used by MiraMon.                                          */
4782
/* -------------------------------------------------------------------- */
4783
4784
void MMInitBoundingBox(struct MMBoundingBox *dfBB)
4785
5.46k
{
4786
5.46k
    if (!dfBB)
4787
0
        return;
4788
5.46k
    dfBB->dfMinX = STATISTICAL_UNDEF_VALUE;
4789
5.46k
    dfBB->dfMaxX = -STATISTICAL_UNDEF_VALUE;
4790
5.46k
    dfBB->dfMinY = STATISTICAL_UNDEF_VALUE;
4791
5.46k
    dfBB->dfMaxY = -STATISTICAL_UNDEF_VALUE;
4792
5.46k
}
4793
4794
void MMUpdateBoundingBox(struct MMBoundingBox *dfBBToBeAct,
4795
                         struct MMBoundingBox *dfBBWithData)
4796
4.40k
{
4797
4.40k
    if (!dfBBToBeAct)
4798
0
        return;
4799
4800
4.40k
    if (dfBBToBeAct->dfMinX > dfBBWithData->dfMinX)
4801
608
        dfBBToBeAct->dfMinX = dfBBWithData->dfMinX;
4802
4803
4.40k
    if (dfBBToBeAct->dfMinY > dfBBWithData->dfMinY)
4804
605
        dfBBToBeAct->dfMinY = dfBBWithData->dfMinY;
4805
4806
4.40k
    if (dfBBToBeAct->dfMaxX < dfBBWithData->dfMaxX)
4807
529
        dfBBToBeAct->dfMaxX = dfBBWithData->dfMaxX;
4808
4809
4.40k
    if (dfBBToBeAct->dfMaxY < dfBBWithData->dfMaxY)
4810
583
        dfBBToBeAct->dfMaxY = dfBBWithData->dfMaxY;
4811
4.40k
}
4812
4813
void MMUpdateBoundingBoxXY(struct MMBoundingBox *dfBB,
4814
                           struct MM_POINT_2D *pCoord)
4815
11.7k
{
4816
11.7k
    if (!pCoord)
4817
0
        return;
4818
4819
11.7k
    if (pCoord->dfX < dfBB->dfMinX)
4820
2.55k
        dfBB->dfMinX = pCoord->dfX;
4821
4822
11.7k
    if (pCoord->dfY < dfBB->dfMinY)
4823
2.93k
        dfBB->dfMinY = pCoord->dfY;
4824
4825
11.7k
    if (pCoord->dfX > dfBB->dfMaxX)
4826
2.46k
        dfBB->dfMaxX = pCoord->dfX;
4827
4828
11.7k
    if (pCoord->dfY > dfBB->dfMaxY)
4829
2.48k
        dfBB->dfMaxY = pCoord->dfY;
4830
11.7k
}
4831
4832
/* -------------------------------------------------------------------- */
4833
/*      Resize structures for reuse                                     */
4834
/* -------------------------------------------------------------------- */
4835
int MMResizeMiraMonFieldValue(struct MiraMonFieldValue **pFieldValue,
4836
                              MM_EXT_DBF_N_MULTIPLE_RECORDS *nMax,
4837
                              MM_EXT_DBF_N_MULTIPLE_RECORDS nNum,
4838
                              MM_EXT_DBF_N_MULTIPLE_RECORDS nIncr,
4839
                              MM_EXT_DBF_N_MULTIPLE_RECORDS nProposedMax)
4840
1.32M
{
4841
1.32M
    MM_EXT_DBF_N_MULTIPLE_RECORDS nPrevMax;
4842
1.32M
    MM_EXT_DBF_N_MULTIPLE_RECORDS nNewMax;
4843
1.32M
    void *pTmp;
4844
4845
1.32M
    if (nNum < *nMax)
4846
1.32M
        return 0;
4847
4848
340
    nPrevMax = *nMax;
4849
340
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
4850
340
    if (MMCheckSize_t(nNewMax, sizeof(**pFieldValue)))
4851
0
    {
4852
0
        return 1;
4853
0
    }
4854
340
    if ((pTmp = VSIRealloc(*pFieldValue,
4855
340
                           (size_t)nNewMax * sizeof(**pFieldValue))) == nullptr)
4856
0
    {
4857
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
4858
0
                 "Memory error in MiraMon "
4859
0
                 "driver (MMResizeMiraMonFieldValue())");
4860
0
        return 1;
4861
0
    }
4862
340
    *nMax = nNewMax;
4863
340
    *pFieldValue = pTmp;
4864
4865
340
    memset((*pFieldValue) + nPrevMax, 0,
4866
340
           (size_t)(*nMax - nPrevMax) * sizeof(**pFieldValue));
4867
340
    return 0;
4868
340
}
4869
4870
int MMResizeMiraMonPolygonArcs(struct MM_PAL_MEM **pFID,
4871
                               MM_POLYGON_ARCS_COUNT *nMax,
4872
                               MM_POLYGON_ARCS_COUNT nNum,
4873
                               MM_POLYGON_ARCS_COUNT nIncr,
4874
                               MM_POLYGON_ARCS_COUNT nProposedMax)
4875
453
{
4876
453
    MM_POLYGON_ARCS_COUNT nPrevMax;
4877
453
    MM_POLYGON_ARCS_COUNT nNewMax;
4878
453
    void *pTmp;
4879
4880
453
    if (nNum < *nMax)
4881
35
        return 0;
4882
4883
418
    nPrevMax = *nMax;
4884
418
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
4885
418
    if (MMCheckSize_t(nNewMax, sizeof(**pFID)))
4886
90
    {
4887
90
        return 1;
4888
90
    }
4889
328
    if (nNewMax == 0 && *pFID)
4890
0
        return 0;
4891
328
    if ((pTmp = VSIRealloc(*pFID, (size_t)nNewMax * sizeof(**pFID))) == nullptr)
4892
0
    {
4893
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
4894
0
                 "Memory error in MiraMon "
4895
0
                 "driver (MMResizeMiraMonPolygonArcs())");
4896
0
        return 1;
4897
0
    }
4898
328
    *nMax = nNewMax;
4899
328
    *pFID = pTmp;
4900
4901
328
    memset((*pFID) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pFID));
4902
328
    return 0;
4903
328
}
4904
4905
int MMResizeMiraMonRecord(struct MiraMonRecord **pMiraMonRecord,
4906
                          MM_EXT_DBF_N_MULTIPLE_RECORDS *nMax,
4907
                          MM_EXT_DBF_N_MULTIPLE_RECORDS nNum,
4908
                          MM_EXT_DBF_N_MULTIPLE_RECORDS nIncr,
4909
                          MM_EXT_DBF_N_MULTIPLE_RECORDS nProposedMax)
4910
0
{
4911
0
    MM_EXT_DBF_N_MULTIPLE_RECORDS nPrevMax;
4912
0
    MM_EXT_DBF_N_MULTIPLE_RECORDS nNewMax;
4913
0
    void *pTmp;
4914
4915
0
    if (nNum < *nMax)
4916
0
        return 0;
4917
4918
0
    nPrevMax = *nMax;
4919
0
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
4920
0
    if (MMCheckSize_t(nNewMax, sizeof(**pMiraMonRecord)))
4921
0
    {
4922
0
        return 1;
4923
0
    }
4924
0
    if (nNewMax == 0 && *pMiraMonRecord)
4925
0
        return 0;
4926
0
    if ((pTmp = VSIRealloc(*pMiraMonRecord,
4927
0
                           (size_t)nNewMax * sizeof(**pMiraMonRecord))) ==
4928
0
        nullptr)
4929
0
    {
4930
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
4931
0
                 "Memory error in MiraMon "
4932
0
                 "driver (MMResizeMiraMonRecord())");
4933
0
        return 1;
4934
0
    }
4935
0
    *nMax = nNewMax;
4936
0
    *pMiraMonRecord = pTmp;
4937
4938
0
    memset((*pMiraMonRecord) + nPrevMax, 0,
4939
0
           (size_t)(*nMax - nPrevMax) * sizeof(**pMiraMonRecord));
4940
0
    return 0;
4941
0
}
4942
4943
int MMResizeZSectionDescrPointer(struct MM_ZD **pZDescription, GUInt64 *nMax,
4944
                                 GUInt64 nNum, GUInt64 nIncr,
4945
                                 GUInt64 nProposedMax)
4946
5.50k
{
4947
5.50k
    GUInt64 nNewMax, nPrevMax;
4948
5.50k
    void *pTmp;
4949
4950
5.50k
    if (nNum < *nMax)
4951
5.26k
        return 0;
4952
4953
238
    nPrevMax = *nMax;
4954
238
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
4955
238
    if (MMCheckSize_t(nNewMax, sizeof(**pZDescription)))
4956
0
    {
4957
0
        return 1;
4958
0
    }
4959
238
    if (nNewMax == 0 && *pZDescription)
4960
0
        return 0;
4961
238
    if ((pTmp = VSIRealloc(*pZDescription,
4962
238
                           (size_t)nNewMax * sizeof(**pZDescription))) ==
4963
238
        nullptr)
4964
0
    {
4965
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
4966
0
                 "Memory error in MiraMon "
4967
0
                 "driver (MMResizeZSectionDescrPointer())");
4968
0
        return 1;
4969
0
    }
4970
238
    *nMax = nNewMax;
4971
238
    *pZDescription = pTmp;
4972
4973
238
    memset((*pZDescription) + nPrevMax, 0,
4974
238
           (size_t)(*nMax - nPrevMax) * sizeof(**pZDescription));
4975
238
    return 0;
4976
238
}
4977
4978
int MMResizeNodeHeaderPointer(struct MM_NH **pNodeHeader, GUInt64 *nMax,
4979
                              GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax)
4980
2.58k
{
4981
2.58k
    GUInt64 nNewMax, nPrevMax;
4982
2.58k
    void *pTmp;
4983
4984
2.58k
    if (nNum < *nMax)
4985
2.58k
        return 0;
4986
4987
0
    nPrevMax = *nMax;
4988
0
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
4989
0
    if (MMCheckSize_t(nNewMax, sizeof(**pNodeHeader)))
4990
0
    {
4991
0
        return 1;
4992
0
    }
4993
0
    if (nNewMax == 0 && *pNodeHeader)
4994
0
        return 0;
4995
0
    if ((pTmp = VSIRealloc(*pNodeHeader,
4996
0
                           (size_t)nNewMax * sizeof(**pNodeHeader))) == nullptr)
4997
0
    {
4998
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
4999
0
                 "Memory error in MiraMon "
5000
0
                 "driver (MMResizeNodeHeaderPointer())");
5001
0
        return 1;
5002
0
    }
5003
0
    *nMax = nNewMax;
5004
0
    *pNodeHeader = pTmp;
5005
5006
0
    memset((*pNodeHeader) + nPrevMax, 0,
5007
0
           (size_t)(*nMax - nPrevMax) * sizeof(**pNodeHeader));
5008
0
    return 0;
5009
0
}
5010
5011
int MMResizeArcHeaderPointer(struct MM_AH **pArcHeader, GUInt64 *nMax,
5012
                             GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax)
5013
2.58k
{
5014
2.58k
    GUInt64 nNewMax, nPrevMax;
5015
2.58k
    void *pTmp;
5016
5017
2.58k
    if (nNum < *nMax)
5018
2.58k
        return 0;
5019
5020
0
    nPrevMax = *nMax;
5021
0
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
5022
0
    if (MMCheckSize_t(nNewMax, sizeof(**pArcHeader)))
5023
0
    {
5024
0
        return 1;
5025
0
    }
5026
0
    if (nNewMax == 0 && *pArcHeader)
5027
0
        return 0;
5028
0
    if ((pTmp = VSIRealloc(*pArcHeader,
5029
0
                           (size_t)nNewMax * sizeof(**pArcHeader))) == nullptr)
5030
0
    {
5031
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
5032
0
                 "Memory error in MiraMon "
5033
0
                 "driver (MMResizeArcHeaderPointer())");
5034
0
        return 1;
5035
0
    }
5036
0
    *nMax = nNewMax;
5037
0
    *pArcHeader = pTmp;
5038
5039
0
    memset((*pArcHeader) + nPrevMax, 0,
5040
0
           (size_t)(*nMax - nPrevMax) * sizeof(**pArcHeader));
5041
0
    return 0;
5042
0
}
5043
5044
int MMResizePolHeaderPointer(struct MM_PH **pPolHeader, GUInt64 *nMax,
5045
                             GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax)
5046
1.70k
{
5047
1.70k
    GUInt64 nNewMax, nPrevMax;
5048
1.70k
    void *pTmp;
5049
5050
1.70k
    if (nNum < *nMax)
5051
1.70k
        return 0;
5052
5053
0
    nPrevMax = *nMax;
5054
0
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
5055
0
    if (MMCheckSize_t(nNewMax, sizeof(**pPolHeader)))
5056
0
    {
5057
0
        return 1;
5058
0
    }
5059
0
    if (nNewMax == 0 && *pPolHeader)
5060
0
        return 0;
5061
0
    if ((pTmp = VSIRealloc(*pPolHeader,
5062
0
                           (size_t)nNewMax * sizeof(**pPolHeader))) == nullptr)
5063
0
    {
5064
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
5065
0
                 "Memory error in MiraMon "
5066
0
                 "driver (MMResizePolHeaderPointer())");
5067
0
        return 1;
5068
0
    }
5069
0
    *nMax = nNewMax;
5070
0
    *pPolHeader = pTmp;
5071
5072
0
    memset((*pPolHeader) + nPrevMax, 0,
5073
0
           (size_t)(*nMax - nPrevMax) * sizeof(**pPolHeader));
5074
0
    return 0;
5075
0
}
5076
5077
int MMResize_MM_N_VERTICES_TYPE_Pointer(MM_N_VERTICES_TYPE **pVrt,
5078
                                        MM_N_VERTICES_TYPE *nMax,
5079
                                        MM_N_VERTICES_TYPE nNum,
5080
                                        MM_N_VERTICES_TYPE nIncr,
5081
                                        MM_N_VERTICES_TYPE nProposedMax)
5082
127k
{
5083
127k
    MM_N_VERTICES_TYPE nNewMax, nPrevMax;
5084
127k
    void *pTmp;
5085
5086
127k
    if (nNum < *nMax)
5087
112k
        return 0;
5088
5089
15.4k
    nPrevMax = *nMax;
5090
15.4k
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
5091
15.4k
    if (MMCheckSize_t(nNewMax, sizeof(**pVrt)))
5092
0
    {
5093
0
        return 1;
5094
0
    }
5095
15.4k
    if (nNewMax == 0 && *pVrt)
5096
0
        return 0;
5097
15.4k
    if ((pTmp = VSIRealloc(*pVrt, (size_t)nNewMax * sizeof(**pVrt))) == nullptr)
5098
0
    {
5099
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
5100
0
                 "Memory error in MiraMon "
5101
0
                 "driver (MMResize_MM_N_VERTICES_TYPE_Pointer())");
5102
0
        return 1;
5103
0
    }
5104
15.4k
    *nMax = nNewMax;
5105
15.4k
    *pVrt = pTmp;
5106
5107
15.4k
    memset((*pVrt) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pVrt));
5108
15.4k
    return 0;
5109
15.4k
}
5110
5111
int MMResizeVFGPointer(char **pInt, MM_INTERNAL_FID *nMax, MM_INTERNAL_FID nNum,
5112
                       MM_INTERNAL_FID nIncr, MM_INTERNAL_FID nProposedMax)
5113
1.75k
{
5114
1.75k
    MM_N_VERTICES_TYPE nNewMax, nPrevMax;
5115
1.75k
    void *pTmp;
5116
5117
1.75k
    if (nNum < *nMax)
5118
1.38k
        return 0;
5119
5120
371
    nPrevMax = *nMax;
5121
371
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
5122
371
    if (MMCheckSize_t(nNewMax, sizeof(**pInt)))
5123
0
    {
5124
0
        return 1;
5125
0
    }
5126
371
    if (nNewMax == 0 && *pInt)
5127
0
        return 0;
5128
371
    if ((pTmp = VSIRealloc(*pInt, (size_t)nNewMax * sizeof(**pInt))) == nullptr)
5129
0
    {
5130
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
5131
0
                 "Memory error in MiraMon "
5132
0
                 "driver (MMResizeVFGPointer())");
5133
0
        return 1;
5134
0
    }
5135
371
    *nMax = nNewMax;
5136
371
    *pInt = pTmp;
5137
5138
371
    memset((*pInt) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pInt));
5139
371
    return 0;
5140
371
}
5141
5142
int MMResizeMM_POINT2DPointer(struct MM_POINT_2D **pPoint2D,
5143
                              MM_N_VERTICES_TYPE *nMax, MM_N_VERTICES_TYPE nNum,
5144
                              MM_N_VERTICES_TYPE nIncr,
5145
                              MM_N_VERTICES_TYPE nProposedMax)
5146
127k
{
5147
127k
    MM_N_VERTICES_TYPE nNewMax, nPrevMax;
5148
127k
    void *pTmp;
5149
5150
127k
    if (nNum < *nMax)
5151
113k
        return 0;
5152
5153
14.6k
    nPrevMax = *nMax;
5154
14.6k
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
5155
14.6k
    if (MMCheckSize_t(nNewMax, sizeof(**pPoint2D)))
5156
134
    {
5157
134
        return 1;
5158
134
    }
5159
14.5k
    if (nNewMax == 0 && *pPoint2D)
5160
2.31k
        return 0;
5161
12.2k
    if ((pTmp = VSIRealloc(*pPoint2D, (size_t)nNewMax * sizeof(**pPoint2D))) ==
5162
12.2k
        nullptr)
5163
0
    {
5164
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
5165
0
                 "Memory error in MiraMon "
5166
0
                 "driver (MMResizeMM_POINT2DPointer())");
5167
0
        return 1;
5168
0
    }
5169
12.2k
    *nMax = nNewMax;
5170
12.2k
    *pPoint2D = pTmp;
5171
5172
12.2k
    memset((*pPoint2D) + nPrevMax, 0,
5173
12.2k
           (size_t)(*nMax - nPrevMax) * sizeof(**pPoint2D));
5174
12.2k
    return 0;
5175
12.2k
}
5176
5177
int MMResizeDoublePointer(MM_COORD_TYPE **pDouble, MM_N_VERTICES_TYPE *nMax,
5178
                          MM_N_VERTICES_TYPE nNum, MM_N_VERTICES_TYPE nIncr,
5179
                          MM_N_VERTICES_TYPE nProposedMax)
5180
49.7k
{
5181
49.7k
    MM_N_VERTICES_TYPE nNewMax, nPrevMax;
5182
49.7k
    void *pTmp;
5183
5184
49.7k
    if (nNum < *nMax)
5185
13.5k
        return 0;
5186
5187
36.1k
    nPrevMax = *nMax;
5188
36.1k
    nNewMax = CPL_MAX(nNum + nIncr, nProposedMax);
5189
36.1k
    if (MMCheckSize_t(nNewMax, sizeof(**pDouble)))
5190
0
    {
5191
0
        return 1;
5192
0
    }
5193
36.1k
    if (nNewMax == 0 && *pDouble)
5194
16.5k
        return 0;
5195
19.5k
    if ((pTmp = VSIRealloc(*pDouble, (size_t)nNewMax * sizeof(**pDouble))) ==
5196
19.5k
        nullptr)
5197
0
    {
5198
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
5199
0
                 "Memory error in MiraMon "
5200
0
                 "driver (MMResizeDoublePointer())");
5201
0
        return 1;
5202
0
    }
5203
19.5k
    *nMax = nNewMax;
5204
19.5k
    *pDouble = pTmp;
5205
5206
19.5k
    memset((*pDouble) + nPrevMax, 0,
5207
19.5k
           (size_t)(*nMax - nPrevMax) * sizeof(**pDouble));
5208
19.5k
    return 0;
5209
19.5k
}
5210
5211
int MMResizeStringToOperateIfNeeded(struct MiraMonVectLayerInfo *hMiraMonLayer,
5212
                                    MM_EXT_DBF_N_FIELDS nNewSize)
5213
2.02M
{
5214
2.02M
    if (!hMiraMonLayer)
5215
0
        return 1;
5216
5217
2.02M
    if (nNewSize >= hMiraMonLayer->nNumStringToOperate)
5218
158k
    {
5219
158k
        char *p;
5220
158k
        if (MMCheckSize_t(nNewSize, 1))
5221
0
            return 1;
5222
158k
        p = (char *)VSICalloc(1, (size_t)nNewSize);
5223
158k
        if (!p)
5224
0
        {
5225
0
            CPLError(CE_Failure, CPLE_OutOfMemory,
5226
0
                     "Memory error in MiraMon "
5227
0
                     "driver (MMResizeStringToOperateIfNeeded())");
5228
0
            return 1;
5229
0
        }
5230
158k
        VSIFree(hMiraMonLayer->szStringToOperate);
5231
158k
        hMiraMonLayer->szStringToOperate = p;
5232
158k
        hMiraMonLayer->nNumStringToOperate = nNewSize;
5233
158k
    }
5234
2.02M
    return 0;
5235
2.02M
}
5236
5237
/* -------------------------------------------------------------------- */
5238
/*      Metadata Functions                                              */
5239
/* -------------------------------------------------------------------- */
5240
5241
65.1k
#define LineReturn "\r\n"
5242
5243
// Converts a string from UTF-8 to ANSI to be written in a REL 4 file
5244
static void MMWrite_ANSI_MetadataKeyDescriptor(
5245
    struct MiraMonVectorMetaData *hMMMD, VSILFILE *pF, const char *pszEng,
5246
    const char *pszCat, const char *pszEsp, const char *pszCurrentEncoding)
5247
4.17k
{
5248
4.17k
    if (!EQUAL(pszCurrentEncoding, CPL_ENC_ISO8859_1))
5249
0
    {
5250
0
        char *pszString = nullptr;
5251
5252
0
        switch (hMMMD->nMMLanguage)
5253
0
        {
5254
0
            case MM_CAT_LANGUAGE:
5255
0
                pszString =
5256
0
                    CPLRecode(pszCat, pszCurrentEncoding, CPL_ENC_ISO8859_1);
5257
0
                break;
5258
0
            case MM_SPA_LANGUAGE:
5259
0
                pszString =
5260
0
                    CPLRecode(pszEsp, pszCurrentEncoding, CPL_ENC_ISO8859_1);
5261
0
                break;
5262
0
            default:
5263
0
            case MM_ENG_LANGUAGE:
5264
0
                pszString =
5265
0
                    CPLRecode(pszEng, pszCurrentEncoding, CPL_ENC_ISO8859_1);
5266
0
                break;
5267
0
        }
5268
0
        if (pszString)
5269
0
        {
5270
0
            VSIFPrintfL(pF, "%s", KEY_descriptor);
5271
0
            VSIFPrintfL(pF, "=");
5272
0
            VSIFPrintfL(pF, "%s", pszString);
5273
0
            VSIFPrintfL(pF, "%s", LineReturn);
5274
0
            CPLFree(pszString);
5275
0
        }
5276
0
    }
5277
4.17k
    else
5278
4.17k
    {
5279
4.17k
        const char *pszString;
5280
4.17k
        switch (hMMMD->nMMLanguage)
5281
4.17k
        {
5282
0
            case MM_CAT_LANGUAGE:
5283
0
                pszString = pszCat;
5284
0
                break;
5285
0
            case MM_SPA_LANGUAGE:
5286
0
                pszString = pszEsp;
5287
0
                break;
5288
4.17k
            default:
5289
4.17k
            case MM_ENG_LANGUAGE:
5290
4.17k
                pszString = pszEng;
5291
4.17k
                break;
5292
4.17k
        }
5293
4.17k
        if (pszString)
5294
4.17k
        {
5295
4.17k
            VSIFPrintfL(pF, "%s", KEY_descriptor);
5296
4.17k
            VSIFPrintfL(pF, "=");
5297
4.17k
            VSIFPrintfL(pF, "%s", pszString);
5298
4.17k
            VSIFPrintfL(pF, "%s", LineReturn);
5299
4.17k
        }
5300
4.17k
    }
5301
4.17k
}
5302
5303
/*
5304
    Writes a MiraMon REL 4 metadata file. Next sections are included:
5305
    VERSION, METADADES, IDENTIFICATION, EXTENT, OVERVIEW,
5306
    TAULA_PRINCIPAL and GEOMETRIA_I_TOPOLOGIA
5307
5308
    Please, consult the meaning of all them at:
5309
    https://www.miramon.cat/help/eng/GeMPlus/ClausREL.htm
5310
5311
    This file must be written in ANSI encoding; therefore, some
5312
    conversions are performed for strings that may originally
5313
    be in UTF-8.
5314
*/
5315
static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD)
5316
1.18k
{
5317
1.18k
    char aMessage[MM_MESSAGE_LENGTH],
5318
1.18k
        aFileIdentifier[MM_MAX_LEN_LAYER_IDENTIFIER], aMMIDSRS[MM_MAX_ID_SNY];
5319
1.18k
    char *pszChaiCP1252;
5320
1.18k
    MM_EXT_DBF_N_FIELDS nIField;
5321
1.18k
    VSILFILE *pF;
5322
1.18k
    time_t currentTime;
5323
1.18k
    char aTimeString[200];
5324
5325
1.18k
    if (!hMMMD->aLayerName)
5326
0
        return 0;
5327
5328
1.18k
    if (nullptr == (pF = VSIFOpenL(hMMMD->aLayerName, "wb")))
5329
0
    {
5330
0
        CPLError(CE_Failure, CPLE_OpenFailed, "The file %s must exist.",
5331
0
                 hMMMD->aLayerName);
5332
0
        return 1;
5333
0
    }
5334
5335
    // Writing MiraMon version section
5336
1.18k
    VSIFPrintfL(pF, "[%s]" LineReturn, SECTION_VERSIO);
5337
5338
1.18k
    VSIFPrintfL(pF, "%s=%u" LineReturn, KEY_Vers, (unsigned)MM_VERS);
5339
1.18k
    VSIFPrintfL(pF, "%s=%u" LineReturn, KEY_SubVers, (unsigned)MM_SUBVERS);
5340
5341
1.18k
    VSIFPrintfL(pF, "%s=%u" LineReturn, KEY_VersMetaDades,
5342
1.18k
                (unsigned)MM_VERS_METADADES);
5343
1.18k
    VSIFPrintfL(pF, "%s=%u" LineReturn, KEY_SubVersMetaDades,
5344
1.18k
                (unsigned)MM_SUBVERS_METADADES);
5345
5346
    // Writing METADADES section
5347
1.18k
    VSIFPrintfL(pF, "\r\n[%s]" LineReturn, SECTION_METADADES);
5348
1.18k
    CPLStrlcpy(aMessage, hMMMD->aLayerName, sizeof(aMessage));
5349
1.18k
    MMGenerateFileIdentifierFromMetadataFileName(aMessage, aFileIdentifier);
5350
5351
1.18k
    pszChaiCP1252 = CPLRecode(aFileIdentifier, CPL_ENC_UTF8, "CP1252");
5352
1.18k
    VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_FileIdentifier,
5353
1.18k
                pszChaiCP1252 ? pszChaiCP1252 : aFileIdentifier);
5354
1.18k
    VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_language, KEY_Value_eng);
5355
1.18k
    VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_MDIdiom, KEY_Value_eng);
5356
1.18k
    VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_characterSet,
5357
1.18k
                KEY_Value_characterSet);
5358
5359
    // Writing IDENTIFICATION section
5360
1.18k
    VSIFPrintfL(pF, LineReturn "[%s]" LineReturn, SECTION_IDENTIFICATION);
5361
1.18k
    VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_code,
5362
1.18k
                pszChaiCP1252 ? pszChaiCP1252 : aFileIdentifier);
5363
1.18k
    VSIFPrintfL(pF, "%s=" LineReturn, KEY_codeSpace);
5364
1.18k
    CPLFree(pszChaiCP1252);  // Not needed
5365
1.18k
    if (hMMMD->szLayerTitle && !MMIsEmptyString(hMMMD->szLayerTitle))
5366
83
    {
5367
83
        pszChaiCP1252 = CPLRecode(hMMMD->szLayerTitle, CPL_ENC_UTF8, "CP1252");
5368
83
        if (hMMMD->ePlainLT == MM_LayerType_Point)
5369
29
            VSIFPrintfL(pF, "%s=%s (pnt)" LineReturn, KEY_DatasetTitle,
5370
29
                        pszChaiCP1252 ? pszChaiCP1252 : hMMMD->szLayerTitle);
5371
83
        if (hMMMD->ePlainLT == MM_LayerType_Arc)
5372
23
            VSIFPrintfL(pF, "%s=%s (arc)" LineReturn, KEY_DatasetTitle,
5373
23
                        pszChaiCP1252 ? pszChaiCP1252 : hMMMD->szLayerTitle);
5374
83
        if (hMMMD->ePlainLT == MM_LayerType_Pol)
5375
8
            VSIFPrintfL(pF, "%s=%s (pol)" LineReturn, KEY_DatasetTitle,
5376
8
                        pszChaiCP1252 ? pszChaiCP1252 : hMMMD->szLayerTitle);
5377
83
        CPLFree(pszChaiCP1252);
5378
83
    }
5379
1.18k
    VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_language, KEY_Value_eng);
5380
5381
1.18k
    if (hMMMD->ePlainLT != MM_LayerType_Node &&
5382
811
        hMMMD->ePlainLT != MM_LayerType_Pol)
5383
654
    {
5384
        // SPATIAL_REFERENCE_SYSTEM:HORIZONTAL
5385
654
        VSIFPrintfL(pF, LineReturn "[%s:%s]" LineReturn,
5386
654
                    SECTION_SPATIAL_REFERENCE_SYSTEM, SECTION_HORIZONTAL);
5387
654
        if (!ReturnMMIDSRSFromEPSGCodeSRS(hMMMD->pSRS, aMMIDSRS) &&
5388
0
            !MMIsEmptyString(aMMIDSRS))
5389
0
            VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_HorizontalSystemIdentifier,
5390
0
                        aMMIDSRS);
5391
654
        else
5392
654
        {
5393
654
            CPLError(CE_Warning, CPLE_NotSupported,
5394
654
                     "The MiraMon driver cannot assign any HRS.");
5395
            // Horizontal Reference System
5396
654
            VSIFPrintfL(pF, "%s=plane" LineReturn,
5397
654
                        KEY_HorizontalSystemIdentifier);
5398
654
            VSIFPrintfL(pF, "%s=local" LineReturn,
5399
654
                        KEY_HorizontalSystemDefinition);
5400
654
            if (hMMMD->pXUnit)
5401
0
                VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_unitats, hMMMD->pXUnit);
5402
654
            if (hMMMD->pYUnit)
5403
0
            {
5404
0
                if (!hMMMD->pXUnit || strcasecmp(hMMMD->pXUnit, hMMMD->pYUnit))
5405
0
                    VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_unitatsY,
5406
0
                                hMMMD->pYUnit);
5407
0
            }
5408
654
        }
5409
5410
        // SPATIAL_REFERENCE_SYSTEM:VERTICAL
5411
        // Llegim les unitats del Sist. ref. vertical
5412
654
        if (hMMMD->pZUnit)
5413
3
        {
5414
3
            VSIFPrintfL(pF, LineReturn "[%s:%s]" LineReturn,
5415
3
                        SECTION_SPATIAL_REFERENCE_SYSTEM, SECTION_VERTICAL);
5416
3
            VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_unitats, hMMMD->pZUnit);
5417
3
        }
5418
654
    }
5419
5420
1.18k
    if (hMMMD->ePlainLT == MM_LayerType_Pol && hMMMD->aArcFile)
5421
157
    {
5422
        // Writing OVERVIEW:ASPECTES_TECNICS in polygon metadata file.
5423
        // ArcSource=fitx_pol.arc
5424
157
        pszChaiCP1252 = CPLRecode(hMMMD->aArcFile, CPL_ENC_UTF8, "CP1252");
5425
157
        VSIFPrintfL(pF, LineReturn "[%s]" LineReturn,
5426
157
                    SECTION_OVVW_ASPECTES_TECNICS);
5427
157
        VSIFPrintfL(pF, "%s=\"%s\"" LineReturn, KEY_ArcSource, pszChaiCP1252);
5428
157
        CPLFree(pszChaiCP1252);
5429
157
    }
5430
1.02k
    else if (hMMMD->ePlainLT == MM_LayerType_Arc && hMMMD->aArcFile)
5431
157
    {
5432
157
        pszChaiCP1252 = CPLRecode(hMMMD->aArcFile, CPL_ENC_UTF8, "CP1252");
5433
        // Writing OVERVIEW:ASPECTES_TECNICS in arc metadata file.
5434
        // Ciclat1=fitx_arc.pol
5435
157
        VSIFPrintfL(pF, LineReturn "[%s]" LineReturn,
5436
157
                    SECTION_OVVW_ASPECTES_TECNICS);
5437
157
        VSIFPrintfL(pF, "Ciclat1=\"%s\"" LineReturn, pszChaiCP1252);
5438
157
        CPLFree(pszChaiCP1252);
5439
157
    }
5440
5441
    // Writing EXTENT section
5442
1.18k
    VSIFPrintfL(pF, LineReturn "[%s]" LineReturn, SECTION_EXTENT);
5443
1.18k
    VSIFPrintfL(pF, "%s=0" LineReturn, KEY_toler_env);
5444
5445
1.18k
    if (hMMMD->hBB.dfMinX != MM_UNDEFINED_STATISTICAL_VALUE &&
5446
666
        hMMMD->hBB.dfMaxX != -MM_UNDEFINED_STATISTICAL_VALUE &&
5447
666
        hMMMD->hBB.dfMinY != MM_UNDEFINED_STATISTICAL_VALUE &&
5448
663
        hMMMD->hBB.dfMaxY != -MM_UNDEFINED_STATISTICAL_VALUE)
5449
663
    {
5450
663
        VSIFPrintfL(pF, "%s=%lf" LineReturn, KEY_MinX, hMMMD->hBB.dfMinX);
5451
663
        VSIFPrintfL(pF, "%s=%lf" LineReturn, KEY_MaxX, hMMMD->hBB.dfMaxX);
5452
663
        VSIFPrintfL(pF, "%s=%lf" LineReturn, KEY_MinY, hMMMD->hBB.dfMinY);
5453
663
        VSIFPrintfL(pF, "%s=%lf" LineReturn, KEY_MaxY, hMMMD->hBB.dfMaxY);
5454
663
    }
5455
5456
    // Writing OVERVIEW section
5457
1.18k
    VSIFPrintfL(pF, LineReturn "[%s]" LineReturn, SECTION_OVERVIEW);
5458
5459
1.18k
    currentTime = time(nullptr);
5460
5461
1.18k
    struct tm ltime;
5462
1.18k
    VSILocalTime(&currentTime, &ltime);
5463
1.18k
    snprintf(aTimeString, sizeof(aTimeString), "%04d%02d%02d %02d%02d%02d%02d",
5464
1.18k
             ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
5465
1.18k
             ltime.tm_hour, ltime.tm_min, ltime.tm_sec, 0);
5466
1.18k
    VSIFPrintfL(pF, "%s=%s" LineReturn, KEY_CreationDate, aTimeString);
5467
1.18k
    VSIFPrintfL(pF, LineReturn);
5468
5469
    // Writing TAULA_PRINCIPAL section
5470
1.18k
    VSIFPrintfL(pF, "[%s]" LineReturn, SECTION_TAULA_PRINCIPAL);
5471
1.18k
    VSIFPrintfL(pF, "IdGrafic=%s" LineReturn, szMMNomCampIdGraficDefecte);
5472
1.18k
    VSIFPrintfL(pF, "TipusRelacio=RELACIO_1_1_DICC" LineReturn);
5473
5474
1.18k
    VSIFPrintfL(pF, LineReturn);
5475
1.18k
    VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5476
1.18k
                szMMNomCampIdGraficDefecte);
5477
1.18k
    VSIFPrintfL(pF, "visible=0" LineReturn);
5478
1.18k
    VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5479
5480
1.18k
    MMWrite_ANSI_MetadataKeyDescriptor(
5481
1.18k
        hMMMD, pF, szInternalGraphicIdentifierEng,
5482
1.18k
        szInternalGraphicIdentifierCat, szInternalGraphicIdentifierSpa,
5483
1.18k
        CPL_ENC_ISO8859_1);
5484
5485
1.18k
    if (hMMMD->ePlainLT == MM_LayerType_Arc)
5486
369
    {
5487
369
        VSIFPrintfL(pF, LineReturn);
5488
369
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5489
369
                    szMMNomCampNVertexsDefecte);
5490
369
        VSIFPrintfL(pF, "visible=0" LineReturn);
5491
369
        VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5492
369
        MMWrite_ANSI_MetadataKeyDescriptor(
5493
369
            hMMMD, pF, szNumberOfVerticesEng, szNumberOfVerticesCat,
5494
369
            szNumberOfVerticesSpa, CPL_ENC_ISO8859_1);
5495
5496
369
        VSIFPrintfL(pF, LineReturn);
5497
369
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5498
369
                    szMMNomCampLongitudArcDefecte);
5499
369
        MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szLengthOfAarcEng,
5500
369
                                           szLengthOfAarcCat, szLengthOfAarcSpa,
5501
369
                                           CPL_ENC_ISO8859_1);
5502
5503
369
        VSIFPrintfL(pF, LineReturn);
5504
369
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5505
369
                    szMMNomCampNodeIniDefecte);
5506
369
        VSIFPrintfL(pF, "visible=0" LineReturn);
5507
369
        VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5508
369
        MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szInitialNodeEng,
5509
369
                                           szInitialNodeCat, szInitialNodeSpa,
5510
369
                                           CPL_ENC_ISO8859_1);
5511
5512
369
        VSIFPrintfL(pF, LineReturn);
5513
369
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5514
369
                    szMMNomCampNodeFiDefecte);
5515
369
        VSIFPrintfL(pF, "visible=0" LineReturn);
5516
369
        VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5517
369
        MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szFinalNodeEng,
5518
369
                                           szFinalNodeCat, szFinalNodeSpa,
5519
369
                                           CPL_ENC_ISO8859_1);
5520
5521
369
        VSIFPrintfL(pF, LineReturn);
5522
369
        VSIFPrintfL(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn);
5523
369
        VSIFPrintfL(pF, "NomCampNVertexs=%s" LineReturn,
5524
369
                    szMMNomCampNVertexsDefecte);
5525
369
        VSIFPrintfL(pF, "NomCampLongitudArc=%s" LineReturn,
5526
369
                    szMMNomCampLongitudArcDefecte);
5527
369
        VSIFPrintfL(pF, "NomCampNodeIni=%s" LineReturn,
5528
369
                    szMMNomCampNodeIniDefecte);
5529
369
        VSIFPrintfL(pF, "NomCampNodeFi=%s" LineReturn,
5530
369
                    szMMNomCampNodeFiDefecte);
5531
369
    }
5532
811
    else if (hMMMD->ePlainLT == MM_LayerType_Node)
5533
369
    {
5534
369
        VSIFPrintfL(pF, LineReturn);
5535
369
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5536
369
                    szMMNomCampArcsANodeDefecte);
5537
369
        VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5538
369
        MMWrite_ANSI_MetadataKeyDescriptor(
5539
369
            hMMMD, pF, szNumberOfArcsToNodeEng, szNumberOfArcsToNodeCat,
5540
369
            szNumberOfArcsToNodeSpa, CPL_ENC_ISO8859_1);
5541
5542
369
        VSIFPrintfL(pF, LineReturn);
5543
369
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5544
369
                    szMMNomCampTipusNodeDefecte);
5545
369
        VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5546
369
        MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNodeTypeEng,
5547
369
                                           szNodeTypeCat, szNodeTypeSpa,
5548
369
                                           CPL_ENC_ISO8859_1);
5549
5550
369
        VSIFPrintfL(pF, LineReturn);
5551
369
        VSIFPrintfL(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn);
5552
369
        VSIFPrintfL(pF, "NomCampArcsANode=%s" LineReturn,
5553
369
                    szMMNomCampArcsANodeDefecte);
5554
369
        VSIFPrintfL(pF, "NomCampTipusNode=%s" LineReturn,
5555
369
                    szMMNomCampTipusNodeDefecte);
5556
369
    }
5557
442
    else if (hMMMD->ePlainLT == MM_LayerType_Pol)
5558
157
    {
5559
157
        VSIFPrintfL(pF, LineReturn);
5560
157
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5561
157
                    szMMNomCampNVertexsDefecte);
5562
157
        VSIFPrintfL(pF, "visible=0" LineReturn);
5563
157
        VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5564
157
        MMWrite_ANSI_MetadataKeyDescriptor(
5565
157
            hMMMD, pF, szNumberOfVerticesEng, szNumberOfVerticesCat,
5566
157
            szNumberOfVerticesSpa, CPL_ENC_ISO8859_1);
5567
5568
157
        VSIFPrintfL(pF, LineReturn);
5569
157
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5570
157
                    szMMNomCampPerimetreDefecte);
5571
157
        MMWrite_ANSI_MetadataKeyDescriptor(
5572
157
            hMMMD, pF, szPerimeterOfThePolygonEng, szPerimeterOfThePolygonCat,
5573
157
            szPerimeterOfThePolygonSpa, CPL_ENC_ISO8859_1);
5574
5575
157
        VSIFPrintfL(pF, LineReturn);
5576
157
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5577
157
                    szMMNomCampAreaDefecte);
5578
157
        MMWrite_ANSI_MetadataKeyDescriptor(
5579
157
            hMMMD, pF, szAreaOfThePolygonEng, szAreaOfThePolygonCat,
5580
157
            szAreaOfThePolygonSpa, CPL_ENC_ISO8859_1);
5581
5582
157
        VSIFPrintfL(pF, LineReturn);
5583
157
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5584
157
                    szMMNomCampNArcsDefecte);
5585
157
        VSIFPrintfL(pF, "visible=0" LineReturn);
5586
157
        VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5587
157
        MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfArcsEng,
5588
157
                                           szNumberOfArcsCat, szNumberOfArcsSpa,
5589
157
                                           CPL_ENC_ISO8859_1);
5590
5591
157
        VSIFPrintfL(pF, LineReturn);
5592
157
        VSIFPrintfL(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5593
157
                    szMMNomCampNPoligonsDefecte);
5594
157
        VSIFPrintfL(pF, "visible=0" LineReturn);
5595
157
        VSIFPrintfL(pF, "simbolitzable=0" LineReturn);
5596
157
        MMWrite_ANSI_MetadataKeyDescriptor(
5597
157
            hMMMD, pF, szNumberOfElementaryPolygonsEng,
5598
157
            szNumberOfElementaryPolygonsCat, szNumberOfElementaryPolygonsSpa,
5599
157
            CPL_ENC_ISO8859_1);
5600
5601
157
        VSIFPrintfL(pF, LineReturn);
5602
157
        VSIFPrintfL(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn);
5603
157
        VSIFPrintfL(pF, "NomCampNVertexs=%s" LineReturn,
5604
157
                    szMMNomCampNVertexsDefecte);
5605
157
        VSIFPrintfL(pF, "NomCampPerimetre=%s" LineReturn,
5606
157
                    szMMNomCampPerimetreDefecte);
5607
157
        VSIFPrintfL(pF, "NomCampArea=%s" LineReturn, szMMNomCampAreaDefecte);
5608
157
        VSIFPrintfL(pF, "NomCampNArcs=%s" LineReturn, szMMNomCampNArcsDefecte);
5609
157
        VSIFPrintfL(pF, "NomCampNPoligons=%s" LineReturn,
5610
157
                    szMMNomCampNPoligonsDefecte);
5611
157
    }
5612
5613
1.18k
    if (hMMMD->pLayerDB && hMMMD->pLayerDB->nNFields > 0)
5614
654
    {
5615
        // For each field of the databes
5616
2.57k
        for (nIField = 0; nIField < hMMMD->pLayerDB->nNFields; nIField++)
5617
1.92k
        {
5618
1.92k
            bool bModifiedFieldName = false;
5619
1.92k
            if (*hMMMD->pLayerDB->pFields[nIField].pszFieldModifName != '\0')
5620
2
                bModifiedFieldName = true;
5621
5622
            // If exists a modified name we need to document that one.
5623
1.92k
            VSIFPrintfL(
5624
1.92k
                pF, LineReturn "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5625
1.92k
                bModifiedFieldName
5626
1.92k
                    ? hMMMD->pLayerDB->pFields[nIField].pszFieldModifName
5627
1.92k
                    : hMMMD->pLayerDB->pFields[nIField].pszFieldName);
5628
5629
1.92k
            if (!MMIsEmptyString(
5630
1.92k
                    hMMMD->pLayerDB->pFields[nIField].pszFieldDescription) &&
5631
0
                !MMIsEmptyString(
5632
0
                    hMMMD->pLayerDB->pFields[nIField].pszFieldName))
5633
0
            {
5634
0
                if (bModifiedFieldName)
5635
0
                {
5636
0
                    MMWrite_ANSI_MetadataKeyDescriptor(
5637
0
                        hMMMD, pF,
5638
0
                        hMMMD->pLayerDB->pFields[nIField]
5639
0
                            .pszFieldModifDescription,
5640
0
                        hMMMD->pLayerDB->pFields[nIField]
5641
0
                            .pszFieldModifDescription,
5642
0
                        hMMMD->pLayerDB->pFields[nIField]
5643
0
                            .pszFieldModifDescription,
5644
0
                        CPL_ENC_UTF8);
5645
0
                }
5646
0
                else
5647
0
                {
5648
0
                    MMWrite_ANSI_MetadataKeyDescriptor(
5649
0
                        hMMMD, pF,
5650
0
                        hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5651
0
                        hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5652
0
                        hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5653
0
                        CPL_ENC_UTF8);
5654
0
                }
5655
0
            }
5656
5657
1.92k
            if (bModifiedFieldName &&
5658
2
                EQUAL(szMMNomCampIdGraficDefecte,
5659
1.92k
                      hMMMD->pLayerDB->pFields[nIField].pszFieldName))
5660
0
            {
5661
0
                VSIFPrintfL(pF, "TractamentVariable=Ordinal" LineReturn);
5662
0
            }
5663
5664
            // Exception in a particular case: "altura" is a catalan word that means
5665
            // "height". Its unit by default will be "m" instead of "unknown".
5666
            // The same goes for "z", which easily means height.
5667
1.92k
            if (EQUAL("altura",
5668
1.92k
                      hMMMD->pLayerDB->pFields[nIField].pszFieldName) ||
5669
1.92k
                EQUAL("z", hMMMD->pLayerDB->pFields[nIField].pszFieldName))
5670
0
            {
5671
0
                VSIFPrintfL(pF, "unitats=m" LineReturn);
5672
0
            }
5673
1.92k
            else
5674
1.92k
            {
5675
                // By default units of field values will not be shown.
5676
1.92k
                VSIFPrintfL(pF, "MostrarUnitats=0" LineReturn);
5677
1.92k
            }
5678
1.92k
        }
5679
654
    }
5680
1.18k
    VSIFCloseL(pF);
5681
1.18k
    return 0;
5682
1.18k
}
5683
5684
// Writes metadata files for MiraMon vector layers
5685
static int MMWriteVectorMetadataFile(struct MiraMonVectLayerInfo *hMiraMonLayer,
5686
                                     int layerPlainType, int layerMainPlainType)
5687
3.25k
{
5688
3.25k
    struct MiraMonVectorMetaData hMMMD;
5689
5690
3.25k
    if (!hMiraMonLayer)
5691
0
        return 1;
5692
5693
    // MiraMon writes a REL file of each .pnt, .arc, .nod or .pol
5694
3.25k
    memset(&hMMMD, 0, sizeof(hMMMD));
5695
3.25k
    hMMMD.ePlainLT = layerPlainType;
5696
3.25k
    hMMMD.pSRS = hMiraMonLayer->pSRS;
5697
3.25k
    hMMMD.pZUnit = hMiraMonLayer->pZUnit;
5698
3.25k
    hMMMD.nMMLanguage = hMiraMonLayer->nMMLanguage;
5699
5700
3.25k
    hMMMD.szLayerTitle = hMiraMonLayer->szLayerTitle;
5701
3.25k
    if (layerPlainType == MM_LayerType_Point)
5702
285
    {
5703
285
        hMMMD.aLayerName = hMiraMonLayer->MMPoint.pszREL_LayerName;
5704
285
        if (MMIsEmptyString(hMMMD.aLayerName))
5705
0
            return 0;  // If no file, no error. Just continue.
5706
285
        memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB, sizeof(hMMMD.hBB));
5707
285
        hMMMD.pLayerDB = hMiraMonLayer->pLayerDB;
5708
285
        return MMWriteMetadataFile(&hMMMD);
5709
285
    }
5710
2.96k
    else if (layerPlainType == MM_LayerType_Arc)
5711
369
    {
5712
369
        int nResult;
5713
5714
        // Arcs and not polygons
5715
369
        if (layerMainPlainType == MM_LayerType_Arc)
5716
212
        {
5717
212
            hMMMD.aLayerName = hMiraMonLayer->MMArc.pszREL_LayerName;
5718
212
            if (MMIsEmptyString(hMMMD.aLayerName))
5719
0
                return 0;  // If no file, no error. Just continue.
5720
212
            memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB,
5721
212
                   sizeof(hMMMD.hBB));
5722
212
            hMMMD.pLayerDB = hMiraMonLayer->pLayerDB;
5723
212
        }
5724
        // Arcs and polygons
5725
157
        else
5726
157
        {
5727
            // Arc from polygon
5728
157
            hMMMD.aLayerName = hMiraMonLayer->MMPolygon.MMArc.pszREL_LayerName;
5729
157
            if (MMIsEmptyString(hMMMD.aLayerName))
5730
0
                return 0;  // If no file, no error. Just continue.
5731
5732
157
            memcpy(&hMMMD.hBB, &hMiraMonLayer->MMPolygon.TopArcHeader.hBB,
5733
157
                   sizeof(hMMMD.hBB));
5734
157
            hMMMD.pLayerDB = nullptr;
5735
157
            hMMMD.aArcFile = CPLStrdup(
5736
157
                CPLGetFilename(hMiraMonLayer->MMPolygon.pszLayerName));
5737
157
        }
5738
369
        nResult = MMWriteMetadataFile(&hMMMD);
5739
369
        VSIFree(hMMMD.aArcFile);
5740
369
        return nResult;
5741
369
    }
5742
2.59k
    else if (layerPlainType == MM_LayerType_Pol)
5743
157
    {
5744
157
        int nResult;
5745
5746
157
        hMMMD.aLayerName = hMiraMonLayer->MMPolygon.pszREL_LayerName;
5747
5748
157
        if (MMIsEmptyString(hMMMD.aLayerName))
5749
0
            return 0;  // If no file, no error. Just continue.
5750
5751
157
        memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB, sizeof(hMMMD.hBB));
5752
157
        hMMMD.pLayerDB = hMiraMonLayer->pLayerDB;
5753
157
        hMMMD.aArcFile = CPLStrdup(
5754
157
            CPLGetFilename(hMiraMonLayer->MMPolygon.MMArc.pszLayerName));
5755
157
        nResult = MMWriteMetadataFile(&hMMMD);
5756
157
        VSIFree(hMMMD.aArcFile);
5757
157
        return nResult;
5758
157
    }
5759
2.44k
    else if (layerPlainType == MM_LayerType_Node)
5760
369
    {
5761
        // Node from arc
5762
369
        if (layerMainPlainType == MM_LayerType_Arc)
5763
212
        {
5764
212
            hMMMD.aLayerName = hMiraMonLayer->MMArc.MMNode.pszREL_LayerName;
5765
212
            if (MMIsEmptyString(hMMMD.aLayerName))
5766
0
                return 0;  // If no file, no error. Just continue.
5767
212
            memcpy(&hMMMD.hBB, &hMiraMonLayer->MMArc.TopNodeHeader.hBB,
5768
212
                   sizeof(hMMMD.hBB));
5769
212
        }
5770
157
        else  // Node from polygon
5771
157
        {
5772
157
            hMMMD.aLayerName =
5773
157
                hMiraMonLayer->MMPolygon.MMArc.MMNode.pszREL_LayerName;
5774
157
            if (MMIsEmptyString(hMMMD.aLayerName))
5775
0
                return 0;  // If no file, no error. Just continue.
5776
157
            memcpy(&hMMMD.hBB,
5777
157
                   &hMiraMonLayer->MMPolygon.MMArc.TopNodeHeader.hBB,
5778
157
                   sizeof(hMMMD.hBB));
5779
157
        }
5780
369
        hMMMD.pLayerDB = nullptr;
5781
369
        return MMWriteMetadataFile(&hMMMD);
5782
369
    }
5783
2.07k
    return 0;
5784
3.25k
}
5785
5786
int MMWriteVectorMetadata(struct MiraMonVectLayerInfo *hMiraMonLayer)
5787
2.72k
{
5788
2.72k
    if (!hMiraMonLayer)
5789
0
        return 1;
5790
5791
2.72k
    if (hMiraMonLayer->bIsPoint)
5792
285
        return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Point,
5793
285
                                         MM_LayerType_Point);
5794
2.44k
    if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
5795
212
    {
5796
212
        if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Node,
5797
212
                                      MM_LayerType_Arc))
5798
0
            return 1;
5799
212
        return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Arc,
5800
212
                                         MM_LayerType_Arc);
5801
212
    }
5802
2.22k
    if (hMiraMonLayer->bIsPolygon)
5803
157
    {
5804
157
        if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Node,
5805
157
                                      MM_LayerType_Pol))
5806
0
            return 1;
5807
157
        if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Arc,
5808
157
                                      MM_LayerType_Pol))
5809
0
            return 1;
5810
157
        return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Pol,
5811
157
                                         MM_LayerType_Pol);
5812
157
    }
5813
2.07k
    if (hMiraMonLayer->bIsDBF)
5814
2.07k
    {
5815
2.07k
        return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Unknown,
5816
2.07k
                                         MM_LayerType_Unknown);
5817
2.07k
    }
5818
0
    return 0;
5819
2.07k
}
5820
5821
/* -------------------------------------------------------------------- */
5822
/*      MiraMon database functions                                      */
5823
/* -------------------------------------------------------------------- */
5824
5825
// Initializes a MiraMon database associated with a vector layer:
5826
// Sets the usual fields that MiraMon needs and after them, adds
5827
// all fields of the input layer
5828
static int MMInitMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
5829
                      struct MMAdmDatabase *pMMAdmDB)
5830
97.7k
{
5831
97.7k
    if (!hMiraMonLayer || !pMMAdmDB)
5832
0
        return 1;
5833
5834
97.7k
    if (MMIsEmptyString(pMMAdmDB->pszExtDBFLayerName))
5835
0
        return 0;  // No file, no error. Just continue
5836
5837
97.7k
    strcpy(pMMAdmDB->pMMBDXP->ReadingMode, "wb+");
5838
97.7k
    if (FALSE == MM_CreateAndOpenDBFFile(pMMAdmDB->pMMBDXP,
5839
97.7k
                                         pMMAdmDB->pszExtDBFLayerName))
5840
95.1k
    {
5841
95.1k
        CPLError(CE_Failure, CPLE_OpenFailed,
5842
95.1k
                 "Error pMMAdmDB: Cannot create or open file %s.",
5843
95.1k
                 pMMAdmDB->pszExtDBFLayerName);
5844
95.1k
        return 1;
5845
95.1k
    }
5846
5847
2.57k
    VSIFSeekL(pMMAdmDB->pMMBDXP->pfDataBase,
5848
2.57k
              pMMAdmDB->pMMBDXP->FirstRecordOffset, SEEK_SET);
5849
5850
2.57k
    if (MMInitFlush(&pMMAdmDB->FlushRecList, pMMAdmDB->pMMBDXP->pfDataBase,
5851
2.57k
                    MM_1MB, &pMMAdmDB->pRecList,
5852
2.57k
                    pMMAdmDB->pMMBDXP->FirstRecordOffset, 0))
5853
0
        return 1;
5854
5855
2.57k
    pMMAdmDB->nNumRecordOnCourse =
5856
2.57k
        (GUInt64)pMMAdmDB->pMMBDXP->BytesPerRecord + 1;
5857
2.57k
    if (MMCheckSize_t(pMMAdmDB->nNumRecordOnCourse, 1))
5858
0
        return 1;
5859
2.57k
    pMMAdmDB->szRecordOnCourse =
5860
2.57k
        VSICalloc(1, (size_t)pMMAdmDB->nNumRecordOnCourse);
5861
2.57k
    if (!pMMAdmDB->szRecordOnCourse)
5862
0
    {
5863
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
5864
0
                 "Memory error in MiraMon "
5865
0
                 "driver (MMInitMMDB())");
5866
0
        return 1;
5867
0
    }
5868
2.57k
    return 0;
5869
2.57k
}
5870
5871
// Creates a MiraMon database associated with a vector layer.
5872
// It determines the number of fields and initializes the database header
5873
// accordingly. Depending on the layer type (point, arc, polygon, or generic),
5874
// it defines the fields and initializes the corresponding MiraMon database
5875
// structures.
5876
int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
5877
                 struct MM_POINT_2D *pFirstCoord)
5878
97.2k
{
5879
97.2k
    struct MM_DATA_BASE_XP *pBD_XP = nullptr, *pBD_XP_Aux = nullptr;
5880
97.2k
    struct MM_FIELD MMField;
5881
97.2k
    size_t nIFieldLayer;
5882
97.2k
    MM_EXT_DBF_N_FIELDS nIField = 0;
5883
97.2k
    MM_EXT_DBF_N_FIELDS nNFields;
5884
5885
97.2k
    if (!hMiraMonLayer)
5886
0
        return 1;
5887
5888
    // If the SRS is unknown, we attempt to deduce the appropriate number
5889
    // of decimals to be used in the reserved fields as LONG_ARC, PERIMETRE,
5890
    // or AREA using the coordinate values. It's not 100% reliable, but it's a
5891
    // good approximation.
5892
97.2k
    if (hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_UNKNOWN_TYPE && pFirstCoord)
5893
615
    {
5894
615
        if (pFirstCoord->dfX < -360 || pFirstCoord->dfX > 360)
5895
135
            hMiraMonLayer->nSRSType = MM_SRS_LAYER_IS_PROJECTED_TYPE;
5896
480
        else
5897
480
            hMiraMonLayer->nSRSType = MM_SRS_LAYER_IS_GEOGRAPHIC_TYPE;
5898
615
    }
5899
5900
97.2k
    if (hMiraMonLayer->bIsPoint)
5901
1.67k
    {
5902
1.67k
        if (hMiraMonLayer->pLayerDB)
5903
1.67k
            nNFields =
5904
1.67k
                MM_PRIVATE_POINT_DB_FIELDS + hMiraMonLayer->pLayerDB->nNFields;
5905
0
        else
5906
0
            nNFields = MM_PRIVATE_POINT_DB_FIELDS;
5907
5908
        // Before allocating new memory, there might be some previously allocated but unused memory.
5909
        // Let's free that memory first.
5910
1.67k
        if (hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP)
5911
1.39k
            MM_ReleaseDBFHeader(&hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP);
5912
5913
1.67k
        pBD_XP = hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP =
5914
1.67k
            MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet);
5915
5916
1.67k
        if (!pBD_XP)
5917
0
            return 1;
5918
5919
1.67k
        if (0 == (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstPointFieldsDB_XP(
5920
1.67k
                      pBD_XP)))
5921
0
            return 1;
5922
1.67k
    }
5923
95.5k
    else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
5924
1.72k
    {
5925
1.72k
        if (hMiraMonLayer->pLayerDB)
5926
1.72k
            nNFields =
5927
1.72k
                MM_PRIVATE_ARC_DB_FIELDS + hMiraMonLayer->pLayerDB->nNFields;
5928
0
        else
5929
0
            nNFields = MM_PRIVATE_ARC_DB_FIELDS;
5930
5931
        // Before allocating new memory, there might be some previously allocated but unused memory.
5932
        // Let's free that memory first.
5933
1.72k
        if (hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP)
5934
1.50k
            MM_ReleaseDBFHeader(&hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP);
5935
5936
1.72k
        pBD_XP = hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP =
5937
1.72k
            MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet);
5938
5939
1.72k
        if (!pBD_XP)
5940
0
            return 1;
5941
5942
1.72k
        if (0 == (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstArcFieldsDB_XP(
5943
1.72k
                      pBD_XP,
5944
1.72k
                      hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE
5945
1.72k
                          ? 3
5946
1.72k
                          : 9)))
5947
0
            return 1;
5948
5949
        // Before allocating new memory, there might be some previously allocated but unused memory.
5950
        // Let's free that memory first.
5951
1.72k
        if (hMiraMonLayer->MMArc.MMNode.MMAdmDB.pMMBDXP)
5952
1.50k
            MM_ReleaseDBFHeader(&hMiraMonLayer->MMArc.MMNode.MMAdmDB.pMMBDXP);
5953
5954
1.72k
        pBD_XP_Aux = hMiraMonLayer->MMArc.MMNode.MMAdmDB.pMMBDXP =
5955
1.72k
            MM_CreateDBFHeader(3, hMiraMonLayer->nCharSet);
5956
5957
1.72k
        if (!pBD_XP_Aux)
5958
0
            return 1;
5959
5960
1.72k
        if (0 == MM_DefineFirstNodeFieldsDB_XP(pBD_XP_Aux))
5961
0
            return 1;
5962
1.72k
    }
5963
93.8k
    else if (hMiraMonLayer->bIsPolygon)
5964
1.00k
    {
5965
1.00k
        if (hMiraMonLayer->pLayerDB)
5966
1.00k
            nNFields = MM_PRIVATE_POLYGON_DB_FIELDS +
5967
1.00k
                       hMiraMonLayer->pLayerDB->nNFields;
5968
0
        else
5969
0
            nNFields = MM_PRIVATE_POLYGON_DB_FIELDS;
5970
5971
        // Before allocating new memory, there might be some previously allocated but unused memory.
5972
        // Let's free that memory first.
5973
1.00k
        if (hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP)
5974
793
            MM_ReleaseDBFHeader(&hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP);
5975
5976
1.00k
        pBD_XP = hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP =
5977
1.00k
            MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet);
5978
5979
1.00k
        if (!pBD_XP)
5980
0
            return 1;
5981
5982
1.00k
        if (0 ==
5983
1.00k
            (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstPolygonFieldsDB_XP(
5984
1.00k
                 pBD_XP,
5985
1.00k
                 hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE ? 3
5986
1.00k
                                                                           : 9,
5987
1.00k
                 hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE
5988
1.00k
                     ? 3
5989
1.00k
                     : 12)))
5990
0
            return 1;
5991
5992
        // Before allocating new memory, there might be some previously allocated but unused memory.
5993
        // Let's free that memory first.
5994
1.00k
        if (hMiraMonLayer->MMPolygon.MMArc.MMAdmDB.pMMBDXP)
5995
793
            MM_ReleaseDBFHeader(
5996
793
                &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB.pMMBDXP);
5997
5998
1.00k
        pBD_XP_Aux = hMiraMonLayer->MMPolygon.MMArc.MMAdmDB.pMMBDXP =
5999
1.00k
            MM_CreateDBFHeader(5, hMiraMonLayer->nCharSet);
6000
6001
1.00k
        if (!pBD_XP_Aux)
6002
0
            return 1;
6003
6004
1.00k
        if (0 == MM_DefineFirstArcFieldsDB_XP(
6005
1.00k
                     pBD_XP_Aux,
6006
1.00k
                     hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE
6007
1.00k
                         ? 3
6008
1.00k
                         : 9))
6009
0
            return 1;
6010
6011
        // Before allocating new memory, there might be some previously allocated but unused memory.
6012
        // Let's free that memory first.
6013
1.00k
        if (hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB.pMMBDXP)
6014
793
            MM_ReleaseDBFHeader(
6015
793
                &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB.pMMBDXP);
6016
6017
1.00k
        pBD_XP_Aux = hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB.pMMBDXP =
6018
1.00k
            MM_CreateDBFHeader(3, hMiraMonLayer->nCharSet);
6019
6020
1.00k
        if (!pBD_XP_Aux)
6021
0
            return 1;
6022
6023
1.00k
        if (0 == MM_DefineFirstNodeFieldsDB_XP(pBD_XP_Aux))
6024
0
            return 1;
6025
1.00k
    }
6026
92.8k
    else if (hMiraMonLayer->bIsDBF)
6027
92.8k
    {
6028
        // Creating only a DBF
6029
92.8k
        if (hMiraMonLayer->pLayerDB)
6030
92.7k
            nNFields = hMiraMonLayer->pLayerDB->nNFields;
6031
52
        else
6032
52
            nNFields = 0;
6033
6034
92.8k
        pBD_XP = hMiraMonLayer->MMAdmDBWriting.pMMBDXP =
6035
92.8k
            MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet);
6036
6037
92.8k
        if (!pBD_XP)
6038
0
            return 1;
6039
92.8k
    }
6040
0
    else
6041
0
        return 0;
6042
6043
    // After private MiraMon fields, other fields are added.
6044
    // If names are no compatible, some changes are done.
6045
97.2k
    if (hMiraMonLayer->pLayerDB)
6046
97.1k
    {
6047
597k
        for (nIFieldLayer = 0; nIField < nNFields; nIField++, nIFieldLayer++)
6048
500k
        {
6049
500k
            MM_InitializeField(&MMField);
6050
500k
            CPLStrlcpy(
6051
500k
                MMField.FieldName,
6052
500k
                hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].pszFieldName,
6053
500k
                MM_MAX_LON_FIELD_NAME_DBF);
6054
6055
500k
            CPLStrlcpy(MMField.FieldDescription[0],
6056
500k
                       hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6057
500k
                           .pszFieldDescription,
6058
500k
                       MM_MAX_BYTES_FIELD_DESC);
6059
6060
500k
            MMField.BytesPerField =
6061
500k
                hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].nFieldSize;
6062
500k
            switch (hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].eFieldType)
6063
500k
            {
6064
5.71k
                case MM_Numeric:
6065
5.71k
                    MMField.FieldType = 'N';
6066
5.71k
                    if (hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6067
5.71k
                            .bIs64BitInteger)
6068
7
                        MMField.Is64 = 1;
6069
5.71k
                    if (MMField.BytesPerField == 0)
6070
0
                        MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_N_DBF;
6071
5.71k
                    break;
6072
494k
                case MM_Character:
6073
494k
                    MMField.FieldType = 'C';
6074
494k
                    if (MMField.BytesPerField == 0)
6075
0
                        MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_C_DBF;
6076
494k
                    break;
6077
0
                case MM_Data:
6078
0
                    MMField.FieldType = 'D';
6079
0
                    if (MMField.BytesPerField == 0)
6080
0
                        MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_D_DBF;
6081
0
                    break;
6082
0
                case MM_Logic:
6083
0
                    MMField.FieldType = 'L';
6084
0
                    if (MMField.BytesPerField == 0)
6085
0
                        MMField.BytesPerField = 1;
6086
0
                    break;
6087
0
                default:
6088
0
                    MMField.FieldType = 'C';
6089
0
                    if (MMField.BytesPerField == 0)
6090
0
                        MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_C_DBF;
6091
500k
            };
6092
6093
500k
            MMField.DecimalsIfFloat =
6094
500k
                (MM_BYTE)hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6095
500k
                    .nNumberOfDecimals;
6096
6097
500k
            MM_DuplicateFieldDBXP(pBD_XP->pField + nIField, &MMField);
6098
500k
            MM_ModifyFieldNameAndDescriptorIfPresentBD_XP(
6099
500k
                pBD_XP->pField + nIField, pBD_XP, FALSE, 0);
6100
6101
500k
            if (!EQUAL(pBD_XP->pField[nIField].FieldName,
6102
500k
                       hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6103
500k
                           .pszFieldName))
6104
2.57k
            {
6105
                // We need to preserve the final given name to write
6106
                // metadata with the modified new name.
6107
2.57k
                CPLStrlcpy(hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6108
2.57k
                               .pszFieldModifName,
6109
2.57k
                           pBD_XP->pField[nIField].FieldName,
6110
2.57k
                           MM_MAX_LON_FIELD_NAME_DBF);
6111
6112
2.57k
                CPLStrlcpy(
6113
2.57k
                    hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6114
2.57k
                        .pszFieldModifDescription,
6115
2.57k
                    pBD_XP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
6116
2.57k
                    MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
6117
6118
                // In this case we are going to use also the modified description in metadata
6119
2.57k
                switch (hMiraMonLayer->nMMLanguage)
6120
2.57k
                {
6121
0
                    case MM_CAT_LANGUAGE:
6122
0
                        CPLStrlcat(
6123
0
                            hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6124
0
                                .pszFieldModifDescription,
6125
0
                            " (previ)", MM_MAX_BYTES_FIELD_DESC + 1);
6126
0
                        break;
6127
0
                    case MM_SPA_LANGUAGE:
6128
0
                        CPLStrlcat(
6129
0
                            hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6130
0
                                .pszFieldModifDescription,
6131
0
                            " (previo)", MM_MAX_BYTES_FIELD_DESC + 1);
6132
0
                        break;
6133
2.57k
                    default:
6134
2.57k
                    case MM_ENG_LANGUAGE:
6135
2.57k
                        CPLStrlcat(
6136
2.57k
                            hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6137
2.57k
                                .pszFieldModifDescription,
6138
2.57k
                            " (previous)", MM_MAX_BYTES_FIELD_DESC + 1);
6139
2.57k
                        break;
6140
2.57k
                }
6141
2.57k
            }
6142
498k
            else
6143
498k
                *hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6144
498k
                     .pszFieldModifName = '\0';
6145
6146
500k
            if (pBD_XP->pField[nIField].FieldType == 'F')
6147
0
                pBD_XP->pField[nIField].FieldType = 'N';
6148
500k
        }
6149
97.1k
    }
6150
6151
97.2k
    if (hMiraMonLayer->bIsPoint)
6152
1.67k
    {
6153
1.67k
        if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB))
6154
1.47k
            return 1;
6155
1.67k
    }
6156
95.5k
    else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
6157
1.72k
    {
6158
1.72k
        if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB))
6159
1.56k
            return 1;
6160
6161
157
        if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMArc.MMNode.MMAdmDB))
6162
0
            return 1;
6163
157
    }
6164
93.8k
    else if (hMiraMonLayer->bIsPolygon)
6165
1.00k
    {
6166
1.00k
        if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMAdmDB))
6167
829
            return 1;
6168
6169
172
        if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB))
6170
0
            return 1;
6171
6172
172
        if (MMInitMMDB(hMiraMonLayer,
6173
172
                       &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB))
6174
0
            return 1;
6175
172
    }
6176
92.8k
    else if (hMiraMonLayer->bIsDBF)
6177
92.8k
    {
6178
92.8k
        if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting))
6179
91.2k
            return 1;
6180
92.8k
    }
6181
2.07k
    return 0;
6182
97.2k
}
6183
6184
// Checks and fits the width of a specific field in a MiraMon database
6185
// associated with a vector layer. It examines the length of the provided
6186
// value and resizes the field width, if necessary, to accommodate the new
6187
// value. If the new width exceeds the current width of the field,
6188
// it updates the database structure, including the field width and
6189
// the size of the record. Additionally, it reallocates memory if needed
6190
// for the record handling buffer.
6191
6192
static int
6193
MMTestAndFixValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer,
6194
                              struct MMAdmDatabase *pMMAdmDB,
6195
                              MM_EXT_DBF_N_FIELDS nIField, char *szValue)
6196
885k
{
6197
885k
    struct MM_FIELD *camp;
6198
885k
    MM_BYTES_PER_FIELD_TYPE_DBF nNewWidth;
6199
6200
885k
    if (!hMiraMonLayer || !pMMAdmDB || !pMMAdmDB->pMMBDXP ||
6201
885k
        !pMMAdmDB->pMMBDXP->pField || !pMMAdmDB->pMMBDXP->pfDataBase)
6202
0
        return 1;
6203
6204
885k
    camp = pMMAdmDB->pMMBDXP->pField + nIField;
6205
6206
885k
    if (!szValue)
6207
2.21k
        return 0;
6208
6209
883k
    nNewWidth = (MM_BYTES_PER_FIELD_TYPE_DBF)strlen(szValue);
6210
883k
    if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, nNewWidth + 1))
6211
0
        return 1;
6212
6213
883k
    if (nNewWidth > camp->BytesPerField)
6214
8.51k
    {
6215
8.51k
        if (MM_WriteNRecordsMMBD_XPFile(pMMAdmDB->pMMBDXP))
6216
0
            return 1;
6217
6218
        // Flushing all to be flushed
6219
8.51k
        pMMAdmDB->FlushRecList.SizeOfBlockToBeSaved = 0;
6220
8.51k
        if (MMAppendBlockToBuffer(&pMMAdmDB->FlushRecList))
6221
0
            return 1;
6222
6223
8.51k
        if (MM_ChangeDBFWidthField(
6224
8.51k
                pMMAdmDB->pMMBDXP, nIField, nNewWidth,
6225
8.51k
                pMMAdmDB->pMMBDXP->pField[nIField].DecimalsIfFloat))
6226
0
            return 1;
6227
6228
        // The record on course also has to change its size.
6229
8.51k
        if ((GUInt64)pMMAdmDB->pMMBDXP->BytesPerRecord + 1 >=
6230
8.51k
            pMMAdmDB->nNumRecordOnCourse)
6231
8.51k
        {
6232
8.51k
            void *pTmp;
6233
8.51k
            if (nullptr == (pTmp = VSIRealloc(
6234
8.51k
                                pMMAdmDB->szRecordOnCourse,
6235
8.51k
                                (size_t)pMMAdmDB->pMMBDXP->BytesPerRecord + 1)))
6236
0
            {
6237
0
                CPLError(CE_Failure, CPLE_OutOfMemory,
6238
0
                         "Memory error in MiraMon "
6239
0
                         "driver (MMTestAndFixValueToRecordDBXP())");
6240
0
                return 1;
6241
0
            }
6242
8.51k
            pMMAdmDB->szRecordOnCourse = pTmp;
6243
8.51k
        }
6244
6245
        // File has changed its size, so it has to be updated
6246
        // at the Flush tool
6247
8.51k
        VSIFSeekL(pMMAdmDB->pMMBDXP->pfDataBase, 0, SEEK_END);
6248
8.51k
        pMMAdmDB->FlushRecList.OffsetWhereToFlush =
6249
8.51k
            VSIFTellL(pMMAdmDB->pMMBDXP->pfDataBase);
6250
8.51k
    }
6251
883k
    return 0;
6252
883k
}
6253
6254
static int
6255
MMWriteValueToszStringToOperate(struct MiraMonVectLayerInfo *hMiraMonLayer,
6256
                                const struct MM_FIELD *camp, const void *valor,
6257
                                MM_BOOLEAN is_64)
6258
893k
{
6259
893k
    if (!hMiraMonLayer)
6260
0
        return 1;
6261
6262
893k
    if (!camp)
6263
0
        return 0;
6264
6265
893k
    if (MMResizeStringToOperateIfNeeded(hMiraMonLayer,
6266
893k
                                        camp->BytesPerField + 10))
6267
0
        return 1;
6268
6269
893k
    if (!valor)
6270
0
        *hMiraMonLayer->szStringToOperate = '\0';
6271
893k
    else
6272
893k
    {
6273
893k
        if (camp->FieldType == 'N')
6274
66.0k
        {
6275
66.0k
            if (!is_64)
6276
25.9k
            {
6277
25.9k
                snprintf(hMiraMonLayer->szStringToOperate,
6278
25.9k
                         (size_t)hMiraMonLayer->nNumStringToOperate, "%*.*f",
6279
25.9k
                         camp->BytesPerField, camp->DecimalsIfFloat,
6280
25.9k
                         *(const double *)valor);
6281
25.9k
            }
6282
40.0k
            else
6283
40.0k
            {
6284
40.0k
                snprintf(hMiraMonLayer->szStringToOperate,
6285
40.0k
                         (size_t)hMiraMonLayer->nNumStringToOperate, "%*lld",
6286
40.0k
                         camp->BytesPerField, *(const GInt64 *)valor);
6287
40.0k
            }
6288
66.0k
        }
6289
827k
        else
6290
827k
        {
6291
827k
            snprintf(hMiraMonLayer->szStringToOperate,
6292
827k
                     (size_t)hMiraMonLayer->nNumStringToOperate, "%-*s",
6293
827k
                     camp->BytesPerField, (const char *)valor);
6294
827k
        }
6295
893k
    }
6296
6297
893k
    return 0;
6298
893k
}
6299
6300
int MMWritePreformatedNumberValueToRecordDBXP(
6301
    struct MiraMonVectLayerInfo *hMiraMonLayer, char *registre,
6302
    const struct MM_FIELD *camp, const char *valor)
6303
1.05k
{
6304
1.05k
    if (!hMiraMonLayer)
6305
0
        return 1;
6306
6307
1.05k
    if (!camp)
6308
0
        return 0;
6309
6310
1.05k
    if (MMResizeStringToOperateIfNeeded(hMiraMonLayer,
6311
1.05k
                                        camp->BytesPerField + 10))
6312
0
        return 1;
6313
6314
1.05k
    if (!valor)
6315
0
        memset(hMiraMonLayer->szStringToOperate, 0, camp->BytesPerField);
6316
1.05k
    else
6317
1.05k
    {
6318
1.05k
        snprintf(hMiraMonLayer->szStringToOperate,
6319
1.05k
                 (size_t)hMiraMonLayer->nNumStringToOperate, "%*s",
6320
1.05k
                 camp->BytesPerField, valor);
6321
1.05k
    }
6322
6323
1.05k
    memcpy(registre + camp->AccumulatedBytes, hMiraMonLayer->szStringToOperate,
6324
1.05k
           camp->BytesPerField);
6325
1.05k
    return 0;
6326
1.05k
}
6327
6328
int MMWriteValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer,
6329
                             char *registre, const struct MM_FIELD *camp,
6330
                             const void *valor, MM_BOOLEAN is_64)
6331
860k
{
6332
860k
    if (!hMiraMonLayer)
6333
0
        return 1;
6334
6335
860k
    if (!camp)
6336
0
        return 0;
6337
6338
860k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer, camp, valor, is_64))
6339
0
        return 1;
6340
6341
860k
    memcpy(registre + camp->AccumulatedBytes, hMiraMonLayer->szStringToOperate,
6342
860k
           camp->BytesPerField);
6343
860k
    return 0;
6344
860k
}
6345
6346
static int MMAddFeatureRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6347
                                    struct MiraMonFeature *hMMFeature,
6348
                                    struct MMAdmDatabase *pMMAdmDB,
6349
                                    char *pszRecordOnCourse,
6350
                                    struct MM_FLUSH_INFO *pFlushRecList,
6351
                                    MM_EXT_DBF_N_RECORDS *nNumRecords,
6352
                                    MM_EXT_DBF_N_FIELDS nNumPrivateMMField)
6353
320k
{
6354
320k
    MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord;
6355
320k
    MM_EXT_DBF_N_FIELDS nIField;
6356
320k
    struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6357
6358
320k
    if (!hMiraMonLayer)
6359
0
        return 1;
6360
6361
320k
    if (!hMMFeature)
6362
0
        return 1;
6363
6364
320k
    pBD_XP = pMMAdmDB->pMMBDXP;
6365
640k
    for (nIRecord = 0; nIRecord < hMMFeature->nNumMRecords; nIRecord++)
6366
320k
    {
6367
1.17M
        for (nIField = 0; nIField < hMMFeature->pRecords[nIRecord].nNumField;
6368
852k
             nIField++)
6369
852k
        {
6370
            // A field with no valid value is written as blank
6371
852k
            if (!hMMFeature->pRecords[nIRecord].pField[nIField].bIsValid)
6372
23.9k
            {
6373
23.9k
                memset(
6374
23.9k
                    pszRecordOnCourse +
6375
23.9k
                        pBD_XP->pField[nIField + nNumPrivateMMField]
6376
23.9k
                            .AccumulatedBytes,
6377
23.9k
                    ' ',
6378
23.9k
                    pBD_XP->pField[nIField + nNumPrivateMMField].BytesPerField);
6379
6380
23.9k
                continue;
6381
23.9k
            }
6382
828k
            if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'C' ||
6383
1.06k
                pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'L' ||
6384
1.06k
                pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'D')
6385
827k
            {
6386
827k
                if (MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse,
6387
827k
                                             pBD_XP->pField + nIField +
6388
827k
                                                 nNumPrivateMMField,
6389
827k
                                             hMMFeature->pRecords[nIRecord]
6390
827k
                                                 .pField[nIField]
6391
827k
                                                 .pDinValue,
6392
827k
                                             FALSE))
6393
0
                    return 1;
6394
827k
            }
6395
1.06k
            else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType ==
6396
1.06k
                         'N' &&
6397
1.06k
                     !pBD_XP->pField[nIField + nNumPrivateMMField].Is64)
6398
1.05k
            {
6399
1.05k
                if (MMWritePreformatedNumberValueToRecordDBXP(
6400
1.05k
                        hMiraMonLayer, pszRecordOnCourse,
6401
1.05k
                        pBD_XP->pField + nIField + nNumPrivateMMField,
6402
1.05k
                        hMMFeature->pRecords[nIRecord]
6403
1.05k
                            .pField[nIField]
6404
1.05k
                            .pDinValue))
6405
0
                    return 1;
6406
1.05k
            }
6407
10
            else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType ==
6408
10
                     'N')
6409
10
            {
6410
10
                if (pBD_XP->pField[nIField + nNumPrivateMMField].Is64)
6411
10
                {
6412
10
                    if (MMWriteValueToRecordDBXP(
6413
10
                            hMiraMonLayer, pszRecordOnCourse,
6414
10
                            pBD_XP->pField + nIField + nNumPrivateMMField,
6415
10
                            &hMMFeature->pRecords[nIRecord]
6416
10
                                 .pField[nIField]
6417
10
                                 .iValue,
6418
10
                            TRUE))
6419
0
                        return 1;
6420
10
                }
6421
10
            }
6422
828k
        }
6423
6424
320k
        if (MMAppendBlockToBuffer(pFlushRecList))
6425
0
            return 1;
6426
6427
320k
        (*nNumRecords)++;
6428
320k
    }
6429
320k
    return 0;
6430
320k
}
6431
6432
// Adds feature records to a MiraMon database associated with a vector layer.
6433
static int MMDetectAndFixDBFWidthChange(
6434
    struct MiraMonVectLayerInfo *hMiraMonLayer,
6435
    struct MiraMonFeature *hMMFeature, struct MMAdmDatabase *pMMAdmDB,
6436
    MM_EXT_DBF_N_FIELDS nNumPrivateMMField,
6437
    MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord, MM_EXT_DBF_N_FIELDS nIField)
6438
852k
{
6439
852k
    if (!hMiraMonLayer)
6440
0
        return 1;
6441
6442
852k
    if (!hMMFeature)
6443
0
        return 1;
6444
6445
852k
    if (nIRecord >= hMMFeature->nNumMRecords)
6446
0
        return 1;
6447
6448
852k
    if (nIField >= hMMFeature->pRecords[nIRecord].nNumField)
6449
0
        return 1;
6450
6451
852k
    if (MMTestAndFixValueToRecordDBXP(
6452
852k
            hMiraMonLayer, pMMAdmDB, nIField + nNumPrivateMMField,
6453
852k
            hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue))
6454
0
        return 1;
6455
6456
    // We analyze next fields
6457
852k
    if (nIField == hMMFeature->pRecords[nIRecord].nNumField - 1)
6458
318k
    {
6459
318k
        if (nIRecord + 1 < hMMFeature->nNumMRecords)
6460
0
        {
6461
0
            if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6462
0
                                             pMMAdmDB, nNumPrivateMMField,
6463
0
                                             nIRecord + 1, 0))
6464
0
                return 1;
6465
0
        }
6466
318k
        else
6467
318k
            return 0;
6468
318k
    }
6469
533k
    else
6470
533k
    {
6471
533k
        if (nIField + 1 < hMMFeature->pRecords[nIRecord].nNumField)
6472
533k
        {
6473
533k
            if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6474
533k
                                             pMMAdmDB, nNumPrivateMMField,
6475
533k
                                             nIRecord, nIField + 1))
6476
0
                return 1;
6477
533k
        }
6478
0
        else
6479
0
            return 0;
6480
533k
    }
6481
533k
    return 0;
6482
852k
}  // End of MMDetectAndFixDBFWidthChange()
6483
6484
// Adds a DBF record to a MiraMon table associated with a vector layer.
6485
// It sets up flush settings for writing to the table and initializes
6486
// variables needed for the process. Then, it checks and fixes the width
6487
// change if necessary.
6488
int MMAddDBFRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6489
                         struct MiraMonFeature *hMMFeature)
6490
316k
{
6491
316k
    struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6492
316k
    MM_EXT_DBF_N_FIELDS nNumPrivateMMField = 0;
6493
316k
    struct MM_FLUSH_INFO *pFlushRecList;
6494
6495
316k
    if (!hMiraMonLayer)
6496
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6497
6498
316k
    pBD_XP = hMiraMonLayer->MMAdmDBWriting.pMMBDXP;
6499
6500
    // Test length
6501
316k
    if (hMMFeature && hMMFeature->nNumMRecords &&
6502
316k
        hMMFeature->pRecords[0].nNumField)
6503
314k
    {
6504
314k
        if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6505
314k
                                         &hMiraMonLayer->MMAdmDBWriting,
6506
314k
                                         nNumPrivateMMField, 0, 0))
6507
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6508
314k
    }
6509
6510
    // Adding record to the MiraMon table (extended DBF)
6511
    // Flush settings
6512
316k
    pFlushRecList = &hMiraMonLayer->MMAdmDBWriting.FlushRecList;
6513
316k
    pFlushRecList->pBlockWhereToSaveOrRead =
6514
316k
        (void *)hMiraMonLayer->MMAdmDBWriting.pRecList;
6515
6516
316k
    pFlushRecList->pBlockToBeSaved =
6517
316k
        (void *)hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse;
6518
316k
    pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
6519
6520
316k
    if (MMAddFeatureRecordToMMDB(
6521
316k
            hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMAdmDBWriting,
6522
316k
            hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse, pFlushRecList,
6523
316k
            &hMiraMonLayer->MMAdmDBWriting.pMMBDXP->nRecords,
6524
316k
            nNumPrivateMMField))
6525
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6526
6527
    // In this case, the number of features is also updated
6528
316k
    hMiraMonLayer->TopHeader.nElemCount =
6529
316k
        hMiraMonLayer->MMAdmDBWriting.pMMBDXP->nRecords;
6530
6531
316k
    return MM_CONTINUE_WRITING_FEATURES;
6532
316k
}
6533
6534
// Adds a point record to a MiraMon table associated with a vector layer.
6535
int MMAddPointRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6536
                           struct MiraMonFeature *hMMFeature,
6537
                           MM_INTERNAL_FID nElemCount)
6538
1.52k
{
6539
1.52k
    struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6540
1.52k
    MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_POINT_DB_FIELDS;
6541
1.52k
    struct MM_FLUSH_INFO *pFlushRecList;
6542
6543
1.52k
    if (!hMiraMonLayer)
6544
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6545
6546
1.52k
    if (!hMMFeature)
6547
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6548
6549
    // In V1.1 only _UI32_MAX records number is allowed
6550
1.52k
    if (MMCheckVersionForFID(hMiraMonLayer,
6551
1.52k
                             hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP->nRecords +
6552
1.52k
                                 hMMFeature->nNumMRecords))
6553
0
    {
6554
0
        CPLError(CE_Failure, CPLE_NotSupported,
6555
0
                 "Error in MMCheckVersionForFID() (6)");
6556
0
        return MM_STOP_WRITING_FEATURES;
6557
0
    }
6558
6559
1.52k
    pBD_XP = hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP;
6560
6561
    // Test length
6562
    // Private fields
6563
    // ID_GRAFIC
6564
1.52k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField,
6565
1.52k
                                        &nElemCount, TRUE))
6566
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6567
1.52k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
6568
1.52k
                                      &hMiraMonLayer->MMPoint.MMAdmDB, 0,
6569
1.52k
                                      hMiraMonLayer->szStringToOperate))
6570
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6571
6572
    // GDAL fields
6573
1.52k
    if (hMMFeature->nNumMRecords && hMMFeature->pRecords[0].nNumField)
6574
1.52k
    {
6575
1.52k
        if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6576
1.52k
                                         &hMiraMonLayer->MMPoint.MMAdmDB,
6577
1.52k
                                         nNumPrivateMMField, 0, 0))
6578
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6579
1.52k
    }
6580
6581
    // Now length is sure, write
6582
1.52k
    memset(hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse, 0,
6583
1.52k
           pBD_XP->BytesPerRecord);
6584
1.52k
    MMWriteValueToRecordDBXP(hMiraMonLayer,
6585
1.52k
                             hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse,
6586
1.52k
                             pBD_XP->pField, &nElemCount, TRUE);
6587
6588
    // Adding record to the MiraMon table (extended DBF)
6589
    // Flush settings
6590
1.52k
    pFlushRecList = &hMiraMonLayer->MMPoint.MMAdmDB.FlushRecList;
6591
1.52k
    pFlushRecList->pBlockWhereToSaveOrRead =
6592
1.52k
        (void *)hMiraMonLayer->MMPoint.MMAdmDB.pRecList;
6593
6594
1.52k
    pFlushRecList->pBlockToBeSaved =
6595
1.52k
        (void *)hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse;
6596
1.52k
    pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
6597
6598
1.52k
    if (MMAddFeatureRecordToMMDB(
6599
1.52k
            hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMPoint.MMAdmDB,
6600
1.52k
            hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse, pFlushRecList,
6601
1.52k
            &hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP->nRecords,
6602
1.52k
            nNumPrivateMMField))
6603
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6604
1.52k
    return MM_CONTINUE_WRITING_FEATURES;
6605
1.52k
}
6606
6607
// Adds a stringline record to a MiraMon table associated with a vector layer.
6608
int MMAddArcRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6609
                         struct MiraMonFeature *hMMFeature,
6610
                         MM_INTERNAL_FID nElemCount, struct MM_AH *pArcHeader)
6611
2.58k
{
6612
2.58k
    struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6613
2.58k
    struct MiraMonArcLayer *pMMArcLayer;
6614
2.58k
    MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_ARC_DB_FIELDS;
6615
2.58k
    struct MM_FLUSH_INFO *pFlushRecList;
6616
6617
2.58k
    if (!hMiraMonLayer)
6618
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6619
6620
2.58k
    if (hMiraMonLayer->bIsPolygon)
6621
906
        pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
6622
1.68k
    else
6623
1.68k
        pMMArcLayer = &hMiraMonLayer->MMArc;
6624
6625
    // In V1.1 only _UI32_MAX records number is allowed
6626
2.58k
    if (hMiraMonLayer->bIsPolygon)
6627
906
    {
6628
906
        if (MMCheckVersionForFID(hMiraMonLayer,
6629
906
                                 pMMArcLayer->MMAdmDB.pMMBDXP->nRecords + 1))
6630
0
        {
6631
0
            CPLError(CE_Failure, CPLE_NotSupported,
6632
0
                     "Error in MMCheckVersionForFID() (7)");
6633
0
            return MM_STOP_WRITING_FEATURES;
6634
0
        }
6635
906
    }
6636
1.68k
    else
6637
1.68k
    {
6638
1.68k
        if (MMCheckVersionForFID(hMiraMonLayer,
6639
1.68k
                                 pMMArcLayer->MMAdmDB.pMMBDXP->nRecords +
6640
1.68k
                                     hMMFeature->nNumMRecords))
6641
0
        {
6642
0
            CPLError(CE_Failure, CPLE_NotSupported,
6643
0
                     "Error in MMCheckVersionForFID() (8)");
6644
0
            return MM_STOP_WRITING_FEATURES;
6645
0
        }
6646
1.68k
    }
6647
6648
2.58k
    pBD_XP = pMMArcLayer->MMAdmDB.pMMBDXP;
6649
6650
    // Test length
6651
    // Private fields
6652
    // ID_GRAFIC
6653
2.58k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField,
6654
2.58k
                                        &nElemCount, TRUE))
6655
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6656
2.58k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 0,
6657
2.58k
                                      hMiraMonLayer->szStringToOperate))
6658
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6659
6660
    // N_VERTEXS
6661
2.58k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 1,
6662
2.58k
                                        &pArcHeader->nElemCount, TRUE))
6663
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6664
2.58k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 1,
6665
2.58k
                                      hMiraMonLayer->szStringToOperate))
6666
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6667
6668
    // LENGTH
6669
2.58k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 2,
6670
2.58k
                                        &pArcHeader->dfLength, FALSE))
6671
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6672
2.58k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 2,
6673
2.58k
                                      hMiraMonLayer->szStringToOperate))
6674
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6675
6676
    // NODE_INI
6677
2.58k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 3,
6678
2.58k
                                        &pArcHeader->nFirstIdNode, TRUE))
6679
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6680
2.58k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 3,
6681
2.58k
                                      hMiraMonLayer->szStringToOperate))
6682
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6683
6684
    // NODE_FI
6685
2.58k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 4,
6686
2.58k
                                        &pArcHeader->nLastIdNode, TRUE))
6687
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6688
2.58k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 4,
6689
2.58k
                                      hMiraMonLayer->szStringToOperate))
6690
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6691
6692
    // GDAL fields
6693
2.58k
    if (!hMiraMonLayer->bIsPolygon)
6694
1.68k
    {
6695
1.68k
        if (hMMFeature->nNumMRecords && hMMFeature->pRecords[0].nNumField)
6696
1.68k
        {
6697
1.68k
            if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6698
1.68k
                                             &pMMArcLayer->MMAdmDB,
6699
1.68k
                                             nNumPrivateMMField, 0, 0))
6700
0
                return MM_FATAL_ERROR_WRITING_FEATURES;
6701
1.68k
        }
6702
1.68k
    }
6703
6704
    // Now length is sure, write
6705
2.58k
    memset(pMMArcLayer->MMAdmDB.szRecordOnCourse, 0, pBD_XP->BytesPerRecord);
6706
2.58k
    MMWriteValueToRecordDBXP(hMiraMonLayer,
6707
2.58k
                             pMMArcLayer->MMAdmDB.szRecordOnCourse,
6708
2.58k
                             pBD_XP->pField, &nElemCount, TRUE);
6709
6710
2.58k
    MMWriteValueToRecordDBXP(hMiraMonLayer,
6711
2.58k
                             pMMArcLayer->MMAdmDB.szRecordOnCourse,
6712
2.58k
                             pBD_XP->pField + 1, &pArcHeader->nElemCount, TRUE);
6713
6714
2.58k
    MMWriteValueToRecordDBXP(hMiraMonLayer,
6715
2.58k
                             pMMArcLayer->MMAdmDB.szRecordOnCourse,
6716
2.58k
                             pBD_XP->pField + 2, &pArcHeader->dfLength, FALSE);
6717
6718
2.58k
    MMWriteValueToRecordDBXP(
6719
2.58k
        hMiraMonLayer, pMMArcLayer->MMAdmDB.szRecordOnCourse,
6720
2.58k
        pBD_XP->pField + 3, &pArcHeader->nFirstIdNode, TRUE);
6721
6722
2.58k
    MMWriteValueToRecordDBXP(
6723
2.58k
        hMiraMonLayer, pMMArcLayer->MMAdmDB.szRecordOnCourse,
6724
2.58k
        pBD_XP->pField + 4, &pArcHeader->nLastIdNode, TRUE);
6725
6726
    // Adding record to the MiraMon table (extended DBF)
6727
    // Flush settings
6728
2.58k
    pFlushRecList = &pMMArcLayer->MMAdmDB.FlushRecList;
6729
2.58k
    pFlushRecList->pBlockWhereToSaveOrRead =
6730
2.58k
        (void *)pMMArcLayer->MMAdmDB.pRecList;
6731
6732
2.58k
    pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
6733
2.58k
    pFlushRecList->pBlockToBeSaved =
6734
2.58k
        (void *)pMMArcLayer->MMAdmDB.szRecordOnCourse;
6735
6736
2.58k
    if (hMiraMonLayer->bIsPolygon)
6737
906
    {
6738
906
        if (MMAppendBlockToBuffer(pFlushRecList))
6739
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6740
906
        pMMArcLayer->MMAdmDB.pMMBDXP->nRecords++;
6741
906
        return MM_CONTINUE_WRITING_FEATURES;
6742
906
    }
6743
6744
1.68k
    pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
6745
1.68k
    if (MMAddFeatureRecordToMMDB(
6746
1.68k
            hMiraMonLayer, hMMFeature, &pMMArcLayer->MMAdmDB,
6747
1.68k
            pMMArcLayer->MMAdmDB.szRecordOnCourse, pFlushRecList,
6748
1.68k
            &pMMArcLayer->MMAdmDB.pMMBDXP->nRecords, nNumPrivateMMField))
6749
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6750
1.68k
    return MM_CONTINUE_WRITING_FEATURES;
6751
1.68k
}
6752
6753
// Adds a node record to a MiraMon table associated with a vector layer.
6754
int MMAddNodeRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6755
                          MM_INTERNAL_FID nElemCount, struct MM_NH *pNodeHeader)
6756
4.27k
{
6757
4.27k
    struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6758
4.27k
    struct MiraMonNodeLayer *pMMNodeLayer;
6759
4.27k
    double nDoubleValue;
6760
6761
4.27k
    if (!hMiraMonLayer)
6762
0
        return 1;
6763
6764
4.27k
    if (hMiraMonLayer->bIsPolygon)
6765
906
        pMMNodeLayer = &hMiraMonLayer->MMPolygon.MMArc.MMNode;
6766
3.36k
    else
6767
3.36k
        pMMNodeLayer = &hMiraMonLayer->MMArc.MMNode;
6768
6769
4.27k
    if (!pMMNodeLayer)
6770
0
    {
6771
0
        CPLError(CE_Failure, CPLE_NotSupported, "Error in pMMNodeLayer() (1)");
6772
0
        return MM_STOP_WRITING_FEATURES;
6773
0
    }
6774
6775
    // In V1.1 only _UI32_MAX records number is allowed
6776
4.27k
    if (MMCheckVersionForFID(hMiraMonLayer,
6777
4.27k
                             pMMNodeLayer->MMAdmDB.pMMBDXP->nRecords + 1))
6778
0
    {
6779
0
        CPLError(CE_Failure, CPLE_NotSupported,
6780
0
                 "Error in MMCheckVersionForFID() (9)");
6781
0
        return MM_STOP_WRITING_FEATURES;
6782
0
    }
6783
6784
    // Test length
6785
    // Private fields
6786
    // ID_GRAFIC
6787
4.27k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer,
6788
4.27k
                                        pMMNodeLayer->MMAdmDB.pMMBDXP->pField,
6789
4.27k
                                        &nElemCount, TRUE))
6790
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6791
4.27k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 0,
6792
4.27k
                                      hMiraMonLayer->szStringToOperate))
6793
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6794
6795
    // ARCS_A_NOD
6796
4.27k
    nDoubleValue = pNodeHeader->nArcsCount;
6797
4.27k
    if (MMWriteValueToszStringToOperate(
6798
4.27k
            hMiraMonLayer, pMMNodeLayer->MMAdmDB.pMMBDXP->pField + 1,
6799
4.27k
            &nDoubleValue, FALSE))
6800
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6801
4.27k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 1,
6802
4.27k
                                      hMiraMonLayer->szStringToOperate))
6803
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6804
6805
    // TIPUS_NODE
6806
4.27k
    nDoubleValue = pNodeHeader->cNodeType;
6807
4.27k
    if (MMWriteValueToszStringToOperate(
6808
4.27k
            hMiraMonLayer, pMMNodeLayer->MMAdmDB.pMMBDXP->pField + 2,
6809
4.27k
            &nDoubleValue, FALSE))
6810
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6811
4.27k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 2,
6812
4.27k
                                      hMiraMonLayer->szStringToOperate))
6813
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6814
6815
    // Adding record to the MiraMon table (extended DBF)
6816
    // Flush settings
6817
4.27k
    pMMNodeLayer->MMAdmDB.FlushRecList.pBlockWhereToSaveOrRead =
6818
4.27k
        (void *)pMMNodeLayer->MMAdmDB.pRecList;
6819
6820
4.27k
    pBD_XP = pMMNodeLayer->MMAdmDB.pMMBDXP;
6821
6822
4.27k
    pMMNodeLayer->MMAdmDB.FlushRecList.SizeOfBlockToBeSaved =
6823
4.27k
        pBD_XP->BytesPerRecord;
6824
4.27k
    pMMNodeLayer->MMAdmDB.FlushRecList.pBlockToBeSaved =
6825
4.27k
        (void *)pMMNodeLayer->MMAdmDB.szRecordOnCourse;
6826
6827
4.27k
    memset(pMMNodeLayer->MMAdmDB.szRecordOnCourse, 0, pBD_XP->BytesPerRecord);
6828
4.27k
    MMWriteValueToRecordDBXP(hMiraMonLayer,
6829
4.27k
                             pMMNodeLayer->MMAdmDB.szRecordOnCourse,
6830
4.27k
                             pBD_XP->pField, &nElemCount, TRUE);
6831
6832
4.27k
    nDoubleValue = pNodeHeader->nArcsCount;
6833
4.27k
    MMWriteValueToRecordDBXP(hMiraMonLayer,
6834
4.27k
                             pMMNodeLayer->MMAdmDB.szRecordOnCourse,
6835
4.27k
                             pBD_XP->pField + 1, &nDoubleValue, FALSE);
6836
6837
4.27k
    nDoubleValue = pNodeHeader->cNodeType;
6838
4.27k
    MMWriteValueToRecordDBXP(hMiraMonLayer,
6839
4.27k
                             pMMNodeLayer->MMAdmDB.szRecordOnCourse,
6840
4.27k
                             pBD_XP->pField + 2, &nDoubleValue, FALSE);
6841
6842
4.27k
    if (MMAppendBlockToBuffer(&pMMNodeLayer->MMAdmDB.FlushRecList))
6843
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6844
4.27k
    pMMNodeLayer->MMAdmDB.pMMBDXP->nRecords++;
6845
4.27k
    return MM_CONTINUE_WRITING_FEATURES;
6846
4.27k
}
6847
6848
// Adds a polygon or multipolygon record to a MiraMon table
6849
// associated with a vector layer.
6850
int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6851
                             struct MiraMonFeature *hMMFeature,
6852
                             MM_INTERNAL_FID nElemCount,
6853
                             MM_N_VERTICES_TYPE nVerticesCount,
6854
                             struct MM_PH *pPolHeader)
6855
1.08k
{
6856
1.08k
    struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6857
1.08k
    MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_POLYGON_DB_FIELDS;
6858
1.08k
    struct MM_FLUSH_INFO *pFlushRecList;
6859
6860
1.08k
    if (!hMiraMonLayer)
6861
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6862
6863
    // In V1.1 only _UI32_MAX records number is allowed
6864
1.08k
    if (MMCheckVersionForFID(
6865
1.08k
            hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords +
6866
1.08k
                               (hMMFeature ? hMMFeature->nNumMRecords : 0)))
6867
0
        return MM_STOP_WRITING_FEATURES;
6868
6869
1.08k
    pBD_XP = hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP;
6870
6871
    // Test length
6872
    // Private fields
6873
    // ID_GRAFIC
6874
1.08k
    if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField,
6875
1.08k
                                        &nElemCount, TRUE))
6876
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6877
1.08k
    if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
6878
1.08k
                                      &hMiraMonLayer->MMPolygon.MMAdmDB, 0,
6879
1.08k
                                      hMiraMonLayer->szStringToOperate))
6880
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6881
6882
    // The other fields are valid if pPolHeader exists (it is not
6883
    // the universal polygon)
6884
1.08k
    if (pPolHeader)
6885
928
    {
6886
        // N_VERTEXS
6887
928
        if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 1,
6888
928
                                            &nVerticesCount, TRUE))
6889
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6890
928
        if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
6891
928
                                          &hMiraMonLayer->MMPolygon.MMAdmDB, 1,
6892
928
                                          hMiraMonLayer->szStringToOperate))
6893
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6894
6895
        // PERIMETER
6896
928
        if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 2,
6897
928
                                            &pPolHeader->dfPerimeter, FALSE))
6898
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6899
928
        if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
6900
928
                                          &hMiraMonLayer->MMPolygon.MMAdmDB, 2,
6901
928
                                          hMiraMonLayer->szStringToOperate))
6902
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6903
6904
        // AREA
6905
928
        if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 3,
6906
928
                                            &pPolHeader->dfArea, FALSE))
6907
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6908
928
        if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
6909
928
                                          &hMiraMonLayer->MMPolygon.MMAdmDB, 3,
6910
928
                                          hMiraMonLayer->szStringToOperate))
6911
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6912
6913
        // N_ARCS
6914
928
        if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 4,
6915
928
                                            &pPolHeader->nArcsCount, TRUE))
6916
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6917
928
        if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
6918
928
                                          &hMiraMonLayer->MMPolygon.MMAdmDB, 4,
6919
928
                                          hMiraMonLayer->szStringToOperate))
6920
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6921
6922
        // N_POLIG
6923
928
        if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 5,
6924
928
                                            &pPolHeader->nRingsCount, TRUE))
6925
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6926
928
        if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
6927
928
                                          &hMiraMonLayer->MMPolygon.MMAdmDB, 5,
6928
928
                                          hMiraMonLayer->szStringToOperate))
6929
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6930
928
    }
6931
6932
    // GDAL fields
6933
1.08k
    if (hMMFeature && hMMFeature->nNumMRecords &&
6934
928
        hMMFeature->pRecords[0].nNumField)
6935
928
    {
6936
928
        if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6937
928
                                         &hMiraMonLayer->MMPolygon.MMAdmDB,
6938
928
                                         nNumPrivateMMField, 0, 0))
6939
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6940
928
    }
6941
6942
    // Adding record to the MiraMon table (extended DBF)
6943
    // Flush settings
6944
1.08k
    pFlushRecList = &hMiraMonLayer->MMPolygon.MMAdmDB.FlushRecList;
6945
1.08k
    pFlushRecList->pBlockWhereToSaveOrRead =
6946
1.08k
        (void *)hMiraMonLayer->MMPolygon.MMAdmDB.pRecList;
6947
6948
1.08k
    pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
6949
1.08k
    pFlushRecList->pBlockToBeSaved =
6950
1.08k
        (void *)hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse;
6951
6952
    // Now length is sure, write
6953
1.08k
    memset(hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, ' ',
6954
1.08k
           pBD_XP->BytesPerRecord);
6955
1.08k
    if (MMWriteValueToRecordDBXP(
6956
1.08k
            hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
6957
1.08k
            pBD_XP->pField, &nElemCount, TRUE))
6958
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6959
6960
1.08k
    if (!hMMFeature)
6961
159
    {
6962
159
        if (MMAppendBlockToBuffer(pFlushRecList))
6963
0
            return MM_FATAL_ERROR_WRITING_FEATURES;
6964
159
        hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords++;
6965
159
        return MM_CONTINUE_WRITING_FEATURES;
6966
159
    }
6967
6968
928
    if (pPolHeader)
6969
928
    {
6970
928
        MMWriteValueToRecordDBXP(
6971
928
            hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
6972
928
            pBD_XP->pField + 1, &nVerticesCount, TRUE);
6973
6974
928
        MMWriteValueToRecordDBXP(
6975
928
            hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
6976
928
            pBD_XP->pField + 2, &pPolHeader->dfPerimeter, FALSE);
6977
6978
928
        MMWriteValueToRecordDBXP(
6979
928
            hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
6980
928
            pBD_XP->pField + 3, &pPolHeader->dfArea, FALSE);
6981
6982
928
        MMWriteValueToRecordDBXP(
6983
928
            hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
6984
928
            pBD_XP->pField + 4, &pPolHeader->nArcsCount, TRUE);
6985
6986
928
        MMWriteValueToRecordDBXP(
6987
928
            hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
6988
928
            pBD_XP->pField + 5, &pPolHeader->nRingsCount, TRUE);
6989
928
    }
6990
6991
928
    pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
6992
928
    if (MMAddFeatureRecordToMMDB(
6993
928
            hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMPolygon.MMAdmDB,
6994
928
            hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, pFlushRecList,
6995
928
            &hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords,
6996
928
            nNumPrivateMMField))
6997
0
        return MM_FATAL_ERROR_WRITING_FEATURES;
6998
928
    return MM_CONTINUE_WRITING_FEATURES;
6999
928
}
7000
7001
// Close the MiraMon database associated with a vector layer.
7002
static int MMCloseMMBD_XPFile(struct MiraMonVectLayerInfo *hMiraMonLayer,
7003
                              struct MMAdmDatabase *MMAdmDB)
7004
17.1k
{
7005
17.1k
    int ret_code = 1;
7006
17.1k
    if (!hMiraMonLayer)
7007
0
        return 1;
7008
7009
17.1k
    if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
7010
3.40k
    {
7011
3.40k
        if (!MMAdmDB->pMMBDXP ||
7012
2.86k
            (MMAdmDB->pMMBDXP && !MMAdmDB->pMMBDXP->pfDataBase))
7013
839
        {
7014
            // In case of 0 elements created we have to
7015
            // create an empty DBF
7016
839
            if (hMiraMonLayer->bIsPolygon)
7017
121
            {
7018
121
                if (hMiraMonLayer->TopHeader.nElemCount <= 1)
7019
121
                {
7020
121
                    if (MMCreateMMDB(hMiraMonLayer, nullptr))
7021
108
                    {
7022
108
                        CPLError(CE_Failure, CPLE_OutOfMemory,
7023
108
                                 "Memory error in MiraMon "
7024
108
                                 "driver (MMCreateMMDB())");
7025
108
                        goto end_label;
7026
108
                    }
7027
121
                }
7028
121
            }
7029
718
            else if (hMiraMonLayer->bIsPoint || hMiraMonLayer->bIsArc)
7030
195
            {
7031
195
                if (hMiraMonLayer->TopHeader.nElemCount == 0)
7032
195
                {
7033
195
                    if (MMCreateMMDB(hMiraMonLayer, nullptr))
7034
195
                    {
7035
195
                        CPLError(CE_Failure, CPLE_OutOfMemory,
7036
195
                                 "Memory error in MiraMon "
7037
195
                                 "driver (MMCreateMMDB())");
7038
195
                        goto end_label;
7039
195
                    }
7040
195
                }
7041
195
            }
7042
839
        }
7043
7044
3.10k
        if (MM_WriteNRecordsMMBD_XPFile(MMAdmDB->pMMBDXP))
7045
0
            goto end_label;
7046
7047
        // Flushing all to be flushed
7048
3.10k
        MMAdmDB->FlushRecList.SizeOfBlockToBeSaved = 0;
7049
3.10k
        if (MMAppendBlockToBuffer(&MMAdmDB->FlushRecList))
7050
0
            goto end_label;
7051
3.10k
    }
7052
7053
16.8k
    ret_code = 0;
7054
17.1k
end_label:
7055
    // Closing database files
7056
17.1k
    if (MMAdmDB && MMAdmDB->pMMBDXP && MMAdmDB->pMMBDXP->pfDataBase)
7057
2.57k
        fclose_and_nullify(&MMAdmDB->pMMBDXP->pfDataBase);
7058
7059
17.1k
    return ret_code;
7060
16.8k
}
7061
7062
int MMCloseMMBD_XP(struct MiraMonVectLayerInfo *hMiraMonLayer)
7063
7.73k
{
7064
7.73k
    int ret_code = 0;
7065
7.73k
    if (!hMiraMonLayer)
7066
0
        return 1;
7067
7068
7.73k
    if (hMiraMonLayer->pMMBDXP && hMiraMonLayer->pMMBDXP->pfDataBase)
7069
836
    {
7070
836
        fclose_and_nullify(&hMiraMonLayer->pMMBDXP->pfDataBase);
7071
836
    }
7072
7073
7.73k
    if (hMiraMonLayer->bIsPoint)
7074
679
        ret_code =
7075
679
            MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB);
7076
7.05k
    else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
7077
513
    {
7078
513
        if (MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB))
7079
55
            ret_code = 1;
7080
513
        if (MMCloseMMBD_XPFile(hMiraMonLayer,
7081
513
                               &hMiraMonLayer->MMArc.MMNode.MMAdmDB))
7082
55
            ret_code = 1;
7083
513
    }
7084
6.54k
    else if (hMiraMonLayer->bIsPolygon)
7085
4.46k
    {
7086
4.46k
        if (MMCloseMMBD_XPFile(hMiraMonLayer,
7087
4.46k
                               &hMiraMonLayer->MMPolygon.MMAdmDB))
7088
36
            ret_code = 1;
7089
4.46k
        if (MMCloseMMBD_XPFile(hMiraMonLayer,
7090
4.46k
                               &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB))
7091
36
            ret_code = 1;
7092
4.46k
        if (MMCloseMMBD_XPFile(hMiraMonLayer,
7093
4.46k
                               &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB))
7094
36
            ret_code = 1;
7095
4.46k
    }
7096
2.07k
    else if (hMiraMonLayer->bIsDBF)
7097
2.07k
        ret_code =
7098
2.07k
            MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting);
7099
7100
7.73k
    return ret_code;
7101
7.73k
}
7102
7103
// Destroys the memory used to create a MiraMon table associated
7104
// with a vector layer.
7105
static void MMDestroyMMDBFile(struct MiraMonVectLayerInfo *hMiraMonLayer,
7106
                              struct MMAdmDatabase *pMMAdmDB)
7107
108k
{
7108
108k
    if (!hMiraMonLayer)
7109
0
        return;
7110
7111
108k
    if (pMMAdmDB && pMMAdmDB->szRecordOnCourse)
7112
1.82k
    {
7113
1.82k
        VSIFree(pMMAdmDB->szRecordOnCourse);
7114
1.82k
        pMMAdmDB->szRecordOnCourse = nullptr;
7115
1.82k
    }
7116
108k
    if (hMiraMonLayer->szStringToOperate)
7117
574
    {
7118
574
        VSIFree(hMiraMonLayer->szStringToOperate);
7119
574
        hMiraMonLayer->szStringToOperate = nullptr;
7120
574
        hMiraMonLayer->nNumStringToOperate = 0;
7121
574
    }
7122
7123
108k
    if (pMMAdmDB && pMMAdmDB->pMMBDXP)
7124
98.9k
    {
7125
98.9k
        MM_ReleaseDBFHeader(&pMMAdmDB->pMMBDXP);
7126
98.9k
        hMiraMonLayer->pMMBDXP = nullptr;
7127
98.9k
    }
7128
108k
    if (pMMAdmDB && pMMAdmDB->pRecList)
7129
1.82k
    {
7130
1.82k
        VSIFree(pMMAdmDB->pRecList);
7131
1.82k
        pMMAdmDB->pRecList = nullptr;
7132
1.82k
    }
7133
108k
}
7134
7135
void MMDestroyMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer)
7136
123k
{
7137
123k
    if (!hMiraMonLayer)
7138
0
        return;
7139
7140
123k
    if (hMiraMonLayer->bIsPoint)
7141
764
    {
7142
764
        MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB);
7143
764
        return;
7144
764
    }
7145
122k
    if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
7146
568
    {
7147
568
        MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB);
7148
568
        MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMNode.MMAdmDB);
7149
568
        return;
7150
568
    }
7151
122k
    if (hMiraMonLayer->bIsPolygon)
7152
4.50k
    {
7153
4.50k
        MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMAdmDB);
7154
4.50k
        MMDestroyMMDBFile(hMiraMonLayer,
7155
4.50k
                          &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB);
7156
4.50k
        MMDestroyMMDBFile(hMiraMonLayer,
7157
4.50k
                          &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB);
7158
4.50k
    }
7159
122k
    if (hMiraMonLayer->bIsDBF)
7160
93.3k
        MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting);
7161
122k
}
7162
7163
// COMING FROM mm_gdal_functions.c/h but only used here
7164
void MM_FillFieldDescriptorByLanguage(void)
7165
12.0k
{
7166
12.0k
    CPLStrlcpy(szInternalGraphicIdentifierEng, "Internal Graphic identifier",
7167
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7168
12.0k
    CPLStrlcpy(szInternalGraphicIdentifierCat, "Identificador Grafic intern",
7169
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7170
12.0k
    *(unsigned char *)&szInternalGraphicIdentifierCat[16] = MM_a_WITH_GRAVE;
7171
12.0k
    CPLStrlcpy(szInternalGraphicIdentifierSpa, "Identificador Grafico interno",
7172
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7173
12.0k
    *(unsigned char *)&szInternalGraphicIdentifierSpa[16] = MM_a_WITH_ACUTE;
7174
7175
12.0k
    CPLStrlcpy(szNumberOfVerticesEng, "Number of vertices",
7176
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7177
12.0k
    CPLStrlcpy(szNumberOfVerticesCat, "Nombre de vertexs",
7178
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7179
12.0k
    CPLStrlcpy(szNumberOfVerticesSpa, "Numero de vertices",
7180
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7181
12.0k
    *(unsigned char *)&szNumberOfVerticesCat[11] = MM_e_WITH_GRAVE;
7182
12.0k
    *(unsigned char *)&szNumberOfVerticesSpa[1] = MM_u_WITH_ACUTE;
7183
12.0k
    *(unsigned char *)&szNumberOfVerticesSpa[11] = MM_e_WITH_ACUTE;
7184
7185
12.0k
    CPLStrlcpy(szLengthOfAarcEng, "Length of arc", MM_MAX_IDENTIFIER_SIZE);
7186
12.0k
    CPLStrlcpy(szLengthOfAarcCat, "Longitud de l'arc", MM_MAX_IDENTIFIER_SIZE);
7187
12.0k
    CPLStrlcpy(szLengthOfAarcSpa, "Longitud del arco", MM_MAX_IDENTIFIER_SIZE);
7188
7189
12.0k
    CPLStrlcpy(szInitialNodeEng, "Initial node", MM_MAX_IDENTIFIER_SIZE);
7190
12.0k
    CPLStrlcpy(szInitialNodeCat, "Node inicial", MM_MAX_IDENTIFIER_SIZE);
7191
12.0k
    CPLStrlcpy(szInitialNodeSpa, "Nodo inicial", MM_MAX_IDENTIFIER_SIZE);
7192
7193
12.0k
    CPLStrlcpy(szFinalNodeEng, "Final node", MM_MAX_IDENTIFIER_SIZE);
7194
12.0k
    CPLStrlcpy(szFinalNodeCat, "Node final", MM_MAX_IDENTIFIER_SIZE);
7195
12.0k
    CPLStrlcpy(szFinalNodeSpa, "Nodo final", MM_MAX_IDENTIFIER_SIZE);
7196
7197
12.0k
    CPLStrlcpy(szNumberOfArcsToNodeEng, "Number of arcs to node",
7198
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7199
12.0k
    CPLStrlcpy(szNumberOfArcsToNodeCat, "Nombre d'arcs al node",
7200
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7201
12.0k
    CPLStrlcpy(szNumberOfArcsToNodeSpa, "Numero de arcos al nodo",
7202
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7203
12.0k
    *(unsigned char *)&szNumberOfArcsToNodeSpa[1] = MM_u_WITH_ACUTE;
7204
7205
12.0k
    CPLStrlcpy(szNodeTypeEng, "Node type", MM_MAX_IDENTIFIER_SIZE);
7206
12.0k
    CPLStrlcpy(szNodeTypeCat, "Tipus de node", MM_MAX_IDENTIFIER_SIZE);
7207
12.0k
    CPLStrlcpy(szNodeTypeSpa, "Tipo de nodo", MM_MAX_IDENTIFIER_SIZE);
7208
7209
12.0k
    CPLStrlcpy(szPerimeterOfThePolygonEng, "Perimeter of the polygon",
7210
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7211
12.0k
    CPLStrlcpy(szPerimeterOfThePolygonCat, "Perimetre del poligon",
7212
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7213
12.0k
    CPLStrlcpy(szPerimeterOfThePolygonSpa, "Perimetro del poligono",
7214
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7215
7216
12.0k
    *(unsigned char *)&szPerimeterOfThePolygonCat[3] = MM_i_WITH_ACUTE;
7217
12.0k
    *(unsigned char *)&szPerimeterOfThePolygonSpa[3] = MM_i_WITH_ACUTE;
7218
12.0k
    *(unsigned char *)&szPerimeterOfThePolygonCat[17] = MM_i_WITH_ACUTE;
7219
12.0k
    *(unsigned char *)&szPerimeterOfThePolygonSpa[17] = MM_i_WITH_ACUTE;
7220
7221
12.0k
    CPLStrlcpy(szAreaOfThePolygonEng, "Area of the polygon",
7222
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7223
12.0k
    CPLStrlcpy(szAreaOfThePolygonCat, "Area del poligon",
7224
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7225
12.0k
    CPLStrlcpy(szAreaOfThePolygonSpa, "Area del poligono",
7226
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7227
7228
12.0k
    *(unsigned char *)&szAreaOfThePolygonCat[0] = MM_A_WITH_GRAVE;
7229
12.0k
    *(unsigned char *)&szAreaOfThePolygonSpa[0] = MM_A_WITH_ACUTE;
7230
12.0k
    *(unsigned char *)&szAreaOfThePolygonCat[12] = MM_i_WITH_ACUTE;
7231
12.0k
    *(unsigned char *)&szAreaOfThePolygonSpa[12] = MM_i_WITH_ACUTE;
7232
7233
12.0k
    CPLStrlcpy(szNumberOfArcsEng, "Number of arcs", MM_MAX_IDENTIFIER_SIZE);
7234
12.0k
    CPLStrlcpy(szNumberOfArcsCat, "Nombre d'arcs", MM_MAX_IDENTIFIER_SIZE);
7235
12.0k
    CPLStrlcpy(szNumberOfArcsSpa, "Numero de arcos", MM_MAX_IDENTIFIER_SIZE);
7236
7237
12.0k
    *(unsigned char *)&szNumberOfArcsSpa[1] = MM_u_WITH_ACUTE;
7238
7239
12.0k
    CPLStrlcpy(szNumberOfElementaryPolygonsEng, "Number of elementary polygons",
7240
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7241
12.0k
    CPLStrlcpy(szNumberOfElementaryPolygonsCat, "Nombre de poligons elementals",
7242
12.0k
               MM_MAX_IDENTIFIER_SIZE);
7243
12.0k
    CPLStrlcpy(szNumberOfElementaryPolygonsSpa,
7244
12.0k
               "Numero de poligonos elementales", MM_MAX_IDENTIFIER_SIZE);
7245
7246
12.0k
    *(unsigned char *)&szNumberOfElementaryPolygonsSpa[1] = MM_u_WITH_ACUTE;
7247
12.0k
    *(unsigned char *)&szNumberOfElementaryPolygonsCat[13] = MM_i_WITH_ACUTE;
7248
12.0k
    *(unsigned char *)&szNumberOfElementaryPolygonsSpa[13] = MM_i_WITH_ACUTE;
7249
12.0k
}
7250
7251
static MM_BOOLEAN MM_FillFieldDB_XP(
7252
    struct MM_FIELD *camp, const char *FieldName,
7253
    const char *FieldDescriptionEng, const char *FieldDescriptionCat,
7254
    const char *FieldDescriptionSpa, char FieldType,
7255
    MM_BYTES_PER_FIELD_TYPE_DBF BytesPerField, MM_BYTE DecimalsIfFloat)
7256
29.4k
{
7257
29.4k
    char nom_temp[MM_MAX_LON_FIELD_NAME_DBF];
7258
29.4k
    int retorn_valida_nom_camp;
7259
7260
29.4k
    if (FieldName)
7261
29.4k
    {
7262
29.4k
        retorn_valida_nom_camp = MM_ISExtendedNameBD_XP(FieldName);
7263
29.4k
        if (retorn_valida_nom_camp == MM_DBF_NAME_NO_VALID)
7264
0
            return FALSE;
7265
29.4k
        CPLStrlcpy(camp->FieldName, FieldName, MM_MAX_LON_FIELD_NAME_DBF);
7266
7267
29.4k
        if (retorn_valida_nom_camp == MM_VALID_EXTENDED_DBF_NAME)
7268
0
        {
7269
0
            MM_CalculateBytesExtendedFieldName(camp);
7270
0
            CPLStrlcpy(nom_temp, FieldName, MM_MAX_LON_FIELD_NAME_DBF);
7271
0
            MM_ReturnValidClassicDBFFieldName(nom_temp);
7272
0
            nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF] = '\0';
7273
0
            CPLStrlcpy(camp->ClassicalDBFFieldName, nom_temp,
7274
0
                       MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
7275
0
        }
7276
29.4k
    }
7277
7278
29.4k
    if (FieldDescriptionEng)
7279
29.4k
        CPLStrlcpy(camp->FieldDescription[MM_DEF_LANGUAGE], FieldDescriptionEng,
7280
29.4k
                   sizeof(camp->FieldDescription[MM_DEF_LANGUAGE]));
7281
0
    else
7282
0
        strcpy(camp->FieldDescription[MM_DEF_LANGUAGE], "\0");
7283
7284
29.4k
    if (FieldDescriptionEng)
7285
29.4k
        CPLStrlcpy(camp->FieldDescription[MM_ENG_LANGUAGE], FieldDescriptionEng,
7286
29.4k
                   sizeof(camp->FieldDescription[MM_ENG_LANGUAGE]));
7287
0
    else
7288
0
        strcpy(camp->FieldDescription[MM_ENG_LANGUAGE], "\0");
7289
7290
29.4k
    if (FieldDescriptionCat)
7291
29.4k
        CPLStrlcpy(camp->FieldDescription[MM_CAT_LANGUAGE], FieldDescriptionCat,
7292
29.4k
                   sizeof(camp->FieldDescription[MM_CAT_LANGUAGE]));
7293
0
    else
7294
0
        strcpy(camp->FieldDescription[MM_CAT_LANGUAGE], "\0");
7295
7296
29.4k
    if (FieldDescriptionSpa)
7297
29.4k
        CPLStrlcpy(camp->FieldDescription[MM_SPA_LANGUAGE], FieldDescriptionSpa,
7298
29.4k
                   sizeof(camp->FieldDescription[MM_SPA_LANGUAGE]));
7299
0
    else
7300
0
        strcpy(camp->FieldDescription[MM_SPA_LANGUAGE], "\0");
7301
7302
29.4k
    camp->FieldType = FieldType;
7303
29.4k
    camp->DecimalsIfFloat = DecimalsIfFloat;
7304
29.4k
    camp->BytesPerField = BytesPerField;
7305
29.4k
    return TRUE;
7306
29.4k
}
7307
7308
size_t MM_DefineFirstPolygonFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp,
7309
                                        MM_BYTE n_perimeter_decimals,
7310
                                        MM_BYTE n_area_decimals_decimals)
7311
1.00k
{
7312
1.00k
    MM_EXT_DBF_N_FIELDS i_camp = 0;
7313
7314
1.00k
    MM_FillFieldDB_XP(
7315
1.00k
        bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
7316
1.00k
        szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
7317
1.00k
        szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
7318
1.00k
    bd_xp->IdGraficField = 0;
7319
1.00k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
7320
1.00k
    i_camp++;
7321
7322
1.00k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte,
7323
1.00k
                      szNumberOfVerticesEng, szNumberOfVerticesCat,
7324
1.00k
                      szNumberOfVerticesSpa, 'N', MM_MIN_WIDTH_N_VERTEXS, 0);
7325
1.00k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS;
7326
1.00k
    i_camp++;
7327
7328
1.00k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampPerimetreDefecte,
7329
1.00k
                      szPerimeterOfThePolygonEng, szPerimeterOfThePolygonCat,
7330
1.00k
                      szPerimeterOfThePolygonSpa, 'N', MM_MIN_WIDTH_LONG,
7331
1.00k
                      n_perimeter_decimals);
7332
1.00k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_PERIMETRE;
7333
1.00k
    i_camp++;
7334
7335
1.00k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampAreaDefecte,
7336
1.00k
                      szAreaOfThePolygonEng, szAreaOfThePolygonCat,
7337
1.00k
                      szAreaOfThePolygonSpa, 'N', MM_MIN_WIDTH_AREA,
7338
1.00k
                      n_area_decimals_decimals);
7339
1.00k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_AREA;
7340
1.00k
    i_camp++;
7341
7342
1.00k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNArcsDefecte,
7343
1.00k
                      szNumberOfArcsEng, szNumberOfArcsCat, szNumberOfArcsSpa,
7344
1.00k
                      'N', MM_MIN_WIDTH_N_ARCS, 0);
7345
1.00k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_ARCS;
7346
1.00k
    i_camp++;
7347
7348
1.00k
    MM_FillFieldDB_XP(
7349
1.00k
        bd_xp->pField + i_camp, szMMNomCampNPoligonsDefecte,
7350
1.00k
        szNumberOfElementaryPolygonsEng, szNumberOfElementaryPolygonsCat,
7351
1.00k
        szNumberOfElementaryPolygonsSpa, 'N', MM_MIN_WIDTH_N_POLIG, 0);
7352
1.00k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_POLIG;
7353
1.00k
    i_camp++;
7354
7355
1.00k
    return i_camp;
7356
1.00k
}
7357
7358
size_t MM_DefineFirstArcFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp,
7359
                                    MM_BYTE n_decimals)
7360
2.72k
{
7361
2.72k
    MM_EXT_DBF_N_FIELDS i_camp;
7362
7363
2.72k
    i_camp = 0;
7364
2.72k
    MM_FillFieldDB_XP(
7365
2.72k
        bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
7366
2.72k
        szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
7367
2.72k
        szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
7368
2.72k
    bd_xp->IdGraficField = 0;
7369
2.72k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
7370
2.72k
    i_camp++;
7371
7372
2.72k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte,
7373
2.72k
                      szNumberOfVerticesEng, szNumberOfVerticesCat,
7374
2.72k
                      szNumberOfVerticesSpa, 'N', MM_MIN_WIDTH_N_VERTEXS, 0);
7375
2.72k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS;
7376
2.72k
    i_camp++;
7377
7378
2.72k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampLongitudArcDefecte,
7379
2.72k
                      szLengthOfAarcEng, szLengthOfAarcCat, szLengthOfAarcSpa,
7380
2.72k
                      'N', MM_MIN_WIDTH_LONG, n_decimals);
7381
2.72k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_LONG_ARC;
7382
2.72k
    i_camp++;
7383
7384
2.72k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeIniDefecte,
7385
2.72k
                      szInitialNodeEng, szInitialNodeCat, szInitialNodeSpa, 'N',
7386
2.72k
                      MM_MIN_WIDTH_INITIAL_NODE, 0);
7387
2.72k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_INI;
7388
2.72k
    i_camp++;
7389
7390
2.72k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeFiDefecte,
7391
2.72k
                      szFinalNodeEng, szFinalNodeCat, szFinalNodeSpa, 'N',
7392
2.72k
                      MM_MIN_WIDTH_FINAL_NODE, 0);
7393
2.72k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_FI;
7394
2.72k
    i_camp++;
7395
7396
2.72k
    return i_camp;
7397
2.72k
}
7398
7399
size_t MM_DefineFirstNodeFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp)
7400
2.72k
{
7401
2.72k
    MM_EXT_DBF_N_FIELDS i_camp;
7402
7403
2.72k
    i_camp = 0;
7404
7405
2.72k
    MM_FillFieldDB_XP(
7406
2.72k
        bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
7407
2.72k
        szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
7408
2.72k
        szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
7409
2.72k
    bd_xp->IdGraficField = 0;
7410
2.72k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
7411
2.72k
    i_camp++;
7412
7413
2.72k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampArcsANodeDefecte,
7414
2.72k
                      szNumberOfArcsToNodeEng, szNumberOfArcsToNodeCat,
7415
2.72k
                      szNumberOfArcsToNodeSpa, 'N', MM_MIN_WIDTH_ARCS_TO_NODE,
7416
2.72k
                      0);
7417
2.72k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ARCS_A_NOD;
7418
2.72k
    i_camp++;
7419
7420
2.72k
    MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampTipusNodeDefecte,
7421
2.72k
                      szNodeTypeEng, szNodeTypeCat, szNodeTypeSpa, 'N', 1, 0);
7422
2.72k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_TIPUS_NODE;
7423
2.72k
    i_camp++;
7424
7425
2.72k
    return i_camp;
7426
2.72k
}
7427
7428
size_t MM_DefineFirstPointFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp)
7429
1.67k
{
7430
1.67k
    size_t i_camp = 0;
7431
7432
1.67k
    MM_FillFieldDB_XP(
7433
1.67k
        bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
7434
1.67k
        szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
7435
1.67k
        szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
7436
1.67k
    bd_xp->IdGraficField = 0;
7437
1.67k
    (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
7438
1.67k
    i_camp++;
7439
7440
1.67k
    return i_camp;
7441
1.67k
}
7442
7443
CPL_C_END  // Necessary for compiling in GDAL project