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