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