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