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->pZUnit)
2441 : {
2442 0 : free_function(hMiraMonLayer->pZUnit);
2443 0 : hMiraMonLayer->pZUnit = nullptr;
2444 : }
2445 :
2446 804 : if (hMiraMonLayer->pMultRecordIndex)
2447 : {
2448 102 : free_function(hMiraMonLayer->pMultRecordIndex);
2449 102 : hMiraMonLayer->pMultRecordIndex = nullptr;
2450 : }
2451 :
2452 804 : if (hMiraMonLayer->ReadFeature.pNCoordRing)
2453 : {
2454 84 : free(hMiraMonLayer->ReadFeature.pNCoordRing);
2455 84 : hMiraMonLayer->ReadFeature.pNCoordRing = nullptr;
2456 : }
2457 804 : if (hMiraMonLayer->ReadFeature.pCoord)
2458 : {
2459 96 : free(hMiraMonLayer->ReadFeature.pCoord);
2460 96 : hMiraMonLayer->ReadFeature.pCoord = nullptr;
2461 : }
2462 804 : if (hMiraMonLayer->ReadFeature.pZCoord)
2463 : {
2464 19 : free(hMiraMonLayer->ReadFeature.pZCoord);
2465 19 : hMiraMonLayer->ReadFeature.pZCoord = nullptr;
2466 : }
2467 804 : if (hMiraMonLayer->ReadFeature.pRecords)
2468 : {
2469 0 : free(hMiraMonLayer->ReadFeature.pRecords);
2470 0 : hMiraMonLayer->ReadFeature.pRecords = nullptr;
2471 : }
2472 804 : if (hMiraMonLayer->ReadFeature.flag_VFG)
2473 : {
2474 38 : free(hMiraMonLayer->ReadFeature.flag_VFG);
2475 38 : hMiraMonLayer->ReadFeature.flag_VFG = nullptr;
2476 : }
2477 :
2478 804 : if (hMiraMonLayer->pArcs)
2479 : {
2480 44 : free_function(hMiraMonLayer->pArcs);
2481 44 : hMiraMonLayer->pArcs = nullptr;
2482 : }
2483 :
2484 804 : if (hMiraMonLayer->szStringToOperate)
2485 : {
2486 439 : free_function(hMiraMonLayer->szStringToOperate);
2487 439 : hMiraMonLayer->szStringToOperate = nullptr;
2488 439 : hMiraMonLayer->nNumStringToOperate = 0;
2489 : }
2490 :
2491 804 : if (hMiraMonLayer->pLayerDB)
2492 : {
2493 107 : if (hMiraMonLayer->pLayerDB->pFields)
2494 : {
2495 107 : free_function(hMiraMonLayer->pLayerDB->pFields);
2496 107 : hMiraMonLayer->pLayerDB->pFields = nullptr;
2497 : }
2498 107 : free_function(hMiraMonLayer->pLayerDB);
2499 107 : hMiraMonLayer->pLayerDB = nullptr;
2500 : }
2501 :
2502 : // Destroys all database objects
2503 804 : MMDestroyMMDB(hMiraMonLayer);
2504 :
2505 804 : return 0;
2506 : }
2507 :
2508 : /* -------------------------------------------------------------------- */
2509 : /* Flush Layer Functions */
2510 : /* -------------------------------------------------------------------- */
2511 :
2512 : // Initializes a MM_FLUSH_INFO structure, which is used for buffering
2513 : // data before writing it to a file.
2514 1129 : int MMInitFlush(struct MM_FLUSH_INFO *pFlush, FILE_TYPE *pF, GUInt64 nBlockSize,
2515 : char **pBuffer, MM_FILE_OFFSET DiskOffsetWhereToFlush,
2516 : GInt32 nMyDiskSize)
2517 : {
2518 1129 : memset(pFlush, 0, sizeof(*pFlush));
2519 1129 : *pBuffer = nullptr;
2520 :
2521 1129 : pFlush->nMyDiskSize = nMyDiskSize;
2522 1129 : pFlush->pF = pF;
2523 1129 : pFlush->nBlockSize = nBlockSize;
2524 1129 : pFlush->nNumBytes = 0;
2525 1129 : if (MMCheckSize_t(nBlockSize, 1))
2526 0 : return 1;
2527 :
2528 1129 : if (!nBlockSize)
2529 : {
2530 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
2531 : "Error in MiraMon "
2532 : "driver: MMInitFlush() with no bytes to process");
2533 0 : return 1;
2534 : }
2535 :
2536 1129 : if (nullptr == (*pBuffer = (char *)calloc_function((size_t)nBlockSize)))
2537 : {
2538 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
2539 : "Memory error in MiraMon "
2540 : "driver (MMInitFlush())");
2541 0 : return 1;
2542 : }
2543 1129 : pFlush->OffsetWhereToFlush = DiskOffsetWhereToFlush;
2544 1129 : pFlush->CurrentOffset = 0;
2545 1129 : return 0;
2546 : }
2547 :
2548 : // Reads data from a file into a buffer.
2549 474 : int MMReadFlush(struct MM_FLUSH_INFO *pFlush)
2550 : {
2551 474 : fseek_function(pFlush->pF, pFlush->OffsetWhereToFlush, SEEK_SET);
2552 474 : if (pFlush->nBlockSize !=
2553 474 : (GUInt64)(fread_function(pFlush->pBlockWhereToSaveOrRead, 1,
2554 : (size_t)pFlush->nBlockSize, pFlush->pF)))
2555 6 : return 1;
2556 468 : return 0;
2557 : }
2558 :
2559 : // Flushes data from a buffer to a disk file.
2560 714 : static int MMFlushToDisk(struct MM_FLUSH_INFO *FlushInfo)
2561 : {
2562 714 : if (!FlushInfo->nNumBytes)
2563 86 : return 0;
2564 : // Just flush to the disk at the correct place.
2565 628 : fseek_function(FlushInfo->pF, FlushInfo->OffsetWhereToFlush, SEEK_SET);
2566 :
2567 628 : if (FlushInfo->nNumBytes !=
2568 628 : (GUInt64)fwrite_function(FlushInfo->pBlockWhereToSaveOrRead, 1,
2569 : (size_t)FlushInfo->nNumBytes, FlushInfo->pF))
2570 0 : return 1;
2571 628 : FlushInfo->OffsetWhereToFlush += FlushInfo->nNumBytes;
2572 628 : FlushInfo->NTimesFlushed++;
2573 628 : FlushInfo->TotalSavedBytes += FlushInfo->nNumBytes;
2574 628 : FlushInfo->nNumBytes = 0;
2575 :
2576 628 : return 0;
2577 : }
2578 :
2579 : // Reads a block of data from a buffer in memory
2580 8219 : int MMReadBlockFromBuffer(struct MM_FLUSH_INFO *FlushInfo)
2581 : {
2582 8219 : if (!FlushInfo->SizeOfBlockToBeSaved)
2583 0 : return 0;
2584 :
2585 8219 : if (FlushInfo->pBlockToBeSaved)
2586 : {
2587 8219 : memcpy(FlushInfo->pBlockToBeSaved,
2588 8219 : (void *)((char *)FlushInfo->pBlockWhereToSaveOrRead +
2589 8219 : FlushInfo->CurrentOffset),
2590 : FlushInfo->SizeOfBlockToBeSaved);
2591 : }
2592 8219 : FlushInfo->CurrentOffset += FlushInfo->SizeOfBlockToBeSaved;
2593 :
2594 8219 : return 0;
2595 : }
2596 :
2597 : // Appends a block of data to a buffer in memory, which is
2598 : // used for later flushing to disk.
2599 5547 : int MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo)
2600 : {
2601 5547 : if (FlushInfo->SizeOfBlockToBeSaved)
2602 : {
2603 : // If all the bloc itself does not fit to the buffer,
2604 : // then all the block is written directly to the disk
2605 4833 : if (FlushInfo->nNumBytes == 0 &&
2606 686 : FlushInfo->SizeOfBlockToBeSaved >= FlushInfo->nBlockSize)
2607 : {
2608 0 : if (MMFlushToDisk(FlushInfo))
2609 0 : return 1;
2610 0 : return 0;
2611 : }
2612 :
2613 : // There is space in FlushInfo->pBlockWhereToSaveOrRead?
2614 4833 : if (FlushInfo->nNumBytes + FlushInfo->SizeOfBlockToBeSaved <=
2615 4833 : FlushInfo->nBlockSize)
2616 : {
2617 4833 : if (FlushInfo->pBlockToBeSaved)
2618 : {
2619 4516 : memcpy((void *)((char *)FlushInfo->pBlockWhereToSaveOrRead +
2620 4516 : FlushInfo->nNumBytes),
2621 4516 : FlushInfo->pBlockToBeSaved,
2622 : FlushInfo->SizeOfBlockToBeSaved);
2623 : }
2624 : else // Add zero characters
2625 : {
2626 317 : char zero_caracters[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2627 317 : memcpy((char *)FlushInfo->pBlockWhereToSaveOrRead +
2628 317 : FlushInfo->nNumBytes,
2629 : zero_caracters, FlushInfo->SizeOfBlockToBeSaved);
2630 : }
2631 :
2632 4833 : FlushInfo->nNumBytes += FlushInfo->SizeOfBlockToBeSaved;
2633 : }
2634 : else
2635 : {
2636 : // Empty the buffer
2637 0 : if (MMFlushToDisk(FlushInfo))
2638 0 : return 1;
2639 : // Append the pendant bytes
2640 0 : if (MMAppendBlockToBuffer(FlushInfo))
2641 0 : return 1;
2642 : }
2643 4833 : return 0;
2644 : }
2645 : // Just flush to the disc.
2646 714 : return MMFlushToDisk(FlushInfo);
2647 : }
2648 :
2649 : // Copy the contents of a temporary file to a final file.
2650 : // Used everywhere when closing layers.
2651 233 : int MMMoveFromFileToFile(FILE_TYPE *pSrcFile, FILE_TYPE *pDestFile,
2652 : MM_FILE_OFFSET *pnOffset)
2653 : {
2654 233 : size_t bufferSize = 1024 * 1024; // 1 MB buffer;
2655 : unsigned char *buffer;
2656 : size_t bytesRead, bytesWritten;
2657 :
2658 233 : if (!pSrcFile || !pDestFile || !pnOffset)
2659 0 : return 0;
2660 :
2661 233 : buffer = (unsigned char *)calloc_function(bufferSize);
2662 :
2663 233 : if (!buffer)
2664 0 : return 1;
2665 :
2666 233 : fseek_function(pSrcFile, 0, SEEK_SET);
2667 233 : fseek_function(pDestFile, *pnOffset, SEEK_SET);
2668 466 : while ((bytesRead = fread_function(buffer, sizeof(unsigned char),
2669 : bufferSize, pSrcFile)) > 0)
2670 : {
2671 233 : bytesWritten = fwrite_function(buffer, sizeof(unsigned char), bytesRead,
2672 : pDestFile);
2673 233 : if (bytesWritten != bytesRead)
2674 : {
2675 0 : free_function(buffer);
2676 0 : return 1;
2677 : }
2678 233 : (*pnOffset) += bytesWritten;
2679 : }
2680 233 : free_function(buffer);
2681 233 : return 0;
2682 : }
2683 :
2684 : /* -------------------------------------------------------------------- */
2685 : /* Layer: Offsets and variables types managing */
2686 : /* -------------------------------------------------------------------- */
2687 :
2688 : // Alineation described in format documents.
2689 190 : static void MMGetOffsetAlignedTo8(MM_FILE_OFFSET *Offset)
2690 : {
2691 : MM_FILE_OFFSET reajust;
2692 :
2693 190 : if ((*Offset) % 8L)
2694 : {
2695 168 : reajust = 8 - ((*Offset) % 8L);
2696 168 : (*Offset) += reajust;
2697 : }
2698 190 : }
2699 :
2700 : // Reading integers depending on the version being read.
2701 2760 : int MMReadGUInt64DependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer,
2702 : struct MM_FLUSH_INFO *FlushInfo,
2703 : GUInt64 *pnUI64)
2704 : {
2705 : uint32_t nUL32;
2706 :
2707 2760 : if (!hMiraMonLayer)
2708 0 : return 1;
2709 :
2710 2760 : if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
2711 : {
2712 2682 : FlushInfo->pBlockToBeSaved = (void *)&nUL32;
2713 2682 : FlushInfo->SizeOfBlockToBeSaved = sizeof(nUL32);
2714 2682 : if (MMReadBlockFromBuffer(FlushInfo))
2715 : {
2716 0 : FlushInfo->pBlockToBeSaved = nullptr;
2717 0 : return 1;
2718 : }
2719 2682 : *pnUI64 = (GUInt64)nUL32;
2720 : }
2721 : else
2722 : {
2723 78 : FlushInfo->pBlockToBeSaved = (void *)pnUI64;
2724 78 : FlushInfo->SizeOfBlockToBeSaved = sizeof(*pnUI64);
2725 78 : if (MMReadBlockFromBuffer(FlushInfo))
2726 : {
2727 0 : FlushInfo->pBlockToBeSaved = nullptr;
2728 0 : return 1;
2729 : }
2730 : }
2731 2760 : FlushInfo->pBlockToBeSaved = nullptr;
2732 2760 : return 0;
2733 : }
2734 :
2735 : // Reading offsets depending on the version is being read.
2736 743 : int MMReadOffsetDependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer,
2737 : struct MM_FLUSH_INFO *FlushInfo,
2738 : MM_FILE_OFFSET *pnUI64)
2739 : {
2740 : uint32_t nUL32;
2741 :
2742 743 : if (!hMiraMonLayer)
2743 0 : return 1;
2744 :
2745 743 : if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
2746 : {
2747 721 : FlushInfo->pBlockToBeSaved = (void *)&nUL32;
2748 721 : FlushInfo->SizeOfBlockToBeSaved = sizeof(nUL32);
2749 721 : if (MMReadBlockFromBuffer(FlushInfo))
2750 : {
2751 0 : FlushInfo->pBlockToBeSaved = nullptr;
2752 0 : return 1;
2753 : }
2754 721 : *pnUI64 = (MM_FILE_OFFSET)nUL32;
2755 : }
2756 : else
2757 : {
2758 22 : FlushInfo->pBlockToBeSaved = (void *)pnUI64;
2759 22 : FlushInfo->SizeOfBlockToBeSaved = sizeof(*pnUI64);
2760 22 : if (MMReadBlockFromBuffer(FlushInfo))
2761 : {
2762 0 : FlushInfo->pBlockToBeSaved = nullptr;
2763 0 : return 1;
2764 : }
2765 : }
2766 743 : FlushInfo->pBlockToBeSaved = nullptr;
2767 743 : return 0;
2768 : }
2769 :
2770 : // Appending integers depending on the version.
2771 1211 : int MMAppendIntegerDependingOnVersion(
2772 : struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo,
2773 : uint32_t *nUL32, GUInt64 nUI64)
2774 : {
2775 : int result;
2776 :
2777 1211 : if (!hMiraMonLayer)
2778 0 : return 1;
2779 :
2780 1211 : if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
2781 : {
2782 1061 : *nUL32 = (uint32_t)nUI64;
2783 1061 : FlushInfo->SizeOfBlockToBeSaved = sizeof(*nUL32);
2784 1061 : hMiraMonLayer->OffsetCheck += FlushInfo->SizeOfBlockToBeSaved;
2785 1061 : FlushInfo->pBlockToBeSaved = (void *)nUL32;
2786 : }
2787 : else
2788 : {
2789 150 : FlushInfo->SizeOfBlockToBeSaved = sizeof(nUI64);
2790 150 : hMiraMonLayer->OffsetCheck += FlushInfo->SizeOfBlockToBeSaved;
2791 150 : FlushInfo->pBlockToBeSaved = (void *)&nUI64;
2792 : }
2793 1211 : result = MMAppendBlockToBuffer(FlushInfo);
2794 1211 : FlushInfo->pBlockToBeSaved = nullptr;
2795 1211 : return result;
2796 : }
2797 :
2798 : /* -------------------------------------------------------------------- */
2799 : /* Layer: Reading and writing layer sections */
2800 : /* This code follows the specifications of the following document: */
2801 : /* https://www.miramon.cat/new_note/eng/notes/ \ */
2802 : /* FormatFitxersTopologicsMiraMon.pdf */
2803 : /* -------------------------------------------------------------------- */
2804 68 : int MMReadAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer)
2805 : {
2806 : MM_INTERNAL_FID iElem, nElem;
2807 : struct MM_FLUSH_INFO FlushTMP;
2808 68 : char *pBuffer = nullptr;
2809 : MM_FILE_OFFSET nBlockSize;
2810 : struct MiraMonArcLayer *pMMArcLayer;
2811 : MM_N_VERTICES_TYPE nElementCount;
2812 :
2813 68 : if (!hMiraMonLayer)
2814 0 : return 1;
2815 :
2816 68 : if (hMiraMonLayer->bIsPolygon)
2817 : {
2818 41 : pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
2819 41 : nElem = hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount;
2820 : }
2821 : else
2822 : {
2823 27 : pMMArcLayer = &hMiraMonLayer->MMArc;
2824 27 : nElem = hMiraMonLayer->TopHeader.nElemCount;
2825 : }
2826 :
2827 68 : if (MMCheckSize_t(nElem, pMMArcLayer->nSizeArcHeader))
2828 : {
2829 0 : return 1;
2830 : }
2831 :
2832 68 : nBlockSize = nElem * (pMMArcLayer->nSizeArcHeader);
2833 :
2834 68 : if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, nBlockSize, &pBuffer,
2835 68 : hMiraMonLayer->nHeaderDiskSize, 0))
2836 : {
2837 0 : if (pBuffer)
2838 0 : free_function(pBuffer);
2839 0 : return 1;
2840 : }
2841 68 : FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
2842 68 : if (MMReadFlush(&FlushTMP))
2843 : {
2844 0 : if (pBuffer)
2845 0 : free_function(pBuffer);
2846 0 : return 1;
2847 : }
2848 :
2849 341 : for (iElem = 0; iElem < nElem; iElem++)
2850 : {
2851 : // Bounding box
2852 273 : FlushTMP.pBlockToBeSaved =
2853 273 : (void *)&(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX);
2854 273 : FlushTMP.SizeOfBlockToBeSaved =
2855 : sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX);
2856 273 : if (MMReadBlockFromBuffer(&FlushTMP))
2857 : {
2858 0 : if (pBuffer)
2859 0 : free_function(pBuffer);
2860 0 : return 1;
2861 : }
2862 273 : FlushTMP.pBlockToBeSaved =
2863 273 : (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX;
2864 273 : FlushTMP.SizeOfBlockToBeSaved =
2865 : sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX);
2866 273 : if (MMReadBlockFromBuffer(&FlushTMP))
2867 : {
2868 0 : if (pBuffer)
2869 0 : free_function(pBuffer);
2870 0 : return 1;
2871 : }
2872 273 : FlushTMP.pBlockToBeSaved =
2873 273 : (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY;
2874 273 : FlushTMP.SizeOfBlockToBeSaved =
2875 : sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY);
2876 273 : if (MMReadBlockFromBuffer(&FlushTMP))
2877 : {
2878 0 : if (pBuffer)
2879 0 : free_function(pBuffer);
2880 0 : return 1;
2881 : }
2882 273 : FlushTMP.pBlockToBeSaved =
2883 273 : (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY;
2884 273 : FlushTMP.SizeOfBlockToBeSaved =
2885 : sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY);
2886 273 : if (MMReadBlockFromBuffer(&FlushTMP))
2887 : {
2888 0 : if (pBuffer)
2889 0 : free_function(pBuffer);
2890 0 : return 1;
2891 : }
2892 :
2893 : // Element count: number of vertices of the arc
2894 273 : nElementCount = pMMArcLayer->pArcHeader[iElem].nElemCount;
2895 273 : if (MMReadGUInt64DependingOnVersion(hMiraMonLayer, &FlushTMP,
2896 : &nElementCount))
2897 : {
2898 0 : if (pBuffer)
2899 0 : free_function(pBuffer);
2900 0 : return 1;
2901 : }
2902 273 : pMMArcLayer->pArcHeader[iElem].nElemCount = nElementCount;
2903 :
2904 : // Offset: offset of the first vertice of the arc
2905 273 : if (MMReadOffsetDependingOnVersion(
2906 : hMiraMonLayer, &FlushTMP,
2907 273 : &pMMArcLayer->pArcHeader[iElem].nOffset))
2908 : {
2909 0 : if (pBuffer)
2910 0 : free_function(pBuffer);
2911 0 : return 1;
2912 : }
2913 : // First node: first node of the arc
2914 273 : if (MMReadGUInt64DependingOnVersion(
2915 : hMiraMonLayer, &FlushTMP,
2916 273 : &pMMArcLayer->pArcHeader[iElem].nFirstIdNode))
2917 : {
2918 0 : if (pBuffer)
2919 0 : free_function(pBuffer);
2920 0 : return 1;
2921 : }
2922 : // Last node: first node of the arc
2923 273 : if (MMReadGUInt64DependingOnVersion(
2924 : hMiraMonLayer, &FlushTMP,
2925 273 : &pMMArcLayer->pArcHeader[iElem].nLastIdNode))
2926 : {
2927 0 : if (pBuffer)
2928 0 : free_function(pBuffer);
2929 0 : return 1;
2930 : }
2931 : // Length of the arc
2932 273 : FlushTMP.pBlockToBeSaved =
2933 273 : (void *)&pMMArcLayer->pArcHeader[iElem].dfLength;
2934 273 : FlushTMP.SizeOfBlockToBeSaved =
2935 : sizeof(pMMArcLayer->pArcHeader[iElem].dfLength);
2936 273 : if (MMReadBlockFromBuffer(&FlushTMP))
2937 : {
2938 0 : if (pBuffer)
2939 0 : free_function(pBuffer);
2940 0 : return 1;
2941 : }
2942 : }
2943 :
2944 68 : if (pBuffer)
2945 68 : free_function(pBuffer);
2946 68 : return 0;
2947 : }
2948 :
2949 57 : int MMWriteAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
2950 : MM_FILE_OFFSET DiskOffset)
2951 : {
2952 : MM_INTERNAL_FID iElem;
2953 : struct MM_FLUSH_INFO FlushTMP;
2954 57 : char *pBuffer = nullptr;
2955 : uint32_t nUL32;
2956 : MM_FILE_OFFSET nOffsetDiff;
2957 : struct MiraMonArcLayer *pMMArcLayer;
2958 :
2959 57 : if (!hMiraMonLayer)
2960 0 : return 1;
2961 :
2962 57 : if (hMiraMonLayer->bIsPolygon)
2963 27 : pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
2964 : else
2965 30 : pMMArcLayer = &hMiraMonLayer->MMArc;
2966 :
2967 57 : nOffsetDiff =
2968 57 : hMiraMonLayer->nHeaderDiskSize +
2969 57 : hMiraMonLayer->nFinalElemCount * (pMMArcLayer->nSizeArcHeader);
2970 :
2971 57 : if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, MM_1MB, &pBuffer, DiskOffset,
2972 : 0))
2973 : {
2974 0 : if (pBuffer)
2975 0 : free_function(pBuffer);
2976 0 : return 1;
2977 : }
2978 :
2979 57 : FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
2980 158 : for (iElem = 0; iElem < hMiraMonLayer->nFinalElemCount; iElem++)
2981 : {
2982 : // Bounding box
2983 101 : FlushTMP.SizeOfBlockToBeSaved =
2984 : sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX);
2985 101 : FlushTMP.pBlockToBeSaved =
2986 101 : (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX;
2987 101 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
2988 101 : if (MMAppendBlockToBuffer(&FlushTMP))
2989 : {
2990 0 : if (pBuffer)
2991 0 : free_function(pBuffer);
2992 0 : return 1;
2993 : }
2994 101 : FlushTMP.pBlockToBeSaved =
2995 101 : (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX;
2996 101 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
2997 101 : if (MMAppendBlockToBuffer(&FlushTMP))
2998 : {
2999 0 : if (pBuffer)
3000 0 : free_function(pBuffer);
3001 0 : return 1;
3002 : }
3003 101 : FlushTMP.pBlockToBeSaved =
3004 101 : (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY;
3005 101 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3006 101 : if (MMAppendBlockToBuffer(&FlushTMP))
3007 : {
3008 0 : if (pBuffer)
3009 0 : free_function(pBuffer);
3010 0 : return 1;
3011 : }
3012 101 : FlushTMP.pBlockToBeSaved =
3013 101 : (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY;
3014 101 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3015 101 : if (MMAppendBlockToBuffer(&FlushTMP))
3016 : {
3017 0 : if (pBuffer)
3018 0 : free_function(pBuffer);
3019 0 : return 1;
3020 : }
3021 :
3022 : // Element count: number of vertices of the arc
3023 101 : if (MMAppendIntegerDependingOnVersion(
3024 : hMiraMonLayer, &FlushTMP, &nUL32,
3025 101 : pMMArcLayer->pArcHeader[iElem].nElemCount))
3026 : {
3027 0 : if (pBuffer)
3028 0 : free_function(pBuffer);
3029 0 : return 1;
3030 : }
3031 :
3032 : // Offset: offset of the first vertice of the arc
3033 101 : if (MMAppendIntegerDependingOnVersion(
3034 : hMiraMonLayer, &FlushTMP, &nUL32,
3035 101 : pMMArcLayer->pArcHeader[iElem].nOffset + nOffsetDiff))
3036 : {
3037 0 : if (pBuffer)
3038 0 : free_function(pBuffer);
3039 0 : return 1;
3040 : }
3041 : // First node: first node of the arc
3042 101 : if (MMAppendIntegerDependingOnVersion(
3043 : hMiraMonLayer, &FlushTMP, &nUL32,
3044 101 : pMMArcLayer->pArcHeader[iElem].nFirstIdNode))
3045 : {
3046 0 : if (pBuffer)
3047 0 : free_function(pBuffer);
3048 0 : return 1;
3049 : }
3050 : // Last node: first node of the arc
3051 101 : if (MMAppendIntegerDependingOnVersion(
3052 : hMiraMonLayer, &FlushTMP, &nUL32,
3053 101 : pMMArcLayer->pArcHeader[iElem].nLastIdNode))
3054 : {
3055 0 : if (pBuffer)
3056 0 : free_function(pBuffer);
3057 0 : return 1;
3058 : }
3059 : // Length of the arc
3060 101 : FlushTMP.SizeOfBlockToBeSaved =
3061 : sizeof(pMMArcLayer->pArcHeader[iElem].dfLength);
3062 101 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3063 101 : FlushTMP.pBlockToBeSaved =
3064 101 : (void *)&pMMArcLayer->pArcHeader[iElem].dfLength;
3065 101 : if (MMAppendBlockToBuffer(&FlushTMP))
3066 : {
3067 0 : if (pBuffer)
3068 0 : free_function(pBuffer);
3069 0 : return 1;
3070 : }
3071 : }
3072 57 : FlushTMP.SizeOfBlockToBeSaved = 0;
3073 57 : if (MMAppendBlockToBuffer(&FlushTMP))
3074 : {
3075 0 : if (pBuffer)
3076 0 : free_function(pBuffer);
3077 0 : return 1;
3078 : }
3079 :
3080 57 : if (pBuffer)
3081 57 : free_function(pBuffer);
3082 57 : return 0;
3083 : }
3084 :
3085 : #ifdef JUST_IN_CASE_WE_NEED_IT_SOMEDAY
3086 : static int MMReadNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer)
3087 : {
3088 : MM_INTERNAL_FID iElem, nElem;
3089 : struct MM_FLUSH_INFO FlushTMP;
3090 : char *pBuffer = nullptr;
3091 : MM_FILE_OFFSET nBlockSize;
3092 : struct MiraMonArcLayer *pMMArcLayer;
3093 :
3094 : if (hMiraMonLayer->bIsPolygon)
3095 : pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
3096 : else
3097 : pMMArcLayer = &hMiraMonLayer->MMArc;
3098 :
3099 : nElem = pMMArcLayer->TopNodeHeader.nElemCount;
3100 :
3101 : nBlockSize = nElem * pMMArcLayer->MMNode.nSizeNodeHeader;
3102 :
3103 : if (MMInitFlush(&FlushTMP, pMMArcLayer->MMNode.pF, nBlockSize, &pBuffer,
3104 : hMiraMonLayer->nHeaderDiskSize, 0))
3105 : {
3106 : if (pBuffer)
3107 : free_function(pBuffer);
3108 : return 1;
3109 : }
3110 :
3111 : FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
3112 : if (MMReadFlush(&FlushTMP))
3113 : {
3114 : if (pBuffer)
3115 : free_function(pBuffer);
3116 : return 1;
3117 : }
3118 :
3119 : for (iElem = 0; iElem < nElem; iElem++)
3120 : {
3121 : // Arcs count
3122 : FlushTMP.pBlockToBeSaved =
3123 : (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount;
3124 : FlushTMP.SizeOfBlockToBeSaved =
3125 : sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount);
3126 : if (MMReadBlockFromBuffer(&FlushTMP))
3127 : {
3128 : if (pBuffer)
3129 : free_function(pBuffer);
3130 : return 1;
3131 : }
3132 : // Node type
3133 : FlushTMP.pBlockToBeSaved =
3134 : (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType;
3135 : FlushTMP.SizeOfBlockToBeSaved =
3136 : sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType);
3137 : if (MMReadBlockFromBuffer(&FlushTMP))
3138 : {
3139 : if (pBuffer)
3140 : free_function(pBuffer);
3141 : return 1;
3142 : }
3143 : FlushTMP.SizeOfBlockToBeSaved = 1;
3144 : FlushTMP.pBlockToBeSaved = (void *)nullptr;
3145 : if (MMReadBlockFromBuffer(&FlushTMP))
3146 : {
3147 : if (pBuffer)
3148 : free_function(pBuffer);
3149 : return 1;
3150 : }
3151 :
3152 : // Offset: offset of the first arc to the node
3153 : if (MMReadOffsetDependingOnVersion(
3154 : hMiraMonLayer, &FlushTMP,
3155 : &pMMArcLayer->MMNode.pNodeHeader[iElem].nOffset))
3156 : {
3157 : if (pBuffer)
3158 : free_function(pBuffer);
3159 : return 1;
3160 : }
3161 : }
3162 :
3163 : if (pBuffer)
3164 : free_function(pBuffer);
3165 : return 0;
3166 : }
3167 : #endif // JUST_IN_CASE_WE_NEED_IT_SOMEDAY
3168 :
3169 57 : int MMWriteNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
3170 : MM_FILE_OFFSET DiskOffset)
3171 : {
3172 : MM_INTERNAL_FID iElem;
3173 : struct MM_FLUSH_INFO FlushTMP;
3174 57 : char *pBuffer = nullptr;
3175 : uint32_t nUL32;
3176 : MM_FILE_OFFSET nOffsetDiff;
3177 : struct MiraMonArcLayer *pMMArcLayer;
3178 :
3179 57 : if (!hMiraMonLayer)
3180 0 : return 1;
3181 :
3182 57 : if (hMiraMonLayer->bIsPolygon)
3183 27 : pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
3184 : else
3185 30 : pMMArcLayer = &hMiraMonLayer->MMArc;
3186 :
3187 57 : nOffsetDiff = hMiraMonLayer->nHeaderDiskSize +
3188 57 : (pMMArcLayer->TopNodeHeader.nElemCount *
3189 57 : pMMArcLayer->MMNode.nSizeNodeHeader);
3190 :
3191 57 : if (MMInitFlush(&FlushTMP, pMMArcLayer->MMNode.pF, MM_1MB, &pBuffer,
3192 : DiskOffset, 0))
3193 : {
3194 0 : if (pBuffer)
3195 0 : free_function(pBuffer);
3196 0 : return 1;
3197 : }
3198 :
3199 57 : FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
3200 206 : for (iElem = 0; iElem < pMMArcLayer->TopNodeHeader.nElemCount; iElem++)
3201 : {
3202 : // Arcs count
3203 149 : FlushTMP.SizeOfBlockToBeSaved =
3204 : sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount);
3205 149 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3206 149 : FlushTMP.pBlockToBeSaved =
3207 149 : (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount;
3208 149 : if (MMAppendBlockToBuffer(&FlushTMP))
3209 : {
3210 0 : if (pBuffer)
3211 0 : free_function(pBuffer);
3212 0 : return 1;
3213 : }
3214 : // Node type
3215 149 : FlushTMP.SizeOfBlockToBeSaved =
3216 : sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType);
3217 149 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3218 149 : FlushTMP.pBlockToBeSaved =
3219 149 : (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType;
3220 149 : if (MMAppendBlockToBuffer(&FlushTMP))
3221 : {
3222 0 : if (pBuffer)
3223 0 : free_function(pBuffer);
3224 0 : return 1;
3225 : }
3226 149 : FlushTMP.SizeOfBlockToBeSaved = 1;
3227 149 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3228 149 : FlushTMP.pBlockToBeSaved = (void *)nullptr;
3229 149 : if (MMAppendBlockToBuffer(&FlushTMP))
3230 : {
3231 0 : if (pBuffer)
3232 0 : free_function(pBuffer);
3233 0 : return 1;
3234 : }
3235 :
3236 : // Offset: offset of the first arc to the node
3237 149 : if (MMAppendIntegerDependingOnVersion(
3238 : hMiraMonLayer, &FlushTMP, &nUL32,
3239 149 : pMMArcLayer->MMNode.pNodeHeader[iElem].nOffset + nOffsetDiff))
3240 : {
3241 0 : if (pBuffer)
3242 0 : free_function(pBuffer);
3243 0 : return 1;
3244 : }
3245 : }
3246 57 : FlushTMP.SizeOfBlockToBeSaved = 0;
3247 57 : if (MMAppendBlockToBuffer(&FlushTMP))
3248 : {
3249 0 : if (pBuffer)
3250 0 : free_function(pBuffer);
3251 0 : return 1;
3252 : }
3253 :
3254 57 : if (pBuffer)
3255 57 : free_function(pBuffer);
3256 57 : return 0;
3257 : }
3258 :
3259 44 : int MMReadPHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer)
3260 : {
3261 : MM_INTERNAL_FID iElem;
3262 : struct MM_FLUSH_INFO FlushTMP;
3263 44 : char *pBuffer = nullptr;
3264 : MM_FILE_OFFSET nBlockSize;
3265 : struct MiraMonPolygonLayer *pMMPolygonLayer;
3266 :
3267 44 : if (!hMiraMonLayer)
3268 0 : return 1;
3269 :
3270 44 : pMMPolygonLayer = &hMiraMonLayer->MMPolygon;
3271 :
3272 44 : if (MMCheckSize_t(hMiraMonLayer->TopHeader.nElemCount,
3273 88 : pMMPolygonLayer->nPHElementSize) ||
3274 44 : MMCheckSize_t(hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount,
3275 44 : hMiraMonLayer->MMPolygon.nPSElementSize))
3276 : {
3277 0 : return 1;
3278 : }
3279 44 : nBlockSize =
3280 44 : hMiraMonLayer->TopHeader.nElemCount * (pMMPolygonLayer->nPHElementSize);
3281 :
3282 44 : if (MMInitFlush(&FlushTMP, pMMPolygonLayer->pF, nBlockSize, &pBuffer,
3283 44 : hMiraMonLayer->nHeaderDiskSize +
3284 44 : (hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount *
3285 44 : hMiraMonLayer->MMPolygon.nPSElementSize),
3286 : 0))
3287 : {
3288 0 : if (pBuffer)
3289 0 : free_function(pBuffer);
3290 0 : return 1;
3291 : }
3292 44 : FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
3293 44 : if (MMReadFlush(&FlushTMP))
3294 : {
3295 0 : if (pBuffer)
3296 0 : free_function(pBuffer);
3297 0 : return 1;
3298 : }
3299 :
3300 175 : for (iElem = 0; iElem < hMiraMonLayer->TopHeader.nElemCount; iElem++)
3301 : {
3302 : // Bounding box
3303 131 : FlushTMP.pBlockToBeSaved =
3304 131 : (void *)&(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX);
3305 131 : FlushTMP.SizeOfBlockToBeSaved =
3306 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX);
3307 131 : if (MMReadBlockFromBuffer(&FlushTMP))
3308 : {
3309 0 : if (pBuffer)
3310 0 : free_function(pBuffer);
3311 0 : return 1;
3312 : }
3313 131 : FlushTMP.pBlockToBeSaved =
3314 131 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX;
3315 131 : FlushTMP.SizeOfBlockToBeSaved =
3316 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX);
3317 131 : if (MMReadBlockFromBuffer(&FlushTMP))
3318 : {
3319 0 : if (pBuffer)
3320 0 : free_function(pBuffer);
3321 0 : return 1;
3322 : }
3323 131 : FlushTMP.pBlockToBeSaved =
3324 131 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY;
3325 131 : FlushTMP.SizeOfBlockToBeSaved =
3326 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY);
3327 131 : if (MMReadBlockFromBuffer(&FlushTMP))
3328 : {
3329 0 : if (pBuffer)
3330 0 : free_function(pBuffer);
3331 0 : return 1;
3332 : }
3333 131 : FlushTMP.pBlockToBeSaved =
3334 131 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY;
3335 131 : FlushTMP.SizeOfBlockToBeSaved =
3336 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY);
3337 131 : if (MMReadBlockFromBuffer(&FlushTMP))
3338 : {
3339 0 : if (pBuffer)
3340 0 : free_function(pBuffer);
3341 0 : return 1;
3342 : }
3343 :
3344 : // Arcs count: number of arcs of the polygon
3345 131 : if (MMReadGUInt64DependingOnVersion(
3346 : hMiraMonLayer, &FlushTMP,
3347 131 : &pMMPolygonLayer->pPolHeader[iElem].nArcsCount))
3348 : {
3349 0 : if (pBuffer)
3350 0 : free_function(pBuffer);
3351 0 : return 1;
3352 : }
3353 :
3354 : // External arcs count: number of external arcs of the polygon
3355 131 : if (MMReadGUInt64DependingOnVersion(
3356 : hMiraMonLayer, &FlushTMP,
3357 131 : &pMMPolygonLayer->pPolHeader[iElem].nExternalRingsCount))
3358 : {
3359 0 : if (pBuffer)
3360 0 : free_function(pBuffer);
3361 0 : return 1;
3362 : }
3363 :
3364 : // Rings count: number of rings of the polygon
3365 131 : if (MMReadGUInt64DependingOnVersion(
3366 : hMiraMonLayer, &FlushTMP,
3367 131 : &pMMPolygonLayer->pPolHeader[iElem].nRingsCount))
3368 : {
3369 0 : if (pBuffer)
3370 0 : free_function(pBuffer);
3371 0 : return 1;
3372 : }
3373 :
3374 : // Offset: offset of the first vertex of the arc
3375 131 : if (MMReadOffsetDependingOnVersion(
3376 : hMiraMonLayer, &FlushTMP,
3377 131 : &pMMPolygonLayer->pPolHeader[iElem].nOffset))
3378 : {
3379 0 : if (pBuffer)
3380 0 : free_function(pBuffer);
3381 0 : return 1;
3382 : }
3383 :
3384 : // Perimeter of the arc
3385 131 : FlushTMP.SizeOfBlockToBeSaved =
3386 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfPerimeter);
3387 131 : FlushTMP.pBlockToBeSaved =
3388 131 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfPerimeter;
3389 131 : if (MMReadBlockFromBuffer(&FlushTMP))
3390 : {
3391 0 : if (pBuffer)
3392 0 : free_function(pBuffer);
3393 0 : return 1;
3394 : }
3395 :
3396 : // Area of the arc
3397 131 : FlushTMP.SizeOfBlockToBeSaved =
3398 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfArea);
3399 131 : FlushTMP.pBlockToBeSaved =
3400 131 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfArea;
3401 131 : if (MMReadBlockFromBuffer(&FlushTMP))
3402 : {
3403 0 : if (pBuffer)
3404 0 : free_function(pBuffer);
3405 0 : return 1;
3406 : }
3407 : }
3408 :
3409 44 : if (pBuffer)
3410 44 : free_function(pBuffer);
3411 44 : return 0;
3412 : }
3413 :
3414 27 : int MMWritePHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer,
3415 : MM_FILE_OFFSET DiskOffset)
3416 : {
3417 : MM_INTERNAL_FID iElem;
3418 : struct MM_FLUSH_INFO FlushTMP;
3419 27 : char *pBuffer = nullptr;
3420 : uint32_t nUL32;
3421 : MM_FILE_OFFSET nOffsetDiff;
3422 : struct MiraMonPolygonLayer *pMMPolygonLayer;
3423 :
3424 27 : if (!hMiraMonLayer)
3425 0 : return 1;
3426 :
3427 27 : pMMPolygonLayer = &hMiraMonLayer->MMPolygon;
3428 :
3429 27 : if (!pMMPolygonLayer->pF)
3430 0 : return 0;
3431 :
3432 27 : if (!hMiraMonLayer->nFinalElemCount)
3433 0 : return 0;
3434 :
3435 27 : nOffsetDiff = DiskOffset + hMiraMonLayer->TopHeader.nElemCount *
3436 27 : (pMMPolygonLayer->nPHElementSize);
3437 :
3438 27 : if (MMInitFlush(&FlushTMP, pMMPolygonLayer->pF, MM_1MB, &pBuffer,
3439 : DiskOffset, 0))
3440 : {
3441 0 : if (pBuffer)
3442 0 : free_function(pBuffer);
3443 0 : return 1;
3444 : }
3445 :
3446 27 : FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer;
3447 95 : for (iElem = 0; iElem < hMiraMonLayer->nFinalElemCount; iElem++)
3448 : {
3449 : // Bounding box
3450 68 : FlushTMP.SizeOfBlockToBeSaved =
3451 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX);
3452 68 : FlushTMP.pBlockToBeSaved =
3453 68 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX;
3454 68 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3455 68 : if (MMAppendBlockToBuffer(&FlushTMP))
3456 : {
3457 0 : if (pBuffer)
3458 0 : free_function(pBuffer);
3459 0 : return 1;
3460 : }
3461 68 : FlushTMP.pBlockToBeSaved =
3462 68 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX;
3463 68 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3464 68 : if (MMAppendBlockToBuffer(&FlushTMP))
3465 : {
3466 0 : if (pBuffer)
3467 0 : free_function(pBuffer);
3468 0 : return 1;
3469 : }
3470 68 : FlushTMP.pBlockToBeSaved =
3471 68 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY;
3472 68 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3473 68 : if (MMAppendBlockToBuffer(&FlushTMP))
3474 : {
3475 0 : if (pBuffer)
3476 0 : free_function(pBuffer);
3477 0 : return 1;
3478 : }
3479 68 : FlushTMP.pBlockToBeSaved =
3480 68 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY;
3481 68 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3482 68 : if (MMAppendBlockToBuffer(&FlushTMP))
3483 : {
3484 0 : if (pBuffer)
3485 0 : free_function(pBuffer);
3486 0 : return 1;
3487 : }
3488 :
3489 : // Arcs count: number of the arcs of the polygon
3490 68 : if (MMAppendIntegerDependingOnVersion(
3491 : hMiraMonLayer, &FlushTMP, &nUL32,
3492 68 : pMMPolygonLayer->pPolHeader[iElem].nArcsCount))
3493 : {
3494 0 : if (pBuffer)
3495 0 : free_function(pBuffer);
3496 0 : return 1;
3497 : }
3498 :
3499 : // External arcs count: number of external arcs of the polygon
3500 68 : if (MMAppendIntegerDependingOnVersion(
3501 : hMiraMonLayer, &FlushTMP, &nUL32,
3502 68 : pMMPolygonLayer->pPolHeader[iElem].nExternalRingsCount))
3503 : {
3504 0 : if (pBuffer)
3505 0 : free_function(pBuffer);
3506 0 : return 1;
3507 : }
3508 :
3509 : // Rings count: number of rings of the polygon
3510 68 : if (MMAppendIntegerDependingOnVersion(
3511 : hMiraMonLayer, &FlushTMP, &nUL32,
3512 68 : pMMPolygonLayer->pPolHeader[iElem].nRingsCount))
3513 : {
3514 0 : if (pBuffer)
3515 0 : free_function(pBuffer);
3516 0 : return 1;
3517 : }
3518 :
3519 : // Offset: offset of the first vertex of the arc
3520 68 : if (MMAppendIntegerDependingOnVersion(
3521 : hMiraMonLayer, &FlushTMP, &nUL32,
3522 68 : pMMPolygonLayer->pPolHeader[iElem].nOffset + nOffsetDiff))
3523 : {
3524 0 : if (pBuffer)
3525 0 : free_function(pBuffer);
3526 0 : return 1;
3527 : }
3528 :
3529 : // Perimeter of the arc
3530 68 : FlushTMP.SizeOfBlockToBeSaved =
3531 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfPerimeter);
3532 68 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3533 68 : FlushTMP.pBlockToBeSaved =
3534 68 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfPerimeter;
3535 68 : if (MMAppendBlockToBuffer(&FlushTMP))
3536 : {
3537 0 : if (pBuffer)
3538 0 : free_function(pBuffer);
3539 0 : return 1;
3540 : }
3541 :
3542 : // Area of the arc
3543 68 : FlushTMP.SizeOfBlockToBeSaved =
3544 : sizeof(pMMPolygonLayer->pPolHeader[iElem].dfArea);
3545 68 : hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved;
3546 68 : FlushTMP.pBlockToBeSaved =
3547 68 : (void *)&pMMPolygonLayer->pPolHeader[iElem].dfArea;
3548 68 : if (MMAppendBlockToBuffer(&FlushTMP))
3549 : {
3550 0 : if (pBuffer)
3551 0 : free_function(pBuffer);
3552 0 : return 1;
3553 : }
3554 : }
3555 27 : FlushTMP.SizeOfBlockToBeSaved = 0;
3556 27 : if (MMAppendBlockToBuffer(&FlushTMP))
3557 : {
3558 0 : if (pBuffer)
3559 0 : free_function(pBuffer);
3560 0 : return 1;
3561 : }
3562 :
3563 27 : if (pBuffer)
3564 27 : free_function(pBuffer);
3565 27 : return 0;
3566 : }
3567 :
3568 : /* -------------------------------------------------------------------- */
3569 : /* Feature Functions */
3570 : /* -------------------------------------------------------------------- */
3571 82 : int MMInitFeature(struct MiraMonFeature *hMMFeature)
3572 : {
3573 82 : memset(hMMFeature, 0, sizeof(*hMMFeature));
3574 :
3575 82 : hMMFeature->nMaxMRecords = MM_INIT_NUMBER_OF_RECORDS;
3576 82 : if (MMCheckSize_t(hMMFeature->nMaxMRecords,
3577 : sizeof(*(hMMFeature->pRecords))))
3578 0 : return 1;
3579 :
3580 82 : if (!hMMFeature->nMaxMRecords)
3581 0 : return 0; // No elements nothing to do.
3582 :
3583 82 : if ((hMMFeature->pRecords =
3584 82 : calloc_function((size_t)hMMFeature->nMaxMRecords *
3585 : sizeof(*(hMMFeature->pRecords)))) == nullptr)
3586 0 : return 1;
3587 :
3588 82 : hMMFeature->pRecords[0].nMaxField = MM_INIT_NUMBER_OF_FIELDS;
3589 82 : hMMFeature->pRecords[0].nNumField = 0;
3590 82 : if (MMCheckSize_t(hMMFeature->pRecords[0].nMaxField,
3591 : sizeof(*(hMMFeature->pRecords[0].pField))))
3592 0 : return 1;
3593 82 : if (nullptr == (hMMFeature->pRecords[0].pField = calloc_function(
3594 : (size_t)hMMFeature->pRecords[0].nMaxField *
3595 : sizeof(*(hMMFeature->pRecords[0].pField)))))
3596 0 : return 1;
3597 :
3598 82 : return 0;
3599 : }
3600 :
3601 : // Conserves all allocated memory but resets the information
3602 550 : void MMResetFeatureGeometry(struct MiraMonFeature *hMMFeature)
3603 : {
3604 550 : if (hMMFeature->pNCoordRing)
3605 : {
3606 407 : memset(hMMFeature->pNCoordRing, 0,
3607 407 : (size_t)hMMFeature->nMaxpNCoordRing *
3608 : sizeof(*(hMMFeature->pNCoordRing)));
3609 : }
3610 550 : if (hMMFeature->pCoord)
3611 : {
3612 407 : memset(hMMFeature->pCoord, 0,
3613 407 : (size_t)hMMFeature->nMaxpCoord * sizeof(*(hMMFeature->pCoord)));
3614 : }
3615 550 : hMMFeature->nICoord = 0;
3616 550 : if (hMMFeature->pZCoord)
3617 : {
3618 274 : memset(hMMFeature->pZCoord, 0,
3619 274 : (size_t)hMMFeature->nMaxpZCoord *
3620 : sizeof(*(hMMFeature->pZCoord)));
3621 : }
3622 550 : hMMFeature->nNRings = 0;
3623 550 : hMMFeature->nIRing = 0;
3624 :
3625 550 : if (hMMFeature->flag_VFG)
3626 : {
3627 318 : memset(hMMFeature->flag_VFG, 0,
3628 318 : (size_t)hMMFeature->nMaxVFG * sizeof(*(hMMFeature->flag_VFG)));
3629 : }
3630 550 : }
3631 :
3632 : // Preserves all allocated memory but initializes it to zero.
3633 547 : void MMResetFeatureRecord(struct MiraMonFeature *hMMFeature)
3634 : {
3635 : MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord;
3636 : MM_EXT_DBF_N_FIELDS nIField;
3637 :
3638 547 : if (!hMMFeature->pRecords)
3639 340 : return;
3640 :
3641 444 : for (nIRecord = 0; nIRecord < hMMFeature->nMaxMRecords; nIRecord++)
3642 : {
3643 237 : if (!hMMFeature->pRecords[nIRecord].pField)
3644 25 : continue;
3645 4502 : for (nIField = 0; nIField < hMMFeature->pRecords[nIRecord].nMaxField;
3646 4290 : nIField++)
3647 : {
3648 4290 : if (hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue)
3649 911 : *(hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue) =
3650 : '\0';
3651 4290 : hMMFeature->pRecords[nIRecord].pField[nIField].bIsValid = 0;
3652 : }
3653 212 : hMMFeature->pRecords[nIRecord].nNumField = 0;
3654 : }
3655 207 : hMMFeature->nNumMRecords = 0;
3656 : }
3657 :
3658 : // Destroys all allocated memory
3659 201 : void MMDestroyFeature(struct MiraMonFeature *hMMFeature)
3660 : {
3661 201 : if (hMMFeature->pCoord)
3662 : {
3663 65 : free_function(hMMFeature->pCoord);
3664 65 : hMMFeature->pCoord = nullptr;
3665 : }
3666 201 : if (hMMFeature->pZCoord)
3667 : {
3668 65 : free_function(hMMFeature->pZCoord);
3669 65 : hMMFeature->pZCoord = nullptr;
3670 : }
3671 201 : if (hMMFeature->pNCoordRing)
3672 : {
3673 65 : free_function(hMMFeature->pNCoordRing);
3674 65 : hMMFeature->pNCoordRing = nullptr;
3675 : }
3676 :
3677 201 : if (hMMFeature->flag_VFG)
3678 : {
3679 27 : free_function(hMMFeature->flag_VFG);
3680 27 : hMMFeature->flag_VFG = nullptr;
3681 : }
3682 :
3683 201 : if (hMMFeature->pRecords)
3684 : {
3685 : MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord;
3686 : MM_EXT_DBF_N_FIELDS nIField;
3687 :
3688 258 : for (nIRecord = 0; nIRecord < hMMFeature->nMaxMRecords; nIRecord++)
3689 : {
3690 176 : if (!hMMFeature->pRecords[nIRecord].pField)
3691 75 : continue;
3692 101 : for (nIField = 0;
3693 2251 : nIField < hMMFeature->pRecords[nIRecord].nMaxField; nIField++)
3694 : {
3695 2150 : if (hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue)
3696 421 : free_function(hMMFeature->pRecords[nIRecord]
3697 : .pField[nIField]
3698 : .pDinValue);
3699 : }
3700 101 : free_function(hMMFeature->pRecords[nIRecord].pField);
3701 : }
3702 82 : free_function(hMMFeature->pRecords);
3703 82 : hMMFeature->pRecords = nullptr;
3704 : }
3705 :
3706 201 : hMMFeature->nNRings = 0;
3707 201 : hMMFeature->nNumMRecords = 0;
3708 201 : hMMFeature->nMaxMRecords = 0;
3709 201 : }
3710 :
3711 : // Creates a MiraMon polygon, multipolygon, or linestring (arc) feature.
3712 89 : static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer,
3713 : struct MiraMonFeature *hMMFeature)
3714 : {
3715 89 : double *pZ = nullptr;
3716 : struct MM_POINT_2D *pCoord, *pCoordReal;
3717 : MM_POLYGON_RINGS_COUNT nIPart;
3718 : MM_N_VERTICES_TYPE nIVertice;
3719 : double dtempx, dtempy;
3720 : MM_POLYGON_RINGS_COUNT nExternalRingsCount;
3721 89 : struct MM_PH *pCurrentPolHeader = nullptr;
3722 : struct MM_AH *pCurrentArcHeader;
3723 : // To access how many points have been stored in the last stringline
3724 89 : struct MM_AH *pLastArcHeader = nullptr;
3725 89 : struct MM_NH *pCurrentNodeHeader, *pCurrentNodeHeaderPlus1 = nullptr;
3726 : uint32_t UnsignedLongNumber;
3727 : struct MiraMonArcLayer *pMMArc;
3728 : struct MiraMonNodeLayer *pMMNode;
3729 : struct MM_TH *pArcTopHeader;
3730 : struct MM_TH *pNodeTopHeader;
3731 89 : char VFG = 0;
3732 : MM_FILE_OFFSET nOffsetTmp;
3733 89 : struct MM_ZD *pZDesc = nullptr;
3734 : struct MM_FLUSH_INFO *pFlushAL, *pFlushNL, *pFlushZL, *pFlushPS, *pFlushPAL;
3735 89 : MM_N_VERTICES_TYPE nPolVertices = 0;
3736 : MM_BOOLEAN bReverseArc;
3737 89 : int prevCoord = -1;
3738 89 : MM_BOOLEAN bPolZeroJustCreated = FALSE;
3739 :
3740 89 : if (!hMiraMonLayer)
3741 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
3742 :
3743 89 : if (!hMMFeature)
3744 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
3745 :
3746 : // Setting pointer to 3D structure (if exists).
3747 89 : if (hMiraMonLayer->TopHeader.bIs3d)
3748 89 : pZ = hMMFeature->pZCoord;
3749 :
3750 : // Setting pointers to arc/node structures.
3751 89 : if (hMiraMonLayer->bIsPolygon)
3752 : {
3753 41 : pMMArc = &hMiraMonLayer->MMPolygon.MMArc;
3754 41 : pArcTopHeader = &hMiraMonLayer->MMPolygon.TopArcHeader;
3755 :
3756 41 : pMMNode = &hMiraMonLayer->MMPolygon.MMArc.MMNode;
3757 41 : pNodeTopHeader = &hMiraMonLayer->MMPolygon.MMArc.TopNodeHeader;
3758 : }
3759 : else
3760 : {
3761 48 : pMMArc = &hMiraMonLayer->MMArc;
3762 48 : pArcTopHeader = &hMiraMonLayer->TopHeader;
3763 :
3764 48 : pMMNode = &hMiraMonLayer->MMArc.MMNode;
3765 48 : pNodeTopHeader = &hMiraMonLayer->MMArc.TopNodeHeader;
3766 : }
3767 :
3768 : // Setting pointers to polygon structures
3769 89 : if (hMiraMonLayer->bIsPolygon)
3770 : {
3771 41 : if (MMResizePolHeaderPointer(&hMiraMonLayer->MMPolygon.pPolHeader,
3772 41 : &hMiraMonLayer->MMPolygon.nMaxPolHeader,
3773 : hMiraMonLayer->TopHeader.nElemCount,
3774 : MM_INCR_NUMBER_OF_POLYGONS, 0))
3775 : {
3776 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
3777 : "Memory error in MiraMon "
3778 : "driver (MMResizePolHeaderPointer())");
3779 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
3780 : }
3781 :
3782 41 : pCurrentPolHeader = hMiraMonLayer->MMPolygon.pPolHeader +
3783 41 : hMiraMonLayer->TopHeader.nElemCount;
3784 41 : MMInitBoundingBox(&pCurrentPolHeader->dfBB);
3785 :
3786 41 : pCurrentPolHeader->dfPerimeter = 0;
3787 41 : pCurrentPolHeader->dfArea = 0L;
3788 : }
3789 :
3790 : // Setting flushes to all sections described in
3791 : // format specifications document.
3792 89 : pFlushAL = &pMMArc->FlushAL;
3793 89 : pFlushNL = &pMMNode->FlushNL;
3794 89 : pFlushZL = &pMMArc->pZSection.FlushZL;
3795 89 : pFlushPS = &hMiraMonLayer->MMPolygon.FlushPS;
3796 89 : pFlushPAL = &hMiraMonLayer->MMPolygon.FlushPAL;
3797 :
3798 89 : pFlushNL->pBlockWhereToSaveOrRead = (void *)pMMNode->pNL;
3799 89 : pFlushAL->pBlockWhereToSaveOrRead = (void *)pMMArc->pAL;
3800 89 : if (hMiraMonLayer->TopHeader.bIs3d)
3801 89 : pFlushZL->pBlockWhereToSaveOrRead = (void *)pMMArc->pZSection.pZL;
3802 89 : if (hMiraMonLayer->bIsPolygon)
3803 : {
3804 41 : pFlushPS->pBlockWhereToSaveOrRead =
3805 41 : (void *)hMiraMonLayer->MMPolygon.pPS;
3806 41 : pFlushPAL->pBlockWhereToSaveOrRead =
3807 41 : (void *)hMiraMonLayer->MMPolygon.pPAL;
3808 : }
3809 :
3810 : // Creation of the MiraMon extended database
3811 89 : if (!hMiraMonLayer->bIsPolygon)
3812 : {
3813 48 : if (hMiraMonLayer->TopHeader.nElemCount == 0)
3814 : {
3815 30 : MMCPLDebug("MiraMon", "Creating MiraMon database");
3816 30 : if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord))
3817 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
3818 30 : MMCPLDebug("MiraMon", "MiraMon database created. "
3819 : "Creating features...");
3820 : }
3821 : }
3822 : else
3823 : { // Universal polygon has been created
3824 41 : if (hMiraMonLayer->TopHeader.nElemCount == 1)
3825 : {
3826 27 : MMCPLDebug("MiraMon", "Creating MiraMon database");
3827 27 : if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord))
3828 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
3829 27 : MMCPLDebug("MiraMon", "MiraMon database created. "
3830 : "Creating features...");
3831 :
3832 : // Universal polygon have a record with ID_GRAFIC=0 and blancs
3833 27 : if (MMAddPolygonRecordToMMDB(hMiraMonLayer, nullptr, 0, 0, nullptr))
3834 : {
3835 : // Rare case where polygon zero creates the database
3836 : // but some error occurs in the creation of the polygon zero.
3837 : // The database must be destroyed and created again
3838 : // next time the polygon zero is created.
3839 0 : MMCloseMMBD_XP(hMiraMonLayer);
3840 0 : MMDestroyMMDB(hMiraMonLayer);
3841 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
3842 : }
3843 27 : bPolZeroJustCreated = TRUE;
3844 : }
3845 : }
3846 :
3847 : // Checking if its possible continue writing the file due
3848 : // to version limitations.
3849 89 : if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION)
3850 : {
3851 : MM_FILE_OFFSET nNodeOffset, nArcOffset;
3852 : MM_INTERNAL_FID nArcElemCount, nNodeElemCount;
3853 75 : nNodeOffset = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
3854 75 : nArcOffset = pMMArc->nOffsetArc;
3855 :
3856 75 : nArcElemCount = pArcTopHeader->nElemCount;
3857 75 : nNodeElemCount = pNodeTopHeader->nElemCount;
3858 162 : for (nIPart = 0; nIPart < hMMFeature->nNRings; nIPart++,
3859 87 : nArcElemCount++,
3860 87 : nNodeElemCount += (hMiraMonLayer->bIsPolygon ? 1 : 2))
3861 : {
3862 : // There is space for the element that is going to be written?
3863 : // Polygon or arc
3864 87 : if (MMCheckVersionForFID(hMiraMonLayer,
3865 : hMiraMonLayer->TopHeader.nElemCount))
3866 : {
3867 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
3868 : "Error in MMCheckVersionForFID() (1)");
3869 0 : return MM_STOP_WRITING_FEATURES;
3870 : }
3871 :
3872 : // Arc if there is no polygon
3873 87 : if (MMCheckVersionForFID(hMiraMonLayer, nArcElemCount))
3874 : {
3875 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
3876 : "Error in MMCheckVersionForFID() (2)");
3877 0 : return MM_STOP_WRITING_FEATURES;
3878 : }
3879 :
3880 : // Nodes
3881 87 : if (MMCheckVersionForFID(hMiraMonLayer, nNodeElemCount))
3882 : {
3883 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
3884 : "Error in MMCheckVersionForFID() (3)");
3885 0 : return MM_STOP_WRITING_FEATURES;
3886 : }
3887 :
3888 : // There is space for the last node(s) that is(are) going to be written?
3889 87 : if (!hMiraMonLayer->bIsPolygon)
3890 : {
3891 40 : if (MMCheckVersionForFID(hMiraMonLayer, nNodeElemCount + 1))
3892 : {
3893 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
3894 : "Error in MMCheckVersionForFID() (4)");
3895 0 : return MM_STOP_WRITING_FEATURES;
3896 : }
3897 : }
3898 :
3899 : // Checking offsets
3900 : // AL: check the last point
3901 87 : if (MMCheckVersionOffset(hMiraMonLayer, nArcOffset))
3902 : {
3903 0 : MMCPLDebug("MiraMon", "Error in MMCheckVersionOffset() (0)");
3904 0 : return MM_STOP_WRITING_FEATURES;
3905 : }
3906 : // Setting next offset
3907 87 : nArcOffset +=
3908 87 : (hMMFeature->pNCoordRing[nIPart]) * pMMArc->nALElementSize;
3909 :
3910 : // NL: check the last node
3911 87 : if (hMiraMonLayer->bIsPolygon)
3912 47 : nNodeOffset += (hMMFeature->nNRings) * MM_SIZE_OF_NL_32BITS;
3913 : else
3914 40 : nNodeOffset += (2 * hMMFeature->nNRings) * MM_SIZE_OF_NL_32BITS;
3915 :
3916 87 : if (MMCheckVersionOffset(hMiraMonLayer, nNodeOffset))
3917 : {
3918 0 : MMCPLDebug("MiraMon", "Error in MMCheckVersionOffset() (1)");
3919 0 : return MM_STOP_WRITING_FEATURES;
3920 : }
3921 : // Setting next offset
3922 87 : nNodeOffset += MM_SIZE_OF_NL_32BITS;
3923 :
3924 87 : if (!hMiraMonLayer->bIsPolygon)
3925 : {
3926 40 : if (MMCheckVersionOffset(hMiraMonLayer, nNodeOffset))
3927 : {
3928 0 : MMCPLDebug("MiraMon",
3929 : "Error in MMCheckVersionOffset() (2)");
3930 0 : return MM_STOP_WRITING_FEATURES;
3931 : }
3932 : // Setting next offset
3933 40 : nNodeOffset += MM_SIZE_OF_NL_32BITS;
3934 : }
3935 :
3936 : // Where 3D part is going to start
3937 87 : if (hMiraMonLayer->TopHeader.bIs3d)
3938 : {
3939 87 : if (nArcElemCount == 0)
3940 : {
3941 53 : if (MMCheckVersionFor3DOffset(hMiraMonLayer,
3942 : nArcElemCount + 1, 0, 0))
3943 0 : return MM_STOP_WRITING_FEATURES;
3944 : }
3945 : else
3946 : {
3947 34 : pZDesc = pMMArc->pZSection.pZDescription;
3948 34 : if (!pZDesc)
3949 : {
3950 0 : MMCPLError(
3951 : CE_Failure, CPLE_ObjectNull,
3952 : "Error: pZDescription should not be nullptr");
3953 0 : return MM_STOP_WRITING_FEATURES;
3954 : }
3955 :
3956 34 : if (pZDesc[nArcElemCount - 1].nZCount < 0)
3957 : {
3958 : // One altitude was written on last element
3959 13 : if (MMCheckVersionFor3DOffset(
3960 : hMiraMonLayer, nArcElemCount + 1, nArcOffset,
3961 13 : pZDesc[nArcElemCount - 1].nOffsetZ +
3962 : sizeof(*pZ)))
3963 0 : return MM_STOP_WRITING_FEATURES;
3964 : }
3965 : else
3966 : {
3967 : // One for each vertice altitude was written on last element
3968 21 : if (MMCheckVersionFor3DOffset(
3969 : hMiraMonLayer, nArcElemCount + 1, nArcOffset,
3970 21 : pZDesc[nArcElemCount - 1].nOffsetZ +
3971 21 : sizeof(*pZ) * (pMMArc->pArcHeader +
3972 : (nArcElemCount - 1))
3973 21 : ->nElemCount))
3974 0 : return MM_STOP_WRITING_FEATURES;
3975 : }
3976 : }
3977 : }
3978 : }
3979 : }
3980 :
3981 : // Going through parts of the feature.
3982 89 : nExternalRingsCount = 0;
3983 89 : pCoord = hMMFeature->pCoord;
3984 :
3985 89 : if (!pCoord)
3986 : {
3987 0 : if (bPolZeroJustCreated)
3988 : {
3989 : // Rare case where polygon zero creates the database
3990 : // but some error occurs in the creation of the polygon zero.
3991 : // The database must be destroyed and created again
3992 : // next time the polygon zero is created.
3993 0 : MMCloseMMBD_XP(hMiraMonLayer);
3994 0 : MMDestroyMMDB(hMiraMonLayer);
3995 : }
3996 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
3997 : }
3998 :
3999 : // Doing real job
4000 190 : for (nIPart = 0; nIPart < hMMFeature->nNRings; nIPart++,
4001 101 : pArcTopHeader->nElemCount++,
4002 101 : pNodeTopHeader->nElemCount += (hMiraMonLayer->bIsPolygon ? 1 : 2))
4003 : {
4004 : // Resize structures if necessary
4005 101 : if (MMResizeArcHeaderPointer(
4006 101 : &pMMArc->pArcHeader, &pMMArc->nMaxArcHeader,
4007 101 : pArcTopHeader->nElemCount + 1, MM_INCR_NUMBER_OF_ARCS, 0))
4008 : {
4009 0 : MMCPLDebug("MiraMon", "Error in MMResizeArcHeaderPointer()");
4010 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4011 : "Memory error in MiraMon "
4012 : "driver (MMCreateFeaturePolOrArc())");
4013 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4014 : }
4015 101 : if (MMResizeNodeHeaderPointer(
4016 101 : &pMMNode->pNodeHeader, &pMMNode->nMaxNodeHeader,
4017 101 : hMiraMonLayer->bIsPolygon ? pNodeTopHeader->nElemCount + 1
4018 48 : : pNodeTopHeader->nElemCount + 2,
4019 : MM_INCR_NUMBER_OF_NODES, 0))
4020 : {
4021 0 : MMCPLDebug("MiraMon", "Error in MMResizeNodeHeaderPointer()");
4022 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4023 : "Memory error in MiraMon "
4024 : "driver (MMCreateFeaturePolOrArc())");
4025 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4026 : }
4027 :
4028 101 : if (hMiraMonLayer->TopHeader.bIs3d)
4029 : {
4030 101 : if (MMResizeZSectionDescrPointer(
4031 : &pMMArc->pZSection.pZDescription,
4032 : &pMMArc->pZSection.nMaxZDescription, pMMArc->nMaxArcHeader,
4033 : MM_INCR_NUMBER_OF_ARCS, 0))
4034 : {
4035 0 : MMCPLDebug("MiraMon",
4036 : "Error in MMResizeZSectionDescrPointer()");
4037 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4038 : "Memory error in MiraMon "
4039 : "driver (MMCreateFeaturePolOrArc())");
4040 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4041 : }
4042 101 : pZDesc = pMMArc->pZSection.pZDescription;
4043 : }
4044 :
4045 : // Setting pointers to current headers
4046 101 : pCurrentArcHeader = pMMArc->pArcHeader + pArcTopHeader->nElemCount;
4047 101 : MMInitBoundingBox(&pCurrentArcHeader->dfBB);
4048 :
4049 101 : pCurrentNodeHeader = pMMNode->pNodeHeader + pNodeTopHeader->nElemCount;
4050 101 : if (!hMiraMonLayer->bIsPolygon)
4051 48 : pCurrentNodeHeaderPlus1 = pCurrentNodeHeader + 1;
4052 :
4053 : // Initializing feature information (section AH/PH)
4054 101 : pCurrentArcHeader->nElemCount = hMMFeature->pNCoordRing[nIPart];
4055 101 : pCurrentArcHeader->dfLength = 0.0;
4056 101 : pCurrentArcHeader->nOffset =
4057 101 : pFlushAL->TotalSavedBytes + pFlushAL->nNumBytes;
4058 :
4059 : // Dumping vertices and calculating stuff that
4060 : // MiraMon needs (longitude/perimeter, area)
4061 101 : bReverseArc = FALSE;
4062 101 : if (hMiraMonLayer->bIsPolygon)
4063 : {
4064 53 : VFG = hMMFeature->flag_VFG[nIPart];
4065 53 : bReverseArc = (VFG & MM_ROTATE_ARC) ? TRUE : FALSE;
4066 : }
4067 :
4068 101 : if (bReverseArc)
4069 : {
4070 1 : prevCoord = 1; // to find previous coordinate
4071 1 : pCoordReal = pCoord + pCurrentArcHeader->nElemCount - 1;
4072 : }
4073 : else
4074 : {
4075 100 : prevCoord = -1; // to find previous coordinate
4076 100 : pCoordReal = pCoord;
4077 : }
4078 :
4079 569 : for (nIVertice = 0; nIVertice < pCurrentArcHeader->nElemCount;
4080 468 : nIVertice++, (bReverseArc) ? pCoordReal-- : pCoordReal++)
4081 : {
4082 : // Writing the arc in the normal way
4083 468 : pFlushAL->SizeOfBlockToBeSaved = sizeof(pCoordReal->dfX);
4084 468 : pFlushAL->pBlockToBeSaved = (void *)&(pCoord + nIVertice)->dfX;
4085 468 : if (MMAppendBlockToBuffer(pFlushAL))
4086 : {
4087 0 : MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer() (1)");
4088 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4089 : }
4090 :
4091 468 : pFlushAL->pBlockToBeSaved = (void *)&(pCoord + nIVertice)->dfY;
4092 468 : if (MMAppendBlockToBuffer(pFlushAL))
4093 : {
4094 0 : MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer() (2)");
4095 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4096 : }
4097 :
4098 : // Calculating stuff using the inverse coordinates if it's needed
4099 468 : MMUpdateBoundingBoxXY(&pCurrentArcHeader->dfBB, pCoordReal);
4100 468 : if (nIVertice == 0 ||
4101 367 : nIVertice == pCurrentArcHeader->nElemCount - 1)
4102 202 : MMUpdateBoundingBoxXY(&pNodeTopHeader->hBB, pCoordReal);
4103 468 : if (nIVertice > 0)
4104 : {
4105 367 : dtempx = pCoordReal->dfX - (pCoordReal + prevCoord)->dfX;
4106 367 : dtempy = pCoordReal->dfY - (pCoordReal + prevCoord)->dfY;
4107 367 : pCurrentArcHeader->dfLength +=
4108 367 : sqrt(dtempx * dtempx + dtempy * dtempy);
4109 367 : if (hMiraMonLayer->bIsPolygon && pCurrentPolHeader)
4110 : {
4111 262 : pCurrentPolHeader->dfArea +=
4112 262 : (pCoordReal->dfX * (pCoordReal + prevCoord)->dfY -
4113 262 : (pCoordReal + prevCoord)->dfX * pCoordReal->dfY);
4114 : }
4115 : }
4116 : }
4117 101 : if (bReverseArc)
4118 1 : pCoord = pCoordReal + pCurrentArcHeader->nElemCount + 1;
4119 : else
4120 100 : pCoord += pCurrentArcHeader->nElemCount;
4121 :
4122 101 : nPolVertices += pCurrentArcHeader->nElemCount;
4123 :
4124 : // Updating bounding boxes
4125 101 : MMUpdateBoundingBox(&pArcTopHeader->hBB, &pCurrentArcHeader->dfBB);
4126 101 : if (hMiraMonLayer->bIsPolygon)
4127 53 : MMUpdateBoundingBox(&hMiraMonLayer->TopHeader.hBB,
4128 : &pCurrentArcHeader->dfBB);
4129 :
4130 101 : pMMArc->nOffsetArc +=
4131 101 : (pCurrentArcHeader->nElemCount) * pMMArc->nALElementSize;
4132 :
4133 101 : pCurrentArcHeader->nFirstIdNode = (2 * pArcTopHeader->nElemCount);
4134 101 : if (hMiraMonLayer->bIsPolygon)
4135 : {
4136 53 : pCurrentArcHeader->nFirstIdNode = pArcTopHeader->nElemCount;
4137 53 : pCurrentArcHeader->nLastIdNode = pArcTopHeader->nElemCount;
4138 : }
4139 : else
4140 : {
4141 48 : pCurrentArcHeader->nFirstIdNode = (2 * pArcTopHeader->nElemCount);
4142 48 : pCurrentArcHeader->nLastIdNode =
4143 48 : (2 * pArcTopHeader->nElemCount + 1);
4144 : }
4145 101 : if (MMAddArcRecordToMMDB(hMiraMonLayer, hMMFeature,
4146 : pArcTopHeader->nElemCount, pCurrentArcHeader))
4147 : {
4148 0 : MMCPLDebug("MiraMon", "Error in MMAddArcRecordToMMDB()");
4149 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4150 : }
4151 :
4152 : // Node Stuff: writing NL section
4153 101 : pCurrentNodeHeader->nArcsCount = 1;
4154 101 : if (hMiraMonLayer->bIsPolygon)
4155 53 : pCurrentNodeHeader->cNodeType = MM_RING_NODE;
4156 : else
4157 48 : pCurrentNodeHeader->cNodeType = MM_FINAL_NODE;
4158 :
4159 101 : pCurrentNodeHeader->nOffset =
4160 101 : pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
4161 101 : if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushNL,
4162 : &UnsignedLongNumber,
4163 : pArcTopHeader->nElemCount))
4164 : {
4165 0 : MMCPLDebug("MiraMon",
4166 : "Error in MMAppendIntegerDependingOnVersion()");
4167 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4168 : }
4169 :
4170 : // 8bytes alignment
4171 101 : nOffsetTmp = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
4172 101 : MMGetOffsetAlignedTo8(&nOffsetTmp);
4173 101 : if (nOffsetTmp != pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes)
4174 : {
4175 87 : pFlushNL->SizeOfBlockToBeSaved =
4176 87 : (size_t)(nOffsetTmp -
4177 87 : (pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes));
4178 87 : pFlushNL->pBlockToBeSaved = (void *)nullptr;
4179 87 : if (MMAppendBlockToBuffer(pFlushNL))
4180 : {
4181 0 : MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer() (3)");
4182 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4183 : }
4184 : }
4185 101 : if (MMAddNodeRecordToMMDB(hMiraMonLayer, pNodeTopHeader->nElemCount,
4186 : pCurrentNodeHeader))
4187 : {
4188 0 : MMCPLDebug("MiraMon", "Error in MMAddNodeRecordToMMDB()");
4189 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4190 : }
4191 :
4192 101 : if (!hMiraMonLayer->bIsPolygon)
4193 : {
4194 48 : pCurrentNodeHeaderPlus1->nArcsCount = 1;
4195 48 : if (hMiraMonLayer->bIsPolygon)
4196 0 : pCurrentNodeHeaderPlus1->cNodeType = MM_RING_NODE;
4197 : else
4198 48 : pCurrentNodeHeaderPlus1->cNodeType = MM_FINAL_NODE;
4199 :
4200 48 : pCurrentNodeHeaderPlus1->nOffset =
4201 48 : pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
4202 :
4203 48 : if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushNL,
4204 : &UnsignedLongNumber,
4205 : pArcTopHeader->nElemCount))
4206 : {
4207 0 : MMCPLDebug("MiraMon",
4208 : "Error in MMAppendIntegerDependingOnVersion()");
4209 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4210 : }
4211 :
4212 : // 8bytes alignment
4213 48 : nOffsetTmp = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes;
4214 48 : MMGetOffsetAlignedTo8(&nOffsetTmp);
4215 48 : if (nOffsetTmp != pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes)
4216 : {
4217 40 : pFlushNL->SizeOfBlockToBeSaved =
4218 40 : (size_t)(nOffsetTmp -
4219 40 : (pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes));
4220 40 : pFlushNL->pBlockToBeSaved = (void *)nullptr;
4221 40 : if (MMAppendBlockToBuffer(pFlushNL))
4222 : {
4223 0 : MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer()");
4224 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4225 : }
4226 : }
4227 48 : if (MMAddNodeRecordToMMDB(hMiraMonLayer,
4228 48 : pNodeTopHeader->nElemCount + 1,
4229 : pCurrentNodeHeaderPlus1))
4230 : {
4231 0 : MMCPLDebug("MiraMon", "Error in MMAddNodeRecordToMMDB()");
4232 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4233 : }
4234 : }
4235 :
4236 : // 3D stuff
4237 101 : if (hMiraMonLayer->TopHeader.bIs3d && pZDesc)
4238 : {
4239 101 : pZDesc[pArcTopHeader->nElemCount].dfBBminz =
4240 : STATISTICAL_UNDEF_VALUE;
4241 101 : pZDesc[pArcTopHeader->nElemCount].dfBBmaxz =
4242 : -STATISTICAL_UNDEF_VALUE;
4243 :
4244 : // Number of arc altitudes. If the number of altitudes is
4245 : // positive this indicates the number of altitudes for
4246 : // each vertex of the arc, and all the altitudes of the
4247 : // vertex 0 are written first, then those of the vertex 1,
4248 : // etc. If the number of altitudes is negative this
4249 : // indicates the number of arc altitudes, understanding
4250 : // that all the vertices have the same altitude (it is
4251 : // the case of a contour line, for example).
4252 :
4253 160 : for (nIVertice = 0; nIVertice < pCurrentArcHeader->nElemCount;
4254 59 : nIVertice++, pZ++)
4255 : {
4256 144 : pFlushZL->SizeOfBlockToBeSaved = sizeof(*pZ);
4257 144 : pFlushZL->pBlockToBeSaved = (void *)pZ;
4258 144 : if (MMAppendBlockToBuffer(pFlushZL))
4259 : {
4260 0 : MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer()");
4261 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4262 : }
4263 :
4264 144 : if (pZDesc[pArcTopHeader->nElemCount].dfBBminz > *pZ)
4265 114 : pZDesc[pArcTopHeader->nElemCount].dfBBminz = *pZ;
4266 144 : if (pZDesc[pArcTopHeader->nElemCount].dfBBmaxz < *pZ)
4267 115 : pZDesc[pArcTopHeader->nElemCount].dfBBmaxz = *pZ;
4268 :
4269 144 : if (pMMArc->pZSection.ZHeader.dfBBminz > *pZ)
4270 67 : pMMArc->pZSection.ZHeader.dfBBminz = *pZ;
4271 144 : if (pMMArc->pZSection.ZHeader.dfBBmaxz < *pZ)
4272 66 : pMMArc->pZSection.ZHeader.dfBBmaxz = *pZ;
4273 :
4274 : // Only one altitude (the same for all vertices) is written
4275 144 : if (hMMFeature->bAllZHaveSameValue)
4276 85 : break;
4277 : }
4278 101 : if (hMMFeature->bAllZHaveSameValue)
4279 : {
4280 : // Same altitude for all vertices
4281 85 : pZDesc[pArcTopHeader->nElemCount].nZCount = -1;
4282 : }
4283 : else
4284 : {
4285 : // One different altitude for each vertice
4286 16 : pZDesc[pArcTopHeader->nElemCount].nZCount = 1;
4287 : }
4288 :
4289 101 : if (pArcTopHeader->nElemCount == 0)
4290 57 : pZDesc[pArcTopHeader->nElemCount].nOffsetZ = 0;
4291 : else
4292 : {
4293 44 : pLastArcHeader =
4294 44 : pMMArc->pArcHeader + pArcTopHeader->nElemCount - 1;
4295 :
4296 44 : if (pZDesc[pArcTopHeader->nElemCount - 1].nZCount < 0)
4297 : {
4298 32 : pZDesc[pArcTopHeader->nElemCount].nOffsetZ =
4299 32 : pZDesc[pArcTopHeader->nElemCount - 1].nOffsetZ +
4300 : sizeof(*pZ);
4301 : }
4302 : else
4303 : {
4304 12 : pZDesc[pArcTopHeader->nElemCount].nOffsetZ =
4305 12 : pZDesc[pArcTopHeader->nElemCount - 1].nOffsetZ +
4306 12 : sizeof(*pZ) * (pLastArcHeader->nElemCount);
4307 : }
4308 : }
4309 : }
4310 :
4311 : // Exclusive polygon stuff
4312 101 : if (hMiraMonLayer->bIsPolygon && pCurrentPolHeader)
4313 : {
4314 : // PS SECTION
4315 53 : if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushPS,
4316 : &UnsignedLongNumber, 0))
4317 : {
4318 0 : MMCPLDebug("MiraMon",
4319 : "Error in MMAppendIntegerDependingOnVersion()");
4320 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4321 : }
4322 :
4323 53 : if (MMAppendIntegerDependingOnVersion(
4324 : hMiraMonLayer, pFlushPS, &UnsignedLongNumber,
4325 : hMiraMonLayer->TopHeader.nElemCount))
4326 : {
4327 0 : MMCPLDebug("MiraMon",
4328 : "Error in MMAppendIntegerDependingOnVersion()");
4329 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4330 : }
4331 :
4332 : // PAL SECTION
4333 : // Vertices of rings defining
4334 : // holes in polygons are in a counterclockwise direction.
4335 : // Holes are at the end of all external rings that contain the holes!!
4336 53 : if (VFG & MM_EXTERIOR_ARC_SIDE)
4337 45 : nExternalRingsCount++;
4338 :
4339 53 : pCurrentPolHeader->nArcsCount++;
4340 : //(MM_POLYGON_ARCS_COUNT)hMMFeature->nNRings;
4341 53 : if (VFG & MM_EXTERIOR_ARC_SIDE)
4342 : pCurrentPolHeader
4343 45 : ->nExternalRingsCount++; //= nExternalRingsCount;
4344 :
4345 53 : if (VFG & MM_END_ARC_IN_RING)
4346 53 : pCurrentPolHeader->nRingsCount++; //= hMMFeature->nNRings;
4347 53 : if (nIPart == 0)
4348 : {
4349 41 : pCurrentPolHeader->nOffset =
4350 41 : pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes;
4351 : }
4352 :
4353 53 : if (nIPart == hMMFeature->nNRings - 1)
4354 41 : pCurrentPolHeader->dfArea /= 2;
4355 :
4356 53 : pFlushPAL->SizeOfBlockToBeSaved = 1;
4357 53 : pFlushPAL->pBlockToBeSaved = (void *)&VFG;
4358 53 : if (MMAppendBlockToBuffer(pFlushPAL))
4359 : {
4360 0 : MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer()");
4361 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4362 : }
4363 :
4364 53 : if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushPAL,
4365 : &UnsignedLongNumber,
4366 : pArcTopHeader->nElemCount))
4367 : {
4368 0 : MMCPLDebug("MiraMon",
4369 : "Error in MMAppendIntegerDependingOnVersion()");
4370 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4371 : }
4372 :
4373 : // 8bytes alignment
4374 53 : if (nIPart == hMMFeature->nNRings - 1)
4375 : {
4376 41 : nOffsetTmp = pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes;
4377 41 : MMGetOffsetAlignedTo8(&nOffsetTmp);
4378 :
4379 41 : if (nOffsetTmp !=
4380 41 : pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes)
4381 : {
4382 41 : pFlushPAL->SizeOfBlockToBeSaved =
4383 41 : (size_t)(nOffsetTmp - (pFlushPAL->TotalSavedBytes +
4384 41 : pFlushPAL->nNumBytes));
4385 41 : pFlushPAL->pBlockToBeSaved = (void *)nullptr;
4386 41 : if (MMAppendBlockToBuffer(pFlushPAL))
4387 : {
4388 0 : MMCPLDebug("MiraMon",
4389 : "Error in MMAppendBlockToBuffer()");
4390 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4391 : }
4392 : }
4393 : }
4394 :
4395 53 : MMUpdateBoundingBox(&pCurrentPolHeader->dfBB,
4396 : &pCurrentArcHeader->dfBB);
4397 53 : pCurrentPolHeader->dfPerimeter += pCurrentArcHeader->dfLength;
4398 : }
4399 : }
4400 :
4401 : // Updating element count and if the polygon is multipart.
4402 : // MiraMon does not accept multipoints or multilines, only multipolygons.
4403 89 : if (hMiraMonLayer->bIsPolygon)
4404 : {
4405 41 : if (MMAddPolygonRecordToMMDB(hMiraMonLayer, hMMFeature,
4406 : hMiraMonLayer->TopHeader.nElemCount,
4407 : nPolVertices, pCurrentPolHeader))
4408 : {
4409 0 : MMCPLDebug("MiraMon", "Error in MMAddPolygonRecordToMMDB()");
4410 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4411 : }
4412 41 : hMiraMonLayer->TopHeader.nElemCount++;
4413 :
4414 41 : if (nExternalRingsCount > 1)
4415 4 : hMiraMonLayer->TopHeader.bIsMultipolygon = TRUE;
4416 : }
4417 :
4418 89 : return MM_CONTINUE_WRITING_FEATURES;
4419 : } // End of de MMCreateFeaturePolOrArc()
4420 :
4421 : // Creates a MiraMon DBF record when not associated with a geometric feature.
4422 34 : static int MMCreateRecordDBF(struct MiraMonVectLayerInfo *hMiraMonLayer,
4423 : struct MiraMonFeature *hMMFeature)
4424 : {
4425 : int result;
4426 :
4427 34 : if (!hMiraMonLayer)
4428 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4429 :
4430 34 : if (hMiraMonLayer->TopHeader.nElemCount == 0)
4431 : {
4432 17 : if (MMCreateMMDB(hMiraMonLayer, nullptr))
4433 : {
4434 0 : MMDestroyMMDB(hMiraMonLayer);
4435 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4436 : }
4437 : }
4438 :
4439 34 : result = MMAddDBFRecordToMMDB(hMiraMonLayer, hMMFeature);
4440 34 : if (result == MM_FATAL_ERROR_WRITING_FEATURES ||
4441 : result == MM_STOP_WRITING_FEATURES)
4442 0 : return result;
4443 :
4444 : // Everything OK.
4445 34 : return MM_CONTINUE_WRITING_FEATURES;
4446 : } // End of de MMCreateRecordDBF()
4447 :
4448 : // Creates a MiraMon point feature.
4449 87 : static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer,
4450 : struct MiraMonFeature *hMMFeature)
4451 : {
4452 87 : double *pZ = nullptr;
4453 : struct MM_POINT_2D *pCoord;
4454 : MM_POLYGON_RINGS_COUNT nIPart;
4455 : MM_N_VERTICES_TYPE nIVertice, nCoord;
4456 87 : struct MM_ZD *pZDescription = nullptr;
4457 : MM_INTERNAL_FID nElemCount;
4458 : int result;
4459 :
4460 87 : if (!hMiraMonLayer)
4461 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4462 :
4463 87 : if (!hMMFeature)
4464 0 : return MM_STOP_WRITING_FEATURES;
4465 :
4466 87 : if (hMiraMonLayer->TopHeader.bIs3d)
4467 87 : pZ = hMMFeature->pZCoord;
4468 :
4469 87 : nElemCount = hMiraMonLayer->TopHeader.nElemCount;
4470 174 : for (nIPart = 0, pCoord = hMMFeature->pCoord; nIPart < hMMFeature->nNRings;
4471 87 : nIPart++, nElemCount++)
4472 : {
4473 87 : nCoord = hMMFeature->pNCoordRing[nIPart];
4474 :
4475 : // Checking if its possible continue writing the file due
4476 : // to version limitations.
4477 87 : if (MMCheckVersionForFID(hMiraMonLayer,
4478 87 : hMiraMonLayer->TopHeader.nElemCount + nCoord))
4479 : {
4480 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
4481 : "Error in MMCheckVersionForFID() (5)");
4482 0 : return MM_STOP_WRITING_FEATURES;
4483 : }
4484 :
4485 87 : if (hMiraMonLayer->TopHeader.bIs3d)
4486 : {
4487 87 : if (nElemCount == 0)
4488 : {
4489 33 : if (MMCheckVersionFor3DOffset(hMiraMonLayer, (nElemCount + 1),
4490 : 0, 0))
4491 0 : return MM_STOP_WRITING_FEATURES;
4492 : }
4493 : else
4494 : {
4495 54 : pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription;
4496 54 : if (!pZDescription)
4497 : {
4498 0 : MMCPLError(CE_Failure, CPLE_ObjectNull,
4499 : "Error: pZDescription should not be nullptr");
4500 0 : return MM_STOP_WRITING_FEATURES;
4501 : }
4502 :
4503 54 : if (MMCheckVersionFor3DOffset(
4504 : hMiraMonLayer, nElemCount + 1, 0,
4505 54 : pZDescription[nElemCount - 1].nOffsetZ + sizeof(*pZ)))
4506 0 : return MM_STOP_WRITING_FEATURES;
4507 : }
4508 : }
4509 :
4510 : // Doing real job
4511 : // Memory issues
4512 87 : if (hMiraMonLayer->TopHeader.bIs3d && pZ)
4513 : {
4514 87 : if (MMResizeZSectionDescrPointer(
4515 : &hMiraMonLayer->MMPoint.pZSection.pZDescription,
4516 : &hMiraMonLayer->MMPoint.pZSection.nMaxZDescription,
4517 : nElemCount, MM_INCR_NUMBER_OF_POINTS, 0))
4518 : {
4519 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4520 : "Memory error in MiraMon "
4521 : "driver (MMCreateFeaturePoint())");
4522 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4523 : }
4524 :
4525 87 : pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription;
4526 87 : if (!pZDescription)
4527 : {
4528 0 : MMCPLError(CE_Failure, CPLE_ObjectNull,
4529 : "Error: pZDescription should not be nullptr");
4530 0 : return MM_STOP_WRITING_FEATURES;
4531 : }
4532 :
4533 87 : pZDescription[nElemCount].dfBBminz = *pZ;
4534 87 : pZDescription[nElemCount].dfBBmaxz = *pZ;
4535 :
4536 87 : if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz > *pZ)
4537 40 : hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz = *pZ;
4538 87 : if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz < *pZ)
4539 37 : hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz = *pZ;
4540 :
4541 : // Specification ask for a negative number.
4542 87 : pZDescription[nElemCount].nZCount = -1;
4543 87 : if (nElemCount == 0)
4544 33 : pZDescription[nElemCount].nOffsetZ = 0;
4545 : else
4546 54 : pZDescription[nElemCount].nOffsetZ =
4547 54 : pZDescription[nElemCount - 1].nOffsetZ + sizeof(*pZ);
4548 : }
4549 :
4550 : // Flush settings
4551 87 : hMiraMonLayer->MMPoint.FlushTL.pBlockWhereToSaveOrRead =
4552 87 : (void *)hMiraMonLayer->MMPoint.pTL;
4553 87 : if (hMiraMonLayer->TopHeader.bIs3d)
4554 87 : hMiraMonLayer->MMPoint.pZSection.FlushZL.pBlockWhereToSaveOrRead =
4555 87 : (void *)hMiraMonLayer->MMPoint.pZSection.pZL;
4556 :
4557 : // Dump point or points (MiraMon does not have multiple points)
4558 174 : for (nIVertice = 0; nIVertice < nCoord; nIVertice++, pCoord++)
4559 : {
4560 : // Updating the bounding box of the layer
4561 87 : MMUpdateBoundingBoxXY(&hMiraMonLayer->TopHeader.hBB, pCoord);
4562 :
4563 : // Adding the point at the memory block
4564 87 : hMiraMonLayer->MMPoint.FlushTL.SizeOfBlockToBeSaved =
4565 : sizeof(pCoord->dfX);
4566 87 : hMiraMonLayer->MMPoint.FlushTL.pBlockToBeSaved =
4567 87 : (void *)&pCoord->dfX;
4568 87 : if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL))
4569 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4570 87 : hMiraMonLayer->MMPoint.FlushTL.pBlockToBeSaved =
4571 87 : (void *)&pCoord->dfY;
4572 87 : if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL))
4573 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4574 :
4575 : // Adding the 3D part, if exists, at the memory block
4576 87 : if (hMiraMonLayer->TopHeader.bIs3d && pZ)
4577 : {
4578 87 : hMiraMonLayer->MMPoint.pZSection.FlushZL.SizeOfBlockToBeSaved =
4579 : sizeof(*pZ);
4580 87 : hMiraMonLayer->MMPoint.pZSection.FlushZL.pBlockToBeSaved =
4581 : (void *)pZ;
4582 87 : if (MMAppendBlockToBuffer(
4583 : &hMiraMonLayer->MMPoint.pZSection.FlushZL))
4584 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4585 :
4586 87 : if (!pZDescription)
4587 : {
4588 0 : MMCPLError(CE_Failure, CPLE_ObjectNull,
4589 : "Error: pZDescription should not be nullptr");
4590 0 : return MM_STOP_WRITING_FEATURES;
4591 : }
4592 :
4593 87 : if (pZDescription[nElemCount].dfBBminz > *pZ)
4594 0 : pZDescription[nElemCount].dfBBminz = *pZ;
4595 87 : if (pZDescription[nElemCount].dfBBmaxz < *pZ)
4596 0 : pZDescription[nElemCount].dfBBmaxz = *pZ;
4597 :
4598 87 : if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz > *pZ)
4599 0 : hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz = *pZ;
4600 87 : if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz < *pZ)
4601 0 : hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz = *pZ;
4602 :
4603 87 : pZ++;
4604 : }
4605 : }
4606 :
4607 87 : if (hMiraMonLayer->TopHeader.nElemCount == 0)
4608 : {
4609 33 : if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord))
4610 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4611 : }
4612 :
4613 87 : result = MMAddPointRecordToMMDB(hMiraMonLayer, hMMFeature, nElemCount);
4614 87 : if (result == MM_FATAL_ERROR_WRITING_FEATURES ||
4615 : result == MM_STOP_WRITING_FEATURES)
4616 0 : return result;
4617 : }
4618 : // Updating nElemCount at the header of the layer
4619 87 : hMiraMonLayer->TopHeader.nElemCount = nElemCount;
4620 :
4621 : // Everything OK.
4622 87 : return MM_CONTINUE_WRITING_FEATURES;
4623 : } // End of de MMCreateFeaturePoint()
4624 :
4625 : // Checks whether a given Feature ID (FID) exceeds the maximum allowed
4626 : // index for 2 GB vectors in a specific MiraMon layer.
4627 793 : int MMCheckVersionForFID(struct MiraMonVectLayerInfo *hMiraMonLayer,
4628 : MM_INTERNAL_FID FID)
4629 : {
4630 793 : if (!hMiraMonLayer)
4631 0 : return 1;
4632 :
4633 793 : if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION)
4634 56 : return 0;
4635 :
4636 737 : if (FID >= MAXIMUM_OBJECT_INDEX_IN_2GB_VECTORS)
4637 0 : return 1;
4638 737 : return 0;
4639 : }
4640 :
4641 : // Checks whether a given offset exceeds the maximum allowed
4642 : // index for 2 GB vectors in a specific MiraMon layer.
4643 214 : int MMCheckVersionOffset(struct MiraMonVectLayerInfo *hMiraMonLayer,
4644 : MM_FILE_OFFSET OffsetToCheck)
4645 : {
4646 214 : if (!hMiraMonLayer)
4647 0 : return 1;
4648 :
4649 : // Checking if the final version is 1.1 or 2.0
4650 214 : if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION)
4651 0 : return 0;
4652 :
4653 : // User decided that if necessary, output version can be 2.0
4654 214 : if (OffsetToCheck < MAXIMUM_OFFSET_IN_2GB_VECTORS)
4655 214 : return 0;
4656 :
4657 0 : return 1;
4658 : }
4659 :
4660 : // Checks whether a given offset in 3D section exceeds the maximum allowed
4661 : // index for 2 GB vectors in a specific MiraMon layer.
4662 174 : int MMCheckVersionFor3DOffset(struct MiraMonVectLayerInfo *hMiraMonLayer,
4663 : MM_INTERNAL_FID nElemCount,
4664 : MM_FILE_OFFSET nOffsetAL,
4665 : MM_FILE_OFFSET nZLOffset)
4666 : {
4667 : MM_FILE_OFFSET LastOffset;
4668 :
4669 174 : if (!hMiraMonLayer)
4670 0 : return 1;
4671 :
4672 : // Checking if the final version is 1.1 or 2.0
4673 174 : if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION)
4674 6 : return 0;
4675 :
4676 : // User decided that if necessary, output version can be 2.0
4677 168 : if (hMiraMonLayer->bIsPoint)
4678 81 : LastOffset = MM_HEADER_SIZE_32_BITS + nElemCount * MM_SIZE_OF_TL;
4679 : else // Arc case
4680 : {
4681 87 : LastOffset = MM_HEADER_SIZE_32_BITS +
4682 87 : nElemCount * MM_SIZE_OF_AH_32BITS + +nOffsetAL;
4683 : }
4684 :
4685 168 : LastOffset += MM_SIZE_OF_ZH;
4686 168 : LastOffset += nElemCount * MM_SIZE_OF_ZD_32_BITS;
4687 168 : LastOffset += nZLOffset;
4688 :
4689 168 : if (LastOffset < MAXIMUM_OFFSET_IN_2GB_VECTORS)
4690 168 : return 0;
4691 :
4692 0 : return 1;
4693 : }
4694 :
4695 : // Adds a feature in a MiraMon layer.
4696 210 : int MMAddFeature(struct MiraMonVectLayerInfo *hMiraMonLayer,
4697 : struct MiraMonFeature *hMiraMonFeature)
4698 : {
4699 : int re;
4700 210 : MM_INTERNAL_FID previousFID = 0;
4701 :
4702 210 : if (!hMiraMonLayer)
4703 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4704 :
4705 210 : if (!hMiraMonLayer->bIsBeenInit)
4706 : {
4707 0 : if (MMInitLayerByType(hMiraMonLayer))
4708 : {
4709 0 : MMCPLDebug("MiraMon", "Error in MMInitLayerByType()");
4710 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
4711 : }
4712 0 : hMiraMonLayer->bIsBeenInit = 1;
4713 : }
4714 :
4715 210 : if (hMiraMonFeature)
4716 210 : previousFID = hMiraMonLayer->TopHeader.nElemCount;
4717 :
4718 210 : if (hMiraMonLayer->bIsPoint)
4719 : {
4720 87 : re = MMCreateFeaturePoint(hMiraMonLayer, hMiraMonFeature);
4721 87 : if (hMiraMonFeature)
4722 : {
4723 87 : hMiraMonFeature->nReadFeatures =
4724 87 : hMiraMonLayer->TopHeader.nElemCount - previousFID;
4725 : }
4726 87 : return re;
4727 : }
4728 123 : if (hMiraMonLayer->bIsArc || hMiraMonLayer->bIsPolygon)
4729 : {
4730 89 : re = MMCreateFeaturePolOrArc(hMiraMonLayer, hMiraMonFeature);
4731 89 : if (hMiraMonFeature)
4732 : {
4733 89 : hMiraMonFeature->nReadFeatures =
4734 89 : hMiraMonLayer->TopHeader.nElemCount - previousFID;
4735 : }
4736 89 : return re;
4737 : }
4738 34 : if (hMiraMonLayer->bIsDBF)
4739 : {
4740 : // Adding a record to DBF file
4741 34 : re = MMCreateRecordDBF(hMiraMonLayer, hMiraMonFeature);
4742 34 : if (hMiraMonFeature)
4743 : {
4744 34 : hMiraMonFeature->nReadFeatures =
4745 34 : hMiraMonLayer->TopHeader.nElemCount - previousFID;
4746 : }
4747 34 : return re;
4748 : }
4749 :
4750 0 : return MM_CONTINUE_WRITING_FEATURES;
4751 : }
4752 :
4753 : /* -------------------------------------------------------------------- */
4754 : /* Tools used by MiraMon. */
4755 : /* -------------------------------------------------------------------- */
4756 :
4757 316 : void MMInitBoundingBox(struct MMBoundingBox *dfBB)
4758 : {
4759 316 : if (!dfBB)
4760 0 : return;
4761 316 : dfBB->dfMinX = STATISTICAL_UNDEF_VALUE;
4762 316 : dfBB->dfMaxX = -STATISTICAL_UNDEF_VALUE;
4763 316 : dfBB->dfMinY = STATISTICAL_UNDEF_VALUE;
4764 316 : dfBB->dfMaxY = -STATISTICAL_UNDEF_VALUE;
4765 : }
4766 :
4767 207 : void MMUpdateBoundingBox(struct MMBoundingBox *dfBBToBeAct,
4768 : struct MMBoundingBox *dfBBWithData)
4769 : {
4770 207 : if (!dfBBToBeAct)
4771 0 : return;
4772 :
4773 207 : if (dfBBToBeAct->dfMinX > dfBBWithData->dfMinX)
4774 132 : dfBBToBeAct->dfMinX = dfBBWithData->dfMinX;
4775 :
4776 207 : if (dfBBToBeAct->dfMinY > dfBBWithData->dfMinY)
4777 147 : dfBBToBeAct->dfMinY = dfBBWithData->dfMinY;
4778 :
4779 207 : if (dfBBToBeAct->dfMaxX < dfBBWithData->dfMaxX)
4780 146 : dfBBToBeAct->dfMaxX = dfBBWithData->dfMaxX;
4781 :
4782 207 : if (dfBBToBeAct->dfMaxY < dfBBWithData->dfMaxY)
4783 144 : dfBBToBeAct->dfMaxY = dfBBWithData->dfMaxY;
4784 : }
4785 :
4786 757 : void MMUpdateBoundingBoxXY(struct MMBoundingBox *dfBB,
4787 : struct MM_POINT_2D *pCoord)
4788 : {
4789 757 : if (!pCoord)
4790 0 : return;
4791 :
4792 757 : if (pCoord->dfX < dfBB->dfMinX)
4793 266 : dfBB->dfMinX = pCoord->dfX;
4794 :
4795 757 : if (pCoord->dfY < dfBB->dfMinY)
4796 291 : dfBB->dfMinY = pCoord->dfY;
4797 :
4798 757 : if (pCoord->dfX > dfBB->dfMaxX)
4799 393 : dfBB->dfMaxX = pCoord->dfX;
4800 :
4801 757 : if (pCoord->dfY > dfBB->dfMaxY)
4802 353 : dfBB->dfMaxY = pCoord->dfY;
4803 : }
4804 :
4805 : /* -------------------------------------------------------------------- */
4806 : /* Resize structures for reuse */
4807 : /* -------------------------------------------------------------------- */
4808 1396 : int MMResizeMiraMonFieldValue(struct MiraMonFieldValue **pFieldValue,
4809 : MM_EXT_DBF_N_MULTIPLE_RECORDS *nMax,
4810 : MM_EXT_DBF_N_MULTIPLE_RECORDS nNum,
4811 : MM_EXT_DBF_N_MULTIPLE_RECORDS nIncr,
4812 : MM_EXT_DBF_N_MULTIPLE_RECORDS nProposedMax)
4813 : {
4814 : MM_EXT_DBF_N_MULTIPLE_RECORDS nPrevMax;
4815 : MM_EXT_DBF_N_MULTIPLE_RECORDS nNewMax;
4816 : void *pTmp;
4817 :
4818 1396 : if (nNum < *nMax)
4819 1377 : return 0;
4820 :
4821 19 : nPrevMax = *nMax;
4822 19 : nNewMax = max_function(nNum + nIncr, nProposedMax);
4823 19 : if (MMCheckSize_t(nNewMax, sizeof(**pFieldValue)))
4824 : {
4825 0 : return 1;
4826 : }
4827 19 : if ((pTmp = realloc_function(
4828 19 : *pFieldValue, (size_t)nNewMax * sizeof(**pFieldValue))) == nullptr)
4829 : {
4830 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4831 : "Memory error in MiraMon "
4832 : "driver (MMResizeMiraMonFieldValue())");
4833 0 : return 1;
4834 : }
4835 19 : *nMax = nNewMax;
4836 19 : *pFieldValue = pTmp;
4837 :
4838 19 : memset((*pFieldValue) + nPrevMax, 0,
4839 19 : (size_t)(*nMax - nPrevMax) * sizeof(**pFieldValue));
4840 19 : return 0;
4841 : }
4842 :
4843 340 : int MMResizeMiraMonPolygonArcs(struct MM_PAL_MEM **pFID,
4844 : MM_POLYGON_ARCS_COUNT *nMax,
4845 : MM_POLYGON_ARCS_COUNT nNum,
4846 : MM_POLYGON_ARCS_COUNT nIncr,
4847 : MM_POLYGON_ARCS_COUNT nProposedMax)
4848 : {
4849 : MM_POLYGON_ARCS_COUNT nPrevMax;
4850 : MM_POLYGON_ARCS_COUNT nNewMax;
4851 : void *pTmp;
4852 :
4853 340 : if (nNum < *nMax)
4854 31 : return 0;
4855 :
4856 309 : nPrevMax = *nMax;
4857 309 : nNewMax = max_function(nNum + nIncr, nProposedMax);
4858 309 : if (MMCheckSize_t(nNewMax, sizeof(**pFID)))
4859 : {
4860 0 : return 1;
4861 : }
4862 309 : if (nNewMax == 0 && *pFID)
4863 0 : return 0;
4864 309 : if ((pTmp = realloc_function(*pFID, (size_t)nNewMax * sizeof(**pFID))) ==
4865 : nullptr)
4866 : {
4867 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4868 : "Memory error in MiraMon "
4869 : "driver (MMResizeMiraMonPolygonArcs())");
4870 0 : return 1;
4871 : }
4872 309 : *nMax = nNewMax;
4873 309 : *pFID = pTmp;
4874 :
4875 309 : memset((*pFID) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pFID));
4876 309 : return 0;
4877 : }
4878 :
4879 88 : int MMResizeMiraMonRecord(struct MiraMonRecord **pMiraMonRecord,
4880 : MM_EXT_DBF_N_MULTIPLE_RECORDS *nMax,
4881 : MM_EXT_DBF_N_MULTIPLE_RECORDS nNum,
4882 : MM_EXT_DBF_N_MULTIPLE_RECORDS nIncr,
4883 : MM_EXT_DBF_N_MULTIPLE_RECORDS nProposedMax)
4884 : {
4885 : MM_EXT_DBF_N_MULTIPLE_RECORDS nPrevMax;
4886 : MM_EXT_DBF_N_MULTIPLE_RECORDS nNewMax;
4887 : void *pTmp;
4888 :
4889 88 : if (nNum < *nMax)
4890 72 : return 0;
4891 :
4892 16 : nPrevMax = *nMax;
4893 16 : nNewMax = max_function(nNum + nIncr, nProposedMax);
4894 16 : if (MMCheckSize_t(nNewMax, sizeof(**pMiraMonRecord)))
4895 : {
4896 0 : return 1;
4897 : }
4898 16 : if (nNewMax == 0 && *pMiraMonRecord)
4899 0 : return 0;
4900 16 : if ((pTmp = realloc_function(*pMiraMonRecord,
4901 16 : (size_t)nNewMax * sizeof(**pMiraMonRecord))) ==
4902 : nullptr)
4903 : {
4904 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4905 : "Memory error in MiraMon "
4906 : "driver (MMResizeMiraMonRecord())");
4907 0 : return 1;
4908 : }
4909 16 : *nMax = nNewMax;
4910 16 : *pMiraMonRecord = pTmp;
4911 :
4912 16 : memset((*pMiraMonRecord) + nPrevMax, 0,
4913 16 : (size_t)(*nMax - nPrevMax) * sizeof(**pMiraMonRecord));
4914 16 : return 0;
4915 : }
4916 :
4917 188 : int MMResizeZSectionDescrPointer(struct MM_ZD **pZDescription, GUInt64 *nMax,
4918 : GUInt64 nNum, GUInt64 nIncr,
4919 : GUInt64 nProposedMax)
4920 : {
4921 : GUInt64 nNewMax, nPrevMax;
4922 : void *pTmp;
4923 :
4924 188 : if (nNum < *nMax)
4925 131 : return 0;
4926 :
4927 57 : nPrevMax = *nMax;
4928 57 : nNewMax = max_function(nNum + nIncr, nProposedMax);
4929 57 : if (MMCheckSize_t(nNewMax, sizeof(**pZDescription)))
4930 : {
4931 0 : return 1;
4932 : }
4933 57 : if (nNewMax == 0 && *pZDescription)
4934 0 : return 0;
4935 57 : if ((pTmp = realloc_function(*pZDescription,
4936 : (size_t)nNewMax * sizeof(**pZDescription))) ==
4937 : nullptr)
4938 : {
4939 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4940 : "Memory error in MiraMon "
4941 : "driver (MMResizeZSectionDescrPointer())");
4942 0 : return 1;
4943 : }
4944 57 : *nMax = nNewMax;
4945 57 : *pZDescription = pTmp;
4946 :
4947 57 : memset((*pZDescription) + nPrevMax, 0,
4948 57 : (size_t)(*nMax - nPrevMax) * sizeof(**pZDescription));
4949 57 : return 0;
4950 : }
4951 :
4952 101 : int MMResizeNodeHeaderPointer(struct MM_NH **pNodeHeader, GUInt64 *nMax,
4953 : GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax)
4954 : {
4955 : GUInt64 nNewMax, nPrevMax;
4956 : void *pTmp;
4957 :
4958 101 : if (nNum < *nMax)
4959 101 : return 0;
4960 :
4961 0 : nPrevMax = *nMax;
4962 0 : nNewMax = max_function(nNum + nIncr, nProposedMax);
4963 0 : if (MMCheckSize_t(nNewMax, sizeof(**pNodeHeader)))
4964 : {
4965 0 : return 1;
4966 : }
4967 0 : if (nNewMax == 0 && *pNodeHeader)
4968 0 : return 0;
4969 0 : if ((pTmp = realloc_function(
4970 : *pNodeHeader, (size_t)nNewMax * sizeof(**pNodeHeader))) == nullptr)
4971 : {
4972 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
4973 : "Memory error in MiraMon "
4974 : "driver (MMResizeNodeHeaderPointer())");
4975 0 : return 1;
4976 : }
4977 0 : *nMax = nNewMax;
4978 0 : *pNodeHeader = pTmp;
4979 :
4980 0 : memset((*pNodeHeader) + nPrevMax, 0,
4981 0 : (size_t)(*nMax - nPrevMax) * sizeof(**pNodeHeader));
4982 0 : return 0;
4983 : }
4984 :
4985 101 : int MMResizeArcHeaderPointer(struct MM_AH **pArcHeader, GUInt64 *nMax,
4986 : GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax)
4987 : {
4988 : GUInt64 nNewMax, nPrevMax;
4989 : void *pTmp;
4990 :
4991 101 : if (nNum < *nMax)
4992 101 : return 0;
4993 :
4994 0 : nPrevMax = *nMax;
4995 0 : nNewMax = max_function(nNum + nIncr, nProposedMax);
4996 0 : if (MMCheckSize_t(nNewMax, sizeof(**pArcHeader)))
4997 : {
4998 0 : return 1;
4999 : }
5000 0 : if (nNewMax == 0 && *pArcHeader)
5001 0 : return 0;
5002 0 : if ((pTmp = realloc_function(
5003 : *pArcHeader, (size_t)nNewMax * sizeof(**pArcHeader))) == nullptr)
5004 : {
5005 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
5006 : "Memory error in MiraMon "
5007 : "driver (MMResizeArcHeaderPointer())");
5008 0 : return 1;
5009 : }
5010 0 : *nMax = nNewMax;
5011 0 : *pArcHeader = pTmp;
5012 :
5013 0 : memset((*pArcHeader) + nPrevMax, 0,
5014 0 : (size_t)(*nMax - nPrevMax) * sizeof(**pArcHeader));
5015 0 : return 0;
5016 : }
5017 :
5018 41 : int MMResizePolHeaderPointer(struct MM_PH **pPolHeader, GUInt64 *nMax,
5019 : GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax)
5020 : {
5021 : GUInt64 nNewMax, nPrevMax;
5022 : void *pTmp;
5023 :
5024 41 : if (nNum < *nMax)
5025 41 : return 0;
5026 :
5027 0 : nPrevMax = *nMax;
5028 0 : nNewMax = max_function(nNum + nIncr, nProposedMax);
5029 0 : if (MMCheckSize_t(nNewMax, sizeof(**pPolHeader)))
5030 : {
5031 0 : return 1;
5032 : }
5033 0 : if (nNewMax == 0 && *pPolHeader)
5034 0 : return 0;
5035 0 : if ((pTmp = realloc_function(
5036 : *pPolHeader, (size_t)nNewMax * sizeof(**pPolHeader))) == nullptr)
5037 : {
5038 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
5039 : "Memory error in MiraMon "
5040 : "driver (MMResizePolHeaderPointer())");
5041 0 : return 1;
5042 : }
5043 0 : *nMax = nNewMax;
5044 0 : *pPolHeader = pTmp;
5045 :
5046 0 : memset((*pPolHeader) + nPrevMax, 0,
5047 0 : (size_t)(*nMax - nPrevMax) * sizeof(**pPolHeader));
5048 0 : return 0;
5049 : }
5050 :
5051 2652 : int MMResize_MM_N_VERTICES_TYPE_Pointer(MM_N_VERTICES_TYPE **pVrt,
5052 : MM_N_VERTICES_TYPE *nMax,
5053 : MM_N_VERTICES_TYPE nNum,
5054 : MM_N_VERTICES_TYPE nIncr,
5055 : MM_N_VERTICES_TYPE nProposedMax)
5056 : {
5057 : MM_N_VERTICES_TYPE nNewMax, nPrevMax;
5058 : void *pTmp;
5059 :
5060 2652 : if (nNum < *nMax)
5061 1192 : return 0;
5062 :
5063 1460 : nPrevMax = *nMax;
5064 1460 : nNewMax = max_function(nNum + nIncr, nProposedMax);
5065 1460 : if (MMCheckSize_t(nNewMax, sizeof(**pVrt)))
5066 : {
5067 0 : return 1;
5068 : }
5069 1460 : if (nNewMax == 0 && *pVrt)
5070 0 : return 0;
5071 1460 : if ((pTmp = realloc_function(*pVrt, (size_t)nNewMax * sizeof(**pVrt))) ==
5072 : nullptr)
5073 : {
5074 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
5075 : "Memory error in MiraMon "
5076 : "driver (MMResize_MM_N_VERTICES_TYPE_Pointer())");
5077 0 : return 1;
5078 : }
5079 1460 : *nMax = nNewMax;
5080 1460 : *pVrt = pTmp;
5081 :
5082 1460 : memset((*pVrt) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pVrt));
5083 1460 : return 0;
5084 : }
5085 :
5086 387 : int MMResizeVFGPointer(char **pInt, MM_INTERNAL_FID *nMax, MM_INTERNAL_FID nNum,
5087 : MM_INTERNAL_FID nIncr, MM_INTERNAL_FID nProposedMax)
5088 : {
5089 : MM_N_VERTICES_TYPE nNewMax, nPrevMax;
5090 : void *pTmp;
5091 :
5092 387 : if (nNum < *nMax)
5093 57 : return 0;
5094 :
5095 330 : nPrevMax = *nMax;
5096 330 : nNewMax = max_function(nNum + nIncr, nProposedMax);
5097 330 : if (MMCheckSize_t(nNewMax, sizeof(**pInt)))
5098 : {
5099 0 : return 1;
5100 : }
5101 330 : if (nNewMax == 0 && *pInt)
5102 0 : return 0;
5103 330 : if ((pTmp = realloc_function(*pInt, (size_t)nNewMax * sizeof(**pInt))) ==
5104 : nullptr)
5105 : {
5106 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
5107 : "Memory error in MiraMon "
5108 : "driver (MMResizeVFGPointer())");
5109 0 : return 1;
5110 : }
5111 330 : *nMax = nNewMax;
5112 330 : *pInt = pTmp;
5113 :
5114 330 : memset((*pInt) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pInt));
5115 330 : return 0;
5116 : }
5117 :
5118 2665 : int MMResizeMM_POINT2DPointer(struct MM_POINT_2D **pPoint2D,
5119 : MM_N_VERTICES_TYPE *nMax, MM_N_VERTICES_TYPE nNum,
5120 : MM_N_VERTICES_TYPE nIncr,
5121 : MM_N_VERTICES_TYPE nProposedMax)
5122 : {
5123 : MM_N_VERTICES_TYPE nNewMax, nPrevMax;
5124 : void *pTmp;
5125 :
5126 2665 : if (nNum < *nMax)
5127 2282 : return 0;
5128 :
5129 383 : nPrevMax = *nMax;
5130 383 : nNewMax = max_function(nNum + nIncr, nProposedMax);
5131 383 : if (MMCheckSize_t(nNewMax, sizeof(**pPoint2D)))
5132 : {
5133 0 : return 1;
5134 : }
5135 383 : if (nNewMax == 0 && *pPoint2D)
5136 0 : return 0;
5137 383 : if ((pTmp = realloc_function(*pPoint2D, (size_t)nNewMax *
5138 : sizeof(**pPoint2D))) == nullptr)
5139 : {
5140 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
5141 : "Memory error in MiraMon "
5142 : "driver (MMResizeMM_POINT2DPointer())");
5143 0 : return 1;
5144 : }
5145 383 : *nMax = nNewMax;
5146 383 : *pPoint2D = pTmp;
5147 :
5148 383 : memset((*pPoint2D) + nPrevMax, 0,
5149 383 : (size_t)(*nMax - nPrevMax) * sizeof(**pPoint2D));
5150 383 : return 0;
5151 : }
5152 :
5153 1727 : int MMResizeDoublePointer(MM_COORD_TYPE **pDouble, MM_N_VERTICES_TYPE *nMax,
5154 : MM_N_VERTICES_TYPE nNum, MM_N_VERTICES_TYPE nIncr,
5155 : MM_N_VERTICES_TYPE nProposedMax)
5156 : {
5157 : MM_N_VERTICES_TYPE nNewMax, nPrevMax;
5158 : void *pTmp;
5159 :
5160 1727 : if (nNum < *nMax)
5161 1564 : return 0;
5162 :
5163 163 : nPrevMax = *nMax;
5164 163 : nNewMax = max_function(nNum + nIncr, nProposedMax);
5165 163 : if (MMCheckSize_t(nNewMax, sizeof(**pDouble)))
5166 : {
5167 0 : return 1;
5168 : }
5169 163 : if (nNewMax == 0 && *pDouble)
5170 0 : return 0;
5171 163 : if ((pTmp = realloc_function(*pDouble, (size_t)nNewMax *
5172 : sizeof(**pDouble))) == nullptr)
5173 : {
5174 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
5175 : "Memory error in MiraMon "
5176 : "driver (MMResizeDoublePointer())");
5177 0 : return 1;
5178 : }
5179 163 : *nMax = nNewMax;
5180 163 : *pDouble = pTmp;
5181 :
5182 163 : memset((*pDouble) + nPrevMax, 0,
5183 163 : (size_t)(*nMax - nPrevMax) * sizeof(**pDouble));
5184 163 : return 0;
5185 : }
5186 :
5187 22924 : int MMResizeStringToOperateIfNeeded(struct MiraMonVectLayerInfo *hMiraMonLayer,
5188 : MM_EXT_DBF_N_FIELDS nNewSize)
5189 : {
5190 22924 : if (!hMiraMonLayer)
5191 0 : return 1;
5192 :
5193 22924 : if (nNewSize >= hMiraMonLayer->nNumStringToOperate)
5194 : {
5195 : char *p;
5196 439 : if (MMCheckSize_t(nNewSize, 1))
5197 0 : return 1;
5198 439 : p = (char *)calloc_function((size_t)nNewSize);
5199 439 : if (!p)
5200 : {
5201 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
5202 : "Memory error in MiraMon "
5203 : "driver (MMResizeStringToOperateIfNeeded())");
5204 0 : return 1;
5205 : }
5206 439 : free_function(hMiraMonLayer->szStringToOperate);
5207 439 : hMiraMonLayer->szStringToOperate = p;
5208 439 : hMiraMonLayer->nNumStringToOperate = nNewSize;
5209 : }
5210 22924 : return 0;
5211 : }
5212 :
5213 : // Checks if a string is empty
5214 6339 : int MMIsEmptyString(const char *string)
5215 : {
5216 6339 : const char *ptr = string;
5217 :
5218 14654 : for (; *ptr; ptr++)
5219 13971 : if (*ptr != ' ' && *ptr != '\t')
5220 5656 : return 0;
5221 :
5222 683 : return 1;
5223 : }
5224 :
5225 : /* -------------------------------------------------------------------- */
5226 : /* Metadata Functions */
5227 : /* -------------------------------------------------------------------- */
5228 :
5229 : // Returns the value of an INI file. Used to read MiraMon metadata
5230 5330 : char *MMReturnValueFromSectionINIFile(const char *filename, const char *section,
5231 : const char *key)
5232 : {
5233 5330 : char *value = nullptr;
5234 : #ifndef GDAL_COMPILATION
5235 : char line[10000];
5236 : #endif
5237 : char *pszString;
5238 : const char *pszLine;
5239 5330 : char *section_header = nullptr;
5240 5330 : size_t key_len = 0;
5241 :
5242 5330 : FILE_TYPE *file = fopen_function(filename, "rb");
5243 5330 : if (file == nullptr)
5244 : {
5245 0 : MMCPLError(CE_Failure, CPLE_OpenFailed, "Cannot open INI file %s.",
5246 : filename);
5247 0 : return nullptr;
5248 : }
5249 :
5250 5330 : if (key)
5251 5170 : key_len = strlen(key);
5252 :
5253 : #ifndef GDAL_COMPILATION
5254 : while (fgets_function(line, (int)sizeof(line), file) && !feof_64(file) &&
5255 : *line != '\0')
5256 : {
5257 : pszLine = line;
5258 : #else
5259 399455 : while ((pszLine = CPLReadLine2L(file, 10000, nullptr)) != nullptr)
5260 : {
5261 : #endif
5262 : pszString =
5263 395828 : CPLRecode_function(pszLine, CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
5264 :
5265 : // Skip comments and empty lines
5266 395828 : if (*pszString == ';' || *pszString == '#' || *pszString == '\n' ||
5267 395828 : *pszString == '\r')
5268 : {
5269 0 : free_function(pszString);
5270 : // Move to next line
5271 0 : continue;
5272 : }
5273 :
5274 : // Check for section header
5275 395828 : if (*pszString == '[')
5276 : {
5277 86263 : char *section_end = strchr(pszString, ']');
5278 86263 : if (section_end != nullptr)
5279 : {
5280 86263 : *section_end = '\0'; // Terminate the string at ']'
5281 86263 : if (section_header)
5282 80933 : free_function(section_header);
5283 : section_header =
5284 86263 : strdup_function(pszString + 1); // Skip the '['
5285 : }
5286 86263 : free_function(pszString);
5287 86263 : continue;
5288 : }
5289 :
5290 309565 : if (key)
5291 : {
5292 : // If the current line belongs to the desired section
5293 309405 : if (section_header != nullptr &&
5294 309405 : strcmp(section_header, section) == 0)
5295 : {
5296 : // Check if the line contains the desired key
5297 11366 : if (strncmp(pszString, key, key_len) == 0 &&
5298 1725 : pszString[key_len] == '=')
5299 : {
5300 : // Extract the value
5301 1543 : char *value_start = pszString + key_len + 1;
5302 1543 : char *value_end = strstr(value_start, "\r\n");
5303 1543 : if (value_end != nullptr)
5304 : {
5305 0 : *value_end =
5306 : '\0'; // Terminate the string at newline character if found
5307 : }
5308 : else
5309 : {
5310 1543 : value_end = strstr(value_start, "\n");
5311 1543 : if (value_end != nullptr)
5312 : {
5313 0 : *value_end =
5314 : '\0'; // Terminate the string at newline character if found
5315 : }
5316 : else
5317 : {
5318 1543 : value_end = strstr(value_start, "\r");
5319 1543 : if (value_end != nullptr)
5320 : {
5321 0 : *value_end =
5322 : '\0'; // Terminate the string at newline character if found
5323 : }
5324 : }
5325 : }
5326 :
5327 1543 : value = strdup_function(value_start);
5328 1543 : fclose_function(file);
5329 1543 : free_function(section_header); // Free allocated memory
5330 1543 : free_function(pszString);
5331 1543 : return value;
5332 : }
5333 : }
5334 : }
5335 : else
5336 : {
5337 160 : if (section_header)
5338 : {
5339 160 : if (!strcmp(section_header, section))
5340 160 : value = section_header; // Freed out
5341 : else
5342 0 : value = nullptr;
5343 : }
5344 : else
5345 0 : value = nullptr;
5346 :
5347 160 : fclose_function(file);
5348 160 : free_function(pszString);
5349 160 : return value;
5350 : }
5351 307862 : free_function(pszString);
5352 : }
5353 :
5354 3627 : if (section_header)
5355 3627 : free_function(section_header); // Free allocated memory
5356 3627 : fclose_function(file);
5357 3627 : return value;
5358 : }
5359 :
5360 : // Retrieves EPSG codes from a CSV file based on provided geodetic identifiers.
5361 201 : int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult,
5362 : MM_BYTE direction)
5363 : {
5364 201 : char *aMMIDDBFFile = nullptr; //m_idofic.dbf
5365 201 : FILE_TYPE *pfMMSRS = nullptr;
5366 : const char *pszLine;
5367 : size_t nLong;
5368 : char *id_geodes, *psidgeodes, *epsg;
5369 : #ifndef GDAL_COMPILATION
5370 : char line[10000];
5371 : char *pszString;
5372 : #endif
5373 :
5374 201 : if (!pMMSRS_or_pSRS)
5375 : {
5376 70 : return 1;
5377 : }
5378 :
5379 : #ifdef GDAL_COMPILATION
5380 : {
5381 : #ifdef USE_ONLY_EMBEDDED_RESOURCE_FILES
5382 : const char *pszFilename = nullptr;
5383 : #else
5384 131 : const char *pszFilename = CPLFindFile("gdal", "MM_m_idofic.csv");
5385 : #endif
5386 : #ifdef EMBED_RESOURCE_FILES
5387 : if (!pszFilename || EQUAL(pszFilename, "MM_m_idofic.csv"))
5388 : {
5389 : pfMMSRS = VSIFileFromMemBuffer(
5390 : nullptr, (GByte *)(MiraMonGetMM_m_idofic_csv()),
5391 : (int)(strlen(MiraMonGetMM_m_idofic_csv())),
5392 : /* bTakeOwnership = */ false);
5393 : }
5394 : else
5395 : #endif
5396 131 : if (pszFilename)
5397 : {
5398 131 : aMMIDDBFFile = strdup_function(pszFilename);
5399 : }
5400 : }
5401 : #else
5402 : {
5403 : char temp_file[MM_CPL_PATH_BUF_SIZE];
5404 : MuntaPath(DirectoriPrograma, strcpy(temp_file, "m_idofic.csv"), TRUE);
5405 : aMMIDDBFFile = strdup_function(temp_file);
5406 : }
5407 : #endif
5408 :
5409 : #ifdef EMBED_RESOURCE_FILES
5410 : if (!pfMMSRS)
5411 : #endif
5412 : {
5413 131 : if (!aMMIDDBFFile)
5414 : {
5415 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
5416 : "Error opening data\\MM_m_idofic.csv.\n");
5417 0 : return 1;
5418 : }
5419 :
5420 : // Opening the file with SRS information
5421 131 : if (nullptr == (pfMMSRS = fopen_function(aMMIDDBFFile, "r")))
5422 : {
5423 0 : free_function(aMMIDDBFFile);
5424 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
5425 : "Error opening data\\MM_m_idofic.csv.\n");
5426 0 : return 1;
5427 : }
5428 131 : free_function(aMMIDDBFFile);
5429 : }
5430 :
5431 : // Checking the header of the csv file
5432 : #ifndef GDAL_COMPILATION
5433 : fgets_function(line, (int)sizeof(line), pfMMSRS);
5434 : if (!feof_64(pfMMSRS))
5435 : pszLine = line;
5436 : else
5437 : pszLine = nullptr;
5438 : #else
5439 131 : pszLine = CPLReadLine2L(pfMMSRS, 10000, nullptr);
5440 : #endif
5441 :
5442 131 : if (!pszLine)
5443 :
5444 : {
5445 0 : fclose_function(pfMMSRS);
5446 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
5447 : "Wrong format in data\\MM_m_idofic.csv.\n");
5448 0 : return 1;
5449 : }
5450 131 : id_geodes = MM_stristr(pszLine, "ID_GEODES");
5451 131 : if (!id_geodes)
5452 : {
5453 0 : fclose_function(pfMMSRS);
5454 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
5455 : "Wrong format in data\\MM_m_idofic.csv.\n");
5456 0 : return 1;
5457 : }
5458 131 : id_geodes[strlen("ID_GEODES")] = '\0';
5459 131 : psidgeodes = MM_stristr(pszLine, "PSIDGEODES");
5460 131 : if (!psidgeodes)
5461 : {
5462 0 : fclose_function(pfMMSRS);
5463 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
5464 : "Wrong format in data\\MM_m_idofic.csv.\n");
5465 0 : return 1;
5466 : }
5467 131 : psidgeodes[strlen("PSIDGEODES")] = '\0';
5468 :
5469 : // Is PSIDGEODES in first place?
5470 131 : if (strncmp(pszLine, psidgeodes, strlen("PSIDGEODES")))
5471 : {
5472 0 : fclose_function(pfMMSRS);
5473 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
5474 : "Wrong format in data\\MM_m_idofic.csv.\n");
5475 0 : return 1;
5476 : }
5477 : // Is ID_GEODES after PSIDGEODES?
5478 131 : if (strncmp(pszLine + strlen("PSIDGEODES") + 1, "ID_GEODES",
5479 : strlen("ID_GEODES")))
5480 : {
5481 0 : fclose_function(pfMMSRS);
5482 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
5483 : "Wrong format in data\\MM_m_idofic.csv.\n");
5484 0 : return 1;
5485 : }
5486 :
5487 : // Looking for the information.
5488 : #ifndef GDAL_COMPILATION
5489 : while (fgets_function(line, (int)sizeof(line), pfMMSRS) &&
5490 : !feof_64(pfMMSRS) && *line != '\0')
5491 : {
5492 : pszLine = line;
5493 : #else
5494 34994 : while ((pszLine = CPLReadLine2L(pfMMSRS, 10000, nullptr)) != nullptr)
5495 : {
5496 : #endif
5497 34943 : id_geodes = strstr(pszLine, ";");
5498 34943 : if (!id_geodes)
5499 : {
5500 0 : fclose_function(pfMMSRS);
5501 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
5502 : "Wrong format in data\\MM_m_idofic.csv.\n");
5503 0 : return 1;
5504 : }
5505 :
5506 34943 : psidgeodes = strstr(id_geodes + 1, ";");
5507 34943 : if (!psidgeodes)
5508 : {
5509 0 : fclose_function(pfMMSRS);
5510 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
5511 : "Wrong format in data\\MM_m_idofic.csv.\n");
5512 0 : return 1;
5513 : }
5514 :
5515 34943 : id_geodes[(ptrdiff_t)psidgeodes - (ptrdiff_t)id_geodes] = '\0';
5516 34943 : psidgeodes = strdup_function(pszLine);
5517 34943 : psidgeodes[(ptrdiff_t)id_geodes - (ptrdiff_t)pszLine] = '\0';
5518 34943 : id_geodes++;
5519 :
5520 34943 : if (direction == EPSG_FROM_MMSRS)
5521 : {
5522 : // I have pMMSRS and I want pSRS
5523 30690 : if (strcmp(pMMSRS_or_pSRS, id_geodes))
5524 : {
5525 30630 : free_function(psidgeodes);
5526 30630 : continue;
5527 : }
5528 :
5529 60 : epsg = strstr(psidgeodes, "EPSG:");
5530 60 : nLong = strlen("EPSG:");
5531 60 : if (epsg && !strncmp(epsg, psidgeodes, nLong))
5532 : {
5533 60 : if (epsg[nLong] != '\0')
5534 : {
5535 60 : strcpy(szResult, epsg + nLong);
5536 60 : free_function(psidgeodes);
5537 60 : fclose_function(pfMMSRS);
5538 60 : return 0; // found
5539 : }
5540 : else
5541 : {
5542 0 : fclose_function(pfMMSRS);
5543 0 : *szResult = '\0';
5544 0 : free_function(psidgeodes);
5545 0 : return 1; // not found
5546 : }
5547 : }
5548 : }
5549 : else
5550 : {
5551 : // I have pSRS and I want pMMSRS
5552 4253 : epsg = strstr(psidgeodes, "EPSG:");
5553 4253 : nLong = strlen("EPSG:");
5554 4253 : if (epsg && !strncmp(epsg, psidgeodes, nLong))
5555 : {
5556 3336 : if (epsg[nLong] != '\0')
5557 : {
5558 3336 : if (!strcmp(pMMSRS_or_pSRS, epsg + nLong))
5559 : {
5560 20 : strcpy(szResult, id_geodes);
5561 20 : fclose_function(pfMMSRS);
5562 20 : free_function(psidgeodes);
5563 20 : return 0; // found
5564 : }
5565 : }
5566 : }
5567 : }
5568 4233 : free_function(psidgeodes);
5569 : }
5570 :
5571 51 : fclose_function(pfMMSRS);
5572 51 : return 1; // not found
5573 : }
5574 :
5575 : #define LineReturn "\r\n"
5576 :
5577 : // Generates an idientifier that REL 4 MiraMon metadata needs.
5578 174 : static void MMGenerateFileIdentifierFromMetadataFileName(char *pMMFN,
5579 : char *aFileIdentifier)
5580 : {
5581 : char aCharRand[8];
5582 : static const char aCharset[] =
5583 : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
5584 : int i, len_charset;
5585 :
5586 174 : memset(aFileIdentifier, '\0', MM_MAX_LEN_LAYER_IDENTIFIER);
5587 :
5588 174 : aCharRand[0] = '_';
5589 174 : len_charset = (int)strlen(aCharset);
5590 1218 : for (i = 1; i < 7; i++)
5591 : {
5592 : // coverity[dont_call]
5593 1044 : aCharRand[i] = aCharset[rand() % (len_charset - 1)];
5594 : }
5595 174 : aCharRand[7] = '\0';
5596 174 : CPLStrlcpy(aFileIdentifier, pMMFN, MM_MAX_LEN_LAYER_IDENTIFIER - 7);
5597 174 : strcat(aFileIdentifier, aCharRand);
5598 174 : return;
5599 : }
5600 :
5601 : // Converts a string from UTF-8 to ANSI to be written in a REL 4 file
5602 : static void
5603 750 : MMWrite_ANSI_MetadataKeyDescriptor(struct MiraMonVectorMetaData *hMMMD,
5604 : FILE_TYPE *pF, const char *pszEng,
5605 : const char *pszCat, const char *pszEsp)
5606 : {
5607 750 : char *pszString = nullptr;
5608 :
5609 750 : switch (hMMMD->nMMLanguage)
5610 : {
5611 3 : case MM_CAT_LANGUAGE:
5612 : pszString =
5613 3 : CPLRecode_function(pszCat, CPL_ENC_UTF8, CPL_ENC_ISO8859_1);
5614 3 : break;
5615 3 : case MM_SPA_LANGUAGE:
5616 : pszString =
5617 3 : CPLRecode_function(pszEsp, CPL_ENC_UTF8, CPL_ENC_ISO8859_1);
5618 3 : break;
5619 744 : default:
5620 : case MM_ENG_LANGUAGE:
5621 : pszString =
5622 744 : CPLRecode_function(pszEng, CPL_ENC_UTF8, CPL_ENC_ISO8859_1);
5623 744 : break;
5624 : }
5625 750 : if (pszString)
5626 : {
5627 750 : fprintf_function(pF, "%s", KEY_descriptor);
5628 750 : fprintf_function(pF, "=");
5629 750 : fprintf_function(pF, "%s", pszString);
5630 750 : fprintf_function(pF, "%s", LineReturn);
5631 750 : CPLFree_function(pszString);
5632 : }
5633 750 : }
5634 :
5635 : /*
5636 : Writes a MiraMon REL 4 metadata file. Next sections are included:
5637 : VERSION, METADADES, IDENTIFICATION, EXTENT, OVERVIEW,
5638 : TAULA_PRINCIPAL and GEOMETRIA_I_TOPOLOGIA
5639 :
5640 : Please, consult the meaning of all them at:
5641 : https://www.miramon.cat/help/eng/GeMPlus/ClausREL.htm
5642 : */
5643 174 : static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD)
5644 : {
5645 : char aMessage[MM_MESSAGE_LENGTH],
5646 : aFileIdentifier[MM_MAX_LEN_LAYER_IDENTIFIER], aMMIDSRS[MM_MAX_ID_SNY];
5647 : MM_EXT_DBF_N_FIELDS nIField;
5648 : FILE_TYPE *pF;
5649 : time_t currentTime;
5650 : char aTimeString[200];
5651 :
5652 174 : if (!hMMMD->aLayerName)
5653 0 : return 0;
5654 :
5655 174 : if (nullptr == (pF = fopen_function(hMMMD->aLayerName, "wb")))
5656 : {
5657 0 : MMCPLError(CE_Failure, CPLE_OpenFailed, "The file %s must exist.",
5658 : hMMMD->aLayerName);
5659 0 : return 1;
5660 : }
5661 :
5662 : // Writing MiraMon version section
5663 174 : fprintf_function(pF, "[%s]" LineReturn, SECTION_VERSIO);
5664 :
5665 174 : fprintf_function(pF, "%s=%u" LineReturn, KEY_Vers, (unsigned)MM_VERS);
5666 174 : fprintf_function(pF, "%s=%u" LineReturn, KEY_SubVers, (unsigned)MM_SUBVERS);
5667 :
5668 174 : fprintf_function(pF, "%s=%u" LineReturn, KEY_VersMetaDades,
5669 : (unsigned)MM_VERS_METADADES);
5670 174 : fprintf_function(pF, "%s=%u" LineReturn, KEY_SubVersMetaDades,
5671 : (unsigned)MM_SUBVERS_METADADES);
5672 :
5673 : // Writing METADADES section
5674 174 : fprintf_function(pF, "\r\n[%s]" LineReturn, SECTION_METADADES);
5675 174 : CPLStrlcpy(aMessage, hMMMD->aLayerName, sizeof(aMessage));
5676 174 : MMGenerateFileIdentifierFromMetadataFileName(aMessage, aFileIdentifier);
5677 174 : fprintf_function(pF, "%s=%s" LineReturn, KEY_FileIdentifier,
5678 : aFileIdentifier);
5679 174 : fprintf_function(pF, "%s=%s" LineReturn, KEY_language, KEY_Value_eng);
5680 174 : fprintf_function(pF, "%s=%s" LineReturn, KEY_MDIdiom, KEY_Value_eng);
5681 174 : fprintf_function(pF, "%s=%s" LineReturn, KEY_characterSet,
5682 : KEY_Value_characterSet);
5683 :
5684 : // Writing IDENTIFICATION section
5685 174 : fprintf_function(pF, LineReturn "[%s]" LineReturn, SECTION_IDENTIFICATION);
5686 174 : fprintf_function(pF, "%s=%s" LineReturn, KEY_code, aFileIdentifier);
5687 174 : fprintf_function(pF, "%s=" LineReturn, KEY_codeSpace);
5688 174 : if (hMMMD->szLayerTitle && !MMIsEmptyString(hMMMD->szLayerTitle))
5689 : {
5690 174 : if (hMMMD->ePlainLT == MM_LayerType_Point)
5691 33 : fprintf_function(pF, "%s=%s (pnt)" LineReturn, KEY_DatasetTitle,
5692 : hMMMD->szLayerTitle);
5693 174 : if (hMMMD->ePlainLT == MM_LayerType_Arc)
5694 57 : fprintf_function(pF, "%s=%s (arc)" LineReturn, KEY_DatasetTitle,
5695 : hMMMD->szLayerTitle);
5696 174 : if (hMMMD->ePlainLT == MM_LayerType_Pol)
5697 27 : fprintf_function(pF, "%s=%s (pol)" LineReturn, KEY_DatasetTitle,
5698 : hMMMD->szLayerTitle);
5699 : }
5700 174 : fprintf_function(pF, "%s=%s" LineReturn, KEY_language, KEY_Value_eng);
5701 :
5702 174 : if (hMMMD->ePlainLT != MM_LayerType_Node &&
5703 117 : hMMMD->ePlainLT != MM_LayerType_Pol)
5704 : {
5705 : // SPATIAL_REFERENCE_SYSTEM:HORIZONTAL
5706 90 : fprintf_function(pF, LineReturn "[%s:%s]" LineReturn,
5707 : SECTION_SPATIAL_REFERENCE_SYSTEM, SECTION_HORIZONTAL);
5708 110 : if (!ReturnMMIDSRSFromEPSGCodeSRS(hMMMD->pSRS, aMMIDSRS) &&
5709 20 : !MMIsEmptyString(aMMIDSRS))
5710 20 : fprintf_function(pF, "%s=%s" LineReturn,
5711 : KEY_HorizontalSystemIdentifier, aMMIDSRS);
5712 : else
5713 : {
5714 70 : MMCPLWarning(CE_Warning, CPLE_NotSupported,
5715 : "The MiraMon driver cannot assign any HRS.");
5716 : // Horizontal Reference System
5717 70 : fprintf_function(pF, "%s=plane" LineReturn,
5718 : KEY_HorizontalSystemIdentifier);
5719 70 : fprintf_function(pF, "%s=local" LineReturn,
5720 : KEY_HorizontalSystemDefinition);
5721 70 : if (hMMMD->pXUnit)
5722 0 : fprintf_function(pF, "%s=%s" LineReturn, KEY_unitats,
5723 : hMMMD->pXUnit);
5724 70 : if (hMMMD->pYUnit)
5725 : {
5726 0 : if (!hMMMD->pXUnit || strcasecmp(hMMMD->pXUnit, hMMMD->pYUnit))
5727 0 : fprintf_function(pF, "%s=%s" LineReturn, KEY_unitatsY,
5728 : hMMMD->pYUnit);
5729 : }
5730 : }
5731 :
5732 : // SPATIAL_REFERENCE_SYSTEM:VERTICAL
5733 : // Llegim les unitats del Sist. ref. vertical
5734 90 : if (hMMMD->pZUnit)
5735 : {
5736 0 : fprintf_function(pF, LineReturn "[%s:%s]" LineReturn,
5737 : SECTION_SPATIAL_REFERENCE_SYSTEM,
5738 : SECTION_VERTICAL);
5739 0 : fprintf_function(pF, "%s=%s" LineReturn, KEY_unitats,
5740 : hMMMD->pZUnit);
5741 : }
5742 : }
5743 :
5744 174 : if (hMMMD->ePlainLT == MM_LayerType_Pol && hMMMD->aArcFile)
5745 : {
5746 : // Writing OVERVIEW:ASPECTES_TECNICS in polygon metadata file.
5747 : // ArcSource=fitx_pol.arc
5748 27 : fprintf_function(pF, LineReturn "[%s]" LineReturn,
5749 : SECTION_OVVW_ASPECTES_TECNICS);
5750 27 : fprintf_function(pF, "%s=\"%s\"" LineReturn, KEY_ArcSource,
5751 : hMMMD->aArcFile);
5752 : }
5753 147 : else if (hMMMD->ePlainLT == MM_LayerType_Arc && hMMMD->aArcFile)
5754 : {
5755 : // Writing OVERVIEW:ASPECTES_TECNICS in arc metadata file.
5756 : // Ciclat1=fitx_arc.pol
5757 27 : fprintf_function(pF, LineReturn "[%s]" LineReturn,
5758 : SECTION_OVVW_ASPECTES_TECNICS);
5759 27 : fprintf_function(pF, "Ciclat1=\"%s\"" LineReturn, hMMMD->aArcFile);
5760 : }
5761 :
5762 : // Writing EXTENT section
5763 174 : fprintf_function(pF, LineReturn "[%s]" LineReturn, SECTION_EXTENT);
5764 174 : fprintf_function(pF, "%s=0" LineReturn, KEY_toler_env);
5765 :
5766 174 : if (hMMMD->hBB.dfMinX != MM_UNDEFINED_STATISTICAL_VALUE &&
5767 174 : hMMMD->hBB.dfMaxX != -MM_UNDEFINED_STATISTICAL_VALUE &&
5768 174 : hMMMD->hBB.dfMinY != MM_UNDEFINED_STATISTICAL_VALUE &&
5769 174 : hMMMD->hBB.dfMaxY != -MM_UNDEFINED_STATISTICAL_VALUE)
5770 : {
5771 174 : fprintf_function(pF, "%s=%lf" LineReturn, KEY_MinX, hMMMD->hBB.dfMinX);
5772 174 : fprintf_function(pF, "%s=%lf" LineReturn, KEY_MaxX, hMMMD->hBB.dfMaxX);
5773 174 : fprintf_function(pF, "%s=%lf" LineReturn, KEY_MinY, hMMMD->hBB.dfMinY);
5774 174 : fprintf_function(pF, "%s=%lf" LineReturn, KEY_MaxY, hMMMD->hBB.dfMaxY);
5775 : }
5776 :
5777 : // Writing OVERVIEW section
5778 174 : fprintf_function(pF, LineReturn "[%s]" LineReturn, SECTION_OVERVIEW);
5779 :
5780 174 : currentTime = time(nullptr);
5781 :
5782 : #ifdef GDAL_COMPILATION
5783 : {
5784 : struct tm ltime;
5785 174 : VSILocalTime(¤tTime, <ime);
5786 174 : snprintf(aTimeString, sizeof(aTimeString),
5787 174 : "%04d%02d%02d %02d%02d%02d%02d", ltime.tm_year + 1900,
5788 174 : ltime.tm_mon + 1, ltime.tm_mday, ltime.tm_hour, ltime.tm_min,
5789 : ltime.tm_sec, 0);
5790 174 : fprintf_function(pF, "%s=%s" LineReturn, KEY_CreationDate, aTimeString);
5791 174 : fprintf_function(pF, LineReturn);
5792 : }
5793 : #else
5794 : {
5795 : struct tm *pLocalTime;
5796 : pLocalTime = localtime(¤tTime);
5797 : snprintf(aTimeString, sizeof(aTimeString),
5798 : "%04d%02d%02d %02d%02d%02d%02d", pLocalTime->tm_year + 1900,
5799 : pLocalTime->tm_mon + 1, pLocalTime->tm_mday,
5800 : pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec,
5801 : 0);
5802 : fprintf_function(pF, "%s=%s" LineReturn, KEY_CreationDate, aTimeString);
5803 : fprintf_function(pF, LineReturn);
5804 : }
5805 : #endif
5806 :
5807 : // Writing TAULA_PRINCIPAL section
5808 174 : fprintf_function(pF, "[%s]" LineReturn, SECTION_TAULA_PRINCIPAL);
5809 174 : fprintf_function(pF, "IdGrafic=%s" LineReturn, szMMNomCampIdGraficDefecte);
5810 174 : fprintf_function(pF, "TipusRelacio=RELACIO_1_1_DICC" LineReturn);
5811 :
5812 174 : fprintf_function(pF, LineReturn);
5813 174 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5814 : szMMNomCampIdGraficDefecte);
5815 174 : fprintf_function(pF, "visible=0" LineReturn);
5816 174 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5817 :
5818 174 : MMWrite_ANSI_MetadataKeyDescriptor(
5819 : hMMMD, pF, szInternalGraphicIdentifierEng,
5820 : szInternalGraphicIdentifierCat, szInternalGraphicIdentifierSpa);
5821 :
5822 174 : if (hMMMD->ePlainLT == MM_LayerType_Arc)
5823 : {
5824 57 : fprintf_function(pF, LineReturn);
5825 57 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5826 : szMMNomCampNVertexsDefecte);
5827 57 : fprintf_function(pF, "visible=0" LineReturn);
5828 57 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5829 57 : MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfVerticesEng,
5830 : szNumberOfVerticesCat,
5831 : szNumberOfVerticesSpa);
5832 :
5833 57 : fprintf_function(pF, LineReturn);
5834 57 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5835 : szMMNomCampLongitudArcDefecte);
5836 57 : MMWrite_ANSI_MetadataKeyDescriptor(
5837 : hMMMD, pF, szLengthOfAarcEng, szLengthOfAarcCat, szLengthOfAarcSpa);
5838 :
5839 57 : fprintf_function(pF, LineReturn);
5840 57 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5841 : szMMNomCampNodeIniDefecte);
5842 57 : fprintf_function(pF, "visible=0" LineReturn);
5843 57 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5844 57 : MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szInitialNodeEng,
5845 : szInitialNodeCat, szInitialNodeSpa);
5846 :
5847 57 : fprintf_function(pF, LineReturn);
5848 57 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5849 : szMMNomCampNodeFiDefecte);
5850 57 : fprintf_function(pF, "visible=0" LineReturn);
5851 57 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5852 57 : MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szFinalNodeEng,
5853 : szFinalNodeCat, szFinalNodeSpa);
5854 :
5855 57 : fprintf_function(pF, LineReturn);
5856 57 : fprintf_function(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn);
5857 57 : fprintf_function(pF, "NomCampNVertexs=%s" LineReturn,
5858 : szMMNomCampNVertexsDefecte);
5859 57 : fprintf_function(pF, "NomCampLongitudArc=%s" LineReturn,
5860 : szMMNomCampLongitudArcDefecte);
5861 57 : fprintf_function(pF, "NomCampNodeIni=%s" LineReturn,
5862 : szMMNomCampNodeIniDefecte);
5863 57 : fprintf_function(pF, "NomCampNodeFi=%s" LineReturn,
5864 : szMMNomCampNodeFiDefecte);
5865 : }
5866 117 : else if (hMMMD->ePlainLT == MM_LayerType_Node)
5867 : {
5868 57 : fprintf_function(pF, LineReturn);
5869 57 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5870 : szMMNomCampArcsANodeDefecte);
5871 57 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5872 57 : MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfArcsToNodeEng,
5873 : szNumberOfArcsToNodeCat,
5874 : szNumberOfArcsToNodeSpa);
5875 :
5876 57 : fprintf_function(pF, LineReturn);
5877 57 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5878 : szMMNomCampTipusNodeDefecte);
5879 57 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5880 57 : MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNodeTypeEng,
5881 : szNodeTypeCat, szNodeTypeSpa);
5882 :
5883 57 : fprintf_function(pF, LineReturn);
5884 57 : fprintf_function(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn);
5885 57 : fprintf_function(pF, "NomCampArcsANode=%s" LineReturn,
5886 : szMMNomCampArcsANodeDefecte);
5887 57 : fprintf_function(pF, "NomCampTipusNode=%s" LineReturn,
5888 : szMMNomCampTipusNodeDefecte);
5889 : }
5890 60 : else if (hMMMD->ePlainLT == MM_LayerType_Pol)
5891 : {
5892 27 : fprintf_function(pF, LineReturn);
5893 27 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5894 : szMMNomCampNVertexsDefecte);
5895 27 : fprintf_function(pF, "visible=0" LineReturn);
5896 27 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5897 27 : MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfVerticesEng,
5898 : szNumberOfVerticesCat,
5899 : szNumberOfVerticesSpa);
5900 :
5901 27 : fprintf_function(pF, LineReturn);
5902 27 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5903 : szMMNomCampPerimetreDefecte);
5904 27 : MMWrite_ANSI_MetadataKeyDescriptor(
5905 : hMMMD, pF, szPerimeterOfThePolygonEng, szPerimeterOfThePolygonCat,
5906 : szPerimeterOfThePolygonSpa);
5907 :
5908 27 : fprintf_function(pF, LineReturn);
5909 27 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5910 : szMMNomCampAreaDefecte);
5911 27 : MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szAreaOfThePolygonEng,
5912 : szAreaOfThePolygonCat,
5913 : szAreaOfThePolygonSpa);
5914 :
5915 27 : fprintf_function(pF, LineReturn);
5916 27 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5917 : szMMNomCampNArcsDefecte);
5918 27 : fprintf_function(pF, "visible=0" LineReturn);
5919 27 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5920 27 : MMWrite_ANSI_MetadataKeyDescriptor(
5921 : hMMMD, pF, szNumberOfArcsEng, szNumberOfArcsCat, szNumberOfArcsSpa);
5922 :
5923 27 : fprintf_function(pF, LineReturn);
5924 27 : fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL,
5925 : szMMNomCampNPoligonsDefecte);
5926 27 : fprintf_function(pF, "visible=0" LineReturn);
5927 27 : fprintf_function(pF, "simbolitzable=0" LineReturn);
5928 27 : MMWrite_ANSI_MetadataKeyDescriptor(
5929 : hMMMD, pF, szNumberOfElementaryPolygonsEng,
5930 : szNumberOfElementaryPolygonsCat, szNumberOfElementaryPolygonsSpa);
5931 :
5932 27 : fprintf_function(pF, LineReturn);
5933 27 : fprintf_function(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn);
5934 27 : fprintf_function(pF, "NomCampNVertexs=%s" LineReturn,
5935 : szMMNomCampNVertexsDefecte);
5936 27 : fprintf_function(pF, "NomCampPerimetre=%s" LineReturn,
5937 : szMMNomCampPerimetreDefecte);
5938 27 : fprintf_function(pF, "NomCampArea=%s" LineReturn,
5939 : szMMNomCampAreaDefecte);
5940 27 : fprintf_function(pF, "NomCampNArcs=%s" LineReturn,
5941 : szMMNomCampNArcsDefecte);
5942 27 : fprintf_function(pF, "NomCampNPoligons=%s" LineReturn,
5943 : szMMNomCampNPoligonsDefecte);
5944 : }
5945 :
5946 174 : if (hMMMD->pLayerDB && hMMMD->pLayerDB->nNFields > 0)
5947 : {
5948 : // For each field of the databes
5949 584 : for (nIField = 0; nIField < hMMMD->pLayerDB->nNFields; nIField++)
5950 : {
5951 494 : fprintf_function(pF, LineReturn "[%s:%s]" LineReturn,
5952 : SECTION_TAULA_PRINCIPAL,
5953 494 : hMMMD->pLayerDB->pFields[nIField].pszFieldName);
5954 :
5955 494 : if (!MMIsEmptyString(
5956 593 : hMMMD->pLayerDB->pFields[nIField].pszFieldDescription) &&
5957 99 : !MMIsEmptyString(
5958 99 : hMMMD->pLayerDB->pFields[nIField].pszFieldName))
5959 : {
5960 99 : MMWrite_ANSI_MetadataKeyDescriptor(
5961 : hMMMD, pF,
5962 99 : hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5963 99 : hMMMD->pLayerDB->pFields[nIField].pszFieldDescription,
5964 99 : hMMMD->pLayerDB->pFields[nIField].pszFieldDescription);
5965 : }
5966 :
5967 : // Exception in a particular case: "altura" is a catalan word that means
5968 : // "height". Its unit by default will be "m" instead of "unknown".
5969 : // The same goes for "z", which easily means height.
5970 494 : if (EQUAL("altura",
5971 494 : hMMMD->pLayerDB->pFields[nIField].pszFieldName) ||
5972 494 : EQUAL("z", hMMMD->pLayerDB->pFields[nIField].pszFieldName))
5973 : {
5974 0 : fprintf_function(pF, "unitats=m" LineReturn);
5975 : }
5976 : else
5977 : {
5978 : // By default units of field values will not be shown.
5979 494 : fprintf_function(pF, "MostrarUnitats=0" LineReturn);
5980 : }
5981 : }
5982 : }
5983 174 : fclose_function(pF);
5984 174 : return 0;
5985 : }
5986 :
5987 : // Writes metadata files for MiraMon vector layers
5988 191 : static int MMWriteVectorMetadataFile(struct MiraMonVectLayerInfo *hMiraMonLayer,
5989 : int layerPlainType, int layerMainPlainType)
5990 : {
5991 : struct MiraMonVectorMetaData hMMMD;
5992 :
5993 191 : if (!hMiraMonLayer)
5994 0 : return 1;
5995 :
5996 : // MiraMon writes a REL file of each .pnt, .arc, .nod or .pol
5997 191 : memset(&hMMMD, 0, sizeof(hMMMD));
5998 191 : hMMMD.ePlainLT = layerPlainType;
5999 191 : hMMMD.pSRS = hMiraMonLayer->pSRS;
6000 191 : hMMMD.pZUnit = hMiraMonLayer->pZUnit;
6001 191 : hMMMD.nMMLanguage = hMiraMonLayer->nMMLanguage;
6002 :
6003 191 : hMMMD.szLayerTitle = hMiraMonLayer->szLayerTitle;
6004 191 : if (layerPlainType == MM_LayerType_Point)
6005 : {
6006 33 : hMMMD.aLayerName = hMiraMonLayer->MMPoint.pszREL_LayerName;
6007 33 : if (MMIsEmptyString(hMMMD.aLayerName))
6008 0 : return 0; // If no file, no error. Just continue.
6009 33 : memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB, sizeof(hMMMD.hBB));
6010 33 : hMMMD.pLayerDB = hMiraMonLayer->pLayerDB;
6011 33 : return MMWriteMetadataFile(&hMMMD);
6012 : }
6013 158 : else if (layerPlainType == MM_LayerType_Arc)
6014 : {
6015 : int nResult;
6016 :
6017 : // Arcs and not polygons
6018 57 : if (layerMainPlainType == MM_LayerType_Arc)
6019 : {
6020 30 : hMMMD.aLayerName = hMiraMonLayer->MMArc.pszREL_LayerName;
6021 30 : if (MMIsEmptyString(hMMMD.aLayerName))
6022 0 : return 0; // If no file, no error. Just continue.
6023 30 : memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB,
6024 : sizeof(hMMMD.hBB));
6025 30 : hMMMD.pLayerDB = hMiraMonLayer->pLayerDB;
6026 : }
6027 : // Arcs and polygons
6028 : else
6029 : {
6030 : // Arc from polygon
6031 27 : hMMMD.aLayerName = hMiraMonLayer->MMPolygon.MMArc.pszREL_LayerName;
6032 27 : if (MMIsEmptyString(hMMMD.aLayerName))
6033 0 : return 0; // If no file, no error. Just continue.
6034 :
6035 27 : memcpy(&hMMMD.hBB, &hMiraMonLayer->MMPolygon.TopArcHeader.hBB,
6036 : sizeof(hMMMD.hBB));
6037 27 : hMMMD.pLayerDB = nullptr;
6038 27 : hMMMD.aArcFile = strdup_function(
6039 : get_filename_function(hMiraMonLayer->MMPolygon.pszLayerName));
6040 : }
6041 57 : nResult = MMWriteMetadataFile(&hMMMD);
6042 57 : free_function(hMMMD.aArcFile);
6043 57 : return nResult;
6044 : }
6045 101 : else if (layerPlainType == MM_LayerType_Pol)
6046 : {
6047 : int nResult;
6048 :
6049 27 : hMMMD.aLayerName = hMiraMonLayer->MMPolygon.pszREL_LayerName;
6050 :
6051 27 : if (MMIsEmptyString(hMMMD.aLayerName))
6052 0 : return 0; // If no file, no error. Just continue.
6053 :
6054 27 : memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB, sizeof(hMMMD.hBB));
6055 27 : hMMMD.pLayerDB = hMiraMonLayer->pLayerDB;
6056 27 : hMMMD.aArcFile = strdup_function(
6057 : get_filename_function(hMiraMonLayer->MMPolygon.MMArc.pszLayerName));
6058 27 : nResult = MMWriteMetadataFile(&hMMMD);
6059 27 : free_function(hMMMD.aArcFile);
6060 27 : return nResult;
6061 : }
6062 74 : else if (layerPlainType == MM_LayerType_Node)
6063 : {
6064 : // Node from arc
6065 57 : if (layerMainPlainType == MM_LayerType_Arc)
6066 : {
6067 30 : hMMMD.aLayerName = hMiraMonLayer->MMArc.MMNode.pszREL_LayerName;
6068 30 : if (MMIsEmptyString(hMMMD.aLayerName))
6069 0 : return 0; // If no file, no error. Just continue.
6070 30 : memcpy(&hMMMD.hBB, &hMiraMonLayer->MMArc.TopNodeHeader.hBB,
6071 : sizeof(hMMMD.hBB));
6072 : }
6073 : else // Node from polygon
6074 : {
6075 27 : hMMMD.aLayerName =
6076 27 : hMiraMonLayer->MMPolygon.MMArc.MMNode.pszREL_LayerName;
6077 27 : if (MMIsEmptyString(hMMMD.aLayerName))
6078 0 : return 0; // If no file, no error. Just continue.
6079 27 : memcpy(&hMMMD.hBB,
6080 27 : &hMiraMonLayer->MMPolygon.MMArc.TopNodeHeader.hBB,
6081 : sizeof(hMMMD.hBB));
6082 : }
6083 57 : hMMMD.pLayerDB = nullptr;
6084 57 : return MMWriteMetadataFile(&hMMMD);
6085 : }
6086 17 : return 0;
6087 : }
6088 :
6089 107 : int MMWriteVectorMetadata(struct MiraMonVectLayerInfo *hMiraMonLayer)
6090 : {
6091 107 : if (!hMiraMonLayer)
6092 0 : return 1;
6093 :
6094 107 : if (hMiraMonLayer->bIsPoint)
6095 33 : return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Point,
6096 : MM_LayerType_Point);
6097 74 : if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
6098 : {
6099 30 : if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Node,
6100 : MM_LayerType_Arc))
6101 0 : return 1;
6102 30 : return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Arc,
6103 : MM_LayerType_Arc);
6104 : }
6105 44 : if (hMiraMonLayer->bIsPolygon)
6106 : {
6107 27 : if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Node,
6108 : MM_LayerType_Pol))
6109 0 : return 1;
6110 27 : if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Arc,
6111 : MM_LayerType_Pol))
6112 0 : return 1;
6113 27 : return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Pol,
6114 : MM_LayerType_Pol);
6115 : }
6116 17 : if (hMiraMonLayer->bIsDBF)
6117 : {
6118 17 : return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Unknown,
6119 : MM_LayerType_Unknown);
6120 : }
6121 0 : return 0;
6122 : }
6123 :
6124 : // Verifies the version of a MiraMon REL 4 file.
6125 163 : int MMCheck_REL_FILE(const char *szREL_file)
6126 : {
6127 : char *pszLine;
6128 : FILE_TYPE *pF;
6129 :
6130 : // Does the REL file exist?
6131 163 : pF = fopen_function(szREL_file, "r");
6132 163 : if (!pF)
6133 : {
6134 3 : MMCPLError(CE_Failure, CPLE_OpenFailed, "The file %s must exist.",
6135 : szREL_file);
6136 3 : return 1;
6137 : }
6138 160 : fclose_function(pF);
6139 :
6140 : // Does the REL file have VERSION?
6141 : pszLine =
6142 160 : MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, nullptr);
6143 160 : if (!pszLine)
6144 : {
6145 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6146 : "The file \"%s\" must be REL4. "
6147 : "You can use ConvREL.exe from MiraMon software "
6148 : " or GeM+ "
6149 : "to convert this file to REL4.",
6150 : szREL_file);
6151 0 : return 1;
6152 : }
6153 160 : free_function(pszLine);
6154 :
6155 : // Does the REL file have the correct VERSION?
6156 : // Vers>=4?
6157 : pszLine =
6158 160 : MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, KEY_Vers);
6159 160 : if (pszLine)
6160 : {
6161 160 : if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS)
6162 : {
6163 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6164 : "The file \"%s\" must have %s>=%d.", szREL_file,
6165 : KEY_Vers, MM_VERS);
6166 0 : free_function(pszLine);
6167 0 : return 1;
6168 : }
6169 160 : free_function(pszLine);
6170 : }
6171 : else
6172 : {
6173 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6174 : "The file \"%s\" must have %s>=%d.", szREL_file, KEY_Vers,
6175 : MM_VERS);
6176 0 : return 1;
6177 : }
6178 :
6179 : // SubVers>=0?
6180 160 : pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
6181 : KEY_SubVers);
6182 160 : if (pszLine)
6183 : {
6184 160 : if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_ACCEPTED)
6185 : {
6186 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6187 : "The file \"%s\" must have %s>=%d.", szREL_file,
6188 : KEY_SubVers, MM_SUBVERS_ACCEPTED);
6189 :
6190 0 : free_function(pszLine);
6191 0 : return 1;
6192 : }
6193 160 : free_function(pszLine);
6194 : }
6195 : else
6196 : {
6197 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6198 : "The file \"%s\" must have %s>=%d.", szREL_file, KEY_SubVers,
6199 : MM_SUBVERS_ACCEPTED);
6200 0 : return 1;
6201 : }
6202 :
6203 : // VersMetaDades>=4?
6204 160 : pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
6205 : KEY_VersMetaDades);
6206 160 : if (pszLine)
6207 : {
6208 160 : if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS_METADADES_ACCEPTED)
6209 : {
6210 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6211 : "The file \"%s\" must have %s>=%d.", szREL_file,
6212 : KEY_VersMetaDades, MM_VERS_METADADES_ACCEPTED);
6213 0 : free_function(pszLine);
6214 0 : return 1;
6215 : }
6216 160 : free_function(pszLine);
6217 : }
6218 : else
6219 : {
6220 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6221 : "The file \"%s\" must have %s>=%d.", szREL_file,
6222 : KEY_VersMetaDades, MM_VERS_METADADES_ACCEPTED);
6223 0 : return 1;
6224 : }
6225 :
6226 : // SubVersMetaDades>=0?
6227 160 : pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
6228 : KEY_SubVersMetaDades);
6229 160 : if (pszLine)
6230 : {
6231 160 : if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_METADADES)
6232 : {
6233 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6234 : "The file \"%s\" must have %s>=%d.", szREL_file,
6235 : KEY_SubVersMetaDades, MM_SUBVERS_METADADES);
6236 0 : free_function(pszLine);
6237 0 : return 1;
6238 : }
6239 160 : free_function(pszLine);
6240 : }
6241 : else
6242 : {
6243 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6244 : "The file \"%s\" must have %s>=%d.", szREL_file,
6245 : KEY_SubVersMetaDades, MM_SUBVERS_METADADES);
6246 0 : return 1;
6247 : }
6248 160 : return 0;
6249 : }
6250 :
6251 : /* -------------------------------------------------------------------- */
6252 : /* MiraMon database functions */
6253 : /* -------------------------------------------------------------------- */
6254 :
6255 : // Initializes a MiraMon database associated with a vector layer:
6256 : // Sets the usual fields that MiraMon needs and after them, adds
6257 : // all fields of the input layer
6258 191 : static int MMInitMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6259 : struct MMAdmDatabase *pMMAdmDB)
6260 : {
6261 191 : if (!hMiraMonLayer || !pMMAdmDB)
6262 0 : return 1;
6263 :
6264 191 : if (MMIsEmptyString(pMMAdmDB->pszExtDBFLayerName))
6265 0 : return 0; // No file, no error. Just continue
6266 :
6267 191 : strcpy(pMMAdmDB->pMMBDXP->ReadingMode, "wb+");
6268 191 : if (FALSE == MM_CreateAndOpenDBFFile(pMMAdmDB->pMMBDXP,
6269 191 : pMMAdmDB->pszExtDBFLayerName))
6270 : {
6271 0 : MMCPLError(CE_Failure, CPLE_OpenFailed,
6272 : "Error pMMAdmDB: Cannot create or open file %s.",
6273 0 : pMMAdmDB->pszExtDBFLayerName);
6274 0 : return 1;
6275 : }
6276 :
6277 191 : fseek_function(pMMAdmDB->pMMBDXP->pfDataBase,
6278 : pMMAdmDB->pMMBDXP->FirstRecordOffset, SEEK_SET);
6279 :
6280 191 : if (MMInitFlush(&pMMAdmDB->FlushRecList, pMMAdmDB->pMMBDXP->pfDataBase,
6281 : MM_1MB, &pMMAdmDB->pRecList,
6282 191 : pMMAdmDB->pMMBDXP->FirstRecordOffset, 0))
6283 0 : return 1;
6284 :
6285 191 : pMMAdmDB->nNumRecordOnCourse =
6286 191 : (GUInt64)pMMAdmDB->pMMBDXP->BytesPerRecord + 1;
6287 191 : if (MMCheckSize_t(pMMAdmDB->nNumRecordOnCourse, 1))
6288 0 : return 1;
6289 191 : pMMAdmDB->szRecordOnCourse =
6290 191 : calloc_function((size_t)pMMAdmDB->nNumRecordOnCourse);
6291 191 : if (!pMMAdmDB->szRecordOnCourse)
6292 : {
6293 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
6294 : "Memory error in MiraMon "
6295 : "driver (MMInitMMDB())");
6296 0 : return 1;
6297 : }
6298 191 : return 0;
6299 : }
6300 :
6301 : // Creates a MiraMon database associated with a vector layer.
6302 : // It determines the number of fields and initializes the database header
6303 : // accordingly. Depending on the layer type (point, arc, polygon, or generic),
6304 : // it defines the fields and initializes the corresponding MiraMon database
6305 : // structures.
6306 107 : int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6307 : struct MM_POINT_2D *pFirstCoord)
6308 : {
6309 107 : struct MM_DATA_BASE_XP *pBD_XP = nullptr, *pBD_XP_Aux = nullptr;
6310 : struct MM_FIELD MMField;
6311 : size_t nIFieldLayer;
6312 107 : MM_EXT_DBF_N_FIELDS nIField = 0;
6313 : MM_EXT_DBF_N_FIELDS nNFields;
6314 :
6315 107 : if (!hMiraMonLayer)
6316 0 : return 1;
6317 :
6318 : // If the SRS is unknown, we attempt to deduce the appropriate number
6319 : // of decimals to be used in the reserved fields as LONG_ARC, PERIMETRE,
6320 : // or AREA using the coordinate values. It's not 100% reliable, but it's a
6321 : // good approximation.
6322 107 : if (hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_UNKNOWN_TYPE && pFirstCoord)
6323 : {
6324 70 : if (pFirstCoord->dfX < -360 || pFirstCoord->dfX > 360)
6325 8 : hMiraMonLayer->nSRSType = MM_SRS_LAYER_IS_PROJECTED_TYPE;
6326 : else
6327 62 : hMiraMonLayer->nSRSType = MM_SRS_LAYER_IS_GEOGRAPHIC_TYPE;
6328 : }
6329 :
6330 107 : if (hMiraMonLayer->bIsPoint)
6331 : {
6332 33 : if (hMiraMonLayer->pLayerDB)
6333 33 : nNFields =
6334 33 : MM_PRIVATE_POINT_DB_FIELDS + hMiraMonLayer->pLayerDB->nNFields;
6335 : else
6336 0 : nNFields = MM_PRIVATE_POINT_DB_FIELDS;
6337 :
6338 : // Before allocating new memory, there might be some previously allocated but unused memory.
6339 : // Let's free that memory first.
6340 33 : if (hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP)
6341 0 : MM_ReleaseDBFHeader(&hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP);
6342 :
6343 33 : pBD_XP = hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP =
6344 33 : MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet);
6345 :
6346 33 : if (!pBD_XP)
6347 0 : return 1;
6348 :
6349 33 : if (0 == (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstPointFieldsDB_XP(
6350 : pBD_XP)))
6351 0 : return 1;
6352 : }
6353 74 : else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
6354 : {
6355 30 : if (hMiraMonLayer->pLayerDB)
6356 30 : nNFields =
6357 30 : MM_PRIVATE_ARC_DB_FIELDS + hMiraMonLayer->pLayerDB->nNFields;
6358 : else
6359 0 : nNFields = MM_PRIVATE_ARC_DB_FIELDS;
6360 :
6361 : // Before allocating new memory, there might be some previously allocated but unused memory.
6362 : // Let's free that memory first.
6363 30 : if (hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP)
6364 0 : MM_ReleaseDBFHeader(&hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP);
6365 :
6366 30 : pBD_XP = hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP =
6367 30 : MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet);
6368 :
6369 30 : if (!pBD_XP)
6370 0 : return 1;
6371 :
6372 30 : if (0 == (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstArcFieldsDB_XP(
6373 : pBD_XP,
6374 30 : hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE
6375 : ? 3
6376 : : 9)))
6377 0 : return 1;
6378 :
6379 : // Before allocating new memory, there might be some previously allocated but unused memory.
6380 : // Let's free that memory first.
6381 30 : if (hMiraMonLayer->MMArc.MMNode.MMAdmDB.pMMBDXP)
6382 0 : MM_ReleaseDBFHeader(&hMiraMonLayer->MMArc.MMNode.MMAdmDB.pMMBDXP);
6383 :
6384 30 : pBD_XP_Aux = hMiraMonLayer->MMArc.MMNode.MMAdmDB.pMMBDXP =
6385 30 : MM_CreateDBFHeader(3, hMiraMonLayer->nCharSet);
6386 :
6387 30 : if (!pBD_XP_Aux)
6388 0 : return 1;
6389 :
6390 30 : if (0 == MM_DefineFirstNodeFieldsDB_XP(pBD_XP_Aux))
6391 0 : return 1;
6392 : }
6393 44 : else if (hMiraMonLayer->bIsPolygon)
6394 : {
6395 27 : if (hMiraMonLayer->pLayerDB)
6396 27 : nNFields = MM_PRIVATE_POLYGON_DB_FIELDS +
6397 27 : hMiraMonLayer->pLayerDB->nNFields;
6398 : else
6399 0 : nNFields = MM_PRIVATE_POLYGON_DB_FIELDS;
6400 :
6401 : // Before allocating new memory, there might be some previously allocated but unused memory.
6402 : // Let's free that memory first.
6403 27 : if (hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP)
6404 0 : MM_ReleaseDBFHeader(&hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP);
6405 :
6406 27 : pBD_XP = hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP =
6407 27 : MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet);
6408 :
6409 27 : if (!pBD_XP)
6410 0 : return 1;
6411 :
6412 27 : if (0 ==
6413 54 : (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstPolygonFieldsDB_XP(
6414 : pBD_XP,
6415 27 : hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE ? 3
6416 : : 9,
6417 27 : hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE
6418 : ? 3
6419 : : 12)))
6420 0 : return 1;
6421 :
6422 : // Before allocating new memory, there might be some previously allocated but unused memory.
6423 : // Let's free that memory first.
6424 27 : if (hMiraMonLayer->MMPolygon.MMArc.MMAdmDB.pMMBDXP)
6425 0 : MM_ReleaseDBFHeader(
6426 : &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB.pMMBDXP);
6427 :
6428 27 : pBD_XP_Aux = hMiraMonLayer->MMPolygon.MMArc.MMAdmDB.pMMBDXP =
6429 27 : MM_CreateDBFHeader(5, hMiraMonLayer->nCharSet);
6430 :
6431 27 : if (!pBD_XP_Aux)
6432 0 : return 1;
6433 :
6434 27 : if (0 == MM_DefineFirstArcFieldsDB_XP(
6435 : pBD_XP_Aux,
6436 27 : hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE
6437 : ? 3
6438 : : 9))
6439 0 : return 1;
6440 :
6441 : // Before allocating new memory, there might be some previously allocated but unused memory.
6442 : // Let's free that memory first.
6443 27 : if (hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB.pMMBDXP)
6444 0 : MM_ReleaseDBFHeader(
6445 : &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB.pMMBDXP);
6446 :
6447 27 : pBD_XP_Aux = hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB.pMMBDXP =
6448 27 : MM_CreateDBFHeader(3, hMiraMonLayer->nCharSet);
6449 :
6450 27 : if (!pBD_XP_Aux)
6451 0 : return 1;
6452 :
6453 27 : if (0 == MM_DefineFirstNodeFieldsDB_XP(pBD_XP_Aux))
6454 0 : return 1;
6455 : }
6456 17 : else if (hMiraMonLayer->bIsDBF)
6457 : {
6458 : // Creating only a DBF
6459 17 : if (hMiraMonLayer->pLayerDB)
6460 17 : nNFields = hMiraMonLayer->pLayerDB->nNFields;
6461 : else
6462 0 : nNFields = 0;
6463 :
6464 17 : pBD_XP = hMiraMonLayer->MMAdmDBWriting.pMMBDXP =
6465 17 : MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet);
6466 :
6467 17 : if (!pBD_XP)
6468 0 : return 1;
6469 : }
6470 : else
6471 0 : return 0;
6472 :
6473 : // After private MiraMon fields, other fields are added.
6474 : // If names are no compatible, some changes are done.
6475 107 : if (hMiraMonLayer->pLayerDB)
6476 : {
6477 682 : for (nIFieldLayer = 0; nIField < nNFields; nIField++, nIFieldLayer++)
6478 : {
6479 575 : MM_InitializeField(&MMField);
6480 575 : CPLStrlcpy(
6481 : MMField.FieldName,
6482 575 : hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].pszFieldName,
6483 : MM_MAX_LON_FIELD_NAME_DBF);
6484 :
6485 575 : CPLStrlcpy(MMField.FieldDescription[0],
6486 575 : hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6487 575 : .pszFieldDescription,
6488 : MM_MAX_BYTES_FIELD_DESC);
6489 :
6490 575 : MMField.BytesPerField =
6491 575 : hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].nFieldSize;
6492 575 : switch (hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].eFieldType)
6493 : {
6494 282 : case MM_Numeric:
6495 282 : MMField.FieldType = 'N';
6496 282 : if (hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6497 282 : .bIs64BitInteger)
6498 79 : MMField.Is64 = 1;
6499 282 : if (MMField.BytesPerField == 0)
6500 0 : MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_N_DBF;
6501 282 : break;
6502 192 : case MM_Character:
6503 192 : MMField.FieldType = 'C';
6504 192 : if (MMField.BytesPerField == 0)
6505 0 : MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_C_DBF;
6506 192 : break;
6507 68 : case MM_Data:
6508 68 : MMField.FieldType = 'D';
6509 68 : if (MMField.BytesPerField == 0)
6510 0 : MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_D_DBF;
6511 68 : break;
6512 33 : case MM_Logic:
6513 33 : MMField.FieldType = 'L';
6514 33 : if (MMField.BytesPerField == 0)
6515 0 : MMField.BytesPerField = 1;
6516 33 : break;
6517 0 : default:
6518 0 : MMField.FieldType = 'C';
6519 0 : if (MMField.BytesPerField == 0)
6520 0 : MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_C_DBF;
6521 : };
6522 :
6523 575 : MMField.DecimalsIfFloat =
6524 575 : (MM_BYTE)hMiraMonLayer->pLayerDB->pFields[nIFieldLayer]
6525 575 : .nNumberOfDecimals;
6526 :
6527 575 : MM_DuplicateFieldDBXP(pBD_XP->pField + nIField, &MMField);
6528 575 : MM_ModifyFieldNameAndDescriptorIfPresentBD_XP(
6529 575 : pBD_XP->pField + nIField, pBD_XP, FALSE, 0);
6530 575 : if (pBD_XP->pField[nIField].FieldType == 'F')
6531 0 : pBD_XP->pField[nIField].FieldType = 'N';
6532 : }
6533 : }
6534 :
6535 107 : if (hMiraMonLayer->bIsPoint)
6536 : {
6537 33 : if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB))
6538 0 : return 1;
6539 : }
6540 74 : else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
6541 : {
6542 30 : if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB))
6543 0 : return 1;
6544 :
6545 30 : if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMArc.MMNode.MMAdmDB))
6546 0 : return 1;
6547 : }
6548 44 : else if (hMiraMonLayer->bIsPolygon)
6549 : {
6550 27 : if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMAdmDB))
6551 0 : return 1;
6552 :
6553 27 : if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB))
6554 0 : return 1;
6555 :
6556 27 : if (MMInitMMDB(hMiraMonLayer,
6557 : &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB))
6558 0 : return 1;
6559 : }
6560 17 : else if (hMiraMonLayer->bIsDBF)
6561 : {
6562 17 : if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting))
6563 0 : return 1;
6564 : }
6565 107 : return 0;
6566 : }
6567 :
6568 : // Checks and fits the width of a specific field in a MiraMon database
6569 : // associated with a vector layer. It examines the length of the provided
6570 : // value and resizes the field width, if necessary, to accommodate the new
6571 : // value. If the new width exceeds the current width of the field,
6572 : // it updates the database structure, including the field width and
6573 : // the size of the record. Additionally, it reallocates memory if needed
6574 : // for the record handling buffer.
6575 :
6576 : static int
6577 2962 : MMTestAndFixValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer,
6578 : struct MMAdmDatabase *pMMAdmDB,
6579 : MM_EXT_DBF_N_FIELDS nIField, char *szValue)
6580 : {
6581 : struct MM_FIELD *camp;
6582 : MM_BYTES_PER_FIELD_TYPE_DBF nNewWidth;
6583 :
6584 2962 : if (!hMiraMonLayer || !pMMAdmDB || !pMMAdmDB->pMMBDXP ||
6585 2962 : !pMMAdmDB->pMMBDXP->pField || !pMMAdmDB->pMMBDXP->pfDataBase)
6586 0 : return 1;
6587 :
6588 2962 : camp = pMMAdmDB->pMMBDXP->pField + nIField;
6589 :
6590 2962 : if (!szValue)
6591 282 : return 0;
6592 :
6593 2680 : nNewWidth = (MM_BYTES_PER_FIELD_TYPE_DBF)strlen(szValue);
6594 2680 : if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, nNewWidth + 1))
6595 0 : return 1;
6596 :
6597 2680 : if (nNewWidth > camp->BytesPerField)
6598 : {
6599 117 : if (MM_WriteNRecordsMMBD_XPFile(pMMAdmDB))
6600 0 : return 1;
6601 :
6602 : // Flushing all to be flushed
6603 117 : pMMAdmDB->FlushRecList.SizeOfBlockToBeSaved = 0;
6604 117 : if (MMAppendBlockToBuffer(&pMMAdmDB->FlushRecList))
6605 0 : return 1;
6606 :
6607 117 : if (MM_ChangeDBFWidthField(
6608 : pMMAdmDB->pMMBDXP, nIField, nNewWidth,
6609 117 : pMMAdmDB->pMMBDXP->pField[nIField].DecimalsIfFloat))
6610 0 : return 1;
6611 :
6612 : // The record on course also has to change its size.
6613 117 : if ((GUInt64)pMMAdmDB->pMMBDXP->BytesPerRecord + 1 >=
6614 117 : pMMAdmDB->nNumRecordOnCourse)
6615 : {
6616 : void *pTmp;
6617 117 : if (nullptr == (pTmp = realloc_function(
6618 117 : pMMAdmDB->szRecordOnCourse,
6619 117 : (size_t)pMMAdmDB->pMMBDXP->BytesPerRecord + 1)))
6620 : {
6621 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
6622 : "Memory error in MiraMon "
6623 : "driver (MMTestAndFixValueToRecordDBXP())");
6624 0 : return 1;
6625 : }
6626 117 : pMMAdmDB->szRecordOnCourse = pTmp;
6627 : }
6628 :
6629 : // File has changed its size, so it has to be updated
6630 : // at the Flush tool
6631 117 : fseek_function(pMMAdmDB->pMMBDXP->pfDataBase, 0, SEEK_END);
6632 117 : pMMAdmDB->FlushRecList.OffsetWhereToFlush =
6633 117 : ftell_function(pMMAdmDB->pMMBDXP->pfDataBase);
6634 : }
6635 2680 : return 0;
6636 : }
6637 :
6638 : static int
6639 3434 : MMWriteValueToszStringToOperate(struct MiraMonVectLayerInfo *hMiraMonLayer,
6640 : const struct MM_FIELD *camp, const void *valor,
6641 : MM_BOOLEAN is_64)
6642 : {
6643 3434 : if (!hMiraMonLayer)
6644 0 : return 1;
6645 :
6646 3434 : if (!camp)
6647 0 : return 0;
6648 :
6649 3434 : if (MMResizeStringToOperateIfNeeded(hMiraMonLayer,
6650 3434 : camp->BytesPerField + 10))
6651 0 : return 1;
6652 :
6653 3434 : if (!valor)
6654 0 : *hMiraMonLayer->szStringToOperate = '\0';
6655 : else
6656 : {
6657 3434 : if (camp->FieldType == 'N')
6658 : {
6659 2836 : if (!is_64)
6660 : {
6661 962 : snprintf(hMiraMonLayer->szStringToOperate,
6662 962 : (size_t)hMiraMonLayer->nNumStringToOperate, "%*.*f",
6663 962 : camp->BytesPerField, camp->DecimalsIfFloat,
6664 : *(const double *)valor);
6665 : }
6666 : else
6667 : {
6668 1874 : snprintf(hMiraMonLayer->szStringToOperate,
6669 1874 : (size_t)hMiraMonLayer->nNumStringToOperate, "%*lld",
6670 : camp->BytesPerField, *(const GInt64 *)valor);
6671 : }
6672 : }
6673 : else
6674 : {
6675 598 : snprintf(hMiraMonLayer->szStringToOperate,
6676 598 : (size_t)hMiraMonLayer->nNumStringToOperate, "%-*s",
6677 : camp->BytesPerField, (const char *)valor);
6678 : }
6679 : }
6680 :
6681 3434 : return 0;
6682 : }
6683 :
6684 557 : int MMWritePreformatedNumberValueToRecordDBXP(
6685 : struct MiraMonVectLayerInfo *hMiraMonLayer, char *registre,
6686 : const struct MM_FIELD *camp, const char *valor)
6687 : {
6688 557 : if (!hMiraMonLayer)
6689 0 : return 1;
6690 :
6691 557 : if (!camp)
6692 0 : return 0;
6693 :
6694 557 : if (MMResizeStringToOperateIfNeeded(hMiraMonLayer,
6695 557 : camp->BytesPerField + 10))
6696 0 : return 1;
6697 :
6698 557 : if (!valor)
6699 0 : memset(hMiraMonLayer->szStringToOperate, 0, camp->BytesPerField);
6700 : else
6701 : {
6702 557 : snprintf(hMiraMonLayer->szStringToOperate,
6703 557 : (size_t)hMiraMonLayer->nNumStringToOperate, "%*s",
6704 : camp->BytesPerField, valor);
6705 : }
6706 :
6707 557 : memcpy(registre + camp->AccumulatedBytes, hMiraMonLayer->szStringToOperate,
6708 557 : camp->BytesPerField);
6709 557 : return 0;
6710 : }
6711 :
6712 2122 : int MMWriteValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer,
6713 : char *registre, const struct MM_FIELD *camp,
6714 : const void *valor, MM_BOOLEAN is_64)
6715 : {
6716 2122 : if (!hMiraMonLayer)
6717 0 : return 1;
6718 :
6719 2122 : if (!camp)
6720 0 : return 0;
6721 :
6722 2122 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, camp, valor, is_64))
6723 0 : return 1;
6724 :
6725 2122 : memcpy(registre + camp->AccumulatedBytes, hMiraMonLayer->szStringToOperate,
6726 2122 : camp->BytesPerField);
6727 2122 : return 0;
6728 : }
6729 :
6730 210 : static int MMAddFeatureRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6731 : struct MiraMonFeature *hMMFeature,
6732 : struct MMAdmDatabase *pMMAdmDB,
6733 : char *pszRecordOnCourse,
6734 : struct MM_FLUSH_INFO *pFlushRecList,
6735 : MM_EXT_DBF_N_RECORDS *nNumRecords,
6736 : MM_EXT_DBF_N_FIELDS nNumPrivateMMField)
6737 : {
6738 : MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord;
6739 : MM_EXT_DBF_N_FIELDS nIField;
6740 210 : struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6741 :
6742 210 : if (!hMiraMonLayer)
6743 0 : return 1;
6744 :
6745 210 : if (!hMMFeature)
6746 0 : return 1;
6747 :
6748 210 : pBD_XP = pMMAdmDB->pMMBDXP;
6749 447 : for (nIRecord = 0; nIRecord < hMMFeature->nNumMRecords; nIRecord++)
6750 : {
6751 1887 : for (nIField = 0; nIField < hMMFeature->pRecords[nIRecord].nNumField;
6752 1650 : nIField++)
6753 : {
6754 : // A field with no valid value is written as blank
6755 1650 : if (!hMMFeature->pRecords[nIRecord].pField[nIField].bIsValid)
6756 : {
6757 283 : memset(
6758 283 : pszRecordOnCourse +
6759 283 : pBD_XP->pField[nIField + nNumPrivateMMField]
6760 283 : .AccumulatedBytes,
6761 : ' ',
6762 283 : pBD_XP->pField[nIField + nNumPrivateMMField].BytesPerField);
6763 :
6764 283 : continue;
6765 : }
6766 1367 : if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'C' ||
6767 981 : pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'L' ||
6768 878 : pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'D')
6769 : {
6770 598 : if (MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse,
6771 598 : pBD_XP->pField + nIField +
6772 : nNumPrivateMMField,
6773 598 : hMMFeature->pRecords[nIRecord]
6774 598 : .pField[nIField]
6775 598 : .pDinValue,
6776 : FALSE))
6777 0 : return 1;
6778 : }
6779 769 : else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType ==
6780 769 : 'N' &&
6781 769 : !pBD_XP->pField[nIField + nNumPrivateMMField].Is64)
6782 : {
6783 557 : if (MMWritePreformatedNumberValueToRecordDBXP(
6784 : hMiraMonLayer, pszRecordOnCourse,
6785 557 : pBD_XP->pField + nIField + nNumPrivateMMField,
6786 557 : hMMFeature->pRecords[nIRecord]
6787 557 : .pField[nIField]
6788 557 : .pDinValue))
6789 0 : return 1;
6790 : }
6791 212 : else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType ==
6792 : 'N')
6793 : {
6794 212 : if (pBD_XP->pField[nIField + nNumPrivateMMField].Is64)
6795 : {
6796 212 : if (MMWriteValueToRecordDBXP(
6797 : hMiraMonLayer, pszRecordOnCourse,
6798 212 : pBD_XP->pField + nIField + nNumPrivateMMField,
6799 212 : &hMMFeature->pRecords[nIRecord]
6800 212 : .pField[nIField]
6801 : .iValue,
6802 : TRUE))
6803 0 : return 1;
6804 : }
6805 : }
6806 : }
6807 :
6808 237 : if (MMAppendBlockToBuffer(pFlushRecList))
6809 0 : return 1;
6810 :
6811 237 : (*nNumRecords)++;
6812 : }
6813 210 : return 0;
6814 : }
6815 :
6816 : // Adds feature records to a MiraMon database associated with a vector layer.
6817 1650 : static int MMDetectAndFixDBFWidthChange(
6818 : struct MiraMonVectLayerInfo *hMiraMonLayer,
6819 : struct MiraMonFeature *hMMFeature, struct MMAdmDatabase *pMMAdmDB,
6820 : MM_EXT_DBF_N_FIELDS nNumPrivateMMField,
6821 : MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord, MM_EXT_DBF_N_FIELDS nIField)
6822 : {
6823 1650 : if (!hMiraMonLayer)
6824 0 : return 1;
6825 :
6826 1650 : if (!hMMFeature)
6827 0 : return 1;
6828 :
6829 1650 : if (nIRecord >= hMMFeature->nNumMRecords)
6830 0 : return 1;
6831 :
6832 1650 : if (nIField >= hMMFeature->pRecords[nIRecord].nNumField)
6833 0 : return 1;
6834 :
6835 1650 : if (MMTestAndFixValueToRecordDBXP(
6836 : hMiraMonLayer, pMMAdmDB, nIField + nNumPrivateMMField,
6837 1650 : hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue))
6838 0 : return 1;
6839 :
6840 : // We analyze next fields
6841 1650 : if (nIField == hMMFeature->pRecords[nIRecord].nNumField - 1)
6842 : {
6843 237 : if (nIRecord + 1 < hMMFeature->nNumMRecords)
6844 : {
6845 27 : if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6846 : pMMAdmDB, nNumPrivateMMField,
6847 : nIRecord + 1, 0))
6848 0 : return 1;
6849 : }
6850 : else
6851 210 : return 0;
6852 : }
6853 : else
6854 : {
6855 1413 : if (nIField + 1 < hMMFeature->pRecords[nIRecord].nNumField)
6856 : {
6857 1413 : if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6858 : pMMAdmDB, nNumPrivateMMField,
6859 : nIRecord, nIField + 1))
6860 0 : return 1;
6861 : }
6862 : else
6863 0 : return 0;
6864 : }
6865 1440 : return 0;
6866 : } // End of MMDetectAndFixDBFWidthChange()
6867 :
6868 : // Adds a DBF record to a MiraMon table associated with a vector layer.
6869 : // It sets up flush settings for writing to the table and initializes
6870 : // variables needed for the process. Then, it checks and fixes the width
6871 : // change if necessary.
6872 34 : int MMAddDBFRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6873 : struct MiraMonFeature *hMMFeature)
6874 : {
6875 34 : struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6876 34 : MM_EXT_DBF_N_FIELDS nNumPrivateMMField = 0;
6877 : struct MM_FLUSH_INFO *pFlushRecList;
6878 :
6879 34 : if (!hMiraMonLayer)
6880 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6881 :
6882 34 : pBD_XP = hMiraMonLayer->MMAdmDBWriting.pMMBDXP;
6883 :
6884 : // Test length
6885 34 : if (hMMFeature && hMMFeature->nNumMRecords &&
6886 34 : hMMFeature->pRecords[0].nNumField)
6887 : {
6888 34 : if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6889 : &hMiraMonLayer->MMAdmDBWriting,
6890 : nNumPrivateMMField, 0, 0))
6891 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6892 : }
6893 :
6894 : // Adding record to the MiraMon table (extended DBF)
6895 : // Flush settings
6896 34 : pFlushRecList = &hMiraMonLayer->MMAdmDBWriting.FlushRecList;
6897 34 : pFlushRecList->pBlockWhereToSaveOrRead =
6898 34 : (void *)hMiraMonLayer->MMAdmDBWriting.pRecList;
6899 :
6900 34 : pFlushRecList->pBlockToBeSaved =
6901 34 : (void *)hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse;
6902 34 : pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
6903 :
6904 34 : if (MMAddFeatureRecordToMMDB(
6905 : hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMAdmDBWriting,
6906 : hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse, pFlushRecList,
6907 34 : &hMiraMonLayer->MMAdmDBWriting.pMMBDXP->nRecords,
6908 : nNumPrivateMMField))
6909 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6910 :
6911 : // In this case, the number of features is also updated
6912 34 : hMiraMonLayer->TopHeader.nElemCount =
6913 34 : hMiraMonLayer->MMAdmDBWriting.pMMBDXP->nRecords;
6914 :
6915 34 : return MM_CONTINUE_WRITING_FEATURES;
6916 : }
6917 :
6918 : // Adds a point record to a MiraMon table associated with a vector layer.
6919 87 : int MMAddPointRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6920 : struct MiraMonFeature *hMMFeature,
6921 : MM_INTERNAL_FID nElemCount)
6922 : {
6923 87 : struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6924 87 : MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_POINT_DB_FIELDS;
6925 : struct MM_FLUSH_INFO *pFlushRecList;
6926 :
6927 87 : if (!hMiraMonLayer)
6928 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6929 :
6930 87 : if (!hMMFeature)
6931 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6932 :
6933 : // In V1.1 only _UI32_MAX records number is allowed
6934 87 : if (MMCheckVersionForFID(hMiraMonLayer,
6935 87 : hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP->nRecords +
6936 87 : hMMFeature->nNumMRecords))
6937 : {
6938 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
6939 : "Error in MMCheckVersionForFID() (6)");
6940 0 : return MM_STOP_WRITING_FEATURES;
6941 : }
6942 :
6943 87 : pBD_XP = hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP;
6944 :
6945 : // Test length
6946 : // Private fields
6947 : // ID_GRAFIC
6948 87 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField,
6949 : &nElemCount, TRUE))
6950 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6951 87 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
6952 : &hMiraMonLayer->MMPoint.MMAdmDB, 0,
6953 : hMiraMonLayer->szStringToOperate))
6954 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6955 :
6956 : // GDAL fields
6957 87 : if (hMMFeature->nNumMRecords && hMMFeature->pRecords[0].nNumField)
6958 : {
6959 87 : if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
6960 : &hMiraMonLayer->MMPoint.MMAdmDB,
6961 : nNumPrivateMMField, 0, 0))
6962 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6963 : }
6964 :
6965 : // Now length is sure, write
6966 87 : memset(hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse, 0,
6967 87 : pBD_XP->BytesPerRecord);
6968 87 : MMWriteValueToRecordDBXP(hMiraMonLayer,
6969 : hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse,
6970 87 : pBD_XP->pField, &nElemCount, TRUE);
6971 :
6972 : // Adding record to the MiraMon table (extended DBF)
6973 : // Flush settings
6974 87 : pFlushRecList = &hMiraMonLayer->MMPoint.MMAdmDB.FlushRecList;
6975 87 : pFlushRecList->pBlockWhereToSaveOrRead =
6976 87 : (void *)hMiraMonLayer->MMPoint.MMAdmDB.pRecList;
6977 :
6978 87 : pFlushRecList->pBlockToBeSaved =
6979 87 : (void *)hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse;
6980 87 : pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
6981 :
6982 87 : if (MMAddFeatureRecordToMMDB(
6983 : hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMPoint.MMAdmDB,
6984 : hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse, pFlushRecList,
6985 87 : &hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP->nRecords,
6986 : nNumPrivateMMField))
6987 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
6988 87 : return MM_CONTINUE_WRITING_FEATURES;
6989 : }
6990 :
6991 : // Adds a stringline record to a MiraMon table associated with a vector layer.
6992 101 : int MMAddArcRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
6993 : struct MiraMonFeature *hMMFeature,
6994 : MM_INTERNAL_FID nElemCount, struct MM_AH *pArcHeader)
6995 : {
6996 101 : struct MM_DATA_BASE_XP *pBD_XP = nullptr;
6997 : struct MiraMonArcLayer *pMMArcLayer;
6998 101 : MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_ARC_DB_FIELDS;
6999 : struct MM_FLUSH_INFO *pFlushRecList;
7000 :
7001 101 : if (!hMiraMonLayer)
7002 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7003 :
7004 101 : if (hMiraMonLayer->bIsPolygon)
7005 53 : pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc;
7006 : else
7007 48 : pMMArcLayer = &hMiraMonLayer->MMArc;
7008 :
7009 : // In V1.1 only _UI32_MAX records number is allowed
7010 101 : if (hMiraMonLayer->bIsPolygon)
7011 : {
7012 53 : if (MMCheckVersionForFID(hMiraMonLayer,
7013 53 : pMMArcLayer->MMAdmDB.pMMBDXP->nRecords + 1))
7014 : {
7015 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
7016 : "Error in MMCheckVersionForFID() (7)");
7017 0 : return MM_STOP_WRITING_FEATURES;
7018 : }
7019 : }
7020 : else
7021 : {
7022 48 : if (MMCheckVersionForFID(hMiraMonLayer,
7023 48 : pMMArcLayer->MMAdmDB.pMMBDXP->nRecords +
7024 48 : hMMFeature->nNumMRecords))
7025 : {
7026 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
7027 : "Error in MMCheckVersionForFID() (8)");
7028 0 : return MM_STOP_WRITING_FEATURES;
7029 : }
7030 : }
7031 :
7032 101 : pBD_XP = pMMArcLayer->MMAdmDB.pMMBDXP;
7033 :
7034 : // Test length
7035 : // Private fields
7036 : // ID_GRAFIC
7037 101 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField,
7038 : &nElemCount, TRUE))
7039 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7040 101 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 0,
7041 : hMiraMonLayer->szStringToOperate))
7042 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7043 :
7044 : // N_VERTEXS
7045 101 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 1,
7046 101 : &pArcHeader->nElemCount, TRUE))
7047 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7048 101 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 1,
7049 : hMiraMonLayer->szStringToOperate))
7050 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7051 :
7052 : // LENGTH
7053 101 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 2,
7054 101 : &pArcHeader->dfLength, FALSE))
7055 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7056 101 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 2,
7057 : hMiraMonLayer->szStringToOperate))
7058 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7059 :
7060 : // NODE_INI
7061 101 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 3,
7062 101 : &pArcHeader->nFirstIdNode, TRUE))
7063 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7064 101 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 3,
7065 : hMiraMonLayer->szStringToOperate))
7066 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7067 :
7068 : // NODE_FI
7069 101 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 4,
7070 101 : &pArcHeader->nLastIdNode, TRUE))
7071 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7072 101 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 4,
7073 : hMiraMonLayer->szStringToOperate))
7074 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7075 :
7076 : // GDAL fields
7077 101 : if (!hMiraMonLayer->bIsPolygon)
7078 : {
7079 48 : if (hMMFeature->nNumMRecords && hMMFeature->pRecords[0].nNumField)
7080 : {
7081 48 : if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
7082 : &pMMArcLayer->MMAdmDB,
7083 : nNumPrivateMMField, 0, 0))
7084 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7085 : }
7086 : }
7087 :
7088 : // Now length is sure, write
7089 101 : memset(pMMArcLayer->MMAdmDB.szRecordOnCourse, 0, pBD_XP->BytesPerRecord);
7090 101 : MMWriteValueToRecordDBXP(hMiraMonLayer,
7091 : pMMArcLayer->MMAdmDB.szRecordOnCourse,
7092 101 : pBD_XP->pField, &nElemCount, TRUE);
7093 :
7094 101 : MMWriteValueToRecordDBXP(hMiraMonLayer,
7095 : pMMArcLayer->MMAdmDB.szRecordOnCourse,
7096 101 : pBD_XP->pField + 1, &pArcHeader->nElemCount, TRUE);
7097 :
7098 101 : MMWriteValueToRecordDBXP(hMiraMonLayer,
7099 : pMMArcLayer->MMAdmDB.szRecordOnCourse,
7100 101 : pBD_XP->pField + 2, &pArcHeader->dfLength, FALSE);
7101 :
7102 101 : MMWriteValueToRecordDBXP(
7103 : hMiraMonLayer, pMMArcLayer->MMAdmDB.szRecordOnCourse,
7104 101 : pBD_XP->pField + 3, &pArcHeader->nFirstIdNode, TRUE);
7105 :
7106 101 : MMWriteValueToRecordDBXP(
7107 : hMiraMonLayer, pMMArcLayer->MMAdmDB.szRecordOnCourse,
7108 101 : pBD_XP->pField + 4, &pArcHeader->nLastIdNode, TRUE);
7109 :
7110 : // Adding record to the MiraMon table (extended DBF)
7111 : // Flush settings
7112 101 : pFlushRecList = &pMMArcLayer->MMAdmDB.FlushRecList;
7113 101 : pFlushRecList->pBlockWhereToSaveOrRead =
7114 101 : (void *)pMMArcLayer->MMAdmDB.pRecList;
7115 :
7116 101 : pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
7117 101 : pFlushRecList->pBlockToBeSaved =
7118 101 : (void *)pMMArcLayer->MMAdmDB.szRecordOnCourse;
7119 :
7120 101 : if (hMiraMonLayer->bIsPolygon)
7121 : {
7122 53 : if (MMAppendBlockToBuffer(pFlushRecList))
7123 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7124 53 : pMMArcLayer->MMAdmDB.pMMBDXP->nRecords++;
7125 53 : return MM_CONTINUE_WRITING_FEATURES;
7126 : }
7127 :
7128 48 : pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
7129 48 : if (MMAddFeatureRecordToMMDB(
7130 : hMiraMonLayer, hMMFeature, &pMMArcLayer->MMAdmDB,
7131 : pMMArcLayer->MMAdmDB.szRecordOnCourse, pFlushRecList,
7132 48 : &pMMArcLayer->MMAdmDB.pMMBDXP->nRecords, nNumPrivateMMField))
7133 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7134 48 : return MM_CONTINUE_WRITING_FEATURES;
7135 : }
7136 :
7137 : // Adds a node record to a MiraMon table associated with a vector layer.
7138 149 : int MMAddNodeRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
7139 : MM_INTERNAL_FID nElemCount, struct MM_NH *pNodeHeader)
7140 : {
7141 149 : struct MM_DATA_BASE_XP *pBD_XP = nullptr;
7142 : struct MiraMonNodeLayer *pMMNodeLayer;
7143 : double nDoubleValue;
7144 :
7145 149 : if (!hMiraMonLayer)
7146 0 : return 1;
7147 :
7148 149 : if (hMiraMonLayer->bIsPolygon)
7149 53 : pMMNodeLayer = &hMiraMonLayer->MMPolygon.MMArc.MMNode;
7150 : else
7151 96 : pMMNodeLayer = &hMiraMonLayer->MMArc.MMNode;
7152 :
7153 149 : if (!pMMNodeLayer)
7154 : {
7155 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
7156 : "Error in pMMNodeLayer() (1)");
7157 0 : return MM_STOP_WRITING_FEATURES;
7158 : }
7159 :
7160 : // In V1.1 only _UI32_MAX records number is allowed
7161 149 : if (MMCheckVersionForFID(hMiraMonLayer,
7162 149 : pMMNodeLayer->MMAdmDB.pMMBDXP->nRecords + 1))
7163 : {
7164 0 : MMCPLError(CE_Failure, CPLE_NotSupported,
7165 : "Error in MMCheckVersionForFID() (9)");
7166 0 : return MM_STOP_WRITING_FEATURES;
7167 : }
7168 :
7169 : // Test length
7170 : // Private fields
7171 : // ID_GRAFIC
7172 149 : if (MMWriteValueToszStringToOperate(hMiraMonLayer,
7173 149 : pMMNodeLayer->MMAdmDB.pMMBDXP->pField,
7174 : &nElemCount, TRUE))
7175 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7176 149 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 0,
7177 : hMiraMonLayer->szStringToOperate))
7178 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7179 :
7180 : // ARCS_A_NOD
7181 149 : nDoubleValue = pNodeHeader->nArcsCount;
7182 149 : if (MMWriteValueToszStringToOperate(
7183 149 : hMiraMonLayer, pMMNodeLayer->MMAdmDB.pMMBDXP->pField + 1,
7184 : &nDoubleValue, FALSE))
7185 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7186 149 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 1,
7187 : hMiraMonLayer->szStringToOperate))
7188 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7189 :
7190 : // TIPUS_NODE
7191 149 : nDoubleValue = pNodeHeader->cNodeType;
7192 149 : if (MMWriteValueToszStringToOperate(
7193 149 : hMiraMonLayer, pMMNodeLayer->MMAdmDB.pMMBDXP->pField + 2,
7194 : &nDoubleValue, FALSE))
7195 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7196 149 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 2,
7197 : hMiraMonLayer->szStringToOperate))
7198 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7199 :
7200 : // Adding record to the MiraMon table (extended DBF)
7201 : // Flush settings
7202 149 : pMMNodeLayer->MMAdmDB.FlushRecList.pBlockWhereToSaveOrRead =
7203 149 : (void *)pMMNodeLayer->MMAdmDB.pRecList;
7204 :
7205 149 : pBD_XP = pMMNodeLayer->MMAdmDB.pMMBDXP;
7206 :
7207 149 : pMMNodeLayer->MMAdmDB.FlushRecList.SizeOfBlockToBeSaved =
7208 149 : pBD_XP->BytesPerRecord;
7209 149 : pMMNodeLayer->MMAdmDB.FlushRecList.pBlockToBeSaved =
7210 149 : (void *)pMMNodeLayer->MMAdmDB.szRecordOnCourse;
7211 :
7212 149 : memset(pMMNodeLayer->MMAdmDB.szRecordOnCourse, 0, pBD_XP->BytesPerRecord);
7213 149 : MMWriteValueToRecordDBXP(hMiraMonLayer,
7214 : pMMNodeLayer->MMAdmDB.szRecordOnCourse,
7215 149 : pBD_XP->pField, &nElemCount, TRUE);
7216 :
7217 149 : nDoubleValue = pNodeHeader->nArcsCount;
7218 149 : MMWriteValueToRecordDBXP(hMiraMonLayer,
7219 : pMMNodeLayer->MMAdmDB.szRecordOnCourse,
7220 149 : pBD_XP->pField + 1, &nDoubleValue, FALSE);
7221 :
7222 149 : nDoubleValue = pNodeHeader->cNodeType;
7223 149 : MMWriteValueToRecordDBXP(hMiraMonLayer,
7224 : pMMNodeLayer->MMAdmDB.szRecordOnCourse,
7225 149 : pBD_XP->pField + 2, &nDoubleValue, FALSE);
7226 :
7227 149 : if (MMAppendBlockToBuffer(&pMMNodeLayer->MMAdmDB.FlushRecList))
7228 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7229 149 : pMMNodeLayer->MMAdmDB.pMMBDXP->nRecords++;
7230 149 : return MM_CONTINUE_WRITING_FEATURES;
7231 : }
7232 :
7233 : // Adds a polygon or multipolygon record to a MiraMon table
7234 : // associated with a vector layer.
7235 68 : int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer,
7236 : struct MiraMonFeature *hMMFeature,
7237 : MM_INTERNAL_FID nElemCount,
7238 : MM_N_VERTICES_TYPE nVerticesCount,
7239 : struct MM_PH *pPolHeader)
7240 : {
7241 68 : struct MM_DATA_BASE_XP *pBD_XP = nullptr;
7242 68 : MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_POLYGON_DB_FIELDS;
7243 : struct MM_FLUSH_INFO *pFlushRecList;
7244 :
7245 68 : if (!hMiraMonLayer)
7246 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7247 :
7248 : // In V1.1 only _UI32_MAX records number is allowed
7249 68 : if (MMCheckVersionForFID(
7250 68 : hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords +
7251 68 : (hMMFeature ? hMMFeature->nNumMRecords : 0)))
7252 0 : return MM_STOP_WRITING_FEATURES;
7253 :
7254 68 : pBD_XP = hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP;
7255 :
7256 : // Test length
7257 : // Private fields
7258 : // ID_GRAFIC
7259 68 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField,
7260 : &nElemCount, TRUE))
7261 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7262 68 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
7263 : &hMiraMonLayer->MMPolygon.MMAdmDB, 0,
7264 : hMiraMonLayer->szStringToOperate))
7265 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7266 :
7267 : // The other fields are valid if pPolHeader exists (it is not
7268 : // the universal polygon)
7269 68 : if (pPolHeader)
7270 : {
7271 : // N_VERTEXS
7272 41 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 1,
7273 : &nVerticesCount, TRUE))
7274 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7275 41 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
7276 : &hMiraMonLayer->MMPolygon.MMAdmDB, 1,
7277 : hMiraMonLayer->szStringToOperate))
7278 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7279 :
7280 : // PERIMETER
7281 41 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 2,
7282 41 : &pPolHeader->dfPerimeter, FALSE))
7283 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7284 41 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
7285 : &hMiraMonLayer->MMPolygon.MMAdmDB, 2,
7286 : hMiraMonLayer->szStringToOperate))
7287 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7288 :
7289 : // AREA
7290 41 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 3,
7291 41 : &pPolHeader->dfArea, FALSE))
7292 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7293 41 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
7294 : &hMiraMonLayer->MMPolygon.MMAdmDB, 3,
7295 : hMiraMonLayer->szStringToOperate))
7296 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7297 :
7298 : // N_ARCS
7299 41 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 4,
7300 41 : &pPolHeader->nArcsCount, TRUE))
7301 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7302 41 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
7303 : &hMiraMonLayer->MMPolygon.MMAdmDB, 4,
7304 : hMiraMonLayer->szStringToOperate))
7305 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7306 :
7307 : // N_POLIG
7308 41 : if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 5,
7309 41 : &pPolHeader->nRingsCount, TRUE))
7310 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7311 41 : if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer,
7312 : &hMiraMonLayer->MMPolygon.MMAdmDB, 5,
7313 : hMiraMonLayer->szStringToOperate))
7314 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7315 : }
7316 :
7317 : // GDAL fields
7318 68 : if (hMMFeature && hMMFeature->nNumMRecords &&
7319 41 : hMMFeature->pRecords[0].nNumField)
7320 : {
7321 41 : if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature,
7322 : &hMiraMonLayer->MMPolygon.MMAdmDB,
7323 : nNumPrivateMMField, 0, 0))
7324 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7325 : }
7326 :
7327 : // Adding record to the MiraMon table (extended DBF)
7328 : // Flush settings
7329 68 : pFlushRecList = &hMiraMonLayer->MMPolygon.MMAdmDB.FlushRecList;
7330 68 : pFlushRecList->pBlockWhereToSaveOrRead =
7331 68 : (void *)hMiraMonLayer->MMPolygon.MMAdmDB.pRecList;
7332 :
7333 68 : pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
7334 68 : pFlushRecList->pBlockToBeSaved =
7335 68 : (void *)hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse;
7336 :
7337 : // Now length is sure, write
7338 68 : memset(hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, ' ',
7339 68 : pBD_XP->BytesPerRecord);
7340 68 : if (MMWriteValueToRecordDBXP(
7341 : hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
7342 68 : pBD_XP->pField, &nElemCount, TRUE))
7343 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7344 :
7345 68 : if (!hMMFeature)
7346 : {
7347 27 : if (MMAppendBlockToBuffer(pFlushRecList))
7348 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7349 27 : hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords++;
7350 27 : return MM_CONTINUE_WRITING_FEATURES;
7351 : }
7352 :
7353 41 : if (pPolHeader)
7354 : {
7355 41 : MMWriteValueToRecordDBXP(
7356 : hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
7357 41 : pBD_XP->pField + 1, &nVerticesCount, TRUE);
7358 :
7359 41 : MMWriteValueToRecordDBXP(
7360 : hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
7361 41 : pBD_XP->pField + 2, &pPolHeader->dfPerimeter, FALSE);
7362 :
7363 41 : MMWriteValueToRecordDBXP(
7364 : hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
7365 41 : pBD_XP->pField + 3, &pPolHeader->dfArea, FALSE);
7366 :
7367 41 : MMWriteValueToRecordDBXP(
7368 : hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
7369 41 : pBD_XP->pField + 4, &pPolHeader->nArcsCount, TRUE);
7370 :
7371 41 : MMWriteValueToRecordDBXP(
7372 : hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse,
7373 41 : pBD_XP->pField + 5, &pPolHeader->nRingsCount, TRUE);
7374 : }
7375 :
7376 41 : pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord;
7377 41 : if (MMAddFeatureRecordToMMDB(
7378 : hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMPolygon.MMAdmDB,
7379 : hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, pFlushRecList,
7380 41 : &hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords,
7381 : nNumPrivateMMField))
7382 0 : return MM_FATAL_ERROR_WRITING_FEATURES;
7383 41 : return MM_CONTINUE_WRITING_FEATURES;
7384 : }
7385 :
7386 : // Close the MiraMon database associated with a vector layer.
7387 436 : static int MMCloseMMBD_XPFile(struct MiraMonVectLayerInfo *hMiraMonLayer,
7388 : struct MMAdmDatabase *MMAdmDB)
7389 : {
7390 436 : int ret_code = 1;
7391 436 : if (!hMiraMonLayer)
7392 0 : return 1;
7393 :
7394 436 : if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE)
7395 : {
7396 191 : if (!MMAdmDB->pMMBDXP ||
7397 191 : (MMAdmDB->pMMBDXP && !MMAdmDB->pMMBDXP->pfDataBase))
7398 : {
7399 : // In case of 0 elements created we have to
7400 : // create an empty DBF
7401 0 : if (hMiraMonLayer->bIsPolygon)
7402 : {
7403 0 : if (hMiraMonLayer->TopHeader.nElemCount <= 1)
7404 : {
7405 0 : if (MMCreateMMDB(hMiraMonLayer, nullptr))
7406 : {
7407 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
7408 : "Memory error in MiraMon "
7409 : "driver (MMCreateMMDB())");
7410 0 : goto end_label;
7411 : }
7412 : }
7413 : }
7414 0 : else if (hMiraMonLayer->bIsPoint || hMiraMonLayer->bIsArc)
7415 : {
7416 0 : if (hMiraMonLayer->TopHeader.nElemCount == 0)
7417 : {
7418 0 : if (MMCreateMMDB(hMiraMonLayer, nullptr))
7419 : {
7420 0 : MMCPLError(CE_Failure, CPLE_OutOfMemory,
7421 : "Memory error in MiraMon "
7422 : "driver (MMCreateMMDB())");
7423 0 : goto end_label;
7424 : }
7425 : }
7426 : }
7427 : }
7428 :
7429 191 : if (MM_WriteNRecordsMMBD_XPFile(MMAdmDB))
7430 0 : goto end_label;
7431 :
7432 : // Flushing all to be flushed
7433 191 : MMAdmDB->FlushRecList.SizeOfBlockToBeSaved = 0;
7434 191 : if (MMAppendBlockToBuffer(&MMAdmDB->FlushRecList))
7435 0 : goto end_label;
7436 : }
7437 :
7438 436 : ret_code = 0;
7439 436 : end_label:
7440 : // Closing database files
7441 436 : if (MMAdmDB && MMAdmDB->pMMBDXP && MMAdmDB->pMMBDXP->pfDataBase)
7442 191 : fclose_and_nullify(&MMAdmDB->pMMBDXP->pfDataBase);
7443 :
7444 436 : return ret_code;
7445 : }
7446 :
7447 226 : int MMCloseMMBD_XP(struct MiraMonVectLayerInfo *hMiraMonLayer)
7448 : {
7449 226 : int ret_code = 0;
7450 226 : if (!hMiraMonLayer)
7451 0 : return 1;
7452 :
7453 226 : if (hMiraMonLayer->pMMBDXP && hMiraMonLayer->pMMBDXP->pfDataBase)
7454 : {
7455 111 : fclose_and_nullify(&hMiraMonLayer->pMMBDXP->pfDataBase);
7456 : }
7457 :
7458 226 : if (hMiraMonLayer->bIsPoint)
7459 : ret_code =
7460 74 : MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB);
7461 152 : else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
7462 : {
7463 60 : if (MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB))
7464 0 : ret_code = 1;
7465 60 : if (MMCloseMMBD_XPFile(hMiraMonLayer,
7466 : &hMiraMonLayer->MMArc.MMNode.MMAdmDB))
7467 0 : ret_code = 1;
7468 : }
7469 92 : else if (hMiraMonLayer->bIsPolygon)
7470 : {
7471 75 : if (MMCloseMMBD_XPFile(hMiraMonLayer,
7472 : &hMiraMonLayer->MMPolygon.MMAdmDB))
7473 0 : ret_code = 1;
7474 75 : if (MMCloseMMBD_XPFile(hMiraMonLayer,
7475 : &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB))
7476 0 : ret_code = 1;
7477 75 : if (MMCloseMMBD_XPFile(hMiraMonLayer,
7478 : &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB))
7479 0 : ret_code = 1;
7480 : }
7481 17 : else if (hMiraMonLayer->bIsDBF)
7482 : ret_code =
7483 17 : MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting);
7484 :
7485 226 : return ret_code;
7486 : }
7487 :
7488 : // Destroys the memory used to create a MiraMon table associated
7489 : // with a vector layer.
7490 436 : static void MMDestroyMMDBFile(struct MiraMonVectLayerInfo *hMiraMonLayer,
7491 : struct MMAdmDatabase *pMMAdmDB)
7492 : {
7493 436 : if (!hMiraMonLayer)
7494 0 : return;
7495 :
7496 436 : if (pMMAdmDB && pMMAdmDB->szRecordOnCourse)
7497 : {
7498 44 : free_function(pMMAdmDB->szRecordOnCourse);
7499 44 : pMMAdmDB->szRecordOnCourse = nullptr;
7500 : }
7501 436 : if (hMiraMonLayer->szStringToOperate)
7502 : {
7503 0 : free_function(hMiraMonLayer->szStringToOperate);
7504 0 : hMiraMonLayer->szStringToOperate = nullptr;
7505 0 : hMiraMonLayer->nNumStringToOperate = 0;
7506 : }
7507 :
7508 436 : if (pMMAdmDB && pMMAdmDB->pMMBDXP)
7509 : {
7510 307 : MM_ReleaseDBFHeader(&pMMAdmDB->pMMBDXP);
7511 307 : hMiraMonLayer->pMMBDXP = nullptr;
7512 : }
7513 436 : if (pMMAdmDB && pMMAdmDB->pRecList)
7514 : {
7515 44 : free_function(pMMAdmDB->pRecList);
7516 44 : pMMAdmDB->pRecList = nullptr;
7517 : }
7518 : }
7519 :
7520 804 : void MMDestroyMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer)
7521 : {
7522 804 : if (!hMiraMonLayer)
7523 0 : return;
7524 :
7525 804 : if (hMiraMonLayer->bIsPoint)
7526 : {
7527 74 : MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB);
7528 74 : return;
7529 : }
7530 730 : if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon)
7531 : {
7532 60 : MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB);
7533 60 : MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMNode.MMAdmDB);
7534 60 : return;
7535 : }
7536 670 : if (hMiraMonLayer->bIsPolygon)
7537 : {
7538 75 : MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMAdmDB);
7539 75 : MMDestroyMMDBFile(hMiraMonLayer,
7540 : &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB);
7541 75 : MMDestroyMMDBFile(hMiraMonLayer,
7542 : &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB);
7543 : }
7544 670 : if (hMiraMonLayer->bIsDBF)
7545 17 : MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting);
7546 : }
7547 : #ifdef GDAL_COMPILATION
7548 : CPL_C_END // Necessary for compiling in GDAL project
7549 : #endif
|