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