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