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