LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/miramon - mm_gdal_functions.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 1015 1609 63.1 %
Date: 2025-05-31 00:00:17 Functions: 51 53 96.2 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  C MiraMon code adapted to be used in GDAL
       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 "ogr_api.h"            // For CPL_C_START
      19             : #include "mm_gdal_functions.h"  // For CPLStrlcpy()
      20             : #include "mm_wrlayr.h"          // For VSIFCloseL()...
      21             : #ifdef EMBED_RESOURCE_FILES
      22             : #include "embedded_resources.h"
      23             : #endif
      24             : 
      25             : CPL_C_START              // Necessary for compiling in GDAL project
      26             : #include "cpl_string.h"  // For CPL_ENC_UTF8
      27             : 
      28             :     char szInternalGraphicIdentifierEng[MM_MAX_IDENTIFIER_SIZE];
      29             : char szInternalGraphicIdentifierCat[MM_MAX_IDENTIFIER_SIZE];
      30             : char szInternalGraphicIdentifierSpa[MM_MAX_IDENTIFIER_SIZE];
      31             : 
      32             : char szNumberOfVerticesEng[MM_MAX_IDENTIFIER_SIZE];
      33             : char szNumberOfVerticesCat[MM_MAX_IDENTIFIER_SIZE];
      34             : char szNumberOfVerticesSpa[MM_MAX_IDENTIFIER_SIZE];
      35             : 
      36             : char szLengthOfAarcEng[MM_MAX_IDENTIFIER_SIZE];
      37             : char szLengthOfAarcCat[MM_MAX_IDENTIFIER_SIZE];
      38             : char szLengthOfAarcSpa[MM_MAX_IDENTIFIER_SIZE];
      39             : 
      40             : char szInitialNodeEng[MM_MAX_IDENTIFIER_SIZE];
      41             : char szInitialNodeCat[MM_MAX_IDENTIFIER_SIZE];
      42             : char szInitialNodeSpa[MM_MAX_IDENTIFIER_SIZE];
      43             : 
      44             : char szFinalNodeEng[MM_MAX_IDENTIFIER_SIZE];
      45             : char szFinalNodeCat[MM_MAX_IDENTIFIER_SIZE];
      46             : char szFinalNodeSpa[MM_MAX_IDENTIFIER_SIZE];
      47             : 
      48             : char szNumberOfArcsToNodeEng[MM_MAX_IDENTIFIER_SIZE];
      49             : char szNumberOfArcsToNodeCat[MM_MAX_IDENTIFIER_SIZE];
      50             : char szNumberOfArcsToNodeSpa[MM_MAX_IDENTIFIER_SIZE];
      51             : 
      52             : char szNodeTypeEng[MM_MAX_IDENTIFIER_SIZE];
      53             : char szNodeTypeCat[MM_MAX_IDENTIFIER_SIZE];
      54             : char szNodeTypeSpa[MM_MAX_IDENTIFIER_SIZE];
      55             : 
      56             : char szPerimeterOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE];
      57             : char szPerimeterOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE];
      58             : char szPerimeterOfThePolygonSpa[MM_MAX_IDENTIFIER_SIZE];
      59             : 
      60             : char szAreaOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE];
      61             : char szAreaOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE];
      62             : char szAreaOfThePolygonSpa[MM_MAX_IDENTIFIER_SIZE];
      63             : 
      64             : char szNumberOfArcsEng[MM_MAX_IDENTIFIER_SIZE];
      65             : char szNumberOfArcsCat[MM_MAX_IDENTIFIER_SIZE];
      66             : char szNumberOfArcsSpa[MM_MAX_IDENTIFIER_SIZE];
      67             : 
      68             : char szNumberOfElementaryPolygonsEng[MM_MAX_IDENTIFIER_SIZE];
      69             : char szNumberOfElementaryPolygonsCat[MM_MAX_IDENTIFIER_SIZE];
      70             : char szNumberOfElementaryPolygonsSpa[MM_MAX_IDENTIFIER_SIZE];
      71             : 
      72         328 : void MM_FillFieldDescriptorByLanguage(void)
      73             : {
      74         328 :     CPLStrlcpy(szInternalGraphicIdentifierEng, "Internal Graphic identifier",
      75             :                MM_MAX_IDENTIFIER_SIZE);
      76         328 :     CPLStrlcpy(szInternalGraphicIdentifierCat, "Identificador Grafic intern",
      77             :                MM_MAX_IDENTIFIER_SIZE);
      78         328 :     *(unsigned char *)&szInternalGraphicIdentifierCat[16] = MM_a_WITH_GRAVE;
      79         328 :     CPLStrlcpy(szInternalGraphicIdentifierSpa, "Identificador Grafico interno",
      80             :                MM_MAX_IDENTIFIER_SIZE);
      81         328 :     *(unsigned char *)&szInternalGraphicIdentifierSpa[16] = MM_a_WITH_ACUTE;
      82             : 
      83         328 :     CPLStrlcpy(szNumberOfVerticesEng, "Number of vertices",
      84             :                MM_MAX_IDENTIFIER_SIZE);
      85         328 :     CPLStrlcpy(szNumberOfVerticesCat, "Nombre de vertexs",
      86             :                MM_MAX_IDENTIFIER_SIZE);
      87         328 :     CPLStrlcpy(szNumberOfVerticesSpa, "Numero de vertices",
      88             :                MM_MAX_IDENTIFIER_SIZE);
      89         328 :     *(unsigned char *)&szNumberOfVerticesCat[11] = MM_e_WITH_GRAVE;
      90         328 :     *(unsigned char *)&szNumberOfVerticesSpa[1] = MM_u_WITH_ACUTE;
      91         328 :     *(unsigned char *)&szNumberOfVerticesSpa[11] = MM_e_WITH_ACUTE;
      92             : 
      93         328 :     CPLStrlcpy(szLengthOfAarcEng, "Length of arc", MM_MAX_IDENTIFIER_SIZE);
      94         328 :     CPLStrlcpy(szLengthOfAarcCat, "Longitud de l'arc", MM_MAX_IDENTIFIER_SIZE);
      95         328 :     CPLStrlcpy(szLengthOfAarcSpa, "Longitud del arco", MM_MAX_IDENTIFIER_SIZE);
      96             : 
      97         328 :     CPLStrlcpy(szInitialNodeEng, "Initial node", MM_MAX_IDENTIFIER_SIZE);
      98         328 :     CPLStrlcpy(szInitialNodeCat, "Node inicial", MM_MAX_IDENTIFIER_SIZE);
      99         328 :     CPLStrlcpy(szInitialNodeSpa, "Nodo inicial", MM_MAX_IDENTIFIER_SIZE);
     100             : 
     101         328 :     CPLStrlcpy(szFinalNodeEng, "Final node", MM_MAX_IDENTIFIER_SIZE);
     102         328 :     CPLStrlcpy(szFinalNodeCat, "Node final", MM_MAX_IDENTIFIER_SIZE);
     103         328 :     CPLStrlcpy(szFinalNodeSpa, "Nodo final", MM_MAX_IDENTIFIER_SIZE);
     104             : 
     105         328 :     CPLStrlcpy(szNumberOfArcsToNodeEng, "Number of arcs to node",
     106             :                MM_MAX_IDENTIFIER_SIZE);
     107         328 :     CPLStrlcpy(szNumberOfArcsToNodeCat, "Nombre d'arcs al node",
     108             :                MM_MAX_IDENTIFIER_SIZE);
     109         328 :     CPLStrlcpy(szNumberOfArcsToNodeSpa, "Numero de arcos al nodo",
     110             :                MM_MAX_IDENTIFIER_SIZE);
     111         328 :     *(unsigned char *)&szNumberOfArcsToNodeSpa[1] = MM_u_WITH_ACUTE;
     112             : 
     113         328 :     CPLStrlcpy(szNodeTypeEng, "Node type", MM_MAX_IDENTIFIER_SIZE);
     114         328 :     CPLStrlcpy(szNodeTypeCat, "Tipus de node", MM_MAX_IDENTIFIER_SIZE);
     115         328 :     CPLStrlcpy(szNodeTypeSpa, "Tipo de nodo", MM_MAX_IDENTIFIER_SIZE);
     116             : 
     117         328 :     CPLStrlcpy(szPerimeterOfThePolygonEng, "Perimeter of the polygon",
     118             :                MM_MAX_IDENTIFIER_SIZE);
     119         328 :     CPLStrlcpy(szPerimeterOfThePolygonCat, "Perimetre del poligon",
     120             :                MM_MAX_IDENTIFIER_SIZE);
     121         328 :     CPLStrlcpy(szPerimeterOfThePolygonSpa, "Perimetro del poligono",
     122             :                MM_MAX_IDENTIFIER_SIZE);
     123             : 
     124         328 :     *(unsigned char *)&szPerimeterOfThePolygonCat[3] = MM_i_WITH_ACUTE;
     125         328 :     *(unsigned char *)&szPerimeterOfThePolygonSpa[3] = MM_i_WITH_ACUTE;
     126         328 :     *(unsigned char *)&szPerimeterOfThePolygonCat[17] = MM_i_WITH_ACUTE;
     127         328 :     *(unsigned char *)&szPerimeterOfThePolygonSpa[17] = MM_i_WITH_ACUTE;
     128             : 
     129         328 :     CPLStrlcpy(szAreaOfThePolygonEng, "Area of the polygon",
     130             :                MM_MAX_IDENTIFIER_SIZE);
     131         328 :     CPLStrlcpy(szAreaOfThePolygonCat, "Area del poligon",
     132             :                MM_MAX_IDENTIFIER_SIZE);
     133         328 :     CPLStrlcpy(szAreaOfThePolygonSpa, "Area del poligono",
     134             :                MM_MAX_IDENTIFIER_SIZE);
     135             : 
     136         328 :     *(unsigned char *)&szAreaOfThePolygonCat[0] = MM_A_WITH_GRAVE;
     137         328 :     *(unsigned char *)&szAreaOfThePolygonSpa[0] = MM_A_WITH_ACUTE;
     138         328 :     *(unsigned char *)&szAreaOfThePolygonCat[12] = MM_i_WITH_ACUTE;
     139         328 :     *(unsigned char *)&szAreaOfThePolygonSpa[12] = MM_i_WITH_ACUTE;
     140             : 
     141         328 :     CPLStrlcpy(szNumberOfArcsEng, "Number of arcs", MM_MAX_IDENTIFIER_SIZE);
     142         328 :     CPLStrlcpy(szNumberOfArcsCat, "Nombre d'arcs", MM_MAX_IDENTIFIER_SIZE);
     143         328 :     CPLStrlcpy(szNumberOfArcsSpa, "Numero de arcos", MM_MAX_IDENTIFIER_SIZE);
     144             : 
     145         328 :     *(unsigned char *)&szNumberOfArcsSpa[1] = MM_u_WITH_ACUTE;
     146             : 
     147         328 :     CPLStrlcpy(szNumberOfElementaryPolygonsEng, "Number of elementary polygons",
     148             :                MM_MAX_IDENTIFIER_SIZE);
     149         328 :     CPLStrlcpy(szNumberOfElementaryPolygonsCat, "Nombre de poligons elementals",
     150             :                MM_MAX_IDENTIFIER_SIZE);
     151         328 :     CPLStrlcpy(szNumberOfElementaryPolygonsSpa,
     152             :                "Numero de poligonos elementales", MM_MAX_IDENTIFIER_SIZE);
     153             : 
     154         328 :     *(unsigned char *)&szNumberOfElementaryPolygonsSpa[1] = MM_u_WITH_ACUTE;
     155         328 :     *(unsigned char *)&szNumberOfElementaryPolygonsCat[13] = MM_i_WITH_ACUTE;
     156         328 :     *(unsigned char *)&szNumberOfElementaryPolygonsSpa[13] = MM_i_WITH_ACUTE;
     157         328 : }
     158             : 
     159             : const char *MM_pszLogFilename = nullptr;
     160             : 
     161             : static const char MM_EmptyString[] = {""};
     162             : #define MM_SetEndOfString (*MM_EmptyString)
     163             : 
     164        1516 : void fclose_and_nullify(VSILFILE **pFunc)
     165             : {
     166        1516 :     if (!pFunc || !(*pFunc))
     167         355 :         return;
     168        1161 :     VSIFCloseL(*pFunc);
     169        1161 :     *pFunc = nullptr;
     170             : }
     171             : 
     172             : // CREATING AN EXTENDED MIRAMON DBF
     173        4108 : void MM_InitializeField(struct MM_FIELD *pField)
     174             : {
     175        4108 :     memset(pField, '\0', sizeof(*pField));
     176        4108 :     pField->FieldType = 'C';
     177        4108 :     pField->GeoTopoTypeField = MM_NO_ES_CAMP_GEOTOPO;
     178        4108 : }
     179             : 
     180             : #define MM_ACCEPTABLE_NUMBER_OF_FIELDS 20000
     181             : 
     182         306 : struct MM_FIELD *MM_CreateAllFields(MM_EXT_DBF_N_FIELDS nFields)
     183             : {
     184             :     struct MM_FIELD *camp;
     185             :     MM_EXT_DBF_N_FIELDS i;
     186             : 
     187             :     // MiraMon could accept a number of fields 13.4 million
     188             :     // but GDAL prefers to limit that to 20.000 to avoid
     189             :     // too large memory allocation attempts with corrupted datasets
     190         306 :     if (nFields > MM_ACCEPTABLE_NUMBER_OF_FIELDS)
     191             :     {
     192           0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     193             :                  "More than 20000 fields not accepted");
     194           0 :         return nullptr;
     195             :     }
     196             : 
     197             : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     198         306 :     if (nFields >= UINT32_MAX / sizeof(*camp))
     199           0 :         return nullptr;
     200             : #else
     201             :     if (nFields >= (1000U * 1000 * 1000) / sizeof(*camp))
     202             :         return nullptr;
     203             : #endif
     204             : 
     205         306 :     if ((camp = VSICalloc(nFields, sizeof(*camp))) == nullptr)
     206           0 :         return nullptr;
     207             : 
     208        2613 :     for (i = 0; i < nFields; i++)
     209        2307 :         MM_InitializeField(camp + i);
     210         306 :     return camp;
     211             : }
     212             : 
     213         191 : static struct MM_DATA_BASE_XP *MM_CreateEmptyHeader(MM_EXT_DBF_N_FIELDS nFields)
     214             : {
     215             :     struct MM_DATA_BASE_XP *data_base_XP;
     216             : 
     217         191 :     if ((data_base_XP = (struct MM_DATA_BASE_XP *)VSICalloc(
     218             :              1, sizeof(struct MM_DATA_BASE_XP))) == nullptr)
     219           0 :         return nullptr;
     220             : 
     221         191 :     if (nFields == 0)
     222             :     {
     223             :         ;
     224             :     }
     225             :     else
     226             :     {
     227         191 :         data_base_XP->pField = (struct MM_FIELD *)MM_CreateAllFields(nFields);
     228         191 :         if (!data_base_XP->pField)
     229             :         {
     230           0 :             VSIFree(data_base_XP);
     231           0 :             return nullptr;
     232             :         }
     233             :     }
     234         191 :     data_base_XP->nFields = nFields;
     235         191 :     return data_base_XP;
     236             : }
     237             : 
     238         191 : struct MM_DATA_BASE_XP *MM_CreateDBFHeader(MM_EXT_DBF_N_FIELDS n_camps,
     239             :                                            MM_BYTE charset)
     240             : {
     241             :     struct MM_DATA_BASE_XP *bd_xp;
     242             :     struct MM_FIELD *camp;
     243             :     MM_EXT_DBF_N_FIELDS i;
     244             : 
     245         191 :     if (nullptr == (bd_xp = MM_CreateEmptyHeader(n_camps)))
     246           0 :         return nullptr;
     247             : 
     248         191 :     bd_xp->CharSet = charset;
     249             : 
     250         191 :     strcpy(bd_xp->ReadingMode, "a+b");
     251             : 
     252         191 :     bd_xp->IdGraficField = n_camps;
     253         191 :     bd_xp->IdEntityField = MM_MAX_EXT_DBF_N_FIELDS_TYPE;
     254         191 :     bd_xp->dbf_version = (MM_BYTE)((n_camps > MM_MAX_N_CAMPS_DBF_CLASSICA)
     255             :                                        ? MM_MARCA_VERSIO_1_DBF_ESTESA
     256             :                                        : MM_MARCA_DBASE4);
     257             : 
     258        1417 :     for (i = 0, camp = bd_xp->pField; i < n_camps; i++, camp++)
     259             :     {
     260        1226 :         MM_InitializeField(camp);
     261        1226 :         if (i < 99999)
     262        1226 :             snprintf(camp->FieldName, sizeof(camp->FieldName), "CAMP%05u",
     263        1226 :                      (unsigned)(i + 1));
     264             :         else
     265           0 :             snprintf(camp->FieldName, sizeof(camp->FieldName), "CM%u",
     266           0 :                      (unsigned)(i + 1));
     267        1226 :         camp->FieldType = 'C';
     268        1226 :         camp->DecimalsIfFloat = 0;
     269        1226 :         camp->BytesPerField = 50;
     270             :     }
     271         191 :     return bd_xp;
     272             : }
     273             : 
     274        1226 : static MM_BYTE MM_GetDefaultDesiredDBFFieldWidth(const struct MM_FIELD *camp)
     275             : {
     276             :     size_t a, b, c, d, e;
     277             : 
     278        1226 :     b = strlen(camp->FieldName);
     279        1226 :     c = strlen(camp->FieldDescription[0]);
     280             : 
     281        1226 :     if (camp->FieldType == 'D')
     282             :     {
     283          68 :         d = (b > c ? b : c);
     284          68 :         a = (size_t)camp->BytesPerField + 2;
     285          68 :         return (MM_BYTE)(a > d ? a : d);
     286             :     }
     287        1158 :     a = camp->BytesPerField;
     288        1158 :     d = (unsigned int)(b > c ? b : c);
     289        1158 :     e = (a > d ? a : d);
     290        1158 :     return (MM_BYTE)(e < 80 ? e : 80);
     291             : }
     292             : 
     293        9063 : static MM_BOOLEAN MM_is_field_name_lowercase(const char *szChain)
     294             : {
     295             :     const char *p;
     296             : 
     297       56071 :     for (p = szChain; *p; p++)
     298             :     {
     299       50335 :         if ((*p >= 'a' && *p <= 'z'))
     300        3327 :             return TRUE;
     301             :     }
     302        5736 :     return FALSE;
     303             : }
     304             : 
     305             : static MM_BOOLEAN
     306        9095 : MM_Is_classical_DBF_field_name_or_lowercase(const char *szChain)
     307             : {
     308             :     const char *p;
     309             : 
     310       76551 :     for (p = szChain; *p; p++)
     311             :     {
     312       67488 :         if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
     313        6275 :             (*p >= '0' && *p <= '9') || *p == '_')
     314             :             ;
     315             :         else
     316          32 :             return FALSE;
     317             :     }
     318        9063 :     if (szChain[0] == '_')
     319           0 :         return FALSE;
     320        9063 :     return TRUE;
     321             : }
     322             : 
     323             : static MM_BOOLEAN
     324       81431 : MM_Is_character_valid_for_extended_DBF_field_name(int valor,
     325             :                                                   int *valor_substitut)
     326             : {
     327       81431 :     if (valor_substitut)
     328             :     {
     329           0 :         switch (valor)
     330             :         {
     331           0 :             case 32:
     332           0 :                 *valor_substitut = '_';
     333           0 :                 return FALSE;
     334           0 :             case 91:
     335           0 :                 *valor_substitut = '(';
     336           0 :                 return FALSE;
     337           0 :             case 93:
     338           0 :                 *valor_substitut = ')';
     339           0 :                 return FALSE;
     340           0 :             case 96:
     341           0 :                 *valor_substitut = '\'';
     342           0 :                 return FALSE;
     343           0 :             case 127:
     344           0 :                 *valor_substitut = '_';
     345           0 :                 return FALSE;
     346           0 :             case 168:
     347           0 :                 *valor_substitut = '-';
     348           0 :                 return FALSE;
     349             :         }
     350             :     }
     351             :     else
     352             :     {
     353       81431 :         if (valor < 32 || valor == 91 || valor == 93 || valor == 96 ||
     354       81431 :             valor == 127 || valor == 168)
     355           0 :             return FALSE;
     356             :     }
     357       81431 :     return TRUE;
     358             : }
     359             : 
     360       10213 : static int MM_ISExtendedNameBD_XP(const char *nom_camp)
     361             : {
     362             :     size_t mida, j;
     363             : 
     364       10213 :     mida = strlen(nom_camp);
     365       10213 :     if (mida >= MM_MAX_LON_FIELD_NAME_DBF)
     366           0 :         return MM_DBF_NAME_NO_VALID;
     367             : 
     368       91644 :     for (j = 0; j < mida; j++)
     369             :     {
     370       81431 :         if (!MM_Is_character_valid_for_extended_DBF_field_name(
     371       81431 :                 (unsigned char)nom_camp[j], nullptr))
     372           0 :             return MM_DBF_NAME_NO_VALID;
     373             :     }
     374             : 
     375       10213 :     if (mida >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF)
     376        1118 :         return MM_VALID_EXTENDED_DBF_NAME;
     377             : 
     378        9095 :     if (!MM_Is_classical_DBF_field_name_or_lowercase(nom_camp))
     379          32 :         return MM_VALID_EXTENDED_DBF_NAME;
     380             : 
     381        9063 :     if (MM_is_field_name_lowercase(nom_camp))
     382        3327 :         return MM_DBF_NAME_LOWERCASE_AND_VALID;
     383             : 
     384        5736 :     return NM_CLASSICAL_DBF_AND_VALID_NAME;
     385             : }
     386             : 
     387         530 : static MM_BYTE MM_CalculateBytesExtendedFieldName(struct MM_FIELD *camp)
     388             : {
     389         530 :     camp->reserved_2[MM_OFFSET_RESERVED2_EXTENDED_NAME_SIZE] =
     390         530 :         (MM_BYTE)strlen(camp->FieldName);
     391         530 :     return MM_DonaBytesNomEstesCamp(camp);
     392             : }
     393             : 
     394             : static MM_ACCUMULATED_BYTES_TYPE_DBF
     395         191 : MM_CalculateBytesExtendedFieldNames(const struct MM_DATA_BASE_XP *bd_xp)
     396             : {
     397         191 :     MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats = 0;
     398             :     MM_EXT_DBF_N_FIELDS i_camp;
     399             : 
     400        1417 :     for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
     401             :     {
     402        1226 :         if (MM_VALID_EXTENDED_DBF_NAME ==
     403        1226 :             MM_ISExtendedNameBD_XP(bd_xp->pField[i_camp].FieldName))
     404          91 :             bytes_acumulats +=
     405          91 :                 MM_CalculateBytesExtendedFieldName(bd_xp->pField + i_camp);
     406             :     }
     407             : 
     408         191 :     return bytes_acumulats;
     409             : }
     410             : 
     411             : static MM_FIRST_RECORD_OFFSET_TYPE
     412         191 : MM_CalculateBytesFirstRecordOffset(struct MM_DATA_BASE_XP *bd_xp)
     413             : {
     414         191 :     if (bd_xp)
     415         191 :         return (32 + 32 * bd_xp->nFields + 1 +
     416         191 :                 MM_CalculateBytesExtendedFieldNames(bd_xp));
     417           0 :     return 0;
     418             : }
     419             : 
     420         191 : static void MM_CheckDBFHeader(struct MM_DATA_BASE_XP *bd_xp)
     421             : {
     422             :     struct MM_FIELD *camp;
     423             :     MM_EXT_DBF_N_FIELDS i;
     424         191 :     MM_BOOLEAN cal_DBF_estesa = FALSE;
     425             : 
     426         191 :     bd_xp->BytesPerRecord = 1;
     427        1417 :     for (i = 0, camp = bd_xp->pField; i < bd_xp->nFields; i++, camp++)
     428             :     {
     429        1226 :         camp->AccumulatedBytes = bd_xp->BytesPerRecord;
     430        1226 :         bd_xp->BytesPerRecord += camp->BytesPerField;
     431        1226 :         if (camp->DesiredWidth == 0)
     432        1226 :             camp->DesiredWidth = camp->OriginalDesiredWidth =
     433        1226 :                 MM_GetDefaultDesiredDBFFieldWidth(camp);  //camp->BytesPerField;
     434        1226 :         if (camp->FieldType == 'C' &&
     435         192 :             camp->BytesPerField > MM_MAX_AMPLADA_CAMP_C_DBF_CLASSICA)
     436           0 :             cal_DBF_estesa = TRUE;
     437        1226 :         if (MM_VALID_EXTENDED_DBF_NAME ==
     438        1226 :             MM_ISExtendedNameBD_XP(camp->FieldName))
     439          91 :             cal_DBF_estesa = TRUE;
     440             :     }
     441             : 
     442         191 :     bd_xp->FirstRecordOffset = MM_CalculateBytesFirstRecordOffset(bd_xp);
     443             : 
     444         191 :     if (cal_DBF_estesa || bd_xp->nFields > MM_MAX_N_CAMPS_DBF_CLASSICA ||
     445         167 :         bd_xp->nRecords > UINT32_MAX)
     446          24 :         bd_xp->dbf_version = (MM_BYTE)MM_MARCA_VERSIO_1_DBF_ESTESA;
     447             :     else
     448         167 :         bd_xp->dbf_version = MM_MARCA_DBASE4;
     449         191 : }
     450             : 
     451             : static void
     452        2105 : MM_InitializeOffsetExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp,
     453             :                                            MM_EXT_DBF_N_FIELDS i_camp)
     454             : {
     455        2105 :     memset((char *)(&bd_xp->pField[i_camp].reserved_2) +
     456             :                MM_OFFSET_RESERVAT2_OFFSET_NOM_ESTES,
     457             :            0, 4);
     458        2105 : }
     459             : 
     460             : static void
     461        2105 : MM_InitializeBytesExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp,
     462             :                                           MM_EXT_DBF_N_FIELDS i_camp)
     463             : {
     464        2105 :     memset((char *)(&bd_xp->pField[i_camp].reserved_2) +
     465             :                MM_OFFSET_RESERVED2_EXTENDED_NAME_SIZE,
     466             :            0, 1);
     467        2105 : }
     468             : 
     469          91 : static short int MM_return_common_valid_DBF_field_name_string(char *szChain)
     470             : {
     471             :     char *p;
     472          91 :     short int error_retornat = 0;
     473             : 
     474          91 :     if (!szChain)
     475           0 :         return 0;
     476             :     //strupr(szChain);
     477        1204 :     for (p = szChain; *p; p++)
     478             :     {
     479        1113 :         (*p) = (char)toupper((unsigned char)*p);
     480        1113 :         if ((*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_')
     481             :             ;
     482             :         else
     483             :         {
     484           7 :             *p = '_';
     485           7 :             error_retornat |= MM_FIELD_NAME_CHARACTER_INVALID;
     486             :         }
     487             :     }
     488          91 :     if (szChain[0] == '_')
     489             :     {
     490             :         // To avoid having field names starting by '_' this case is
     491             :         // substituted by a 0 (not a '\0').
     492           0 :         szChain[0] = '0';
     493           0 :         error_retornat |= MM_FIELD_NAME_FIRST_CHARACTER_;
     494             :     }
     495          91 :     return error_retornat;
     496             : }
     497             : 
     498          91 : static short int MM_ReturnValidClassicDBFFieldName(char *szChain)
     499             : {
     500             :     size_t long_nom_camp;
     501          91 :     short int error_retornat = 0;
     502             : 
     503          91 :     long_nom_camp = strlen(szChain);
     504          91 :     if ((long_nom_camp < 1) ||
     505             :         (long_nom_camp >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF))
     506             :     {
     507          89 :         szChain[MM_MAX_LON_FIELD_NAME_DBF - 1] = '\0';
     508          89 :         error_retornat |= MM_FIELD_NAME_TOO_LONG;
     509             :     }
     510          91 :     error_retornat |= MM_return_common_valid_DBF_field_name_string(szChain);
     511          91 :     return error_retornat;
     512             : }
     513             : 
     514             : static MM_BOOLEAN
     515          91 : MM_CheckClassicFieldNameEqual(const struct MM_DATA_BASE_XP *data_base_XP,
     516             :                               const char *classical_name)
     517             : {
     518             :     MM_EXT_DBF_N_FIELDS i;
     519             : 
     520        1300 :     for (i = 0; i < data_base_XP->nFields; i++)
     521             :     {
     522        1209 :         if ((strcasecmp(data_base_XP->pField[i].ClassicalDBFFieldName,
     523        1209 :                         classical_name)) == 0 ||
     524        1209 :             (strcasecmp(data_base_XP->pField[i].FieldName, classical_name)) ==
     525             :                 0)
     526           0 :             return TRUE;
     527             :     }
     528          91 :     return FALSE;
     529             : }
     530             : 
     531           0 : static char *MM_GiveNewStringWithCharacterInFront(const char *text,
     532             :                                                   char character)
     533             : {
     534             :     char *ptr;
     535             :     size_t i;
     536             : 
     537           0 :     if (!text)
     538           0 :         return nullptr;
     539             : 
     540           0 :     i = strlen(text);
     541           0 :     if ((ptr = VSICalloc(1, i + 2)) == nullptr)
     542           0 :         return nullptr;
     543             : 
     544           0 :     *ptr = character;
     545           0 :     memcpy(ptr + 1, text, i + 1);
     546           0 :     return ptr;
     547             : }
     548             : 
     549           0 : static char *MM_SetSubIndexFieldNam(const char *nom_camp,
     550             :                                     MM_EXT_DBF_N_FIELDS index,
     551             :                                     size_t ampladamax)
     552             : {
     553             :     char *NomCamp_SubIndex;
     554             :     char *_subindex;
     555             :     char subindex[19 + 1];
     556             :     size_t sizet_subindex;
     557             :     size_t sizet_nomcamp;
     558             : 
     559           0 :     NomCamp_SubIndex = VSICalloc(1, ampladamax);
     560           0 :     if (!NomCamp_SubIndex)
     561           0 :         return nullptr;
     562             : 
     563           0 :     CPLStrlcpy(NomCamp_SubIndex, nom_camp, ampladamax);
     564           0 :     NomCamp_SubIndex[ampladamax - 1] = '\0';
     565             : 
     566           0 :     snprintf(subindex, sizeof(subindex), sprintf_UINT64, (GUInt64)index);
     567             : 
     568           0 :     _subindex = MM_GiveNewStringWithCharacterInFront(subindex, '_');
     569           0 :     if (!_subindex)
     570             :     {
     571           0 :         VSIFree(NomCamp_SubIndex);
     572           0 :         return nullptr;
     573             :     }
     574             : 
     575           0 :     sizet_subindex = strlen(_subindex);
     576           0 :     sizet_nomcamp = strlen(NomCamp_SubIndex);
     577             : 
     578           0 :     if (sizet_nomcamp + sizet_subindex > ampladamax - 1)
     579           0 :         memcpy(NomCamp_SubIndex + ((ampladamax - 1) - sizet_subindex),
     580             :                _subindex, strlen(_subindex));
     581             :     else
     582           0 :         NomCamp_SubIndex = strcat(NomCamp_SubIndex, _subindex);
     583             : 
     584           0 :     VSIFree(_subindex);
     585             : 
     586           0 :     return NomCamp_SubIndex;
     587             : }
     588             : 
     589             : MM_FIRST_RECORD_OFFSET_TYPE
     590         771 : MM_GiveOffsetExtendedFieldName(const struct MM_FIELD *camp)
     591             : {
     592             :     MM_FIRST_RECORD_OFFSET_TYPE offset_nom_camp;
     593             : 
     594         771 :     memcpy(&offset_nom_camp,
     595         771 :            (char *)(&camp->reserved_2) + MM_OFFSET_RESERVAT2_OFFSET_NOM_ESTES,
     596             :            4);
     597         771 :     return offset_nom_camp;
     598             : }
     599             : 
     600         308 : int MM_WriteNRecordsMMBD_XPFile(struct MMAdmDatabase *MMAdmDB)
     601             : {
     602         308 :     if (!MMAdmDB->pMMBDXP || !MMAdmDB->pMMBDXP->pfDataBase)
     603           0 :         return 0;
     604             : 
     605             :     // Updating number of features in features table
     606         308 :     VSIFSeekL(MMAdmDB->pMMBDXP->pfDataBase, MM_FIRST_OFFSET_to_N_RECORDS,
     607             :               SEEK_SET);
     608             : 
     609         308 :     if (MMAdmDB->pMMBDXP->nRecords > UINT32_MAX)
     610             :     {
     611           0 :         MMAdmDB->pMMBDXP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     612             :     }
     613             :     else
     614             :     {
     615         308 :         MMAdmDB->pMMBDXP->dbf_version = MM_MARCA_DBASE4;
     616             :     }
     617             : 
     618             :     {
     619         308 :         GUInt32 nRecords32LowBits =
     620         308 :             (GUInt32)(MMAdmDB->pMMBDXP->nRecords & UINT32_MAX);
     621         308 :         if (VSIFWriteL(&nRecords32LowBits, 4, 1,
     622         308 :                        MMAdmDB->pMMBDXP->pfDataBase) != 1)
     623           0 :             return 1;
     624             :     }
     625             : 
     626         308 :     VSIFSeekL(MMAdmDB->pMMBDXP->pfDataBase, MM_SECOND_OFFSET_to_N_RECORDS,
     627             :               SEEK_SET);
     628         308 :     if (MMAdmDB->pMMBDXP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA)
     629             :     {
     630             :         /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */
     631           0 :         GUInt32 nRecords32HighBits =
     632           0 :             (GUInt32)(MMAdmDB->pMMBDXP->nRecords >> 32);
     633           0 :         if (VSIFWriteL(&nRecords32HighBits, 4, 1,
     634           0 :                        MMAdmDB->pMMBDXP->pfDataBase) != 1)
     635           0 :             return 1;
     636             : 
     637             :         /* from 20 to 27 */
     638           0 :         if (VSIFWriteL(&(MMAdmDB->pMMBDXP->dbf_on_a_LAN), 8, 1,
     639           0 :                        MMAdmDB->pMMBDXP->pfDataBase) != 1)
     640           0 :             return 1;
     641             :     }
     642             :     else
     643             :     {
     644         308 :         if (VSIFWriteL(&(MMAdmDB->pMMBDXP->dbf_on_a_LAN), 12, 1,
     645         308 :                        MMAdmDB->pMMBDXP->pfDataBase) != 1)
     646           0 :             return 1;
     647             :     }
     648             : 
     649         308 :     return 0;
     650             : }
     651             : 
     652             : static MM_BOOLEAN
     653         308 : MM_OpenIfNeededAndUpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP)
     654             : {
     655             :     MM_BYTE variable_byte;
     656         308 :     MM_EXT_DBF_N_FIELDS i, j = 0;
     657         308 :     char zero[11] = {0};
     658         308 :     const MM_BYTE byte_zero = 0;
     659         308 :     char ModeLectura_previ[4] = "";
     660             :     MM_FIRST_RECORD_OFFSET_TYPE bytes_acumulats;
     661             :     MM_BYTE name_size;
     662             :     int estat;
     663             :     char nom_camp[MM_MAX_LON_FIELD_NAME_DBF];
     664             :     size_t retorn_fwrite;
     665             : 
     666         308 :     if (!data_base_XP)
     667           0 :         return FALSE;
     668             : 
     669         308 :     if (data_base_XP->pfDataBase == nullptr)
     670             :     {
     671         191 :         strcpy(ModeLectura_previ, data_base_XP->ReadingMode);
     672         191 :         strcpy(data_base_XP->ReadingMode, "wb+");
     673             : 
     674         191 :         if ((data_base_XP->pfDataBase = VSIFOpenL(data_base_XP->szFileName,
     675         191 :                                                   data_base_XP->ReadingMode)) ==
     676             :             nullptr)
     677             :         {
     678           0 :             return FALSE;
     679             :         }
     680             :     }
     681             :     else
     682             :     {
     683             :         // If it's open we just update the header
     684         117 :         VSIFSeekL(data_base_XP->pfDataBase, 0, SEEK_SET);
     685             :     }
     686             : 
     687         308 :     if ((data_base_XP->nFields) > MM_MAX_N_CAMPS_DBF_CLASSICA)
     688           0 :         data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     689         308 :     else if ((data_base_XP->nRecords) > UINT32_MAX)
     690           0 :         data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     691             :     else
     692             :     {
     693         308 :         if (data_base_XP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA)
     694          24 :             data_base_XP->dbf_version = MM_MARCA_DBASE4;
     695        2240 :         for (i = 0; i < data_base_XP->nFields; i++)
     696             :         {
     697        2022 :             if (data_base_XP->pField[i].FieldType == 'C' &&
     698         348 :                 data_base_XP->pField[i].BytesPerField >
     699             :                     MM_MAX_AMPLADA_CAMP_C_DBF_CLASSICA)
     700             :             {
     701           0 :                 data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     702           0 :                 break;
     703             :             }
     704        2022 :             if (MM_VALID_EXTENDED_DBF_NAME ==
     705        2022 :                 MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName))
     706             :             {
     707          90 :                 data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     708          90 :                 break;
     709             :             }
     710             :         }
     711             :     }
     712             : 
     713             :     // Writing header
     714         308 :     VSIFSeekL(data_base_XP->pfDataBase, 0, SEEK_SET);
     715             : 
     716             :     /* Byte 0 */
     717         308 :     if (VSIFWriteL(&(data_base_XP->dbf_version), 1, 1,
     718             :                    data_base_XP->pfDataBase) != 1)
     719             :     {
     720           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     721           0 :         data_base_XP->pfDataBase = nullptr;
     722           0 :         return FALSE;
     723             :     }
     724             : 
     725             :     /* MM_BYTE from 1 to 3 */
     726         308 :     variable_byte = (MM_BYTE)(data_base_XP->year - 1900);
     727         308 :     if (VSIFWriteL(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1)
     728             :     {
     729           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     730           0 :         data_base_XP->pfDataBase = nullptr;
     731           0 :         return FALSE;
     732             :     }
     733         308 :     if (VSIFWriteL(&(data_base_XP->month), 1, 1, data_base_XP->pfDataBase) != 1)
     734             :     {
     735           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     736           0 :         data_base_XP->pfDataBase = nullptr;
     737           0 :         return FALSE;
     738             :     }
     739         308 :     if (VSIFWriteL(&(data_base_XP->day), 1, 1, data_base_XP->pfDataBase) != 1)
     740             :     {
     741           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     742           0 :         data_base_XP->pfDataBase = nullptr;
     743           0 :         return FALSE;
     744             :     }
     745             : 
     746             :     /* from 4 a 7, position MM_FIRST_OFFSET_to_N_RECORDS */
     747             :     {
     748         308 :         GUInt32 nRecords32LowBits =
     749         308 :             (GUInt32)(data_base_XP->nRecords & UINT32_MAX);
     750         308 :         if (VSIFWriteL(&nRecords32LowBits, 4, 1, data_base_XP->pfDataBase) != 1)
     751             :         {
     752           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     753           0 :             data_base_XP->pfDataBase = nullptr;
     754           0 :             return FALSE;
     755             :         }
     756             :     }
     757             : 
     758             :     /* from 8 a 9, position MM_PRIMER_OFFSET_a_OFFSET_1a_FITXA */
     759         308 :     if (VSIFWriteL(&(data_base_XP->FirstRecordOffset), 2, 1,
     760             :                    data_base_XP->pfDataBase) != 1)
     761             :     {
     762           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     763           0 :         data_base_XP->pfDataBase = nullptr;
     764           0 :         return FALSE;
     765             :     }
     766             :     /* from 10 to 11, & from 12 to 13 */
     767         308 :     if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version))
     768             :     {
     769          90 :         if (VSIFWriteL(&(data_base_XP->BytesPerRecord),
     770             :                        sizeof(MM_ACCUMULATED_BYTES_TYPE_DBF), 1,
     771             :                        data_base_XP->pfDataBase) != 1)
     772             :         {
     773           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     774           0 :             data_base_XP->pfDataBase = nullptr;
     775           0 :             return FALSE;
     776             :         }
     777             :     }
     778             :     else
     779             :     {
     780             :         /* from 10 to 11 */
     781         218 :         if (VSIFWriteL(&(data_base_XP->BytesPerRecord), 2, 1,
     782             :                        data_base_XP->pfDataBase) != 1)
     783             :         {
     784           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     785           0 :             data_base_XP->pfDataBase = nullptr;
     786           0 :             return FALSE;
     787             :         }
     788             :         /* from 12 to 13 */
     789         218 :         if (VSIFWriteL(&(data_base_XP->reserved_1), 2, 1,
     790             :                        data_base_XP->pfDataBase) != 1)
     791             :         {
     792           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     793           0 :             data_base_XP->pfDataBase = nullptr;
     794           0 :             return FALSE;
     795             :         }
     796             :     }
     797             :     /* byte 14 */
     798         308 :     if (VSIFWriteL(&(data_base_XP->transaction_flag), 1, 1,
     799             :                    data_base_XP->pfDataBase) != 1)
     800             :     {
     801           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     802           0 :         data_base_XP->pfDataBase = nullptr;
     803           0 :         return FALSE;
     804             :     }
     805             :     /* byte 15 */
     806         308 :     if (VSIFWriteL(&(data_base_XP->encryption_flag), 1, 1,
     807             :                    data_base_XP->pfDataBase) != 1)
     808             :     {
     809           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     810           0 :         data_base_XP->pfDataBase = nullptr;
     811           0 :         return FALSE;
     812             :     }
     813             : 
     814             :     /* from 16 to 27 */
     815         308 :     if (data_base_XP->nRecords > UINT32_MAX)
     816             :     {
     817             :         /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */
     818           0 :         GUInt32 nRecords32HighBits = (GUInt32)(data_base_XP->nRecords >> 32);
     819           0 :         if (VSIFWriteL(&nRecords32HighBits, 4, 1, data_base_XP->pfDataBase) !=
     820             :             1)
     821             :         {
     822           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     823           0 :             data_base_XP->pfDataBase = nullptr;
     824           0 :             return FALSE;
     825             :         }
     826             : 
     827             :         /* from 20 to 27 */
     828           0 :         if (VSIFWriteL(&(data_base_XP->dbf_on_a_LAN), 8, 1,
     829             :                        data_base_XP->pfDataBase) != 1)
     830             :         {
     831           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     832           0 :             data_base_XP->pfDataBase = nullptr;
     833           0 :             return FALSE;
     834             :         }
     835             :     }
     836             :     else
     837             :     {
     838             :         /* from 16 to 27 */
     839         308 :         if (VSIFWriteL(&(data_base_XP->dbf_on_a_LAN), 12, 1,
     840             :                        data_base_XP->pfDataBase) != 1)
     841             :         {
     842           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     843           0 :             data_base_XP->pfDataBase = nullptr;
     844           0 :             return FALSE;
     845             :         }
     846             :     }
     847             :     /* byte 28 */
     848         308 :     if (VSIFWriteL(&(data_base_XP->MDX_flag), 1, 1, data_base_XP->pfDataBase) !=
     849             :         1)
     850             :     {
     851           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     852           0 :         data_base_XP->pfDataBase = nullptr;
     853           0 :         return FALSE;
     854             :     }
     855             : 
     856             :     /* Byte 29 */
     857         308 :     if (VSIFWriteL(&(data_base_XP->CharSet), 1, 1, data_base_XP->pfDataBase) !=
     858             :         1)
     859             :     {
     860           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     861           0 :         data_base_XP->pfDataBase = nullptr;
     862           0 :         return FALSE;
     863             :     }
     864             : 
     865             :     /* Bytes from 30 to 31, in position MM_SEGON_OFFSET_a_OFFSET_1a_FITXA */
     866         308 :     if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version))
     867             :     {
     868          90 :         if (VSIFWriteL(((char *)&(data_base_XP->FirstRecordOffset)) + 2, 2, 1,
     869             :                        data_base_XP->pfDataBase) != 1)
     870             :         {
     871           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     872           0 :             data_base_XP->pfDataBase = nullptr;
     873           0 :             return FALSE;
     874             :         }
     875             :     }
     876             :     else
     877             :     {
     878         218 :         if (VSIFWriteL(&(data_base_XP->reserved_2), 2, 1,
     879             :                        data_base_XP->pfDataBase) != 1)
     880             :         {
     881           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     882           0 :             data_base_XP->pfDataBase = nullptr;
     883           0 :             return FALSE;
     884             :         }
     885             :     }
     886             : 
     887             :     /* At 32th byte fields description begins   */
     888             :     /* Every description is 32 bytes long       */
     889         308 :     bytes_acumulats = 32 + 32 * (data_base_XP->nFields) + 1;
     890             : 
     891        2852 :     for (i = 0; i < data_base_XP->nFields; i++)
     892             :     {
     893             :         /* Bytes from 0 to 10    -> Field name, \0 finished */
     894        2544 :         estat = MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName);
     895        2544 :         if (estat == NM_CLASSICAL_DBF_AND_VALID_NAME ||
     896             :             estat == MM_DBF_NAME_LOWERCASE_AND_VALID)
     897             :         {
     898        2105 :             j = (short)strlen(data_base_XP->pField[i].FieldName);
     899             : 
     900        2105 :             retorn_fwrite = VSIFWriteL(&data_base_XP->pField[i].FieldName, 1, j,
     901             :                                        data_base_XP->pfDataBase);
     902        2105 :             if (retorn_fwrite != (size_t)j)
     903             :             {
     904           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     905           0 :                 data_base_XP->pfDataBase = nullptr;
     906           0 :                 return FALSE;
     907             :             }
     908        2105 :             MM_InitializeOffsetExtendedFieldNameFields(data_base_XP, i);
     909        2105 :             MM_InitializeBytesExtendedFieldNameFields(data_base_XP, i);
     910             :         }
     911         439 :         else if (estat == MM_VALID_EXTENDED_DBF_NAME)
     912             :         {
     913         439 :             if (*(data_base_XP->pField[i].ClassicalDBFFieldName) == '\0')
     914             :             {
     915             :                 char nom_temp[MM_MAX_LON_FIELD_NAME_DBF];
     916             : 
     917          91 :                 CPLStrlcpy(nom_temp, data_base_XP->pField[i].FieldName,
     918             :                            MM_MAX_LON_FIELD_NAME_DBF);
     919          91 :                 MM_ReturnValidClassicDBFFieldName(nom_temp);
     920          91 :                 nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0';
     921          91 :                 if ((MM_CheckClassicFieldNameEqual(data_base_XP, nom_temp)) ==
     922             :                     TRUE)
     923             :                 {
     924             :                     char *c;
     925             : 
     926           0 :                     c = MM_SetSubIndexFieldNam(
     927             :                         nom_temp, i, MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
     928             : 
     929           0 :                     if (c)
     930             :                     {
     931           0 :                         j = 0;
     932           0 :                         while (MM_CheckClassicFieldNameEqual(data_base_XP, c) ==
     933           0 :                                    TRUE &&
     934           0 :                                j < data_base_XP->nFields)
     935             :                         {
     936           0 :                             VSIFree(c);
     937           0 :                             c = MM_SetSubIndexFieldNam(
     938             :                                 nom_temp, ++j,
     939             :                                 MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
     940             :                         }
     941           0 :                         if (c)
     942             :                         {
     943           0 :                             CPLStrlcpy(
     944           0 :                                 data_base_XP->pField[i].ClassicalDBFFieldName,
     945             :                                 c,
     946             :                                 sizeof(data_base_XP->pField[i]
     947             :                                            .ClassicalDBFFieldName));
     948           0 :                             VSIFree(c);
     949             :                         }
     950             :                     }
     951             :                 }
     952             :                 else
     953          91 :                     CPLStrlcpy(
     954          91 :                         data_base_XP->pField[i].ClassicalDBFFieldName, nom_temp,
     955             :                         sizeof(data_base_XP->pField[i].ClassicalDBFFieldName));
     956             :             }
     957             : 
     958             :             // This is a 11-byte fixed size field consisting of the filename
     959             :             // and it's been padding calculated some next lines.
     960         439 :             j = (short)strlen(data_base_XP->pField[i].ClassicalDBFFieldName);
     961             : 
     962             :             retorn_fwrite =
     963         439 :                 VSIFWriteL(&data_base_XP->pField[i].ClassicalDBFFieldName, 1, j,
     964             :                            data_base_XP->pfDataBase);
     965         439 :             if (retorn_fwrite != (size_t)j)
     966             :             {
     967           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     968           0 :                 data_base_XP->pfDataBase = nullptr;
     969           0 :                 return FALSE;
     970             :             }
     971             : 
     972             :             name_size =
     973         439 :                 MM_CalculateBytesExtendedFieldName(data_base_XP->pField + i);
     974         439 :             MM_EscriuOffsetNomEstesBD_XP(data_base_XP, i, bytes_acumulats);
     975         439 :             bytes_acumulats += name_size;
     976             :         }
     977             :         else
     978             :         {
     979           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     980           0 :             data_base_XP->pfDataBase = nullptr;
     981           0 :             return FALSE;
     982             :         }
     983             : 
     984        2544 :         if (VSIFWriteL(zero, 1, 11 - j, data_base_XP->pfDataBase) !=
     985        2544 :             11 - (size_t)j)
     986             :         {
     987           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     988           0 :             data_base_XP->pfDataBase = nullptr;
     989           0 :             return FALSE;
     990             :         }
     991             :         /* Byte 11, Field type */
     992        2544 :         if (VSIFWriteL(&data_base_XP->pField[i].FieldType, 1, 1,
     993             :                        data_base_XP->pfDataBase) != 1)
     994             :         {
     995           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     996           0 :             data_base_XP->pfDataBase = nullptr;
     997           0 :             return FALSE;
     998             :         }
     999             :         /* Bytes 12 to 15 --> Reserved */
    1000        2544 :         if (VSIFWriteL(&data_base_XP->pField[i].reserved_1, 4, 1,
    1001             :                        data_base_XP->pfDataBase) != 1)
    1002             :         {
    1003           0 :             VSIFCloseL(data_base_XP->pfDataBase);
    1004           0 :             data_base_XP->pfDataBase = nullptr;
    1005           0 :             return FALSE;
    1006             :         }
    1007             :         /* Byte 16, or OFFSET_BYTESxCAMP_CAMP_CLASSIC --> BytesPerField */
    1008        2544 :         if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version) &&
    1009        1192 :             data_base_XP->pField[i].FieldType == 'C')
    1010             :         {
    1011         201 :             if (VSIFWriteL((void *)&byte_zero, 1, 1,
    1012             :                            data_base_XP->pfDataBase) != 1)
    1013             :             {
    1014           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1015           0 :                 data_base_XP->pfDataBase = nullptr;
    1016           0 :                 return FALSE;
    1017             :             }
    1018             :         }
    1019             :         else
    1020             :         {
    1021        2343 :             if (VSIFWriteL(&data_base_XP->pField[i].BytesPerField, 1, 1,
    1022             :                            data_base_XP->pfDataBase) != 1)
    1023             :             {
    1024           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1025           0 :                 data_base_XP->pfDataBase = nullptr;
    1026           0 :                 return FALSE;
    1027             :             }
    1028             :         }
    1029             :         /* 17th byte 17 --> In fields of type 'N' and 'F' indicates decimal places.*/
    1030        2544 :         if (data_base_XP->pField[i].FieldType == 'N' ||
    1031         716 :             data_base_XP->pField[i].FieldType == 'F')
    1032             :         {
    1033        1828 :             if (VSIFWriteL(&data_base_XP->pField[i].DecimalsIfFloat, 1, 1,
    1034             :                            data_base_XP->pfDataBase) != 1)
    1035             :             {
    1036           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1037           0 :                 data_base_XP->pfDataBase = nullptr;
    1038           0 :                 return FALSE;
    1039             :             }
    1040             :         }
    1041             :         else
    1042             :         {
    1043         716 :             if (VSIFWriteL(zero, 1, 1, data_base_XP->pfDataBase) != 1)
    1044             :             {
    1045           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1046           0 :                 data_base_XP->pfDataBase = nullptr;
    1047           0 :                 return FALSE;
    1048             :             }
    1049             :         }
    1050        2544 :         if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version) &&
    1051        1192 :             data_base_XP->pField[i].FieldType == 'C')
    1052             :         {
    1053             :             /* Bytes from 18 to 20 --> Reserved */
    1054         201 :             if (VSIFWriteL(&data_base_XP->pField[i].reserved_2, 20 - 18 + 1, 1,
    1055             :                            data_base_XP->pfDataBase) != 1)
    1056             :             {
    1057           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1058           0 :                 data_base_XP->pfDataBase = nullptr;
    1059           0 :                 return FALSE;
    1060             :             }
    1061             :             /* Bytes from 21 to 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C
    1062             :                                     in extended DBF */
    1063         201 :             if (VSIFWriteL(&data_base_XP->pField[i].BytesPerField,
    1064             :                            sizeof(MM_BYTES_PER_FIELD_TYPE_DBF), 1,
    1065             :                            data_base_XP->pfDataBase) != 1)
    1066             :             {
    1067           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1068           0 :                 data_base_XP->pfDataBase = nullptr;
    1069           0 :                 return FALSE;
    1070             :             }
    1071             : 
    1072             :             /* Bytes from 25 to 30 --> Reserved */
    1073         201 :             if (VSIFWriteL(&data_base_XP->pField[i].reserved_2[25 - 18],
    1074             :                            30 - 25 + 1, 1, data_base_XP->pfDataBase) != 1)
    1075             :             {
    1076           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1077           0 :                 data_base_XP->pfDataBase = nullptr;
    1078           0 :                 return FALSE;
    1079             :             }
    1080             :         }
    1081             :         else
    1082             :         {
    1083             :             /* Bytes de 21 a 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C */
    1084        2343 :             memset(data_base_XP->pField[i].reserved_2 +
    1085             :                        MM_OFFSET_RESERVAT2_BYTESxCAMP_CAMP_ESPECIAL,
    1086             :                    '\0', 4);
    1087             :             /* Bytes from 18 to 30 --> Reserved */
    1088        2343 :             if (VSIFWriteL(&data_base_XP->pField[i].reserved_2, 13, 1,
    1089             :                            data_base_XP->pfDataBase) != 1)
    1090             :             {
    1091           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1092           0 :                 data_base_XP->pfDataBase = nullptr;
    1093           0 :                 return FALSE;
    1094             :             }
    1095             :         }
    1096             :         /* Byte 31 --> MDX flag.    */
    1097        2544 :         if (VSIFWriteL(&data_base_XP->pField[i].MDX_field_flag, 1, 1,
    1098             :                        data_base_XP->pfDataBase) != 1)
    1099             :         {
    1100           0 :             VSIFCloseL(data_base_XP->pfDataBase);
    1101           0 :             data_base_XP->pfDataBase = nullptr;
    1102           0 :             return FALSE;
    1103             :         }
    1104             :     }
    1105             : 
    1106         308 :     variable_byte = 13;
    1107         308 :     if (VSIFWriteL(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1)
    1108             :     {
    1109           0 :         VSIFCloseL(data_base_XP->pfDataBase);
    1110           0 :         data_base_XP->pfDataBase = nullptr;
    1111           0 :         return FALSE;
    1112             :     }
    1113             : 
    1114         308 :     if (data_base_XP->FirstRecordOffset != bytes_acumulats)
    1115             :     {
    1116           0 :         VSIFCloseL(data_base_XP->pfDataBase);
    1117           0 :         data_base_XP->pfDataBase = nullptr;
    1118           0 :         return FALSE;
    1119             :     }
    1120             : 
    1121             :     // Extended fields
    1122        2852 :     for (i = 0; i < data_base_XP->nFields; i++)
    1123             :     {
    1124        2544 :         if (MM_VALID_EXTENDED_DBF_NAME ==
    1125        2544 :             MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName))
    1126             :         {
    1127         439 :             bytes_acumulats =
    1128         439 :                 MM_GiveOffsetExtendedFieldName(data_base_XP->pField + i);
    1129         439 :             name_size = MM_DonaBytesNomEstesCamp(data_base_XP->pField + i);
    1130             : 
    1131         439 :             VSIFSeekL(data_base_XP->pfDataBase, bytes_acumulats, SEEK_SET);
    1132             : 
    1133         439 :             strcpy(nom_camp, data_base_XP->pField[i].FieldName);
    1134             :             //CanviaJocCaracPerEscriureDBF(nom_camp, JocCaracDBFaMM(data_base_XP->CharSet, ParMM.JocCaracDBFPerDefecte));
    1135             : 
    1136             :             retorn_fwrite =
    1137         439 :                 VSIFWriteL(nom_camp, 1, name_size, data_base_XP->pfDataBase);
    1138             : 
    1139         439 :             if (retorn_fwrite != (size_t)name_size)
    1140             :             {
    1141           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1142           0 :                 data_base_XP->pfDataBase = nullptr;
    1143           0 :                 return FALSE;
    1144             :             }
    1145             :         }
    1146             :     }
    1147             : 
    1148         308 :     return TRUE;
    1149             : } /* End of MM_OpenIfNeededAndUpdateEntireHeader() */
    1150             : 
    1151         191 : MM_BOOLEAN MM_CreateAndOpenDBFFile(struct MM_DATA_BASE_XP *bd_xp,
    1152             :                                    const char *NomFitxer)
    1153             : {
    1154             :     time_t currentTime;
    1155             : 
    1156         191 :     if (!NomFitxer || MMIsEmptyString(NomFitxer) || !bd_xp)
    1157           0 :         return FALSE;
    1158             : 
    1159         191 :     MM_CheckDBFHeader(bd_xp);
    1160             : 
    1161             :     // Setting the current date
    1162         191 :     currentTime = time(nullptr);
    1163             : 
    1164             :     struct tm ltime;
    1165         191 :     VSILocalTime(&currentTime, &ltime);
    1166             : 
    1167         191 :     bd_xp->year = (short int)(ltime.tm_year + 1900);
    1168         191 :     bd_xp->month = (MM_BYTE)(ltime.tm_mon + 1);
    1169         191 :     bd_xp->day = (MM_BYTE)ltime.tm_mday;
    1170             : 
    1171         191 :     CPLStrlcpy(bd_xp->szFileName, NomFitxer, sizeof(bd_xp->szFileName));
    1172         191 :     return MM_OpenIfNeededAndUpdateEntireHeader(bd_xp);
    1173             : }
    1174             : 
    1175         307 : void MM_ReleaseMainFields(struct MM_DATA_BASE_XP *data_base_XP)
    1176             : {
    1177             :     MM_EXT_DBF_N_FIELDS i;
    1178             :     size_t j;
    1179             :     char **szChain;
    1180             : 
    1181         307 :     if (data_base_XP->pField)
    1182             :     {
    1183        2613 :         for (i = 0; i < data_base_XP->nFields; i++)
    1184             :         {
    1185       11535 :             for (j = 0; j < MM_NUM_IDIOMES_MD_MULTIDIOMA; j++)
    1186             :             {
    1187        9228 :                 szChain = data_base_XP->pField[i].Separator;
    1188        9228 :                 if (szChain[j])
    1189             :                 {
    1190           0 :                     VSIFree(szChain[j]);
    1191           0 :                     szChain[j] = nullptr;
    1192             :                 }
    1193             :             }
    1194             :         }
    1195         306 :         VSIFree(data_base_XP->pField);
    1196         306 :         data_base_XP->pField = nullptr;
    1197         306 :         data_base_XP->nFields = 0;
    1198             :     }
    1199         307 :     return;
    1200             : }
    1201             : 
    1202             : // READING THE HEADER OF AN EXTENDED DBF
    1203             : // Free with MM_ReleaseDBFHeader()
    1204         116 : int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName,
    1205             :                                      struct MM_DATA_BASE_XP *pMMBDXP,
    1206             :                                      const char *pszRelFile)
    1207             : {
    1208             :     MM_BYTE variable_byte;
    1209             :     VSILFILE *pf;
    1210             :     unsigned short int two_bytes;
    1211             :     MM_EXT_DBF_N_FIELDS nIField;
    1212             :     uint16_t offset_primera_fitxa;
    1213         116 :     MM_FIRST_RECORD_OFFSET_TYPE offset_fals = 0;
    1214         116 :     MM_BOOLEAN incoherent_record_size = FALSE;
    1215             :     MM_BYTE un_byte;
    1216             :     MM_BYTES_PER_FIELD_TYPE_DBF bytes_per_camp;
    1217             :     MM_BYTE tretze_bytes[13];
    1218             :     MM_FIRST_RECORD_OFFSET_TYPE offset_possible;
    1219         116 :     MM_BYTE some_problems_when_reading = 0;
    1220         116 :     MM_FILE_OFFSET offset_reintent = 0;  // For retrying
    1221             :     char cpg_file[MM_CPL_PATH_BUF_SIZE];
    1222             :     char *pszDesc;
    1223             :     char section[MM_MAX_LON_FIELD_NAME_DBF + 25];  // TAULA_PRINCIPAL:field_name
    1224             :     GUInt32 nRecords32LowBits;
    1225             :     char *pszString;
    1226             : 
    1227         116 :     if (!szFileName || !pMMBDXP)
    1228           0 :         return 1;
    1229             : 
    1230         116 :     CPLStrlcpy(pMMBDXP->szFileName, szFileName, sizeof(pMMBDXP->szFileName));
    1231         116 :     strcpy(pMMBDXP->ReadingMode, "rb");
    1232             : 
    1233         116 :     if ((pMMBDXP->pfDataBase =
    1234         116 :              VSIFOpenL(pMMBDXP->szFileName, pMMBDXP->ReadingMode)) == nullptr)
    1235           1 :         return 1;
    1236             : 
    1237         115 :     pf = pMMBDXP->pfDataBase;
    1238             : 
    1239         115 :     VSIFSeekL(pf, 0, SEEK_SET);
    1240             :     /* ====== Header reading (32 bytes) =================== */
    1241         115 :     offset_primera_fitxa = 0;
    1242             : 
    1243         230 :     if (1 != VSIFReadL(&(pMMBDXP->dbf_version), 1, 1, pf) ||
    1244         230 :         1 != VSIFReadL(&variable_byte, 1, 1, pf) ||
    1245         230 :         1 != VSIFReadL(&(pMMBDXP->month), 1, 1, pf) ||
    1246         115 :         1 != VSIFReadL(&(pMMBDXP->day), 1, 1, pf))
    1247             :     {
    1248           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1249           0 :         return 1;
    1250             :     }
    1251             : 
    1252         115 :     if (1 != VSIFReadL(&nRecords32LowBits, 4, 1, pf))
    1253             :     {
    1254           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1255           0 :         return 1;
    1256             :     }
    1257             : 
    1258         115 :     if (1 != VSIFReadL(&offset_primera_fitxa, 2, 1, pf))
    1259             :     {
    1260           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1261           0 :         return 1;
    1262             :     }
    1263             : 
    1264         115 :     pMMBDXP->year = (short)(1900 + variable_byte);
    1265         115 : reintenta_lectura_per_si_error_CreaCampBD_XP:
    1266             : 
    1267         115 :     if (some_problems_when_reading > 0)
    1268             :     {
    1269           0 :         if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
    1270             :         {
    1271           0 :             offset_fals =
    1272           0 :                 offset_primera_fitxa & (MM_FIRST_RECORD_OFFSET_TYPE)(~31);
    1273             :         }
    1274             :     }
    1275             :     else
    1276         115 :         offset_reintent = VSIFTellL(pf);
    1277             : 
    1278         230 :     if (1 != VSIFReadL(&two_bytes, 2, 1, pf) ||
    1279         230 :         1 != VSIFReadL(&(pMMBDXP->reserved_1), 2, 1, pf) ||
    1280         230 :         1 != VSIFReadL(&(pMMBDXP->transaction_flag), 1, 1, pf) ||
    1281         230 :         1 != VSIFReadL(&(pMMBDXP->encryption_flag), 1, 1, pf) ||
    1282         115 :         1 != VSIFReadL(&(pMMBDXP->dbf_on_a_LAN), 12, 1, pf))
    1283             :     {
    1284           0 :         VSIFree(pMMBDXP->pField);
    1285           0 :         pMMBDXP->pField = nullptr;
    1286           0 :         pMMBDXP->nFields = 0;
    1287           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1288           0 :         return 1;
    1289             :     }
    1290             : 
    1291         115 :     if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
    1292             :     {
    1293             :         GUInt32 nRecords32HighBits;
    1294             : 
    1295             :         // Getting 4 bytes of the 8 bytes variable
    1296          38 :         memcpy(&nRecords32HighBits, &pMMBDXP->dbf_on_a_LAN, 4);
    1297             : 
    1298             :         // Getting other 4 bytes of the 8 bytes variable
    1299             :         // The cast to GUInt64 of the high 32 bits is important to
    1300             :         // make sure the left bit shift is done correctly
    1301          38 :         pMMBDXP->nRecords =
    1302          38 :             ((GUInt64)nRecords32HighBits << 32) | nRecords32LowBits;
    1303             :     }
    1304             :     else
    1305          77 :         pMMBDXP->nRecords = nRecords32LowBits;
    1306             : 
    1307         230 :     if (1 != VSIFReadL(&(pMMBDXP->MDX_flag), 1, 1, pf) ||
    1308         230 :         1 != VSIFReadL(&(pMMBDXP->CharSet), 1, 1, pf) ||
    1309         115 :         1 != VSIFReadL(&(pMMBDXP->reserved_2), 2, 1, pf))
    1310             :     {
    1311           0 :         VSIFree(pMMBDXP->pField);
    1312           0 :         pMMBDXP->pField = nullptr;
    1313           0 :         pMMBDXP->nFields = 0;
    1314           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1315           0 :         return 1;
    1316             :     }
    1317             : 
    1318             :     // Checking for a cpg file
    1319         115 :     if (pMMBDXP->CharSet == 0)
    1320             :     {
    1321             :         VSILFILE *f_cpg;
    1322             :         char charset_cpg[11];
    1323             : 
    1324           3 :         strcpy(cpg_file, pMMBDXP->szFileName);
    1325           3 :         CPLStrlcpy(cpg_file, CPLResetExtension(cpg_file, "cpg"),
    1326             :                    sizeof(cpg_file));
    1327           3 :         f_cpg = VSIFOpenL(cpg_file, "r");
    1328           3 :         if (f_cpg)
    1329             :         {
    1330             :             char *p;
    1331             :             size_t read_bytes;
    1332           0 :             VSIFSeekL(f_cpg, 0L, SEEK_SET);
    1333           0 :             if (11 > (read_bytes = VSIFReadL(charset_cpg, 1, 10, f_cpg)))
    1334             :             {
    1335           0 :                 charset_cpg[read_bytes] = '\0';
    1336           0 :                 p = MM_stristr(charset_cpg, "UTF-8");
    1337           0 :                 if (p)
    1338           0 :                     pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF;
    1339           0 :                 p = MM_stristr(charset_cpg, "UTF8");
    1340           0 :                 if (p)
    1341           0 :                     pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF;
    1342           0 :                 p = MM_stristr(charset_cpg, "ISO-8859-1");
    1343           0 :                 if (p)
    1344           0 :                     pMMBDXP->CharSet = MM_JOC_CARAC_ANSI_DBASE;
    1345             :             }
    1346           0 :             VSIFCloseL(f_cpg);
    1347             :         }
    1348             :     }
    1349         115 :     if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
    1350             :     {
    1351             :         unsigned short FirstRecordOffsetLow16Bits;
    1352             :         unsigned short FirstRecordOffsetHigh16Bits;
    1353             :         GUInt32 nTmp;
    1354             : 
    1355          38 :         memcpy(&FirstRecordOffsetLow16Bits, &offset_primera_fitxa, 2);
    1356          38 :         memcpy(&FirstRecordOffsetHigh16Bits, &pMMBDXP->reserved_2, 2);
    1357             : 
    1358          38 :         nTmp = ((GUInt32)FirstRecordOffsetHigh16Bits << 16) |
    1359             :                FirstRecordOffsetLow16Bits;
    1360          38 :         if (nTmp > INT32_MAX)
    1361             :         {
    1362           0 :             VSIFree(pMMBDXP->pField);
    1363           0 :             pMMBDXP->pField = nullptr;
    1364           0 :             pMMBDXP->nFields = 0;
    1365           0 :             fclose_and_nullify(&pMMBDXP->pfDataBase);
    1366           0 :             return 1;
    1367             :         }
    1368          38 :         pMMBDXP->FirstRecordOffset = (MM_FIRST_RECORD_OFFSET_TYPE)nTmp;
    1369             : 
    1370          38 :         if (some_problems_when_reading > 0)
    1371           0 :             offset_fals = pMMBDXP->FirstRecordOffset;
    1372             : 
    1373          38 :         memcpy(&FirstRecordOffsetLow16Bits, &two_bytes, 2);
    1374          38 :         memcpy(&FirstRecordOffsetHigh16Bits, &pMMBDXP->reserved_1, 2);
    1375             : 
    1376          38 :         pMMBDXP->BytesPerRecord = ((GUInt32)FirstRecordOffsetHigh16Bits << 16) |
    1377             :                                   FirstRecordOffsetLow16Bits;
    1378             :     }
    1379             :     else
    1380             :     {
    1381          77 :         pMMBDXP->FirstRecordOffset = offset_primera_fitxa;
    1382          77 :         pMMBDXP->BytesPerRecord = two_bytes;
    1383             :     }
    1384             : 
    1385             :     /* ====== Record structure ========================= */
    1386             : 
    1387         115 :     if (some_problems_when_reading > 0)
    1388             :     {
    1389           0 :         if (offset_fals < 1 + 32)
    1390           0 :             pMMBDXP->nFields = 0;
    1391             :         else
    1392           0 :             pMMBDXP->nFields =
    1393           0 :                 (MM_EXT_DBF_N_FIELDS)(((offset_fals - 1) - 32) / 32);
    1394             :     }
    1395             :     else
    1396             :     {
    1397             :         // There's a chance that bytes_acumulats could overflow if it's GUInt32.
    1398             :         // For that reason it's better to promote to GUInt64.
    1399         115 :         GUInt64 bytes_acumulats = 1;
    1400             : 
    1401         115 :         pMMBDXP->nFields = 0;
    1402             : 
    1403         115 :         VSIFSeekL(pf, 0, SEEK_END);
    1404         115 :         if (32 - 1 < VSIFTellL(pf))
    1405             :         {
    1406         115 :             VSIFSeekL(pf, 32, SEEK_SET);
    1407             :             do
    1408             :             {
    1409        1081 :                 bytes_per_camp = 0;
    1410        1081 :                 VSIFSeekL(pf,
    1411        1081 :                           32 + (MM_FILE_OFFSET)pMMBDXP->nFields * 32 +
    1412             :                               (MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF + 1 + 4),
    1413             :                           SEEK_SET);
    1414        2162 :                 if (1 != VSIFReadL(&bytes_per_camp, 1, 1, pf) ||
    1415        2162 :                     1 != VSIFReadL(&un_byte, 1, 1, pf) ||
    1416        1081 :                     1 != VSIFReadL(&tretze_bytes, 3 + sizeof(bytes_per_camp), 1,
    1417             :                                    pf))
    1418             :                 {
    1419           0 :                     VSIFree(pMMBDXP->pField);
    1420           0 :                     pMMBDXP->pField = nullptr;
    1421           0 :                     pMMBDXP->nFields = 0;
    1422           0 :                     fclose_and_nullify(&pMMBDXP->pfDataBase);
    1423           0 :                     return 1;
    1424             :                 }
    1425        1081 :                 if (bytes_per_camp == 0)
    1426          79 :                     memcpy(&bytes_per_camp, (char *)(&tretze_bytes) + 3,
    1427             :                            sizeof(bytes_per_camp));
    1428             : 
    1429        1081 :                 bytes_acumulats += bytes_per_camp;
    1430        1081 :                 pMMBDXP->nFields++;
    1431        1081 :             } while (bytes_acumulats < pMMBDXP->BytesPerRecord);
    1432             :         }
    1433             :     }
    1434             : 
    1435         115 :     if (pMMBDXP->nFields != 0)
    1436             :     {
    1437         115 :         VSIFree(pMMBDXP->pField);
    1438         115 :         pMMBDXP->pField = MM_CreateAllFields(pMMBDXP->nFields);
    1439         115 :         if (!pMMBDXP->pField)
    1440             :         {
    1441           0 :             pMMBDXP->nFields = 0;
    1442           0 :             fclose_and_nullify(&pMMBDXP->pfDataBase);
    1443           0 :             return 1;
    1444             :         }
    1445             :     }
    1446             :     else
    1447             :     {
    1448           0 :         VSIFree(pMMBDXP->pField);
    1449           0 :         pMMBDXP->pField = nullptr;
    1450             :     }
    1451             : 
    1452         115 :     VSIFSeekL(pf, 32, SEEK_SET);
    1453        1196 :     for (nIField = 0; nIField < pMMBDXP->nFields; nIField++)
    1454             :     {
    1455        1081 :         if (1 != VSIFReadL(pMMBDXP->pField[nIField].FieldName,
    1456        1081 :                            MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF, 1, pf) ||
    1457        2162 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].FieldType), 1, 1, pf) ||
    1458        2162 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].reserved_1), 4, 1, pf) ||
    1459        1081 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].BytesPerField), 1, 1,
    1460        1081 :                            pf) ||
    1461        1081 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].DecimalsIfFloat), 1, 1,
    1462        1081 :                            pf) ||
    1463        2162 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].reserved_2), 13, 1, pf) ||
    1464             :             1 !=
    1465        1081 :                 VSIFReadL(&(pMMBDXP->pField[nIField].MDX_field_flag), 1, 1, pf))
    1466             :         {
    1467           0 :             VSIFree(pMMBDXP->pField);
    1468           0 :             pMMBDXP->pField = nullptr;
    1469           0 :             pMMBDXP->nFields = 0;
    1470           0 :             VSIFCloseL(pf);
    1471           0 :             pMMBDXP->pfDataBase = nullptr;
    1472           0 :             return 1;
    1473             :         }
    1474             : 
    1475        1081 :         if (pMMBDXP->pField[nIField].FieldType == 'F')
    1476           0 :             pMMBDXP->pField[nIField].FieldType = 'N';
    1477             : 
    1478        1081 :         pMMBDXP->pField[nIField]
    1479        1081 :             .FieldName[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0';
    1480        1081 :         if (EQUAL(pMMBDXP->pField[nIField].FieldName,
    1481             :                   szMMNomCampIdGraficDefecte))
    1482         115 :             pMMBDXP->IdGraficField = nIField;
    1483             : 
    1484             :         // Limit BytesPerField to avoid later integer overflows
    1485             :         // We could potentially limit further...
    1486        1081 :         if (pMMBDXP->pField[nIField].BytesPerField > (uint32_t)(INT32_MAX - 1))
    1487             :         {
    1488           0 :             VSIFree(pMMBDXP->pField);
    1489           0 :             pMMBDXP->pField = nullptr;
    1490           0 :             pMMBDXP->nFields = 0;
    1491           0 :             VSIFCloseL(pf);
    1492           0 :             pMMBDXP->pfDataBase = nullptr;
    1493           0 :             return 1;
    1494             :         }
    1495             : 
    1496        1081 :         if (pMMBDXP->pField[nIField].BytesPerField == 0)
    1497             :         {
    1498          79 :             if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
    1499             :             {
    1500           0 :                 VSIFree(pMMBDXP->pField);
    1501           0 :                 pMMBDXP->pField = nullptr;
    1502           0 :                 pMMBDXP->nFields = 0;
    1503           0 :                 VSIFCloseL(pf);
    1504           0 :                 pMMBDXP->pfDataBase = nullptr;
    1505           0 :                 return 1;
    1506             :             }
    1507          79 :             if (pMMBDXP->pField[nIField].FieldType != 'C')
    1508             :             {
    1509           0 :                 VSIFree(pMMBDXP->pField);
    1510           0 :                 pMMBDXP->pField = nullptr;
    1511           0 :                 pMMBDXP->nFields = 0;
    1512           0 :                 VSIFCloseL(pf);
    1513           0 :                 pMMBDXP->pfDataBase = nullptr;
    1514           0 :                 return 1;
    1515             :             }
    1516             : 
    1517          79 :             memcpy(&pMMBDXP->pField[nIField].BytesPerField,
    1518          79 :                    (char *)(&pMMBDXP->pField[nIField].reserved_2) + 3,
    1519             :                    sizeof(MM_BYTES_PER_FIELD_TYPE_DBF));
    1520             :         }
    1521             : 
    1522        1081 :         if (nIField)
    1523             :         {
    1524             :             // To avoid overflow
    1525         966 :             if (pMMBDXP->pField[nIField - 1].AccumulatedBytes >
    1526         966 :                 UINT32_MAX - pMMBDXP->pField[nIField - 1].BytesPerField)
    1527             :             {
    1528           0 :                 VSIFree(pMMBDXP->pField);
    1529           0 :                 pMMBDXP->pField = nullptr;
    1530           0 :                 pMMBDXP->nFields = 0;
    1531           0 :                 VSIFCloseL(pf);
    1532           0 :                 pMMBDXP->pfDataBase = nullptr;
    1533           0 :                 return 1;
    1534             :             }
    1535             : 
    1536         966 :             pMMBDXP->pField[nIField].AccumulatedBytes =
    1537         966 :                 (pMMBDXP->pField[nIField - 1].AccumulatedBytes +
    1538         966 :                  pMMBDXP->pField[nIField - 1].BytesPerField);
    1539             :         }
    1540             :         else
    1541             :         {
    1542         115 :             pMMBDXP->pField[nIField].AccumulatedBytes = 1;
    1543             :         }
    1544             : 
    1545        1081 :         if (pszRelFile)
    1546             :         {
    1547             :             // Usually, in multilingual MiraMon metadata files, the main
    1548             :             // language is the default one and has no "_cat", "_spa", or
    1549             :             // "_eng" suffix after the keyword. So, to retrieve all
    1550             :             // languages in a multilingual file, first, we'll identify
    1551             :             // the one with no suffix "_cat", "_spa", or "_eng", and then the
    1552             :             // others. If one of them lacks a value, it gets the default value.
    1553        1081 :             snprintf(section, sizeof(section), "TAULA_PRINCIPAL:%s",
    1554        1081 :                      pMMBDXP->pField[nIField].FieldName);
    1555             : 
    1556             :             // MM_DEF_LANGUAGE
    1557        1081 :             pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
    1558             :                                                       "descriptor");
    1559        1081 :             if (pszDesc)
    1560             :             {
    1561         602 :                 CPLStrlcpy(
    1562         602 :                     pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
    1563             :                     pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1564             : 
    1565         602 :                 VSIFree(pszDesc);
    1566             :             }
    1567             :             else
    1568         479 :                 *pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE] =
    1569             :                     '\0';
    1570             : 
    1571             :             // MM_ENG_LANGUAGE
    1572        1081 :             pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
    1573             :                                                       "descriptor_eng");
    1574        1081 :             if (pszDesc)
    1575             :             {
    1576          70 :                 CPLStrlcpy(
    1577          70 :                     pMMBDXP->pField[nIField].FieldDescription[MM_ENG_LANGUAGE],
    1578             :                     pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1579             : 
    1580          70 :                 if (*pMMBDXP->pField[nIField]
    1581             :                          .FieldDescription[MM_DEF_LANGUAGE] == '\0')
    1582             :                 {
    1583           0 :                     CPLStrlcpy(pMMBDXP->pField[nIField]
    1584           0 :                                    .FieldDescription[MM_DEF_LANGUAGE],
    1585             :                                pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1586             :                 }
    1587          70 :                 VSIFree(pszDesc);
    1588             :             }
    1589             :             else
    1590             :             {
    1591             :                 // If there is no value descriptor_eng it's because it's the
    1592             :                 // default one. So, it's taken from there.
    1593        1011 :                 CPLStrlcpy(
    1594        1011 :                     pMMBDXP->pField[nIField].FieldDescription[MM_ENG_LANGUAGE],
    1595        1011 :                     pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
    1596             :                     MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1597             :             }
    1598             : 
    1599             :             // MM_CAT_LANGUAGE
    1600        1081 :             pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
    1601             :                                                       "descriptor_cat");
    1602        1081 :             if (pszDesc)
    1603             :             {
    1604           0 :                 CPLStrlcpy(
    1605           0 :                     pMMBDXP->pField[nIField].FieldDescription[MM_CAT_LANGUAGE],
    1606             :                     pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1607             : 
    1608           0 :                 if (*pMMBDXP->pField[nIField]
    1609             :                          .FieldDescription[MM_DEF_LANGUAGE] == '\0')
    1610             :                 {
    1611           0 :                     CPLStrlcpy(pMMBDXP->pField[nIField]
    1612           0 :                                    .FieldDescription[MM_DEF_LANGUAGE],
    1613             :                                pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1614             :                 }
    1615             : 
    1616           0 :                 VSIFree(pszDesc);
    1617             :             }
    1618             :             else
    1619             :             {
    1620             :                 // If there is no value descriptor_cat it's because it's the
    1621             :                 // default one. So, it's taken from there.
    1622        1081 :                 CPLStrlcpy(
    1623        1081 :                     pMMBDXP->pField[nIField].FieldDescription[MM_CAT_LANGUAGE],
    1624        1081 :                     pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
    1625             :                     MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1626             :             }
    1627             : 
    1628             :             // MM_SPA_LANGUAGE
    1629        1081 :             pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
    1630             :                                                       "descriptor_spa");
    1631        1081 :             if (pszDesc)
    1632             :             {
    1633          70 :                 CPLStrlcpy(
    1634          70 :                     pMMBDXP->pField[nIField].FieldDescription[MM_SPA_LANGUAGE],
    1635             :                     pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1636             : 
    1637          70 :                 if (*pMMBDXP->pField[nIField]
    1638             :                          .FieldDescription[MM_DEF_LANGUAGE] == '\0')
    1639             :                 {
    1640           0 :                     CPLStrlcpy(pMMBDXP->pField[nIField]
    1641           0 :                                    .FieldDescription[MM_DEF_LANGUAGE],
    1642             :                                pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1643             :                 }
    1644             : 
    1645          70 :                 VSIFree(pszDesc);
    1646             :             }
    1647             :             else
    1648             :             {
    1649             :                 // If there is no value descriptor_spa it's because it's the
    1650             :                 // default one. So, it's taken from there.
    1651        1011 :                 CPLStrlcpy(
    1652        1011 :                     pMMBDXP->pField[nIField].FieldDescription[MM_SPA_LANGUAGE],
    1653        1011 :                     pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
    1654             :                     MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1655             :             }
    1656             :         }
    1657             :     }
    1658             : 
    1659         115 :     if (!pMMBDXP->nFields)
    1660             :     {
    1661           0 :         if (pMMBDXP->BytesPerRecord)
    1662           0 :             incoherent_record_size = TRUE;
    1663             :     }
    1664             :     else
    1665             :     {
    1666             :         // To avoid overflow
    1667         115 :         if (pMMBDXP->pField[pMMBDXP->nFields - 1].AccumulatedBytes >
    1668         115 :             UINT32_MAX - pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField)
    1669             :         {
    1670           0 :             VSIFree(pMMBDXP->pField);
    1671           0 :             pMMBDXP->pField = nullptr;
    1672           0 :             pMMBDXP->nFields = 0;
    1673           0 :             VSIFCloseL(pf);
    1674           0 :             pMMBDXP->pfDataBase = nullptr;
    1675           0 :             return 1;
    1676             :         }
    1677         115 :         if (pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField +
    1678         115 :                 pMMBDXP->pField[pMMBDXP->nFields - 1].AccumulatedBytes >
    1679         115 :             pMMBDXP->BytesPerRecord)
    1680           0 :             incoherent_record_size = TRUE;
    1681             :     }
    1682         115 :     if (incoherent_record_size)
    1683             :     {
    1684           0 :         if (some_problems_when_reading == 0)
    1685             :         {
    1686           0 :             incoherent_record_size = FALSE;
    1687           0 :             VSIFSeekL(pf, offset_reintent, SEEK_SET);
    1688           0 :             some_problems_when_reading++;
    1689             :             /* Reset IdGraficField as it might no longer be valid */
    1690           0 :             pMMBDXP->IdGraficField = 0;
    1691           0 :             goto reintenta_lectura_per_si_error_CreaCampBD_XP;
    1692             :         }
    1693             :         else
    1694             :         {
    1695           0 :             VSIFree(pMMBDXP->pField);
    1696           0 :             pMMBDXP->pField = nullptr;
    1697           0 :             pMMBDXP->nFields = 0;
    1698           0 :             VSIFCloseL(pf);
    1699           0 :             pMMBDXP->pfDataBase = nullptr;
    1700           0 :             return 1;
    1701             :         }
    1702             :     }
    1703             : 
    1704         115 :     offset_possible = 32 + 32 * (pMMBDXP->nFields) + 1;
    1705             : 
    1706         115 :     if (!incoherent_record_size &&
    1707         115 :         offset_possible != pMMBDXP->FirstRecordOffset)
    1708             :     {  // Extended names
    1709             :         MM_FIRST_RECORD_OFFSET_TYPE offset_nom_camp;
    1710             :         int mida_nom;
    1711             : 
    1712         370 :         for (nIField = 0; nIField < pMMBDXP->nFields; nIField++)
    1713             :         {
    1714             :             offset_nom_camp =
    1715         332 :                 MM_GiveOffsetExtendedFieldName(pMMBDXP->pField + nIField);
    1716         332 :             mida_nom = MM_DonaBytesNomEstesCamp(pMMBDXP->pField + nIField);
    1717         332 :             if (mida_nom > 0 && mida_nom < MM_MAX_LON_FIELD_NAME_DBF &&
    1718         101 :                 offset_nom_camp >= offset_possible &&
    1719         101 :                 offset_nom_camp < pMMBDXP->FirstRecordOffset)
    1720             :             {
    1721         101 :                 CPLStrlcpy(pMMBDXP->pField[nIField].ClassicalDBFFieldName,
    1722         101 :                            pMMBDXP->pField[nIField].FieldName,
    1723             :                            MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
    1724         101 :                 VSIFSeekL(pf, offset_nom_camp, SEEK_SET);
    1725         101 :                 if (1 != VSIFReadL(pMMBDXP->pField[nIField].FieldName, mida_nom,
    1726             :                                    1, pf))
    1727             :                 {
    1728           0 :                     VSIFree(pMMBDXP->pField);
    1729           0 :                     pMMBDXP->pField = nullptr;
    1730           0 :                     pMMBDXP->nFields = 0;
    1731           0 :                     VSIFCloseL(pf);
    1732           0 :                     pMMBDXP->pfDataBase = nullptr;
    1733           0 :                     return 1;
    1734             :                 }
    1735         101 :                 pMMBDXP->pField[nIField].FieldName[mida_nom] = '\0';
    1736             : 
    1737             :                 // All field names to UTF-8
    1738         101 :                 if (pMMBDXP->CharSet == MM_JOC_CARAC_ANSI_DBASE)
    1739             :                 {
    1740          81 :                     pszString = CPLRecode(pMMBDXP->pField[nIField].FieldName,
    1741             :                                           CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
    1742          81 :                     CPLStrlcpy(pMMBDXP->pField[nIField].FieldName, pszString,
    1743             :                                MM_MAX_LON_FIELD_NAME_DBF);
    1744          81 :                     CPLFree(pszString);
    1745             :                 }
    1746          20 :                 else if (pMMBDXP->CharSet == MM_JOC_CARAC_OEM850_DBASE)
    1747             :                 {
    1748          15 :                     MM_oemansi(pMMBDXP->pField[nIField].FieldName);
    1749          15 :                     pszString = CPLRecode(pMMBDXP->pField[nIField].FieldName,
    1750             :                                           CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
    1751          15 :                     CPLStrlcpy(pMMBDXP->pField[nIField].FieldName, pszString,
    1752             :                                MM_MAX_LON_FIELD_NAME_DBF - 1);
    1753          15 :                     CPLFree(pszString);
    1754             :                 }
    1755             :             }
    1756             :         }
    1757             :     }
    1758             : 
    1759         115 :     pMMBDXP->IdEntityField = MM_MAX_EXT_DBF_N_FIELDS_TYPE;
    1760         115 :     return 0;
    1761             : }  // End of MM_ReadExtendedDBFHeaderFromFile()
    1762             : 
    1763         307 : void MM_ReleaseDBFHeader(struct MM_DATA_BASE_XP **data_base_XP)
    1764             : {
    1765         307 :     if (!data_base_XP)
    1766           0 :         return;
    1767         307 :     if (!*data_base_XP)
    1768           0 :         return;
    1769             : 
    1770         307 :     MM_ReleaseMainFields(*data_base_XP);
    1771         307 :     VSIFree(*data_base_XP);
    1772         307 :     *data_base_XP = nullptr;
    1773             : 
    1774         307 :     return;
    1775             : }
    1776             : 
    1777         575 : int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP(
    1778             :     struct MM_FIELD *camp, struct MM_DATA_BASE_XP *bd_xp,
    1779             :     MM_BOOLEAN no_modifica_descriptor, size_t mida_nom)
    1780             : {
    1781             :     MM_EXT_DBF_N_FIELDS i_camp;
    1782         575 :     unsigned n_digits_i = 0, i;
    1783         575 :     int retorn = 0;
    1784             : 
    1785         575 :     if (mida_nom == 0)
    1786         575 :         mida_nom = MM_MAX_LON_FIELD_NAME_DBF;
    1787             : 
    1788        5744 :     for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1789             :     {
    1790        5239 :         if (bd_xp->pField + i_camp == camp)
    1791         505 :             continue;
    1792        4734 :         if (!strcasecmp(bd_xp->pField[i_camp].FieldName, camp->FieldName))
    1793          70 :             break;
    1794             :     }
    1795         575 :     if (i_camp < bd_xp->nFields)
    1796             :     {
    1797          70 :         retorn = 1;
    1798          70 :         if (strlen(camp->FieldName) > mida_nom - 2)
    1799           0 :             camp->FieldName[mida_nom - 2] = '\0';
    1800          70 :         strcat(camp->FieldName, "0");
    1801          70 :         for (i = 2; i < (size_t)10; i++)
    1802             :         {
    1803          70 :             snprintf(camp->FieldName + strlen(camp->FieldName) - 1,
    1804          70 :                      sizeof(camp->FieldName) - strlen(camp->FieldName) + 1,
    1805             :                      "%u", i);
    1806         965 :             for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1807             :             {
    1808         895 :                 if (bd_xp->pField + i_camp == camp)
    1809          70 :                     continue;
    1810         825 :                 if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
    1811         825 :                                 camp->FieldName))
    1812           0 :                     break;
    1813             :             }
    1814          70 :             if (i_camp == bd_xp->nFields)
    1815             :             {
    1816          70 :                 n_digits_i = 1;
    1817          70 :                 break;
    1818             :             }
    1819             :         }
    1820          70 :         if (i == 10)
    1821             :         {
    1822           0 :             camp->FieldName[strlen(camp->FieldName) - 1] = '\0';
    1823           0 :             if (strlen(camp->FieldName) > mida_nom - 3)
    1824           0 :                 camp->FieldName[mida_nom - 3] = '\0';
    1825           0 :             strcat(camp->FieldName, "00");
    1826           0 :             for (i = 10; i < (size_t)100; i++)
    1827             :             {
    1828           0 :                 snprintf(camp->FieldName + strlen(camp->FieldName) - 2,
    1829           0 :                          sizeof(camp->FieldName) - strlen(camp->FieldName) + 2,
    1830             :                          "%u", i);
    1831           0 :                 for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1832             :                 {
    1833           0 :                     if (bd_xp->pField + i_camp == camp)
    1834           0 :                         continue;
    1835           0 :                     if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
    1836           0 :                                     camp->FieldName))
    1837           0 :                         break;
    1838             :                 }
    1839           0 :                 if (i_camp == bd_xp->nFields)
    1840             :                 {
    1841           0 :                     n_digits_i = 2;
    1842           0 :                     break;
    1843             :                 }
    1844             :             }
    1845           0 :             if (i == 100)
    1846             :             {
    1847           0 :                 camp->FieldName[strlen(camp->FieldName) - 2] = '\0';
    1848           0 :                 if (strlen(camp->FieldName) > mida_nom - 4)
    1849           0 :                     camp->FieldName[mida_nom - 4] = '\0';
    1850           0 :                 strcat(camp->FieldName, "000");
    1851           0 :                 for (i = 100; i < (size_t)256 + 2; i++)
    1852             :                 {
    1853           0 :                     snprintf(camp->FieldName + strlen(camp->FieldName) - 3,
    1854           0 :                              sizeof(camp->FieldName) - strlen(camp->FieldName) +
    1855             :                                  3,
    1856             :                              "%u", i);
    1857           0 :                     for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1858             :                     {
    1859           0 :                         if (bd_xp->pField + i_camp == camp)
    1860           0 :                             continue;
    1861           0 :                         if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
    1862           0 :                                         camp->FieldName))
    1863           0 :                             break;
    1864             :                     }
    1865           0 :                     if (i_camp == bd_xp->nFields)
    1866             :                     {
    1867           0 :                         n_digits_i = 3;
    1868           0 :                         break;
    1869             :                     }
    1870             :                 }
    1871           0 :                 if (i == 256)
    1872           0 :                     return 2;
    1873             :             }
    1874             :         }
    1875             :     }
    1876             :     else
    1877             :     {
    1878         505 :         i = 1;
    1879             :     }
    1880             : 
    1881         575 :     if ((*(camp->FieldDescription[0]) == '\0') || no_modifica_descriptor)
    1882         476 :         return retorn;
    1883             : 
    1884        1329 :     for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1885             :     {
    1886        1230 :         if (bd_xp->pField + i_camp == camp)
    1887          99 :             continue;
    1888        1131 :         if (!strcasecmp(bd_xp->pField[i_camp].FieldDescription[0],
    1889        1131 :                         camp->FieldDescription[0]))
    1890           0 :             break;
    1891             :     }
    1892          99 :     if (i_camp == bd_xp->nFields)
    1893          99 :         return retorn;
    1894             : 
    1895           0 :     if (retorn == 1)
    1896             :     {
    1897           0 :         if (strlen(camp->FieldDescription[0]) >
    1898           0 :             MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i)
    1899           0 :             camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0';
    1900             : 
    1901           0 :         snprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]),
    1902             :                  sizeof(camp->FieldDescription[0]) -
    1903           0 :                      strlen(camp->FieldDescription[0]),
    1904             :                  " (%u)", i);
    1905           0 :         for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1906             :         {
    1907           0 :             if (bd_xp->pField + i_camp == camp)
    1908           0 :                 continue;
    1909           0 :             if (!strcasecmp(bd_xp->pField[i_camp].FieldDescription[0],
    1910           0 :                             camp->FieldDescription[0]))
    1911           0 :                 break;
    1912             :         }
    1913           0 :         if (i_camp == bd_xp->nFields)
    1914           0 :             return retorn;
    1915             :     }
    1916             : 
    1917           0 :     retorn = 1;
    1918           0 :     if (strlen(camp->FieldDescription[0]) >
    1919           0 :         MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i)
    1920           0 :         camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0';
    1921           0 :     camp->FieldDescription[0][strlen(camp->FieldDescription[0]) - 4 -
    1922           0 :                               n_digits_i + 1] = '\0';
    1923           0 :     if (strlen(camp->FieldDescription[0]) > MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 7)
    1924           0 :         camp->FieldDescription[0][mida_nom - 7] = '\0';
    1925           0 :     for (i++; i < (size_t)256; i++)
    1926             :     {
    1927             :         //if (camp->FieldDescription[0] + strlen(camp->FieldDescription[0]))
    1928           0 :         snprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]),
    1929             :                  sizeof(camp->FieldDescription[0]) -
    1930           0 :                      strlen(camp->FieldDescription[0]),
    1931             :                  " (%u)", i);
    1932           0 :         for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1933             :         {
    1934           0 :             if (bd_xp->pField + i_camp == camp)
    1935           0 :                 continue;
    1936           0 :             if (!strcasecmp(bd_xp->pField[i_camp].FieldName, camp->FieldName))
    1937           0 :                 break;
    1938             :         }
    1939           0 :         if (i_camp == bd_xp->nFields)
    1940           0 :             return retorn;
    1941             :     }
    1942           0 :     return 2;
    1943             : }  // End of MM_ModifyFieldNameAndDescriptorIfPresentBD_XP()
    1944             : 
    1945         575 : static int MM_DuplicateMultilingualString(
    1946             :     char *(szChain_final[MM_NUM_IDIOMES_MD_MULTIDIOMA]),
    1947             :     const char *const(szChain_inicial[MM_NUM_IDIOMES_MD_MULTIDIOMA]))
    1948             : {
    1949             :     size_t i;
    1950             : 
    1951        2875 :     for (i = 0; i < MM_NUM_IDIOMES_MD_MULTIDIOMA; i++)
    1952             :     {
    1953        2300 :         if (szChain_inicial[i])
    1954             :         {
    1955           0 :             if (nullptr == (szChain_final[i] = strdup(szChain_inicial[i])))
    1956           0 :                 return 1;
    1957             :         }
    1958             :         else
    1959        2300 :             szChain_final[i] = nullptr;
    1960             :     }
    1961         575 :     return 0;
    1962             : }
    1963             : 
    1964         575 : int MM_DuplicateFieldDBXP(struct MM_FIELD *camp_final,
    1965             :                           const struct MM_FIELD *camp_inicial)
    1966             : {
    1967         575 :     *camp_final = *camp_inicial;
    1968             : 
    1969         575 :     if (0 != MM_DuplicateMultilingualString(
    1970         575 :                  camp_final->Separator,
    1971         575 :                  (const char *const(*))camp_inicial->Separator))
    1972           0 :         return 1;
    1973             : 
    1974         575 :     return 0;
    1975             : }
    1976             : 
    1977             : // If n_bytes==SIZE_MAX, the parameter is ignored ant, then,
    1978             : // it's assumed that szszChain is NUL terminated
    1979        2619 : char *MM_oemansi_n(char *szszChain, size_t n_bytes)
    1980             : {
    1981             :     size_t u_i;
    1982             :     unsigned char *punter_bait;
    1983        2619 :     unsigned char t_oemansi[128] = {
    1984             :         199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238,
    1985             :         236, 196, 197, 201, 230, 198, 244, 246, 242, 251, 249, 255, 214,
    1986             :         220, 248, 163, 216, 215, 131, 225, 237, 243, 250, 241, 209, 170,
    1987             :         186, 191, 174, 172, 189, 188, 161, 171, 187, 164, 164, 164, 166,
    1988             :         166, 193, 194, 192, 169, 166, 166, 164, 164, 162, 165, 164, 164,
    1989             :         164, 164, 164, 164, 164, 227, 195, 164, 164, 164, 164, 166, 164,
    1990             :         164, 164, 240, 208, 202, 203, 200, 180, 205, 206, 207, 164, 164,
    1991             :         164, 164, 166, 204, 164, 211, 223, 212, 210, 245, 213, 181, 254,
    1992             :         222, 218, 219, 217, 253, 221, 175, 180, 173, 177, 164, 190, 182,
    1993             :         167, 247, 184, 176, 168, 183, 185, 179, 178, 164, 183};
    1994        2619 :     if (n_bytes == SIZE_MAX)
    1995             :     {
    1996       26979 :         for (punter_bait = (unsigned char *)szszChain; *punter_bait;
    1997       24504 :              punter_bait++)
    1998             :         {
    1999       24504 :             if (*punter_bait > 127)
    2000         299 :                 *punter_bait = t_oemansi[*punter_bait - 128];
    2001             :         }
    2002             :     }
    2003             :     else
    2004             :     {
    2005        2004 :         for (u_i = 0, punter_bait = (unsigned char *)szszChain; u_i < n_bytes;
    2006        1860 :              punter_bait++, u_i++)
    2007             :         {
    2008        1860 :             if (*punter_bait > 127)
    2009           0 :                 *punter_bait = t_oemansi[*punter_bait - 128];
    2010             :         }
    2011             :     }
    2012        2619 :     return szszChain;
    2013             : }
    2014             : 
    2015             : // An implementation of non-sensitive strstr()
    2016        1250 : char *MM_stristr(const char *haystack, const char *needle)
    2017             : {
    2018        1250 :     if (!haystack)
    2019           0 :         return nullptr;
    2020             : 
    2021        1250 :     if (!needle)
    2022           0 :         return nullptr;
    2023             : 
    2024        1250 :     if (!*needle)
    2025           0 :         return (char *)haystack;
    2026             : 
    2027        1250 :     char *p1 = (char *)haystack;
    2028       27229 :     while (*p1 != '\0' && !EQUALN(p1, needle, strlen(needle)))
    2029       25979 :         p1++;
    2030             : 
    2031        1250 :     if (*p1 == '\0')
    2032         494 :         return nullptr;
    2033             : 
    2034         756 :     return p1;
    2035             : }
    2036             : 
    2037        2475 : char *MM_oemansi(char *szszChain)
    2038             : {
    2039        2475 :     return MM_oemansi_n(szszChain, SIZE_MAX);
    2040             : }
    2041             : 
    2042         651 : static MM_BOOLEAN MM_FillFieldDB_XP(
    2043             :     struct MM_FIELD *camp, const char *FieldName,
    2044             :     const char *FieldDescriptionEng, const char *FieldDescriptionCat,
    2045             :     const char *FieldDescriptionSpa, char FieldType,
    2046             :     MM_BYTES_PER_FIELD_TYPE_DBF BytesPerField, MM_BYTE DecimalsIfFloat)
    2047             : {
    2048             :     char nom_temp[MM_MAX_LON_FIELD_NAME_DBF];
    2049             :     int retorn_valida_nom_camp;
    2050             : 
    2051         651 :     if (FieldName)
    2052             :     {
    2053         651 :         retorn_valida_nom_camp = MM_ISExtendedNameBD_XP(FieldName);
    2054         651 :         if (retorn_valida_nom_camp == MM_DBF_NAME_NO_VALID)
    2055           0 :             return FALSE;
    2056         651 :         CPLStrlcpy(camp->FieldName, FieldName, MM_MAX_LON_FIELD_NAME_DBF);
    2057             : 
    2058         651 :         if (retorn_valida_nom_camp == MM_VALID_EXTENDED_DBF_NAME)
    2059             :         {
    2060           0 :             MM_CalculateBytesExtendedFieldName(camp);
    2061           0 :             CPLStrlcpy(nom_temp, FieldName, MM_MAX_LON_FIELD_NAME_DBF);
    2062           0 :             MM_ReturnValidClassicDBFFieldName(nom_temp);
    2063           0 :             nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF] = '\0';
    2064           0 :             CPLStrlcpy(camp->ClassicalDBFFieldName, nom_temp,
    2065             :                        MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
    2066             :         }
    2067             :     }
    2068             : 
    2069         651 :     if (FieldDescriptionEng)
    2070         651 :         CPLStrlcpy(camp->FieldDescription[MM_DEF_LANGUAGE], FieldDescriptionEng,
    2071             :                    sizeof(camp->FieldDescription[MM_DEF_LANGUAGE]));
    2072             :     else
    2073           0 :         strcpy(camp->FieldDescription[MM_DEF_LANGUAGE], "\0");
    2074             : 
    2075         651 :     if (FieldDescriptionEng)
    2076         651 :         CPLStrlcpy(camp->FieldDescription[MM_ENG_LANGUAGE], FieldDescriptionEng,
    2077             :                    sizeof(camp->FieldDescription[MM_ENG_LANGUAGE]));
    2078             :     else
    2079           0 :         strcpy(camp->FieldDescription[MM_ENG_LANGUAGE], "\0");
    2080             : 
    2081         651 :     if (FieldDescriptionCat)
    2082         651 :         CPLStrlcpy(camp->FieldDescription[MM_CAT_LANGUAGE], FieldDescriptionCat,
    2083             :                    sizeof(camp->FieldDescription[MM_CAT_LANGUAGE]));
    2084             :     else
    2085           0 :         strcpy(camp->FieldDescription[MM_CAT_LANGUAGE], "\0");
    2086             : 
    2087         651 :     if (FieldDescriptionSpa)
    2088         651 :         CPLStrlcpy(camp->FieldDescription[MM_SPA_LANGUAGE], FieldDescriptionSpa,
    2089             :                    sizeof(camp->FieldDescription[MM_SPA_LANGUAGE]));
    2090             :     else
    2091           0 :         strcpy(camp->FieldDescription[MM_SPA_LANGUAGE], "\0");
    2092             : 
    2093         651 :     camp->FieldType = FieldType;
    2094         651 :     camp->DecimalsIfFloat = DecimalsIfFloat;
    2095         651 :     camp->BytesPerField = BytesPerField;
    2096         651 :     return TRUE;
    2097             : }
    2098             : 
    2099          27 : size_t MM_DefineFirstPolygonFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp,
    2100             :                                         MM_BYTE n_perimeter_decimals,
    2101             :                                         MM_BYTE n_area_decimals_decimals)
    2102             : {
    2103          27 :     MM_EXT_DBF_N_FIELDS i_camp = 0;
    2104             : 
    2105          27 :     MM_FillFieldDB_XP(
    2106          27 :         bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
    2107             :         szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
    2108             :         szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
    2109          27 :     bd_xp->IdGraficField = 0;
    2110          27 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
    2111          27 :     i_camp++;
    2112             : 
    2113          27 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte,
    2114             :                       szNumberOfVerticesEng, szNumberOfVerticesCat,
    2115             :                       szNumberOfVerticesSpa, 'N', MM_MIN_WIDTH_N_VERTEXS, 0);
    2116          27 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS;
    2117          27 :     i_camp++;
    2118             : 
    2119          27 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampPerimetreDefecte,
    2120             :                       szPerimeterOfThePolygonEng, szPerimeterOfThePolygonCat,
    2121             :                       szPerimeterOfThePolygonSpa, 'N', MM_MIN_WIDTH_LONG,
    2122             :                       n_perimeter_decimals);
    2123          27 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_PERIMETRE;
    2124          27 :     i_camp++;
    2125             : 
    2126          27 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampAreaDefecte,
    2127             :                       szAreaOfThePolygonEng, szAreaOfThePolygonCat,
    2128             :                       szAreaOfThePolygonSpa, 'N', MM_MIN_WIDTH_AREA,
    2129             :                       n_area_decimals_decimals);
    2130          27 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_AREA;
    2131          27 :     i_camp++;
    2132             : 
    2133          27 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNArcsDefecte,
    2134             :                       szNumberOfArcsEng, szNumberOfArcsCat, szNumberOfArcsSpa,
    2135             :                       'N', MM_MIN_WIDTH_N_ARCS, 0);
    2136          27 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_ARCS;
    2137          27 :     i_camp++;
    2138             : 
    2139          27 :     MM_FillFieldDB_XP(
    2140          27 :         bd_xp->pField + i_camp, szMMNomCampNPoligonsDefecte,
    2141             :         szNumberOfElementaryPolygonsEng, szNumberOfElementaryPolygonsCat,
    2142             :         szNumberOfElementaryPolygonsSpa, 'N', MM_MIN_WIDTH_N_POLIG, 0);
    2143          27 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_POLIG;
    2144          27 :     i_camp++;
    2145             : 
    2146          27 :     return i_camp;
    2147             : }
    2148             : 
    2149          57 : size_t MM_DefineFirstArcFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp,
    2150             :                                     MM_BYTE n_decimals)
    2151             : {
    2152             :     MM_EXT_DBF_N_FIELDS i_camp;
    2153             : 
    2154          57 :     i_camp = 0;
    2155          57 :     MM_FillFieldDB_XP(
    2156          57 :         bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
    2157             :         szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
    2158             :         szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
    2159          57 :     bd_xp->IdGraficField = 0;
    2160          57 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
    2161          57 :     i_camp++;
    2162             : 
    2163          57 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte,
    2164             :                       szNumberOfVerticesEng, szNumberOfVerticesCat,
    2165             :                       szNumberOfVerticesSpa, 'N', MM_MIN_WIDTH_N_VERTEXS, 0);
    2166          57 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS;
    2167          57 :     i_camp++;
    2168             : 
    2169          57 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampLongitudArcDefecte,
    2170             :                       szLengthOfAarcEng, szLengthOfAarcCat, szLengthOfAarcSpa,
    2171             :                       'N', MM_MIN_WIDTH_LONG, n_decimals);
    2172          57 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_LONG_ARC;
    2173          57 :     i_camp++;
    2174             : 
    2175          57 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeIniDefecte,
    2176             :                       szInitialNodeEng, szInitialNodeCat, szInitialNodeSpa, 'N',
    2177             :                       MM_MIN_WIDTH_INITIAL_NODE, 0);
    2178          57 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_INI;
    2179          57 :     i_camp++;
    2180             : 
    2181          57 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeFiDefecte,
    2182             :                       szFinalNodeEng, szFinalNodeCat, szFinalNodeSpa, 'N',
    2183             :                       MM_MIN_WIDTH_FINAL_NODE, 0);
    2184          57 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_FI;
    2185          57 :     i_camp++;
    2186             : 
    2187          57 :     return i_camp;
    2188             : }
    2189             : 
    2190          57 : size_t MM_DefineFirstNodeFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp)
    2191             : {
    2192             :     MM_EXT_DBF_N_FIELDS i_camp;
    2193             : 
    2194          57 :     i_camp = 0;
    2195             : 
    2196          57 :     MM_FillFieldDB_XP(
    2197          57 :         bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
    2198             :         szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
    2199             :         szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
    2200          57 :     bd_xp->IdGraficField = 0;
    2201          57 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
    2202          57 :     i_camp++;
    2203             : 
    2204          57 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampArcsANodeDefecte,
    2205             :                       szNumberOfArcsToNodeEng, szNumberOfArcsToNodeCat,
    2206             :                       szNumberOfArcsToNodeSpa, 'N', MM_MIN_WIDTH_ARCS_TO_NODE,
    2207             :                       0);
    2208          57 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ARCS_A_NOD;
    2209          57 :     i_camp++;
    2210             : 
    2211          57 :     MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampTipusNodeDefecte,
    2212             :                       szNodeTypeEng, szNodeTypeCat, szNodeTypeSpa, 'N', 1, 0);
    2213          57 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_TIPUS_NODE;
    2214          57 :     i_camp++;
    2215             : 
    2216          57 :     return i_camp;
    2217             : }
    2218             : 
    2219          33 : size_t MM_DefineFirstPointFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp)
    2220             : {
    2221          33 :     size_t i_camp = 0;
    2222             : 
    2223          33 :     MM_FillFieldDB_XP(
    2224          33 :         bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
    2225             :         szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
    2226             :         szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
    2227          33 :     bd_xp->IdGraficField = 0;
    2228          33 :     (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
    2229          33 :     i_camp++;
    2230             : 
    2231          33 :     return i_camp;
    2232             : }
    2233             : 
    2234             : /*
    2235             :     Controlling the number of significant figures is often crucial in science
    2236             :     and technology, and the best option when nothing is known about the number
    2237             :     to be printed (if it is really small (near to 0), or very large), and
    2238             :     allows a good return (the same value) into memory when re-read from a text
    2239             :     file with scanf() functions.
    2240             :     If you need to print 0.00000000000000000000000000000000000000001 with %f
    2241             :     you will need an extremely large string. If you print 1980.45 with %E you
    2242             :     obtain 1.98045E+003, needing more space, and not being easy to interpret
    2243             :     for some people. Moreover, “normal” users do not want to see 1.0 as
    2244             :     1.0E+000 or 1.0E+00. The choice of the format specifier, and the integer
    2245             :     to be passed to the ‘*’ is not always easy,
    2246             :     and MM_SprintfDoubleSignifFigures() automatically uses a “fair” notation
    2247             :     whenever it is possible, resulting in shorter strings, being them under
    2248             :     control (the maximum length of the resulting string is always known).
    2249             :     Moreover, it avoids some failures in compilers not expecting
    2250             :     NAN or INF values.
    2251             : */
    2252         233 : int MM_SprintfDoubleSignifFigures(char *szChain, size_t size_szChain,
    2253             :                                   int nSignifFigures, double dfRealValue)
    2254             : {
    2255             :     double VALOR_LIMIT_PRINT_IN_FORMAT_E;
    2256             :     double VALOR_TOO_SMALL_TO_PRINT_f;
    2257             :     int retorn, exponent;
    2258             :     char *ptr;
    2259             : 
    2260             : #define N_POWERS MM_MAX_XS_DOUBLE
    2261             : 
    2262             :     /* This expression ensures that no garbage is written in
    2263             :     the non-significant digits of the integer part, i.e., requesting 9E20
    2264             :     with 16 significant digits does not print 90000000000000004905, where
    2265             :     "4905" is garbage generated by the print call with such a large value 
    2266             :     and "%.16f", but rather writes 9.000000000000000E+20.
    2267             :     At the same time, it ensures that 9000 requested with 4 significant
    2268             :     digits is written as 9000 and that requested with 5 significant digits
    2269             :     is written as 9000.0, but that requested with 3 significant digits is
    2270             :     written as 9.00E+03. */
    2271         233 :     double potencies_de_10[N_POWERS] = {
    2272             :         1E+1,  1E+2,  1E+3,  1E+4,  1E+5,  1E+6,  1E+7,  1E+8, 1E+9,
    2273             :         1E+10, 1E+11, 1E+12, 1E+13, 1E+14, 1E+15, 1E+16, 1E+17};
    2274             : 
    2275             :     /* This expression ensures that -9E-7 requested with 11 significant digits
    2276             :     still uses "natural" notation and gives -0.0000009000000000, which still
    2277             :     fits exactly within the 20 characters of a 'N' field in dBASE, while
    2278             :     requested with 12 significant digits jumps to exponential notation and
    2279             :     writes -9.00000000000E-07, which also fits (in this case, comfortably)
    2280             :     within the 20 characters of dBASE.
    2281             :     The expression could be replaced by: pow(10,-max(0,20-2-signif_digits)); */
    2282         233 :     double fraccions_de_10[N_POWERS + 1] = {
    2283             :         1E-1,  1E-2,  1E-3,  1E-4,  1E-5,  1E-6,  1E-7,  1E-8,  1E-9,
    2284             :         1E-10, 1E-11, 1E-12, 1E-13, 1E-14, 1E-15, 1E-16, 1E-17, 1E-18};
    2285             : 
    2286         233 :     if (!szChain)
    2287           0 :         return 0;
    2288             : 
    2289         233 :     if (size_szChain < 3)
    2290           0 :         return 0;
    2291             : 
    2292         233 :     memset(szChain, '\0', size_szChain);
    2293             : 
    2294         233 :     if (MM_IsNANDouble(dfRealValue))
    2295           0 :         return snprintf(szChain, size_szChain, "NAN");
    2296             : 
    2297         233 :     if (MM_IsDoubleInfinite(dfRealValue))
    2298           0 :         return snprintf(szChain, size_szChain, "INF");
    2299             : 
    2300         233 :     if (dfRealValue == 0.0)
    2301           3 :         return snprintf(szChain, size_szChain, "%.*f", nSignifFigures, 0.0);
    2302             : 
    2303         230 :     if (nSignifFigures < 1)
    2304           0 :         return snprintf(szChain, size_szChain, "0.0");
    2305             : 
    2306         230 :     if (nSignifFigures > N_POWERS)
    2307           0 :         nSignifFigures = N_POWERS;
    2308             : 
    2309         230 :     retorn = snprintf(szChain, size_szChain, "%.*E", nSignifFigures - 1,
    2310             :                       dfRealValue);
    2311             : 
    2312         230 :     VALOR_LIMIT_PRINT_IN_FORMAT_E = potencies_de_10[nSignifFigures - 1];
    2313         230 :     VALOR_TOO_SMALL_TO_PRINT_f =
    2314         230 :         fraccions_de_10[MM_MAX_XS_DOUBLE - nSignifFigures];
    2315             : 
    2316         230 :     if (dfRealValue > VALOR_LIMIT_PRINT_IN_FORMAT_E ||
    2317         212 :         dfRealValue < -VALOR_LIMIT_PRINT_IN_FORMAT_E ||
    2318           1 :         (dfRealValue < VALOR_TOO_SMALL_TO_PRINT_f &&
    2319           1 :          dfRealValue > -VALOR_TOO_SMALL_TO_PRINT_f))
    2320          18 :         return retorn;
    2321             : 
    2322         212 :     ptr = strchr(szChain, 'E');
    2323         212 :     if (!ptr)
    2324           0 :         return 0;
    2325         212 :     exponent = atoi(ptr + 1);
    2326             : 
    2327         212 :     return sprintf(szChain, "%.*f",
    2328         212 :                    (nSignifFigures - exponent - 1) > 0
    2329             :                        ? (nSignifFigures - exponent - 1)
    2330             :                        : 0,
    2331             :                    dfRealValue);
    2332             : #undef N_POWERS
    2333             : }  // End of SprintfDoubleXifSignif()
    2334             : 
    2335        1331 : int MM_SecureCopyStringFieldValue(char **pszStringDst, const char *pszStringSrc,
    2336             :                                   MM_EXT_DBF_N_FIELDS *nStringCurrentLength)
    2337             : {
    2338             : 
    2339        1331 :     if (!pszStringSrc)
    2340             :     {
    2341           0 :         if (1 >= *nStringCurrentLength)
    2342             :         {
    2343           0 :             void *new_ptr = VSIRealloc(*pszStringDst, 2);
    2344           0 :             if (!new_ptr)
    2345           0 :                 return 1;
    2346           0 :             *pszStringDst = new_ptr;
    2347           0 :             *nStringCurrentLength = (MM_EXT_DBF_N_FIELDS)2;
    2348             :         }
    2349           0 :         strcpy(*pszStringDst, "\0");
    2350           0 :         return 0;
    2351             :     }
    2352             : 
    2353        1331 :     if (strlen(pszStringSrc) >= *nStringCurrentLength)
    2354             :     {
    2355         450 :         void *new_ptr = VSIRealloc(*pszStringDst, strlen(pszStringSrc) + 1);
    2356         450 :         if (!new_ptr)
    2357           0 :             return 1;
    2358         450 :         (*pszStringDst) = new_ptr;
    2359         450 :         *nStringCurrentLength = (MM_EXT_DBF_N_FIELDS)(strlen(pszStringSrc) + 1);
    2360             :     }
    2361        1331 :     strcpy(*pszStringDst, pszStringSrc);
    2362        1331 :     return 0;
    2363             : }
    2364             : 
    2365             : // This function assumes that all the file is saved in disk and closed.
    2366         117 : int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP,
    2367             :                            MM_EXT_DBF_N_FIELDS nIField,
    2368             :                            MM_BYTES_PER_FIELD_TYPE_DBF nNewWidth,
    2369             :                            MM_BYTE nNewPrecision)
    2370             : {
    2371         117 :     char *record, *whites = nullptr;
    2372             :     MM_BYTES_PER_FIELD_TYPE_DBF l_glop1, l_glop2, i_glop2;
    2373             :     MM_EXT_DBF_N_RECORDS nfitx, i_reg;
    2374             :     int canvi_amplada;  // change width
    2375             :     GInt32 j;
    2376             :     MM_EXT_DBF_N_FIELDS i_camp;
    2377             :     size_t retorn_fwrite;
    2378             :     int retorn_TruncaFitxer;
    2379             : 
    2380         117 :     if (!data_base_XP)
    2381           0 :         return 1;
    2382             : 
    2383         117 :     canvi_amplada = nNewWidth - data_base_XP->pField[nIField].BytesPerField;
    2384             : 
    2385         117 :     if (data_base_XP->nRecords != 0)
    2386             :     {
    2387          48 :         l_glop1 = data_base_XP->pField[nIField].AccumulatedBytes;
    2388          48 :         i_glop2 = l_glop1 + data_base_XP->pField[nIField].BytesPerField;
    2389          48 :         if (nIField == data_base_XP->nFields - 1)
    2390          26 :             l_glop2 = 0;
    2391             :         else
    2392          22 :             l_glop2 = data_base_XP->BytesPerRecord -
    2393          22 :                       data_base_XP->pField[nIField + 1].AccumulatedBytes;
    2394             : 
    2395          48 :         if ((record = VSICalloc(1, (size_t)data_base_XP->BytesPerRecord)) ==
    2396             :             nullptr)
    2397           0 :             return 1;
    2398             : 
    2399          48 :         record[data_base_XP->BytesPerRecord - 1] = MM_SetEndOfString;
    2400             : 
    2401          48 :         if ((whites = (char *)VSICalloc(1, (size_t)nNewWidth)) == nullptr)
    2402             :         {
    2403           0 :             VSIFree(record);
    2404           0 :             return 1;
    2405             :         }
    2406          48 :         memset(whites, ' ', nNewWidth);
    2407             : 
    2408          48 :         nfitx = data_base_XP->nRecords;
    2409          48 :         i_reg = (canvi_amplada < 0 ? 0 : nfitx - 1);
    2410             :         while (TRUE)
    2411             :         {
    2412          48 :             if (0 != VSIFSeekL(data_base_XP->pfDataBase,
    2413          48 :                                data_base_XP->FirstRecordOffset +
    2414          48 :                                    (MM_FILE_OFFSET)i_reg *
    2415          48 :                                        data_base_XP->BytesPerRecord,
    2416             :                                SEEK_SET))
    2417             :             {
    2418           0 :                 VSIFree(whites);
    2419           0 :                 VSIFree(record);
    2420           0 :                 return 1;
    2421             :             }
    2422             : 
    2423          48 :             if (1 != VSIFReadL(record, data_base_XP->BytesPerRecord, 1,
    2424             :                                data_base_XP->pfDataBase))
    2425             :             {
    2426           0 :                 VSIFree(whites);
    2427           0 :                 VSIFree(record);
    2428           0 :                 return 1;
    2429             :             }
    2430             : 
    2431          48 :             if (0 !=
    2432          48 :                 VSIFSeekL(
    2433             :                     data_base_XP->pfDataBase,
    2434          48 :                     (MM_FILE_OFFSET)data_base_XP->FirstRecordOffset +
    2435          48 :                         i_reg * ((MM_FILE_OFFSET)data_base_XP->BytesPerRecord +
    2436             :                                  canvi_amplada),
    2437             :                     SEEK_SET))
    2438             :             {
    2439           0 :                 VSIFree(whites);
    2440           0 :                 VSIFree(record);
    2441           0 :                 return 1;
    2442             :             }
    2443             : 
    2444          48 :             if (1 != VSIFWriteL(record, l_glop1, 1, data_base_XP->pfDataBase))
    2445             :             {
    2446           0 :                 VSIFree(whites);
    2447           0 :                 VSIFree(record);
    2448           0 :                 return 1;
    2449             :             }
    2450             : 
    2451          48 :             switch (data_base_XP->pField[nIField].FieldType)
    2452             :             {
    2453          30 :                 case 'C':
    2454             :                 case 'L':
    2455          30 :                     memcpy(whites, record + l_glop1,
    2456             :                            (canvi_amplada < 0
    2457             :                                 ? nNewWidth
    2458          30 :                                 : data_base_XP->pField[nIField].BytesPerField));
    2459          30 :                     retorn_fwrite = VSIFWriteL(whites, nNewWidth, 1,
    2460             :                                                data_base_XP->pfDataBase);
    2461             : 
    2462          30 :                     if (1 != retorn_fwrite)
    2463             :                     {
    2464           0 :                         VSIFree(whites);
    2465           0 :                         VSIFree(record);
    2466           0 :                         return 1;
    2467             :                     }
    2468          30 :                     break;
    2469          18 :                 case 'N':
    2470             : 
    2471          18 :                     if (canvi_amplada >= 0)
    2472             :                     {
    2473          18 :                         if (1 != VSIFWriteL(whites, canvi_amplada, 1,
    2474          18 :                                             data_base_XP->pfDataBase) ||
    2475             :                             1 !=
    2476          18 :                                 VSIFWriteL(
    2477          18 :                                     record + l_glop1,
    2478          18 :                                     data_base_XP->pField[nIField].BytesPerField,
    2479             :                                     1, data_base_XP->pfDataBase))
    2480             :                         {
    2481           0 :                             VSIFree(whites);
    2482           0 :                             VSIFree(record);
    2483           0 :                             return 1;
    2484             :                         }
    2485             :                     }
    2486           0 :                     else if (canvi_amplada < 0)
    2487             :                     {
    2488           0 :                         j = (GInt32)(l_glop1 + (data_base_XP->pField[nIField]
    2489           0 :                                                     .BytesPerField -
    2490             :                                                 1));
    2491             :                         while (TRUE)
    2492             :                         {
    2493           0 :                             j--;
    2494             : 
    2495           0 :                             if (j < (GInt32)l_glop1 || record[j] == ' ')
    2496             :                             {
    2497           0 :                                 j++;
    2498           0 :                                 break;
    2499             :                             }
    2500             :                         }
    2501             : 
    2502           0 :                         if ((data_base_XP->pField[nIField].BytesPerField +
    2503           0 :                              l_glop1 - j) < nNewWidth)
    2504           0 :                             j -= (GInt32)(nNewWidth -
    2505           0 :                                           (data_base_XP->pField[nIField]
    2506           0 :                                                .BytesPerField +
    2507             :                                            l_glop1 - j));
    2508             : 
    2509           0 :                         retorn_fwrite = VSIFWriteL(record + j, nNewWidth, 1,
    2510             :                                                    data_base_XP->pfDataBase);
    2511           0 :                         if (1 != retorn_fwrite)
    2512             :                         {
    2513           0 :                             VSIFree(whites);
    2514           0 :                             VSIFree(record);
    2515           0 :                             return 1;
    2516             :                         }
    2517             :                     }
    2518             : 
    2519          18 :                     break;
    2520           0 :                 default:
    2521           0 :                     VSIFree(whites);
    2522           0 :                     VSIFree(record);
    2523           0 :                     return 1;
    2524             :             }
    2525          48 :             if (l_glop2)
    2526             :             {
    2527          22 :                 retorn_fwrite = VSIFWriteL(record + i_glop2, l_glop2, 1,
    2528             :                                            data_base_XP->pfDataBase);
    2529          22 :                 if (1 != retorn_fwrite)
    2530             :                 {
    2531           0 :                     VSIFree(whites);
    2532           0 :                     VSIFree(record);
    2533           0 :                     return 1;
    2534             :                 }
    2535             :             }
    2536             : 
    2537          48 :             if (canvi_amplada < 0)
    2538             :             {
    2539           0 :                 if (i_reg + 1 == nfitx)
    2540           0 :                     break;
    2541           0 :                 i_reg++;
    2542             :             }
    2543             :             else
    2544             :             {
    2545          48 :                 if (i_reg == 0)
    2546          48 :                     break;
    2547           0 :                 i_reg--;
    2548             :             }
    2549             :         }
    2550             : 
    2551          48 :         VSIFree(whites);
    2552          48 :         VSIFree(record);
    2553             : 
    2554          48 :         retorn_TruncaFitxer = VSIFTruncateL(
    2555             :             data_base_XP->pfDataBase,
    2556          48 :             (MM_FILE_OFFSET)data_base_XP->FirstRecordOffset +
    2557          48 :                 (MM_FILE_OFFSET)data_base_XP->nRecords *
    2558          48 :                     ((MM_FILE_OFFSET)data_base_XP->BytesPerRecord +
    2559             :                      canvi_amplada));
    2560          48 :         if (canvi_amplada < 0 && retorn_TruncaFitxer)
    2561           0 :             return 1;
    2562             :     } /* Fi de registres de != 0*/
    2563             : 
    2564         117 :     if (canvi_amplada != 0)
    2565             :     {
    2566         117 :         data_base_XP->pField[nIField].BytesPerField = nNewWidth;
    2567         117 :         data_base_XP->BytesPerRecord += canvi_amplada;
    2568         117 :         for (i_camp = (MM_EXT_DBF_N_FIELDS)(nIField + 1);
    2569         477 :              i_camp < data_base_XP->nFields; i_camp++)
    2570         360 :             data_base_XP->pField[i_camp].AccumulatedBytes += canvi_amplada;
    2571             :     }
    2572         117 :     data_base_XP->pField[nIField].DecimalsIfFloat = nNewPrecision;
    2573             : 
    2574         117 :     if ((MM_OpenIfNeededAndUpdateEntireHeader(data_base_XP)) == FALSE)
    2575           0 :         return 1;
    2576             : 
    2577         117 :     return 0;
    2578             : } /* End of MMChangeCFieldWidthDBF() */
    2579             : 
    2580        1525 : static void MM_AdoptHeight(double *desti, const double *proposta, uint32_t flag)
    2581             : {
    2582        1525 :     if (*proposta == MM_NODATA_COORD_Z)
    2583           0 :         return;
    2584             : 
    2585        1525 :     if (flag & MM_STRING_HIGHEST_ALTITUDE)
    2586             :     {
    2587           0 :         if (*desti == MM_NODATA_COORD_Z || *desti < *proposta)
    2588           0 :             *desti = *proposta;
    2589             :     }
    2590        1525 :     else if (flag & MM_STRING_LOWEST_ALTITUDE)
    2591             :     {
    2592           0 :         if (*desti == MM_NODATA_COORD_Z || *desti > *proposta)
    2593           0 :             *desti = *proposta;
    2594             :     }
    2595             :     else
    2596             :     {
    2597             :         // First coordinate of this vertice
    2598        1525 :         if (*desti == MM_NODATA_COORD_Z)
    2599        1525 :             *desti = *proposta;
    2600             :     }
    2601             : }
    2602             : 
    2603         665 : int MM_GetArcHeights(double *coord_z, VSILFILE *pF, MM_N_VERTICES_TYPE n_vrt,
    2604             :                      struct MM_ZD *pZDescription, uint32_t flag)
    2605             : {
    2606             :     MM_N_HEIGHT_TYPE i;
    2607             :     MM_N_VERTICES_TYPE i_vrt;
    2608             :     double *pcoord_z;
    2609             :     MM_N_HEIGHT_TYPE n_alcada, n_h_total;
    2610             :     int tipus;
    2611         665 :     double *alcada = nullptr, *palcada, *palcada_i;
    2612             : #define MM_N_ALCADA_LOCAL 50  // Nr of local heights
    2613             :     double local_CinquantaAlcades[MM_N_ALCADA_LOCAL];
    2614             : 
    2615        2192 :     for (i_vrt = 0; i_vrt < n_vrt; i_vrt++)
    2616        1527 :         coord_z[i_vrt] = MM_NODATA_COORD_Z;
    2617             : 
    2618         665 :     if (pZDescription->nZCount == INT_MIN)
    2619           0 :         return 0;
    2620         665 :     tipus = MM_ARC_HEIGHT_TYPE(pZDescription->nZCount);
    2621         665 :     n_alcada = MM_ARC_N_HEIGHTS(pZDescription->nZCount);
    2622         665 :     if (n_vrt == 0 || n_alcada == 0)
    2623           0 :         return 0;
    2624             : 
    2625         665 :     if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
    2626             :     {
    2627         664 :         if (n_vrt > (unsigned)(INT_MAX / n_alcada))
    2628             :         {
    2629           0 :             CPLError(CE_Failure, CPLE_OutOfMemory, "Integer overflow");
    2630           0 :             return 1;
    2631             :         }
    2632         664 :         n_h_total = (MM_N_HEIGHT_TYPE)n_vrt * n_alcada;
    2633             :     }
    2634             :     else
    2635           1 :         n_h_total = n_alcada;
    2636             : 
    2637         665 :     if (n_h_total <= MM_N_ALCADA_LOCAL)
    2638         665 :         palcada = local_CinquantaAlcades;
    2639             :     else
    2640             :     {
    2641           0 :         if (MMCheckSize_t(n_h_total, sizeof(double)))
    2642           0 :             return 1;
    2643           0 :         if (nullptr ==
    2644           0 :             (palcada = alcada = VSICalloc((size_t)n_h_total, sizeof(double))))
    2645           0 :             return 1;
    2646             :     }
    2647             : 
    2648         665 :     if (VSIFSeekL(pF, pZDescription->nOffsetZ, SEEK_SET))
    2649             :     {
    2650           0 :         if (alcada)
    2651           0 :             VSIFree(alcada);
    2652           0 :         return 1;
    2653             :     }
    2654         665 :     if (n_h_total !=
    2655         665 :         (MM_N_HEIGHT_TYPE)VSIFReadL(palcada, sizeof(double), n_h_total, pF))
    2656             :     {
    2657           0 :         if (alcada)
    2658           0 :             VSIFree(alcada);
    2659           0 :         return 1;
    2660             :     }
    2661             : 
    2662         665 :     if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
    2663             :     {
    2664         664 :         palcada_i = palcada;
    2665        1328 :         for (i = 0; i < n_alcada; i++)
    2666             :         {
    2667        2188 :             for (i_vrt = 0, pcoord_z = coord_z; i_vrt < n_vrt;
    2668        1524 :                  i_vrt++, pcoord_z++, palcada_i++)
    2669        1524 :                 MM_AdoptHeight(pcoord_z, palcada_i, flag);
    2670             :         }
    2671             :     }
    2672             :     else
    2673             :     {
    2674           1 :         palcada_i = palcada;
    2675           1 :         pcoord_z = coord_z;
    2676           2 :         for (i = 0; i < n_alcada; i++, palcada_i++)
    2677           1 :             MM_AdoptHeight(pcoord_z, palcada_i, flag);
    2678             : 
    2679           1 :         if (*pcoord_z != MM_NODATA_COORD_Z)
    2680             :         {
    2681             :             /*Copio el mateix valor a totes les alcades.*/
    2682           3 :             for (i_vrt = 1, pcoord_z++; i_vrt < (size_t)n_vrt;
    2683           2 :                  i_vrt++, pcoord_z++)
    2684           2 :                 *pcoord_z = *coord_z;
    2685             :         }
    2686             :     }
    2687         665 :     if (alcada)
    2688           0 :         VSIFree(alcada);
    2689         665 :     return 0;
    2690             : }  // End of MM_GetArcHeights()
    2691             : 
    2692       15322 : static char *MM_l_RemoveWhitespacesFromEndOfString(char *punter,
    2693             :                                                    size_t l_szChain)
    2694             : {
    2695       15322 :     size_t longitud_szChain = l_szChain;
    2696       34628 :     while (longitud_szChain > 0)
    2697             :     {
    2698       34216 :         longitud_szChain--;
    2699       34216 :         if (punter[longitud_szChain] != ' ' && punter[longitud_szChain] != '\t')
    2700             :         {
    2701       14910 :             break;
    2702             :         }
    2703       19306 :         punter[longitud_szChain] = '\0';
    2704             :     }
    2705       15322 :     return punter;
    2706             : }
    2707             : 
    2708          50 : char *MM_RemoveInitial_and_FinalQuotationMarks(char *szChain)
    2709             : {
    2710             :     char *ptr1, *ptr2;
    2711          50 :     char cometa = '"';
    2712             : 
    2713          50 :     if (*szChain == cometa)
    2714             :     {
    2715          11 :         ptr1 = szChain;
    2716          11 :         ptr2 = ptr1 + 1;
    2717          11 :         if (*ptr2)
    2718             :         {
    2719         182 :             while (*ptr2)
    2720             :             {
    2721         171 :                 *ptr1 = *ptr2;
    2722         171 :                 ptr1++;
    2723         171 :                 ptr2++;
    2724             :             }
    2725          11 :             if (*ptr1 == cometa)
    2726          11 :                 *(ptr1 - 1) = 0;
    2727             :             else
    2728           0 :                 *ptr1 = 0;
    2729             :         }
    2730             :     }
    2731          50 :     return szChain;
    2732             : } /* End of MM_RemoveInitial_and_FinalQuotationMarks() */
    2733             : 
    2734          84 : char *MM_RemoveLeadingWhitespaceOfString(char *szChain)
    2735             : {
    2736             :     char *ptr;
    2737             :     char *ptr2;
    2738             : 
    2739          84 :     if (szChain == nullptr)
    2740           0 :         return szChain;
    2741             : 
    2742         630 :     for (ptr = szChain; *ptr && (*ptr == ' ' || *ptr == '\t'); ptr++)
    2743         546 :         continue;
    2744             : 
    2745          84 :     if (ptr != szChain)
    2746             :     {
    2747          66 :         ptr2 = szChain;
    2748         534 :         while (*ptr)
    2749             :         {
    2750         468 :             *ptr2 = *ptr;
    2751         468 :             ptr2++;
    2752         468 :             ptr++;
    2753             :         }
    2754          66 :         *ptr2 = 0;
    2755             :     }
    2756          84 :     return szChain;
    2757             : }
    2758             : 
    2759       15322 : char *MM_RemoveWhitespacesFromEndOfString(char *str)
    2760             : {
    2761       15322 :     if (str == nullptr)
    2762           0 :         return str;
    2763       15322 :     return MM_l_RemoveWhitespacesFromEndOfString(str, strlen(str));
    2764             : }
    2765             : 
    2766         111 : struct MM_ID_GRAFIC_MULTIPLE_RECORD *MMCreateExtendedDBFIndex(
    2767             :     VSILFILE *f, MM_EXT_DBF_N_RECORDS nNumberOfRecords,
    2768             :     MM_FIRST_RECORD_OFFSET_TYPE offset_1era,
    2769             :     MM_ACCUMULATED_BYTES_TYPE_DBF bytes_per_fitxa,
    2770             :     MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats_id_grafic,
    2771             :     MM_BYTES_PER_FIELD_TYPE_DBF bytes_id_grafic, MM_BOOLEAN *isListField,
    2772             :     MM_EXT_DBF_N_RECORDS *nMaxN)
    2773             : {
    2774             :     struct MM_ID_GRAFIC_MULTIPLE_RECORD *id;
    2775             :     MM_EXT_DBF_N_RECORDS i_dbf;
    2776             :     MM_EXT_DBF_SIGNED_N_RECORDS i, id_grafic;
    2777             :     char *fitxa;
    2778         111 :     MM_BYTES_PER_FIELD_TYPE_DBF bytes_final_id_principi_id1 =
    2779             :         bytes_per_fitxa - bytes_id_grafic;
    2780             : 
    2781         111 :     *isListField = FALSE;
    2782         111 :     *nMaxN = 0;
    2783         111 :     if (!nNumberOfRecords)
    2784           9 :         return nullptr;  // No elements to read
    2785             : 
    2786         102 :     if (MMCheckSize_t(nNumberOfRecords, sizeof(*id)))
    2787           0 :         return nullptr;
    2788         102 :     if (nullptr == (id = (struct MM_ID_GRAFIC_MULTIPLE_RECORD *)VSICalloc(
    2789             :                         (size_t)nNumberOfRecords, sizeof(*id))))
    2790           0 :         return nullptr;
    2791             : 
    2792         102 :     if (bytes_id_grafic == UINT32_MAX)
    2793             :     {
    2794           0 :         VSIFree(id);
    2795           0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Overflow in bytes_id_graphic");
    2796           0 :         return nullptr;
    2797             :     }
    2798             : 
    2799         102 :     if (nullptr == (fitxa = (char *)VSICalloc(1, (size_t)bytes_id_grafic + 1)))
    2800             :     {
    2801           0 :         VSIFree(id);
    2802           0 :         return nullptr;
    2803             :     }
    2804         102 :     fitxa[bytes_id_grafic] = '\0';
    2805             : 
    2806         102 :     VSIFSeekL(f,
    2807         102 :               (MM_FILE_OFFSET)offset_1era +
    2808         102 :                   (MM_FILE_OFFSET)bytes_acumulats_id_grafic,
    2809             :               SEEK_SET);
    2810             : 
    2811         102 :     i_dbf = 0;
    2812             :     do
    2813             :     {
    2814         102 :         if (i_dbf == nNumberOfRecords ||
    2815         102 :             VSIFReadL(fitxa, 1, bytes_id_grafic, f) != (size_t)bytes_id_grafic)
    2816             :         {
    2817           0 :             VSIFree(id);
    2818           0 :             VSIFree(fitxa);
    2819           0 :             return nullptr;
    2820             :         }
    2821         102 :         i_dbf++;
    2822             :     } while (1 !=
    2823         204 :                  sscanf(fitxa, scanf_MM_EXT_DBF_SIGNED_N_RECORDS, &id_grafic) ||
    2824         102 :              id_grafic < 0);
    2825         102 :     i = 0;
    2826             : 
    2827             :     while (TRUE)
    2828             :     {
    2829         557 :         if (i > id_grafic)
    2830             :         {
    2831           0 :             VSIFree(id);
    2832           0 :             VSIFree(fitxa);
    2833           0 :             return nullptr;
    2834             :         }
    2835         557 :         i = id_grafic;
    2836         557 :         if (i >= (MM_EXT_DBF_SIGNED_N_RECORDS)nNumberOfRecords)
    2837             :         {
    2838           0 :             VSIFree(fitxa);
    2839           0 :             return id;
    2840             :         }
    2841         557 :         id[(size_t)i].offset = (MM_FILE_OFFSET)offset_1era +
    2842         557 :                                (MM_FILE_OFFSET)(i_dbf - 1) * bytes_per_fitxa;
    2843             :         do
    2844             :         {
    2845         599 :             id[(size_t)i].nMR++;
    2846         599 :             if (!(*isListField) && id[(size_t)i].nMR > 1)
    2847          33 :                 *isListField = TRUE;
    2848         599 :             if (*nMaxN < id[(size_t)i].nMR)
    2849         139 :                 *nMaxN = id[(size_t)i].nMR;
    2850             : 
    2851         599 :             if (i_dbf == nNumberOfRecords)
    2852             :             {
    2853         102 :                 VSIFree(fitxa);
    2854         102 :                 return id;
    2855             :             }
    2856         497 :             VSIFSeekL(f, bytes_final_id_principi_id1, SEEK_CUR);
    2857         497 :             if (VSIFReadL(fitxa, 1, bytes_id_grafic, f) !=
    2858             :                 (size_t)bytes_id_grafic)
    2859             :             {
    2860           0 :                 VSIFree(id);
    2861           0 :                 VSIFree(fitxa);
    2862           0 :                 return nullptr;
    2863             :             }
    2864         497 :             if (1 != sscanf(fitxa, scanf_MM_EXT_DBF_SIGNED_N_RECORDS,
    2865         497 :                             &id_grafic) ||
    2866         497 :                 id_grafic >= (MM_EXT_DBF_SIGNED_N_RECORDS)nNumberOfRecords)
    2867             :             {
    2868           0 :                 VSIFree(fitxa);
    2869           0 :                 return id;
    2870             :             }
    2871         497 :             i_dbf++;
    2872         497 :         } while (id_grafic == i);
    2873             :     }
    2874             : }  // End of MMCreateExtendedDBFIndex()
    2875             : 
    2876             : // READING/CREATING MIRAMON METADATA
    2877             : // Returns the value of an INI file. Used to read MiraMon metadata
    2878        5330 : char *MMReturnValueFromSectionINIFile(const char *filename, const char *section,
    2879             :                                       const char *key)
    2880             : {
    2881        5330 :     char *value = nullptr;
    2882             :     char *pszString;
    2883             :     const char *pszLine;
    2884        5330 :     char *section_header = nullptr;
    2885        5330 :     size_t key_len = 0;
    2886             : 
    2887        5330 :     VSILFILE *file = VSIFOpenL(filename, "rb");
    2888        5330 :     if (file == nullptr)
    2889             :     {
    2890           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Cannot open INI file %s.",
    2891             :                  filename);
    2892           0 :         return nullptr;
    2893             :     }
    2894             : 
    2895        5330 :     if (key)
    2896        5170 :         key_len = strlen(key);
    2897             : 
    2898      399455 :     while ((pszLine = CPLReadLine2L(file, 10000, nullptr)) != nullptr)
    2899             :     {
    2900      395828 :         pszString = CPLRecode(pszLine, CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
    2901             : 
    2902             :         // Skip comments and empty lines
    2903      395828 :         if (*pszString == ';' || *pszString == '#' || *pszString == '\n' ||
    2904      395828 :             *pszString == '\r')
    2905             :         {
    2906           0 :             VSIFree(pszString);
    2907             :             // Move to next line
    2908           0 :             continue;
    2909             :         }
    2910             : 
    2911             :         // Check for section header
    2912      395828 :         if (*pszString == '[')
    2913             :         {
    2914       86263 :             char *section_end = strchr(pszString, ']');
    2915       86263 :             if (section_end != nullptr)
    2916             :             {
    2917       86263 :                 *section_end = '\0';  // Terminate the string at ']'
    2918       86263 :                 if (section_header)
    2919       80933 :                     VSIFree(section_header);
    2920       86263 :                 section_header = CPLStrdup(pszString + 1);  // Skip the '['
    2921             :             }
    2922       86263 :             VSIFree(pszString);
    2923       86263 :             continue;
    2924             :         }
    2925             : 
    2926      309565 :         if (key)
    2927             :         {
    2928             :             // If the current line belongs to the desired section
    2929      309405 :             if (section_header != nullptr &&
    2930      309405 :                 strcmp(section_header, section) == 0)
    2931             :             {
    2932             :                 // Check if the line contains the desired key
    2933       11366 :                 if (strncmp(pszString, key, key_len) == 0 &&
    2934        1725 :                     pszString[key_len] == '=')
    2935             :                 {
    2936             :                     // Extract the value
    2937        1543 :                     char *value_start = pszString + key_len + 1;
    2938        1543 :                     char *value_end = strstr(value_start, "\r\n");
    2939        1543 :                     if (value_end != nullptr)
    2940             :                     {
    2941           0 :                         *value_end =
    2942             :                             '\0';  // Terminate the string at newline character if found
    2943             :                     }
    2944             :                     else
    2945             :                     {
    2946        1543 :                         value_end = strstr(value_start, "\n");
    2947        1543 :                         if (value_end != nullptr)
    2948             :                         {
    2949           0 :                             *value_end =
    2950             :                                 '\0';  // Terminate the string at newline character if found
    2951             :                         }
    2952             :                         else
    2953             :                         {
    2954        1543 :                             value_end = strstr(value_start, "\r");
    2955        1543 :                             if (value_end != nullptr)
    2956             :                             {
    2957           0 :                                 *value_end =
    2958             :                                     '\0';  // Terminate the string at newline character if found
    2959             :                             }
    2960             :                         }
    2961             :                     }
    2962             : 
    2963        1543 :                     value = CPLStrdup(value_start);
    2964        1543 :                     VSIFCloseL(file);
    2965        1543 :                     VSIFree(section_header);  // Free allocated memory
    2966        1543 :                     VSIFree(pszString);
    2967        1543 :                     return value;
    2968             :                 }
    2969             :             }
    2970             :         }
    2971             :         else
    2972             :         {
    2973         160 :             if (section_header)
    2974             :             {
    2975         160 :                 if (!strcmp(section_header, section))
    2976         160 :                     value = section_header;  // Freed out
    2977             :                 else
    2978           0 :                     value = nullptr;
    2979             :             }
    2980             :             else
    2981           0 :                 value = nullptr;
    2982             : 
    2983         160 :             VSIFCloseL(file);
    2984         160 :             VSIFree(pszString);
    2985         160 :             return value;
    2986             :         }
    2987      307862 :         VSIFree(pszString);
    2988             :     }
    2989             : 
    2990        3627 :     if (section_header)
    2991        3627 :         VSIFree(section_header);  // Free allocated memory
    2992        3627 :     VSIFCloseL(file);
    2993        3627 :     return value;
    2994             : }
    2995             : 
    2996             : // Retrieves EPSG codes from a CSV file based on provided geodetic identifiers.
    2997         201 : int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult,
    2998             :                                 MM_BYTE direction)
    2999             : {
    3000         201 :     char *aMMIDDBFFile = nullptr;  //m_idofic.dbf
    3001         201 :     VSILFILE *pfMMSRS = nullptr;
    3002             :     const char *pszLine;
    3003             :     size_t nLong;
    3004             :     char *id_geodes, *psidgeodes, *epsg;
    3005             : 
    3006         201 :     if (!pMMSRS_or_pSRS)
    3007             :     {
    3008          70 :         return 1;
    3009             :     }
    3010             : 
    3011             :     {
    3012             : #ifdef USE_ONLY_EMBEDDED_RESOURCE_FILES
    3013             :         const char *pszFilename = nullptr;
    3014             : #else
    3015         131 :         const char *pszFilename = CPLFindFile("gdal", "MM_m_idofic.csv");
    3016             : #endif
    3017             : #ifdef EMBED_RESOURCE_FILES
    3018             :         if (!pszFilename || EQUAL(pszFilename, "MM_m_idofic.csv"))
    3019             :         {
    3020             :             pfMMSRS = VSIFileFromMemBuffer(
    3021             :                 nullptr, (GByte *)(MiraMonGetMM_m_idofic_csv()),
    3022             :                 (int)(strlen(MiraMonGetMM_m_idofic_csv())),
    3023             :                 /* bTakeOwnership = */ false);
    3024             :         }
    3025             :         else
    3026             : #endif
    3027         131 :             if (pszFilename)
    3028             :         {
    3029         131 :             aMMIDDBFFile = CPLStrdup(pszFilename);
    3030             :         }
    3031             :     }
    3032             : 
    3033             : #ifdef EMBED_RESOURCE_FILES
    3034             :     if (!pfMMSRS)
    3035             : #endif
    3036             :     {
    3037         131 :         if (!aMMIDDBFFile)
    3038             :         {
    3039           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    3040             :                      "Error opening data\\MM_m_idofic.csv.\n");
    3041           0 :             return 1;
    3042             :         }
    3043             : 
    3044             :         // Opening the file with SRS information
    3045         131 :         if (nullptr == (pfMMSRS = VSIFOpenL(aMMIDDBFFile, "r")))
    3046             :         {
    3047           0 :             VSIFree(aMMIDDBFFile);
    3048           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    3049             :                      "Error opening data\\MM_m_idofic.csv.\n");
    3050           0 :             return 1;
    3051             :         }
    3052         131 :         VSIFree(aMMIDDBFFile);
    3053             :     }
    3054             : 
    3055             :     // Checking the header of the csv file
    3056         131 :     pszLine = CPLReadLine2L(pfMMSRS, 10000, nullptr);
    3057             : 
    3058         131 :     if (!pszLine)
    3059             : 
    3060             :     {
    3061           0 :         VSIFCloseL(pfMMSRS);
    3062           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    3063             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    3064           0 :         return 1;
    3065             :     }
    3066         131 :     id_geodes = MM_stristr(pszLine, "ID_GEODES");
    3067         131 :     if (!id_geodes)
    3068             :     {
    3069           0 :         VSIFCloseL(pfMMSRS);
    3070           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    3071             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    3072           0 :         return 1;
    3073             :     }
    3074         131 :     id_geodes[strlen("ID_GEODES")] = '\0';
    3075         131 :     psidgeodes = MM_stristr(pszLine, "PSIDGEODES");
    3076         131 :     if (!psidgeodes)
    3077             :     {
    3078           0 :         VSIFCloseL(pfMMSRS);
    3079           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    3080             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    3081           0 :         return 1;
    3082             :     }
    3083         131 :     psidgeodes[strlen("PSIDGEODES")] = '\0';
    3084             : 
    3085             :     // Is PSIDGEODES in first place?
    3086         131 :     if (strncmp(pszLine, psidgeodes, strlen("PSIDGEODES")))
    3087             :     {
    3088           0 :         VSIFCloseL(pfMMSRS);
    3089           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    3090             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    3091           0 :         return 1;
    3092             :     }
    3093             :     // Is ID_GEODES after PSIDGEODES?
    3094         131 :     if (strncmp(pszLine + strlen("PSIDGEODES") + 1, "ID_GEODES",
    3095             :                 strlen("ID_GEODES")))
    3096             :     {
    3097           0 :         VSIFCloseL(pfMMSRS);
    3098           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    3099             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    3100           0 :         return 1;
    3101             :     }
    3102             : 
    3103             :     // Looking for the information.
    3104       34994 :     while ((pszLine = CPLReadLine2L(pfMMSRS, 10000, nullptr)) != nullptr)
    3105             :     {
    3106       34943 :         id_geodes = strstr(pszLine, ";");
    3107       34943 :         if (!id_geodes)
    3108             :         {
    3109           0 :             VSIFCloseL(pfMMSRS);
    3110           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    3111             :                      "Wrong format in data\\MM_m_idofic.csv.\n");
    3112           0 :             return 1;
    3113             :         }
    3114             : 
    3115       34943 :         psidgeodes = strstr(id_geodes + 1, ";");
    3116       34943 :         if (!psidgeodes)
    3117             :         {
    3118           0 :             VSIFCloseL(pfMMSRS);
    3119           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    3120             :                      "Wrong format in data\\MM_m_idofic.csv.\n");
    3121           0 :             return 1;
    3122             :         }
    3123             : 
    3124       34943 :         id_geodes[(ptrdiff_t)psidgeodes - (ptrdiff_t)id_geodes] = '\0';
    3125       34943 :         psidgeodes = CPLStrdup(pszLine);
    3126       34943 :         psidgeodes[(ptrdiff_t)id_geodes - (ptrdiff_t)pszLine] = '\0';
    3127       34943 :         id_geodes++;
    3128             : 
    3129       34943 :         if (direction == EPSG_FROM_MMSRS)
    3130             :         {
    3131             :             // I have pMMSRS and I want pSRS
    3132       30690 :             if (strcmp(pMMSRS_or_pSRS, id_geodes))
    3133             :             {
    3134       30630 :                 VSIFree(psidgeodes);
    3135       30630 :                 continue;
    3136             :             }
    3137             : 
    3138          60 :             epsg = strstr(psidgeodes, "EPSG:");
    3139          60 :             nLong = strlen("EPSG:");
    3140          60 :             if (epsg && !strncmp(epsg, psidgeodes, nLong))
    3141             :             {
    3142          60 :                 if (epsg[nLong] != '\0')
    3143             :                 {
    3144          60 :                     strcpy(szResult, epsg + nLong);
    3145          60 :                     VSIFree(psidgeodes);
    3146          60 :                     VSIFCloseL(pfMMSRS);
    3147          60 :                     return 0;  // found
    3148             :                 }
    3149             :                 else
    3150             :                 {
    3151           0 :                     VSIFCloseL(pfMMSRS);
    3152           0 :                     *szResult = '\0';
    3153           0 :                     VSIFree(psidgeodes);
    3154           0 :                     return 1;  // not found
    3155             :                 }
    3156             :             }
    3157             :         }
    3158             :         else
    3159             :         {
    3160             :             // I have pSRS and I want pMMSRS
    3161        4253 :             epsg = strstr(psidgeodes, "EPSG:");
    3162        4253 :             nLong = strlen("EPSG:");
    3163        4253 :             if (epsg && !strncmp(epsg, psidgeodes, nLong))
    3164             :             {
    3165        3336 :                 if (epsg[nLong] != '\0')
    3166             :                 {
    3167        3336 :                     if (!strcmp(pMMSRS_or_pSRS, epsg + nLong))
    3168             :                     {
    3169          20 :                         strcpy(szResult, id_geodes);
    3170          20 :                         VSIFCloseL(pfMMSRS);
    3171          20 :                         VSIFree(psidgeodes);
    3172          20 :                         return 0;  // found
    3173             :                     }
    3174             :                 }
    3175             :             }
    3176             :         }
    3177        4233 :         VSIFree(psidgeodes);
    3178             :     }
    3179             : 
    3180          51 :     VSIFCloseL(pfMMSRS);
    3181          51 :     return 1;  // not found
    3182             : }
    3183             : 
    3184             : // Verifies the version of a MiraMon REL 4 file.
    3185         163 : int MMCheck_REL_FILE(const char *szREL_file)
    3186             : {
    3187             :     char *pszLine;
    3188             :     VSILFILE *pF;
    3189             : 
    3190             :     // Does the REL file exist?
    3191         163 :     pF = VSIFOpenL(szREL_file, "r");
    3192         163 :     if (!pF)
    3193             :     {
    3194           3 :         CPLError(CE_Failure, CPLE_OpenFailed, "The file %s must exist.",
    3195             :                  szREL_file);
    3196           3 :         return 1;
    3197             :     }
    3198         160 :     VSIFCloseL(pF);
    3199             : 
    3200             :     // Does the REL file have VERSION?
    3201             :     pszLine =
    3202         160 :         MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, nullptr);
    3203         160 :     if (!pszLine)
    3204             :     {
    3205           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    3206             :                  "The file \"%s\" must be REL4. "
    3207             :                  "You can use ConvREL.exe from MiraMon software "
    3208             :                  " or GeM+ "
    3209             :                  "to convert this file to REL4.",
    3210             :                  szREL_file);
    3211           0 :         return 1;
    3212             :     }
    3213         160 :     VSIFree(pszLine);
    3214             : 
    3215             :     // Does the REL file have the correct VERSION?
    3216             :     // Vers>=4?
    3217             :     pszLine =
    3218         160 :         MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, KEY_Vers);
    3219         160 :     if (pszLine)
    3220             :     {
    3221         160 :         if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS)
    3222             :         {
    3223           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    3224             :                      "The file \"%s\" must have %s>=%d.", szREL_file, KEY_Vers,
    3225             :                      MM_VERS);
    3226           0 :             VSIFree(pszLine);
    3227           0 :             return 1;
    3228             :         }
    3229         160 :         VSIFree(pszLine);
    3230             :     }
    3231             :     else
    3232             :     {
    3233           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    3234             :                  "The file \"%s\" must have %s>=%d.", szREL_file, KEY_Vers,
    3235             :                  MM_VERS);
    3236           0 :         return 1;
    3237             :     }
    3238             : 
    3239             :     // SubVers>=0?
    3240         160 :     pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
    3241             :                                               KEY_SubVers);
    3242         160 :     if (pszLine)
    3243             :     {
    3244         160 :         if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_ACCEPTED)
    3245             :         {
    3246           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    3247             :                      "The file \"%s\" must have %s>=%d.", szREL_file,
    3248             :                      KEY_SubVers, MM_SUBVERS_ACCEPTED);
    3249             : 
    3250           0 :             VSIFree(pszLine);
    3251           0 :             return 1;
    3252             :         }
    3253         160 :         VSIFree(pszLine);
    3254             :     }
    3255             :     else
    3256             :     {
    3257           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    3258             :                  "The file \"%s\" must have %s>=%d.", szREL_file, KEY_SubVers,
    3259             :                  MM_SUBVERS_ACCEPTED);
    3260           0 :         return 1;
    3261             :     }
    3262             : 
    3263             :     // VersMetaDades>=4?
    3264         160 :     pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
    3265             :                                               KEY_VersMetaDades);
    3266         160 :     if (pszLine)
    3267             :     {
    3268         160 :         if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS_METADADES_ACCEPTED)
    3269             :         {
    3270           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    3271             :                      "The file \"%s\" must have %s>=%d.", szREL_file,
    3272             :                      KEY_VersMetaDades, MM_VERS_METADADES_ACCEPTED);
    3273           0 :             VSIFree(pszLine);
    3274           0 :             return 1;
    3275             :         }
    3276         160 :         VSIFree(pszLine);
    3277             :     }
    3278             :     else
    3279             :     {
    3280           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    3281             :                  "The file \"%s\" must have %s>=%d.", szREL_file,
    3282             :                  KEY_VersMetaDades, MM_VERS_METADADES_ACCEPTED);
    3283           0 :         return 1;
    3284             :     }
    3285             : 
    3286             :     // SubVersMetaDades>=0?
    3287         160 :     pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
    3288             :                                               KEY_SubVersMetaDades);
    3289         160 :     if (pszLine)
    3290             :     {
    3291         160 :         if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_METADADES)
    3292             :         {
    3293           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    3294             :                      "The file \"%s\" must have %s>=%d.", szREL_file,
    3295             :                      KEY_SubVersMetaDades, MM_SUBVERS_METADADES);
    3296           0 :             VSIFree(pszLine);
    3297           0 :             return 1;
    3298             :         }
    3299         160 :         VSIFree(pszLine);
    3300             :     }
    3301             :     else
    3302             :     {
    3303           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    3304             :                  "The file \"%s\" must have %s>=%d.", szREL_file,
    3305             :                  KEY_SubVersMetaDades, MM_SUBVERS_METADADES);
    3306           0 :         return 1;
    3307             :     }
    3308         160 :     return 0;
    3309             : }
    3310             : 
    3311             : CPL_C_END  // Necessary for compiling in GDAL project

Generated by: LCOV version 1.14