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