From 21b77074814e57fddb7c3246814832fda2ccab1a Mon Sep 17 00:00:00 2001 From: AbelPau Date: Wed, 17 Apr 2024 16:19:21 +0200 Subject: [PATCH] Initial version of the OGR MiramonVector driver --- .gitignore | 4 +- .../Arcs/SimpleArcs/SimpleArcFileA.rel | 64 +- .../Points/SimplePoints/SimplePointsFileT.rel | 13 +- autotest/ogr/ogr_miramon_vector.py | 359 +- doc/source/drivers/vector/miramon.rst | 187 +- fuzzers/CMakeLists.txt | 1 + fuzzers/build_google_oss_fuzzers.sh | 1 + fuzzers/build_seed_corpus.sh | 20 + fuzzers/ogr_fuzzer.cpp | 26 + ogr/ogrsf_frmts/CMakeLists.txt | 4 +- ogr/ogrsf_frmts/miramon/CMakeLists.txt | 2 +- ogr/ogrsf_frmts/miramon/mm_constants.h | 12 +- ogr/ogrsf_frmts/miramon/mm_gdal_constants.h | 9 +- .../miramon/mm_gdal_driver_structs.h | 80 +- ogr/ogrsf_frmts/miramon/mm_gdal_functions.c | 1378 ++-- .../miramon/mm_gdal_functions.c.bak | 2695 ------- ogr/ogrsf_frmts/miramon/mm_gdal_functions.h | 96 +- ogr/ogrsf_frmts/miramon/mm_gdal_structures.h | 16 +- ogr/ogrsf_frmts/miramon/mm_rdlayr.c | 98 +- ogr/ogrsf_frmts/miramon/mm_wrlayr.c | 2469 +++--- ogr/ogrsf_frmts/miramon/mm_wrlayr.c.bak | 7021 ----------------- ogr/ogrsf_frmts/miramon/mm_wrlayr.h | 38 +- ogr/ogrsf_frmts/miramon/ogrmiramon.h | 39 +- .../miramon/ogrmiramondatasource.cpp | 145 +- ogr/ogrsf_frmts/miramon/ogrmiramondriver.cpp | 94 +- ogr/ogrsf_frmts/miramon/ogrmiramonlayer.cpp | 1845 +++-- scripts/fix_typos.sh | 1 + scripts/typos_allowlist.txt | 22 + 28 files changed, 4292 insertions(+), 12447 deletions(-) delete mode 100644 ogr/ogrsf_frmts/miramon/mm_gdal_functions.c.bak delete mode 100644 ogr/ogrsf_frmts/miramon/mm_wrlayr.c.bak diff --git a/.gitignore b/.gitignore index cb9a1c882aaa..731b01478725 100644 --- a/.gitignore +++ b/.gitignore @@ -169,6 +169,4 @@ gdal/share # CMake files (CMakeSettings.json is generated by Visual Studio) /build CMakeSettings.json -out/ -autotest/build/ -/buildVS +out/ \ No newline at end of file diff --git a/autotest/ogr/data/miramon/Arcs/SimpleArcs/SimpleArcFileA.rel b/autotest/ogr/data/miramon/Arcs/SimpleArcs/SimpleArcFileA.rel index d652bff7e0d8..9f92d9a62f2c 100644 --- a/autotest/ogr/data/miramon/Arcs/SimpleArcs/SimpleArcFileA.rel +++ b/autotest/ogr/data/miramon/Arcs/SimpleArcs/SimpleArcFileA.rel @@ -5,8 +5,8 @@ Vers=4 SubVers=3 [METADADES] -language=cat -MDIdiom=cat +language=cat,spa,eng +MDIdiom=cat,spa,eng dateStamp=20230628 16235471+0200 characterSet=006 nOrganismes=1 @@ -19,7 +19,7 @@ PositionName=T OrganisationName=Students and educational institutions [IDENTIFICATION] -code= +code=16b4eae3-8f74-4145-95db-babb7f0feb0f_SimpleArcFileA codeSpace= DatasetTitle=Simple Arc File @@ -29,19 +29,6 @@ HorizontalSystemIdentifier=plane unitats=STB#T_pixels unitatsY=? -[QUALITY:LINEAGE:PROCESS1] -nOrganismes=1 -history=C:\MiraMon\MM64.exe -date=20230628 16235471+0200 - -[QUALITY:LINEAGE:PROCESS1:ORGANISME_1] -IndividualName=Abel Pau -PositionName=Tècnic SIG -OrganisationName=Students and educational institutions - -[QUALITY:LINEAGE] -processes=1 - [EXTENT] toler_env=0 MinX=351.333967649907 @@ -57,36 +44,59 @@ IdGrafic=ID_GRAFIC TipusRelacio=RELACIO_1_N_DICC [TAULA_PRINCIPAL:ID_GRAFIC] -descriptor=Identificador Gràfic intern visible=0 -TractamentVariable=Ordinal +descriptor=Identificador Gràfic intern +descriptor_spa=Identificador Gráfico interno +descriptor_eng=Internal Graphic identifier +MostrarUnitats=0 [TAULA_PRINCIPAL:N_VERTEXS] -descriptor=Nombre de vèrtexs visible=0 MostrarUnitats=0 +descriptor=Nombre de vèrtexs +descriptor_spa=Número de vertices +descriptor_eng=Number of vertices [TAULA_PRINCIPAL:LONG_ARC] descriptor=Longitud de l'arc +descriptor_spa=Longitud del arco +descriptor_eng=Lenght of arc [TAULA_PRINCIPAL:NODE_INI] -descriptor=Node inicial visible=0 MostrarUnitats=0 +descriptor=Node inicial +descriptor_spa=Nodo inicial +descriptor_eng=Initial node [TAULA_PRINCIPAL:NODE_FI] -descriptor=Node final visible=0 MostrarUnitats=0 - -[GEOMETRIA_I_TOPOLOGIA] -NomCampNVertexs=N_VERTEXS -NomCampLongitudArc=LONG_ARC -NomCampNodeIni=NODE_INI -NomCampNodeFi=NODE_FI +descriptor=Node final +descriptor_spa=Nodo final +descriptor_eng=Final node [TAULA_PRINCIPAL:ATT1] descriptor=Atributte1 [TAULA_PRINCIPAL:ATT2] descriptor=Attribute2 + +[QUALITY:LINEAGE:PROCESS1] +nOrganismes=1 +history=C:\MiraMon\MM64.exe +date=20230628 16235471+0200 + +[QUALITY:LINEAGE:PROCESS1:ORGANISME_1] +IndividualName=Abel Pau +PositionName=Tècnic SIG +OrganisationName=Students and educational institutions + +[QUALITY:LINEAGE] +processes=1 + +[GEOMETRIA_I_TOPOLOGIA] +NomCampNVertexs=N_VERTEXS +NomCampLongitudArc=LONG_ARC +NomCampNodeIni=NODE_INI +NomCampNodeFi=NODE_FI diff --git a/autotest/ogr/data/miramon/Points/SimplePoints/SimplePointsFileT.rel b/autotest/ogr/data/miramon/Points/SimplePoints/SimplePointsFileT.rel index 4313888e6deb..69a72d07ba46 100644 --- a/autotest/ogr/data/miramon/Points/SimplePoints/SimplePointsFileT.rel +++ b/autotest/ogr/data/miramon/Points/SimplePoints/SimplePointsFileT.rel @@ -6,12 +6,15 @@ SubVersMetaDades=0 [TAULA_PRINCIPAL] IdGrafic=ID_GRAFIC +TipusRelacio=RELACIO_1_N_DICC [TAULA_PRINCIPAL:ID_GRAFIC] -descriptor=Identificador Gràfic intern visible=0 simbolitzable=0 -TractamentVariable=Ordinal +MostrarUnitats=0 +descriptor=Identificador Gràfic intern +descriptor_spa=Identificador Gráfico interno +descriptor_eng=Internal Graphic identifier [TAULA_PRINCIPAL:ATT1] descriptor=Atributte1 @@ -20,8 +23,8 @@ descriptor=Atributte1 descriptor=Atributte2 [METADADES] -language=cat -MDIdiom=cat +language=cat,spa,eng +MDIdiom=cat,spa,eng dateStamp=20230628 16344458+0200 characterSet=006 nOrganismes=1 @@ -34,7 +37,7 @@ PositionName=T OrganisationName=Students and educational institutions [IDENTIFICATION] -code= +code=68ddf845-79e8-4791-bf7a-5459eb951a04_SimplePointsFile codeSpace= DatasetTitle=Simple Points File diff --git a/autotest/ogr/ogr_miramon_vector.py b/autotest/ogr/ogr_miramon_vector.py index d83940c76549..98a3cad117e8 100644 --- a/autotest/ogr/ogr_miramon_vector.py +++ b/autotest/ogr/ogr_miramon_vector.py @@ -32,22 +32,21 @@ # import os # import pdb -# import gdaltest +import gdaltest + # import ogrtest -# import pytest +import pytest # from osgeo import gdal, ogr, osr from osgeo import gdal, ogr +pytestmark = pytest.mark.require_driver("MiraMonVector") + ############################################################################### # basic point test -def test_ogr_miramon_simple_point(): - - ds = gdal.OpenEx("data/miramon/Points/SimplePoints/SimplePointsFile.pnt") - - assert ds is not None, "Failed to get dataset" +def check_simple_point(ds): lyr = ds.GetLayer(0) assert lyr is not None, "Failed to get layer" @@ -83,17 +82,46 @@ def test_ogr_miramon_simple_point(): assert f.GetFieldAsString("ATT1") == "" assert f.GetFieldAsString("ATTRIBUTE_2") == "" - ds = None + +def test_ogr_miramon_read_simple_point(): + + ds = gdal.OpenEx("data/miramon/Points/SimplePoints/SimplePointsFile.pnt") + assert ds is not None, "Failed to get dataset" + + check_simple_point(ds) + + +def test_ogr_miramon_write_simple_pointV11(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.pnt") + gdal.VectorTranslate( + out_filename, + "data/miramon/Points/SimplePoints/SimplePointsFile.pnt", + format="MiraMonVector", + ) + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_simple_point(ds) + + +def test_ogr_miramon_write_simple_pointV20(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.pnt") + gdal.VectorTranslate( + out_filename, + "data/miramon/Points/SimplePoints/SimplePointsFile.pnt", + format="MiraMonVector", + options="-lco Version=V2.0", + ) + + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_simple_point(ds) ############################################################################### # basic linestring test -def test_ogr_miramon_simple_arc(): - - ds = gdal.OpenEx("data/miramon/Arcs/SimpleArcs/SimpleArcFile.arc") - assert ds is not None, "Failed to get dataset" +def check_simple_arc(ds): lyr = ds.GetLayer(0) assert lyr is not None, "Failed to get layer" @@ -110,7 +138,7 @@ def test_ogr_miramon_simple_arc(): ) assert f.GetField("ID_GRAFIC") == 0 assert f.GetField("N_VERTEXS") == 5 - assert f.GetField("LONG_ARC") == 1226.052755 + assert f.GetField("LONG_ARC") == pytest.approx(1226.052754666, abs=1e-5) assert f.GetField("NODE_INI") == 0 assert f.GetField("NODE_FI") == 1 assert f.GetFieldAsString("ATT1") == "A" @@ -125,7 +153,7 @@ def test_ogr_miramon_simple_arc(): ) assert f.GetField("ID_GRAFIC") == 1 assert f.GetField("N_VERTEXS") == 7 - assert f.GetField("LONG_ARC") == 1986.750568 + assert f.GetField("LONG_ARC") == pytest.approx(1986.750568, abs=1e-5) assert f.GetField("NODE_INI") == 2 assert f.GetField("NODE_FI") == 3 assert f.GetFieldAsString("ATT1") == "C" @@ -140,7 +168,7 @@ def test_ogr_miramon_simple_arc(): ) assert f.GetField("ID_GRAFIC") == 2 assert f.GetField("N_VERTEXS") == 2 - assert f.GetField("LONG_ARC") == 136.823147 + assert f.GetField("LONG_ARC") == pytest.approx(136.823147, abs=1e-5) assert f.GetField("NODE_INI") == 4 assert f.GetField("NODE_FI") == 5 assert f.GetFieldAsString("ATT1") == "C" @@ -155,25 +183,52 @@ def test_ogr_miramon_simple_arc(): ) assert f.GetField("ID_GRAFIC") == 3 assert f.GetField("N_VERTEXS") == 6 - assert f.GetField("LONG_ARC") == 396.238966 + assert f.GetField("LONG_ARC") == pytest.approx(396.238966, abs=1e-5) assert f.GetField("NODE_INI") == 6 assert f.GetField("NODE_FI") == 7 assert f.GetFieldAsString("ATT1") == "E" assert f.GetFieldAsString("ATT2") == "F" - ds = None +def test_ogr_miramon_read_simple_arc(): -############################################################################### -# basic polygon test + ds = gdal.OpenEx("data/miramon/Arcs/SimpleArcs/SimpleArcFile.arc") + assert ds is not None, "Failed to get dataset" + check_simple_arc(ds) -def test_ogr_miramon_simple_polygon(): +def test_ogr_miramon_write_simple_arcV11(tmp_vsimem): - ds = gdal.OpenEx( - "data/miramon/Polygons/SimplePolygons/SimplePolFile.pol", gdal.OF_VECTOR + out_filename = str(tmp_vsimem / "out.arc") + gdal.VectorTranslate( + out_filename, + "data/miramon/Arcs/SimpleArcs/SimpleArcFile.arc", + format="MiraMonVector", ) - assert ds is not None, "Failed to get dataset" + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_simple_arc(ds) + del ds + + +def test_ogr_miramon_write_simple_arcV20(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.arc") + gdal.VectorTranslate( + out_filename, + "data/miramon/Arcs/SimpleArcs/SimpleArcFile.arc", + format="MiraMonVector", + options="-lco Version=V2.0", + ) + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_simple_arc(ds) + del ds + + +############################################################################### +# basic polygon test + + +def check_simple_polygon(ds): lyr = ds.GetLayer(0) @@ -182,17 +237,18 @@ def test_ogr_miramon_simple_polygon(): assert lyr.GetFeatureCount() == 3 assert lyr.GetGeomType() == ogr.wkbPolygon + # going to the first polygon f = lyr.GetNextFeature() assert f is not None, "Failed to get feature" - assert f.GetFID() == 1 + assert f.GetFID() == 0 assert ( f.GetGeometryRef().ExportToWkt() == "POLYGON ((335.318744053333 769.731684110321,552.525214081877 856.814462416696,775.737392959137 707.672692673594,648.616555661325 493.469077069408,386.367269267414 498.473834443337,335.318744053333 769.731684110321))" ) assert f.GetField("ID_GRAFIC") == 1 assert f.GetField("N_VERTEXS") == 6 - assert f.GetField("PERIMETRE") == 1289.866489 - assert f.GetField("AREA") == 112471.221989 + assert f.GetField("PERIMETRE") == pytest.approx(1289.866489495, abs=1e-5) + assert f.GetField("AREA") == pytest.approx(112471.221989, abs=1e-5) assert f.GetField("N_ARCS") == 1 assert f.GetField("N_POLIG") == 1 assert f.GetFieldAsString("ATT1") == "A" @@ -200,15 +256,15 @@ def test_ogr_miramon_simple_polygon(): f = lyr.GetNextFeature() assert f is not None, "Failed to get feature" - assert f.GetFID() == 2 + assert f.GetFID() == 1 assert ( f.GetGeometryRef().ExportToWkt() == "POLYGON ((1068.01522359662 849.807802093194,1160.10275927693 795.756422454755,1224.16365366323 682.648905803946,1156.09895337779 525.499524262557,962.915318744103 489.465271170264,830.789724072362 617.587059942862,924.879162702239 740.704091341529,1068.01522359662 849.807802093194))" ) assert f.GetField("ID_GRAFIC") == 2 assert f.GetField("N_VERTEXS") == 8 - assert f.GetField("PERIMETRE") == 1123.514024 - assert f.GetField("AREA") == 88563.792204 + assert f.GetField("PERIMETRE") == pytest.approx(1123.514024, abs=1e-5) + assert f.GetField("AREA") == pytest.approx(88563.792204, abs=1e-5) assert f.GetField("N_ARCS") == 1 assert f.GetField("N_POLIG") == 1 assert f.GetFieldAsString("ATT1") == "C" @@ -216,21 +272,53 @@ def test_ogr_miramon_simple_polygon(): f = lyr.GetNextFeature() assert f is not None, "Failed to get feature" - assert f.GetFID() == 3 + assert f.GetFID() == 2 assert ( f.GetGeometryRef().ExportToWkt() == "POLYGON ((636.605137963894 390.371075166458,580.551855375883 575.547098001853,723.687916270269 594.565176022785,796.757373929641 475.451950523261,744.707897240773 396.376784015173,636.605137963894 390.371075166458))" ) assert f.GetField("ID_GRAFIC") == 3 assert f.GetField("N_VERTEXS") == 6 - assert f.GetField("PERIMETRE") == 680.544697 - assert f.GetField("AREA") == 30550.052343 + assert f.GetField("PERIMETRE") == pytest.approx(680.544697, abs=1e-5) + assert f.GetField("AREA") == pytest.approx(30550.052343, abs=1e-5) assert f.GetField("N_ARCS") == 1 assert f.GetField("N_POLIG") == 1 assert f.GetFieldAsString("ATT1") == "C" assert f.GetFieldAsString("ATT2") == "D" - ds = None + +def test_ogr_miramon_read_simple_polygon(): + + ds = gdal.OpenEx( + "data/miramon/Polygons/SimplePolygons/SimplePolFile.pol", gdal.OF_VECTOR + ) + assert ds is not None, "Failed to get dataset" + check_simple_polygon(ds) + + +def test_ogr_miramon_write_simple_polygonV11(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.pol") + gdal.VectorTranslate( + out_filename, + "data/miramon/Polygons/SimplePolygons/SimplePolFile.pol", + format="MiraMonVector", + ) + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_simple_polygon(ds) + + +def test_ogr_miramon_write_simple_polygonV20(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.pol") + gdal.VectorTranslate( + out_filename, + "data/miramon/Polygons/SimplePolygons/SimplePolFile.pol", + format="MiraMonVector", + options="-lco Version=V2.0", + ) + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_simple_polygon(ds) ############################################################################### @@ -282,6 +370,7 @@ def test_ogr_miramon_empty_pol_layers(): assert lyr is not None, "Failed to get layer" + # The layer has no features assert lyr.GetFeatureCount() == 0 f = lyr.GetNextFeature() @@ -294,10 +383,7 @@ def test_ogr_miramon_empty_pol_layers(): # testing 3d part -def test_ogr_miramon_3d_point(): - - ds = gdal.OpenEx("data/miramon/Points/3dpoints/Some3dPoints.pnt", gdal.OF_VECTOR) - assert ds is not None, "Failed to get dataset" +def check_3d_point(ds): lyr = ds.GetLayer(0) @@ -313,6 +399,8 @@ def test_ogr_miramon_3d_point(): assert f.GetGeometryRef().ExportToWkt() == "POINT (440551.66 4635315.3 619.96)" g = f.GetGeometryRef() + assert g is not None, "Failed to get geometry" + assert g.GetCoordinateDimension() == 3 assert g.GetZ() == 619.96 f = lyr.GetFeature(30) @@ -321,13 +409,27 @@ def test_ogr_miramon_3d_point(): assert g is not None, "Failed to get geometry" assert g.GetZ() == 619.77 - ds = None - -def test_ogr_miramon_3d_arc(): +def test_ogr_miramon_read_3d_point(tmp_vsimem): - ds = gdal.OpenEx("data/miramon/Arcs/3dArcs/linies_3d_WGS84.arc", gdal.OF_VECTOR) + ds = gdal.OpenEx("data/miramon/Points/3dpoints/Some3dPoints.pnt", gdal.OF_VECTOR) assert ds is not None, "Failed to get dataset" + check_3d_point(ds) + + +def test_ogr_miramon_write_3d_point(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.pnt") + gdal.VectorTranslate( + out_filename, + "data/miramon/Points/3dpoints/Some3dPoints.pnt", + format="MiraMonVector", + ) + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_3d_point(ds) + + +def check_3d_arc(ds): lyr = ds.GetLayer(0) @@ -340,6 +442,7 @@ def test_ogr_miramon_3d_arc(): assert f is not None, "Failed to get feature" g = f.GetGeometryRef() assert g is not None, "Failed to get geometry" + assert g.GetCoordinateDimension() == 3 assert g.GetPointCount() == 4 p = g.GetPoint(0) assert p[2] == 595.1063842773438 @@ -354,6 +457,7 @@ def test_ogr_miramon_3d_arc(): assert f is not None, "Failed to get feature" g = f.GetGeometryRef() assert g is not None, "Failed to get geometry" + assert g.GetCoordinateDimension() == 3 assert g.GetPointCount() == 2 p = g.GetPoint(0) assert p[2] == 233.82064819335938 @@ -363,10 +467,27 @@ def test_ogr_miramon_3d_arc(): ds = None -def test_ogr_miramon_3d_pol(): +def test_ogr_miramon_read_3d_arc(tmp_vsimem): - ds = gdal.OpenEx("data/miramon/Polygons/3dPolygons/tin_3d.pol", gdal.OF_VECTOR) + ds = gdal.OpenEx("data/miramon/Arcs/3dArcs/linies_3d_WGS84.arc", gdal.OF_VECTOR) assert ds is not None, "Failed to get dataset" + check_3d_arc(ds) + + +def test_ogr_miramon_write_3d_arc(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.arc") + gdal.VectorTranslate( + out_filename, + "data/miramon/Arcs/3dArcs/linies_3d_WGS84.arc", + format="MiraMonVector", + ) + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_3d_arc(ds) + del ds + + +def check_3d_pol(ds): lyr = ds.GetLayer(0) @@ -375,10 +496,11 @@ def test_ogr_miramon_3d_pol(): assert lyr.GetFeatureCount() == 5 assert lyr.GetGeomType() == ogr.wkbPolygon25D - f = lyr.GetFeature(1) + f = lyr.GetFeature(0) assert f is not None, "Failed to get feature" g = f.GetGeometryRef() assert g is not None, "Failed to get geometry" + assert g.GetCoordinateDimension() == 3 r = g.GetGeometryRef(0) assert r is not None, "Failed to get geometry" assert r.GetPointCount() == 4 @@ -391,10 +513,11 @@ def test_ogr_miramon_3d_pol(): p = r.GetPoint(3) assert p[2] == 11.223576545715332 - f = lyr.GetFeature(5) + f = lyr.GetFeature(4) assert f is not None, "Failed to get feature" g = f.GetGeometryRef() assert g is not None, "Failed to get geometry" + assert g.GetCoordinateDimension() == 3 r = g.GetGeometryRef(0) assert r is not None, "Failed to get geometry" assert r.GetPointCount() == 4 @@ -407,4 +530,148 @@ def test_ogr_miramon_3d_pol(): p = r.GetPoint(3) assert p[2] == 18.207277297973633 - ds = None + +def test_ogr_miramon_read_3d_pol(): + + ds = gdal.OpenEx("data/miramon/Polygons/3dPolygons/tin_3d.pol", gdal.OF_VECTOR) + assert ds is not None, "Failed to get dataset" + check_3d_pol(ds) + + +def test_ogr_miramon_write_3d_pol(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.pol") + gdal.VectorTranslate( + out_filename, + "data/miramon/Polygons/3dPolygons/tin_3d.pol", + format="MiraMonVector", + ) + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + check_3d_pol(ds) + del ds + + +############################################################################### +# ogrsf test in some files + + +@pytest.mark.parametrize( + "filename", + [ + "Points/3dpoints/Some3dPoints.pnt", + "Points/SimplePoints/SimplePointsFile.pnt", + "Points/EmptyPoints/Empty_PNT.pnt", + "Arcs/SimpleArcs/SimpleArcFile.arc", + "Arcs/EmptyArcs/Empty_ARC.arc", + "Arcs/3dArcs/linies_3d_WGS84.arc", + "Polygons/SimplePolygons/SimplePolFile.pol", + "Polygons/EmptyPolygons/Empty_POL.pol", + "Polygons/3dPolygons/tin_3d.pol", + ], +) +def test_ogr_miramon_test_ogrsf(filename): + + import test_cli_utilities + + if test_cli_utilities.get_test_ogrsf_path() is None: + pytest.skip("test_ogrsf not available") + + ret = gdaltest.runexternal( + test_cli_utilities.get_test_ogrsf_path() + " -ro data/miramon/" + filename + ) + + assert "INFO" in ret + assert "ERROR" not in ret + + +############################################################################### +# -lco tests: CreationLanguage + + +@pytest.mark.parametrize( + "Language, expected_description", + [ + ("CAT", "Identificador Gràfic intern"), + ("SPA", "Identificador Gráfico interno"), + ("ENG", "Internal Graphic identifier"), + ], +) +def test_ogr_miramon_CreationLanguage(tmp_vsimem, Language, expected_description): + + out_filename = str(tmp_vsimem / "out.pnt") + gdal.VectorTranslate( + out_filename, + "data/miramon/Points/SimplePoints/SimplePointsFile.pnt", + format="MiraMonVector", + options="-lco CreationLanguage=" + Language, + ) + + ds = gdal.OpenEx(out_filename, gdal.OF_VECTOR) + lyr = ds.GetLayer(0) + assert lyr is not None, "Failed to get layer" + + layer_def = lyr.GetLayerDefn() + field_index = layer_def.GetFieldIndex("ID_GRAFIC") + assert field_index >= 0 + + field_def = layer_def.GetFieldDefn(field_index) + field_description = field_def.GetAlternativeNameRef() + assert field_description == expected_description + + +############################################################################### +# -lco tests: CreationLanguage + + +@pytest.mark.parametrize( + "Language,expected_description", + [ + ("CAT", "Identificador Gràfic intern"), + ("SPA", "Identificador Gráfico interno"), + ("ENG", "Internal Graphic identifier"), + ], +) +def test_ogr_miramon_OpenLanguagePoint(Language, expected_description): + + ds = gdal.OpenEx( + "data/miramon/Points/SimplePoints/SimplePointsFile.pnt", + gdal.OF_VECTOR, + open_options=["OpenLanguage=" + Language], + ) + lyr = ds.GetLayer(0) + assert lyr is not None, "Failed to get layer" + + layer_def = lyr.GetLayerDefn() + field_index = layer_def.GetFieldIndex("ID_GRAFIC") + assert field_index >= 0 + + field_def = layer_def.GetFieldDefn(field_index) + field_description = field_def.GetAlternativeNameRef() + assert field_description == expected_description + + +@pytest.mark.parametrize( + "Language,expected_description", + [ + ("CAT", "Node inicial"), + ("SPA", "Nodo inicial"), + ("ENG", "Initial node"), + ], +) +def test_ogr_miramon_OpenLanguageArc(Language, expected_description): + + ds = gdal.OpenEx( + "data/miramon/Arcs/SimpleArcs/SimpleArcFile.arc", + gdal.OF_VECTOR, + open_options=["OpenLanguage=" + Language], + ) + lyr = ds.GetLayer(0) + assert lyr is not None, "Failed to get layer" + + layer_def = lyr.GetLayerDefn() + field_index = layer_def.GetFieldIndex("NODE_INI") + assert field_index >= 0 + + field_def = layer_def.GetFieldDefn(field_index) + field_description = field_def.GetAlternativeNameRef() + assert field_description == expected_description diff --git a/doc/source/drivers/vector/miramon.rst b/doc/source/drivers/vector/miramon.rst index 1e6eb265634b..79ddaebe8910 100644 --- a/doc/source/drivers/vector/miramon.rst +++ b/doc/source/drivers/vector/miramon.rst @@ -8,27 +8,81 @@ MiraMon Vector .. built_in_by_default:: This driver is capable of translating (reading and writing) structured vectors -of point, arc (*linestrings*), and polygon types from MiraMon vector format. Structured vectors is -the binary format of MiraMon for vector layer data, linked to one or more database tables, -with or without topology and with reach metadata. More information about the structured MiraMon -vector format is available `on the public specification `__. +of point, arc (*linestrings*), and polygon types from MiraMon vector format. + +In MiraMon the concepts of OGRMultiPoints and OGRMultiLineStrings are not supported, +but the driver translates a multipoint into N points and a multistring into N arcs. +So, when reading a MiraMon file of type *.pol*, the corresponding +layer will be reported as of type wkbPolygon, but depending on the +number of parts of each geometry, the actual type of the geometry for +each feature can be either OGRPolygon or OGRMultiPolygon. + +The reading driver verifies if multipart polygons adhere to the +specification (that is to say, the vertices of outer rings should be +oriented clockwise on the X/Y plane, and those of inner rings +counterclockwise). Otherwise, the driver corrects the orientation +(in the original format this specification is not the case as polygon +files are based on topological arc files, where the order of the vertices +may be relevant). + +Measures (M coordinate) are not supported. +Symbolization is neither read nor generated by this driver. + +A `look-up-table of MiraMon `__ and +`EPSG `__ Spatial Reference Systems allows matching +identifiers in both systems. + +If a layer contains an old *.rel* format file (used some decades ago), +a warning message will appear explaining how to convert it into a modern *.rel 4* file. + +Driver capabilities +------------------- + +.. supports_create:: + +.. supports_georeferencing:: + +.. supports_virtualio:: + +Overview of MiraMon format +-------------------------- + +In MiraMon format structured vectors is the binary format of MiraMon for vector layer data, linked to +one or more database tables, with or without topology and with rich metadata. +More information about the structured MiraMon vector format is available `on the public +specification `__. It is important to keep in mind that a MiraMon vector layer is composed by several files as follows: -Previous note: *FileName* is, in the following explanations, the first part of the name +To operate with a points layer, you must provide the name with the extension .pnt +(the T.dbf and T.rel files must accompany the .pnt). + +To operate with a stringlines layer, you must provide the name with the extension .arc +(the A.dbf and A.rel, .nod, N.dbf, and N.rel files must accompany the .arc). + +To operate with a polygons layer, you must provide the name with the extension .pol +(the P.dbf, P.rel, A.dbf and A.rel, .nod, N.dbf, and N.rel files must accompany the .pol). + +By providing only the main file name, the driver will access the rest to search for the +necessary information. In the creation of MiraMon layers, you only need to provide the name +of the main file (with or without extension), and the driver will create the rest of the files. + +The following outlines the information contained within each type of file with the mentioned extensions: + +Preliminary note: *FileName* is, in the following explanations, the first part of the name of the layer file. - **Point layers**: These layers contain *point* type features which are described by a single coordinate (x,y) or (x, y, z). Each layer is composed by 3 files: - - *FileName.pnt* file: Contains the graphic database with the coordinates that define the + - *FileName.pnt* file: Contains the geographic database with the coordinates that define the point vector features. - *FileNameT.dbf* file (note the 'T' before the '.'): Contains the main table of the database in dBASE (DBF) format, or in `extended DBF format `__, if necessary. It contains the information (usually alphanumeric, but also file or web links, etc) of every feature. The Feature Identifier (FID) field is a field called *ID_GRAFIC* and relates - every graphical feature to one or more records in the main table. + every geographical feature to one or more records in the main table. - *FileNameT.rel* file (note the 'T' before the '.'): Contains the layer metadata, the relational structure of the database (links between the main table and other @@ -41,14 +95,14 @@ of the layer file. described by a series of segments, each one defined by coordinates (x, y) or (x, y, z). Both extreme vertices of each *linestring* are called nodes. Each layer is composed by 6 files: - - *FileName.arc* file: Contains the graphic database with the coordinates that define the + - *FileName.arc* file: Contains the geographic database with the coordinates that define the linestring (arc) vector features. - *FileNameA.dbf* file (note the 'A' before the '.'): Contains the main table of the database in dBASE (DBF) format, or in `extended DBF format `__, if necessary. It contains the information (usually alphanumeric, but also file or web links, etc) of every feature. The Feature Identifier (FID) field is a field called *ID_GRAFIC* and relates - every graphical feature to one or more records in the main table. + every geographical feature to one or more records in the main table. - *FileNameA.rel* file (note the 'A' before the '.'): Contains the layer metadata, the relational structure of the database (links between the main table and other @@ -57,7 +111,7 @@ of the layer file. only some aspects are documented: the spatial reference system, the language of the metadata (English), the extension and a description of the fields. - - *FileName.nod* file: Contains the graphic database with information about the + - *FileName.nod* file: Contains the geographic database with information about the linestring needed to define each node. It is necessary in the MiraMon vector format but not read by the GDAL MiraMon vector driver because nodes contain topological information that is not transferred to other formats. @@ -81,14 +135,14 @@ of the layer file. in this case, it is termed a group (*multipolygon*). Each layer is composed by 9 files: - - *FileName.pol* file: Contains the graphic database with information about the linestring + - *FileName.pol* file: Contains the geographic database with information about the linestring vector features needed to define the polygonal (or multipolygonal) vector features. - *FileNameP.dbf* file (note the 'P' before the '.'): Contains the main table of the database in dBASE (DBF) format, or in `extended DBF format `__, if necessary. It contains the information (usually alphanumeric, but also file or web links, etc) of every feature. The Feature Identifier (FID) field is a field called *ID_GRAFIC* and relates - every graphical feature to one or more records in the main table. + every geographical feature to one or more records in the main table. - *FileNameP.rel* file (note the 'P' before the '.'): Contains the layer metadata, the relational structure of the database (links between the main table and other @@ -97,7 +151,7 @@ of the layer file. only some aspects are documented: the spatial reference system, the language of the metadata (English), the extension and a description of the fields. - - *FileName.arc* file: Contains the graphic database with the coordinates that define the + - *FileName.arc* file: Contains the geographic database with the coordinates that define the arc vector features. The polygons within the polygon file reference the arcs in this file by their index. - *FileNameA.dbf* file (note the 'A' before the '.'): Contains the main table of the database @@ -110,7 +164,7 @@ of the layer file. the relations of the database and the symbolization description. It is necessary in MiraMon but not read directly by the GDAL MiraMon vector driver. - - *FileName.nod* file: Contains the graphic database with information about the + - *FileName.nod* file: Contains the geographic database with information about the linestring needed to define each node. It is necessary in the MiraMon vector format but not read by the GDAL MiraMon vector driver because nodes contain topological information that is not transferred to other formats. @@ -125,39 +179,28 @@ of the layer file. the relations of the database and the symbolization description. It is necessary in MiraMon but not read directly by the GDAL MiraMon vector driver. -In MiraMon the concepts of OGRMultiPoints and OGRMultiLineStrings are not supported, -but the driver translates a multipoint into N points and a multistring into N arcs. -So, when reading a MiraMon file of type *.pol*, the corresponding -layer will be reported as of type wkbPolygon, but depending on the -number of parts of each geometry, the actual type of the geometry for -each feature can be either OGRPolygon or OGRMultiPolygon. - -The reading driver verifies if multipart polygons adhere to the -specification (that is to say, the vertices of outer rings should be -oriented clockwise on the X/Y plane, and those of inner rings -counterclockwise). Otherwise, the driver corrects the orientation -(in the original format this specification is not the case as polygon -files are based on topological arc files, where the order of the vertices -may be relevant). - -Measures (M coordinate) are not supported. -Symbolization is neither read nor generated by this driver. - -A `look-up-table of MiraMon `__ and -`EPSG `__ Spatial Reference Systems allows matching -identifiers in both systems. - -If a layer contains an old *.rel* format file (used some decades ago), -a warning message will appear explaining how to convert it into a modern *.rel 4* file. - -Driver capabilities -------------------- - -.. supports_create:: - -.. supports_georeferencing:: - -.. supports_virtualio:: +Reserved field names +-------------------- +As mentioned a few lines above, all DBF files have a field named ID_GRAFIC. In addition to this field, +there are other fields reserved for the case of stringlines and polygons. + +For stringlines: + - N_VERTEXS: a numeric field containing the number of vertices of the stringline. + - LONG_ARC: a numeric field containing the length of the stringline. + - NODE_INI: a numeric field containing the identifier of the node (from the .nod node file) where the stringline starts. + - NODE_FI: a numeric field containing the identifier of the node (from the .nod node file) where the stringline ends. + +For polygons: + - N_VERTEXS: a numeric field containing the number of vertices of the polygon. + - PERIMETRE: a numeric field containing the perimeter of the polygon, understanding that if it has multiple parts, + it is the sum of all parts. + - AREA: a numeric field containing the area of the polygon. + - N_ARCS: a numeric field containing the number of stringlines forming a polygon, understanding that in MiraMon, a polygon + can be formed by several stringlines. + - N_POLIG: a numeric field containing the number of rings forming a polygon. + +In the creation of a layer in MiraMon format, if any of the fields in the original layer have a name +that matches the reserved ones, it will be slightly modified by adding a 2 at the end (or a 3 if that one is also occupied). Encoding -------- @@ -192,9 +235,6 @@ folder or a set of files with the appropriate extension (*.pnt*, etc): - If it the output is a **file** with extension all the translated layers in the origin dataset will be created with the specified name. Use this option only when you know that there is only one layer with one feature type in the origin dataset. -When translating from a MiraMon vector format, the MiraMon vector driver input needs a file with one of the -described extensions: *.pnt*, *.arc* or *.pol*. The extension *.nod* is not valid for translation. - The attributes of the MiraMon feature are stored in an associated *.dbf*. If a classical DBF IV table could not be used (too many fields or records, large text fields, etc) a file type called extended DBF is used. @@ -207,6 +247,20 @@ is not installed on the computer, the free and standalone MiraD application can be downloaded from `this page `__ to open them. +Connection string +----------------- + +The MiraMon driver accepts three types of sources of data: + +When translating from a MiraMon vector format, the MiraMon vector driver input needs a file with one of the +described extensions: + +- *.pnt* for *points*. +- *.arc* for *stringlines*. +- *.pol* for *polygons* (or *multipolygons*). + +The extension *.nod* is not valid for translation. Take in consideration all auxiliary files described above. + Field sizes ----------- @@ -242,20 +296,7 @@ The following open options are available. user can select which one wants to keep: *iMultiRecord=1* for first, *iMultiRecord=2* for second, etc and *iMultiRecord=last* for the last element of the list. *iMultiRecord=JSON* option converts the list in a single value in JSON format. - If not specified, all elements of the list will be translated by default. - -- .. oo:: OpenMemoryRatio - :choices: 0.5, 1, 2, ... - :default: 1 - - It is a ratio used to enhance certain aspects of memory. - In some memory allocations a block of either 256 or 512 bytes is used. - This parameter can be adjusted to achieve - nMemoryRatio*256 or nMemoryRatio*512. - By way of example, please use nMemoryRatio=2 in powerful computers and - nMemoryRatio=0.5 in less powerful computers. - By increasing this parameter, more memory will be required, - but there will be fewer read/write operations to the (network and) disk. + If not specified, all elements of the list will be translated by default as a OGR list field type. - .. oo:: OpenLanguage :choices: ENG, CAT, SPA @@ -276,8 +317,7 @@ Layer creation options - .. lco:: Version :choices: V1.1, V2.0, last_version :default: V1.1 - :since: 3.9 - + Version of the file. Version 1.1 is limited to an unsigned 32-bit integer for FID, for internal offsets and for the number of entities the layer can handle. @@ -289,8 +329,7 @@ Layer creation options - .. lco:: DBFEncoding :choices: UTF8, ANSI :default: ANSI - :since: 3.9 - + Encoding of the *.dbf* files. The MiraMon vector driver can write *.dbf* files in UTF-8 or ANSI charsets. @@ -298,18 +337,6 @@ Layer creation options `MiraD application `__, so it is recommended to use ANSI instead, if there are no coding problems. -- .. oo:: CreationMemoryRatio - :choices: 0.5, 1, 2, ... - :default: 1 - - It is a ratio used to enhance certain aspects of memory. - In some memory allocations a block of 256 bytes is used. - This parameter can be adjusted to achieve nMemoryRatio*256. - By way of example, please use nMemoryRatio=2 in powerful computers and - nMemoryRatio=0.5 in less powerful computers. - By increasing this parameter, more memory will be required, - but there will be fewer read/write operations to the (network and) disk. - - .. oo:: CreationLanguage :choices: ENG, CAT, SPA :default: ENG diff --git a/fuzzers/CMakeLists.txt b/fuzzers/CMakeLists.txt index 47a0c5bf144c..5cf1b6dc73bf 100644 --- a/fuzzers/CMakeLists.txt +++ b/fuzzers/CMakeLists.txt @@ -90,6 +90,7 @@ build_ogr_specialized_fuzzer(avcbin RegisterOGRAVCBin "/vsimem/test.tar" "/vsita build_ogr_specialized_fuzzer(gml RegisterOGRGML "/vsimem/test.tar" "/vsitar//vsimem/test.tar/test.gml") build_fuzzer(NAME cad_fuzzer SOURCES ogr_fuzzer.cpp DEFINITIONS -DREGISTER_FUNC=RegisterOGRCAD) +build_fuzzer(NAME ogr_miramon_fuzzer SOURCES ogr_fuzzer.cpp DEFINITIONS -DREGISTER_FUNC=RegisterOGRMiraMon -DMEM_FILENAME="/vsimem/test.tar" -DFOR_OGR_MIRAMON) function (build_gdal_specialized_fuzzer _format _registerFunc _memfile _gdalfile) build_fuzzer( diff --git a/fuzzers/build_google_oss_fuzzers.sh b/fuzzers/build_google_oss_fuzzers.sh index 6095517a0120..ad0b2c2a863c 100755 --- a/fuzzers/build_google_oss_fuzzers.sh +++ b/fuzzers/build_google_oss_fuzzers.sh @@ -93,6 +93,7 @@ build_ogr_specialized_fuzzer avcbin RegisterOGRAVCBin "/vsimem/test.tar" "/vsita build_ogr_specialized_fuzzer gml RegisterOGRGML "/vsimem/test.tar" "/vsitar//vsimem/test.tar/test.gml" build_ogr_specialized_fuzzer gmlas RegisterOGRGMLAS "/vsimem/test.tar" "GMLAS:/vsitar//vsimem/test.tar/test.gml" build_ogr_specialized_fuzzer fgb RegisterOGRFlatGeobuf "/vsimem/test.fgb" "/vsimem/test.fgb" +build_fuzzer ogr_miramon_fuzzer $(dirname $0)/ogr_fuzzer.cpp -DREGISTER_FUNC=RegisterOGRMiraMon -DMEM_FILENAME="\"/vsimem/test.tar\"" -DFOR_OGR_MIRAMON build_fuzzer cad_fuzzer $(dirname $0)/ogr_fuzzer.cpp -DREGISTER_FUNC=RegisterOGRCAD formats="GTiff HFA" diff --git a/fuzzers/build_seed_corpus.sh b/fuzzers/build_seed_corpus.sh index f158e5bf8fe5..291fc011250d 100755 --- a/fuzzers/build_seed_corpus.sh +++ b/fuzzers/build_seed_corpus.sh @@ -592,6 +592,26 @@ rm -f $OUT/lvbag_fuzzer_seed_corpus.zip zip -r $OUT/lvbag_fuzzer_seed_corpus.zip ./*.xml >/dev/null cd $OLDPWD +echo "Building ogr_miramon_fuzzer_seed_corpus.zip" +rm -f $OUT/ogr_miramon_fuzzer_seed_corpus.zip +CUR_DIR=$PWD +cd $(dirname $0)/../autotest/ogr/data/miramon +for subdir in *; do + (cd $subdir + for subdir2 in *; do + (cd $subdir2 + printf "FUZZER_FRIENDLY_ARCHIVE\\n" > $CUR_DIR/ogr_miramon_${subdir}_${subdir2}.tar + for file in *; do + printf "***NEWFILE***:%s\\n" "$file" >> $CUR_DIR/ogr_miramon_${subdir}_${subdir2}.tar + cat $file >> $CUR_DIR/ogr_miramon_${subdir}_${subdir2}.tar + done + ) + done + ) +done +cd $CUR_DIR +zip -r $OUT/ogr_miramon_fuzzer_seed_corpus.zip ogr_miramon_*.tar >/dev/null +rm ogr_miramon_*.tar echo "Copying data to $OUT" cp $(dirname $0)/../data/* $OUT diff --git a/fuzzers/ogr_fuzzer.cpp b/fuzzers/ogr_fuzzer.cpp index 75286078a614..805473ce236e 100644 --- a/fuzzers/ogr_fuzzer.cpp +++ b/fuzzers/ogr_fuzzer.cpp @@ -107,6 +107,32 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) CPLPushErrorHandler(CPLQuietErrorHandler); #ifdef USE_FILESYSTEM OGRDataSourceH hDS = OGROpen(szTempFilename, FALSE, nullptr); +#elif defined(FOR_OGR_MIRAMON) + std::string osVsitarPrefix("/vsitar/"); + char **papszFiles = + VSIReadDir(std::string(osVsitarPrefix).append(MEM_FILENAME).c_str()); + std::string osFileInTar; + for (int i = 0; papszFiles && papszFiles[i]; ++i) + { + if (EQUAL(CPLGetExtension(papszFiles[i]), "pol") || + EQUAL(CPLGetExtension(papszFiles[i]), "arc") || + EQUAL(CPLGetExtension(papszFiles[i]), "pnt")) + { + osFileInTar = papszFiles[i]; + break; + } + } + CSLDestroy(papszFiles); + OGRDataSourceH hDS = nullptr; + if (!osFileInTar.empty()) + { + hDS = OGROpen(std::string(osVsitarPrefix) + .append(MEM_FILENAME) + .append("/") + .append(osFileInTar) + .c_str(), + FALSE, nullptr); + } #else OGRDataSourceH hDS = OGROpen(GDAL_FILENAME, FALSE, nullptr); #endif diff --git a/ogr/ogrsf_frmts/CMakeLists.txt b/ogr/ogrsf_frmts/CMakeLists.txt index cd608d1f5348..f11285935dcb 100644 --- a/ogr/ogrsf_frmts/CMakeLists.txt +++ b/ogr/ogrsf_frmts/CMakeLists.txt @@ -47,7 +47,9 @@ ogr_optional_driver(vdv "VDV-451/VDV-452/INTREST Data Format") ogr_optional_driver(flatgeobuf FlatGeobuf) ogr_optional_driver(mapml MapML) ogr_optional_driver(jsonfg JSONFG) -ogr_optional_driver(miramon "MiraMonVector") +if( NOT WORDS_BIGENDIAN ) + ogr_optional_driver(miramon "MiraMonVector") +endif() # ###################################################################################################################### # diff --git a/ogr/ogrsf_frmts/miramon/CMakeLists.txt b/ogr/ogrsf_frmts/miramon/CMakeLists.txt index 6f7bf9a9e396..8eccd4e46b07 100644 --- a/ogr/ogrsf_frmts/miramon/CMakeLists.txt +++ b/ogr/ogrsf_frmts/miramon/CMakeLists.txt @@ -1,7 +1,7 @@ add_gdal_driver( TARGET ogr_MiraMon SOURCES ogrmiramondatasource.cpp ogrmiramondriver.cpp ogrmiramonlayer.cpp mm_wrlayr.c mm_gdal_functions.c mm_rdlayr.c - BUILTIN) + PLUGIN_CAPABLE) gdal_standard_includes(ogr_MiraMon) target_include_directories(ogr_MiraMon PRIVATE $) diff --git a/ogr/ogrsf_frmts/miramon/mm_constants.h b/ogr/ogrsf_frmts/miramon/mm_constants.h index bb6495eb73b1..dbef6343ccd4 100644 --- a/ogr/ogrsf_frmts/miramon/mm_constants.h +++ b/ogr/ogrsf_frmts/miramon/mm_constants.h @@ -42,7 +42,7 @@ CPL_C_START // Necessary for compiling C in GDAL project #define MM_BOOLEAN char #define MM_HANDLE void * -#define MM_MESSAGE_LENGHT 512 +#define MM_MESSAGE_LENGTH 512 #define MM_MAX_BYTES_FIELD_DESC 360 #define MM_MAX_BYTES_IN_A_FIELD_EXT (UINT32_MAX - 1) #define MM_MAX_LON_FIELD_NAME_DBF 129 @@ -50,7 +50,9 @@ CPL_C_START // Necessary for compiling C in GDAL project #define MM_MAX_LON_UNITATS 66 #define MM_MAX_LON_UNITATS_CAMP MM_MAX_LON_UNITATS -// Vora fi gir in MiraMon +// Determines if an arc is external, the last one in a ring or +// if it has to be inverted to be consistent with other arcs +// in the ring. #define MM_POL_EXTERIOR_SIDE 0x01 #define MM_POL_END_RING 0x02 #define MM_POL_REVERSE_ARC 0x04 @@ -77,8 +79,8 @@ CPL_C_START // Necessary for compiling C in GDAL project #define MM_MAX_ID_SNY 41 #ifndef GDAL_COMPILATION - typedef unsigned long int uint32_t; -typedef long int int32_t; + typedef unsigned int uint32_t; +typedef int int32_t; #endif // Extended DBF @@ -163,7 +165,7 @@ typedef unsigned char MM_BYTE; #define MM_APLICAR_NOU_N_DECIMALS 1 #define MM_NOMES_DOCUMENTAR_NOU_N_DECIMALS 2 #define MM_PREGUNTA_SI_APLICAR_NOU_N_DECIM 3 -#define MM_CARACTERS_DOUBLE 40 +#define MM_CHARACTERS_DOUBLE 40 #ifdef GDAL_COMPILATION CPL_C_END // Necessary for compiling in GDAL project diff --git a/ogr/ogrsf_frmts/miramon/mm_gdal_constants.h b/ogr/ogrsf_frmts/miramon/mm_gdal_constants.h index 16104f7ebd24..f42878f7d088 100644 --- a/ogr/ogrsf_frmts/miramon/mm_gdal_constants.h +++ b/ogr/ogrsf_frmts/miramon/mm_gdal_constants.h @@ -48,10 +48,11 @@ typedef GUInt32 MM_EXT_DBF_N_FIELDS; //(TIPUS_NUMERADOR_CAMP in MiraMon internal code) #define MM_MAX_EXT_DBF_N_FIELDS_TYPE UINT32_MAX -#define MM_BYTES_PER_FIELD_TYPE_DBF \ - GUInt32 // In MiraMon code: MM_TIPUS_BYTES_PER_CAMP_DBF -#define MM_ACUMULATED_BYTES_TYPE_DBF \ - GUInt32 // In MiraMon code: MM_TIPUS_BYTES_ACUMULATS_DBF +// In MiraMon code: MM_TIPUS_BYTES_PER_CAMP_DBF +typedef GUInt32 MM_BYTES_PER_FIELD_TYPE_DBF; + +// In MiraMon code: MM_TIPUS_BYTES_ACUMULATS_DBF +typedef GUInt32 MM_ACCUMULATED_BYTES_TYPE_DBF; // Type of the number of records of an extended DBF typedef GUInt32 MM_EXT_DBF_N_MULTIPLE_RECORDS; diff --git a/ogr/ogrsf_frmts/miramon/mm_gdal_driver_structs.h b/ogr/ogrsf_frmts/miramon/mm_gdal_driver_structs.h index 06d8b22f6704..d906b38c3145 100644 --- a/ogr/ogrsf_frmts/miramon/mm_gdal_driver_structs.h +++ b/ogr/ogrsf_frmts/miramon/mm_gdal_driver_structs.h @@ -70,6 +70,24 @@ CPL_C_START // Necessary for compiling in GDAL project #define szMMNomCampNArcsDefecte "N_ARCS" #define szMMNomCampNPoligonsDefecte "N_POLIG" +// Used maximum nr. of reliable significant figures in any double. +#define MAX_RELIABLE_SF_DOUBLE 15 + +// Maximum nr. of reliable significant figures +#define MM_MAX_XS_DOUBLE 17 + +// Initial width of MiraMon fields +#define MM_MIN_WIDTH_ID_GRAFIC 3 +#define MM_MIN_WIDTH_N_VERTEXS 5 +#define MM_MIN_WIDTH_INITIAL_NODE MM_MIN_WIDTH_ID_GRAFIC + 1 +#define MM_MIN_WIDTH_FINAL_NODE MM_MIN_WIDTH_ID_GRAFIC + 1 +#define MM_MIN_WIDTH_ARCS_TO_NODE 1 +#define MM_MIN_WIDTH_LONG 14 // For LONG_ARC and PERIMETRE +#define MM_MIN_WIDTH_AREA 19 // For LONG_ARC and PERIMETRE + +#define MM_MIN_WIDTH_N_ARCS 2 +#define MM_MIN_WIDTH_N_POLIG 2 + // Types of layers in MiraMon #define MM_LayerType_Unknown 0 // Unknown type, or DBF alone #define MM_LayerType_Point 1 // Layer of Points @@ -92,8 +110,7 @@ CPL_C_START // Necessary for compiling in GDAL project #define MM_FIRST_NUMBER_OF_VERTICES 10000 #define MM_INCR_NUMBER_OF_VERTICES 1000 -//#define MM_250MB 262144000 -#define MM_25MB 2621440 +#define MM_1MB 1048576 // 1 MB of buffer // Version asked for user #define MM_UNKNOWN_VERSION 0 @@ -123,10 +140,10 @@ CPL_C_START // Necessary for compiling in GDAL project #define MAXIMUM_OBJECT_INDEX_IN_2GB_VECTORS UINT32_MAX //_UI32_MAX #define MAXIMUM_OFFSET_IN_2GB_VECTORS UINT32_MAX //_UI32_MAX -// Number of rings a polygon could have (it is just an initial aproximation) +// Number of rings a polygon could have (it is just an initial approximation) #define MM_MEAN_NUMBER_OF_RINGS 10 -// Number of coordinates a feature could have (it is just an initial aproximation) +// Number of coordinates a feature could have (it is just an initial approximation) #define MM_MEAN_NUMBER_OF_NCOORDS 100 #define MM_MEAN_NUMBER_OF_COORDS 1000 @@ -190,9 +207,10 @@ CPL_C_START // Necessary for compiling in GDAL project // It is the language of the MiraMon generated descriptors. // Metadata will not be translated but these descriptors are // generated from scratch and it is good to use a custom language. -#define MM_ENG_LANGUAGE 0 -#define MM_CAT_LANGUAGE 1 -#define MM_SPA_LANGUAGE 2 +#define MM_DEF_LANGUAGE 0 +#define MM_ENG_LANGUAGE 1 // English language +#define MM_CAT_LANGUAGE 2 // Catalan language +#define MM_SPA_LANGUAGE 3 // Spanish language /* -------------------------------------------------------------------- */ /* Structures */ @@ -303,12 +321,9 @@ struct MiraMonVectorMetaData struct MiraMonFieldValue { MM_BOOLEAN bIsValid; // If 1 the value is filled. If 0, there is no value. -#define MM_INIT_STRING_FIELD_VALUE 50000 // Never less than 10 - MM_EXT_DBF_N_FIELDS nNumDinValue; // Size of the reserved string value - char *pDinValue; // Used if MM_MAX_STRING_FIELD_VALUE is not enough - double dValue; // For double and 32 bit integer numeric values - GInt64 iValue; // For 64 bit integer values. - //MM_BOOLEAN kbValue; // For binary values. + MM_EXT_DBF_N_FIELDS nNumDinValue; // Size of the reserved string value + char *pDinValue; // Used to store the value as string + GInt64 iValue; // For 64 bit integer values. }; struct MiraMonRecord @@ -341,7 +356,7 @@ struct MMAdmDatabase char pszExtDBFLayerName[MM_CPL_PATH_BUF_SIZE]; // Pointer to the extended DBF file FILE_TYPE *pFExtDBF; - // Pointer to a MiraMon table (auxiliar) + // Pointer to a MiraMon table (auxiliary) struct MM_DATA_BASE_XP *pMMBDXP; // How to write all it to disk struct MM_FLUSH_INFO FlushRecList; @@ -424,7 +439,7 @@ struct MM_AH MM_FILE_OFFSET nOffset; // 4/8 bytes depending on the version MM_INTERNAL_FID nFirstIdNode; // 4/8 bytes depending on the version MM_INTERNAL_FID nLastIdNode; // 4/8 bytes depending on the version - double dfLenght; + double dfLength; }; // Header of Nodes @@ -620,7 +635,7 @@ struct MiraMonFeature MM_N_VERTICES_TYPE nMaxpCoord; // Number of used elements in *pCoord (only for reading features) MM_N_VERTICES_TYPE nNumpCoord; - // Coordinate index thats is being processed + // Coordinate index that is being processed MM_N_VERTICES_TYPE nICoord; // List of the coordinates of the feature struct MM_POINT_2D *pCoord; @@ -680,9 +695,9 @@ struct MiraMonVectLayerInfo // Pointer to the main REL name (do not free it) char *pszMainREL_LayerName; -// To know if we are writting or reading -#define MM_READING_MODE 0 // Reading MiraMon layer -#define MM_WRITTING_MODE 1 // Writing MiraMon layer +// To know if we are writing or reading +#define MM_READING_MODE 0 // Reading MiraMon layer +#define MM_WRITING_MODE 1 // Writing MiraMon layer MM_BOOLEAN ReadOrWrite; char pszFlags[10]; // To Open the file @@ -699,16 +714,6 @@ struct MiraMonVectLayerInfo // Final number of elements of the layer. MM_INTERNAL_FID nFinalElemCount; // Real element count after conversion - // Ratio used to enhance certain aspects of memory - // In some memory settings, a block of 256 or 512 bytes is used. - // This parameter can be adjusted to achieve - // nMemoryRatio*256 or nMemoryRatio*512. - // For example, nMemoryRatio=2 in powerful computers and - // nMemoryRatio=0.5 in less powerful computers. - // By increasing this parameter, more memory will be required, - // but there will be fewer read/write operations to the disk. - double nMemoryRatio; - // Header of the layer size_t nHeaderDiskSize; struct MM_TH TopHeader; @@ -732,6 +737,12 @@ struct MiraMonVectLayerInfo char *pSRS; int nSRS_EPSG; // Ref. system if has EPSG code. +// Used to write the precision of the reserved fields in the DBF +#define MM_SRS_LAYER_IS_UNKNOWN_TYPE 0 +#define MM_SRS_LAYER_IS_PROJECTED_TYPE 1 +#define MM_SRS_LAYER_IS_GEOGRAPHIC_TYPE 2 + int nSRSType; + // In GDAL->MiraMon sense: // Transformed table from input layer to a MiraMon table. // This table has to be merged with private MiraMon fields to obtain @@ -752,9 +763,12 @@ struct MiraMonVectLayerInfo MM_EXT_DBF_N_RECORDS nMaxN; // Max number of elements in a field features list struct MM_ID_GRAFIC_MULTIPLE_RECORD *pMultRecordIndex; - // In case of multirecord, if user wants only one Record 'iMultiRecord' - // specifies which one: 0, 1, 2,... or "Last". There is also the "JSON" option - // that writes a serialized JSON array like (``[1,2]``). +// In case of multirecord, if user wants only one Record 'iMultiRecord' +// specifies which one: 0, 1, 2,... or "Last". There is also the "JSON" option +// that writes a serialized JSON array like (``[1,2]``). +#define MM_MULTIRECORD_LAST -1 +#define MM_MULTIRECORD_NO_MULTIRECORD -2 +#define MM_MULTIRECORD_JSON -3 int iMultiRecord; // Charset of DBF files (same for all) when writing it. @@ -770,7 +784,7 @@ struct MiraMonVectLayerInfo // This is used only to write temporary stuff char szNFieldAux[MM_MAX_AMPLADA_CAMP_N_DBF]; - // Dinamic string that is used as temporary buffer + // Dynamic string that is used as temporary buffer // with variable size as needed. Its value is // highly temporary. Copy in a safe place to save its value. GUInt64 nNumStringToOperate; diff --git a/ogr/ogrsf_frmts/miramon/mm_gdal_functions.c b/ogr/ogrsf_frmts/miramon/mm_gdal_functions.c index 319410ac0a70..dc8c179a3401 100644 --- a/ogr/ogrsf_frmts/miramon/mm_gdal_functions.c +++ b/ogr/ogrsf_frmts/miramon/mm_gdal_functions.c @@ -28,16 +28,16 @@ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifdef GDAL_COMPILATION #include "ogr_api.h" // For CPL_C_START -#include "mm_gdal_functions.h" // For MM_strnzcpy() +#include "mm_gdal_functions.h" // For CPLStrlcpy() #include "mm_wrlayr.h" // For calloc_function()... #else #include "CmptCmp.h" -#include "mm_gdal\mm_gdal_functions.h" // For MM_strnzcpy() +#include "mm_gdal\mm_gdal_functions.h" // For CPLStrlcpy() #include "mm_gdal\mm_wrlayr.h" // For calloc_function()... #endif // GDAL_COMPILATION @@ -48,143 +48,144 @@ CPL_C_START // Necessary for compiling in GDAL project #ifdef _WIN64 #include "gdal\release-1911-x64\cpl_string.h" // For CPL_ENC_UTF8 #else -#include "gdal\release-1911-32\cpl_string.h" // For CPL_ENC_UTF8 +#include "gdal\release-1911-32\cpl_string.h" // For CPL_ENC_UTF8szNumberOfVerticesEsp #endif #endif - static char local_message[MAX_LOCAL_MESSAGE]; - -char szInternalGraphicIdentifierEng[MM_MAX_IDENTIFIER_SIZE]; + char szInternalGraphicIdentifierEng[MM_MAX_IDENTIFIER_SIZE]; char szInternalGraphicIdentifierCat[MM_MAX_IDENTIFIER_SIZE]; -char szInternalGraphicIdentifierEsp[MM_MAX_IDENTIFIER_SIZE]; +char szInternalGraphicIdentifierSpa[MM_MAX_IDENTIFIER_SIZE]; char szNumberOfVerticesEng[MM_MAX_IDENTIFIER_SIZE]; char szNumberOfVerticesCat[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfVerticesEsp[MM_MAX_IDENTIFIER_SIZE]; +char szNumberOfVerticesSpa[MM_MAX_IDENTIFIER_SIZE]; -char szLenghtOfAarcEng[MM_MAX_IDENTIFIER_SIZE]; -char szLenghtOfAarcCat[MM_MAX_IDENTIFIER_SIZE]; -char szLenghtOfAarcEsp[MM_MAX_IDENTIFIER_SIZE]; +char szLengthOfAarcEng[MM_MAX_IDENTIFIER_SIZE]; +char szLengthOfAarcCat[MM_MAX_IDENTIFIER_SIZE]; +char szLengthOfAarcSpa[MM_MAX_IDENTIFIER_SIZE]; char szInitialNodeEng[MM_MAX_IDENTIFIER_SIZE]; char szInitialNodeCat[MM_MAX_IDENTIFIER_SIZE]; -char szInitialNodeEsp[MM_MAX_IDENTIFIER_SIZE]; +char szInitialNodeSpa[MM_MAX_IDENTIFIER_SIZE]; char szFinalNodeEng[MM_MAX_IDENTIFIER_SIZE]; char szFinalNodeCat[MM_MAX_IDENTIFIER_SIZE]; -char szFinalNodeEsp[MM_MAX_IDENTIFIER_SIZE]; +char szFinalNodeSpa[MM_MAX_IDENTIFIER_SIZE]; char szNumberOfArcsToNodeEng[MM_MAX_IDENTIFIER_SIZE]; char szNumberOfArcsToNodeCat[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfArcsToNodeEsp[MM_MAX_IDENTIFIER_SIZE]; +char szNumberOfArcsToNodeSpa[MM_MAX_IDENTIFIER_SIZE]; char szNodeTypeEng[MM_MAX_IDENTIFIER_SIZE]; char szNodeTypeCat[MM_MAX_IDENTIFIER_SIZE]; -char szNodeTypeEsp[MM_MAX_IDENTIFIER_SIZE]; +char szNodeTypeSpa[MM_MAX_IDENTIFIER_SIZE]; char szPerimeterOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE]; char szPerimeterOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE]; -char szPerimeterOfThePolygonEsp[MM_MAX_IDENTIFIER_SIZE]; +char szPerimeterOfThePolygonSpa[MM_MAX_IDENTIFIER_SIZE]; char szAreaOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE]; char szAreaOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE]; -char szAreaOfThePolygonEsp[MM_MAX_IDENTIFIER_SIZE]; +char szAreaOfThePolygonSpa[MM_MAX_IDENTIFIER_SIZE]; char szNumberOfArcsEng[MM_MAX_IDENTIFIER_SIZE]; char szNumberOfArcsCat[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfArcsEsp[MM_MAX_IDENTIFIER_SIZE]; +char szNumberOfArcsSpa[MM_MAX_IDENTIFIER_SIZE]; char szNumberOfElementaryPolygonsEng[MM_MAX_IDENTIFIER_SIZE]; char szNumberOfElementaryPolygonsCat[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfElementaryPolygonsEsp[MM_MAX_IDENTIFIER_SIZE]; +char szNumberOfElementaryPolygonsSpa[MM_MAX_IDENTIFIER_SIZE]; void MM_FillFieldDescriptorByLanguage(void) { - MM_strnzcpy(szInternalGraphicIdentifierEng, "Internal Graphic identifier", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szInternalGraphicIdentifierCat, "Identificador Grafic intern", - MM_MAX_IDENTIFIER_SIZE); - szInternalGraphicIdentifierCat[16] = MM_a_WITH_GRAVE; - MM_strnzcpy(szInternalGraphicIdentifierEsp, "Identificador Grafico interno", - MM_MAX_IDENTIFIER_SIZE); - szInternalGraphicIdentifierEsp[16] = MM_a_WITH_ACUTE; - - MM_strnzcpy(szNumberOfVerticesEng, "Number of vertices", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfVerticesCat, "Nombre de vertexs", - MM_MAX_IDENTIFIER_SIZE); - szNumberOfVerticesCat[11] = MM_e_WITH_GRAVE; - MM_strnzcpy(szNumberOfVerticesEsp, "Numero de vertices", - MM_MAX_IDENTIFIER_SIZE); - szNumberOfVerticesEsp[1] = MM_u_WITH_ACUTE; - szNumberOfVerticesEsp[11] = MM_e_WITH_ACUTE; - - MM_strnzcpy(szLenghtOfAarcEng, "Lenght of arc", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szLenghtOfAarcCat, "Longitud de l'arc", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szLenghtOfAarcEsp, "Longitud del arco", MM_MAX_IDENTIFIER_SIZE); - - MM_strnzcpy(szInitialNodeEng, "Initial node", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szInitialNodeCat, "Node inicial", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szInitialNodeEsp, "Nodo inicial", MM_MAX_IDENTIFIER_SIZE); - - MM_strnzcpy(szFinalNodeEng, "Final node", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szFinalNodeCat, "Node final", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szFinalNodeEsp, "Nodo final", MM_MAX_IDENTIFIER_SIZE); - - MM_strnzcpy(szNumberOfArcsToNodeEng, "Number of arcs to node", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfArcsToNodeCat, "Nombre d'arcs al node", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfArcsToNodeEsp, "Numero de arcos al nodo", - MM_MAX_IDENTIFIER_SIZE); - szNumberOfArcsToNodeEsp[1] = MM_u_WITH_ACUTE; - - MM_strnzcpy(szNodeTypeEng, "Node type", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNodeTypeCat, "Tipus de node", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNodeTypeEsp, "Tipo de nodo", MM_MAX_IDENTIFIER_SIZE); - - MM_strnzcpy(szPerimeterOfThePolygonEng, "Perimeter of the polygon", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szPerimeterOfThePolygonCat, "Perimetre del poligon", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szPerimeterOfThePolygonEsp, "Perimetro del poligono", - MM_MAX_IDENTIFIER_SIZE); - szPerimeterOfThePolygonCat[3] = MM_i_WITH_ACUTE; - szPerimeterOfThePolygonEsp[3] = MM_i_WITH_ACUTE; - szPerimeterOfThePolygonCat[17] = MM_i_WITH_ACUTE; - szPerimeterOfThePolygonEsp[17] = MM_i_WITH_ACUTE; - - MM_strnzcpy(szAreaOfThePolygonEng, "Area of the polygon", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szAreaOfThePolygonCat, "Area del poligon", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szAreaOfThePolygonEsp, "Area del poligono", - MM_MAX_IDENTIFIER_SIZE); - szAreaOfThePolygonCat[0] = MM_A_WITH_GRAVE; - szAreaOfThePolygonEsp[0] = MM_A_WITH_ACUTE; - szAreaOfThePolygonCat[12] = MM_i_WITH_ACUTE; - szAreaOfThePolygonEsp[12] = MM_i_WITH_ACUTE; - - MM_strnzcpy(szNumberOfArcsEng, "Number of arcs", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfArcsCat, "Nombre d'arcs", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfArcsEsp, "Numero de arcos", MM_MAX_IDENTIFIER_SIZE); - szNumberOfArcsEsp[1] = MM_u_WITH_ACUTE; - - MM_strnzcpy(szNumberOfElementaryPolygonsEng, - "Number of elementary polygons", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfElementaryPolygonsCat, - "Nombre de poligons elementals", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfElementaryPolygonsEsp, - "Numero de poligonos elementales", MM_MAX_IDENTIFIER_SIZE); - szNumberOfElementaryPolygonsEsp[1] = MM_u_WITH_ACUTE; - szNumberOfElementaryPolygonsCat[13] = MM_i_WITH_ACUTE; - szNumberOfElementaryPolygonsEsp[13] = MM_i_WITH_ACUTE; + CPLStrlcpy(szInternalGraphicIdentifierEng, "Internal Graphic identifier", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szInternalGraphicIdentifierCat, "Identificador Grafic intern", + MM_MAX_IDENTIFIER_SIZE); + *(unsigned char *)&szInternalGraphicIdentifierCat[16] = MM_a_WITH_GRAVE; + CPLStrlcpy(szInternalGraphicIdentifierSpa, "Identificador Grafico interno", + MM_MAX_IDENTIFIER_SIZE); + *(unsigned char *)&szInternalGraphicIdentifierSpa[16] = MM_a_WITH_ACUTE; + + CPLStrlcpy(szNumberOfVerticesEng, "Number of vertices", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNumberOfVerticesCat, "Nombre de vertexs", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNumberOfVerticesSpa, "Numero de vertices", + MM_MAX_IDENTIFIER_SIZE); + *(unsigned char *)&szNumberOfVerticesSpa[1] = MM_u_WITH_ACUTE; + *(unsigned char *)&szNumberOfVerticesSpa[11] = MM_e_WITH_ACUTE; + + CPLStrlcpy(szLengthOfAarcEng, "Length of arc", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szLengthOfAarcCat, "Longitud de l'arc", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szLengthOfAarcSpa, "Longitud del arco", MM_MAX_IDENTIFIER_SIZE); + + CPLStrlcpy(szInitialNodeEng, "Initial node", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szInitialNodeCat, "Node inicial", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szInitialNodeSpa, "Nodo inicial", MM_MAX_IDENTIFIER_SIZE); + + CPLStrlcpy(szFinalNodeEng, "Final node", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szFinalNodeCat, "Node final", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szFinalNodeSpa, "Nodo final", MM_MAX_IDENTIFIER_SIZE); + + CPLStrlcpy(szNumberOfArcsToNodeEng, "Number of arcs to node", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNumberOfArcsToNodeCat, "Nombre d'arcs al node", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNumberOfArcsToNodeSpa, "Numero de arcos al nodo", + MM_MAX_IDENTIFIER_SIZE); + *(unsigned char *)&szNumberOfArcsToNodeSpa[1] = MM_u_WITH_ACUTE; + + CPLStrlcpy(szNodeTypeEng, "Node type", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNodeTypeCat, "Tipus de node", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNodeTypeSpa, "Tipo de nodo", MM_MAX_IDENTIFIER_SIZE); + + CPLStrlcpy(szPerimeterOfThePolygonEng, "Perimeter of the polygon", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szPerimeterOfThePolygonCat, "Perimetre del poligon", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szPerimeterOfThePolygonSpa, "Perimetro del poligono", + MM_MAX_IDENTIFIER_SIZE); + + *(unsigned char *)&szPerimeterOfThePolygonCat[3] = MM_i_WITH_ACUTE; + *(unsigned char *)&szPerimeterOfThePolygonSpa[3] = MM_i_WITH_ACUTE; + *(unsigned char *)&szPerimeterOfThePolygonCat[17] = MM_i_WITH_ACUTE; + *(unsigned char *)&szPerimeterOfThePolygonSpa[17] = MM_i_WITH_ACUTE; + + CPLStrlcpy(szAreaOfThePolygonEng, "Area of the polygon", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szAreaOfThePolygonCat, "Area del poligon", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szAreaOfThePolygonSpa, "Area del poligono", + MM_MAX_IDENTIFIER_SIZE); + + *(unsigned char *)&szAreaOfThePolygonCat[0] = MM_A_WITH_GRAVE; + *(unsigned char *)&szAreaOfThePolygonSpa[0] = MM_A_WITH_ACUTE; + *(unsigned char *)&szAreaOfThePolygonCat[12] = MM_i_WITH_ACUTE; + *(unsigned char *)&szAreaOfThePolygonSpa[12] = MM_i_WITH_ACUTE; + + CPLStrlcpy(szNumberOfArcsEng, "Number of arcs", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNumberOfArcsCat, "Nombre d'arcs", MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNumberOfArcsSpa, "Numero de arcos", MM_MAX_IDENTIFIER_SIZE); + + *(unsigned char *)&szNumberOfArcsSpa[1] = MM_u_WITH_ACUTE; + + CPLStrlcpy(szNumberOfElementaryPolygonsEng, "Number of elementary polygons", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNumberOfElementaryPolygonsCat, "Nombre de poligons elementals", + MM_MAX_IDENTIFIER_SIZE); + CPLStrlcpy(szNumberOfElementaryPolygonsSpa, + "Numero de poligonos elementales", MM_MAX_IDENTIFIER_SIZE); + + *(unsigned char *)&szNumberOfElementaryPolygonsSpa[1] = MM_u_WITH_ACUTE; + *(unsigned char *)&szNumberOfElementaryPolygonsCat[13] = MM_i_WITH_ACUTE; + *(unsigned char *)&szNumberOfElementaryPolygonsSpa[13] = MM_i_WITH_ACUTE; } const char *MM_pszLogFilename = nullptr; -// Loging -const char *Log(const char *pszMsg, int nLineNumber) +// Logging +const char *MMLog(const char *pszMsg, int nLineNumber) { FILE *f; @@ -193,7 +194,7 @@ const char *Log(const char *pszMsg, int nLineNumber) f = fopen(MM_pszLogFilename, "at"); if (f == nullptr) return pszMsg; - fprintf(f, "%d: %s\n", nLineNumber, pszMsg); + fprintf(f, "%d: %s\n", nLineNumber, pszMsg); /*ok*/ fclose(f); return pszMsg; } @@ -202,6 +203,14 @@ static const char MM_EmptyString[] = {""}; #define MM_SetEndOfString (*MM_EmptyString) static const char MM_BlankString[] = {" "}; +void fclose_and_nullify(FILE_TYPE **pFunc) +{ + if (!pFunc || !(*pFunc)) + return; + fclose_function(*pFunc); + *pFunc = nullptr; +} + // CREATING AN EXTENDED MIRAMON DBF void MM_InitializeField(struct MM_FIELD *pField) { @@ -210,11 +219,31 @@ void MM_InitializeField(struct MM_FIELD *pField) pField->GeoTopoTypeField = MM_NO_ES_CAMP_GEOTOPO; } +#define MM_ACCEPTABLE_NUMBER_OF_FIELDS 20000 + struct MM_FIELD *MM_CreateAllFields(MM_EXT_DBF_N_FIELDS nFields) { struct MM_FIELD *camp; MM_EXT_DBF_N_FIELDS i; + // MiraMon could accept a number of fields 13.4 million + // but GDAL prefers to limit that to 20.000 to avoid + // too large memory allocation attempts with corrupted datasets + if (nFields > MM_ACCEPTABLE_NUMBER_OF_FIELDS) + { + MMCPLError(CE_Failure, CPLE_OutOfMemory, + "More than 20000 fields not accepted"); + return nullptr; + } + +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (nFields >= UINT32_MAX / sizeof(*camp)) + return nullptr; +#else + if (nFields >= (1000U * 1000 * 1000) / sizeof(*camp)) + return nullptr; +#endif + if ((camp = calloc_function(nFields * sizeof(*camp))) == nullptr) return nullptr; @@ -272,9 +301,11 @@ struct MM_DATA_BASE_XP *MM_CreateDBFHeader(MM_EXT_DBF_N_FIELDS n_camps, { MM_InitializeField(camp); if (i < 99999) - sprintf(camp->FieldName, "CAMP%05u", (unsigned)(i + 1)); + snprintf(camp->FieldName, sizeof(camp->FieldName), "CAMP%05u", + (unsigned)(i + 1)); else - sprintf(camp->FieldName, "CM%u", (unsigned)(i + 1)); + snprintf(camp->FieldName, sizeof(camp->FieldName), "CM%u", + (unsigned)(i + 1)); camp->FieldType = 'C'; camp->DecimalsIfFloat = 0; camp->BytesPerField = 50; @@ -315,11 +346,11 @@ static MM_BYTE MM_GetDefaultDesiredDBFFieldWidth(const struct MM_FIELD *camp) return (MM_BYTE)(e < 80 ? e : 80); } -static MM_BOOLEAN MM_is_field_name_lowercase(const char *cadena) +static MM_BOOLEAN MM_is_field_name_lowercase(const char *szChain) { const char *p; - for (p = cadena; *p; p++) + for (p = szChain; *p; p++) { if ((*p >= 'a' && *p <= 'z')) return TRUE; @@ -328,11 +359,11 @@ static MM_BOOLEAN MM_is_field_name_lowercase(const char *cadena) } static MM_BOOLEAN -MM_Is_classical_DBF_field_name_or_lowercase(const char *cadena) +MM_Is_classical_DBF_field_name_or_lowercase(const char *szChain) { const char *p; - for (p = cadena; *p; p++) + for (p = szChain; *p; p++) { if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_') @@ -340,7 +371,7 @@ MM_Is_classical_DBF_field_name_or_lowercase(const char *cadena) else return FALSE; } - if (cadena[0] == '_') + if (szChain[0] == '_') return FALSE; return TRUE; } @@ -384,9 +415,9 @@ MM_Is_character_valid_for_extended_DBF_field_name(int valor, static int MM_ISExtendedNameBD_XP(const char *nom_camp) { - GInt32 mida, j; + size_t mida, j; - mida = (GInt32)strlen(nom_camp); + mida = strlen(nom_camp); if (mida >= MM_MAX_LON_FIELD_NAME_DBF) return MM_DBF_NAME_NO_VALID; @@ -416,10 +447,10 @@ static MM_BYTE MM_CalculateBytesExtendedFieldName(struct MM_FIELD *camp) return MM_DonaBytesNomEstesCamp(camp); } -static MM_ACUMULATED_BYTES_TYPE_DBF +static MM_ACCUMULATED_BYTES_TYPE_DBF MM_CalculateBytesExtendedFieldNames(const struct MM_DATA_BASE_XP *bd_xp) { - MM_ACUMULATED_BYTES_TYPE_DBF bytes_acumulats = 0; + MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats = 0; MM_EXT_DBF_N_FIELDS i_camp; for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) @@ -451,7 +482,7 @@ static void MM_CheckDBFHeader(struct MM_DATA_BASE_XP *bd_xp) bd_xp->BytesPerRecord = 1; for (i = 0, camp = bd_xp->pField; i < bd_xp->nFields; i++, camp++) { - camp->AcumulatedBytes = bd_xp->BytesPerRecord; + camp->AccumulatedBytes = bd_xp->BytesPerRecord; bd_xp->BytesPerRecord += camp->BytesPerField; if (camp->DesiredWidth == 0) camp->DesiredWidth = camp->OriginalDesiredWidth = @@ -491,17 +522,17 @@ MM_InitializeBytesExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp, 0, 1); } -static short int MM_return_common_valid_DBF_field_name_string(char *cadena) +static short int MM_return_common_valid_DBF_field_name_string(char *szChain) { char *p; short int error_retornat = 0; - if (!cadena) + if (!szChain) return 0; - //strupr(cadena); - for (p = cadena; *p; p++) + //strupr(szChain); + for (p = szChain; *p; p++) { - (*p) = (char)toupper(*p); + (*p) = (char)toupper((unsigned char)*p); if ((*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_') ; else @@ -510,27 +541,29 @@ static short int MM_return_common_valid_DBF_field_name_string(char *cadena) error_retornat |= MM_FIELD_NAME_CHARACTER_INVALID; } } - if (cadena[0] == '_') + if (szChain[0] == '_') { - cadena[0] = '0'; + // To avoid having field names starting by '_' this case is + // substituted by a 0 (not a '\0'). + szChain[0] = '0'; error_retornat |= MM_FIELD_NAME_FIRST_CHARACTER_; } return error_retornat; } -static short int MM_ReturnValidClassicDBFFieldName(char *cadena) +static short int MM_ReturnValidClassicDBFFieldName(char *szChain) { size_t long_nom_camp; short int error_retornat = 0; - long_nom_camp = strlen(cadena); + long_nom_camp = strlen(szChain); if ((long_nom_camp < 1) || (long_nom_camp >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF)) { - cadena[MM_MAX_LON_FIELD_NAME_DBF - 1] = '\0'; + szChain[MM_MAX_LON_FIELD_NAME_DBF - 1] = '\0'; error_retornat |= MM_FIELD_NAME_TOO_LONG; } - error_retornat |= MM_return_common_valid_DBF_field_name_string(cadena); + error_retornat |= MM_return_common_valid_DBF_field_name_string(szChain); return error_retornat; } @@ -552,7 +585,7 @@ MM_CheckClassicFieldNameEqual(const struct MM_DATA_BASE_XP *data_base_XP, } static char *MM_GiveNewStringWithCharacterInFront(const char *text, - char caracter) + char character) { char *ptr; size_t i; @@ -564,29 +597,37 @@ static char *MM_GiveNewStringWithCharacterInFront(const char *text, if ((ptr = calloc_function(i + 2)) == nullptr) return nullptr; - *ptr = caracter; + *ptr = character; memcpy(ptr + 1, text, i + 1); return ptr; } -static char *MM_SetSubIndexFieldNam(char *nom_camp, MM_EXT_DBF_N_FIELDS index, +static char *MM_SetSubIndexFieldNam(const char *nom_camp, + MM_EXT_DBF_N_FIELDS index, size_t ampladamax) { char *NomCamp_SubIndex; char *_subindex; - char subindex[15]; + char subindex[19 + 1]; size_t sizet_subindex; size_t sizet_nomcamp; - NomCamp_SubIndex = calloc_function(ampladamax * sizeof(char)); + NomCamp_SubIndex = calloc_function(ampladamax); if (!NomCamp_SubIndex) return nullptr; - strcpy(NomCamp_SubIndex, nom_camp); + CPLStrlcpy(NomCamp_SubIndex, nom_camp, ampladamax); + NomCamp_SubIndex[ampladamax - 1] = '\0'; - sprintf(subindex, sprintf_UINT64, (GUInt64)index); + snprintf(subindex, sizeof(subindex), sprintf_UINT64, (GUInt64)index); _subindex = MM_GiveNewStringWithCharacterInFront(subindex, '_'); + if (!_subindex) + { + free_function(NomCamp_SubIndex); + return nullptr; + } + sizet_subindex = strlen(_subindex); sizet_nomcamp = strlen(NomCamp_SubIndex); @@ -614,7 +655,6 @@ MM_GiveOffsetExtendedFieldName(const struct MM_FIELD *camp) int MM_WriteNRecordsMMBD_XPFile(struct MMAdmDatabase *MMAdmDB) { - GUInt32 nRecords; if (!MMAdmDB->pMMBDXP || !MMAdmDB->pFExtDBF) return 0; @@ -624,17 +664,16 @@ int MM_WriteNRecordsMMBD_XPFile(struct MMAdmDatabase *MMAdmDB) if (MMAdmDB->pMMBDXP->nRecords > UINT32_MAX) { MMAdmDB->pMMBDXP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA; - - if (fwrite_function(&MMAdmDB->pMMBDXP->nRecords, 4, 1, - MMAdmDB->pFExtDBF) != 1) - return 1; } else { MMAdmDB->pMMBDXP->dbf_version = MM_MARCA_DBASE4; + } - nRecords = (GUInt32)MMAdmDB->pMMBDXP->nRecords; - if (fwrite_function(&nRecords, 4, 1, MMAdmDB->pFExtDBF) != 1) + { + GUInt32 nRecords32LowBits = + (GUInt32)(MMAdmDB->pMMBDXP->nRecords & UINT32_MAX); + if (fwrite_function(&nRecords32LowBits, 4, 1, MMAdmDB->pFExtDBF) != 1) return 1; } @@ -642,8 +681,9 @@ int MM_WriteNRecordsMMBD_XPFile(struct MMAdmDatabase *MMAdmDB) if (MMAdmDB->pMMBDXP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA) { /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */ - if (fwrite_function(((char *)(&MMAdmDB->pMMBDXP->nRecords)) + 4, 4, 1, - MMAdmDB->pFExtDBF) != 1) + GUInt32 nRecords32HighBits = + (GUInt32)(MMAdmDB->pMMBDXP->nRecords >> 32); + if (fwrite_function(&nRecords32HighBits, 4, 1, MMAdmDB->pFExtDBF) != 1) return 1; /* from 20 to 27 */ @@ -665,8 +705,7 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) { MM_BYTE variable_byte; MM_EXT_DBF_N_FIELDS i, j = 0; - const size_t max_n_zeros = 11; - char *zero; + char zero[11] = {0}; const MM_BYTE byte_zero = 0; char ModeLectura_previ[4] = ""; MM_FIRST_RECORD_OFFSET_TYPE bytes_acumulats; @@ -675,10 +714,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) char nom_camp[MM_MAX_LON_FIELD_NAME_DBF]; size_t retorn_fwrite; MM_BOOLEAN table_should_be_closed = FALSE; - GUInt32 nRecords; - - if ((zero = calloc_function(max_n_zeros)) == nullptr) - return FALSE; if (data_base_XP->pfDataBase == nullptr) { @@ -689,7 +724,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) fopen_function(data_base_XP->szFileName, data_base_XP->ReadingMode)) == nullptr) { - free_function(zero); return FALSE; } @@ -722,14 +756,13 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) } } - // Writting header + // Writing header fseek_function(data_base_XP->pfDataBase, 0, SEEK_SET); /* Byte 0 */ if (fwrite_function(&(data_base_XP->dbf_version), 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } @@ -745,18 +778,13 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) return FALSE; /* from 4 a 7, position MM_FIRST_OFFSET_to_N_RECORDS */ - if (data_base_XP->nRecords > UINT32_MAX) { - if (fwrite_function(&data_base_XP->nRecords, 4, 1, + GUInt32 nRecords32LowBits = + (GUInt32)(data_base_XP->nRecords & UINT32_MAX); + if (fwrite_function(&nRecords32LowBits, 4, 1, data_base_XP->pfDataBase) != 1) return FALSE; } - else - { - nRecords = (GUInt32)data_base_XP->nRecords; - if (fwrite_function(&nRecords, 4, 1, data_base_XP->pfDataBase) != 1) - return FALSE; - } /* from 8 a 9, position MM_PRIMER_OFFSET_a_OFFSET_1a_FITXA */ if (fwrite_function(&(data_base_XP->FirstRecordOffset), 2, 1, @@ -766,7 +794,7 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version)) { if (fwrite_function(&(data_base_XP->BytesPerRecord), - sizeof(MM_ACUMULATED_BYTES_TYPE_DBF), 1, + sizeof(MM_ACCUMULATED_BYTES_TYPE_DBF), 1, data_base_XP->pfDataBase) != 1) return FALSE; } @@ -794,7 +822,8 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (data_base_XP->nRecords > UINT32_MAX) { /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */ - if (fwrite_function(((char *)(&data_base_XP->nRecords)) + 4, 4, 1, + GUInt32 nRecords32HighBits = (GUInt32)(data_base_XP->nRecords >> 32); + if (fwrite_function(&nRecords32HighBits, 4, 1, data_base_XP->pfDataBase) != 1) return FALSE; @@ -862,8 +891,8 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) { char nom_temp[MM_MAX_LON_FIELD_NAME_DBF]; - MM_strnzcpy(nom_temp, data_base_XP->pField[i].FieldName, - MM_MAX_LON_FIELD_NAME_DBF); + CPLStrlcpy(nom_temp, data_base_XP->pField[i].FieldName, + MM_MAX_LON_FIELD_NAME_DBF); MM_ReturnValidClassicDBFFieldName(nom_temp); nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0'; if ((MM_CheckClassicFieldNameEqual(data_base_XP, nom_temp)) == @@ -874,23 +903,37 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) c = MM_SetSubIndexFieldNam( nom_temp, i, MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); - j = 0; - while (MM_CheckClassicFieldNameEqual(data_base_XP, c) == - TRUE && - j < data_base_XP->nFields) + if (c) { - free_function(c); - c = MM_SetSubIndexFieldNam( - nom_temp, ++j, MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); + j = 0; + while (MM_CheckClassicFieldNameEqual(data_base_XP, c) == + TRUE && + j < data_base_XP->nFields) + { + free_function(c); + c = MM_SetSubIndexFieldNam( + nom_temp, ++j, + MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); + } + if (c) + { + CPLStrlcpy( + data_base_XP->pField[i].ClassicalDBFFieldName, + c, + sizeof(data_base_XP->pField[i] + .ClassicalDBFFieldName)); + free_function(c); + } } - - strcpy(data_base_XP->pField[i].ClassicalDBFFieldName, c); - free_function(c); } else - strcpy(data_base_XP->pField[i].ClassicalDBFFieldName, - nom_temp); + CPLStrlcpy( + data_base_XP->pField[i].ClassicalDBFFieldName, nom_temp, + sizeof(data_base_XP->pField[i].ClassicalDBFFieldName)); } + + // This is a 11-byte fixed size field consisting of the filename + // and it's been padding calculated some next lines. j = (short)strlen(data_base_XP->pField[i].ClassicalDBFFieldName); retorn_fwrite = @@ -898,7 +941,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) 1, j, data_base_XP->pfDataBase); if (retorn_fwrite != (size_t)j) { - free_function(zero); return FALSE; } @@ -909,28 +951,24 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) } else { - free_function(zero); return FALSE; } if (fwrite_function(zero, 1, 11 - j, data_base_XP->pfDataBase) != 11 - (size_t)j) { - free_function(zero); return FALSE; } /* Byte 11, Field type */ if (fwrite_function(&data_base_XP->pField[i].FieldType, 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } /* Bytes 12 to 15 --> Reserved */ if (fwrite_function(&data_base_XP->pField[i].reserved_1, 4, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } /* Byte 16, or OFFSET_BYTESxCAMP_CAMP_CLASSIC --> BytesPerField */ @@ -940,7 +978,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (fwrite_function((void *)&byte_zero, 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } } @@ -949,7 +986,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (fwrite_function(&data_base_XP->pField[i].BytesPerField, 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } } @@ -960,7 +996,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (fwrite_function(&data_base_XP->pField[i].DecimalsIfFloat, 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } } @@ -968,7 +1003,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) { if (fwrite_function(zero, 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } } @@ -979,7 +1013,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (fwrite_function(&data_base_XP->pField[i].reserved_2, 20 - 18 + 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } /* Bytes from 21 to 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C @@ -988,7 +1021,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) sizeof(MM_BYTES_PER_FIELD_TYPE_DBF), 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } @@ -996,7 +1028,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (fwrite_function(&data_base_XP->pField[i].reserved_2[25 - 18], 30 - 25 + 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } } @@ -1010,7 +1041,6 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (fwrite_function(&data_base_XP->pField[i].reserved_2, 13, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } } @@ -1018,13 +1048,10 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (fwrite_function(&data_base_XP->pField[i].MDX_field_flag, 1, 1, data_base_XP->pfDataBase) != 1) { - free_function(zero); return FALSE; } } - free_function(zero); - variable_byte = 13; if (fwrite_function(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1) return FALSE; @@ -1057,8 +1084,7 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) if (table_should_be_closed) { - fclose_function(data_base_XP->pfDataBase); - data_base_XP->pfDataBase = nullptr; + fclose_and_nullify(&data_base_XP->pfDataBase); } return TRUE; @@ -1067,11 +1093,11 @@ static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) MM_BOOLEAN MM_CreateDBFFile(struct MM_DATA_BASE_XP *bd_xp, const char *NomFitxer) { - if (MMIsEmptyString(NomFitxer)) - return TRUE; // No file no error. Just continue + if (!NomFitxer || MMIsEmptyString(NomFitxer) || !bd_xp) + return FALSE; + MM_CheckDBFHeader(bd_xp); - if (NomFitxer) - strcpy(bd_xp->szFileName, NomFitxer); + CPLStrlcpy(bd_xp->szFileName, NomFitxer, sizeof(bd_xp->szFileName)); return MM_UpdateEntireHeader(bd_xp); } @@ -1079,7 +1105,7 @@ void MM_ReleaseMainFields(struct MM_DATA_BASE_XP *data_base_XP) { MM_EXT_DBF_N_FIELDS i; size_t j; - char **cadena; + char **szChain; if (data_base_XP->pField) { @@ -1087,11 +1113,11 @@ void MM_ReleaseMainFields(struct MM_DATA_BASE_XP *data_base_XP) { for (j = 0; j < MM_NUM_IDIOMES_MD_MULTIDIOMA; j++) { - cadena = data_base_XP->pField[i].Separator; - if (cadena[j]) + szChain = data_base_XP->pField[i].Separator; + if (szChain[j]) { - free_function(cadena[j]); - cadena[j] = nullptr; + free_function(szChain[j]); + szChain[j] = nullptr; } } } @@ -1110,8 +1136,8 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, { MM_BYTE variable_byte; FILE_TYPE *pf; - unsigned short int ushort; - MM_EXT_DBF_N_FIELDS nIField, j; + unsigned short int two_bytes; + MM_EXT_DBF_N_FIELDS nIField; MM_FIRST_RECORD_OFFSET_TYPE offset_primera_fitxa; MM_FIRST_RECORD_OFFSET_TYPE offset_fals = 0; MM_BOOLEAN incoherent_record_size = FALSE; @@ -1119,18 +1145,18 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, MM_BYTES_PER_FIELD_TYPE_DBF bytes_per_camp; MM_BYTE tretze_bytes[13]; MM_FIRST_RECORD_OFFSET_TYPE offset_possible; - MM_BYTE n_queixes_estructura_incorrecta = 0; + MM_BYTE some_problems_when_reading = 0; MM_FILE_OFFSET offset_reintent = 0; // For retrying char cpg_file[MM_CPL_PATH_BUF_SIZE]; char *pszDesc; char section[MM_MAX_LON_FIELD_NAME_DBF + 25]; // TAULA_PRINCIPAL:field_name - GUInt32 nRecords; + GUInt32 nRecords32LowBits; char *pszString; if (!szFileName) return 1; - strcpy(pMMBDXP->szFileName, szFileName); + CPLStrlcpy(pMMBDXP->szFileName, szFileName, sizeof(pMMBDXP->szFileName)); strcpy(pMMBDXP->ReadingMode, "rb"); if ((pMMBDXP->pfDataBase = fopen_function(pMMBDXP->szFileName, @@ -1148,64 +1174,73 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, 1 != fread_function(&(pMMBDXP->month), 1, 1, pf) || 1 != fread_function(&(pMMBDXP->day), 1, 1, pf)) { - fclose_function(pf); + fclose_and_nullify(&pMMBDXP->pfDataBase); return 1; } - if (1 != fread_function(&nRecords, 4, 1, pf)) + if (1 != fread_function(&nRecords32LowBits, 4, 1, pf)) { - fclose_function(pf); + fclose_and_nullify(&pMMBDXP->pfDataBase); return 1; } if (1 != fread_function(&offset_primera_fitxa, 2, 1, pf)) { - fclose_function(pf); + fclose_and_nullify(&pMMBDXP->pfDataBase); return 1; } pMMBDXP->year = (short)(1900 + variable_byte); reintenta_lectura_per_si_error_CreaCampBD_XP: - if (n_queixes_estructura_incorrecta > 0) + if (some_problems_when_reading > 0) { if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version)) { - offset_fals = offset_primera_fitxa; - if ((offset_primera_fitxa - 1) % 32) - { - for (offset_fals = (offset_primera_fitxa - 1); - !((offset_fals - 1) % 32); offset_fals--) - ; - } + offset_fals = + offset_primera_fitxa & (MM_FIRST_RECORD_OFFSET_TYPE)(~31); } } else offset_reintent = ftell_function(pf); - if (1 != fread_function(&ushort, 2, 1, pf) || + if (1 != fread_function(&two_bytes, 2, 1, pf) || 1 != fread_function(&(pMMBDXP->reserved_1), 2, 1, pf) || 1 != fread_function(&(pMMBDXP->transaction_flag), 1, 1, pf) || 1 != fread_function(&(pMMBDXP->encryption_flag), 1, 1, pf) || 1 != fread_function(&(pMMBDXP->dbf_on_a_LAN), 12, 1, pf)) { - fclose_function(pf); + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; + fclose_and_nullify(&pMMBDXP->pfDataBase); return 1; } if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version)) { - memcpy(&pMMBDXP->nRecords, &nRecords, 4); - memcpy(((char *)&pMMBDXP->nRecords) + 4, &pMMBDXP->dbf_on_a_LAN, 4); + GUInt32 nRecords32HighBits; + + // Getting 4 bytes of the 8 bytes variable + memcpy(&nRecords32HighBits, &pMMBDXP->dbf_on_a_LAN, 4); + + // Getting other 4 bytes of the 8 bytes variable + // The cast to GUInt64 of the high 32 bits is important to + // make sure the left bit shift is done correctly + pMMBDXP->nRecords = + ((GUInt64)nRecords32HighBits << 32) | nRecords32LowBits; } else - pMMBDXP->nRecords = nRecords; + pMMBDXP->nRecords = nRecords32LowBits; if (1 != fread_function(&(pMMBDXP->MDX_flag), 1, 1, pf) || 1 != fread_function(&(pMMBDXP->CharSet), 1, 1, pf) || 1 != fread_function(&(pMMBDXP->reserved_2), 2, 1, pf)) { - fclose_function(pf); + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; + fclose_and_nullify(&pMMBDXP->pfDataBase); return 1; } @@ -1213,25 +1248,27 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, if (pMMBDXP->CharSet == 0) { FILE_TYPE *f_cpg; + char charset_cpg[11]; strcpy(cpg_file, pMMBDXP->szFileName); - strcpy(cpg_file, reset_extension(cpg_file, "cpg")); + CPLStrlcpy(cpg_file, reset_extension(cpg_file, "cpg"), + sizeof(cpg_file)); f_cpg = fopen_function(cpg_file, "r"); if (f_cpg) { char *p; size_t read_bytes; fseek_function(f_cpg, 0L, SEEK_SET); - if (11 > (read_bytes = fread_function(local_message, 1, 10, f_cpg))) + if (11 > (read_bytes = fread_function(charset_cpg, 1, 10, f_cpg))) { - local_message[read_bytes] = '\0'; - p = strstr(local_message, "UTF-8"); + charset_cpg[read_bytes] = '\0'; + p = strstr(charset_cpg, "UTF-8"); if (p) pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF; - p = strstr(local_message, "UTF8"); + p = strstr(charset_cpg, "UTF8"); if (p) pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF; - p = strstr(local_message, "ISO-8859-1"); + p = strstr(charset_cpg, "ISO-8859-1"); if (p) pMMBDXP->CharSet = MM_JOC_CARAC_ANSI_DBASE; } @@ -1240,34 +1277,51 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, } if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version)) { - memcpy(&pMMBDXP->FirstRecordOffset, &offset_primera_fitxa, 2); - memcpy(((char *)&pMMBDXP->FirstRecordOffset) + 2, &pMMBDXP->reserved_2, - 2); + unsigned short FirstRecordOffsetLow16Bits; + unsigned short FirstRecordOffsetHigh16Bits; + + memcpy(&FirstRecordOffsetLow16Bits, &offset_primera_fitxa, 2); + memcpy(&FirstRecordOffsetHigh16Bits, &pMMBDXP->reserved_2, 2); - if (n_queixes_estructura_incorrecta > 0) + pMMBDXP->FirstRecordOffset = + ((GUInt32)FirstRecordOffsetHigh16Bits << 16) | + FirstRecordOffsetLow16Bits; + + if (some_problems_when_reading > 0) offset_fals = pMMBDXP->FirstRecordOffset; - memcpy(&pMMBDXP->BytesPerRecord, &ushort, 2); - memcpy(((char *)&pMMBDXP->BytesPerRecord) + 2, &pMMBDXP->reserved_1, 2); + memcpy(&FirstRecordOffsetLow16Bits, &two_bytes, 2); + memcpy(&FirstRecordOffsetHigh16Bits, &pMMBDXP->reserved_1, 2); + + pMMBDXP->BytesPerRecord = ((GUInt32)FirstRecordOffsetHigh16Bits << 16) | + FirstRecordOffsetLow16Bits; } else { pMMBDXP->FirstRecordOffset = offset_primera_fitxa; - pMMBDXP->BytesPerRecord = ushort; + pMMBDXP->BytesPerRecord = two_bytes; } /* ====== Record structure ========================= */ - if (n_queixes_estructura_incorrecta > 0) - pMMBDXP->nFields = (MM_EXT_DBF_N_FIELDS)(((offset_fals - 1) - 32) / 32); + if (some_problems_when_reading > 0) + { + if ((offset_fals - 1) - 32 < 0) + pMMBDXP->nFields = 0; + else + pMMBDXP->nFields = + (MM_EXT_DBF_N_FIELDS)(((offset_fals - 1) - 32) / 32); + } else { - MM_ACUMULATED_BYTES_TYPE_DBF bytes_acumulats = 1; + // There's a chance that bytes_acumulats could overflow if it's GUInt32. + // For that reason it's better to promote to GUInt64. + GUInt64 bytes_acumulats = 1; pMMBDXP->nFields = 0; fseek_function(pf, 0, SEEK_END); - if (32 < (ftell_function(pf) - 1)) + if (32 - 1 < ftell_function(pf)) { fseek_function(pf, 32, SEEK_SET); do @@ -1283,8 +1337,10 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, 1 != fread_function(&tretze_bytes, 3 + sizeof(bytes_per_camp), 1, pf)) { - free(pMMBDXP->pField); - fclose_function(pf); + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; + fclose_and_nullify(&pMMBDXP->pfDataBase); return 1; } if (bytes_per_camp == 0) @@ -1299,15 +1355,20 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, if (pMMBDXP->nFields != 0) { + free_function(pMMBDXP->pField); pMMBDXP->pField = MM_CreateAllFields(pMMBDXP->nFields); if (!pMMBDXP->pField) { - fclose_function(pf); + pMMBDXP->nFields = 0; + fclose_and_nullify(&pMMBDXP->pfDataBase); return 1; } } else + { + free_function(pMMBDXP->pField); pMMBDXP->pField = nullptr; + } fseek_function(pf, 32, SEEK_SET); for (nIField = 0; nIField < pMMBDXP->nFields; nIField++) @@ -1327,8 +1388,11 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, 1 != fread_function(&(pMMBDXP->pField[nIField].MDX_field_flag), 1, 1, pf)) { - free(pMMBDXP->pField); + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; fclose_function(pf); + pMMBDXP->pfDataBase = nullptr; return 1; } @@ -1345,14 +1409,20 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, { if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version)) { - free(pMMBDXP->pField); + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; fclose_function(pf); + pMMBDXP->pfDataBase = nullptr; return 1; } if (pMMBDXP->pField[nIField].FieldType != 'C') { - free(pMMBDXP->pField); + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; fclose_function(pf); + pMMBDXP->pfDataBase = nullptr; return 1; } @@ -1362,41 +1432,138 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, } if (nIField) - pMMBDXP->pField[nIField].AcumulatedBytes = - (pMMBDXP->pField[nIField - 1].AcumulatedBytes + + { + // To avoid overflow + if (pMMBDXP->pField[nIField - 1].AccumulatedBytes > + UINT32_MAX - pMMBDXP->pField[nIField - 1].BytesPerField) + { + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; + fclose_function(pf); + pMMBDXP->pfDataBase = nullptr; + return 1; + } + + pMMBDXP->pField[nIField].AccumulatedBytes = + (pMMBDXP->pField[nIField - 1].AccumulatedBytes + pMMBDXP->pField[nIField - 1].BytesPerField); + } else - pMMBDXP->pField[nIField].AcumulatedBytes = 1; + { + pMMBDXP->pField[nIField].AccumulatedBytes = 1; + } - for (j = 0; j < MM_NUM_IDIOMES_MD_MULTIDIOMA; j++) + if (pszRelFile) { - pMMBDXP->pField[nIField].Separator[j] = nullptr; + // Usually, in multilingual MiraMon metadata files, the main + // language is the default one and has no "_cat", "_spa", or + // "_eng" suffix after the keyword. So, to retrieve all + // languages in a multilingual file, first, we'll identify + // the one with no suffix "_cat", "_spa", or "_eng", and then the + // others. If one of them lacks a value, it gets the default value. + snprintf(section, sizeof(section), "TAULA_PRINCIPAL:%s", + pMMBDXP->pField[nIField].FieldName); + + // MM_DEF_LANGUAGE + pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section, + "descriptor"); + if (pszDesc) + { + CPLStrlcpy( + pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE], + pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); - if (pszRelFile) + free_function(pszDesc); + } + else + *pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE] = + '\0'; + + // MM_ENG_LANGUAGE + pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section, + "descriptor_eng"); + if (pszDesc) { - sprintf(section, "TAULA_PRINCIPAL:%s", - pMMBDXP->pField[nIField].FieldName); - pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section, - "descriptor_eng"); - if (pszDesc) + CPLStrlcpy( + pMMBDXP->pField[nIField].FieldDescription[MM_ENG_LANGUAGE], + pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); + + if (*pMMBDXP->pField[nIField] + .FieldDescription[MM_DEF_LANGUAGE] == '\0') { - MM_strnzcpy(pMMBDXP->pField[nIField].FieldDescription[j], - pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); - free_function(pszDesc); + CPLStrlcpy(pMMBDXP->pField[nIField] + .FieldDescription[MM_DEF_LANGUAGE], + pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); } - else + free_function(pszDesc); + } + else + { + // If there is no value descriptor_eng it's because it's the + // default one. So, it's taken from there. + CPLStrlcpy( + pMMBDXP->pField[nIField].FieldDescription[MM_ENG_LANGUAGE], + pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE], + MM_MAX_LON_DESCRIPCIO_CAMP_DBF); + } + + // MM_CAT_LANGUAGE + pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section, + "descriptor_cat"); + if (pszDesc) + { + CPLStrlcpy( + pMMBDXP->pField[nIField].FieldDescription[MM_CAT_LANGUAGE], + pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); + + if (*pMMBDXP->pField[nIField] + .FieldDescription[MM_DEF_LANGUAGE] == '\0') { - sprintf(section, "TAULA_PRINCIPAL:%s", - pMMBDXP->pField[nIField].FieldName); - pszDesc = MMReturnValueFromSectionINIFile( - pszRelFile, section, "descriptor"); - if (pszDesc) - MM_strnzcpy( - pMMBDXP->pField[nIField].FieldDescription[j], - pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); - pMMBDXP->pField[nIField].FieldDescription[j][0] = 0; - free_function(pszDesc); + CPLStrlcpy(pMMBDXP->pField[nIField] + .FieldDescription[MM_DEF_LANGUAGE], + pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); } + + free_function(pszDesc); + } + else + { + // If there is no value descriptor_cat it's because it's the + // default one. So, it's taken from there. + CPLStrlcpy( + pMMBDXP->pField[nIField].FieldDescription[MM_CAT_LANGUAGE], + pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE], + MM_MAX_LON_DESCRIPCIO_CAMP_DBF); + } + + // MM_SPA_LANGUAGE + pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section, + "descriptor_spa"); + if (pszDesc) + { + CPLStrlcpy( + pMMBDXP->pField[nIField].FieldDescription[MM_SPA_LANGUAGE], + pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); + + if (*pMMBDXP->pField[nIField] + .FieldDescription[MM_DEF_LANGUAGE] == '\0') + { + CPLStrlcpy(pMMBDXP->pField[nIField] + .FieldDescription[MM_DEF_LANGUAGE], + pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); + } + + free_function(pszDesc); + } + else + { + // If there is no value descriptor_spa it's because it's the + // default one. So, it's taken from there. + CPLStrlcpy( + pMMBDXP->pField[nIField].FieldDescription[MM_SPA_LANGUAGE], + pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE], + MM_MAX_LON_DESCRIPCIO_CAMP_DBF); } } } @@ -1406,19 +1573,44 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, if (pMMBDXP->BytesPerRecord) incoherent_record_size = TRUE; } - else if (pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField + - pMMBDXP->pField[pMMBDXP->nFields - 1].AcumulatedBytes > - pMMBDXP->BytesPerRecord) - incoherent_record_size = TRUE; + else + { + // To avoid overflow + if (pMMBDXP->pField[pMMBDXP->nFields - 1].AccumulatedBytes > + UINT32_MAX - pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField) + { + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; + fclose_function(pf); + pMMBDXP->pfDataBase = nullptr; + return 1; + } + if (pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField + + pMMBDXP->pField[pMMBDXP->nFields - 1].AccumulatedBytes > + pMMBDXP->BytesPerRecord) + incoherent_record_size = TRUE; + } if (incoherent_record_size) { - if (n_queixes_estructura_incorrecta == 0) + if (some_problems_when_reading == 0) { incoherent_record_size = FALSE; fseek_function(pf, offset_reintent, SEEK_SET); - n_queixes_estructura_incorrecta++; + some_problems_when_reading++; + /* Reset IdGraficField as it might no longer be valid */ + pMMBDXP->IdGraficField = 0; goto reintenta_lectura_per_si_error_CreaCampBD_XP; } + else + { + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; + fclose_function(pf); + pMMBDXP->pfDataBase = nullptr; + return 1; + } } offset_possible = 32 + 32 * (pMMBDXP->nFields) + 1; @@ -1438,15 +1630,18 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, offset_nom_camp >= offset_possible && offset_nom_camp < pMMBDXP->FirstRecordOffset) { - MM_strnzcpy(pMMBDXP->pField[nIField].ClassicalDBFFieldName, - pMMBDXP->pField[nIField].FieldName, - MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); + CPLStrlcpy(pMMBDXP->pField[nIField].ClassicalDBFFieldName, + pMMBDXP->pField[nIField].FieldName, + MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); fseek_function(pf, offset_nom_camp, SEEK_SET); if (1 != fread_function(pMMBDXP->pField[nIField].FieldName, mida_nom, 1, pf)) { - free(pMMBDXP->pField); + free_function(pMMBDXP->pField); + pMMBDXP->pField = nullptr; + pMMBDXP->nFields = 0; fclose_function(pf); + pMMBDXP->pfDataBase = nullptr; return 1; } pMMBDXP->pField[nIField].FieldName[mida_nom] = '\0'; @@ -1457,8 +1652,8 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, pszString = CPLRecode_function(pMMBDXP->pField[nIField].FieldName, CPL_ENC_ISO8859_1, CPL_ENC_UTF8); - MM_strnzcpy(pMMBDXP->pField[nIField].FieldName, pszString, - MM_MAX_LON_FIELD_NAME_DBF); + CPLStrlcpy(pMMBDXP->pField[nIField].FieldName, pszString, + MM_MAX_LON_FIELD_NAME_DBF); CPLFree_function(pszString); } else if (pMMBDXP->CharSet == MM_JOC_CARAC_OEM850_DBASE) @@ -1467,8 +1662,8 @@ int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, pszString = CPLRecode_function(pMMBDXP->pField[nIField].FieldName, CPL_ENC_ISO8859_1, CPL_ENC_UTF8); - MM_strnzcpy(pMMBDXP->pField[nIField].FieldName, pszString, - MM_MAX_LON_FIELD_NAME_DBF - 1); + CPLStrlcpy(pMMBDXP->pField[nIField].FieldName, pszString, + MM_MAX_LON_FIELD_NAME_DBF - 1); CPLFree_function(pszString); } } @@ -1515,7 +1710,9 @@ int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( strcat(camp->FieldName, "0"); for (i = 2; i < (size_t)10; i++) { - sprintf(camp->FieldName + strlen(camp->FieldName) - 1, "%u", i); + snprintf(camp->FieldName + strlen(camp->FieldName) - 1, + sizeof(camp->FieldName) - strlen(camp->FieldName) + 1, + "%u", i); for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) { if (bd_xp->pField + i_camp == camp) @@ -1538,7 +1735,9 @@ int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( strcat(camp->FieldName, "00"); for (i = 10; i < (size_t)100; i++) { - sprintf(camp->FieldName + strlen(camp->FieldName) - 2, "%u", i); + snprintf(camp->FieldName + strlen(camp->FieldName) - 2, + sizeof(camp->FieldName) - strlen(camp->FieldName) + 2, + "%u", i); for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) { if (bd_xp->pField + i_camp == camp) @@ -1561,8 +1760,10 @@ int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( strcat(camp->FieldName, "000"); for (i = 100; i < (size_t)256 + 2; i++) { - sprintf(camp->FieldName + strlen(camp->FieldName) - 3, "%u", - i); + snprintf(camp->FieldName + strlen(camp->FieldName) - 3, + sizeof(camp->FieldName) - strlen(camp->FieldName) + + 3, + "%u", i); for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) { if (bd_xp->pField + i_camp == camp) @@ -1606,9 +1807,11 @@ int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( if (strlen(camp->FieldDescription[0]) > MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i) camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0'; - //if (camp->FieldDescription[0] + strlen(camp->FieldDescription[0])) - sprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]), - " (%u)", i); + + snprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]), + sizeof(camp->FieldDescription[0]) - + strlen(camp->FieldDescription[0]), + " (%u)", i); for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) { if (bd_xp->pField + i_camp == camp) @@ -1632,8 +1835,10 @@ int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( for (i++; i < (size_t)256; i++) { //if (camp->FieldDescription[0] + strlen(camp->FieldDescription[0])) - sprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]), - " (%u)", i); + snprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]), + sizeof(camp->FieldDescription[0]) - + strlen(camp->FieldDescription[0]), + " (%u)", i); for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) { if (bd_xp->pField + i_camp == camp) @@ -1648,20 +1853,20 @@ int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( } // End of MM_ModifyFieldNameAndDescriptorIfPresentBD_XP() static int MM_DuplicateMultilingualString( - char *(cadena_final[MM_NUM_IDIOMES_MD_MULTIDIOMA]), - const char *const(cadena_inicial[MM_NUM_IDIOMES_MD_MULTIDIOMA])) + char *(szChain_final[MM_NUM_IDIOMES_MD_MULTIDIOMA]), + const char *const(szChain_inicial[MM_NUM_IDIOMES_MD_MULTIDIOMA])) { size_t i; for (i = 0; i < MM_NUM_IDIOMES_MD_MULTIDIOMA; i++) { - if (cadena_inicial[i]) + if (szChain_inicial[i]) { - if (nullptr == (cadena_final[i] = strdup(cadena_inicial[i]))) + if (nullptr == (szChain_final[i] = strdup(szChain_inicial[i]))) return 1; } else - cadena_final[i] = nullptr; + szChain_final[i] = nullptr; } return 0; } @@ -1679,44 +1884,31 @@ int MM_DuplicateFieldDBXP(struct MM_FIELD *camp_final, return 0; } -char *MM_strnzcpy(char *dest, const char *src, size_t maxlen) +#ifndef GDAL_COMPILATION +size_t CPLStrlcpy(char *pszDest, const char *pszSrc, size_t nDestSize) { - size_t i = 0; - if (!src || maxlen == 0) - { - *dest = '\0'; - return dest; - } + if (nDestSize == 0) + return strlen(pszSrc); - for (; i < maxlen - 1 && src[i] != '\0'; ++i) - { - dest[i] = src[i]; - } - dest[i] = '\0'; - - return dest; -} + char *pszDestIter = pszDest; + const char *pszSrcIter = pszSrc; -/* -char *MM_strnzcpy(char *dest, const char *src, size_t maxlen) -{ - size_t i; - if (!src) + --nDestSize; + while (nDestSize != 0 && *pszSrcIter != '\0') { - *dest = '\0'; - return dest; + *pszDestIter = *pszSrcIter; + ++pszDestIter; + ++pszSrcIter; + --nDestSize; } + *pszDestIter = '\0'; + return pszSrcIter - pszSrc + strlen(pszSrcIter); +} +#endif - if (!maxlen) - i = 0; - else - strncpy(dest, src, i = maxlen - 1); - - dest[i] = '\0'; - return dest; -}*/ - -char *MM_oemansi_n(char *szcadena, size_t n_bytes) +// If n_bytes==SIZE_MAX, the parameter is ignored ant, then, +// it's assumed that szszChain is NUL terminated +char *MM_oemansi_n(char *szszChain, size_t n_bytes) { size_t u_i; unsigned char *punter_bait; @@ -1731,9 +1923,9 @@ char *MM_oemansi_n(char *szcadena, size_t n_bytes) 164, 164, 166, 204, 164, 211, 223, 212, 210, 245, 213, 181, 254, 222, 218, 219, 217, 253, 221, 175, 180, 173, 177, 164, 190, 182, 167, 247, 184, 176, 168, 183, 185, 179, 178, 164, 183}; - if (n_bytes == USHRT_MAX) + if (n_bytes == SIZE_MAX) { - for (punter_bait = (unsigned char *)szcadena; *punter_bait; + for (punter_bait = (unsigned char *)szszChain; *punter_bait; punter_bait++) { if (*punter_bait > 127) @@ -1742,27 +1934,26 @@ char *MM_oemansi_n(char *szcadena, size_t n_bytes) } else { - for (u_i = 0, punter_bait = (unsigned char *)szcadena; u_i < n_bytes; + for (u_i = 0, punter_bait = (unsigned char *)szszChain; u_i < n_bytes; punter_bait++, u_i++) { if (*punter_bait > 127) *punter_bait = t_oemansi[*punter_bait - 128]; } } - return szcadena; + return szszChain; } -char *MM_oemansi(char *szcadena) +char *MM_oemansi(char *szszChain) { - return MM_oemansi_n(szcadena, USHRT_MAX); + return MM_oemansi_n(szszChain, SIZE_MAX); } -static MM_BOOLEAN MM_FillFieldDB_XP(struct MM_FIELD *camp, - const char *FieldName, - const char *FieldDescription, - char FieldType, - MM_BYTES_PER_FIELD_TYPE_DBF BytesPerField, - MM_BYTE DecimalsIfFloat) +static MM_BOOLEAN MM_FillFieldDB_XP( + struct MM_FIELD *camp, const char *FieldName, + const char *FieldDescriptionEng, const char *FieldDescriptionCat, + const char *FieldDescriptionSpa, char FieldType, + MM_BYTES_PER_FIELD_TYPE_DBF BytesPerField, MM_BYTE DecimalsIfFloat) { char nom_temp[MM_MAX_LON_FIELD_NAME_DBF]; int retorn_valida_nom_camp; @@ -1772,23 +1963,43 @@ static MM_BOOLEAN MM_FillFieldDB_XP(struct MM_FIELD *camp, retorn_valida_nom_camp = MM_ISExtendedNameBD_XP(FieldName); if (retorn_valida_nom_camp == MM_DBF_NAME_NO_VALID) return FALSE; - MM_strnzcpy(camp->FieldName, FieldName, MM_MAX_LON_FIELD_NAME_DBF); + CPLStrlcpy(camp->FieldName, FieldName, MM_MAX_LON_FIELD_NAME_DBF); if (retorn_valida_nom_camp == MM_VALID_EXTENDED_DBF_NAME) { MM_CalculateBytesExtendedFieldName(camp); - MM_strnzcpy(nom_temp, FieldName, MM_MAX_LON_FIELD_NAME_DBF); + CPLStrlcpy(nom_temp, FieldName, MM_MAX_LON_FIELD_NAME_DBF); MM_ReturnValidClassicDBFFieldName(nom_temp); nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF] = '\0'; - MM_strnzcpy(camp->ClassicalDBFFieldName, nom_temp, - MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); + CPLStrlcpy(camp->ClassicalDBFFieldName, nom_temp, + MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); } } - if (FieldDescription) - strcpy(camp->FieldDescription[0], FieldDescription); + if (FieldDescriptionEng) + CPLStrlcpy(camp->FieldDescription[MM_DEF_LANGUAGE], FieldDescriptionEng, + sizeof(camp->FieldDescription[MM_DEF_LANGUAGE])); + else + strcpy(camp->FieldDescription[MM_DEF_LANGUAGE], "\0"); + + if (FieldDescriptionEng) + CPLStrlcpy(camp->FieldDescription[MM_ENG_LANGUAGE], FieldDescriptionEng, + sizeof(camp->FieldDescription[MM_ENG_LANGUAGE])); + else + strcpy(camp->FieldDescription[MM_ENG_LANGUAGE], "\0"); + + if (FieldDescriptionCat) + CPLStrlcpy(camp->FieldDescription[MM_CAT_LANGUAGE], FieldDescriptionCat, + sizeof(camp->FieldDescription[MM_CAT_LANGUAGE])); else - strcpy(camp->FieldDescription[0], "\0"); + strcpy(camp->FieldDescription[MM_CAT_LANGUAGE], "\0"); + + if (FieldDescriptionSpa) + CPLStrlcpy(camp->FieldDescription[MM_SPA_LANGUAGE], FieldDescriptionSpa, + sizeof(camp->FieldDescription[MM_SPA_LANGUAGE])); + else + strcpy(camp->FieldDescription[MM_SPA_LANGUAGE], "\0"); + camp->FieldType = FieldType; camp->DecimalsIfFloat = DecimalsIfFloat; camp->BytesPerField = BytesPerField; @@ -1796,42 +2007,49 @@ static MM_BOOLEAN MM_FillFieldDB_XP(struct MM_FIELD *camp, } size_t MM_DefineFirstPolygonFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp, - MM_BYTE n_decimals) + MM_BYTE n_perimeter_decimals, + MM_BYTE n_area_decimals_decimals) { MM_EXT_DBF_N_FIELDS i_camp = 0; - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, - szInternalGraphicIdentifierEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); + MM_FillFieldDB_XP( + bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, + szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat, + szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0); bd_xp->IdGraficField = 0; (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte, - szNumberOfVerticesEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); + szNumberOfVerticesEng, szNumberOfVerticesCat, + szNumberOfVerticesSpa, 'N', MM_MIN_WIDTH_N_VERTEXS, 0); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampPerimetreDefecte, - szPerimeterOfThePolygonEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, n_decimals); + szPerimeterOfThePolygonEng, szPerimeterOfThePolygonCat, + szPerimeterOfThePolygonSpa, 'N', MM_MIN_WIDTH_LONG, + n_perimeter_decimals); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_PERIMETRE; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampAreaDefecte, - szAreaOfThePolygonEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, - n_decimals); + szAreaOfThePolygonEng, szAreaOfThePolygonCat, + szAreaOfThePolygonSpa, 'N', MM_MIN_WIDTH_AREA, + n_area_decimals_decimals); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_AREA; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNArcsDefecte, - szNumberOfArcsEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); + szNumberOfArcsEng, szNumberOfArcsCat, szNumberOfArcsSpa, + 'N', MM_MIN_WIDTH_N_ARCS, 0); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_ARCS; i_camp++; - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNPoligonsDefecte, - szNumberOfElementaryPolygonsEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); + MM_FillFieldDB_XP( + bd_xp->pField + i_camp, szMMNomCampNPoligonsDefecte, + szNumberOfElementaryPolygonsEng, szNumberOfElementaryPolygonsCat, + szNumberOfElementaryPolygonsSpa, 'N', MM_MIN_WIDTH_N_POLIG, 0); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_POLIG; i_camp++; @@ -1844,31 +2062,35 @@ size_t MM_DefineFirstArcFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp, MM_EXT_DBF_N_FIELDS i_camp; i_camp = 0; - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, - szInternalGraphicIdentifierEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); + MM_FillFieldDB_XP( + bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, + szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat, + szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0); bd_xp->IdGraficField = 0; (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte, - szNumberOfVerticesEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); + szNumberOfVerticesEng, szNumberOfVerticesCat, + szNumberOfVerticesSpa, 'N', MM_MIN_WIDTH_N_VERTEXS, 0); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampLongitudArcDefecte, - szLenghtOfAarcEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, - n_decimals); + szLengthOfAarcEng, szLengthOfAarcCat, szLengthOfAarcSpa, + 'N', MM_MIN_WIDTH_LONG, n_decimals); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_LONG_ARC; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeIniDefecte, - szInitialNodeEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); + szInitialNodeEng, szInitialNodeCat, szInitialNodeSpa, 'N', + MM_MIN_WIDTH_INITIAL_NODE, 0); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_INI; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeFiDefecte, - szFinalNodeEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); + szFinalNodeEng, szFinalNodeCat, szFinalNodeSpa, 'N', + MM_MIN_WIDTH_FINAL_NODE, 0); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_FI; i_camp++; @@ -1881,21 +2103,23 @@ size_t MM_DefineFirstNodeFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp) i_camp = 0; - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, - szInternalGraphicIdentifierEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); + MM_FillFieldDB_XP( + bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, + szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat, + szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0); bd_xp->IdGraficField = 0; (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampArcsANodeDefecte, - szNumberOfArcsToNodeEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, + szNumberOfArcsToNodeEng, szNumberOfArcsToNodeCat, + szNumberOfArcsToNodeSpa, 'N', MM_MIN_WIDTH_ARCS_TO_NODE, 0); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ARCS_A_NOD; i_camp++; MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampTipusNodeDefecte, - szNodeTypeEng, 'N', 1, 0); + szNodeTypeEng, szNodeTypeCat, szNodeTypeSpa, 'N', 1, 0); (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_TIPUS_NODE; i_camp++; @@ -1906,9 +2130,10 @@ size_t MM_DefineFirstPointFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp) { size_t i_camp = 0; - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, - szInternalGraphicIdentifierEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); + MM_FillFieldDB_XP( + bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, + szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat, + szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0); bd_xp->IdGraficField = 0; (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC; i_camp++; @@ -1916,42 +2141,144 @@ size_t MM_DefineFirstPointFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp) return i_camp; } -static int MM_SprintfDoubleWidth(char *cadena, int amplada, int n_decimals, +/* + Controlling the number of significant figures is often crucial in science + and technology, and the best option when nothing is known about the number + to be printed (if it is really small (near to 0), or very large), and + allows a good return (the same value) into memory when re-read from a text + file with scanf() functions. + If you need to print 0.00000000000000000000000000000000000000001 with %f + you will need an extremely large string. If you print 1980.45 with %E you + obtain 1.98045E+003, needing more space, and not being easy to interpret + for some people. Moreover, “normal†users do not want to see 1.0 as + 1.0E+000 or 1.0E+00. The choice of the format specifier, and the integer + to be passed to the ‘*’ is not always easy, + and MM_SprintfDoubleSignifFigures() automatically uses a “fair†notation + whenever it is possible, resulting in shorter strings, being them under + control (the maximum length of the resulting string is always known). + Moreover, it avoids some failures in compilers not expecting + NAN or INF values. +*/ +int MM_SprintfDoubleSignifFigures(char *szChain, size_t size_szChain, + int nSignifFigures, double dfRealValue) +{ + double VALOR_LIMIT_PRINT_IN_FORMAT_E; + double VALOR_TOO_SMALL_TO_PRINT_f; + int retorn, exponent; + char *ptr; + +#define N_POWERS MM_MAX_XS_DOUBLE + + /* This expression ensures that no garbage is written in + the non-significant digits of the integer part, i.e., requesting 9E20 + with 16 significant digits does not print 90000000000000004905, where + "4905" is garbage generated by the print call with such a large value + and "%.16f", but rather writes 9.000000000000000E+20. + At the same time, it ensures that 9000 requested with 4 significant + digits is written as 9000 and that requested with 5 significant digits + is written as 9000.0, but that requested with 3 significant digits is + written as 9.00E+03. */ + double potencies_de_10[N_POWERS] = { + 1E+1, 1E+2, 1E+3, 1E+4, 1E+5, 1E+6, 1E+7, 1E+8, 1E+9, + 1E+10, 1E+11, 1E+12, 1E+13, 1E+14, 1E+15, 1E+16, 1E+17}; + + /* This expression ensures that -9E-7 requested with 11 significant digits + still uses "natural" notation and gives -0.0000009000000000, which still + fits exactly within the 20 characters of a 'N' field in dBASE, while + requested with 12 significant digits jumps to exponential notation and + writes -9.00000000000E-07, which also fits (in this case, comfortably) + within the 20 characters of dBASE. + The expression could be replaced by: pow(10,-max(0,20-2-signif_digits)); */ + double fraccions_de_10[N_POWERS + 1] = { + 1E-1, 1E-2, 1E-3, 1E-4, 1E-5, 1E-6, 1E-7, 1E-8, 1E-9, + 1E-10, 1E-11, 1E-12, 1E-13, 1E-14, 1E-15, 1E-16, 1E-17, 1E-18}; + + if (!szChain) + return 0; + + if (size_szChain < 3) + return 0; + + memset(szChain, '\0', size_szChain); + + if (MM_IsNANDouble(dfRealValue)) + return snprintf(szChain, size_szChain, "NAN"); + + if (MM_IsDoubleInfinite(dfRealValue)) + return snprintf(szChain, size_szChain, "INF"); + + if (dfRealValue == 0.0) + return snprintf(szChain, size_szChain, "%.*f", nSignifFigures, 0.0); + + if (nSignifFigures < 1) + return snprintf(szChain, size_szChain, "0.0"); + + if (nSignifFigures > N_POWERS) + nSignifFigures = N_POWERS; + + retorn = snprintf(szChain, size_szChain, "%.*E", nSignifFigures - 1, + dfRealValue); + + VALOR_LIMIT_PRINT_IN_FORMAT_E = potencies_de_10[nSignifFigures - 1]; + VALOR_TOO_SMALL_TO_PRINT_f = + fraccions_de_10[MM_MAX_XS_DOUBLE - nSignifFigures]; + + if (dfRealValue > VALOR_LIMIT_PRINT_IN_FORMAT_E || + dfRealValue < -VALOR_LIMIT_PRINT_IN_FORMAT_E || + (dfRealValue < VALOR_TOO_SMALL_TO_PRINT_f && + dfRealValue > -VALOR_TOO_SMALL_TO_PRINT_f)) + return retorn; + + ptr = strchr(szChain, 'E'); + if (!ptr) + return 0; + exponent = atoi(ptr + 1); + + return sprintf(szChain, "%.*f", + (nSignifFigures - exponent - 1) > 0 + ? (nSignifFigures - exponent - 1) + : 0, + dfRealValue); +#undef N_POWERS +} // End of SprintfDoubleXifSignif() + +static int MM_SprintfDoubleWidth(char *szChain, size_t szChain_size, + int amplada, int n_decimals, double valor_double, MM_BOOLEAN *Error_sprintf_n_decimals) { -#define VALOR_LIMIT_IMPRIMIR_EN_FORMAT_E 1E+17 -#define VALOR_MASSA_PETIT_PER_IMPRIMIR_f 1E-17 - char cadena_treball[MM_CARACTERS_DOUBLE + 1]; +#define VALOR_LIMIT_PRINT_IN_FORMAT_E 1E+17 +#define VALOR_TOO_SMALL_TO_PRINT_f 1E-17 + char szChain_treball[MM_CHARACTERS_DOUBLE + 1]; int retorn_printf; if (MM_IsNANDouble(valor_double)) { if (amplada < 3) { - *cadena = *MM_EmptyString; + *szChain = *MM_EmptyString; return EOF; } - return sprintf(cadena, "NAN"); + return snprintf(szChain, szChain_size, "NAN"); } - if (MM_IsDoubleInfinit(valor_double)) + if (MM_IsDoubleInfinite(valor_double)) { if (amplada < 3) { - *cadena = *MM_EmptyString; + *szChain = *MM_EmptyString; return EOF; } - return sprintf(cadena, "INF"); + return snprintf(szChain, szChain_size, "INF"); } *Error_sprintf_n_decimals = FALSE; if (valor_double == 0) { - retorn_printf = - sprintf(cadena_treball, "%*.*f", amplada, n_decimals, valor_double); - if (retorn_printf == EOF) + retorn_printf = snprintf(szChain_treball, sizeof(szChain_treball), + "%*.*f", amplada, n_decimals, valor_double); + if (retorn_printf >= (int)sizeof(szChain_treball)) { - *cadena = *MM_EmptyString; + *szChain = *MM_EmptyString; return retorn_printf; } @@ -1960,30 +2287,31 @@ static int MM_SprintfDoubleWidth(char *cadena, int amplada, int n_decimals, int escurcament = retorn_printf - amplada; if (escurcament > n_decimals) { - *cadena = *MM_EmptyString; + *szChain = *MM_EmptyString; return EOF; } *Error_sprintf_n_decimals = TRUE; n_decimals = n_decimals - escurcament; - retorn_printf = - sprintf(cadena, "%*.*f", amplada, n_decimals, valor_double); + retorn_printf = snprintf(szChain, szChain_size, "%*.*f", amplada, + n_decimals, valor_double); } else - strcpy(cadena, cadena_treball); + CPLStrlcpy(szChain, szChain_treball, szChain_size); return retorn_printf; } - if (valor_double > VALOR_LIMIT_IMPRIMIR_EN_FORMAT_E || - valor_double < -VALOR_LIMIT_IMPRIMIR_EN_FORMAT_E || - (valor_double < VALOR_MASSA_PETIT_PER_IMPRIMIR_f && - valor_double > -VALOR_MASSA_PETIT_PER_IMPRIMIR_f)) + if (valor_double > VALOR_LIMIT_PRINT_IN_FORMAT_E || + valor_double < -VALOR_LIMIT_PRINT_IN_FORMAT_E || + (valor_double < VALOR_TOO_SMALL_TO_PRINT_f && + valor_double > -VALOR_TOO_SMALL_TO_PRINT_f)) { - retorn_printf = - sprintf(cadena_treball, "%*.*E", amplada, n_decimals, valor_double); - if (retorn_printf == EOF) + retorn_printf = snprintf(szChain_treball, sizeof(szChain_treball), + "%*.*E", amplada, n_decimals, valor_double); + + if (retorn_printf >= (int)sizeof(szChain_treball)) { - *cadena = *MM_EmptyString; + *szChain = *MM_EmptyString; return retorn_printf; } if (retorn_printf > amplada) @@ -1991,25 +2319,26 @@ static int MM_SprintfDoubleWidth(char *cadena, int amplada, int n_decimals, int escurcament = retorn_printf - amplada; if (escurcament > n_decimals) { - *cadena = *MM_EmptyString; + *szChain = *MM_EmptyString; return EOF; } *Error_sprintf_n_decimals = TRUE; n_decimals = n_decimals - escurcament; - retorn_printf = - sprintf(cadena, "%*.*E", amplada, n_decimals, valor_double); + retorn_printf = snprintf(szChain, szChain_size, "%*.*E", amplada, + n_decimals, valor_double); } else - strcpy(cadena, cadena_treball); + CPLStrlcpy(szChain, szChain_treball, szChain_size); return retorn_printf; } - retorn_printf = - sprintf(cadena_treball, "%*.*f", amplada, n_decimals, valor_double); - if (retorn_printf == EOF) + retorn_printf = snprintf(szChain_treball, sizeof(szChain_treball), "%*.*f", + amplada, n_decimals, valor_double); + + if (retorn_printf >= (int)sizeof(szChain_treball)) { - *cadena = *MM_EmptyString; + *szChain = *MM_EmptyString; return retorn_printf; } @@ -2018,58 +2347,66 @@ static int MM_SprintfDoubleWidth(char *cadena, int amplada, int n_decimals, int escurcament = retorn_printf - amplada; if (escurcament > n_decimals) { - *cadena = *MM_EmptyString; + *szChain = *MM_EmptyString; return EOF; } *Error_sprintf_n_decimals = TRUE; n_decimals = n_decimals - escurcament; - retorn_printf = - sprintf(cadena, "%*.*f", amplada, n_decimals, valor_double); + retorn_printf = snprintf(szChain, szChain_size, "%*.*f", amplada, + n_decimals, valor_double); } else - strcpy(cadena, cadena_treball); + CPLStrlcpy(szChain, szChain_treball, szChain_size); return retorn_printf; -#undef VALOR_LIMIT_IMPRIMIR_EN_FORMAT_E -#undef VALOR_MASSA_PETIT_PER_IMPRIMIR_f +#undef VALOR_LIMIT_PRINT_IN_FORMAT_E +#undef VALOR_TOO_SMALL_TO_PRINT_f } // End of MM_SprintfDoubleWidth() -static MM_BOOLEAN MM_EmptyString_function(const char *cadena) +static MM_BOOLEAN MM_EmptyString_function(const char *szChain) { - char *ptr; + const char *ptr = szChain; - for (ptr = (char *)cadena; *ptr; ptr++) + for (; *ptr; ptr++) + { if (*ptr != ' ' && *ptr != '\t') + { return FALSE; + } + } return TRUE; } int MM_SecureCopyStringFieldValue(char **pszStringDst, const char *pszStringSrc, - MM_EXT_DBF_N_FIELDS *nStringCurrentLenght) + MM_EXT_DBF_N_FIELDS *nStringCurrentLength) { + if (!pszStringSrc) { - if (1 >= *nStringCurrentLenght) + if (1 >= *nStringCurrentLength) { - (*pszStringDst) = realloc_function(*pszStringDst, 2); - if (!(*pszStringDst)) + void *new_ptr = realloc_function(*pszStringDst, 2); + if (!new_ptr) return 1; - *nStringCurrentLenght = (MM_EXT_DBF_N_FIELDS)2; + *pszStringDst = new_ptr; + *nStringCurrentLength = (MM_EXT_DBF_N_FIELDS)2; } strcpy(*pszStringDst, "\0"); return 0; } - if (strlen(pszStringSrc) >= *nStringCurrentLenght) + if (strlen(pszStringSrc) >= *nStringCurrentLength) { - (*pszStringDst) = + void *new_ptr = realloc_function(*pszStringDst, strlen(pszStringSrc) + 1); - if (!(*pszStringDst)) + if (!new_ptr) return 1; - *nStringCurrentLenght = (MM_EXT_DBF_N_FIELDS)(strlen(pszStringSrc) + 1); + (*pszStringDst) = new_ptr; + *nStringCurrentLength = (MM_EXT_DBF_N_FIELDS)(strlen(pszStringSrc) + 1); } + strcpy(*pszStringDst, pszStringSrc); return 0; } @@ -2096,13 +2433,13 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, if (data_base_XP->nRecords != 0) { - l_glop1 = data_base_XP->pField[nIField].AcumulatedBytes; + l_glop1 = data_base_XP->pField[nIField].AccumulatedBytes; i_glop2 = l_glop1 + data_base_XP->pField[nIField].BytesPerField; if (nIField == data_base_XP->nFields - 1) l_glop2 = 0; else l_glop2 = data_base_XP->BytesPerRecord - - data_base_XP->pField[nIField + 1].AcumulatedBytes; + data_base_XP->pField[nIField + 1].AccumulatedBytes; if ((record = calloc_function((size_t)data_base_XP->BytesPerRecord)) == nullptr) @@ -2118,14 +2455,8 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, memset(whites, ' ', nNewWidth); nfitx = data_base_XP->nRecords; - -#ifdef _MSC_VER -#pragma warning(disable : 4127) -#endif - for (i_reg = (canvi_amplada < 0 ? 0 : nfitx - 1); TRUE;) -#ifdef _MSC_VER -#pragma warning(default : 4127) -#endif + i_reg = (canvi_amplada < 0 ? 0 : nfitx - 1); + while (TRUE) { if (0 != fseek_function(data_base_XP->pfDataBase, data_base_XP->FirstRecordOffset + @@ -2133,8 +2464,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, data_base_XP->BytesPerRecord, SEEK_SET)) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } @@ -2142,8 +2472,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, if (1 != fread_function(record, data_base_XP->BytesPerRecord, 1, data_base_XP->pfDataBase)) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } @@ -2156,8 +2485,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, canvi_amplada), SEEK_SET)) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } @@ -2165,8 +2493,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, if (1 != fwrite_function(record, l_glop1, 1, data_base_XP->pfDataBase)) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } @@ -2184,8 +2511,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, if (1 != retorn_fwrite) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } @@ -2216,27 +2542,21 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, .BytesPerField, 1, data_base_XP->pfDataBase)) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } } else if (canvi_amplada < 0) { - -#ifdef _MSC_VER -#pragma warning(disable : 4127) -#endif - for (j = (GInt32)(l_glop1 + - (data_base_XP->pField[nIField] - .BytesPerField - - 1)); - TRUE; j--) -#ifdef _MSC_VER -#pragma warning(default : 4127) -#endif + j = (GInt32)(l_glop1 + + (data_base_XP->pField[nIField] + .BytesPerField - + 1)); + while (TRUE) { + j--; + if (j < (GInt32)l_glop1 || record[j] == ' ') { j++; @@ -2256,8 +2576,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, data_base_XP->pfDataBase); if (1 != retorn_fwrite) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } @@ -2267,16 +2586,16 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, { double valor; char *sz_valor; + size_t sz_valor_size = + max_function( + nNewWidth, + data_base_XP->pField[nIField].BytesPerField) + + 1; - if ((sz_valor = calloc_function( - max_function(nNewWidth, - data_base_XP->pField[nIField] - .BytesPerField) + - 1)) == + if ((sz_valor = calloc_function(sz_valor_size)) == nullptr) // Sumo 1 per poder posar-hi el \0 { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } @@ -2296,7 +2615,8 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, else { MM_SprintfDoubleWidth( - sz_valor, nNewWidth, nNewPrecision, valor, + sz_valor, sz_valor_size, nNewWidth, + nNewPrecision, valor, &error_sprintf_n_decimals); } @@ -2305,8 +2625,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, data_base_XP->pfDataBase); if (1 != retorn_fwrite) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); free_function(sz_valor); return 1; @@ -2320,8 +2639,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, data_base_XP->pfDataBase); if (1 != retorn_fwrite) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); free_function(sz_valor); return 1; @@ -2341,8 +2659,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, data_base_XP->pfDataBase); if (1 != retorn_fwrite) { - if (whites) - free_function(whites); + free_function(whites); free_function(record); return 1; } @@ -2362,8 +2679,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, } } - if (whites) - free_function(whites); + free_function(whites); free_function(record); retorn_TruncaFitxer = TruncateFile_function( @@ -2382,7 +2698,7 @@ int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, data_base_XP->BytesPerRecord += canvi_amplada; for (i_camp = (MM_EXT_DBF_N_FIELDS)(nIField + 1); i_camp < data_base_XP->nFields; i_camp++) - data_base_XP->pField[i_camp].AcumulatedBytes += canvi_amplada; + data_base_XP->pField[i_camp].AccumulatedBytes += canvi_amplada; } data_base_XP->pField[nIField].DecimalsIfFloat = nNewPrecision; @@ -2432,13 +2748,22 @@ int MM_GetArcHeights(double *coord_z, FILE_TYPE *pF, MM_N_VERTICES_TYPE n_vrt, for (i_vrt = 0; i_vrt < n_vrt; i_vrt++) coord_z[i_vrt] = MM_NODATA_COORD_Z; + if (pZDescription->nZCount == INT_MIN) + return 0; tipus = MM_ARC_HEIGHT_TYPE(pZDescription->nZCount); n_alcada = MM_ARC_N_HEIGHTS(pZDescription->nZCount); if (n_vrt == 0 || n_alcada == 0) return 0; if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX) + { + if (n_vrt > (unsigned)(INT_MAX / n_alcada)) + { + MMCPLError(CE_Failure, CPLE_OutOfMemory, "Integer overflow"); + return 1; + } n_h_total = (MM_N_HEIGHT_TYPE)n_vrt * n_alcada; + } else n_h_total = n_alcada; @@ -2446,10 +2771,10 @@ int MM_GetArcHeights(double *coord_z, FILE_TYPE *pF, MM_N_VERTICES_TYPE n_vrt, palcada = local_CinquantaAlcades; else { - if (MMCheckSize_t(n_vrt * sizeof(double) * n_alcada, 1)) + if (MMCheckSize_t(n_h_total, sizeof(double))) return 1; - if (nullptr == (palcada = alcada = calloc_function( - (size_t)n_vrt * sizeof(double) * n_alcada))) + if (nullptr == (palcada = alcada = calloc_function((size_t)n_h_total * + sizeof(double)))) return 1; } @@ -2498,37 +2823,29 @@ int MM_GetArcHeights(double *coord_z, FILE_TYPE *pF, MM_N_VERTICES_TYPE n_vrt, } // End of MM_GetArcHeights() static char *MM_l_RemoveWhitespacesFromEndOfString(char *punter, - size_t l_cadena) + size_t l_szChain) { - int longitud_cadena = (int)l_cadena; - if (longitud_cadena-- == 0) - return punter; - - if (punter[longitud_cadena] != ' ' && punter[longitud_cadena] != '\t') - return punter; - longitud_cadena--; - - while (longitud_cadena > -1) + size_t longitud_szChain = l_szChain; + while (longitud_szChain > 0) { - if (punter[longitud_cadena] != ' ' && punter[longitud_cadena] != '\t') + longitud_szChain--; + if (punter[longitud_szChain] != ' ' && punter[longitud_szChain] != '\t') { break; } - longitud_cadena--; + punter[longitud_szChain] = '\0'; } - - punter[++longitud_cadena] = '\0'; return punter; } -char *MM_RemoveInitial_and_FinalQuotationMarks(char *cadena) +char *MM_RemoveInitial_and_FinalQuotationMarks(char *szChain) { char *ptr1, *ptr2; char cometa = '"'; - if (*cadena == cometa) + if (*szChain == cometa) { - ptr1 = cadena; + ptr1 = szChain; ptr2 = ptr1 + 1; if (*ptr2) { @@ -2544,23 +2861,23 @@ char *MM_RemoveInitial_and_FinalQuotationMarks(char *cadena) *ptr1 = 0; } } - return cadena; + return szChain; } /* End of MM_RemoveInitial_and_FinalQuotationMarks() */ -char *MM_RemoveLeadingWhitespaceOfString(char *cadena) +char *MM_RemoveLeadingWhitespaceOfString(char *szChain) { char *ptr; char *ptr2; - if (cadena == nullptr) - return cadena; + if (szChain == nullptr) + return szChain; - for (ptr = cadena; *ptr && (*ptr == ' ' || *ptr == '\t'); ptr++) + for (ptr = szChain; *ptr && (*ptr == ' ' || *ptr == '\t'); ptr++) continue; - if (ptr != cadena) + if (ptr != szChain) { - ptr2 = cadena; + ptr2 = szChain; while (*ptr) { *ptr2 = *ptr; @@ -2569,28 +2886,23 @@ char *MM_RemoveLeadingWhitespaceOfString(char *cadena) } *ptr2 = 0; } - return cadena; + return szChain; } char *MM_RemoveWhitespacesFromEndOfString(char *str) { - const char *s; - if (str == nullptr) return str; - - for (s = str; *s; ++s) - continue; - return MM_l_RemoveWhitespacesFromEndOfString(str, (s - str)); + return MM_l_RemoveWhitespacesFromEndOfString(str, strlen(str)); } -struct MM_ID_GRAFIC_MULTIPLE_RECORD * -MMCreateExtendedDBFIndex(FILE_TYPE *f, MM_EXT_DBF_N_RECORDS nNumberOfRecords, - MM_FIRST_RECORD_OFFSET_TYPE offset_1era, - MM_ACUMULATED_BYTES_TYPE_DBF bytes_per_fitxa, - MM_ACUMULATED_BYTES_TYPE_DBF bytes_acumulats_id_grafic, - MM_BYTES_PER_FIELD_TYPE_DBF bytes_id_grafic, - MM_BOOLEAN *isListField, MM_EXT_DBF_N_RECORDS *nMaxN) +struct MM_ID_GRAFIC_MULTIPLE_RECORD *MMCreateExtendedDBFIndex( + FILE_TYPE *f, MM_EXT_DBF_N_RECORDS nNumberOfRecords, + MM_FIRST_RECORD_OFFSET_TYPE offset_1era, + MM_ACCUMULATED_BYTES_TYPE_DBF bytes_per_fitxa, + MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats_id_grafic, + MM_BYTES_PER_FIELD_TYPE_DBF bytes_id_grafic, MM_BOOLEAN *isListField, + MM_EXT_DBF_N_RECORDS *nMaxN) { struct MM_ID_GRAFIC_MULTIPLE_RECORD *id; MM_EXT_DBF_N_RECORDS i_dbf; @@ -2604,14 +2916,20 @@ MMCreateExtendedDBFIndex(FILE_TYPE *f, MM_EXT_DBF_N_RECORDS nNumberOfRecords, if (!nNumberOfRecords) return nullptr; // No elements to read - if (MMCheckSize_t(nNumberOfRecords * sizeof(*id), 1)) + if (MMCheckSize_t(nNumberOfRecords, sizeof(*id))) return nullptr; if (nullptr == (id = (struct MM_ID_GRAFIC_MULTIPLE_RECORD *)calloc_function( (size_t)nNumberOfRecords * sizeof(*id)))) return nullptr; - if (MMCheckSize_t(bytes_id_grafic + 1, 1)) + if (bytes_id_grafic == UINT32_MAX) + { + free_function(id); + MMCPLError(CE_Failure, CPLE_OutOfMemory, + "Overflow in bytes_id_graphic"); return nullptr; + } + if (nullptr == (fitxa = (char *)calloc_function((size_t)bytes_id_grafic + 1))) { @@ -2642,13 +2960,7 @@ MMCreateExtendedDBFIndex(FILE_TYPE *f, MM_EXT_DBF_N_RECORDS nNumberOfRecords, id_grafic < 0); i = 0; -#ifdef _MSC_VER -#pragma warning(disable : 4127) -#endif while (TRUE) -#ifdef _MSC_VER -#pragma warning(default : 4127) -#endif { if (i > id_grafic) { diff --git a/ogr/ogrsf_frmts/miramon/mm_gdal_functions.c.bak b/ogr/ogrsf_frmts/miramon/mm_gdal_functions.c.bak deleted file mode 100644 index 193b66ab3763..000000000000 --- a/ogr/ogrsf_frmts/miramon/mm_gdal_functions.c.bak +++ /dev/null @@ -1,2695 +0,0 @@ -/****************************************************************************** - * - * Project: OpenGIS Simple Features Reference Implementation - * Purpose: C MiraMon code adapted to be used in GDAL - * Author: Abel Pau, a.pau@creaf.uab.cat, based on the MiraMon codes, - * mainly written by Xavier Pons, Joan Maso (correctly written - * "Mas0xF3"), Abel Pau, Nuria Julia (N0xFAria Juli0xE0), - * Xavier Calaf, Lluis (Llu0xEDs) Pesquer and Alaitz Zabala, from - * CREAF and Universitat Autonoma (Aut0xF2noma) de Barcelona. - * For a complete list of contributors: - * https://www.miramon.cat/eng/QuiSom.htm - ****************************************************************************** - * Copyright (c) 2024, Xavier Pons - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - ****************************************************************************/ - -#ifdef GDAL_COMPILATION -#include "ogr_api.h" // For CPL_C_START -#include "mm_gdal_functions.h" // For MM_strnzcpy() -#include "mm_wrlayr.h" // For calloc_function()... -#else -#include "CmptCmp.h" -#include "mm_gdal\mm_gdal_functions.h" // For MM_strnzcpy() -#include "mm_gdal\mm_wrlayr.h" // For calloc_function()... -#endif // GDAL_COMPILATION - -#ifdef GDAL_COMPILATION -CPL_C_START // Necessary for compiling in GDAL project -#endif // GDAL_COMPILATION - -#include "cpl_string.h" // For CPL_ENC_UTF8 - - static char local_message[MAX_LOCAL_MESSAGE]; - -char szInternalGraphicIdentifierEng[MM_MAX_IDENTIFIER_SIZE]; -char szInternalGraphicIdentifierCat[MM_MAX_IDENTIFIER_SIZE]; -char szInternalGraphicIdentifierEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szNumberOfVerticesEng[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfVerticesCat[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfVerticesEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szLenghtOfAarcEng[MM_MAX_IDENTIFIER_SIZE]; -char szLenghtOfAarcCat[MM_MAX_IDENTIFIER_SIZE]; -char szLenghtOfAarcEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szInitialNodeEng[MM_MAX_IDENTIFIER_SIZE]; -char szInitialNodeCat[MM_MAX_IDENTIFIER_SIZE]; -char szInitialNodeEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szFinalNodeEng[MM_MAX_IDENTIFIER_SIZE]; -char szFinalNodeCat[MM_MAX_IDENTIFIER_SIZE]; -char szFinalNodeEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szNumberOfArcsToNodeEng[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfArcsToNodeCat[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfArcsToNodeEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szNodeTypeEng[MM_MAX_IDENTIFIER_SIZE]; -char szNodeTypeCat[MM_MAX_IDENTIFIER_SIZE]; -char szNodeTypeEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szPerimeterOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE]; -char szPerimeterOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE]; -char szPerimeterOfThePolygonEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szAreaOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE]; -char szAreaOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE]; -char szAreaOfThePolygonEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szNumberOfArcsEng[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfArcsCat[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfArcsEsp[MM_MAX_IDENTIFIER_SIZE]; - -char szNumberOfElementaryPolygonsEng[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfElementaryPolygonsCat[MM_MAX_IDENTIFIER_SIZE]; -char szNumberOfElementaryPolygonsEsp[MM_MAX_IDENTIFIER_SIZE]; - -void MM_FillFieldDescriptorByLanguage(void) -{ - MM_strnzcpy(szInternalGraphicIdentifierEng, "Internal Graphic identifier", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szInternalGraphicIdentifierCat, "Identificador Grafic intern", - MM_MAX_IDENTIFIER_SIZE); - szInternalGraphicIdentifierCat[16] = MM_a_WITH_GRAVE; - MM_strnzcpy(szInternalGraphicIdentifierEsp, "Identificador Grafico interno", - MM_MAX_IDENTIFIER_SIZE); - szInternalGraphicIdentifierEsp[16] = MM_a_WITH_ACUTE; - - MM_strnzcpy(szNumberOfVerticesEng, "Number of vertices", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfVerticesCat, "Nombre de vertexs", - MM_MAX_IDENTIFIER_SIZE); - szNumberOfVerticesCat[11] = MM_e_WITH_GRAVE; - MM_strnzcpy(szNumberOfVerticesEsp, "Numero de vertices", - MM_MAX_IDENTIFIER_SIZE); - szNumberOfVerticesEsp[1] = MM_u_WITH_ACUTE; - szNumberOfVerticesEsp[11] = MM_e_WITH_ACUTE; - - MM_strnzcpy(szLenghtOfAarcEng, "Lenght of arc", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szLenghtOfAarcCat, "Longitud de l'arc", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szLenghtOfAarcEsp, "Longitud del arco", MM_MAX_IDENTIFIER_SIZE); - - MM_strnzcpy(szInitialNodeEng, "Initial node", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szInitialNodeCat, "Node inicial", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szInitialNodeEsp, "Nodo inicial", MM_MAX_IDENTIFIER_SIZE); - - MM_strnzcpy(szFinalNodeEng, "Final node", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szFinalNodeCat, "Node final", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szFinalNodeEsp, "Nodo final", MM_MAX_IDENTIFIER_SIZE); - - MM_strnzcpy(szNumberOfArcsToNodeEng, "Number of arcs to node", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfArcsToNodeCat, "Nombre d'arcs al node", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfArcsToNodeEsp, "Numero de arcos al nodo", - MM_MAX_IDENTIFIER_SIZE); - szNumberOfArcsToNodeEsp[1] = MM_u_WITH_ACUTE; - - MM_strnzcpy(szNodeTypeEng, "Node type", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNodeTypeCat, "Tipus de node", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNodeTypeEsp, "Tipo de nodo", MM_MAX_IDENTIFIER_SIZE); - - MM_strnzcpy(szPerimeterOfThePolygonEng, "Perimeter of the polygon", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szPerimeterOfThePolygonCat, "Perimetre del poligon", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szPerimeterOfThePolygonEsp, "Perimetro del poligono", - MM_MAX_IDENTIFIER_SIZE); - szPerimeterOfThePolygonCat[3] = MM_i_WITH_ACUTE; - szPerimeterOfThePolygonEsp[3] = MM_i_WITH_ACUTE; - szPerimeterOfThePolygonCat[17] = MM_i_WITH_ACUTE; - szPerimeterOfThePolygonEsp[17] = MM_i_WITH_ACUTE; - - MM_strnzcpy(szAreaOfThePolygonEng, "Area of the polygon", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szAreaOfThePolygonCat, "Area del poligon", - MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szAreaOfThePolygonEsp, "Area del poligono", - MM_MAX_IDENTIFIER_SIZE); - szAreaOfThePolygonCat[0] = MM_A_WITH_GRAVE; - szAreaOfThePolygonEsp[0] = MM_A_WITH_ACUTE; - szAreaOfThePolygonCat[12] = MM_i_WITH_ACUTE; - szAreaOfThePolygonEsp[12] = MM_i_WITH_ACUTE; - - MM_strnzcpy(szNumberOfArcsEng, "Number of arcs", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfArcsCat, "Nombre d'arcs", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfArcsEsp, "Numero de arcos", MM_MAX_IDENTIFIER_SIZE); - szNumberOfArcsEsp[1] = MM_u_WITH_ACUTE; - - MM_strnzcpy(szNumberOfElementaryPolygonsEng, - "Number of elementary polygons", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfElementaryPolygonsCat, - "Nombre de poligons elementals", MM_MAX_IDENTIFIER_SIZE); - MM_strnzcpy(szNumberOfElementaryPolygonsEsp, - "Numero de poligonos elementales", MM_MAX_IDENTIFIER_SIZE); - szNumberOfElementaryPolygonsEsp[1] = MM_u_WITH_ACUTE; - szNumberOfElementaryPolygonsCat[13] = MM_i_WITH_ACUTE; - szNumberOfElementaryPolygonsEsp[13] = MM_i_WITH_ACUTE; -} - -const char *MM_pszLogFilename = nullptr; - -// Loging -const char *Log(const char *pszMsg, int nLineNumber) -{ - FILE *f; - - if (MM_pszLogFilename == nullptr) - return pszMsg; - f = fopen(MM_pszLogFilename, "at"); - if (f == nullptr) - return pszMsg; - fprintf(f, "%d: %s\n", nLineNumber, pszMsg); - fclose(f); - return pszMsg; -} - -static const char MM_EmptyString[] = {""}; -#define MM_SetEndOfString (*MM_EmptyString) -static const char MM_BlankString[] = {" "}; - -// CREATING AN EXTENDED MIRAMON DBF -void MM_InitializeField(struct MM_FIELD *pField) -{ - memset(pField, '\0', sizeof(*pField)); - pField->FieldType = 'C'; - pField->GeoTopoTypeField = MM_NO_ES_CAMP_GEOTOPO; -} - -struct MM_FIELD *MM_CreateAllFields(MM_EXT_DBF_N_FIELDS nFields) -{ - struct MM_FIELD *camp; - MM_EXT_DBF_N_FIELDS i; - - if ((camp = calloc_function(nFields * sizeof(*camp))) == nullptr) - return nullptr; - - for (i = 0; i < nFields; i++) - MM_InitializeField(camp + i); - return camp; -} - -static struct MM_DATA_BASE_XP *MM_CreateEmptyHeader(MM_EXT_DBF_N_FIELDS nFields) -{ - struct MM_DATA_BASE_XP *data_base_XP; - - if ((data_base_XP = (struct MM_DATA_BASE_XP *)calloc_function( - sizeof(struct MM_DATA_BASE_XP))) == nullptr) - return nullptr; - - if (nFields == 0) - { - ; - } - else - { - data_base_XP->pField = (struct MM_FIELD *)MM_CreateAllFields(nFields); - if (!data_base_XP->pField) - { - free_function(data_base_XP); - return nullptr; - } - } - data_base_XP->nFields = nFields; - return data_base_XP; -} - -struct MM_DATA_BASE_XP *MM_CreateDBFHeader(MM_EXT_DBF_N_FIELDS n_camps, - MM_BYTE charset) -{ - struct MM_DATA_BASE_XP *bd_xp; - struct MM_FIELD *camp; - MM_EXT_DBF_N_FIELDS i; - - if (nullptr == (bd_xp = MM_CreateEmptyHeader(n_camps))) - return nullptr; - - bd_xp->CharSet = charset; - - strcpy(bd_xp->ReadingMode, "a+b"); - - bd_xp->IdGraficField = n_camps; - bd_xp->IdEntityField = MM_MAX_EXT_DBF_N_FIELDS_TYPE; - bd_xp->dbf_version = (MM_BYTE)((n_camps > MM_MAX_N_CAMPS_DBF_CLASSICA) - ? MM_MARCA_VERSIO_1_DBF_ESTESA - : MM_MARCA_DBASE4); - - for (i = 0, camp = bd_xp->pField; i < n_camps; i++, camp++) - { - MM_InitializeField(camp); - if (i < 99999) - sprintf(camp->FieldName, "CAMP%05u", (unsigned)(i + 1)); - else - sprintf(camp->FieldName, "CM%u", (unsigned)(i + 1)); - camp->FieldType = 'C'; - camp->DecimalsIfFloat = 0; - camp->BytesPerField = 50; - } - return bd_xp; -} - -MM_BYTE MM_DBFFieldTypeToVariableProcessing(MM_BYTE tipus_camp_DBF) -{ - switch (tipus_camp_DBF) - { - case 'N': - return MM_QUANTITATIVE_CONTINUOUS_FIELD; - case 'D': - case 'C': - case 'L': - return MM_CATEGORICAL_FIELD; - } - return MM_CATEGORICAL_FIELD; -} - -static MM_BYTE MM_GetDefaultDesiredDBFFieldWidth(const struct MM_FIELD *camp) -{ - size_t a, b, c, d, e; - - b = strlen(camp->FieldName); - c = strlen(camp->FieldDescription[0]); - - if (camp->FieldType == 'D') - { - d = (b > c ? b : c); - a = (size_t)camp->BytesPerField + 2; - return (MM_BYTE)(a > d ? a : d); - } - a = camp->BytesPerField; - d = (unsigned int)(b > c ? b : c); - e = (a > d ? a : d); - return (MM_BYTE)(e < 80 ? e : 80); -} - -static MM_BOOLEAN MM_is_field_name_lowercase(const char *cadena) -{ - const char *p; - - for (p = cadena; *p; p++) - { - if ((*p >= 'a' && *p <= 'z')) - return TRUE; - } - return FALSE; -} - -static MM_BOOLEAN -MM_Is_classical_DBF_field_name_or_lowercase(const char *cadena) -{ - const char *p; - - for (p = cadena; *p; p++) - { - if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9') || *p == '_') - ; - else - return FALSE; - } - if (cadena[0] == '_') - return FALSE; - return TRUE; -} - -static MM_BOOLEAN -MM_Is_character_valid_for_extended_DBF_field_name(int valor, - int *valor_substitut) -{ - if (valor_substitut) - { - switch (valor) - { - case 32: - *valor_substitut = '_'; - return FALSE; - case 91: - *valor_substitut = '('; - return FALSE; - case 93: - *valor_substitut = ')'; - return FALSE; - case 96: - *valor_substitut = '\''; - return FALSE; - case 127: - *valor_substitut = '_'; - return FALSE; - case 168: - *valor_substitut = '-'; - return FALSE; - } - } - else - { - if (valor < 32 || valor == 91 || valor == 93 || valor == 96 || - valor == 127 || valor == 168) - return FALSE; - } - return TRUE; -} - -static int MM_ISExtendedNameBD_XP(const char *nom_camp) -{ - GInt32 mida, j; - - mida = (GInt32)strlen(nom_camp); - if (mida >= MM_MAX_LON_FIELD_NAME_DBF) - return MM_DBF_NAME_NO_VALID; - - for (j = 0; j < mida; j++) - { - if (!MM_Is_character_valid_for_extended_DBF_field_name( - (unsigned char)nom_camp[j], nullptr)) - return MM_DBF_NAME_NO_VALID; - } - - if (mida >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF) - return MM_VALID_EXTENDED_DBF_NAME; - - if (!MM_Is_classical_DBF_field_name_or_lowercase(nom_camp)) - return MM_VALID_EXTENDED_DBF_NAME; - - if (MM_is_field_name_lowercase(nom_camp)) - return MM_DBF_NAME_LOWERCASE_AND_VALID; - - return NM_CLASSICAL_DBF_AND_VALID_NAME; -} - -static MM_BYTE MM_CalculateBytesExtendedFieldName(struct MM_FIELD *camp) -{ - camp->reserved_2[MM_OFFSET_RESERVED2_EXTENDED_NAME_SIZE] = - (MM_BYTE)strlen(camp->FieldName); - return MM_DonaBytesNomEstesCamp(camp); -} - -static MM_ACUMULATED_BYTES_TYPE_DBF -MM_CalculateBytesExtendedFieldNames(const struct MM_DATA_BASE_XP *bd_xp) -{ - MM_ACUMULATED_BYTES_TYPE_DBF bytes_acumulats = 0; - MM_EXT_DBF_N_FIELDS i_camp; - - for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) - { - if (MM_VALID_EXTENDED_DBF_NAME == - MM_ISExtendedNameBD_XP(bd_xp->pField[i_camp].FieldName)) - bytes_acumulats += - MM_CalculateBytesExtendedFieldName(bd_xp->pField + i_camp); - } - - return bytes_acumulats; -} - -static MM_FIRST_RECORD_OFFSET_TYPE -MM_CalculateBytesFirstRecordOffset(struct MM_DATA_BASE_XP *bd_xp) -{ - if (bd_xp) - return (32 + 32 * bd_xp->nFields + 1 + - MM_CalculateBytesExtendedFieldNames(bd_xp)); - return 0; -} - -static void MM_CheckDBFHeader(struct MM_DATA_BASE_XP *bd_xp) -{ - struct MM_FIELD *camp; - MM_EXT_DBF_N_FIELDS i; - MM_BOOLEAN cal_DBF_estesa = FALSE; - - bd_xp->BytesPerRecord = 1; - for (i = 0, camp = bd_xp->pField; i < bd_xp->nFields; i++, camp++) - { - camp->AcumulatedBytes = bd_xp->BytesPerRecord; - bd_xp->BytesPerRecord += camp->BytesPerField; - if (camp->DesiredWidth == 0) - camp->DesiredWidth = camp->OriginalDesiredWidth = - MM_GetDefaultDesiredDBFFieldWidth(camp); //camp->BytesPerField; - if (camp->FieldType == 'C' && - camp->BytesPerField > MM_MAX_AMPLADA_CAMP_C_DBF_CLASSICA) - cal_DBF_estesa = TRUE; - if (MM_VALID_EXTENDED_DBF_NAME == - MM_ISExtendedNameBD_XP(camp->FieldName)) - cal_DBF_estesa = TRUE; - } - - bd_xp->FirstRecordOffset = MM_CalculateBytesFirstRecordOffset(bd_xp); - - if (cal_DBF_estesa || bd_xp->nFields > MM_MAX_N_CAMPS_DBF_CLASSICA || - bd_xp->nRecords > UINT32_MAX) - bd_xp->dbf_version = (MM_BYTE)MM_MARCA_VERSIO_1_DBF_ESTESA; - else - bd_xp->dbf_version = MM_MARCA_DBASE4; -} - -static void -MM_InitializeOffsetExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp, - MM_EXT_DBF_N_FIELDS i_camp) -{ - memset((char *)(&bd_xp->pField[i_camp].reserved_2) + - MM_OFFSET_RESERVAT2_OFFSET_NOM_ESTES, - 0, 4); -} -static void -MM_InitializeBytesExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp, - MM_EXT_DBF_N_FIELDS i_camp) -{ - memset((char *)(&bd_xp->pField[i_camp].reserved_2) + - MM_OFFSET_RESERVED2_EXTENDED_NAME_SIZE, - 0, 1); -} - -static short int MM_return_common_valid_DBF_field_name_string(char *cadena) -{ - char *p; - short int error_retornat = 0; - - if (!cadena) - return 0; - //strupr(cadena); - for (p = cadena; *p; p++) - { - (*p) = (char)toupper(*p); - if ((*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_') - ; - else - { - *p = '_'; - error_retornat |= MM_FIELD_NAME_CHARACTER_INVALID; - } - } - if (cadena[0] == '_') - { - cadena[0] = '0'; - error_retornat |= MM_FIELD_NAME_FIRST_CHARACTER_; - } - return error_retornat; -} - -static short int MM_ReturnValidClassicDBFFieldName(char *cadena) -{ - size_t long_nom_camp; - short int error_retornat = 0; - - long_nom_camp = strlen(cadena); - if ((long_nom_camp < 1) || - (long_nom_camp >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF)) - { - cadena[MM_MAX_LON_FIELD_NAME_DBF - 1] = '\0'; - error_retornat |= MM_FIELD_NAME_TOO_LONG; - } - error_retornat |= MM_return_common_valid_DBF_field_name_string(cadena); - return error_retornat; -} - -static MM_BOOLEAN -MM_CheckClassicFieldNameEqual(const struct MM_DATA_BASE_XP *data_base_XP, - const char *classical_name) -{ - MM_EXT_DBF_N_FIELDS i; - - for (i = 0; i < data_base_XP->nFields; i++) - { - if ((strcasecmp(data_base_XP->pField[i].ClassicalDBFFieldName, - classical_name)) == 0 || - (strcasecmp(data_base_XP->pField[i].FieldName, classical_name)) == - 0) - return TRUE; - } - return FALSE; -} - -static char *MM_GiveNewStringWithCharacterInFront(const char *text, - char caracter) -{ - char *ptr; - size_t i; - - if (!text) - return nullptr; - - i = strlen(text); - if ((ptr = calloc_function(i + 2)) == nullptr) - return nullptr; - - *ptr = caracter; - memcpy(ptr + 1, text, i + 1); - return ptr; -} - -static char *MM_SetSubIndexFieldNam(char *nom_camp, MM_EXT_DBF_N_FIELDS index, - size_t ampladamax) -{ - char *NomCamp_SubIndex; - char *_subindex; - char subindex[15]; - size_t sizet_subindex; - size_t sizet_nomcamp; - - NomCamp_SubIndex = calloc_function(ampladamax * sizeof(char)); - if (!NomCamp_SubIndex) - return nullptr; - - strcpy(NomCamp_SubIndex, nom_camp); - - sprintf(subindex, sprintf_UINT64, (GUInt64)index); - - _subindex = MM_GiveNewStringWithCharacterInFront(subindex, '_'); - sizet_subindex = strlen(_subindex); - sizet_nomcamp = strlen(NomCamp_SubIndex); - - if (sizet_nomcamp + sizet_subindex > ampladamax - 1) - memcpy(NomCamp_SubIndex + ((ampladamax - 1) - sizet_subindex), - _subindex, strlen(_subindex)); - else - NomCamp_SubIndex = strcat(NomCamp_SubIndex, _subindex); - - free_function(_subindex); - - return NomCamp_SubIndex; -} - -MM_FIRST_RECORD_OFFSET_TYPE -MM_GiveOffsetExtendedFieldName(const struct MM_FIELD *camp) -{ - MM_FIRST_RECORD_OFFSET_TYPE offset_nom_camp; - - memcpy(&offset_nom_camp, - (char *)(&camp->reserved_2) + MM_OFFSET_RESERVAT2_OFFSET_NOM_ESTES, - 4); - return offset_nom_camp; -} - -int MM_WriteNRecordsMMBD_XPFile(struct MMAdmDatabase *MMAdmDB) -{ - GUInt32 nRecords; - if (!MMAdmDB->pMMBDXP || !MMAdmDB->pFExtDBF) - return 0; - - // Updating number of features in features table - fseek_function(MMAdmDB->pFExtDBF, MM_FIRST_OFFSET_to_N_RECORDS, SEEK_SET); - - if (MMAdmDB->pMMBDXP->nRecords > UINT32_MAX) - { - MMAdmDB->pMMBDXP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA; - - if (fwrite_function(&MMAdmDB->pMMBDXP->nRecords, 4, 1, - MMAdmDB->pFExtDBF) != 1) - return 1; - } - else - { - MMAdmDB->pMMBDXP->dbf_version = MM_MARCA_DBASE4; - - nRecords = (GUInt32)MMAdmDB->pMMBDXP->nRecords; - if (fwrite_function(&nRecords, 4, 1, MMAdmDB->pFExtDBF) != 1) - return 1; - } - - fseek_function(MMAdmDB->pFExtDBF, MM_SECOND_OFFSET_to_N_RECORDS, SEEK_SET); - if (MMAdmDB->pMMBDXP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA) - { - /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */ - if (fwrite_function(((char *)(&MMAdmDB->pMMBDXP->nRecords)) + 4, 4, 1, - MMAdmDB->pFExtDBF) != 1) - return 1; - - /* from 20 to 27 */ - if (fwrite_function(&(MMAdmDB->pMMBDXP->dbf_on_a_LAN), 8, 1, - MMAdmDB->pFExtDBF) != 1) - return 1; - } - else - { - if (fwrite_function(&(MMAdmDB->pMMBDXP->dbf_on_a_LAN), 12, 1, - MMAdmDB->pFExtDBF) != 1) - return 1; - } - - return 0; -} - -static MM_BOOLEAN MM_UpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP) -{ - MM_BYTE variable_byte; - MM_EXT_DBF_N_FIELDS i, j = 0; - const size_t max_n_zeros = 11; - char *zero; - const MM_BYTE byte_zero = 0; - char ModeLectura_previ[4] = ""; - MM_FIRST_RECORD_OFFSET_TYPE bytes_acumulats; - MM_BYTE name_size; - int estat; - char nom_camp[MM_MAX_LON_FIELD_NAME_DBF]; - size_t retorn_fwrite; - MM_BOOLEAN table_should_be_closed = FALSE; - GUInt32 nRecords; - - if ((zero = calloc_function(max_n_zeros)) == nullptr) - return FALSE; - - if (data_base_XP->pfDataBase == nullptr) - { - strcpy(ModeLectura_previ, data_base_XP->ReadingMode); - strcpy(data_base_XP->ReadingMode, "wb"); - - if ((data_base_XP->pfDataBase = - fopen_function(data_base_XP->szFileName, - data_base_XP->ReadingMode)) == nullptr) - { - free_function(zero); - return FALSE; - } - - table_should_be_closed = TRUE; - } - - if ((data_base_XP->nFields) > MM_MAX_N_CAMPS_DBF_CLASSICA) - data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA; - else if ((data_base_XP->nRecords) > UINT32_MAX) - data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA; - else - { - if (data_base_XP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA) - data_base_XP->dbf_version = MM_MARCA_DBASE4; - for (i = 0; i < data_base_XP->nFields; i++) - { - if (data_base_XP->pField[i].FieldType == 'C' && - data_base_XP->pField[i].BytesPerField > - MM_MAX_AMPLADA_CAMP_C_DBF_CLASSICA) - { - data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA; - break; - } - if (MM_VALID_EXTENDED_DBF_NAME == - MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName)) - { - data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA; - break; - } - } - } - - // Writting header - fseek_function(data_base_XP->pfDataBase, 0, SEEK_SET); - - /* Byte 0 */ - if (fwrite_function(&(data_base_XP->dbf_version), 1, 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - - /* MM_BYTE from 1 to 3 */ - variable_byte = (MM_BYTE)(data_base_XP->year - 1900); - if (fwrite_function(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1) - return FALSE; - if (fwrite_function(&(data_base_XP->month), 1, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - if (fwrite_function(&(data_base_XP->day), 1, 1, data_base_XP->pfDataBase) != - 1) - return FALSE; - - /* from 4 a 7, position MM_FIRST_OFFSET_to_N_RECORDS */ - if (data_base_XP->nRecords > UINT32_MAX) - { - if (fwrite_function(&data_base_XP->nRecords, 4, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - } - else - { - nRecords = (GUInt32)data_base_XP->nRecords; - if (fwrite_function(&nRecords, 4, 1, data_base_XP->pfDataBase) != 1) - return FALSE; - } - - /* from 8 a 9, position MM_PRIMER_OFFSET_a_OFFSET_1a_FITXA */ - if (fwrite_function(&(data_base_XP->FirstRecordOffset), 2, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - /* from 10 to 11, & from 12 to 13 */ - if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version)) - { - if (fwrite_function(&(data_base_XP->BytesPerRecord), - sizeof(MM_ACUMULATED_BYTES_TYPE_DBF), 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - } - else - { - /* from 10 to 11 */ - if (fwrite_function(&(data_base_XP->BytesPerRecord), 2, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - /* from 12 to 13 */ - if (fwrite_function(&(data_base_XP->reserved_1), 2, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - } - /* byte 14 */ - if (fwrite_function(&(data_base_XP->transaction_flag), 1, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - /* byte 15 */ - if (fwrite_function(&(data_base_XP->encryption_flag), 1, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - - /* from 16 to 27 */ - if (data_base_XP->nRecords > UINT32_MAX) - { - /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */ - if (fwrite_function(((char *)(&data_base_XP->nRecords)) + 4, 4, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - - /* from 20 to 27 */ - if (fwrite_function(&(data_base_XP->dbf_on_a_LAN), 8, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - } - else - { - /* from 16 to 27 */ - if (fwrite_function(&(data_base_XP->dbf_on_a_LAN), 12, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - } - /* byte 28 */ - if (fwrite_function(&(data_base_XP->MDX_flag), 1, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - - /* Byte 29 */ - if (fwrite_function(&(data_base_XP->CharSet), 1, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - - /* Bytes from 30 to 31, in position MM_SEGON_OFFSET_a_OFFSET_1a_FITXA */ - if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version)) - { - if (fwrite_function(((char *)&(data_base_XP->FirstRecordOffset)) + 2, 2, - 1, data_base_XP->pfDataBase) != 1) - return FALSE; - } - else - { - if (fwrite_function(&(data_base_XP->reserved_2), 2, 1, - data_base_XP->pfDataBase) != 1) - return FALSE; - } - - /* At 32th byte fields description begins */ - /* Every description is 32 bytes long */ - bytes_acumulats = 32 + 32 * (data_base_XP->nFields) + 1; - - for (i = 0; i < data_base_XP->nFields; i++) - { - /* Bytes from 0 to 10 -> Field name, \0 finished */ - estat = MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName); - if (estat == NM_CLASSICAL_DBF_AND_VALID_NAME || - estat == MM_DBF_NAME_LOWERCASE_AND_VALID) - { - j = (short)strlen(data_base_XP->pField[i].FieldName); - - retorn_fwrite = fwrite_function(&data_base_XP->pField[i].FieldName, - 1, j, data_base_XP->pfDataBase); - if (retorn_fwrite != (size_t)j) - { - return FALSE; - } - MM_InitializeOffsetExtendedFieldNameFields(data_base_XP, i); - MM_InitializeBytesExtendedFieldNameFields(data_base_XP, i); - } - else if (estat == MM_VALID_EXTENDED_DBF_NAME) - { - if (*(data_base_XP->pField[i].ClassicalDBFFieldName) == '\0') - { - char nom_temp[MM_MAX_LON_FIELD_NAME_DBF]; - - MM_strnzcpy(nom_temp, data_base_XP->pField[i].FieldName, - MM_MAX_LON_FIELD_NAME_DBF); - MM_ReturnValidClassicDBFFieldName(nom_temp); - nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0'; - if ((MM_CheckClassicFieldNameEqual(data_base_XP, nom_temp)) == - TRUE) - { - char *c; - - c = MM_SetSubIndexFieldNam( - nom_temp, i, MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); - - j = 0; - while (MM_CheckClassicFieldNameEqual(data_base_XP, c) == - TRUE && - j < data_base_XP->nFields) - { - free_function(c); - c = MM_SetSubIndexFieldNam( - nom_temp, ++j, MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); - } - - strcpy(data_base_XP->pField[i].ClassicalDBFFieldName, c); - free_function(c); - } - else - strcpy(data_base_XP->pField[i].ClassicalDBFFieldName, - nom_temp); - } - j = (short)strlen(data_base_XP->pField[i].ClassicalDBFFieldName); - - retorn_fwrite = - fwrite_function(&data_base_XP->pField[i].ClassicalDBFFieldName, - 1, j, data_base_XP->pfDataBase); - if (retorn_fwrite != (size_t)j) - { - free_function(zero); - return FALSE; - } - - name_size = - MM_CalculateBytesExtendedFieldName(data_base_XP->pField + i); - MM_EscriuOffsetNomEstesBD_XP(data_base_XP, i, bytes_acumulats); - bytes_acumulats += name_size; - } - else - { - free_function(zero); - return FALSE; - } - - if (fwrite_function(zero, 1, 11 - j, data_base_XP->pfDataBase) != - 11 - (size_t)j) - { - free_function(zero); - return FALSE; - } - /* Byte 11, Field type */ - if (fwrite_function(&data_base_XP->pField[i].FieldType, 1, 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - /* Bytes 12 to 15 --> Reserved */ - if (fwrite_function(&data_base_XP->pField[i].reserved_1, 4, 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - /* Byte 16, or OFFSET_BYTESxCAMP_CAMP_CLASSIC --> BytesPerField */ - if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version) && - data_base_XP->pField[i].FieldType == 'C') - { - if (fwrite_function((void *)&byte_zero, 1, 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - } - else - { - if (fwrite_function(&data_base_XP->pField[i].BytesPerField, 1, 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - } - /* 17th byte 17 --> In fields of type 'N' and 'F' indicates decimal places.*/ - if (data_base_XP->pField[i].FieldType == 'N' || - data_base_XP->pField[i].FieldType == 'F') - { - if (fwrite_function(&data_base_XP->pField[i].DecimalsIfFloat, 1, 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - } - else - { - if (fwrite_function(zero, 1, 1, data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - } - if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version) && - data_base_XP->pField[i].FieldType == 'C') - { - /* Bytes from 18 to 20 --> Reserved */ - if (fwrite_function(&data_base_XP->pField[i].reserved_2, - 20 - 18 + 1, 1, data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - /* Bytes from 21 to 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C - in extended DBF */ - if (fwrite_function(&data_base_XP->pField[i].BytesPerField, - sizeof(MM_BYTES_PER_FIELD_TYPE_DBF), 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - - /* Bytes from 25 to 30 --> Reserved */ - if (fwrite_function(&data_base_XP->pField[i].reserved_2[25 - 18], - 30 - 25 + 1, 1, data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - } - else - { - /* Bytes de 21 a 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C */ - memset(data_base_XP->pField[i].reserved_2 + - MM_OFFSET_RESERVAT2_BYTESxCAMP_CAMP_ESPECIAL, - '\0', 4); - /* Bytes from 18 to 30 --> Reserved */ - if (fwrite_function(&data_base_XP->pField[i].reserved_2, 13, 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - } - /* Byte 31 --> MDX flag. */ - if (fwrite_function(&data_base_XP->pField[i].MDX_field_flag, 1, 1, - data_base_XP->pfDataBase) != 1) - { - free_function(zero); - return FALSE; - } - } - - free_function(zero); - - variable_byte = 13; - if (fwrite_function(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1) - return FALSE; - - if (data_base_XP->FirstRecordOffset != bytes_acumulats) - return FALSE; - - // Extended fields - for (i = 0; i < data_base_XP->nFields; i++) - { - if (MM_VALID_EXTENDED_DBF_NAME == - MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName)) - { - bytes_acumulats = - MM_GiveOffsetExtendedFieldName(data_base_XP->pField + i); - name_size = MM_DonaBytesNomEstesCamp(data_base_XP->pField + i); - - fseek_function(data_base_XP->pfDataBase, bytes_acumulats, SEEK_SET); - - strcpy(nom_camp, data_base_XP->pField[i].FieldName); - //CanviaJocCaracPerEscriureDBF(nom_camp, JocCaracDBFaMM(data_base_XP->CharSet, ParMM.JocCaracDBFPerDefecte)); - - retorn_fwrite = fwrite_function(nom_camp, 1, name_size, - data_base_XP->pfDataBase); - - if (retorn_fwrite != (size_t)name_size) - return FALSE; - } - } - - if (table_should_be_closed) - { - fclose_function(data_base_XP->pfDataBase); - data_base_XP->pfDataBase = nullptr; - } - - return TRUE; -} /* End of MM_UpdateEntireHeader() */ - -MM_BOOLEAN MM_CreateDBFFile(struct MM_DATA_BASE_XP *bd_xp, - const char *NomFitxer) -{ - if (MMIsEmptyString(NomFitxer)) - return TRUE; // No file no error. Just continue - MM_CheckDBFHeader(bd_xp); - if (NomFitxer) - strcpy(bd_xp->szFileName, NomFitxer); - return MM_UpdateEntireHeader(bd_xp); -} - -void MM_ReleaseMainFields(struct MM_DATA_BASE_XP *data_base_XP) -{ - MM_EXT_DBF_N_FIELDS i; - size_t j; - char **cadena; - - if (data_base_XP->pField) - { - for (i = 0; i < data_base_XP->nFields; i++) - { - for (j = 0; j < MM_NUM_IDIOMES_MD_MULTIDIOMA; j++) - { - cadena = data_base_XP->pField[i].Separator; - if (cadena[j]) - { - free_function(cadena[j]); - cadena[j] = nullptr; - } - } - } - free_function(data_base_XP->pField); - data_base_XP->pField = nullptr; - data_base_XP->nFields = 0; - } - return; -} - -// READING THE HEADER OF AN EXTENDED DBF -// Free with MM_ReleaseDBFHeader() -int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, - struct MM_DATA_BASE_XP *pMMBDXP, - const char *pszRelFile) -{ - MM_BYTE variable_byte; - FILE_TYPE *pf; - unsigned short int ushort; - MM_EXT_DBF_N_FIELDS nIField, j; - MM_FIRST_RECORD_OFFSET_TYPE offset_primera_fitxa; - MM_FIRST_RECORD_OFFSET_TYPE offset_fals = 0; - MM_BOOLEAN incoherent_record_size = FALSE; - MM_BYTE un_byte; - MM_BYTES_PER_FIELD_TYPE_DBF bytes_per_camp; - MM_BYTE tretze_bytes[13]; - MM_FIRST_RECORD_OFFSET_TYPE offset_possible; - MM_BYTE n_queixes_estructura_incorrecta = 0; - MM_FILE_OFFSET offset_reintent = 0; // For retrying - char cpg_file[MM_CPL_PATH_BUF_SIZE]; - char *pszDesc; - char section[MM_MAX_LON_FIELD_NAME_DBF + 25]; // TAULA_PRINCIPAL:field_name - GUInt32 nRecords; - char *pszString; - - if (!szFileName) - return 1; - - strcpy(pMMBDXP->szFileName, szFileName); - strcpy(pMMBDXP->ReadingMode, "rb"); - - if ((pMMBDXP->pfDataBase = fopen_function(pMMBDXP->szFileName, - pMMBDXP->ReadingMode)) == nullptr) - return 1; - - pf = pMMBDXP->pfDataBase; - - fseek_function(pf, 0, SEEK_SET); - /* ====== Header reading (32 bytes) =================== */ - offset_primera_fitxa = 0; - - if (1 != fread_function(&(pMMBDXP->dbf_version), 1, 1, pf) || - 1 != fread_function(&variable_byte, 1, 1, pf) || - 1 != fread_function(&(pMMBDXP->month), 1, 1, pf) || - 1 != fread_function(&(pMMBDXP->day), 1, 1, pf)) - { - fclose_function(pf); - return 1; - } - - if (1 != fread_function(&nRecords, 4, 1, pf)) - { - fclose_function(pf); - return 1; - } - - if (1 != fread_function(&offset_primera_fitxa, 2, 1, pf)) - { - fclose_function(pf); - return 1; - } - - pMMBDXP->year = (short)(1900 + variable_byte); -reintenta_lectura_per_si_error_CreaCampBD_XP: - - if (n_queixes_estructura_incorrecta > 0) - { - if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version)) - { - offset_fals = offset_primera_fitxa; - if ((offset_primera_fitxa - 1) % 32) - { - for (offset_fals = (offset_primera_fitxa - 1); - !((offset_fals - 1) % 32); offset_fals--) - ; - } - } - } - else - offset_reintent = ftell_function(pf); - - if (1 != fread_function(&ushort, 2, 1, pf) || - 1 != fread_function(&(pMMBDXP->reserved_1), 2, 1, pf) || - 1 != fread_function(&(pMMBDXP->transaction_flag), 1, 1, pf) || - 1 != fread_function(&(pMMBDXP->encryption_flag), 1, 1, pf) || - 1 != fread_function(&(pMMBDXP->dbf_on_a_LAN), 12, 1, pf)) - { - fclose_function(pf); - return 1; - } - - if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version)) - { - memcpy(&pMMBDXP->nRecords, &nRecords, 4); - memcpy(((char *)&pMMBDXP->nRecords) + 4, &pMMBDXP->dbf_on_a_LAN, 4); - } - else - pMMBDXP->nRecords = nRecords; - - if (1 != fread_function(&(pMMBDXP->MDX_flag), 1, 1, pf) || - 1 != fread_function(&(pMMBDXP->CharSet), 1, 1, pf) || - 1 != fread_function(&(pMMBDXP->reserved_2), 2, 1, pf)) - { - fclose_function(pf); - return 1; - } - - // Checking for a cpg file - if (pMMBDXP->CharSet == 0) - { - FILE_TYPE *f_cpg; - - strcpy(cpg_file, pMMBDXP->szFileName); - strcpy(cpg_file, reset_extension(cpg_file, "cpg")); - f_cpg = fopen_function(cpg_file, "r"); - if (f_cpg) - { - char *p; - size_t read_bytes; - fseek_function(f_cpg, 0L, SEEK_SET); - if (11 > (read_bytes = fread_function(local_message, 1, 10, f_cpg))) - { - local_message[read_bytes] = '\0'; - p = strstr(local_message, "UTF-8"); - if (p) - pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF; - p = strstr(local_message, "UTF8"); - if (p) - pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF; - p = strstr(local_message, "ISO-8859-1"); - if (p) - pMMBDXP->CharSet = MM_JOC_CARAC_ANSI_DBASE; - } - fclose_function(f_cpg); - } - } - if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version)) - { - memcpy(&pMMBDXP->FirstRecordOffset, &offset_primera_fitxa, 2); - memcpy(((char *)&pMMBDXP->FirstRecordOffset) + 2, &pMMBDXP->reserved_2, - 2); - - if (n_queixes_estructura_incorrecta > 0) - offset_fals = pMMBDXP->FirstRecordOffset; - - memcpy(&pMMBDXP->BytesPerRecord, &ushort, 2); - memcpy(((char *)&pMMBDXP->BytesPerRecord) + 2, &pMMBDXP->reserved_1, 2); - } - else - { - pMMBDXP->FirstRecordOffset = offset_primera_fitxa; - pMMBDXP->BytesPerRecord = ushort; - } - - /* ====== Record structure ========================= */ - - if (n_queixes_estructura_incorrecta > 0) - pMMBDXP->nFields = (MM_EXT_DBF_N_FIELDS)(((offset_fals - 1) - 32) / 32); - else - { - MM_ACUMULATED_BYTES_TYPE_DBF bytes_acumulats = 1; - - pMMBDXP->nFields = 0; - - fseek_function(pf, 0, SEEK_END); - if (32 < (ftell_function(pf) - 1)) - { - fseek_function(pf, 32, SEEK_SET); - do - { - bytes_per_camp = 0; - fseek_function( - pf, - 32 + (MM_FILE_OFFSET)pMMBDXP->nFields * 32 + - (MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF + 1 + 4), - SEEK_SET); - if (1 != fread_function(&bytes_per_camp, 1, 1, pf) || - 1 != fread_function(&un_byte, 1, 1, pf) || - 1 != fread_function(&tretze_bytes, - 3 + sizeof(bytes_per_camp), 1, pf)) - { - free(pMMBDXP->pField); - fclose_function(pf); - return 1; - } - if (bytes_per_camp == 0) - memcpy(&bytes_per_camp, (char *)(&tretze_bytes) + 3, - sizeof(bytes_per_camp)); - - bytes_acumulats += bytes_per_camp; - pMMBDXP->nFields++; - } while (bytes_acumulats < pMMBDXP->BytesPerRecord); - } - } - - if (pMMBDXP->nFields != 0) - { - pMMBDXP->pField = MM_CreateAllFields(pMMBDXP->nFields); - if (!pMMBDXP->pField) - { - fclose_function(pf); - return 1; - } - } - else - pMMBDXP->pField = nullptr; - - fseek_function(pf, 32, SEEK_SET); - for (nIField = 0; nIField < pMMBDXP->nFields; nIField++) - { - if (1 != fread_function(pMMBDXP->pField[nIField].FieldName, - MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF, 1, pf) || - 1 != fread_function(&(pMMBDXP->pField[nIField].FieldType), 1, 1, - pf) || - 1 != fread_function(&(pMMBDXP->pField[nIField].reserved_1), 4, 1, - pf) || - 1 != fread_function(&(pMMBDXP->pField[nIField].BytesPerField), 1, 1, - pf) || - 1 != fread_function(&(pMMBDXP->pField[nIField].DecimalsIfFloat), 1, - 1, pf) || - 1 != fread_function(&(pMMBDXP->pField[nIField].reserved_2), 13, 1, - pf) || - 1 != fread_function(&(pMMBDXP->pField[nIField].MDX_field_flag), 1, - 1, pf)) - { - free(pMMBDXP->pField); - fclose_function(pf); - return 1; - } - - if (pMMBDXP->pField[nIField].FieldType == 'F') - pMMBDXP->pField[nIField].FieldType = 'N'; - - pMMBDXP->pField[nIField] - .FieldName[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0'; - if (EQUAL(pMMBDXP->pField[nIField].FieldName, - szMMNomCampIdGraficDefecte)) - pMMBDXP->IdGraficField = nIField; - - if (pMMBDXP->pField[nIField].BytesPerField == 0) - { - if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version)) - { - free(pMMBDXP->pField); - fclose_function(pf); - return 1; - } - if (pMMBDXP->pField[nIField].FieldType != 'C') - { - free(pMMBDXP->pField); - fclose_function(pf); - return 1; - } - - memcpy(&pMMBDXP->pField[nIField].BytesPerField, - (char *)(&pMMBDXP->pField[nIField].reserved_2) + 3, - sizeof(MM_BYTES_PER_FIELD_TYPE_DBF)); - } - - if (nIField) - pMMBDXP->pField[nIField].AcumulatedBytes = - (pMMBDXP->pField[nIField - 1].AcumulatedBytes + - pMMBDXP->pField[nIField - 1].BytesPerField); - else - pMMBDXP->pField[nIField].AcumulatedBytes = 1; - - for (j = 0; j < MM_NUM_IDIOMES_MD_MULTIDIOMA; j++) - { - pMMBDXP->pField[nIField].Separator[j] = nullptr; - - if (pszRelFile) - { - sprintf(section, "TAULA_PRINCIPAL:%s", - pMMBDXP->pField[nIField].FieldName); - pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section, - "descriptor_eng"); - if (pszDesc) - { - MM_strnzcpy(pMMBDXP->pField[nIField].FieldDescription[j], - pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); - free_function(pszDesc); - } - else - { - sprintf(section, "TAULA_PRINCIPAL:%s", - pMMBDXP->pField[nIField].FieldName); - pszDesc = MMReturnValueFromSectionINIFile( - pszRelFile, section, "descriptor"); - if (pszDesc) - MM_strnzcpy( - pMMBDXP->pField[nIField].FieldDescription[j], - pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF); - pMMBDXP->pField[nIField].FieldDescription[j][0] = 0; - free_function(pszDesc); - } - } - } - } - - if (!pMMBDXP->nFields) - { - if (pMMBDXP->BytesPerRecord) - incoherent_record_size = TRUE; - } - else if (pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField + - pMMBDXP->pField[pMMBDXP->nFields - 1].AcumulatedBytes > - pMMBDXP->BytesPerRecord) - incoherent_record_size = TRUE; - if (incoherent_record_size) - { - if (n_queixes_estructura_incorrecta == 0) - { - incoherent_record_size = FALSE; - fseek_function(pf, offset_reintent, SEEK_SET); - n_queixes_estructura_incorrecta++; - goto reintenta_lectura_per_si_error_CreaCampBD_XP; - } - } - - offset_possible = 32 + 32 * (pMMBDXP->nFields) + 1; - - if (!incoherent_record_size && - offset_possible != pMMBDXP->FirstRecordOffset) - { // Extended names - MM_FIRST_RECORD_OFFSET_TYPE offset_nom_camp; - int mida_nom; - - for (nIField = 0; nIField < pMMBDXP->nFields; nIField++) - { - offset_nom_camp = - MM_GiveOffsetExtendedFieldName(pMMBDXP->pField + nIField); - mida_nom = MM_DonaBytesNomEstesCamp(pMMBDXP->pField + nIField); - if (mida_nom > 0 && mida_nom < MM_MAX_LON_FIELD_NAME_DBF && - offset_nom_camp >= offset_possible && - offset_nom_camp < pMMBDXP->FirstRecordOffset) - { - MM_strnzcpy(pMMBDXP->pField[nIField].ClassicalDBFFieldName, - pMMBDXP->pField[nIField].FieldName, - MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); - fseek_function(pf, offset_nom_camp, SEEK_SET); - if (1 != fread_function(pMMBDXP->pField[nIField].FieldName, - mida_nom, 1, pf)) - { - free(pMMBDXP->pField); - fclose_function(pf); - return 1; - } - pMMBDXP->pField[nIField].FieldName[mida_nom] = '\0'; - - // All field names to UTF-8 - if (pMMBDXP->CharSet == MM_JOC_CARAC_ANSI_DBASE) - { - pszString = - CPLRecode_function(pMMBDXP->pField[nIField].FieldName, - CPL_ENC_ISO8859_1, CPL_ENC_UTF8); - MM_strnzcpy(pMMBDXP->pField[nIField].FieldName, pszString, - MM_MAX_LON_FIELD_NAME_DBF); - CPLFree_function(pszString); - } - else if (pMMBDXP->CharSet == MM_JOC_CARAC_OEM850_DBASE) - { - MM_oemansi(pMMBDXP->pField[nIField].FieldName); - pszString = - CPLRecode_function(pMMBDXP->pField[nIField].FieldName, - CPL_ENC_ISO8859_1, CPL_ENC_UTF8); - MM_strnzcpy(pMMBDXP->pField[nIField].FieldName, pszString, - MM_MAX_LON_FIELD_NAME_DBF - 1); - CPLFree_function(pszString); - } - } - } - } - - pMMBDXP->IdEntityField = MM_MAX_EXT_DBF_N_FIELDS_TYPE; - return 0; -} // End of MM_ReadExtendedDBFHeaderFromFile() - -void MM_ReleaseDBFHeader(struct MM_DATA_BASE_XP *data_base_XP) -{ - if (data_base_XP) - { - MM_ReleaseMainFields(data_base_XP); - free_function(data_base_XP); - } - return; -} - -int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( - struct MM_FIELD *camp, struct MM_DATA_BASE_XP *bd_xp, - MM_BOOLEAN no_modifica_descriptor, size_t mida_nom) -{ - MM_EXT_DBF_N_FIELDS i_camp; - unsigned n_digits_i = 0, i; - int retorn = 0; - - if (mida_nom == 0) - mida_nom = MM_MAX_LON_FIELD_NAME_DBF; - - for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) - { - if (bd_xp->pField + i_camp == camp) - continue; - if (!strcasecmp(bd_xp->pField[i_camp].FieldName, camp->FieldName)) - break; - } - if (i_camp < bd_xp->nFields) - { - retorn = 1; - if (strlen(camp->FieldName) > mida_nom - 2) - camp->FieldName[mida_nom - 2] = '\0'; - strcat(camp->FieldName, "0"); - for (i = 2; i < (size_t)10; i++) - { - sprintf(camp->FieldName + strlen(camp->FieldName) - 1, "%u", i); - for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) - { - if (bd_xp->pField + i_camp == camp) - continue; - if (!strcasecmp(bd_xp->pField[i_camp].FieldName, - camp->FieldName)) - break; - } - if (i_camp == bd_xp->nFields) - { - n_digits_i = 1; - break; - } - } - if (i == 10) - { - camp->FieldName[strlen(camp->FieldName) - 1] = '\0'; - if (strlen(camp->FieldName) > mida_nom - 3) - camp->FieldName[mida_nom - 3] = '\0'; - strcat(camp->FieldName, "00"); - for (i = 10; i < (size_t)100; i++) - { - sprintf(camp->FieldName + strlen(camp->FieldName) - 2, "%u", i); - for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) - { - if (bd_xp->pField + i_camp == camp) - continue; - if (!strcasecmp(bd_xp->pField[i_camp].FieldName, - camp->FieldName)) - break; - } - if (i_camp == bd_xp->nFields) - { - n_digits_i = 2; - break; - } - } - if (i == 100) - { - camp->FieldName[strlen(camp->FieldName) - 2] = '\0'; - if (strlen(camp->FieldName) > mida_nom - 4) - camp->FieldName[mida_nom - 4] = '\0'; - strcat(camp->FieldName, "000"); - for (i = 100; i < (size_t)256 + 2; i++) - { - sprintf(camp->FieldName + strlen(camp->FieldName) - 3, "%u", - i); - for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) - { - if (bd_xp->pField + i_camp == camp) - continue; - if (!strcasecmp(bd_xp->pField[i_camp].FieldName, - camp->FieldName)) - break; - } - if (i_camp == bd_xp->nFields) - { - n_digits_i = 3; - break; - } - } - if (i == 256) - return 2; - } - } - } - else - { - i = 1; - } - - if ((*(camp->FieldDescription[0]) == '\0') || no_modifica_descriptor) - return retorn; - - for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) - { - if (bd_xp->pField + i_camp == camp) - continue; - if (!strcasecmp(bd_xp->pField[i_camp].FieldDescription[0], - camp->FieldDescription[0])) - break; - } - if (i_camp == bd_xp->nFields) - return retorn; - - if (retorn == 1) - { - if (strlen(camp->FieldDescription[0]) > - MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i) - camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0'; - //if (camp->FieldDescription[0] + strlen(camp->FieldDescription[0])) - sprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]), - " (%u)", i); - for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) - { - if (bd_xp->pField + i_camp == camp) - continue; - if (!strcasecmp(bd_xp->pField[i_camp].FieldDescription[0], - camp->FieldDescription[0])) - break; - } - if (i_camp == bd_xp->nFields) - return retorn; - } - - retorn = 1; - if (strlen(camp->FieldDescription[0]) > - MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i) - camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0'; - camp->FieldDescription[0][strlen(camp->FieldDescription[0]) - 4 - - n_digits_i + 1] = '\0'; - if (strlen(camp->FieldDescription[0]) > MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 7) - camp->FieldDescription[0][mida_nom - 7] = '\0'; - for (i++; i < (size_t)256; i++) - { - //if (camp->FieldDescription[0] + strlen(camp->FieldDescription[0])) - sprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]), - " (%u)", i); - for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++) - { - if (bd_xp->pField + i_camp == camp) - continue; - if (!strcasecmp(bd_xp->pField[i_camp].FieldName, camp->FieldName)) - break; - } - if (i_camp == bd_xp->nFields) - return retorn; - } - return 2; -} // End of MM_ModifyFieldNameAndDescriptorIfPresentBD_XP() - -static int MM_DuplicateMultilingualString( - char *(cadena_final[MM_NUM_IDIOMES_MD_MULTIDIOMA]), - const char *const(cadena_inicial[MM_NUM_IDIOMES_MD_MULTIDIOMA])) -{ - size_t i; - - for (i = 0; i < MM_NUM_IDIOMES_MD_MULTIDIOMA; i++) - { - if (cadena_inicial[i]) - { - if (nullptr == (cadena_final[i] = strdup(cadena_inicial[i]))) - return 1; - } - else - cadena_final[i] = nullptr; - } - return 0; -} - -int MM_DuplicateFieldDBXP(struct MM_FIELD *camp_final, - const struct MM_FIELD *camp_inicial) -{ - *camp_final = *camp_inicial; - - if (0 != MM_DuplicateMultilingualString( - camp_final->Separator, - (const char *const(*))camp_inicial->Separator)) - return 1; - - return 0; -} - -char *MM_strnzcpy(char *dest, const char *src, size_t maxlen) -{ - size_t i = 0; - if (!src || maxlen == 0) - { - *dest = '\0'; - return dest; - } - - for (; i < maxlen - 1 && src[i] != '\0'; ++i) - { - dest[i] = src[i]; - } - dest[i] = '\0'; - - return dest; -} -/* -char *MM_strnzcpy(char *dest, const char *src, size_t maxlen) -{ - size_t i; - if (!src) - { - *dest = '\0'; - return dest; - } - - if (!maxlen) - i = 0; - else - strncpy(dest, src, i = maxlen - 1); - - dest[i] = '\0'; - return dest; -}*/ - -char *MM_oemansi_n(char *szcadena, size_t n_bytes) -{ - size_t u_i; - unsigned char *punter_bait; - unsigned char t_oemansi[128] = { - 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, - 236, 196, 197, 201, 230, 198, 244, 246, 242, 251, 249, 255, 214, - 220, 248, 163, 216, 215, 131, 225, 237, 243, 250, 241, 209, 170, - 186, 191, 174, 172, 189, 188, 161, 171, 187, 164, 164, 164, 166, - 166, 193, 194, 192, 169, 166, 166, 164, 164, 162, 165, 164, 164, - 164, 164, 164, 164, 164, 227, 195, 164, 164, 164, 164, 166, 164, - 164, 164, 240, 208, 202, 203, 200, 180, 205, 206, 207, 164, 164, - 164, 164, 166, 204, 164, 211, 223, 212, 210, 245, 213, 181, 254, - 222, 218, 219, 217, 253, 221, 175, 180, 173, 177, 164, 190, 182, - 167, 247, 184, 176, 168, 183, 185, 179, 178, 164, 183}; - if (n_bytes == USHRT_MAX) - { - for (punter_bait = (unsigned char *)szcadena; *punter_bait; - punter_bait++) - { - if (*punter_bait > 127) - *punter_bait = t_oemansi[*punter_bait - 128]; - } - } - else - { - for (u_i = 0, punter_bait = (unsigned char *)szcadena; u_i < n_bytes; - punter_bait++, u_i++) - { - if (*punter_bait > 127) - *punter_bait = t_oemansi[*punter_bait - 128]; - } - } - return szcadena; -} - -char *MM_oemansi(char *szcadena) -{ - return MM_oemansi_n(szcadena, USHRT_MAX); -} - -static MM_BOOLEAN MM_FillFieldDB_XP(struct MM_FIELD *camp, - const char *FieldName, - const char *FieldDescription, - char FieldType, - MM_BYTES_PER_FIELD_TYPE_DBF BytesPerField, - MM_BYTE DecimalsIfFloat) -{ - char nom_temp[MM_MAX_LON_FIELD_NAME_DBF]; - int retorn_valida_nom_camp; - - if (FieldName) - { - retorn_valida_nom_camp = MM_ISExtendedNameBD_XP(FieldName); - if (retorn_valida_nom_camp == MM_DBF_NAME_NO_VALID) - return FALSE; - MM_strnzcpy(camp->FieldName, FieldName, MM_MAX_LON_FIELD_NAME_DBF); - - if (retorn_valida_nom_camp == MM_VALID_EXTENDED_DBF_NAME) - { - MM_CalculateBytesExtendedFieldName(camp); - MM_strnzcpy(nom_temp, FieldName, MM_MAX_LON_FIELD_NAME_DBF); - MM_ReturnValidClassicDBFFieldName(nom_temp); - nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF] = '\0'; - MM_strnzcpy(camp->ClassicalDBFFieldName, nom_temp, - MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF); - } - } - - if (FieldDescription) - strcpy(camp->FieldDescription[0], FieldDescription); - else - strcpy(camp->FieldDescription[0], "\0"); - camp->FieldType = FieldType; - camp->DecimalsIfFloat = DecimalsIfFloat; - camp->BytesPerField = BytesPerField; - return TRUE; -} - -size_t MM_DefineFirstPolygonFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp, - MM_BYTE n_decimals) -{ - MM_EXT_DBF_N_FIELDS i_camp = 0; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, - szInternalGraphicIdentifierEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); - bd_xp->IdGraficField = 0; - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte, - szNumberOfVerticesEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampPerimetreDefecte, - szPerimeterOfThePolygonEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, n_decimals); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_PERIMETRE; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampAreaDefecte, - szAreaOfThePolygonEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, - n_decimals); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_AREA; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNArcsDefecte, - szNumberOfArcsEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_ARCS; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNPoligonsDefecte, - szNumberOfElementaryPolygonsEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_POLIG; - i_camp++; - - return i_camp; -} - -size_t MM_DefineFirstArcFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp, - MM_BYTE n_decimals) -{ - MM_EXT_DBF_N_FIELDS i_camp; - - i_camp = 0; - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, - szInternalGraphicIdentifierEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); - bd_xp->IdGraficField = 0; - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte, - szNumberOfVerticesEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampLongitudArcDefecte, - szLenghtOfAarcEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, - n_decimals); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_LONG_ARC; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeIniDefecte, - szInitialNodeEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_INI; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeFiDefecte, - szFinalNodeEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, 0); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_FI; - i_camp++; - - return i_camp; -} - -size_t MM_DefineFirstNodeFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp) -{ - MM_EXT_DBF_N_FIELDS i_camp; - - i_camp = 0; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, - szInternalGraphicIdentifierEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); - bd_xp->IdGraficField = 0; - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampArcsANodeDefecte, - szNumberOfArcsToNodeEng, 'N', MM_MAX_AMPLADA_CAMP_N_DBF, - 0); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ARCS_A_NOD; - i_camp++; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampTipusNodeDefecte, - szNodeTypeEng, 'N', 1, 0); - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_TIPUS_NODE; - i_camp++; - - return i_camp; -} - -size_t MM_DefineFirstPointFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp) -{ - size_t i_camp = 0; - - MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte, - szInternalGraphicIdentifierEng, 'N', - MM_MAX_AMPLADA_CAMP_N_DBF, 0); - bd_xp->IdGraficField = 0; - (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC; - i_camp++; - - return i_camp; -} - -static int MM_SprintfDoubleWidth(char *cadena, int amplada, int n_decimals, - double valor_double, - MM_BOOLEAN *Error_sprintf_n_decimals) -{ -#define VALOR_LIMIT_IMPRIMIR_EN_FORMAT_E 1E+17 -#define VALOR_MASSA_PETIT_PER_IMPRIMIR_f 1E-17 - char cadena_treball[MM_CARACTERS_DOUBLE + 1]; - int retorn_printf; - - if (MM_IsNANDouble(valor_double)) - { - if (amplada < 3) - { - *cadena = *MM_EmptyString; - return EOF; - } - return sprintf(cadena, "NAN"); - } - if (MM_IsDoubleInfinit(valor_double)) - { - if (amplada < 3) - { - *cadena = *MM_EmptyString; - return EOF; - } - return sprintf(cadena, "INF"); - } - - *Error_sprintf_n_decimals = FALSE; - if (valor_double == 0) - { - retorn_printf = - sprintf(cadena_treball, "%*.*f", amplada, n_decimals, valor_double); - if (retorn_printf == EOF) - { - *cadena = *MM_EmptyString; - return retorn_printf; - } - - if (retorn_printf > amplada) - { - int escurcament = retorn_printf - amplada; - if (escurcament > n_decimals) - { - *cadena = *MM_EmptyString; - return EOF; - } - *Error_sprintf_n_decimals = TRUE; - n_decimals = n_decimals - escurcament; - retorn_printf = - sprintf(cadena, "%*.*f", amplada, n_decimals, valor_double); - } - else - strcpy(cadena, cadena_treball); - - return retorn_printf; - } - - if (valor_double > VALOR_LIMIT_IMPRIMIR_EN_FORMAT_E || - valor_double < -VALOR_LIMIT_IMPRIMIR_EN_FORMAT_E || - (valor_double < VALOR_MASSA_PETIT_PER_IMPRIMIR_f && - valor_double > -VALOR_MASSA_PETIT_PER_IMPRIMIR_f)) - { - retorn_printf = - sprintf(cadena_treball, "%*.*E", amplada, n_decimals, valor_double); - if (retorn_printf == EOF) - { - *cadena = *MM_EmptyString; - return retorn_printf; - } - if (retorn_printf > amplada) - { - int escurcament = retorn_printf - amplada; - if (escurcament > n_decimals) - { - *cadena = *MM_EmptyString; - return EOF; - } - *Error_sprintf_n_decimals = TRUE; - n_decimals = n_decimals - escurcament; - retorn_printf = - sprintf(cadena, "%*.*E", amplada, n_decimals, valor_double); - } - else - strcpy(cadena, cadena_treball); - - return retorn_printf; - } - - retorn_printf = - sprintf(cadena_treball, "%*.*f", amplada, n_decimals, valor_double); - if (retorn_printf == EOF) - { - *cadena = *MM_EmptyString; - return retorn_printf; - } - - if (retorn_printf > amplada) - { - int escurcament = retorn_printf - amplada; - if (escurcament > n_decimals) - { - *cadena = *MM_EmptyString; - return EOF; - } - *Error_sprintf_n_decimals = TRUE; - n_decimals = n_decimals - escurcament; - retorn_printf = - sprintf(cadena, "%*.*f", amplada, n_decimals, valor_double); - } - else - strcpy(cadena, cadena_treball); - - return retorn_printf; - -#undef VALOR_LIMIT_IMPRIMIR_EN_FORMAT_E -#undef VALOR_MASSA_PETIT_PER_IMPRIMIR_f -} // End of MM_SprintfDoubleWidth() - -static MM_BOOLEAN MM_EmptyString_function(const char *cadena) -{ - char *ptr; - - for (ptr = (char *)cadena; *ptr; ptr++) - if (*ptr != ' ' && *ptr != '\t') - return FALSE; - - return TRUE; -} - -int MM_SecureCopyStringFieldValue(char **pszStringDst, const char *pszStringSrc, - MM_EXT_DBF_N_FIELDS *nStringCurrentLenght) -{ - if (!pszStringSrc) - { - if (1 >= *nStringCurrentLenght) - { - (*pszStringDst) = realloc_function(*pszStringDst, 2); - if (!(*pszStringDst)) - return 1; - *nStringCurrentLenght = (MM_EXT_DBF_N_FIELDS)2; - } - strcpy(*pszStringDst, "\0"); - return 0; - } - - if (strlen(pszStringSrc) >= *nStringCurrentLenght) - { - (*pszStringDst) = - realloc_function(*pszStringDst, strlen(pszStringSrc) + 1); - if (!(*pszStringDst)) - return 1; - *nStringCurrentLenght = (MM_EXT_DBF_N_FIELDS)(strlen(pszStringSrc) + 1); - } - strcpy(*pszStringDst, pszStringSrc); - return 0; -} - -// This function assumes that all the file is saved in disk and closed. -int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, - MM_EXT_DBF_N_FIELDS nIField, - MM_BYTES_PER_FIELD_TYPE_DBF nNewWidth, - MM_BYTE nNewPrecision, - MM_BYTE que_fer_amb_reformatat_decimals) -{ - char *record, *whites = nullptr; - MM_BYTES_PER_FIELD_TYPE_DBF l_glop1, l_glop2, i_glop2; - MM_EXT_DBF_N_RECORDS nfitx, i_reg; - int canvi_amplada; // change width - GInt32 j; - MM_EXT_DBF_N_FIELDS i_camp; - size_t retorn_fwrite; - int retorn_TruncaFitxer; - - MM_BOOLEAN error_sprintf_n_decimals = FALSE; - - canvi_amplada = nNewWidth - data_base_XP->pField[nIField].BytesPerField; - - if (data_base_XP->nRecords != 0) - { - l_glop1 = data_base_XP->pField[nIField].AcumulatedBytes; - i_glop2 = l_glop1 + data_base_XP->pField[nIField].BytesPerField; - if (nIField == data_base_XP->nFields - 1) - l_glop2 = 0; - else - l_glop2 = data_base_XP->BytesPerRecord - - data_base_XP->pField[nIField + 1].AcumulatedBytes; - - if ((record = calloc_function((size_t)data_base_XP->BytesPerRecord)) == - nullptr) - return 1; - - record[data_base_XP->BytesPerRecord - 1] = MM_SetEndOfString; - - if ((whites = (char *)calloc_function((size_t)nNewWidth)) == nullptr) - { - free_function(record); - return 1; - } - memset(whites, ' ', nNewWidth); - - nfitx = data_base_XP->nRecords; - -#ifdef _MSC_VER -#pragma warning(disable : 4127) -#endif - for (i_reg = (canvi_amplada < 0 ? 0 : nfitx - 1); TRUE;) -#ifdef _MSC_VER -#pragma warning(default : 4127) -#endif - { - if (0 != fseek_function(data_base_XP->pfDataBase, - data_base_XP->FirstRecordOffset + - (MM_FILE_OFFSET)i_reg * - data_base_XP->BytesPerRecord, - SEEK_SET)) - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - - if (1 != fread_function(record, data_base_XP->BytesPerRecord, 1, - data_base_XP->pfDataBase)) - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - - if (0 != - fseek_function( - data_base_XP->pfDataBase, - (MM_FILE_OFFSET)data_base_XP->FirstRecordOffset + - i_reg * ((MM_FILE_OFFSET)data_base_XP->BytesPerRecord + - canvi_amplada), - SEEK_SET)) - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - - if (1 != - fwrite_function(record, l_glop1, 1, data_base_XP->pfDataBase)) - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - - switch (data_base_XP->pField[nIField].FieldType) - { - case 'C': - case 'L': - memcpy(whites, record + l_glop1, - (canvi_amplada < 0 - ? nNewWidth - : data_base_XP->pField[nIField].BytesPerField)); - retorn_fwrite = fwrite_function(whites, nNewWidth, 1, - data_base_XP->pfDataBase); - - if (1 != retorn_fwrite) - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - break; - case 'N': - if (nNewPrecision == - data_base_XP->pField[nIField].DecimalsIfFloat || - que_fer_amb_reformatat_decimals == - MM_NOU_N_DECIMALS_NO_APLICA) - que_fer_amb_reformatat_decimals = - MM_NOMES_DOCUMENTAR_NOU_N_DECIMALS; - else if (que_fer_amb_reformatat_decimals == - MM_PREGUNTA_SI_APLICAR_NOU_N_DECIM) - que_fer_amb_reformatat_decimals = - MM_NOMES_DOCUMENTAR_NOU_N_DECIMALS; - - if (que_fer_amb_reformatat_decimals == - MM_NOMES_DOCUMENTAR_NOU_N_DECIMALS) - { - if (canvi_amplada >= 0) - { - if (1 != - fwrite_function(whites, canvi_amplada, 1, - data_base_XP->pfDataBase) || - 1 != fwrite_function( - record + l_glop1, - data_base_XP->pField[nIField] - .BytesPerField, - 1, data_base_XP->pfDataBase)) - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - } - else if (canvi_amplada < 0) - { - -#ifdef _MSC_VER -#pragma warning(disable : 4127) -#endif - for (j = (GInt32)(l_glop1 + - (data_base_XP->pField[nIField] - .BytesPerField - - 1)); - TRUE; j--) -#ifdef _MSC_VER -#pragma warning(default : 4127) -#endif - { - if (j < (GInt32)l_glop1 || record[j] == ' ') - { - j++; - break; - } - } - - if ((data_base_XP->pField[nIField].BytesPerField + - l_glop1 - j) < nNewWidth) - j -= (GInt32)(nNewWidth - - (data_base_XP->pField[nIField] - .BytesPerField + - l_glop1 - j)); - - retorn_fwrite = - fwrite_function(record + j, nNewWidth, 1, - data_base_XP->pfDataBase); - if (1 != retorn_fwrite) - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - } - } - else // MM_APLICAR_NOU_N_DECIMALS - { - double valor; - char *sz_valor; - - if ((sz_valor = calloc_function( - max_function(nNewWidth, - data_base_XP->pField[nIField] - .BytesPerField) + - 1)) == - nullptr) // Sumo 1 per poder posar-hi el \0 - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - memcpy(sz_valor, record + l_glop1, - data_base_XP->pField[nIField].BytesPerField); - sz_valor[data_base_XP->pField[nIField].BytesPerField] = - 0; - - if (!MM_EmptyString_function(sz_valor)) - { - if (sscanf(sz_valor, "%lf", &valor) != 1) - memset( - sz_valor, *MM_BlankString, - max_function(nNewWidth, - data_base_XP->pField[nIField] - .BytesPerField)); - else - { - MM_SprintfDoubleWidth( - sz_valor, nNewWidth, nNewPrecision, valor, - &error_sprintf_n_decimals); - } - - retorn_fwrite = - fwrite_function(sz_valor, nNewWidth, 1, - data_base_XP->pfDataBase); - if (1 != retorn_fwrite) - { - if (whites) - free_function(whites); - free_function(record); - free_function(sz_valor); - return 1; - } - } - else - { - memset(sz_valor, *MM_BlankString, nNewWidth); - retorn_fwrite = - fwrite_function(sz_valor, nNewWidth, 1, - data_base_XP->pfDataBase); - if (1 != retorn_fwrite) - { - if (whites) - free_function(whites); - free_function(record); - free_function(sz_valor); - return 1; - } - } - free_function(sz_valor); - } - break; - default: - free_function(whites); - free_function(record); - return 1; - } - if (l_glop2) - { - retorn_fwrite = fwrite_function(record + i_glop2, l_glop2, 1, - data_base_XP->pfDataBase); - if (1 != retorn_fwrite) - { - if (whites) - free_function(whites); - free_function(record); - return 1; - } - } - - if (canvi_amplada < 0) - { - if (i_reg + 1 == nfitx) - break; - i_reg++; - } - else - { - if (i_reg == 0) - break; - i_reg--; - } - } - - if (whites) - free_function(whites); - free_function(record); - - retorn_TruncaFitxer = TruncateFile_function( - data_base_XP->pfDataBase, - (MM_FILE_OFFSET)data_base_XP->FirstRecordOffset + - (MM_FILE_OFFSET)data_base_XP->nRecords * - ((MM_FILE_OFFSET)data_base_XP->BytesPerRecord + - canvi_amplada)); - if (canvi_amplada < 0 && retorn_TruncaFitxer) - return 1; - } /* Fi de registres de != 0*/ - - if (canvi_amplada != 0) - { - data_base_XP->pField[nIField].BytesPerField = nNewWidth; - data_base_XP->BytesPerRecord += canvi_amplada; - for (i_camp = (MM_EXT_DBF_N_FIELDS)(nIField + 1); - i_camp < data_base_XP->nFields; i_camp++) - data_base_XP->pField[i_camp].AcumulatedBytes += canvi_amplada; - } - data_base_XP->pField[nIField].DecimalsIfFloat = nNewPrecision; - - //DonaData(&(data_base_XP->day), &(data_base_XP->month), &(data_base_XP->year)); - - if ((MM_UpdateEntireHeader(data_base_XP)) == FALSE) - return 1; - - return 0; -} /* End of MMChangeCFieldWidthDBF() */ - -static void MM_AdoptHeight(double *desti, const double *proposta, uint32_t flag) -{ - if (*proposta == MM_NODATA_COORD_Z) - return; - - if (flag & MM_STRING_HIGHEST_ALTITUDE) - { - if (*desti == MM_NODATA_COORD_Z || *desti < *proposta) - *desti = *proposta; - } - else if (flag & MM_STRING_LOWEST_ALTITUDE) - { - if (*desti == MM_NODATA_COORD_Z || *desti > *proposta) - *desti = *proposta; - } - else - { - // First coordinate of this vertice - if (*desti == MM_NODATA_COORD_Z) - *desti = *proposta; - } -} - -int MM_GetArcHeights(double *coord_z, FILE_TYPE *pF, MM_N_VERTICES_TYPE n_vrt, - struct MM_ZD *pZDescription, uint32_t flag) -{ - MM_N_HEIGHT_TYPE i; - MM_N_VERTICES_TYPE i_vrt; - double *pcoord_z; - MM_N_HEIGHT_TYPE n_alcada, n_h_total; - int tipus; - double *alcada = nullptr, *palcada, *palcada_i; -#define MM_N_ALCADA_LOCAL 50 // Nr of local heights - double local_CinquantaAlcades[MM_N_ALCADA_LOCAL]; - - for (i_vrt = 0; i_vrt < n_vrt; i_vrt++) - coord_z[i_vrt] = MM_NODATA_COORD_Z; - - tipus = MM_ARC_HEIGHT_TYPE(pZDescription->nZCount); - n_alcada = MM_ARC_N_HEIGHTS(pZDescription->nZCount); - if (n_vrt == 0 || n_alcada == 0) - return 0; - - if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX) - n_h_total = (MM_N_HEIGHT_TYPE)n_vrt * n_alcada; - else - n_h_total = n_alcada; - - if (n_h_total <= MM_N_ALCADA_LOCAL) - palcada = local_CinquantaAlcades; - else - { - if (MMCheckSize_t(n_vrt * sizeof(double) * n_alcada, 1)) - return 1; - if (nullptr == (palcada = alcada = calloc_function( - (size_t)n_vrt * sizeof(double) * n_alcada))) - return 1; - } - - if (fseek_function(pF, pZDescription->nOffsetZ, SEEK_SET)) - { - if (alcada) - free_function(alcada); - return 1; - } - if (n_h_total != (MM_N_HEIGHT_TYPE)fread_function(palcada, sizeof(double), - n_h_total, pF)) - { - if (alcada) - free_function(alcada); - return 1; - } - - if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX) - { - palcada_i = palcada; - for (i = 0; i < n_alcada; i++) - { - for (i_vrt = 0, pcoord_z = coord_z; i_vrt < n_vrt; - i_vrt++, pcoord_z++, palcada_i++) - MM_AdoptHeight(pcoord_z, palcada_i, flag); - } - } - else - { - palcada_i = palcada; - pcoord_z = coord_z; - for (i = 0; i < n_alcada; i++, palcada_i++) - MM_AdoptHeight(pcoord_z, palcada_i, flag); - - if (*pcoord_z != MM_NODATA_COORD_Z) - { - /*Copio el mateix valor a totes les alcades.*/ - for (i_vrt = 1, pcoord_z++; i_vrt < (size_t)n_vrt; - i_vrt++, pcoord_z++) - *pcoord_z = *coord_z; - } - } - if (alcada) - free_function(alcada); - return 0; -} // End of MM_GetArcHeights() - -static char *MM_l_RemoveWhitespacesFromEndOfString(char *punter, - size_t l_cadena) -{ - int longitud_cadena = (int)l_cadena; - if (longitud_cadena-- == 0) - return punter; - - if (punter[longitud_cadena] != ' ' && punter[longitud_cadena] != '\t') - return punter; - longitud_cadena--; - - while (longitud_cadena > -1) - { - if (punter[longitud_cadena] != ' ' && punter[longitud_cadena] != '\t') - { - break; - } - longitud_cadena--; - } - - punter[++longitud_cadena] = '\0'; - return punter; -} - -char *MM_RemoveInitial_and_FinalQuotationMarks(char *cadena) -{ - char *ptr1, *ptr2; - char cometa = '"'; - - if (*cadena == cometa) - { - ptr1 = cadena; - ptr2 = ptr1 + 1; - if (*ptr2) - { - while (*ptr2) - { - *ptr1 = *ptr2; - ptr1++; - ptr2++; - } - if (*ptr1 == cometa) - *(ptr1 - 1) = 0; - else - *ptr1 = 0; - } - } - return cadena; -} /* End of MM_RemoveInitial_and_FinalQuotationMarks() */ - -char *MM_RemoveLeadingWhitespaceOfString(char *cadena) -{ - char *ptr; - char *ptr2; - - if (cadena == nullptr) - return cadena; - - for (ptr = cadena; *ptr && (*ptr == ' ' || *ptr == '\t'); ptr++) - continue; - - if (ptr != cadena) - { - ptr2 = cadena; - while (*ptr) - { - *ptr2 = *ptr; - ptr2++; - ptr++; - } - *ptr2 = 0; - } - return cadena; -} - -char *MM_RemoveWhitespacesFromEndOfString(char *str) -{ - const char *s; - - if (str == nullptr) - return str; - - for (s = str; *s; ++s) - continue; - return MM_l_RemoveWhitespacesFromEndOfString(str, (s - str)); -} - -struct MM_ID_GRAFIC_MULTIPLE_RECORD * -MMCreateExtendedDBFIndex(FILE_TYPE *f, MM_EXT_DBF_N_RECORDS nNumberOfRecords, - MM_FIRST_RECORD_OFFSET_TYPE offset_1era, - MM_ACUMULATED_BYTES_TYPE_DBF bytes_per_fitxa, - MM_ACUMULATED_BYTES_TYPE_DBF bytes_acumulats_id_grafic, - MM_BYTES_PER_FIELD_TYPE_DBF bytes_id_grafic, - MM_BOOLEAN *isListField, MM_EXT_DBF_N_RECORDS *nMaxN) -{ - struct MM_ID_GRAFIC_MULTIPLE_RECORD *id; - MM_EXT_DBF_N_RECORDS i_dbf; - MM_EXT_DBF_SIGNED_N_RECORDS i, id_grafic; - char *fitxa; - MM_BYTES_PER_FIELD_TYPE_DBF bytes_final_id_principi_id1 = - bytes_per_fitxa - bytes_id_grafic; - - *isListField = FALSE; - *nMaxN = 0; - if (!nNumberOfRecords) - return nullptr; // No elements to read - - if (MMCheckSize_t(nNumberOfRecords * sizeof(*id), 1)) - return nullptr; - if (nullptr == (id = (struct MM_ID_GRAFIC_MULTIPLE_RECORD *)calloc_function( - (size_t)nNumberOfRecords * sizeof(*id)))) - return nullptr; - - if (MMCheckSize_t(bytes_id_grafic + 1, 1)) - return nullptr; - if (nullptr == - (fitxa = (char *)calloc_function((size_t)bytes_id_grafic + 1))) - { - free_function(id); - return nullptr; - } - fitxa[bytes_id_grafic] = '\0'; - - fseek_function(f, - (MM_FILE_OFFSET)offset_1era + - (MM_FILE_OFFSET)bytes_acumulats_id_grafic, - SEEK_SET); - - i_dbf = 0; - do - { - if (i_dbf == nNumberOfRecords || - fread_function(fitxa, 1, bytes_id_grafic, f) != - (size_t)bytes_id_grafic) - { - free_function(id); - free_function(fitxa); - return nullptr; - } - i_dbf++; - } while (1 != - sscanf(fitxa, scanf_MM_EXT_DBF_SIGNED_N_RECORDS, &id_grafic) || - id_grafic < 0); - i = 0; - -#ifdef _MSC_VER -#pragma warning(disable : 4127) -#endif - while (TRUE) -#ifdef _MSC_VER -#pragma warning(default : 4127) -#endif - { - if (i > id_grafic) - { - free_function(id); - free_function(fitxa); - return nullptr; - } - i = id_grafic; - if (i >= (MM_EXT_DBF_SIGNED_N_RECORDS)nNumberOfRecords) - { - free_function(fitxa); - return id; - } - id[(size_t)i].offset = (MM_FILE_OFFSET)offset_1era + - (MM_FILE_OFFSET)(i_dbf - 1) * bytes_per_fitxa; - do - { - id[(size_t)i].nMR++; - if (!(*isListField) && id[(size_t)i].nMR > 1) - *isListField = TRUE; - if (*nMaxN < id[(size_t)i].nMR) - *nMaxN = id[(size_t)i].nMR; - - if (i_dbf == nNumberOfRecords) - { - free_function(fitxa); - return id; - } - fseek_function(f, bytes_final_id_principi_id1, SEEK_CUR); - if (fread_function(fitxa, 1, bytes_id_grafic, f) != - (size_t)bytes_id_grafic) - { - free_function(id); - free_function(fitxa); - return nullptr; - } - if (1 != sscanf(fitxa, scanf_MM_EXT_DBF_SIGNED_N_RECORDS, - &id_grafic) || - id_grafic >= (MM_EXT_DBF_SIGNED_N_RECORDS)nNumberOfRecords) - { - free_function(fitxa); - return id; - } - i_dbf++; - } while (id_grafic == i); - } -} // End of MMCreateExtendedDBFIndex() - -#ifdef GDAL_COMPILATION -CPL_C_END // Necessary for compiling in GDAL project -#endif diff --git a/ogr/ogrsf_frmts/miramon/mm_gdal_functions.h b/ogr/ogrsf_frmts/miramon/mm_gdal_functions.h index 3ce6388fd614..222fc8af16d9 100644 --- a/ogr/ogrsf_frmts/miramon/mm_gdal_functions.h +++ b/ogr/ogrsf_frmts/miramon/mm_gdal_functions.h @@ -20,30 +20,32 @@ CPL_C_START // Necessary for compiling in GDAL project // Log. It should be temporal extern const char *MM_pszLogFilename; -#define LOG_STR(str) (Log((str), __LINE__)) -#define LOG_ACTION(action) ((void)Log(#action, __LINE__), (action)) +#define LOG_STR(str) (MMLog((str), __LINE__)) +#define LOG_ACTION(action) ((void)MMLog(#action, __LINE__), (action)) -const char *Log(const char *pszMsg, int nLineNumber); +const char *MMLog(const char *pszMsg, int nLineNumber); + +void fclose_and_nullify(FILE_TYPE **pFunc); // MiraMon feature table descriptors #define MM_MAX_IDENTIFIER_SIZE 50 -#define MM_a_WITH_GRAVE (-32) -#define MM_a_WITH_ACUTE (-31) -#define MM_e_WITH_GRAVE (-24) -#define MM_e_WITH_ACUTE (-23) -#define MM_i_WITH_ACUTE (-19) -#define MM_o_WITH_GRAVE (-14) -#define MM_o_WITH_ACUTE (-13) -#define MM_u_WITH_ACUTE (-6) - -#define MM_A_WITH_GRAVE (-64) -#define MM_A_WITH_ACUTE (-63) -#define MM_E_WITH_GRAVE (-56) -#define MM_E_WITH_ACUTE (-55) -#define MM_I_WITH_ACUTE (-51) -#define MM_O_WITH_GRAVE (-46) -#define MM_O_WITH_ACUTE (-45) -#define MM_U_WITH_ACUTE (-38) +#define MM_a_WITH_GRAVE 224 +#define MM_a_WITH_ACUTE 225 +#define MM_e_WITH_GRAVE 232 +#define MM_e_WITH_ACUTE 233 +#define MM_i_WITH_ACUTE 237 +#define MM_o_WITH_GRAVE 242 +#define MM_o_WITH_ACUTE 243 +#define MM_u_WITH_ACUTE 250 + +#define MM_A_WITH_GRAVE 192 +#define MM_A_WITH_ACUTE 193 +#define MM_E_WITH_GRAVE 200 +#define MM_E_WITH_ACUTE 201 +#define MM_I_WITH_ACUTE 205 +#define MM_O_WITH_GRAVE 210 +#define MM_O_WITH_ACUTE 211 +#define MM_U_WITH_ACUTE 218 // In case of diaeresis use "_WITH_DIAERESIS" // In case of cedilla use "_WITH_CEDILLA" @@ -54,49 +56,51 @@ void MM_FillFieldDescriptorByLanguage(void); extern char szInternalGraphicIdentifierEng[]; extern char szInternalGraphicIdentifierCat[]; -extern char szInternalGraphicIdentifierEsp[]; +extern char szInternalGraphicIdentifierSpa[]; extern char szNumberOfVerticesEng[]; extern char szNumberOfVerticesCat[]; -extern char szNumberOfVerticesEsp[]; +extern char szNumberOfVerticesSpa[]; -extern char szLenghtOfAarcEng[]; -extern char szLenghtOfAarcCat[]; -extern char szLenghtOfAarcEsp[]; +extern char szLengthOfAarcEng[]; +extern char szLengthOfAarcCat[]; +extern char szLengthOfAarcSpa[]; extern char szInitialNodeEng[]; extern char szInitialNodeCat[]; -extern char szInitialNodeEsp[]; +extern char szInitialNodeSpa[]; extern char szFinalNodeEng[]; extern char szFinalNodeCat[]; -extern char szFinalNodeEsp[]; +extern char szFinalNodeSpa[]; extern char szNumberOfArcsToNodeEng[]; extern char szNumberOfArcsToNodeCat[]; -extern char szNumberOfArcsToNodeEsp[]; +extern char szNumberOfArcsToNodeSpa[]; extern char szNodeTypeEng[]; extern char szNodeTypeCat[]; -extern char szNodeTypeEsp[]; +extern char szNodeTypeSpa[]; extern char szPerimeterOfThePolygonEng[]; extern char szPerimeterOfThePolygonCat[]; -extern char szPerimeterOfThePolygonEsp[]; +extern char szPerimeterOfThePolygonSpa[]; extern char szAreaOfThePolygonEng[]; extern char szAreaOfThePolygonCat[]; -extern char szAreaOfThePolygonEsp[]; +extern char szAreaOfThePolygonSpa[]; extern char szNumberOfArcsEng[]; extern char szNumberOfArcsCat[]; -extern char szNumberOfArcsEsp[]; +extern char szNumberOfArcsSpa[]; extern char szNumberOfElementaryPolygonsEng[]; extern char szNumberOfElementaryPolygonsCat[]; -extern char szNumberOfElementaryPolygonsEsp[]; +extern char szNumberOfElementaryPolygonsSpa[]; -char *MM_strnzcpy(char *dest, const char *src, size_t maxlen); +#ifndef GDAL_COMPILATION +char *CPLStrlcpy(char *dest, const char *src, size_t maxlen); +#endif char *MM_oemansi(char *szcadena); char *MM_oemansi_n(char *szcadena, size_t n_bytes); void MM_InitializeField(struct MM_FIELD *camp); @@ -115,7 +119,8 @@ int MM_DuplicateFieldDBXP(struct MM_FIELD *camp_final, int MM_WriteNRecordsMMBD_XPFile(struct MMAdmDatabase *MMAdmDB); size_t MM_DefineFirstPolygonFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp, - MM_BYTE n_decimals); + MM_BYTE n_perimeter_decimals, + MM_BYTE n_area_decimals_decimals); size_t MM_DefineFirstArcFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp, MM_BYTE n_decimals); size_t MM_DefineFirstNodeFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp); @@ -124,11 +129,16 @@ int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( struct MM_FIELD *camp, struct MM_DATA_BASE_XP *bd_xp, MM_BOOLEAN no_modifica_descriptor, size_t mida_nom); +int MMWritePreformatedNumberValueToRecordDBXP( + struct MiraMonVectLayerInfo *hMiraMonLayer, char *registre, + const struct MM_FIELD *camp, const char *valor); int MMWriteValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, char *registre, const struct MM_FIELD *camp, const void *valor, MM_BOOLEAN is_64); +int MM_SprintfDoubleSignifFigures(char *szChain, size_t size_szChain, + int nSignifFigures, double dfRealValue); int MM_SecureCopyStringFieldValue(char **pszStringDst, const char *pszStringSrc, - MM_EXT_DBF_N_FIELDS *nStringCurrentLenght); + MM_EXT_DBF_N_FIELDS *nStringCurrentLength); int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP, MM_EXT_DBF_N_FIELDS quincamp, MM_BYTES_PER_FIELD_TYPE_DBF novaamplada, @@ -144,13 +154,13 @@ char *MM_RemoveWhitespacesFromEndOfString(char *str); char *MM_RemoveLeadingWhitespaceOfString(char *cadena); // DBF -struct MM_ID_GRAFIC_MULTIPLE_RECORD * -MMCreateExtendedDBFIndex(FILE_TYPE *f, MM_EXT_DBF_N_RECORDS n_dbf, - MM_FIRST_RECORD_OFFSET_TYPE offset_1era, - MM_ACUMULATED_BYTES_TYPE_DBF bytes_per_fitxa, - MM_ACUMULATED_BYTES_TYPE_DBF bytes_acumulats_id_grafic, - MM_BYTES_PER_FIELD_TYPE_DBF bytes_id_grafic, - MM_BOOLEAN *isListField, MM_EXT_DBF_N_RECORDS *nMaxN); +struct MM_ID_GRAFIC_MULTIPLE_RECORD *MMCreateExtendedDBFIndex( + FILE_TYPE *f, MM_EXT_DBF_N_RECORDS n_dbf, + MM_FIRST_RECORD_OFFSET_TYPE offset_1era, + MM_ACCUMULATED_BYTES_TYPE_DBF bytes_per_fitxa, + MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats_id_grafic, + MM_BYTES_PER_FIELD_TYPE_DBF bytes_id_grafic, MM_BOOLEAN *isListField, + MM_EXT_DBF_N_RECORDS *nMaxN); int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName, struct MM_DATA_BASE_XP *pMMBDXP, diff --git a/ogr/ogrsf_frmts/miramon/mm_gdal_structures.h b/ogr/ogrsf_frmts/miramon/mm_gdal_structures.h index f006105cbb24..58133dca3ff1 100644 --- a/ogr/ogrsf_frmts/miramon/mm_gdal_structures.h +++ b/ogr/ogrsf_frmts/miramon/mm_gdal_structures.h @@ -49,16 +49,16 @@ review the code of the driver. MM_BYTES_PER_FIELD_TYPE_DBF BytesPerField; // In MiraMon code: MM_TIPUS_BYTES_PER_CAMP_DBF BytesPerCamp - // Acumulated bytes before a field starts - MM_ACUMULATED_BYTES_TYPE_DBF - AcumulatedBytes; // In MiraMon code: - // MM_TIPUS_BYTES_ACUMULATS_DBF BytesAcumulats + // Accumulated bytes before a field starts + MM_ACCUMULATED_BYTES_TYPE_DBF + AccumulatedBytes; // In MiraMon code: + // MM_TIPUS_BYTES_ACUMULATS_DBF BytesAcumulats // Not used in GDAL char *Separator[MM_NUM_IDIOMES_MD_MULTIDIOMA]; // In MiraMon code: separador - // Description of the field + // Description of the field (alternative name) char FieldDescription [MM_NUM_IDIOMES_MD_MULTIDIOMA] [MM_MAX_LON_DESCRIPCIO_CAMP_DBF]; // In MiraMon code: DescripcioCamp @@ -87,7 +87,7 @@ struct MM_DATA_BASE_XP // MiraMon table Structure char ReadingMode[4]; // In MiraMon code: ModeLectura MM_EXT_DBF_N_RECORDS nRecords; // In MiraMon code: n_fitxes - MM_ACUMULATED_BYTES_TYPE_DBF + MM_ACCUMULATED_BYTES_TYPE_DBF BytesPerRecord; // In MiraMon code: BytesPerFitxa MM_EXT_DBF_N_FIELDS nFields; // In MiraMon code: ncamps struct MM_FIELD *pField; // In MiraMon code: Camp @@ -101,13 +101,13 @@ struct MM_DATA_BASE_XP // MiraMon table Structure MM_BYTE dbf_version; // In MiraMon code: versio_dbf - MM_BYTE reserved_1 + MM_BYTE reserved_1 // Used in extended DBF format to recompose BytesPerRecord [MM_MAX_LON_RESERVAT_1_BASE_DADES_XP]; // In MiraMon code: reservat_1 MM_BYTE transaction_flag; MM_BYTE encryption_flag; MM_BYTE dbf_on_a_LAN[MM_MAX_LON_DBF_ON_A_LAN_BASE_DADES_XP]; MM_BYTE MDX_flag; - MM_BYTE reserved_2 + MM_BYTE reserved_2 // Used in extended DBF format to recompose BytesPerRecord [MM_MAX_LON_RESERVAT_2_BASE_DADES_XP]; // In MiraMon code: reservat_2 }; #ifdef GDAL_COMPILATION diff --git a/ogr/ogrsf_frmts/miramon/mm_rdlayr.c b/ogr/ogrsf_frmts/miramon/mm_rdlayr.c index f6bb562cefdd..4a8a2ec09126 100644 --- a/ogr/ogrsf_frmts/miramon/mm_rdlayr.c +++ b/ogr/ogrsf_frmts/miramon/mm_rdlayr.c @@ -28,7 +28,7 @@ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifdef GDAL_COMPILATION @@ -50,14 +50,13 @@ CPL_C_START // Necessary for compiling in GDAL project #endif - static char local_message[MAX_LOCAL_MESSAGE]; + /* -------------------------------------------------------------------- */ + /* Reading MiraMon format file functions */ + /* -------------------------------------------------------------------- */ -/* -------------------------------------------------------------------- */ -/* Reading MiraMon format file functions */ -/* -------------------------------------------------------------------- */ - -// Initializes a MiraMon vector layer for reading -int MMInitLayerToRead(struct MiraMonVectLayerInfo *hMiraMonLayer, + // Initializes a MiraMon vector layer for reading + int + MMInitLayerToRead(struct MiraMonVectLayerInfo *hMiraMonLayer, FILE_TYPE *m_fp, const char *pszFilename) { char szResult[MM_MAX_ID_SNY + 10]; @@ -66,11 +65,10 @@ int MMInitLayerToRead(struct MiraMonVectLayerInfo *hMiraMonLayer, memset(hMiraMonLayer, 0, sizeof(*hMiraMonLayer)); if (MMReadHeader(m_fp, &hMiraMonLayer->TopHeader)) { - sprintf(local_message, "Error reading header of file %s", pszFilename); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error reading header of file %s", pszFilename); return 1; } - hMiraMonLayer->nMemoryRatio = 1.0; hMiraMonLayer->ReadOrWrite = MM_READING_MODE; strcpy(hMiraMonLayer->pszFlags, "rb"); @@ -178,7 +176,7 @@ int MMInitLayerToRead(struct MiraMonVectLayerInfo *hMiraMonLayer, if (hMiraMonLayer->pSRS && strcmp(hMiraMonLayer->pSRS, "plane")) { MMCPLWarning(CE_Warning, CPLE_NotSupported, - "The MiraMon layer HRS has no equivalent " + "The MiraMon layer SRS has no equivalent " "in EPSG code"); } } @@ -253,7 +251,7 @@ MMAddStringLineCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer, pF, pArcHeader[i_elem].nElemCount, pZDescription + i_elem, flag_z); - // If there is a value for Z-nodata in GDAL this lines can be uncomented + // If there is a value for Z-nodata in GDAL this lines can be uncommented // and MM_GDAL_NODATA_COORD_Z can be defined /*if(!DOUBLES_DIFERENTS_DJ(punts_z[k], MM_NODATA_COORD_Z)) { @@ -317,7 +315,7 @@ MMAddStringLineCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer, pF, pArcHeader[i_elem].nElemCount, pZDescription + i_elem, flag_z); - // If there is a value for Z-nodata in GDAL this lines can be uncomented + // If there is a value for Z-nodata in GDAL this lines can be uncommented // and MM_GDAL_NODATA_COORD_Z can be defined /*if(!DOUBLES_DIFERENTS_DJ(punts_z[k], MM_NODATA_COORD_Z)) { @@ -346,10 +344,23 @@ MMGetMultiPolygonCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer, MM_BOOLEAN bAvoidFirst; MM_N_VERTICES_TYPE nNAcumulVertices = 0; + // Checking if the index of the polygon is in the correct range. + if (i_pol >= hMiraMonLayer->TopHeader.nElemCount) + return 1; + MMResetFeatureGeometry(&hMiraMonLayer->ReadFeature); MMResetFeatureRecord(&hMiraMonLayer->ReadFeature); pPolHeader = hMiraMonLayer->MMPolygon.pPolHeader + i_pol; + // It's accepted not having arcs in the universal polygon + if (!pPolHeader->nArcsCount) + { + if (i_pol == 0) + return 0; + else + return 1; + } + if (MMResizeMiraMonPolygonArcs(&hMiraMonLayer->pArcs, &hMiraMonLayer->nMaxArcs, pPolHeader->nArcsCount, 0, 0)) @@ -379,13 +390,19 @@ MMGetMultiPolygonCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer, &hMiraMonLayer->ReadFeature.pNCoordRing, &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10, 10)) + { + free_function(pBuffer); return 1; + } if (MMResizeVFGPointer(&hMiraMonLayer->ReadFeature.flag_VFG, &hMiraMonLayer->ReadFeature.nMaxVFG, (MM_INTERNAL_FID)pPolHeader->nArcsCount, 0, 0)) // Perhaps more memory than needed + { + free_function(pBuffer); return 1; + } // Preparing memory for all coordinates hMiraMonLayer->ReadFeature.pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] = @@ -413,6 +430,21 @@ MMGetMultiPolygonCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer, return 1; } + if (hMiraMonLayer->MMPolygon.MMArc.pArcHeader == nullptr) + { + if (pBuffer) + free_function(pBuffer); + return 1; + } + + // Checking if the index of the arc is in the correct range. + if ((hMiraMonLayer->pArcs + nIndex)->nIArc >= + hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount) + { + free_function(pBuffer); + return 1; + } + pArcHeader = hMiraMonLayer->MMPolygon.MMArc.pArcHeader + (hMiraMonLayer->pArcs + nIndex)->nIArc; hMiraMonLayer->ReadFeature @@ -425,7 +457,10 @@ MMGetMultiPolygonCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer, hMiraMonLayer->ReadFeature .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings], 0, 0)) + { + free_function(pBuffer); return 1; + } hMiraMonLayer->FlushPAL.CurrentOffset = 0; @@ -465,14 +500,20 @@ MMGetMultiPolygonCoordinates(struct MiraMonVectLayerInfo *hMiraMonLayer, (hMiraMonLayer->pArcs + nIndex)->nIArc, flag_z, nNAcumulVertices, bAvoidFirst, (hMiraMonLayer->pArcs + nIndex)->VFG)) + { + free_function(pBuffer); return 1; + } if (MMResize_MM_N_VERTICES_TYPE_Pointer( &hMiraMonLayer->ReadFeature.pNCoordRing, &hMiraMonLayer->ReadFeature.nMaxpNCoordRing, (MM_N_VERTICES_TYPE)hMiraMonLayer->ReadFeature.nNRings + 1, 10, 10)) + { + free_function(pBuffer); return 1; + } hMiraMonLayer->ReadFeature .pNCoordRing[hMiraMonLayer->ReadFeature.nNRings] += @@ -548,16 +589,19 @@ int MMGetGeoFeatureFromVector(struct MiraMonVectLayerInfo *hMiraMonLayer, { pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription + i_elem; + if (pZDescription->nZCount == INT_MIN) + return 1; num = MM_ARC_TOTAL_N_HEIGHTS_DISK(pZDescription->nZCount, 1); + + if (MMResizeDoublePointer(&hMiraMonLayer->ReadFeature.pZCoord, + &hMiraMonLayer->ReadFeature.nMaxpZCoord, + 1, 1, 1)) + return 1; + if (num == 0) hMiraMonLayer->ReadFeature.pZCoord[0] = MM_NODATA_COORD_Z; else { - if (MMResizeDoublePointer( - &hMiraMonLayer->ReadFeature.pZCoord, - &hMiraMonLayer->ReadFeature.nMaxpZCoord, 1, 1, 1)) - return 1; - if (flag_z == MM_STRING_HIGHEST_ALTITUDE) // Max z cz = pZDescription->dfBBmaxz; else if (flag_z == MM_STRING_LOWEST_ALTITUDE) // Min z @@ -574,7 +618,7 @@ int MMGetGeoFeatureFromVector(struct MiraMonVectLayerInfo *hMiraMonLayer, return 1; } } - // If there is a value for Z-nodata in GDAL this lines can be uncomented + // If there is a value for Z-nodata in GDAL this lines can be uncommented // and MM_GDAL_NODATA_COORD_Z can be defined /*if(!DOUBLES_DIFERENTS_DJ(cz, MM_NODATA_COORD_Z)) hMiraMonLayer->ReadFeature.pZCoord[0]=MM_GDAL_NODATA_COORD_Z; @@ -620,8 +664,8 @@ int MM_ReadExtendedDBFHeader(struct MiraMonVectLayerInfo *hMiraMonLayer) struct MM_DATA_BASE_XP *pMMBDXP; const char *szDBFFileName = nullptr; - // If readed don't read again. It happens when Polygon reads - // the database and then in initArc() it's readed again. + // If read don't read again. It happens when Polygon reads + // the database and then in initArc() it's read again. if (hMiraMonLayer->pMMBDXP) return 0; @@ -648,15 +692,13 @@ int MM_ReadExtendedDBFHeader(struct MiraMonVectLayerInfo *hMiraMonLayer) if (MM_ReadExtendedDBFHeaderFromFile(szDBFFileName, pMMBDXP, pszRelFile)) { - sprintf(local_message, "Error reading the format in the DBF file %s.", - szDBFFileName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error reading the format in the DBF file %s.", + szDBFFileName); return 1; } - fclose_function(pMMBDXP->pfDataBase); - pMMBDXP->pfDataBase = nullptr; - + fclose_and_nullify(&pMMBDXP->pfDataBase); return 0; } diff --git a/ogr/ogrsf_frmts/miramon/mm_wrlayr.c b/ogr/ogrsf_frmts/miramon/mm_wrlayr.c index 4c5222f1dd03..9bf89e9cd735 100644 --- a/ogr/ogrsf_frmts/miramon/mm_wrlayr.c +++ b/ogr/ogrsf_frmts/miramon/mm_wrlayr.c @@ -28,7 +28,7 @@ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifdef GDAL_COMPILATION @@ -43,7 +43,7 @@ #include "CmptCmp.h" // Compatibility between compilers #include "PrjMMVGl.h" // For a DirectoriPrograma #include "mm_gdal\mm_wrlayr.h" // For fseek_function() -#include "mm_gdal\mm_gdal_functions.h" // For MM_strnzcpy() +#include "mm_gdal\mm_gdal_functions.h" // For CPLStrlcpy() #include "mm_gdal\mm_rdlayr.h" // For MM_ReadExtendedDBFHeader() #include "msg.h" // For ErrorMsg() #ifdef _WIN64 @@ -53,8 +53,6 @@ #endif #endif -static char local_message[MAX_LOCAL_MESSAGE]; - #ifdef GDAL_COMPILATION CPL_C_START // Necessary for compiling in GDAL project #endif // GDAL_COMPILATION @@ -99,7 +97,8 @@ int MMCheckVersionForFID(struct MiraMonVectLayerInfo *hMiraMonLayer, MM_INTERNAL_FID FID); // Extended DBF functions -int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer); +int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, + struct MM_POINT_2D *pFirstCoord); int MMAddDBFRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MiraMonFeature *hMMFeature); int MMAddPointRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, @@ -123,41 +122,40 @@ void MMDestroyMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer); /* Managing errors and warnings */ /* -------------------------------------------------------------------- */ -void MMCPLError(int level, int code, const char *message) +#ifndef GDAL_COMPILATION +void MMCPLError(int code, const char *fmt, ...) { -#ifdef GDAL_COMPILATION - CPLError(level, code, "%s", message); -#else - sprintf(local_message, "level(%d), code(%d)", level, code); - InfoMsg(local_message); - ErrorMsg(message); -#endif + char szBigEnoughBuffer[1024]; + + va_list args; + va_start(args, fmt); + vsnprintf(szBigEnoughBuffer, sizeof(szBigEnoughBuffer), fmt, args); + ErrorMsg(szBigEnoughBuffer); + va_end(args); } -void MMCPLWarning(int level, int code, const char *message) +void MMCPLWarning(int code, const char *fmt, ...) { -#ifdef GDAL_COMPILATION - CPLError(level, code, "%s", message); -#else - sprintf(local_message, "level(%d), code(%d)", level, code); - InfoMsg(local_message); - InfoMsg(message); -#endif + char szBigEnoughBuffer[1024]; + + va_list args; + va_start(args, fmt); + vsnprintf(szBigEnoughBuffer, sizeof(szBigEnoughBuffer), fmt, args); + InfoMsg(szBigEnoughBuffer); + va_end(args); } -void MMCPLDebug(const char *c, const char *message) +void MMCPLDebug(int code, const char *fmt, ...) { -#ifdef GDAL_COMPILATION - CPLDebug(c, "%s", message); -#else - sprintf(local_message, "Code(%s)\n", c); - printf(local_message); /*ok*/ - printf(message); /*ok*/ - printf("\n"); /*ok*/ -#endif + char szBigEnoughBuffer[1024]; + + va_list args; + va_start(args, fmt); + vsnprintf(szBigEnoughBuffer, sizeof(szBigEnoughBuffer), fmt, args); + printf(szBigEnoughBuffer); /*ok*/ + va_end(args); } -#ifndef GDAL_COMPILATION int snprintf(char *str, size_t size, const char *format, ...) { int result; @@ -176,15 +174,17 @@ int snprintf(char *str, size_t size, const char *format, ...) // Important for 32 vs. 64 bit compiling compatibility. int MMCheckSize_t(GUInt64 nCount, GUInt64 nSize) { - size_t nMul; if ((size_t)nCount != nCount) return 1; if ((size_t)nSize != nSize) return 1; - nMul = (size_t)(nCount * nSize); - if (nCount != 0 && nMul / nCount != nSize) +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (nCount != 0 && nSize > SIZE_MAX / nCount) +#else + if (nCount != 0 && nSize > (1000 * 1000 * 1000U) / nCount) +#endif { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Overflow in MMCheckSize_t()"); return 1; @@ -524,6 +524,11 @@ int MMReadZSection(struct MiraMonVectLayerInfo *hMiraMonLayer, FILE_TYPE *pF, if (hMiraMonLayer->bIsPoint) { + if (MMCheckSize_t(hMiraMonLayer->TopHeader.nElemCount, MM_SIZE_OF_TL)) + return 1; + if (hMiraMonLayer->TopHeader.nElemCount * MM_SIZE_OF_TL > + UINT64_MAX - hMiraMonLayer->nHeaderDiskSize) + return 1; pZSection->ZSectionOffset = hMiraMonLayer->nHeaderDiskSize + hMiraMonLayer->TopHeader.nElemCount * MM_SIZE_OF_TL; @@ -531,29 +536,35 @@ int MMReadZSection(struct MiraMonVectLayerInfo *hMiraMonLayer, FILE_TYPE *pF, else if (hMiraMonLayer->bIsArc && !(hMiraMonLayer->bIsPolygon) && hMiraMonLayer->TopHeader.nElemCount > 0) { + const struct MM_AH *pArcHeader = + &(hMiraMonLayer->MMArc + .pArcHeader[hMiraMonLayer->TopHeader.nElemCount - 1]); + if (MMCheckSize_t(pArcHeader->nElemCount, MM_SIZE_OF_COORDINATE)) + return 1; + if (pArcHeader->nElemCount * MM_SIZE_OF_COORDINATE > + UINT64_MAX - pArcHeader->nOffset) + return 1; // Z section begins just after last coordinate of the last arc pZSection->ZSectionOffset = - hMiraMonLayer->MMArc - .pArcHeader[hMiraMonLayer->TopHeader.nElemCount - 1] - .nOffset + - hMiraMonLayer->MMArc - .pArcHeader[hMiraMonLayer->TopHeader.nElemCount - 1] - .nElemCount * - MM_SIZE_OF_COORDINATE; + pArcHeader->nOffset + + pArcHeader->nElemCount * MM_SIZE_OF_COORDINATE; } - else if (hMiraMonLayer->bIsPolygon) + else if (hMiraMonLayer->bIsPolygon && + hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount > 0) { + const struct MM_AH *pArcHeader = + &(hMiraMonLayer->MMPolygon.MMArc + .pArcHeader[hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount - + 1]); + if (MMCheckSize_t(pArcHeader->nElemCount, MM_SIZE_OF_COORDINATE)) + return 1; + if (pArcHeader->nElemCount * MM_SIZE_OF_COORDINATE > + UINT64_MAX - pArcHeader->nOffset) + return 1; // Z section begins just after last coordinate of the last arc pZSection->ZSectionOffset = - hMiraMonLayer->MMPolygon.MMArc - .pArcHeader[hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount - - 1] - .nOffset + - hMiraMonLayer->MMPolygon.MMArc - .pArcHeader - [hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount - 1] - .nElemCount * - MM_SIZE_OF_COORDINATE; + pArcHeader->nOffset + + pArcHeader->nElemCount * MM_SIZE_OF_COORDINATE; } else return 1; @@ -739,19 +750,10 @@ MMWriteZDescriptionHeaders(struct MiraMonVectLayerInfo *hMiraMonLayer, pZDescription = pZSection->pZDescription; nOffsetDiff = - pZSection->ZSectionOffset + - nElements * - (sizeof(pZDescription->dfBBminz) + sizeof(pZDescription->dfBBmaxz) + - sizeof(pZDescription->nZCount) + - ((hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - ? sizeof(nUL32) - : sizeof(pZDescription->nOffsetZ))); - - if (MMInitFlush(&FlushTMP, pF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pBuffer, pZSection->ZSectionOffset, 0)) + pZSection->ZSectionOffset + nElements * pZSection->nZDDiskSize; + + if (MMInitFlush(&FlushTMP, pF, MM_1MB, &pBuffer, pZSection->ZSectionOffset, + 0)) { if (pBuffer) free_function(pBuffer); @@ -844,8 +846,8 @@ static void MMDestroyZSectionDescription(struct MM_ZSection *pZSection) static int MMInitZSectionDescription(struct MM_ZSection *pZSection) { - if (MMCheckSize_t( - pZSection->nMaxZDescription * sizeof(*pZSection->pZDescription), 1)) + if (MMCheckSize_t(pZSection->nMaxZDescription, + sizeof(*pZSection->pZDescription))) return 1; if (!pZSection->nMaxZDescription) @@ -875,7 +877,7 @@ static int MMInitZSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, return 0; } - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { pZSection->ZHeader.dfBBminz = STATISTICAL_UNDEF_VALUE; pZSection->ZHeader.dfBBmaxz = -STATISTICAL_UNDEF_VALUE; @@ -886,7 +888,7 @@ static int MMInitZSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, pZSection->ZSectionOffset = 0; // ZD - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { pZSection->nMaxZDescription = MM_FIRST_NUMBER_OF_VERTICES * sizeof(double); @@ -895,8 +897,25 @@ static int MMInitZSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, } else { - pZSection->nMaxZDescription = - hMiraMonLayer->TopHeader.nElemCount * sizeof(double); + if (hMiraMonLayer->bIsPolygon) + { + if (MMCheckSize_t(hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount, + sizeof(double))) + return 1; + + pZSection->nMaxZDescription = + hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount * + sizeof(double); + } + else + { + if (MMCheckSize_t(hMiraMonLayer->TopHeader.nElemCount, + sizeof(double))) + return 1; + + pZSection->nMaxZDescription = + hMiraMonLayer->TopHeader.nElemCount * sizeof(double); + } if (MMInitZSectionDescription(pZSection)) return 1; } @@ -909,13 +928,10 @@ static int MMInitZSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, pZSection->ZDOffset = 0; // ZL - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { - if (MMInitFlush(&pZSection->FlushZL, pF3d, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pZSection->pZL, 0, sizeof(double))) + if (MMInitFlush(&pZSection->FlushZL, pF3d, MM_1MB, &pZSection->pZL, 0, + sizeof(double))) return 1; } return 0; @@ -925,10 +941,10 @@ static int MMInitZSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, /* Layer Functions: Extensions */ /* -------------------------------------------------------------------- */ -/* Find the last ocurrence of pszFinalPart in pszName +/* Find the last occurrence of pszFinalPart in pszName and changes it by pszNewPart. - - Examples of desired behaviour + + Examples of desired behavior AA.pnt -> AAT.rel AA.nod -> N.~idx AA.nod -> N.dbf @@ -952,6 +968,8 @@ static int MMChangeFinalPartOfTheName(char *pszName, size_t nMaxSizeOfName, nMaxSizeOfName) return 1; // It's not possible to change the final part + // It's the implementation on windows of the linux strrstr() + // pszLastFound = strrstr(pszWhereToFind, pszFinalPart); pszWhereToFind = pszName; while (nullptr != (pAux = strstr(pszWhereToFind, pszFinalPart))) { @@ -977,7 +995,7 @@ static int MMInitPointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) hMiraMonLayer->bIsPoint = 1; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { // Geometrical part // Init header structure @@ -992,62 +1010,58 @@ static int MMInitPointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) // Opening the binary file where sections TH, TL[...] and ZH-ZD[...]-ZL[...] // are going to be written. - strcpy(hMiraMonLayer->MMPoint.pszLayerName, - hMiraMonLayer->pszSrcLayerName); - strcat(hMiraMonLayer->MMPoint.pszLayerName, ".pnt"); + snprintf(hMiraMonLayer->MMPoint.pszLayerName, + sizeof(hMiraMonLayer->MMPoint.pszLayerName), "%s.pnt", + hMiraMonLayer->pszSrcLayerName); } if (nullptr == (hMiraMonLayer->MMPoint.pF = fopen_function(hMiraMonLayer->MMPoint.pszLayerName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, "Error MMPoint.pF: Cannot open file %s.", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error MMPoint.pF: Cannot open file %s.", + hMiraMonLayer->MMPoint.pszLayerName); return 1; } fseek_function(hMiraMonLayer->MMPoint.pF, 0, SEEK_SET); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { // TL - strcpy(hMiraMonLayer->MMPoint.pszTLName, - hMiraMonLayer->pszSrcLayerName); - strcat(hMiraMonLayer->MMPoint.pszTLName, "T.~xy"); + snprintf(hMiraMonLayer->MMPoint.pszTLName, + sizeof(hMiraMonLayer->MMPoint.pszTLName), "%sT.~xy", + hMiraMonLayer->pszSrcLayerName); if (nullptr == (hMiraMonLayer->MMPoint.pFTL = fopen_function(hMiraMonLayer->MMPoint.pszTLName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, "Error MMPoint.pFTL: Cannot open file %s.", - hMiraMonLayer->MMPoint.pszTLName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error MMPoint.pFTL: Cannot open file %s.", + hMiraMonLayer->MMPoint.pszTLName); return 1; } fseek_function(hMiraMonLayer->MMPoint.pFTL, 0, SEEK_SET); if (MMInitFlush(&hMiraMonLayer->MMPoint.FlushTL, - hMiraMonLayer->MMPoint.pFTL, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, + hMiraMonLayer->MMPoint.pFTL, MM_1MB, &hMiraMonLayer->MMPoint.pTL, 0, MM_SIZE_OF_TL)) return 1; // 3D part if (hMiraMonLayer->TopHeader.bIs3d) { - strcpy(hMiraMonLayer->MMPoint.psz3DLayerName, - hMiraMonLayer->pszSrcLayerName); - strcat(hMiraMonLayer->MMPoint.psz3DLayerName, "T.~z"); + snprintf(hMiraMonLayer->MMPoint.psz3DLayerName, + sizeof(hMiraMonLayer->MMPoint.psz3DLayerName), "%sT.~z", + hMiraMonLayer->pszSrcLayerName); if (nullptr == (hMiraMonLayer->MMPoint.pF3d = fopen_function( hMiraMonLayer->MMPoint.psz3DLayerName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, - "Error MMPoint.pF3d: Cannot open file %s.", - hMiraMonLayer->MMPoint.psz3DLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error MMPoint.pF3d: Cannot open file %s.", + hMiraMonLayer->MMPoint.psz3DLayerName); return 1; } fseek_function(hMiraMonLayer->MMPoint.pF3d, 0, SEEK_SET); @@ -1075,12 +1089,17 @@ static int MMInitPointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) } // MiraMon metadata - strcpy(hMiraMonLayer->MMPoint.pszREL_LayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(hMiraMonLayer->MMPoint.pszREL_LayerName, "T.rel"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(hMiraMonLayer->MMPoint.pszREL_LayerName, + sizeof(hMiraMonLayer->MMPoint.pszREL_LayerName), "%sT.rel", + hMiraMonLayer->pszSrcLayerName); + } else { + CPLStrlcpy(hMiraMonLayer->MMPoint.pszREL_LayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(hMiraMonLayer->MMPoint.pszREL_LayerName)); if (MMChangeFinalPartOfTheName(hMiraMonLayer->MMPoint.pszREL_LayerName, MM_CPL_PATH_BUF_SIZE, ".pnt", "T.rel")) return 1; @@ -1098,12 +1117,18 @@ static int MMInitPointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) // MIRAMON DATA BASE // Creating the DBF file name - strcpy(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName, "T.dbf"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName, + sizeof(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName), + "%sT.dbf", hMiraMonLayer->pszSrcLayerName); + } else { + CPLStrlcpy(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName)); + if (MMChangeFinalPartOfTheName( hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName, MM_CPL_PATH_BUF_SIZE, ".pnt", "T.dbf")) @@ -1131,7 +1156,7 @@ static int MMInitNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) else pMMArcLayer = &hMiraMonLayer->MMArc; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { // Init header structure pMMArcLayer->TopNodeHeader.aFileType[0] = 'N'; @@ -1145,27 +1170,28 @@ static int MMInitNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) // Opening the binary file where sections TH, NH and NL[...] // are going to be written. strcpy(pMMArcLayer->MMNode.pszLayerName, pMMArcLayer->pszLayerName); - strcpy(pMMArcLayer->MMNode.pszLayerName, - reset_extension(pMMArcLayer->MMNode.pszLayerName, "nod")); + CPLStrlcpy(pMMArcLayer->MMNode.pszLayerName, + reset_extension(pMMArcLayer->MMNode.pszLayerName, "nod"), + sizeof(pMMArcLayer->MMNode.pszLayerName)); if (nullptr == (pMMArcLayer->MMNode.pF = fopen_function(pMMArcLayer->MMNode.pszLayerName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, "Error MMNode.pF: Cannot open file %s.", - pMMArcLayer->MMNode.pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error MMNode.pF: Cannot open file %s.", + pMMArcLayer->MMNode.pszLayerName); return 1; } fseek_function(pMMArcLayer->MMNode.pF, 0, SEEK_SET); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { // Node Header pMMArcLayer->MMNode.nMaxNodeHeader = MM_FIRST_NUMBER_OF_NODES; - if (MMCheckSize_t(pMMArcLayer->MMNode.nMaxNodeHeader * - sizeof(*pMMArcLayer->MMNode.pNodeHeader), - 1)) + if (MMCheckSize_t(pMMArcLayer->MMNode.nMaxNodeHeader, + sizeof(*pMMArcLayer->MMNode.pNodeHeader))) return 1; if (!pMMArcLayer->MMNode.nMaxNodeHeader) @@ -1202,18 +1228,16 @@ static int MMInitNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) fopen_function(pMMArcLayer->MMNode.pszNLName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, "Error MMNode.pFNL: Cannot open file %s.", - pMMArcLayer->MMNode.pszNLName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error MMNode.pFNL: Cannot open file %s.", + pMMArcLayer->MMNode.pszNLName); return 1; } fseek_function(pMMArcLayer->MMNode.pFNL, 0, SEEK_SET); if (MMInitFlush(&pMMArcLayer->MMNode.FlushNL, pMMArcLayer->MMNode.pFNL, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pMMArcLayer->MMNode.pNL, 0, 0)) + MM_1MB, &pMMArcLayer->MMNode.pNL, 0, 0)) return 1; // Creating the DBF file name @@ -1256,7 +1280,7 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) // Init header structure hMiraMonLayer->bIsArc = 1; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { pArcTopHeader->bIs3d = 1; // Read description of bRealIs3d MMInitBoundingBox(&pArcTopHeader->hBB); @@ -1265,19 +1289,26 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) pArcTopHeader->aFileType[1] = 'R'; pArcTopHeader->aFileType[2] = 'C'; - strcpy(pMMArcLayer->pszLayerName, hMiraMonLayer->pszSrcLayerName); if (hMiraMonLayer->bIsPolygon) - strcat(pMMArcLayer->pszLayerName, "_bound.arc"); + { + snprintf(pMMArcLayer->pszLayerName, + sizeof(pMMArcLayer->pszLayerName), "%s_bound.arc", + hMiraMonLayer->pszSrcLayerName); + } else - strcat(pMMArcLayer->pszLayerName, ".arc"); + { + snprintf(pMMArcLayer->pszLayerName, + sizeof(pMMArcLayer->pszLayerName), "%s.arc", + hMiraMonLayer->pszSrcLayerName); + } } if (nullptr == (pMMArcLayer->pF = fopen_function(pMMArcLayer->pszLayerName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, "Error pMMArcLayer->pF: Cannot open file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error pMMArcLayer->pF: Cannot open file %s.", + pMMArcLayer->pszLayerName); return 1; } @@ -1288,9 +1319,9 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) if (MMReadHeader(pMMArcLayer->pF, &hMiraMonLayer->MMPolygon.TopArcHeader)) { - sprintf(local_message, "Error reading the format in file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error reading the format in file %s.", + pMMArcLayer->pszLayerName); return 1; } // 3D information is in arcs file @@ -1304,16 +1335,15 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) else pMMArcLayer->nSizeArcHeader = MM_SIZE_OF_AH_64BITS; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) pMMArcLayer->nMaxArcHeader = MM_FIRST_NUMBER_OF_ARCS; else pMMArcLayer->nMaxArcHeader = pArcTopHeader->nElemCount; if (pMMArcLayer->nMaxArcHeader) { - if (MMCheckSize_t(pMMArcLayer->nMaxArcHeader * - sizeof(*pMMArcLayer->pArcHeader), - 1)) + if (MMCheckSize_t(pMMArcLayer->nMaxArcHeader, + sizeof(*pMMArcLayer->pArcHeader))) return 1; if (nullptr == (pMMArcLayer->pArcHeader = (struct MM_AH *) calloc_function((size_t)pMMArcLayer->nMaxArcHeader * @@ -1328,9 +1358,9 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) { if (MMReadAHArcSection(hMiraMonLayer)) { - sprintf(local_message, "Error reading the format in file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error reading the format in file %s.", + pMMArcLayer->pszLayerName); return 1; } } @@ -1339,31 +1369,32 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) pMMArcLayer->pArcHeader = nullptr; // AL - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { pMMArcLayer->nALElementSize = MM_SIZE_OF_AL; - strcpy(pMMArcLayer->pszALName, hMiraMonLayer->pszSrcLayerName); if (hMiraMonLayer->bIsPolygon) - strcat(pMMArcLayer->pszALName, "_boundA.~xy"); + { + snprintf(pMMArcLayer->pszALName, sizeof(pMMArcLayer->pszALName), + "%s_boundA.~xy", hMiraMonLayer->pszSrcLayerName); + } else - strcat(pMMArcLayer->pszALName, "A.~xy"); + { + snprintf(pMMArcLayer->pszALName, sizeof(pMMArcLayer->pszALName), + "%sA.~xy", hMiraMonLayer->pszSrcLayerName); + } if (nullptr == (pMMArcLayer->pFAL = fopen_function( pMMArcLayer->pszALName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, - "Error pMMArcLayer->pFAL: Cannot open file %s.", - pMMArcLayer->pszALName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error pMMArcLayer->pFAL: Cannot open file %s.", + pMMArcLayer->pszALName); return 1; } fseek_function(pMMArcLayer->pFAL, 0, SEEK_SET); - if (MMInitFlush(&pMMArcLayer->FlushAL, pMMArcLayer->pFAL, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, + if (MMInitFlush(&pMMArcLayer->FlushAL, pMMArcLayer->pFAL, MM_1MB, &pMMArcLayer->pAL, 0, 0)) return 1; } @@ -1371,22 +1402,28 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) // 3D if (pArcTopHeader->bIs3d) { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { - strcpy(pMMArcLayer->psz3DLayerName, hMiraMonLayer->pszSrcLayerName); if (hMiraMonLayer->bIsPolygon) - strcat(pMMArcLayer->psz3DLayerName, "_boundA.~z"); + { + snprintf(pMMArcLayer->psz3DLayerName, + sizeof(pMMArcLayer->psz3DLayerName), "%s_boundA.~z", + hMiraMonLayer->pszSrcLayerName); + } else - strcat(pMMArcLayer->psz3DLayerName, "A.~z"); + { + snprintf(pMMArcLayer->psz3DLayerName, + sizeof(pMMArcLayer->psz3DLayerName), "%sA.~z", + hMiraMonLayer->pszSrcLayerName); + } if (nullptr == (pMMArcLayer->pF3d = fopen_function(pMMArcLayer->psz3DLayerName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, - "Error pMMArcLayer->pF3d: Cannot open file %s.", - pMMArcLayer->psz3DLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error pMMArcLayer->pF3d: Cannot open file %s.", + pMMArcLayer->psz3DLayerName); return 1; } fseek_function(pMMArcLayer->pF3d, 0, SEEK_SET); @@ -1395,9 +1432,9 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) if (MMInitZSectionLayer(hMiraMonLayer, pMMArcLayer->pF3d, &pMMArcLayer->pZSection)) { - sprintf(local_message, "Error reading the format in file %s %d.", - pMMArcLayer->pszLayerName, 6); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error reading the format in file %s %d.", + pMMArcLayer->pszLayerName, 6); return 1; } @@ -1406,9 +1443,9 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) if (MMReadZSection(hMiraMonLayer, pMMArcLayer->pF, &pMMArcLayer->pZSection)) { - sprintf(local_message, "Error reading the format in file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error reading the format in file %s.", + pMMArcLayer->pszLayerName); return 1; } @@ -1416,19 +1453,22 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) pArcTopHeader->nElemCount, &pMMArcLayer->pZSection)) { - sprintf(local_message, "Error reading the format in file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error reading the format in file %s.", + pMMArcLayer->pszLayerName); return 1; } } } // MiraMon metadata - strcpy(pMMArcLayer->pszREL_LayerName, hMiraMonLayer->pszSrcLayerName); if (hMiraMonLayer->bIsPolygon) { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->pszREL_LayerName, "_boundA.rel"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(pMMArcLayer->pszREL_LayerName, + sizeof(pMMArcLayer->pszREL_LayerName), "%s_boundA.rel", + hMiraMonLayer->pszSrcLayerName); + } else { strcpy(pMMArcLayer->pszREL_LayerName, pMMArcLayer->pszLayerName); @@ -1440,10 +1480,17 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) } else { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->pszREL_LayerName, "A.rel"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(pMMArcLayer->pszREL_LayerName, + sizeof(pMMArcLayer->pszREL_LayerName), "%sA.rel", + hMiraMonLayer->pszSrcLayerName); + } else { + CPLStrlcpy(pMMArcLayer->pszREL_LayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(pMMArcLayer->pszREL_LayerName)); if (MMChangeFinalPartOfTheName(pMMArcLayer->pszREL_LayerName, MM_CPL_PATH_BUF_SIZE, ".arc", "A.rel")) @@ -1463,12 +1510,14 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) // MIRAMON DATA BASE // Creating the DBF file name - strcpy(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, - hMiraMonLayer->pszSrcLayerName); if (hMiraMonLayer->bIsPolygon) { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, "_boundA.dbf"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, + sizeof(pMMArcLayer->MMAdmDB.pszExtDBFLayerName), + "%s_boundA.dbf", hMiraMonLayer->pszSrcLayerName); + } else { strcpy(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, @@ -1481,10 +1530,17 @@ static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) } else { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, "A.dbf"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, + sizeof(pMMArcLayer->MMAdmDB.pszExtDBFLayerName), "%sA.dbf", + hMiraMonLayer->pszSrcLayerName); + } else { + CPLStrlcpy(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(pMMArcLayer->MMAdmDB.pszExtDBFLayerName)); if (MMChangeFinalPartOfTheName( pMMArcLayer->MMAdmDB.pszExtDBFLayerName, MM_CPL_PATH_BUF_SIZE, ".arc", "A.dbf")) @@ -1521,7 +1577,7 @@ static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) // Init header structure hMiraMonLayer->bIsPolygon = 1; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { hMiraMonLayer->TopHeader.bIs3d = 1; // Read description of bRealIs3d MMInitBoundingBox(&hMiraMonLayer->TopHeader.hBB); @@ -1530,18 +1586,18 @@ static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) hMiraMonLayer->TopHeader.aFileType[1] = 'O'; hMiraMonLayer->TopHeader.aFileType[2] = 'L'; - strcpy(pMMPolygonLayer->pszLayerName, hMiraMonLayer->pszSrcLayerName); - strcat(pMMPolygonLayer->pszLayerName, ".pol"); + snprintf(pMMPolygonLayer->pszLayerName, + sizeof(pMMPolygonLayer->pszLayerName), "%s.pol", + hMiraMonLayer->pszSrcLayerName); } if (nullptr == (pMMPolygonLayer->pF = fopen_function(pMMPolygonLayer->pszLayerName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, - "Error pMMPolygonLayer->pF: Cannot open file %s.", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error pMMPolygonLayer->pF: Cannot open file %s.", + pMMPolygonLayer->pszLayerName); return 1; } @@ -1551,28 +1607,24 @@ static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) else pMMPolygonLayer->nPSElementSize = MM_SIZE_OF_PS_64BITS; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { - strcpy(pMMPolygonLayer->pszPSName, hMiraMonLayer->pszSrcLayerName); - strcat(pMMPolygonLayer->pszPSName, "P.~PS"); + snprintf(pMMPolygonLayer->pszPSName, sizeof(pMMPolygonLayer->pszPSName), + "%sP.~PS", hMiraMonLayer->pszSrcLayerName); if (nullptr == (pMMPolygonLayer->pFPS = fopen_function(pMMPolygonLayer->pszPSName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, - "Error pMMPolygonLayer->pFPS: Cannot open file %s.", - pMMPolygonLayer->pszPSName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error pMMPolygonLayer->pFPS: Cannot open file %s.", + pMMPolygonLayer->pszPSName); return 1; } fseek_function(pMMPolygonLayer->pFPS, 0, SEEK_SET); if (MMInitFlush(&pMMPolygonLayer->FlushPS, pMMPolygonLayer->pFPS, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pMMPolygonLayer->pPS, 0, + MM_1MB, &pMMPolygonLayer->pPS, 0, pMMPolygonLayer->nPSElementSize)) return 1; } @@ -1583,16 +1635,15 @@ static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) else pMMPolygonLayer->nPHElementSize = MM_SIZE_OF_PH_64BITS; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) pMMPolygonLayer->nMaxPolHeader = MM_FIRST_NUMBER_OF_POLYGONS + 1; else pMMPolygonLayer->nMaxPolHeader = hMiraMonLayer->TopHeader.nElemCount; if (pMMPolygonLayer->nMaxPolHeader) { - if (MMCheckSize_t(pMMPolygonLayer->nMaxPolHeader * - sizeof(*pMMPolygonLayer->pPolHeader), - 1)) + if (MMCheckSize_t(pMMPolygonLayer->nMaxPolHeader, + sizeof(*pMMPolygonLayer->pPolHeader))) return 1; if (nullptr == (pMMPolygonLayer->pPolHeader = (struct MM_PH *)calloc_function( @@ -1614,7 +1665,7 @@ static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) else pMMPolygonLayer->nPALElementSize = MM_SIZE_OF_PAL_64BITS; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { // Universal polygon. memset(pMMPolygonLayer->pPolHeader, 0, @@ -1622,36 +1673,40 @@ static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) hMiraMonLayer->TopHeader.nElemCount = 1; // PAL - strcpy(pMMPolygonLayer->pszPALName, hMiraMonLayer->pszSrcLayerName); - strcat(pMMPolygonLayer->pszPALName, "P.~idx"); + snprintf(pMMPolygonLayer->pszPALName, + sizeof(pMMPolygonLayer->pszPALName), "%sP.~idx", + hMiraMonLayer->pszSrcLayerName); if (nullptr == (pMMPolygonLayer->pFPAL = fopen_function(pMMPolygonLayer->pszPALName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, - "Error pMMPolygonLayer->pFPAL: Cannot open file %s.", - pMMPolygonLayer->pszPALName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error pMMPolygonLayer->pFPAL: Cannot open file %s.", + pMMPolygonLayer->pszPALName); return 1; } fseek_function(pMMPolygonLayer->pFPAL, 0, SEEK_SET); if (MMInitFlush(&pMMPolygonLayer->FlushPAL, pMMPolygonLayer->pFPAL, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pMMPolygonLayer->pPAL, 0, 0)) + MM_1MB, &pMMPolygonLayer->pPAL, 0, 0)) return 1; } // MiraMon metadata - strcpy(hMiraMonLayer->MMPolygon.pszREL_LayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(hMiraMonLayer->MMPolygon.pszREL_LayerName, "P.rel"); + + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(hMiraMonLayer->MMPolygon.pszREL_LayerName, + sizeof(hMiraMonLayer->MMPolygon.pszREL_LayerName), "%sP.rel", + hMiraMonLayer->pszSrcLayerName); + } else { + CPLStrlcpy(hMiraMonLayer->MMPolygon.pszREL_LayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(hMiraMonLayer->MMPolygon.pszREL_LayerName)); + if (MMChangeFinalPartOfTheName( hMiraMonLayer->MMPolygon.pszREL_LayerName, MM_CPL_PATH_BUF_SIZE, ".pol", "P.rel")) @@ -1669,12 +1724,17 @@ static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) hMiraMonLayer->MMPolygon.pszREL_LayerName; // MIRAMON DATA BASE - strcpy(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName, "P.dbf"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName, + sizeof(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName), "%sP.dbf", + hMiraMonLayer->pszSrcLayerName); + } else { + CPLStrlcpy(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName)); if (MMChangeFinalPartOfTheName( pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName, MM_CPL_PATH_BUF_SIZE, ".pol", "P.dbf")) @@ -1698,10 +1758,18 @@ int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer) if (hMiraMonLayer->eLT == MM_LayerType_Point || hMiraMonLayer->eLT == MM_LayerType_Point3d) { - strcpy(hMiraMonLayer->MMPoint.pszLayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(hMiraMonLayer->MMPoint.pszLayerName, ".pnt"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(hMiraMonLayer->MMPoint.pszLayerName, + sizeof(hMiraMonLayer->MMPoint.pszLayerName), "%s.pnt", + hMiraMonLayer->pszSrcLayerName); + } + else + { + CPLStrlcpy(hMiraMonLayer->MMPoint.pszLayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(hMiraMonLayer->MMPoint.pszLayerName)); + } if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap) { hMiraMonLayer->MMMap->nNumberOfLayers++; @@ -1723,9 +1791,18 @@ int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer) { struct MiraMonArcLayer *pMMArcLayer = &hMiraMonLayer->MMArc; - strcpy(pMMArcLayer->pszLayerName, hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->pszLayerName, ".arc"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(pMMArcLayer->pszLayerName, + sizeof(pMMArcLayer->pszLayerName), "%s.arc", + hMiraMonLayer->pszSrcLayerName); + } + else + { + CPLStrlcpy(pMMArcLayer->pszLayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(pMMArcLayer->pszLayerName)); + } if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap) { @@ -1748,9 +1825,18 @@ int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer) { struct MiraMonPolygonLayer *pMMPolygonLayer = &hMiraMonLayer->MMPolygon; - strcpy(pMMPolygonLayer->pszLayerName, hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMPolygonLayer->pszLayerName, ".pol"); + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) + { + snprintf(pMMPolygonLayer->pszLayerName, + sizeof(pMMPolygonLayer->pszLayerName), "%s.pol", + hMiraMonLayer->pszSrcLayerName); + } + else + { + CPLStrlcpy(pMMPolygonLayer->pszLayerName, + hMiraMonLayer->pszSrcLayerName, + sizeof(pMMPolygonLayer->pszLayerName)); + } if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap) { @@ -1775,71 +1861,86 @@ int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer) pszArcLayerName = MMReturnValueFromSectionINIFile( pMMPolygonLayer->pszREL_LayerName, SECTION_OVVW_ASPECTES_TECNICS, KEY_ArcSource); - MM_RemoveInitial_and_FinalQuotationMarks(pszArcLayerName); - - // If extension is not specified ".arc" will be used - pszExt = get_extension_function(pszArcLayerName); - if (MMIsEmptyString(pszExt)) + if (pszArcLayerName) { - char *pszArcLayerNameAux = - calloc_function(strlen(pszArcLayerName) + 5); - if (!pszArcLayerNameAux) + MM_RemoveInitial_and_FinalQuotationMarks(pszArcLayerName); + + // If extension is not specified ".arc" will be used + pszExt = get_extension_function(pszArcLayerName); + if (MMIsEmptyString(pszExt)) { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMInitLayerByType())"); - return 1; + char *pszArcLayerNameAux = + calloc_function(strlen(pszArcLayerName) + 5); + if (!pszArcLayerNameAux) + { + MMCPLError(CE_Failure, CPLE_OutOfMemory, + "Memory error in MiraMon " + "driver (MMInitLayerByType())"); + free_function(pszArcLayerName); + return 1; + } + snprintf(pszArcLayerNameAux, strlen(pszArcLayerName) + 5, + "%s.arc", pszArcLayerName); + + free_function(pszArcLayerName); + pszArcLayerName = pszArcLayerNameAux; } - strcpy(pszArcLayerNameAux, pszArcLayerName); - strcat(pszArcLayerNameAux, ".arc"); - free_function(pszArcLayerName); - pszArcLayerName = pszArcLayerNameAux; - } - strcpy(pMMPolygonLayer->MMArc.pszLayerName, - form_filename_function( - get_path_function(hMiraMonLayer->pszSrcLayerName), - pszArcLayerName)); + CPLStrlcpy( + pMMPolygonLayer->MMArc.pszLayerName, + form_filename_function( + get_path_function(hMiraMonLayer->pszSrcLayerName), + pszArcLayerName), + sizeof(pMMPolygonLayer->MMArc.pszLayerName)); - free_function(pszArcLayerName); + free_function(pszArcLayerName); + } + else + { + // There is no arc layer on the metada file + MMCPLError( + CE_Failure, CPLE_OpenFailed, + "Error reading the ARC file in the metadata file %s.", + pMMPolygonLayer->pszREL_LayerName); + return 1; + } if (nullptr == (hMiraMonLayer->MMPolygon.MMArc.pF = fopen_function( pMMPolygonLayer->MMArc.pszLayerName, hMiraMonLayer->pszFlags))) { - sprintf(local_message, - "Error pMMPolygonLayer.MMArc.pF: Cannot open file %s.", - pMMPolygonLayer->MMArc.pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError( + CE_Failure, CPLE_OpenFailed, + "Error pMMPolygonLayer.MMArc.pF: Cannot open file %s.", + pMMPolygonLayer->MMArc.pszLayerName); return 1; } if (MMReadHeader(hMiraMonLayer->MMPolygon.MMArc.pF, &hMiraMonLayer->MMPolygon.TopArcHeader)) { - sprintf(local_message, "Error reading the format in file %s.", - pMMPolygonLayer->MMArc.pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error reading the format in file %s.", + pMMPolygonLayer->MMArc.pszLayerName); return 1; } if (MMReadPHPolygonSection(hMiraMonLayer)) { - sprintf(local_message, "Error reading the format in file %s.", - pMMPolygonLayer->MMArc.pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error reading the format in file %s.", + pMMPolygonLayer->MMArc.pszLayerName); return 1; } - fclose_function(hMiraMonLayer->MMPolygon.MMArc.pF); - hMiraMonLayer->MMPolygon.MMArc.pF = nullptr; + fclose_and_nullify(&hMiraMonLayer->MMPolygon.MMArc.pF); } else { // Creating the stringLine file associated to the polygon - strcpy(pMMPolygonLayer->MMArc.pszLayerName, - hMiraMonLayer->pszSrcLayerName); - strcat(pMMPolygonLayer->MMArc.pszLayerName, ".arc"); + snprintf(pMMPolygonLayer->MMArc.pszLayerName, + sizeof(pMMPolygonLayer->MMArc.pszLayerName), "%s.arc", + hMiraMonLayer->pszSrcLayerName); } if (MMInitArcLayer(hMiraMonLayer)) @@ -1857,12 +1958,12 @@ int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer) else MMSet2_0Version(&pMMPolygonLayer->TopArcHeader); } - else if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + else if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { // Trying to get DBF information - strcpy(hMiraMonLayer->MMAdmDBWriting.pszExtDBFLayerName, - hMiraMonLayer->pszSrcLayerName); - strcat(hMiraMonLayer->MMAdmDBWriting.pszExtDBFLayerName, ".dbf"); + snprintf(hMiraMonLayer->MMAdmDBWriting.pszExtDBFLayerName, + sizeof(hMiraMonLayer->MMAdmDBWriting.pszExtDBFLayerName), + "%s.dbf", hMiraMonLayer->pszSrcLayerName); } return 0; @@ -1870,9 +1971,8 @@ int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer) int MMInitLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, const char *pzFileName, int LayerVersion, char nMMRecode, - char nMMLanguage, double nMMMemoryRatio, - struct MiraMonDataBase *pLayerDB, MM_BOOLEAN ReadOrWrite, - struct MiraMonVectMapInfo *MMMap) + char nMMLanguage, struct MiraMonDataBase *pLayerDB, + MM_BOOLEAN ReadOrWrite, struct MiraMonVectMapInfo *MMMap) { if (!hMiraMonLayer) return 1; @@ -1883,7 +1983,6 @@ int MMInitLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, memset(hMiraMonLayer, 0, sizeof(*hMiraMonLayer)); //hMiraMonLayer->Version = MM_VECTOR_LAYER_LAST_VERSION; - hMiraMonLayer->nMemoryRatio = nMMMemoryRatio; hMiraMonLayer->ReadOrWrite = ReadOrWrite; hMiraMonLayer->MMMap = MMMap; @@ -1962,10 +2061,12 @@ static int MMClose3DSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_ZSection *pZSection, MM_FILE_OFFSET FinalOffset) { + int ret_code = 1; if (!hMiraMonLayer) return 1; - // Flushing if there is something to flush on the disk + // Avoid closing when it has no sense. But it's not an error. + // Just return elegantly. if (!pF || !pF3d || !pszF3d || !pZSection) return 0; @@ -1973,45 +2074,47 @@ static int MMClose3DSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, { pZSection->ZSectionOffset = FinalOffset; if (MMWriteZSection(pF, pZSection)) - return 1; + goto end_label; // Header 3D. Writes it after header if (MMWriteZDescriptionHeaders(hMiraMonLayer, pF, nElements, pZSection)) - return 1; + goto end_label; // ZL section pZSection->FlushZL.SizeOfBlockToBeSaved = 0; if (MMAppendBlockToBuffer(&pZSection->FlushZL)) - return 1; + goto end_label; if (MMMoveFromFileToFile(pF3d, pF, &pZSection->ZSectionOffset)) - return 1; + goto end_label; } - if (pF3d) - fclose_function(pF3d); + ret_code = 0; +end_label: + fclose_and_nullify(&pF3d); if (pszF3d && *pszF3d != '\0') remove_function(pszF3d); - return 0; + return ret_code; } static int MMClosePointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) { + int ret_code = 1; if (!hMiraMonLayer) return 1; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { hMiraMonLayer->nFinalElemCount = hMiraMonLayer->TopHeader.nElemCount; hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d; if (MMWriteHeader(hMiraMonLayer->MMPoint.pF, &hMiraMonLayer->TopHeader)) { - sprintf(local_message, "Error writing to file %s", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + hMiraMonLayer->MMPoint.pszLayerName); + goto end_label; } hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize; @@ -2019,22 +2122,23 @@ static int MMClosePointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) hMiraMonLayer->MMPoint.FlushTL.SizeOfBlockToBeSaved = 0; if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL)) { - sprintf(local_message, "Error writing to file %s", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + hMiraMonLayer->MMPoint.pszLayerName); + goto end_label; } if (MMMoveFromFileToFile(hMiraMonLayer->MMPoint.pFTL, hMiraMonLayer->MMPoint.pF, &hMiraMonLayer->OffsetCheck)) { - sprintf(local_message, "Error writing to file %s", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + hMiraMonLayer->MMPoint.pszLayerName); + goto end_label; } - fclose_function(hMiraMonLayer->MMPoint.pFTL); + fclose_and_nullify(&hMiraMonLayer->MMPoint.pFTL); + if (*hMiraMonLayer->MMPoint.pszTLName != '\0') remove_function(hMiraMonLayer->MMPoint.pszTLName); @@ -2044,19 +2148,22 @@ static int MMClosePointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) hMiraMonLayer->MMPoint.psz3DLayerName, &hMiraMonLayer->MMPoint.pZSection, hMiraMonLayer->OffsetCheck)) { - sprintf(local_message, "Error writing to file %s", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + hMiraMonLayer->MMPoint.pszLayerName); + goto end_label; } } - if (hMiraMonLayer->MMPoint.pF) - fclose_function(hMiraMonLayer->MMPoint.pF); - return 0; + + ret_code = 0; +end_label: + fclose_and_nullify(&hMiraMonLayer->MMPoint.pF); + return ret_code; } static int MMCloseNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) { + int ret_code = 1; struct MiraMonArcLayer *pMMArcLayer; if (!hMiraMonLayer) @@ -2067,41 +2174,44 @@ static int MMCloseNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) else pMMArcLayer = &hMiraMonLayer->MMArc; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d; if (MMWriteHeader(pMMArcLayer->MMNode.pF, &pMMArcLayer->TopNodeHeader)) - return 1; + goto end_label; hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize; // NH Section if (MMWriteNHNodeSection(hMiraMonLayer, hMiraMonLayer->nHeaderDiskSize)) - return 1; + goto end_label; // NL Section pMMArcLayer->MMNode.FlushNL.SizeOfBlockToBeSaved = 0; if (MMAppendBlockToBuffer(&pMMArcLayer->MMNode.FlushNL)) - return 1; + goto end_label; if (MMMoveFromFileToFile(pMMArcLayer->MMNode.pFNL, pMMArcLayer->MMNode.pF, &hMiraMonLayer->OffsetCheck)) - return 1; + goto end_label; - if (pMMArcLayer->MMNode.pFNL) - fclose_function(pMMArcLayer->MMNode.pFNL); + fclose_and_nullify(&pMMArcLayer->MMNode.pFNL); if (*pMMArcLayer->MMNode.pszNLName != '\0') remove_function(pMMArcLayer->MMNode.pszNLName); } - if (pMMArcLayer->MMNode.pF) - fclose_function(pMMArcLayer->MMNode.pF); + ret_code = 0; +end_label: + fclose_and_nullify(&pMMArcLayer->MMNode.pFNL); - return 0; + fclose_and_nullify(&pMMArcLayer->MMNode.pF); + + return ret_code; } static int MMCloseArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) { + int ret_code = 0; struct MiraMonArcLayer *pMMArcLayer; struct MM_TH *pArcTopHeader; @@ -2119,48 +2229,44 @@ static int MMCloseArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) pArcTopHeader = &hMiraMonLayer->TopHeader; } - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { hMiraMonLayer->nFinalElemCount = pArcTopHeader->nElemCount; pArcTopHeader->bIs3d = hMiraMonLayer->bIsReal3d; if (MMWriteHeader(pMMArcLayer->pF, pArcTopHeader)) { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", pMMArcLayer->pszLayerName); + goto end_label; } hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize; // AH Section if (MMWriteAHArcSection(hMiraMonLayer, hMiraMonLayer->OffsetCheck)) { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", pMMArcLayer->pszLayerName); + goto end_label; } // AL Section pMMArcLayer->FlushAL.SizeOfBlockToBeSaved = 0; if (MMAppendBlockToBuffer(&pMMArcLayer->FlushAL)) { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", pMMArcLayer->pszLayerName); + goto end_label; } if (MMMoveFromFileToFile(pMMArcLayer->pFAL, pMMArcLayer->pF, &hMiraMonLayer->OffsetCheck)) { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", pMMArcLayer->pszLayerName); + goto end_label; } - if (pMMArcLayer->pFAL) - fclose_function(pMMArcLayer->pFAL); + fclose_and_nullify(&pMMArcLayer->pFAL); + if (*pMMArcLayer->pszALName != '\0') remove_function(pMMArcLayer->pszALName); @@ -2170,24 +2276,27 @@ static int MMCloseArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) pMMArcLayer->pF3d, pMMArcLayer->psz3DLayerName, &pMMArcLayer->pZSection, hMiraMonLayer->OffsetCheck)) { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", pMMArcLayer->pszLayerName); + goto end_label; } } - if (pMMArcLayer->pF) - fclose_function(pMMArcLayer->pF); + ret_code = 0; +end_label: + fclose_and_nullify(&pMMArcLayer->pF); + + fclose_and_nullify(&pMMArcLayer->pFAL); if (MMCloseNodeLayer(hMiraMonLayer)) - return 1; + ret_code = 1; - return 0; + return ret_code; } static int MMClosePolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) { + int ret_code = 0; struct MiraMonPolygonLayer *pMMPolygonLayer; if (!hMiraMonLayer) @@ -2197,17 +2306,17 @@ static int MMClosePolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) MMCloseArcLayer(hMiraMonLayer); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { hMiraMonLayer->nFinalElemCount = hMiraMonLayer->TopHeader.nElemCount; hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d; if (MMWriteHeader(pMMPolygonLayer->pF, &hMiraMonLayer->TopHeader)) { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + pMMPolygonLayer->pszLayerName); + goto end_label; } hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize; @@ -2215,65 +2324,69 @@ static int MMClosePolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) pMMPolygonLayer->FlushPS.SizeOfBlockToBeSaved = 0; if (MMAppendBlockToBuffer(&pMMPolygonLayer->FlushPS)) { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + pMMPolygonLayer->pszLayerName); + goto end_label; } if (MMMoveFromFileToFile(pMMPolygonLayer->pFPS, pMMPolygonLayer->pF, &hMiraMonLayer->OffsetCheck)) { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + pMMPolygonLayer->pszLayerName); + goto end_label; } - if (pMMPolygonLayer->pFPS) - fclose_function(pMMPolygonLayer->pFPS); + fclose_and_nullify(&pMMPolygonLayer->pFPS); if (*pMMPolygonLayer->pszPSName != '\0') remove_function(pMMPolygonLayer->pszPSName); // AH Section if (MMWritePHPolygonSection(hMiraMonLayer, hMiraMonLayer->OffsetCheck)) { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + pMMPolygonLayer->pszLayerName); + goto end_label; } // PAL Section pMMPolygonLayer->FlushPAL.SizeOfBlockToBeSaved = 0; if (MMAppendBlockToBuffer(&pMMPolygonLayer->FlushPAL)) { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + pMMPolygonLayer->pszLayerName); + goto end_label; } if (MMMoveFromFileToFile(pMMPolygonLayer->pFPAL, pMMPolygonLayer->pF, &hMiraMonLayer->OffsetCheck)) { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; + MMCPLError(CE_Failure, CPLE_NoWriteAccess, + "Error writing to file %s", + pMMPolygonLayer->pszLayerName); + goto end_label; } - if (pMMPolygonLayer->pFPAL) - fclose_function(pMMPolygonLayer->pFPAL); + fclose_and_nullify(&pMMPolygonLayer->pFPAL); + if (*pMMPolygonLayer->pszPALName != '\0') remove_function(pMMPolygonLayer->pszPALName); } - if (pMMPolygonLayer->pF) - fclose_function(pMMPolygonLayer->pF); + ret_code = 0; - return 0; +end_label: + fclose_and_nullify(&pMMPolygonLayer->pF); + + fclose_and_nullify(&pMMPolygonLayer->pFPAL); + + return ret_code; } int MMCloseLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) { + int ret_code = 0; //CheckMMVectorLayerVersion(hMiraMonLayer, 1) if (!hMiraMonLayer) @@ -2281,18 +2394,15 @@ int MMCloseLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) if (hMiraMonLayer->bIsPoint) { - if (MMClosePointLayer(hMiraMonLayer)) - return 1; + ret_code = MMClosePointLayer(hMiraMonLayer); } else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) { - if (MMCloseArcLayer(hMiraMonLayer)) - return 1; + ret_code = MMCloseArcLayer(hMiraMonLayer); } else if (hMiraMonLayer->bIsPolygon) { - if (MMClosePolygonLayer(hMiraMonLayer)) - return 1; + ret_code = MMClosePolygonLayer(hMiraMonLayer); } else if (hMiraMonLayer->bIsDBF) { @@ -2304,13 +2414,13 @@ int MMCloseLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) } // MiraMon metadata files - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { if (MMWriteVectorMetadata(hMiraMonLayer)) { MMCPLError(CE_Failure, CPLE_NoWriteAccess, "Some error writing in metadata file of the layer"); - return 1; + ret_code = 1; } } @@ -2319,9 +2429,9 @@ int MMCloseLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) { MMCPLError(CE_Failure, CPLE_NoWriteAccess, "Some error writing in DBF file of the layer"); - return 1; + ret_code = 1; } - return 0; + return ret_code; } /* -------------------------------------------------------------------- */ @@ -2639,7 +2749,7 @@ int MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo) { if (FlushInfo->SizeOfBlockToBeSaved) { - // If all the bloc itselfs does not fit to the buffer, + // If all the bloc itself does not fit to the buffer, // then all the block is written directly to the disk if (FlushInfo->nNumBytes == 0 && FlushInfo->SizeOfBlockToBeSaved >= FlushInfo->nBlockSize) @@ -2660,9 +2770,9 @@ int MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo) FlushInfo->pBlockToBeSaved, FlushInfo->SizeOfBlockToBeSaved); } - else // Add zero caracters + else // Add zero characters { - char zero_caracters[8] = "\0\0\0\0\0\0\0"; + char zero_caracters[8] = {0, 0, 0, 0, 0, 0, 0, 0}; memcpy((char *)FlushInfo->pBlockWhereToSaveOrRead + FlushInfo->nNumBytes, zero_caracters, FlushInfo->SizeOfBlockToBeSaved); @@ -2690,29 +2800,20 @@ int MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo) int MMMoveFromFileToFile(FILE_TYPE *pSrcFile, FILE_TYPE *pDestFile, MM_FILE_OFFSET *nOffset) { - size_t bufferSize = 100 * 1024 * 1024; // 100 MB buffer; + size_t bufferSize = 1024 * 1024; // 1 MB buffer; unsigned char *buffer; size_t bytesRead, bytesWritten; - MM_FILE_OFFSET size_of_dst_file; if (!pSrcFile || !pDestFile || !nOffset) return 0; - fseek_function(pDestFile, 0, SEEK_END); - size_of_dst_file = ftell_function(pDestFile); - - if (!size_of_dst_file) - return 0; - - if (size_of_dst_file < bufferSize) - bufferSize = (size_t)size_of_dst_file; - buffer = (unsigned char *)calloc_function(bufferSize); if (!buffer) return 1; fseek_function(pSrcFile, 0, SEEK_SET); + fseek_function(pDestFile, *nOffset, SEEK_SET); while ((bytesRead = fread_function(buffer, sizeof(unsigned char), bufferSize, pSrcFile)) > 0) { @@ -2749,7 +2850,7 @@ static void MMGetOffsetAlignedTo8(MM_FILE_OFFSET *Offset) // Reading integers depending on the version being read. int MMReadGUInt64DependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo, - GUInt64 *nUI64) + GUInt64 *pnUI64) { uint32_t nUL32; @@ -2765,12 +2866,12 @@ int MMReadGUInt64DependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, FlushInfo->pBlockToBeSaved = nullptr; return 1; } - *nUI64 = (GUInt64)nUL32; + *pnUI64 = (GUInt64)nUL32; } else { - FlushInfo->pBlockToBeSaved = (void *)nUI64; - FlushInfo->SizeOfBlockToBeSaved = sizeof(&nUI64); + FlushInfo->pBlockToBeSaved = (void *)pnUI64; + FlushInfo->SizeOfBlockToBeSaved = sizeof(*pnUI64); if (MMReadBlockFromBuffer(FlushInfo)) { FlushInfo->pBlockToBeSaved = nullptr; @@ -2784,7 +2885,7 @@ int MMReadGUInt64DependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, // Reading offsets depending on the version is being read. int MMReadOffsetDependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo, - MM_FILE_OFFSET *nUI64) + MM_FILE_OFFSET *pnUI64) { uint32_t nUL32; @@ -2800,12 +2901,12 @@ int MMReadOffsetDependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, FlushInfo->pBlockToBeSaved = nullptr; return 1; } - *nUI64 = (MM_FILE_OFFSET)nUL32; + *pnUI64 = (MM_FILE_OFFSET)nUL32; } else { - FlushInfo->pBlockToBeSaved = (void *)nUI64; - FlushInfo->SizeOfBlockToBeSaved = sizeof(&nUI64); + FlushInfo->pBlockToBeSaved = (void *)pnUI64; + FlushInfo->SizeOfBlockToBeSaved = sizeof(*pnUI64); if (MMReadBlockFromBuffer(FlushInfo)) { FlushInfo->pBlockToBeSaved = nullptr; @@ -2847,7 +2948,7 @@ int MMAppendIntegerDependingOnVersion( /* -------------------------------------------------------------------- */ /* Layer: Reading and writing layer sections */ /* This code follows the specifications of the following document: */ -/* https://www.miramon.cat/new_note/usa/notes/ \ */ +/* https://www.miramon.cat/new_note/eng/notes/ \ */ /* FormatFitxersTopologicsMiraMon.pdf */ /* -------------------------------------------------------------------- */ int MMReadAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer) @@ -2873,6 +2974,11 @@ int MMReadAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer) nElem = hMiraMonLayer->TopHeader.nElemCount; } + if (MMCheckSize_t(nElem, pMMArcLayer->nSizeArcHeader)) + { + return 1; + } + nBlockSize = nElem * (pMMArcLayer->nSizeArcHeader); if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, nBlockSize, &pBuffer, @@ -2972,11 +3078,11 @@ int MMReadAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer) free_function(pBuffer); return 1; } - // Lenght of the arc + // Length of the arc FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfLenght; + (void *)&pMMArcLayer->pArcHeader[iElem].dfLength; FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfLenght); + sizeof(pMMArcLayer->pArcHeader[iElem].dfLength); if (MMReadBlockFromBuffer(&FlushTMP)) { if (pBuffer) @@ -3012,11 +3118,8 @@ int MMWriteAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer, hMiraMonLayer->nHeaderDiskSize + hMiraMonLayer->nFinalElemCount * (pMMArcLayer->nSizeArcHeader); - if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pBuffer, DiskOffset, 0)) + if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, MM_1MB, &pBuffer, DiskOffset, + 0)) { if (pBuffer) free_function(pBuffer); @@ -3103,12 +3206,12 @@ int MMWriteAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer, free_function(pBuffer); return 1; } - // Lenght of the arc + // Length of the arc FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfLenght); + sizeof(pMMArcLayer->pArcHeader[iElem].dfLength); hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfLenght; + (void *)&pMMArcLayer->pArcHeader[iElem].dfLength; if (MMAppendBlockToBuffer(&FlushTMP)) { if (pBuffer) @@ -3235,11 +3338,8 @@ int MMWriteNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer, (pMMArcLayer->TopNodeHeader.nElemCount * pMMArcLayer->MMNode.nSizeNodeHeader); - if (MMInitFlush(&FlushTMP, pMMArcLayer->MMNode.pF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pBuffer, DiskOffset, 0)) + if (MMInitFlush(&FlushTMP, pMMArcLayer->MMNode.pF, MM_1MB, &pBuffer, + DiskOffset, 0)) { if (pBuffer) free_function(pBuffer); @@ -3319,6 +3419,13 @@ int MMReadPHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer) pMMPolygonLayer = &hMiraMonLayer->MMPolygon; + if (MMCheckSize_t(hMiraMonLayer->TopHeader.nElemCount, + pMMPolygonLayer->nPHElementSize) || + MMCheckSize_t(hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount, + hMiraMonLayer->MMPolygon.nPSElementSize)) + { + return 1; + } nBlockSize = hMiraMonLayer->TopHeader.nElemCount * (pMMPolygonLayer->nPHElementSize); @@ -3478,11 +3585,8 @@ int MMWritePHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer, nOffsetDiff = DiskOffset + hMiraMonLayer->TopHeader.nElemCount * (pMMPolygonLayer->nPHElementSize); - if (MMInitFlush(&FlushTMP, pMMPolygonLayer->pF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pBuffer, DiskOffset, 0)) + if (MMInitFlush(&FlushTMP, pMMPolygonLayer->pF, MM_1MB, &pBuffer, + DiskOffset, 0)) { if (pBuffer) free_function(pBuffer); @@ -3619,8 +3723,8 @@ int MMInitFeature(struct MiraMonFeature *hMMFeature) memset(hMMFeature, 0, sizeof(*hMMFeature)); hMMFeature->nMaxMRecords = MM_INIT_NUMBER_OF_RECORDS; - if (MMCheckSize_t( - hMMFeature->nMaxMRecords * sizeof(*(hMMFeature->pRecords)), 1)) + if (MMCheckSize_t(hMMFeature->nMaxMRecords, + sizeof(*(hMMFeature->pRecords)))) return 1; if (!hMMFeature->nMaxMRecords) @@ -3633,9 +3737,8 @@ int MMInitFeature(struct MiraMonFeature *hMMFeature) hMMFeature->pRecords[0].nMaxField = MM_INIT_NUMBER_OF_FIELDS; hMMFeature->pRecords[0].nNumField = 0; - if (MMCheckSize_t(hMMFeature->pRecords[0].nMaxField * - sizeof(*(hMMFeature->pRecords[0].pField)), - 1)) + if (MMCheckSize_t(hMMFeature->pRecords[0].nMaxField, + sizeof(*(hMMFeature->pRecords[0].pField)))) return 1; if (nullptr == (hMMFeature->pRecords[0].pField = calloc_function( (size_t)hMMFeature->pRecords[0].nMaxField * @@ -3765,6 +3868,8 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, MM_POLYGON_RINGS_COUNT nExternalRingsCount; struct MM_PH *pCurrentPolHeader = nullptr; struct MM_AH *pCurrentArcHeader; + // To access how many points have been stored in the last stringline + struct MM_AH *pLastArcHeader = nullptr; struct MM_NH *pCurrentNodeHeader, *pCurrentNodeHeaderPlus1 = nullptr; uint32_t UnsignedLongNumber; struct MiraMonArcLayer *pMMArc; @@ -3785,9 +3890,6 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, if (!hMMFeature) return MM_FATAL_ERROR_WRITING_FEATURES; - if (!hMMFeature->pCoord) - return MM_FATAL_ERROR_WRITING_FEATURES; - // Setting pointer to 3D structure (if exists). if (hMiraMonLayer->TopHeader.bIs3d) pZ = hMMFeature->pZCoord; @@ -3815,7 +3917,7 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, { if (MMResizePolHeaderPointer(&hMiraMonLayer->MMPolygon.pPolHeader, &hMiraMonLayer->MMPolygon.nMaxPolHeader, - pNodeTopHeader->nElemCount + 2, + hMiraMonLayer->TopHeader.nElemCount, MM_INCR_NUMBER_OF_POLYGONS, 0)) { MMCPLError(CE_Failure, CPLE_OutOfMemory, @@ -3858,9 +3960,10 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, if (hMiraMonLayer->TopHeader.nElemCount == 0) { MMCPLDebug("MiraMon", "Creating MiraMon database"); - if (MMCreateMMDB(hMiraMonLayer)) + if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord)) return MM_FATAL_ERROR_WRITING_FEATURES; - MMCPLDebug("MiraMon", "MiraMon database created"); + MMCPLDebug("MiraMon", "MiraMon database created. " + "Creating features..."); } } else @@ -3868,9 +3971,10 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, if (hMiraMonLayer->TopHeader.nElemCount == 1) { MMCPLDebug("MiraMon", "Creating MiraMon database"); - if (MMCreateMMDB(hMiraMonLayer)) + if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord)) return MM_FATAL_ERROR_WRITING_FEATURES; - MMCPLDebug("MiraMon", "MiraMon database created"); + MMCPLDebug("MiraMon", "MiraMon database created. " + "Creating features..."); // Universal polygon have a record with ID_GRAFIC=0 and blancs if (MMAddPolygonRecordToMMDB(hMiraMonLayer, nullptr, 0, 0, nullptr)) @@ -3898,21 +4002,24 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, if (MMCheckVersionForFID(hMiraMonLayer, hMiraMonLayer->TopHeader.nElemCount)) { - MMCPLDebug("MiraMon", "Error in MMCheckVersionForFID() (1)"); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in MMCheckVersionForFID() (1)"); return MM_STOP_WRITING_FEATURES; } // Arc if there is no polygon if (MMCheckVersionForFID(hMiraMonLayer, nArcElemCount)) { - MMCPLDebug("MiraMon", "Error in MMCheckVersionForFID() (2)"); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in MMCheckVersionForFID() (2)"); return MM_STOP_WRITING_FEATURES; } // Nodes if (MMCheckVersionForFID(hMiraMonLayer, nNodeElemCount)) { - MMCPLDebug("MiraMon", "Error in MMCheckVersionForFID() (3)"); + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in MMCheckVersionForFID() (3)"); return MM_STOP_WRITING_FEATURES; } @@ -3921,7 +4028,7 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, { if (MMCheckVersionForFID(hMiraMonLayer, nNodeElemCount + 1)) { - MMCPLDebug("MiraMon", + MMCPLError(CE_Failure, CPLE_NotSupported, "Error in MMCheckVersionForFID() (4)"); return MM_STOP_WRITING_FEATURES; } @@ -3986,6 +4093,9 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, nExternalRingsCount = 0; pCoord = hMMFeature->pCoord; + if (!pCoord) + return MM_FATAL_ERROR_WRITING_FEATURES; + // Doing real job for (nIPart = 0; nIPart < hMMFeature->nNRings; nIPart++, pArcTopHeader->nElemCount++, @@ -4040,9 +4150,9 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, if (!hMiraMonLayer->bIsPolygon) pCurrentNodeHeaderPlus1 = pCurrentNodeHeader + 1; - // Initialiting feature information (section AH/PH) + // Initializing feature information (section AH/PH) pCurrentArcHeader->nElemCount = hMMFeature->pNCoordRing[nIPart]; - pCurrentArcHeader->dfLenght = 0.0; + pCurrentArcHeader->dfLength = 0.0; pCurrentArcHeader->nOffset = pFlushAL->TotalSavedBytes + pFlushAL->nNumBytes; @@ -4094,7 +4204,7 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, { dtempx = pCoordReal->dfX - (pCoordReal + prevCoord)->dfX; dtempy = pCoordReal->dfY - (pCoordReal + prevCoord)->dfY; - pCurrentArcHeader->dfLenght += + pCurrentArcHeader->dfLength += sqrt(dtempx * dtempx + dtempy * dtempy); if (hMiraMonLayer->bIsPolygon && pCurrentPolHeader) { @@ -4109,6 +4219,10 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, else pCoord += pCurrentArcHeader->nElemCount; + // If the ring is finished a jump to the next ring must be done. + if (hMiraMonLayer->bIsPolygon && VFG & MM_END_ARC_IN_RING) + pCoord++; + nPolVertices += pCurrentArcHeader->nElemCount; // Updating bounding boxes @@ -4139,7 +4253,7 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, return MM_FATAL_ERROR_WRITING_FEATURES; } - // Node Stuff: writting NL section + // Node Stuff: writing NL section pCurrentNodeHeader->nArcsCount = 1; if (hMiraMonLayer->bIsPolygon) pCurrentNodeHeader->cNodeType = MM_RING_NODE; @@ -4247,12 +4361,16 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, pZDesc[pArcTopHeader->nElemCount].dfBBmaxz = *pZ; } pZDesc[pArcTopHeader->nElemCount].nZCount = 1; - if (hMiraMonLayer->TopHeader.nElemCount == 0) - pZDesc[hMiraMonLayer->TopHeader.nElemCount].nOffsetZ = 0; + if (pArcTopHeader->nElemCount == 0) + pZDesc[pArcTopHeader->nElemCount].nOffsetZ = 0; else - pZDesc[hMiraMonLayer->TopHeader.nElemCount].nOffsetZ = - pZDesc[hMiraMonLayer->TopHeader.nElemCount - 1].nOffsetZ + - sizeof(*pZ); + { + pLastArcHeader = + pMMArc->pArcHeader + pArcTopHeader->nElemCount - 1; + pZDesc[pArcTopHeader->nElemCount].nOffsetZ = + pZDesc[pArcTopHeader->nElemCount - 1].nOffsetZ + + sizeof(*pZ) * (pLastArcHeader->nElemCount); + } } // Exclusive polygon stuff @@ -4283,10 +4401,14 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, if (VFG & MM_EXTERIOR_ARC_SIDE) nExternalRingsCount++; - pCurrentPolHeader->nArcsCount = - (MM_POLYGON_ARCS_COUNT)hMMFeature->nNRings; - pCurrentPolHeader->nExternalRingsCount = nExternalRingsCount; - pCurrentPolHeader->nRingsCount = hMMFeature->nNRings; + pCurrentPolHeader->nArcsCount++; + //(MM_POLYGON_ARCS_COUNT)hMMFeature->nNRings; + if (VFG & MM_EXTERIOR_ARC_SIDE) + pCurrentPolHeader + ->nExternalRingsCount++; //= nExternalRingsCount; + + if (VFG & MM_END_ARC_IN_RING) + pCurrentPolHeader->nRingsCount++; //= hMMFeature->nNRings; if (nIPart == 0) { pCurrentPolHeader->nOffset = @@ -4337,7 +4459,7 @@ static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, MMUpdateBoundingBox(&pCurrentPolHeader->dfBB, &pCurrentArcHeader->dfBB); - pCurrentPolHeader->dfPerimeter += pCurrentArcHeader->dfLenght; + pCurrentPolHeader->dfPerimeter += pCurrentArcHeader->dfLength; } } @@ -4372,7 +4494,7 @@ static int MMCreateRecordDBF(struct MiraMonVectLayerInfo *hMiraMonLayer, if (hMiraMonLayer->TopHeader.nElemCount == 0) { - if (MMCreateMMDB(hMiraMonLayer)) + if (MMCreateMMDB(hMiraMonLayer, nullptr)) return MM_FATAL_ERROR_WRITING_FEATURES; } @@ -4416,7 +4538,11 @@ static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer, // to version limitations. if (MMCheckVersionForFID(hMiraMonLayer, hMiraMonLayer->TopHeader.nElemCount + nCoord)) + { + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in MMCheckVersionForFID() (5)"); return MM_STOP_WRITING_FEATURES; + } if (hMiraMonLayer->TopHeader.bIs3d) { @@ -4428,6 +4554,12 @@ static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer, else { pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription; + if (!pZDescription) + { + MMCPLError(CE_Failure, CPLE_ObjectNull, + "Error: pZDescription should not be nullptr"); + return MM_STOP_WRITING_FEATURES; + } if (MMCheckVersionFor3DOffset( hMiraMonLayer, pZDescription[nElemCount - 1].nOffsetZ + sizeof(*pZ), @@ -4452,6 +4584,12 @@ static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer, } pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription; + if (!pZDescription) + { + MMCPLError(CE_Failure, CPLE_ObjectNull, + "Error: pZDescription should not be nullptr"); + return MM_STOP_WRITING_FEATURES; + } pZDescription[nElemCount].dfBBminz = *pZ; pZDescription[nElemCount].dfBBmaxz = *pZ; @@ -4471,7 +4609,7 @@ static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer, (void *)hMiraMonLayer->MMPoint.pZSection.pZL; // Dump point or points (MiraMon does not have multiple points) - for (nIVertice = 0; nIVertice < nCoord; nIVertice++, pCoord++, pZ++) + for (nIVertice = 0; nIVertice < nCoord; nIVertice++, pCoord++) { // Updating the bounding box of the layer MMUpdateBoundingBoxXY(&hMiraMonLayer->TopHeader.hBB, pCoord); @@ -4499,6 +4637,13 @@ static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer, &hMiraMonLayer->MMPoint.pZSection.FlushZL)) return MM_FATAL_ERROR_WRITING_FEATURES; + if (!pZDescription) + { + MMCPLError(CE_Failure, CPLE_ObjectNull, + "Error: pZDescription should not be nullptr"); + return MM_STOP_WRITING_FEATURES; + } + if (pZDescription[nElemCount].dfBBminz > *pZ) pZDescription[nElemCount].dfBBminz = *pZ; if (pZDescription[nElemCount].dfBBmaxz < *pZ) @@ -4508,12 +4653,14 @@ static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer, hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz = *pZ; if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz < *pZ) hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz = *pZ; + + pZ++; } } if (hMiraMonLayer->TopHeader.nElemCount == 0) { - if (MMCreateMMDB(hMiraMonLayer)) + if (MMCreateMMDB(hMiraMonLayer, hMMFeature->pCoord)) return MM_FATAL_ERROR_WRITING_FEATURES; } @@ -4596,7 +4743,7 @@ int MMAddFeature(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MiraMonFeature *hMiraMonFeature) { int re; - MM_INTERNAL_FID previusFID = 0; + MM_INTERNAL_FID previousFID = 0; if (!hMiraMonLayer) return MM_FATAL_ERROR_WRITING_FEATURES; @@ -4612,7 +4759,7 @@ int MMAddFeature(struct MiraMonVectLayerInfo *hMiraMonLayer, } if (hMiraMonFeature) - previusFID = hMiraMonLayer->TopHeader.nElemCount; + previousFID = hMiraMonLayer->TopHeader.nElemCount; if (hMiraMonLayer->bIsPoint) { @@ -4620,7 +4767,7 @@ int MMAddFeature(struct MiraMonVectLayerInfo *hMiraMonLayer, if (hMiraMonFeature) { hMiraMonFeature->nReadFeatures = - hMiraMonLayer->TopHeader.nElemCount - previusFID; + hMiraMonLayer->TopHeader.nElemCount - previousFID; } return re; } @@ -4631,7 +4778,7 @@ int MMAddFeature(struct MiraMonVectLayerInfo *hMiraMonLayer, if (hMiraMonFeature) { hMiraMonFeature->nReadFeatures = - hMiraMonLayer->TopHeader.nElemCount - previusFID; + hMiraMonLayer->TopHeader.nElemCount - previousFID; } return re; } @@ -4642,7 +4789,7 @@ int MMAddFeature(struct MiraMonVectLayerInfo *hMiraMonLayer, if (hMiraMonFeature) { hMiraMonFeature->nReadFeatures = - hMiraMonLayer->TopHeader.nElemCount - previusFID; + hMiraMonLayer->TopHeader.nElemCount - previousFID; } return re; } @@ -4712,20 +4859,28 @@ int MMResizeMiraMonFieldValue(struct MiraMonFieldValue **pFieldValue, MM_EXT_DBF_N_MULTIPLE_RECORDS nProposedMax) { MM_EXT_DBF_N_MULTIPLE_RECORDS nPrevMax; + MM_EXT_DBF_N_MULTIPLE_RECORDS nNewMax; + void *pTmp; if (nNum < *nMax) return 0; nPrevMax = *nMax; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pFieldValue) = realloc_function( - *pFieldValue, (size_t)*nMax * sizeof(**pFieldValue))) == nullptr) + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pFieldValue))) + { + return 1; + } + if ((pTmp = realloc_function( + *pFieldValue, (size_t)nNewMax * sizeof(**pFieldValue))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMResizeMiraMonFieldValue())"); return 1; } + *nMax = nNewMax; + *pFieldValue = pTmp; memset((*pFieldValue) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pFieldValue)); @@ -4739,13 +4894,21 @@ int MMResizeMiraMonPolygonArcs(struct MM_PAL_MEM **pFID, MM_POLYGON_ARCS_COUNT nProposedMax) { MM_POLYGON_ARCS_COUNT nPrevMax; + MM_POLYGON_ARCS_COUNT nNewMax; + void *pTmp; if (nNum < *nMax) return 0; nPrevMax = *nMax; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pFID) = realloc_function(*pFID, (size_t)*nMax * sizeof(**pFID))) == + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pFID))) + { + return 1; + } + if (nNewMax == 0 && *pFID) + return 0; + if ((pTmp = realloc_function(*pFID, (size_t)nNewMax * sizeof(**pFID))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, @@ -4753,6 +4916,8 @@ int MMResizeMiraMonPolygonArcs(struct MM_PAL_MEM **pFID, "driver (MMResizeMiraMonPolygonArcs())"); return 1; } + *nMax = nNewMax; + *pFID = pTmp; memset((*pFID) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pFID)); return 0; @@ -4765,14 +4930,22 @@ int MMResizeMiraMonRecord(struct MiraMonRecord **pMiraMonRecord, MM_EXT_DBF_N_MULTIPLE_RECORDS nProposedMax) { MM_EXT_DBF_N_MULTIPLE_RECORDS nPrevMax; + MM_EXT_DBF_N_MULTIPLE_RECORDS nNewMax; + void *pTmp; if (nNum < *nMax) return 0; nPrevMax = *nMax; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pMiraMonRecord) = realloc_function( - *pMiraMonRecord, (size_t)*nMax * sizeof(**pMiraMonRecord))) == + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pMiraMonRecord))) + { + return 1; + } + if (nNewMax == 0 && *pMiraMonRecord) + return 0; + if ((pTmp = realloc_function(*pMiraMonRecord, + (size_t)nNewMax * sizeof(**pMiraMonRecord))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, @@ -4780,6 +4953,8 @@ int MMResizeMiraMonRecord(struct MiraMonRecord **pMiraMonRecord, "driver (MMResizeMiraMonRecord())"); return 1; } + *nMax = nNewMax; + *pMiraMonRecord = pTmp; memset((*pMiraMonRecord) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pMiraMonRecord)); @@ -4790,12 +4965,22 @@ int MMResizeZSectionDescrPointer(struct MM_ZD **pZDescription, GUInt64 *nMax, GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax) { + GUInt64 nNewMax, nPrevMax; + void *pTmp; + if (nNum < *nMax) return 0; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pZDescription) = realloc_function( - *pZDescription, (size_t)*nMax * sizeof(**pZDescription))) == + nPrevMax = *nMax; + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pZDescription))) + { + return 1; + } + if (nNewMax == 0 && *pZDescription) + return 0; + if ((pTmp = realloc_function(*pZDescription, + (size_t)nNewMax * sizeof(**pZDescription))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, @@ -4803,60 +4988,110 @@ int MMResizeZSectionDescrPointer(struct MM_ZD **pZDescription, GUInt64 *nMax, "driver (MMResizeZSectionDescrPointer())"); return 1; } + *nMax = nNewMax; + *pZDescription = pTmp; + + memset((*pZDescription) + nPrevMax, 0, + (size_t)(*nMax - nPrevMax) * sizeof(**pZDescription)); return 0; } int MMResizeNodeHeaderPointer(struct MM_NH **pNodeHeader, GUInt64 *nMax, GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax) { + GUInt64 nNewMax, nPrevMax; + void *pTmp; + if (nNum < *nMax) return 0; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pNodeHeader) = realloc_function( - *pNodeHeader, (size_t)*nMax * sizeof(**pNodeHeader))) == nullptr) + nPrevMax = *nMax; + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pNodeHeader))) + { + return 1; + } + if (nNewMax == 0 && *pNodeHeader) + return 0; + if ((pTmp = realloc_function( + *pNodeHeader, (size_t)nNewMax * sizeof(**pNodeHeader))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMResizeNodeHeaderPointer())"); return 1; } + *nMax = nNewMax; + *pNodeHeader = pTmp; + + memset((*pNodeHeader) + nPrevMax, 0, + (size_t)(*nMax - nPrevMax) * sizeof(**pNodeHeader)); return 0; } int MMResizeArcHeaderPointer(struct MM_AH **pArcHeader, GUInt64 *nMax, GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax) { + GUInt64 nNewMax, nPrevMax; + void *pTmp; + if (nNum < *nMax) return 0; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pArcHeader) = realloc_function( - *pArcHeader, (size_t)*nMax * sizeof(**pArcHeader))) == nullptr) + nPrevMax = *nMax; + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pArcHeader))) + { + return 1; + } + if (nNewMax == 0 && *pArcHeader) + return 0; + if ((pTmp = realloc_function( + *pArcHeader, (size_t)nNewMax * sizeof(**pArcHeader))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMResizeArcHeaderPointer())"); return 1; } + *nMax = nNewMax; + *pArcHeader = pTmp; + + memset((*pArcHeader) + nPrevMax, 0, + (size_t)(*nMax - nPrevMax) * sizeof(**pArcHeader)); return 0; } int MMResizePolHeaderPointer(struct MM_PH **pPolHeader, GUInt64 *nMax, GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax) { + GUInt64 nNewMax, nPrevMax; + void *pTmp; + if (nNum < *nMax) return 0; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pPolHeader) = realloc_function( - *pPolHeader, (size_t)*nMax * sizeof(**pPolHeader))) == nullptr) + nPrevMax = *nMax; + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pPolHeader))) + { + return 1; + } + if (nNewMax == 0 && *pPolHeader) + return 0; + if ((pTmp = realloc_function( + *pPolHeader, (size_t)nNewMax * sizeof(**pPolHeader))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMResizePolHeaderPointer())"); return 1; } + *nMax = nNewMax; + *pPolHeader = pTmp; + + memset((*pPolHeader) + nPrevMax, 0, + (size_t)(*nMax - nPrevMax) * sizeof(**pPolHeader)); return 0; } @@ -4866,29 +5101,53 @@ int MMResize_MM_N_VERTICES_TYPE_Pointer(MM_N_VERTICES_TYPE **pVrt, MM_N_VERTICES_TYPE nIncr, MM_N_VERTICES_TYPE nProposedMax) { + MM_N_VERTICES_TYPE nNewMax, nPrevMax; + void *pTmp; + if (nNum < *nMax) return 0; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pVrt) = realloc_function(*pVrt, (size_t)*nMax * sizeof(**pVrt))) == - nullptr) + nPrevMax = *nMax; + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pVrt))) { - MMCPLError(CE_Failure, CPLE_OutOfMemory, + return 1; + } + if (nNewMax == 0 && *pVrt) + return 0; + if ((pTmp = realloc_function(*pVrt, (size_t)nNewMax * sizeof(**pVrt))) == + nullptr) + { + MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMResize_MM_N_VERTICES_TYPE_Pointer())"); return 1; } + *nMax = nNewMax; + *pVrt = pTmp; + + memset((*pVrt) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pVrt)); return 0; } int MMResizeVFGPointer(char **pInt, MM_INTERNAL_FID *nMax, MM_INTERNAL_FID nNum, MM_INTERNAL_FID nIncr, MM_INTERNAL_FID nProposedMax) { + MM_N_VERTICES_TYPE nNewMax, nPrevMax; + void *pTmp; + if (nNum < *nMax) return 0; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pInt) = realloc_function(*pInt, (size_t)*nMax * sizeof(**pInt))) == + nPrevMax = *nMax; + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pInt))) + { + return 1; + } + if (nNewMax == 0 && *pInt) + return 0; + if ((pTmp = realloc_function(*pInt, (size_t)nNewMax * sizeof(**pInt))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, @@ -4896,6 +5155,10 @@ int MMResizeVFGPointer(char **pInt, MM_INTERNAL_FID *nMax, MM_INTERNAL_FID nNum, "driver (MMResizeVFGPointer())"); return 1; } + *nMax = nNewMax; + *pInt = pTmp; + + memset((*pInt) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pInt)); return 0; } @@ -4904,18 +5167,33 @@ int MMResizeMM_POINT2DPointer(struct MM_POINT_2D **pPoint2D, MM_N_VERTICES_TYPE nIncr, MM_N_VERTICES_TYPE nProposedMax) { + MM_N_VERTICES_TYPE nNewMax, nPrevMax; + void *pTmp; + if (nNum < *nMax) return 0; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pPoint2D) = realloc_function( - *pPoint2D, (size_t)*nMax * sizeof(**pPoint2D))) == nullptr) + nPrevMax = *nMax; + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pPoint2D))) + { + return 1; + } + if (nNewMax == 0 && *pPoint2D) + return 0; + if ((pTmp = realloc_function(*pPoint2D, (size_t)nNewMax * + sizeof(**pPoint2D))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMResizeMM_POINT2DPointer())"); return 1; } + *nMax = nNewMax; + *pPoint2D = pTmp; + + memset((*pPoint2D) + nPrevMax, 0, + (size_t)(*nMax - nPrevMax) * sizeof(**pPoint2D)); return 0; } @@ -4923,18 +5201,33 @@ int MMResizeDoublePointer(MM_COORD_TYPE **pDouble, MM_N_VERTICES_TYPE *nMax, MM_N_VERTICES_TYPE nNum, MM_N_VERTICES_TYPE nIncr, MM_N_VERTICES_TYPE nProposedMax) { + MM_N_VERTICES_TYPE nNewMax, nPrevMax; + void *pTmp; + if (nNum < *nMax) return 0; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pDouble) = realloc_function( - *pDouble, (size_t)*nMax * sizeof(**pDouble))) == nullptr) + nPrevMax = *nMax; + nNewMax = max_function(nNum + nIncr, nProposedMax); + if (MMCheckSize_t(nNewMax, sizeof(**pDouble))) + { + return 1; + } + if (nNewMax == 0 && *pDouble) + return 0; + if ((pTmp = realloc_function(*pDouble, (size_t)nNewMax * + sizeof(**pDouble))) == nullptr) { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMResizeDoublePointer())"); return 1; } + *nMax = nNewMax; + *pDouble = pTmp; + + memset((*pDouble) + nPrevMax, 0, + (size_t)(*nMax - nPrevMax) * sizeof(**pDouble)); return 0; } @@ -4966,9 +5259,9 @@ int MMResizeStringToOperateIfNeeded(struct MiraMonVectLayerInfo *hMiraMonLayer, // Checks if a string is empty int MMIsEmptyString(const char *string) { - char *ptr; + const char *ptr = string; - for (ptr = (char *)string; *ptr; ptr++) + for (; *ptr; ptr++) if (*ptr != ' ' && *ptr != '\t') return 0; @@ -4984,86 +5277,81 @@ char *MMReturnValueFromSectionINIFile(const char *filename, const char *section, const char *key) { char *value = nullptr; - char line[16000]; +#ifndef GDAL_COMPILATION + char line[1024]; +#endif + const char *pszLine; char *section_header = nullptr; size_t key_len = 0; - size_t bytes_read; - char *pszString; - char *start; - char *end; FILE_TYPE *file = fopen_function(filename, "rb"); if (file == nullptr) { - sprintf(local_message, "Cannot open INI file %s.", filename); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, "Cannot open INI file %s.", + filename); return nullptr; } if (key) key_len = strlen(key); - while ((bytes_read = fread_function(line, 1, sizeof(line), file)) > 0) +#ifndef GDAL_COMPILATION + while (fgets(line, (int)sizeof(line), file)) { - // As MiraMon is written in ANSI convertion to UTF-8 must be done - line[bytes_read - 1] = '\0'; - pszString = CPLRecode_function(line, CPL_ENC_ISO8859_1, CPL_ENC_UTF8); - MM_strnzcpy(line, pszString, 16000); - CPLFree_function(pszString); + pszLine = line; +#else + while ((pszLine = CPLReadLine2L(file, 1024, nullptr)) != nullptr) + { +#endif + char *pszString = + CPLRecode_function(pszLine, CPL_ENC_ISO8859_1, CPL_ENC_UTF8); - // Iterate through the read buffer - start = line; - end = line + bytes_read; - while (start < end) + // Skip comments and empty lines + if (*pszString == ';' || *pszString == '#' || *pszString == '\n' || + *pszString == '\r') { - if (!start) - return nullptr; - - // Skip comments and empty lines - if (*start == ';' || *start == '#' || *start == '\n' || - *start == '\r') - { - while (start < end && *start != '\n') - start++; - start++; // Move to next line - continue; - } - - if (!start) - return nullptr; + free_function(pszString); + // Move to next line + continue; + } - // Check for section header - if (*start == '[') + // Check for section header + if (*pszString == '[') + { + char *section_end = strchr(pszString, ']'); + if (section_end != nullptr) { - char *section_end = strchr(start, ']'); - if (section_end != nullptr) - { - *section_end = '\0'; // Terminate the string at ']' - if (section_header) - free_function(section_header); - section_header = - strdup_function(start + 1); // Skip the '[' - } - start = section_end + 1; - continue; + *section_end = '\0'; // Terminate the string at ']' + if (section_header) + free_function(section_header); + section_header = + strdup_function(pszString + 1); // Skip the '[' } + free_function(pszString); + continue; + } - if (!start) - return nullptr; - - if (key) + if (key) + { + // If the current line belongs to the desired section + if (section_header != nullptr && + strcmp(section_header, section) == 0) { - // If the current line belongs to the desired section - if (section_header != nullptr && - strcmp(section_header, section) == 0) + // Check if the line contains the desired key + if (strncmp(pszString, key, key_len) == 0 && + pszString[key_len] == '=') { - // Check if the line contains the desired key - if (strncmp(start, key, key_len) == 0 && - start[key_len] == '=') + // Extract the value + char *value_start = pszString + key_len + 1; + char *value_end = strstr(value_start, "\r\n"); + if (value_end != nullptr) + { + *value_end = + '\0'; // Terminate the string at newline character if found + } + else { - // Extract the value - char *value_start = start + key_len + 1; - char *value_end = strstr(value_start, "\r\n"); + value_end = strstr(value_start, "\n"); if (value_end != nullptr) { *value_end = @@ -5071,42 +5359,31 @@ char *MMReturnValueFromSectionINIFile(const char *filename, const char *section, } else { - value_end = strstr(value_start, "\n"); + value_end = strstr(value_start, "\r"); if (value_end != nullptr) { *value_end = '\0'; // Terminate the string at newline character if found } - else - { - value_end = strstr(value_start, "\r"); - if (value_end != nullptr) - { - *value_end = - '\0'; // Terminate the string at newline character if found - } - } } - - value = strdup_function(value_start); - fclose_function(file); - free_function(section_header); // Free allocated memory - return value; } + + value = strdup_function(value_start); + fclose_function(file); + free_function(section_header); // Free allocated memory + free_function(pszString); + return value; } } - else - { - value = section_header; // Freed out - fclose_function(file); - return value; - } - - // Move to the next line - while (start < end && *start != '\n') - start++; - start++; } + else + { + value = section_header; // Freed out + fclose_function(file); + free_function(pszString); + return value; + } + free_function(pszString); } if (section_header) @@ -5119,27 +5396,16 @@ char *MMReturnValueFromSectionINIFile(const char *filename, const char *section, int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult, MM_BYTE direction) { - static char aEPSGCodeSRS[MM_MAX_ID_SNY]; char *aMMIDDBFFile = nullptr; //m_idofic.dbf - FILE *pfMMSRS; + FILE_TYPE *pfMMSRS; + const char *pszLine; size_t nLong; - int nLongBuffer = 5000; - char *pszBuffer = calloc_function(nLongBuffer); char *id_geodes, *psidgeodes, *epsg; - if (!pszBuffer) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMReturnCodeFromMM_m_idofic())"); - return 1; - } if (!pMMSRS_or_pSRS) { - free_function(pszBuffer); return 1; } - memset(aEPSGCodeSRS, '\0', sizeof(*aEPSGCodeSRS)); #ifdef GDAL_COMPILATION aMMIDDBFFile = strdup_function(CPLFindFile("gdal", "MM_m_idofic.csv")); @@ -5153,17 +5419,15 @@ int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult, if (!aMMIDDBFFile) { - free_function(pszBuffer); MMCPLError(CE_Failure, CPLE_OpenFailed, "Error opening data\\MM_m_idofic.csv.\n"); return 1; } // Opening the file with SRS information - if (nullptr == (pfMMSRS = fopen(aMMIDDBFFile, "r"))) + if (nullptr == (pfMMSRS = fopen_function(aMMIDDBFFile, "r"))) { free_function(aMMIDDBFFile); - free_function(pszBuffer); MMCPLError(CE_Failure, CPLE_OpenFailed, "Error opening data\\MM_m_idofic.csv.\n"); return 1; @@ -5171,30 +5435,28 @@ int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult, free_function(aMMIDDBFFile); // Checking the header of the csv file - memset(pszBuffer, 0, nLongBuffer); - if (!fgets(pszBuffer, nLongBuffer, pfMMSRS)) + pszLine = CPLReadLine2L(pfMMSRS, 1024, nullptr); + if (!pszLine) + { - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); MMCPLError(CE_Failure, CPLE_NotSupported, "Wrong format in data\\MM_m_idofic.csv.\n"); return 1; } - id_geodes = strstr(pszBuffer, "ID_GEODES"); + id_geodes = strstr(pszLine, "ID_GEODES"); if (!id_geodes) { - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); MMCPLError(CE_Failure, CPLE_NotSupported, "Wrong format in data\\MM_m_idofic.csv.\n"); return 1; } id_geodes[strlen("ID_GEODES")] = '\0'; - psidgeodes = strstr(pszBuffer, "PSIDGEODES"); + psidgeodes = strstr(pszLine, "PSIDGEODES"); if (!psidgeodes) { - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); MMCPLError(CE_Failure, CPLE_NotSupported, "Wrong format in data\\MM_m_idofic.csv.\n"); return 1; @@ -5202,33 +5464,30 @@ int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult, psidgeodes[strlen("PSIDGEODES")] = '\0'; // Is PSIDGEODES in first place? - if (strncmp(pszBuffer, psidgeodes, strlen("PSIDGEODES"))) + if (strncmp(pszLine, psidgeodes, strlen("PSIDGEODES"))) { - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); MMCPLError(CE_Failure, CPLE_NotSupported, "Wrong format in data\\MM_m_idofic.csv.\n"); return 1; } // Is ID_GEODES after PSIDGEODES? - if (strncmp(pszBuffer + strlen("PSIDGEODES") + 1, "ID_GEODES", + if (strncmp(pszLine + strlen("PSIDGEODES") + 1, "ID_GEODES", strlen("ID_GEODES"))) { - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); MMCPLError(CE_Failure, CPLE_NotSupported, "Wrong format in data\\MM_m_idofic.csv.\n"); return 1; } - // Looking for the information - while (fgets(pszBuffer, nLongBuffer, pfMMSRS)) + // Looking for the information. + while ((pszLine = CPLReadLine2L(pfMMSRS, 1024, nullptr)) != nullptr) { - id_geodes = strstr(pszBuffer, ";"); - if (!id_geodes || (id_geodes + 1)[0] == '\n') + id_geodes = strstr(pszLine, ";"); + if (!id_geodes) { - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); MMCPLError(CE_Failure, CPLE_NotSupported, "Wrong format in data\\MM_m_idofic.csv.\n"); return 1; @@ -5237,23 +5496,25 @@ int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult, psidgeodes = strstr(id_geodes + 1, ";"); if (!psidgeodes) { - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); MMCPLError(CE_Failure, CPLE_NotSupported, "Wrong format in data\\MM_m_idofic.csv.\n"); return 1; } id_geodes[(ptrdiff_t)psidgeodes - (ptrdiff_t)id_geodes] = '\0'; - psidgeodes = pszBuffer; - psidgeodes[(ptrdiff_t)id_geodes - (ptrdiff_t)psidgeodes] = '\0'; + psidgeodes = strdup_function(pszLine); + psidgeodes[(ptrdiff_t)id_geodes - (ptrdiff_t)pszLine] = '\0'; id_geodes++; if (direction == EPSG_FROM_MMSRS) { // I have pMMSRS and I want pSRS if (strcmp(pMMSRS_or_pSRS, id_geodes)) + { + free_function(psidgeodes); continue; + } epsg = strstr(psidgeodes, "EPSG:"); nLong = strlen("EPSG:"); @@ -5262,15 +5523,15 @@ int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult, if (epsg[nLong] != '\0') { strcpy(szResult, epsg + nLong); - free_function(pszBuffer); - fclose(pfMMSRS); + free_function(psidgeodes); + fclose_function(pfMMSRS); return 0; // found } else { - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); *szResult = '\0'; + free_function(psidgeodes); return 1; // not found } } @@ -5287,41 +5548,44 @@ int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult, if (!strcmp(pMMSRS_or_pSRS, epsg + nLong)) { strcpy(szResult, id_geodes); - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); + free_function(psidgeodes); return 0; // found } } } } + free_function(psidgeodes); } - free_function(pszBuffer); - fclose(pfMMSRS); + fclose_function(pfMMSRS); return 1; // not found } #define LineReturn "\r\n" // Generates an idientifier that REL 4 MiraMon metadata needs. -static char *MMGenerateFileIdentifierFromMetadataFileName(char *pMMFN) +static void MMGenerateFileIdentifierFromMetadataFileName(char *pMMFN, + char *aFileIdentifier) { - static char aCharRand[8], - aCharset[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + char aCharRand[8]; + static const char aCharset[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; int i, len_charset; - static char aFileIdentifier[MM_MAX_LEN_LAYER_IDENTIFIER]; memset(aFileIdentifier, '\0', MM_MAX_LEN_LAYER_IDENTIFIER); aCharRand[0] = '_'; len_charset = (int)strlen(aCharset); for (i = 1; i < 7; i++) + { + // coverity[dont_call] aCharRand[i] = aCharset[rand() % (len_charset - 1)]; + } aCharRand[7] = '\0'; - MM_strnzcpy(aFileIdentifier, pMMFN, MM_MAX_LEN_LAYER_IDENTIFIER - 7); + CPLStrlcpy(aFileIdentifier, pMMFN, MM_MAX_LEN_LAYER_IDENTIFIER - 7); strcat(aFileIdentifier, aCharRand); - return aFileIdentifier; + return; } // Converts a string from UTF-8 to ANSI to be written in a REL 4 file @@ -5368,12 +5632,11 @@ MMWrite_ANSI_MetadataKeyDescriptor(struct MiraMonVectorMetaData *hMMMD, */ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) { - char aMessage[MM_MESSAGE_LENGHT], + char aMessage[MM_MESSAGE_LENGTH], aFileIdentifier[MM_MAX_LEN_LAYER_IDENTIFIER], aMMIDSRS[MM_MAX_ID_SNY]; MM_EXT_DBF_N_FIELDS nIField; FILE_TYPE *pF; time_t currentTime; - struct tm *pLocalTime; char aTimeString[200]; if (!hMMMD->aLayerName) @@ -5381,8 +5644,8 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) if (nullptr == (pF = fopen_function(hMMMD->aLayerName, "wb"))) { - sprintf(local_message, "The file %s must exist.", hMMMD->aLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, "The file %s must exist.", + hMMMD->aLayerName); return 1; } @@ -5399,9 +5662,8 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) // Writing METADADES section fprintf_function(pF, "\r\n[%s]" LineReturn, SECTION_METADADES); - strcpy(aMessage, hMMMD->aLayerName); - strcpy(aFileIdentifier, - MMGenerateFileIdentifierFromMetadataFileName(aMessage)); + CPLStrlcpy(aMessage, hMMMD->aLayerName, sizeof(aMessage)); + MMGenerateFileIdentifierFromMetadataFileName(aMessage, aFileIdentifier); fprintf_function(pF, "%s=%s" LineReturn, KEY_FileIdentifier, aFileIdentifier); fprintf_function(pF, "%s=%s" LineReturn, KEY_language, KEY_Value_eng); @@ -5509,14 +5771,31 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, LineReturn "[%s]" LineReturn, SECTION_OVERVIEW); currentTime = time(nullptr); - pLocalTime = localtime(¤tTime); - snprintf(aTimeString, sizeof(aTimeString), - "%04d%02d%02d %02d%02d%02d%02d+00:00", pLocalTime->tm_year + 1900, - pLocalTime->tm_mon + 1, pLocalTime->tm_mday, pLocalTime->tm_hour, - pLocalTime->tm_min, pLocalTime->tm_sec, 0); - fprintf_function(pF, "%s=%s" LineReturn, KEY_CreationDate, aTimeString); - fprintf_function(pF, LineReturn); +#ifdef GDAL_COMPILATION + { + struct tm ltime; + VSILocalTime(¤tTime, <ime); + snprintf(aTimeString, sizeof(aTimeString), + "%04d%02d%02d %02d%02d%02d%02d+00:00", ltime.tm_year + 1900, + ltime.tm_mon + 1, ltime.tm_mday, ltime.tm_hour, ltime.tm_min, + ltime.tm_sec, 0); + fprintf_function(pF, "%s=%s" LineReturn, KEY_CreationDate, aTimeString); + fprintf_function(pF, LineReturn); + } +#else + { + struct tm *pLocalTime; + pLocalTime = localtime(¤tTime); + snprintf(aTimeString, sizeof(aTimeString), + "%04d%02d%02d %02d%02d%02d%02d+00:00", + pLocalTime->tm_year + 1900, pLocalTime->tm_mon + 1, + pLocalTime->tm_mday, pLocalTime->tm_hour, pLocalTime->tm_min, + pLocalTime->tm_sec, 0); + fprintf_function(pF, "%s=%s" LineReturn, KEY_CreationDate, aTimeString); + fprintf_function(pF, LineReturn); + } +#endif // Writing TAULA_PRINCIPAL section fprintf_function(pF, "[%s]" LineReturn, SECTION_TAULA_PRINCIPAL); @@ -5531,7 +5810,7 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) MMWrite_ANSI_MetadataKeyDescriptor( hMMMD, pF, szInternalGraphicIdentifierEng, - szInternalGraphicIdentifierCat, szInternalGraphicIdentifierEsp); + szInternalGraphicIdentifierCat, szInternalGraphicIdentifierSpa); if (hMMMD->ePlainLT == MM_LayerType_Arc) { @@ -5543,16 +5822,15 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfVerticesEng, szNumberOfVerticesCat, - szNumberOfVerticesEsp); + szNumberOfVerticesSpa); fprintf_function(pF, LineReturn); fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, szMMNomCampLongitudArcDefecte); - fprintf_function(pF, "visible=0" LineReturn); fprintf_function(pF, "simbolitzable=0" LineReturn); fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor( - hMMMD, pF, szLenghtOfAarcEng, szLenghtOfAarcCat, szLenghtOfAarcEsp); + hMMMD, pF, szLengthOfAarcEng, szLengthOfAarcCat, szLengthOfAarcSpa); fprintf_function(pF, LineReturn); fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, @@ -5561,7 +5839,7 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, "simbolitzable=0" LineReturn); fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szInitialNodeEng, - szInitialNodeCat, szInitialNodeEsp); + szInitialNodeCat, szInitialNodeSpa); fprintf_function(pF, LineReturn); fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, @@ -5570,8 +5848,9 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, "simbolitzable=0" LineReturn); fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szFinalNodeEng, - szFinalNodeCat, szFinalNodeEsp); + szFinalNodeCat, szFinalNodeSpa); + fprintf_function(pF, LineReturn); fprintf_function(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn); fprintf_function(pF, "NomCampNVertexs=%s" LineReturn, szMMNomCampNVertexsDefecte); @@ -5592,7 +5871,7 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfArcsToNodeEng, szNumberOfArcsToNodeCat, - szNumberOfArcsToNodeEsp); + szNumberOfArcsToNodeSpa); fprintf_function(pF, LineReturn); fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, @@ -5601,7 +5880,7 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, "simbolitzable=0" LineReturn); fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNodeTypeEng, - szNodeTypeCat, szNodeTypeEsp); + szNodeTypeCat, szNodeTypeSpa); } else if (hMMMD->ePlainLT == MM_LayerType_Pol) { @@ -5613,27 +5892,25 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfVerticesEng, szNumberOfVerticesCat, - szNumberOfVerticesEsp); + szNumberOfVerticesSpa); fprintf_function(pF, LineReturn); fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, szMMNomCampPerimetreDefecte); - fprintf_function(pF, "visible=0" LineReturn); fprintf_function(pF, "simbolitzable=0" LineReturn); fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor( hMMMD, pF, szPerimeterOfThePolygonEng, szPerimeterOfThePolygonCat, - szPerimeterOfThePolygonEsp); + szPerimeterOfThePolygonSpa); fprintf_function(pF, LineReturn); fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, szMMNomCampAreaDefecte); - fprintf_function(pF, "visible=0" LineReturn); fprintf_function(pF, "simbolitzable=0" LineReturn); fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szAreaOfThePolygonEng, szAreaOfThePolygonCat, - szAreaOfThePolygonEsp); + szAreaOfThePolygonSpa); fprintf_function(pF, LineReturn); fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, @@ -5642,7 +5919,7 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, "simbolitzable=0" LineReturn); fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor( - hMMMD, pF, szNumberOfArcsEng, szNumberOfArcsCat, szNumberOfArcsEsp); + hMMMD, pF, szNumberOfArcsEng, szNumberOfArcsCat, szNumberOfArcsSpa); fprintf_function(pF, LineReturn); fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, @@ -5652,8 +5929,9 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) fprintf_function(pF, "MostrarUnitats=0" LineReturn); MMWrite_ANSI_MetadataKeyDescriptor( hMMMD, pF, szNumberOfElementaryPolygonsEng, - szNumberOfElementaryPolygonsCat, szNumberOfElementaryPolygonsEsp); + szNumberOfElementaryPolygonsCat, szNumberOfElementaryPolygonsSpa); + fprintf_function(pF, LineReturn); fprintf_function(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn); fprintf_function(pF, "NomCampNVertexs=%s" LineReturn, szMMNomCampNVertexsDefecte); @@ -5672,22 +5950,36 @@ static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) // For each field of the databes for (nIField = 0; nIField < hMMMD->pLayerDB->nNFields; nIField++) { + fprintf_function(pF, LineReturn "[%s:%s]" LineReturn, + SECTION_TAULA_PRINCIPAL, + hMMMD->pLayerDB->pFields[nIField].pszFieldName); + if (!MMIsEmptyString( hMMMD->pLayerDB->pFields[nIField].pszFieldDescription) && !MMIsEmptyString( hMMMD->pLayerDB->pFields[nIField].pszFieldName)) { - fprintf_function( - pF, LineReturn "[%s:%s]" LineReturn, - SECTION_TAULA_PRINCIPAL, - hMMMD->pLayerDB->pFields[nIField].pszFieldName); - MMWrite_ANSI_MetadataKeyDescriptor( hMMMD, pF, hMMMD->pLayerDB->pFields[nIField].pszFieldDescription, hMMMD->pLayerDB->pFields[nIField].pszFieldDescription, hMMMD->pLayerDB->pFields[nIField].pszFieldDescription); } + + // Exception in a particular case: "altura" is a catalan word that means + // "height". Its unit by default will be "m" instead of "unknown". + // The same goes for "z", which easily means height. + if (EQUAL("altura", + hMMMD->pLayerDB->pFields[nIField].pszFieldName) || + EQUAL("z", hMMMD->pLayerDB->pFields[nIField].pszFieldName)) + { + fprintf_function(pF, "unitats=m" LineReturn); + } + else + { + // By default units of field values will not be shown. + fprintf_function(pF, "MostrarUnitats=0" LineReturn); + } } } fclose_function(pF); @@ -5825,7 +6117,7 @@ int MMWriteVectorMetadata(struct MiraMonVectLayerInfo *hMiraMonLayer) } // Verifies the version of a MiraMon REL 4 file. -int MMCheck_REL_FILE(char *szREL_file) +int MMCheck_REL_FILE(const char *szREL_file) { char *pszLine; FILE_TYPE *pF; @@ -5834,8 +6126,8 @@ int MMCheck_REL_FILE(char *szREL_file) pF = fopen_function(szREL_file, "r"); if (!pF) { - sprintf(local_message, "The file %s must exist.", szREL_file); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, "The file %s must exist.", + szREL_file); return 1; } fclose_function(pF); @@ -5845,12 +6137,11 @@ int MMCheck_REL_FILE(char *szREL_file) MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, nullptr); if (!pszLine) { - sprintf(local_message, - "The file \"%s\" must be REL4. " - "You can use ConvREL.exe from MiraMon software " - "to convert this file to REL4.", - szREL_file); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must be REL4. " + "You can use ConvREL.exe from MiraMon software " + "to convert this file to REL4.", + szREL_file); return 1; } free_function(pszLine); @@ -5863,18 +6154,19 @@ int MMCheck_REL_FILE(char *szREL_file) { if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS) { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", - szREL_file, KEY_Vers, MM_VERS); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must have %s>=%d.", szREL_file, + KEY_Vers, MM_VERS); + free_function(pszLine); return 1; } free_function(pszLine); } else { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", szREL_file, - KEY_Vers, MM_VERS); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must have %s>=%d.", szREL_file, KEY_Vers, + MM_VERS); return 1; } @@ -5885,18 +6177,20 @@ int MMCheck_REL_FILE(char *szREL_file) { if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS) { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", - szREL_file, KEY_SubVers, MM_SUBVERS); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must have %s>=%d.", szREL_file, + KEY_SubVers, MM_SUBVERS); + + free_function(pszLine); return 1; } free_function(pszLine); } else { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", szREL_file, - KEY_SubVers, MM_SUBVERS); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must have %s>=%d.", szREL_file, KEY_SubVers, + MM_SUBVERS); return 1; } @@ -5907,18 +6201,19 @@ int MMCheck_REL_FILE(char *szREL_file) { if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS_METADADES) { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", - szREL_file, KEY_VersMetaDades, MM_VERS_METADADES); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must have %s>=%d.", szREL_file, + KEY_VersMetaDades, MM_VERS_METADADES); + free_function(pszLine); return 1; } free_function(pszLine); } else { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", szREL_file, - KEY_VersMetaDades, MM_VERS_METADADES); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must have %s>=%d.", szREL_file, + KEY_VersMetaDades, MM_VERS_METADADES); return 1; } @@ -5929,19 +6224,19 @@ int MMCheck_REL_FILE(char *szREL_file) { if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_METADADES) { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", - szREL_file, KEY_SubVersMetaDades, MM_SUBVERS_METADADES); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must have %s>=%d.", szREL_file, + KEY_SubVersMetaDades, MM_SUBVERS_METADADES); + free_function(pszLine); return 1; } free_function(pszLine); } else { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", szREL_file, - KEY_SubVersMetaDades, MM_SUBVERS_METADADES); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "The file \"%s\" must have %s>=%d.", szREL_file, + KEY_SubVersMetaDades, MM_SUBVERS_METADADES); return 1; } return 0; @@ -5976,18 +6271,15 @@ static int MMInitMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, fopen_function(pMMAdmDB->pszExtDBFLayerName, "r+b"))) //hMiraMonLayer->pszFlags))) { - sprintf(local_message, "Error pMMAdmDB: Cannot open file %s.", - pMMAdmDB->pszExtDBFLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); + MMCPLError(CE_Failure, CPLE_OpenFailed, + "Error pMMAdmDB: Cannot open file %s.", + pMMAdmDB->pszExtDBFLayerName); return 1; } fseek_function(pMMAdmDB->pFExtDBF, pMMAdmDB->pMMBDXP->FirstRecordOffset, SEEK_SET); - if (MMInitFlush(&pMMAdmDB->FlushRecList, pMMAdmDB->pFExtDBF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, + if (MMInitFlush(&pMMAdmDB->FlushRecList, pMMAdmDB->pFExtDBF, MM_1MB, &pMMAdmDB->pRecList, pMMAdmDB->pMMBDXP->FirstRecordOffset, 0)) return 1; @@ -6013,7 +6305,8 @@ static int MMInitMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, // accordingly. Depending on the layer type (point, arc, polygon, or generic), // it defines the fields and initializes the corresponding MiraMon database // structures. -int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer) +int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, + struct MM_POINT_2D *pFirstCoord) { struct MM_DATA_BASE_XP *pBD_XP = nullptr, *pBD_XP_Aux = nullptr; struct MM_FIELD MMField; @@ -6024,6 +6317,18 @@ int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer) if (!hMiraMonLayer) return 1; + // If the SRS is unknown, we attempt to deduce the appropriate number + // of decimals to be used in the reserved fields as LONG_ARC, PERIMETRE, + // or AREA using the coordinate values. It's not 100% reliable, but it's a + // good approximation. + if (hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_UNKNOWN_TYPE && pFirstCoord) + { + if (pFirstCoord->dfX < -360 || pFirstCoord->dfX > 360) + hMiraMonLayer->nSRSType = MM_SRS_LAYER_IS_PROJECTED_TYPE; + else + hMiraMonLayer->nSRSType = MM_SRS_LAYER_IS_GEOGRAPHIC_TYPE; + } + if (hMiraMonLayer->bIsPoint) { if (hMiraMonLayer->pLayerDB) @@ -6056,7 +6361,10 @@ int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer) return 1; if (0 == (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstArcFieldsDB_XP( - pBD_XP, 0))) + pBD_XP, + hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE + ? 3 + : 9))) return 1; pBD_XP_Aux = hMiraMonLayer->MMArc.MMNode.MMAdmDB.pMMBDXP = @@ -6082,8 +6390,14 @@ int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer) if (!pBD_XP) return 1; - if (0 == (nIField = (MM_EXT_DBF_N_FIELDS) - MM_DefineFirstPolygonFieldsDB_XP(pBD_XP, 6))) + if (0 == + (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstPolygonFieldsDB_XP( + pBD_XP, + hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE ? 3 + : 9, + hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE + ? 3 + : 12))) return 1; pBD_XP_Aux = hMiraMonLayer->MMPolygon.MMArc.MMAdmDB.pMMBDXP = @@ -6092,7 +6406,11 @@ int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer) if (!pBD_XP_Aux) return 1; - if (0 == MM_DefineFirstArcFieldsDB_XP(pBD_XP_Aux, 6)) + if (0 == MM_DefineFirstArcFieldsDB_XP( + pBD_XP_Aux, + hMiraMonLayer->nSRSType == MM_SRS_LAYER_IS_PROJECTED_TYPE + ? 3 + : 9)) return 1; pBD_XP_Aux = hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB.pMMBDXP = @@ -6128,15 +6446,15 @@ int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer) for (nIFieldLayer = 0; nIField < nNFields; nIField++, nIFieldLayer++) { MM_InitializeField(&MMField); - MM_strnzcpy( + CPLStrlcpy( MMField.FieldName, hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].pszFieldName, MM_MAX_LON_FIELD_NAME_DBF); - MM_strnzcpy(MMField.FieldDescription[0], - hMiraMonLayer->pLayerDB->pFields[nIFieldLayer] - .pszFieldDescription, - MM_MAX_BYTES_FIELD_DESC); + CPLStrlcpy(MMField.FieldDescription[0], + hMiraMonLayer->pLayerDB->pFields[nIFieldLayer] + .pszFieldDescription, + MM_MAX_BYTES_FIELD_DESC); MMField.BytesPerField = hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].nFieldSize; @@ -6266,7 +6584,8 @@ MMTestAndFixValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, if ((GUInt64)pMMAdmDB->pMMBDXP->BytesPerRecord + 1 >= pMMAdmDB->nNumRecordOnCourse) { - if (nullptr == (pMMAdmDB->szRecordOnCourse = realloc_function( + void *pTmp; + if (nullptr == (pTmp = realloc_function( pMMAdmDB->szRecordOnCourse, (size_t)pMMAdmDB->pMMBDXP->BytesPerRecord + 1))) { @@ -6275,9 +6594,10 @@ MMTestAndFixValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, "driver (MMTestAndFixValueToRecordDBXP())"); return 1; } + pMMAdmDB->szRecordOnCourse = pTmp; } - // File has changed it's size, so it has to be updated + // File has changed its size, so it has to be updated // at the Flush tool fseek_function(pMMAdmDB->pFExtDBF, 0, SEEK_END); pMMAdmDB->FlushRecList.OffsetWhereToFlush = @@ -6286,9 +6606,10 @@ MMTestAndFixValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, return 0; } -int MMWriteValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, - char *registre, const struct MM_FIELD *camp, - const void *valor, MM_BOOLEAN is_64) +static int +MMWriteValueToszStringToOperate(struct MiraMonVectLayerInfo *hMiraMonLayer, + const struct MM_FIELD *camp, const void *valor, + MM_BOOLEAN is_64) { if (!hMiraMonLayer) return 1; @@ -6308,77 +6629,73 @@ int MMWriteValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, { if (!is_64) { - sprintf(hMiraMonLayer->szStringToOperate, "%*.*f", - camp->BytesPerField, camp->DecimalsIfFloat, - *(const double *)valor); + snprintf(hMiraMonLayer->szStringToOperate, + (size_t)hMiraMonLayer->nNumStringToOperate, "%*.*f", + camp->BytesPerField, camp->DecimalsIfFloat, + *(const double *)valor); } else { - sprintf(hMiraMonLayer->szStringToOperate, "%*lld", - camp->BytesPerField, *(const GInt64 *)valor); + snprintf(hMiraMonLayer->szStringToOperate, + (size_t)hMiraMonLayer->nNumStringToOperate, "%*lld", + camp->BytesPerField, *(const GInt64 *)valor); } } else { - sprintf(hMiraMonLayer->szStringToOperate, "%-*s", - camp->BytesPerField, (const char *)valor); + snprintf(hMiraMonLayer->szStringToOperate, + (size_t)hMiraMonLayer->nNumStringToOperate, "%-*s", + camp->BytesPerField, (const char *)valor); } } - memcpy(registre + camp->AcumulatedBytes, hMiraMonLayer->szStringToOperate, - camp->BytesPerField); return 0; } -// Gets the n-th value of the format (number_of_values:val1,val2,...,valN) -char *MMGetNFieldValue(const char *pszStringList, GUInt32 nIRecord) +int MMWritePreformatedNumberValueToRecordDBXP( + struct MiraMonVectLayerInfo *hMiraMonLayer, char *registre, + const struct MM_FIELD *camp, const char *valor) { - char *p, *q; - GUInt32 nNValues, nIValues; - char *pszAux; + if (!hMiraMonLayer) + return 1; - if (!pszStringList) - return nullptr; + if (!camp) + return 0; - pszAux = strdup_function(pszStringList); - p = strstr(pszAux, "("); - if (!p) - return nullptr; - p++; - if (!p) - return nullptr; - q = strstr(p, ":"); - p[(ptrdiff_t)q - (ptrdiff_t)p] = '\0'; - nNValues = atoi(p); - if (nIRecord > nNValues) - return nullptr; + if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, + camp->BytesPerField + 10)) + return 1; - q++; - nIValues = 0; - while (nIValues <= nIRecord) + if (!valor) + *hMiraMonLayer->szStringToOperate = '\0'; + else { - if (!q) - return nullptr; - p = strstr(q, ","); - if (!p) - { - p = strstr(q, ")"); - if (!p) - return nullptr; - q[(ptrdiff_t)p - (ptrdiff_t)q] = '\0'; - return q; - } - if (nIValues == nIRecord) - { - p = strstr(q, ","); - q[(ptrdiff_t)p - (ptrdiff_t)q] = '\0'; - - return q; - } - q = p + 1; + snprintf(hMiraMonLayer->szStringToOperate, + (size_t)hMiraMonLayer->nNumStringToOperate, "%*s", + camp->BytesPerField, valor); } - return q; + memcpy(registre + camp->AccumulatedBytes, hMiraMonLayer->szStringToOperate, + camp->BytesPerField); + return 0; +} + +int MMWriteValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, + char *registre, const struct MM_FIELD *camp, + const void *valor, MM_BOOLEAN is_64) +{ + if (!hMiraMonLayer) + return 1; + + if (!camp) + return 0; + + if (MMWriteValueToszStringToOperate(hMiraMonLayer, camp, valor, is_64)) + return 1; + + memcpy(registre + camp->AccumulatedBytes, hMiraMonLayer->szStringToOperate, + camp->BytesPerField); + return 0; } static int MMAddFeatureRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, @@ -6408,21 +6725,17 @@ static int MMAddFeatureRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, // A field with no valid value is written as blank if (!hMMFeature->pRecords[nIRecord].pField[nIField].bIsValid) { - MM_ACUMULATED_BYTES_TYPE_DBF i = 0; - while ( - i < - pBD_XP->pField[nIField + nNumPrivateMMField].BytesPerField) - { - memcpy(pszRecordOnCourse + - pBD_XP->pField[nIField + nNumPrivateMMField] - .AcumulatedBytes + - i, - " ", 1); - i++; - } + memset( + pszRecordOnCourse + + pBD_XP->pField[nIField + nNumPrivateMMField] + .AccumulatedBytes, + ' ', + pBD_XP->pField[nIField + nNumPrivateMMField].BytesPerField); + continue; } - if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'C') + if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'C' || + pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'D') { if (MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, pBD_XP->pField + nIField + @@ -6433,6 +6746,18 @@ static int MMAddFeatureRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, FALSE)) return 1; } + else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == + 'N' && + !pBD_XP->pField[nIField + nNumPrivateMMField].Is64) + { + if (MMWritePreformatedNumberValueToRecordDBXP( + hMiraMonLayer, pszRecordOnCourse, + pBD_XP->pField + nIField + nNumPrivateMMField, + hMMFeature->pRecords[nIRecord] + .pField[nIField] + .pDinValue)) + return 1; + } else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'N') { @@ -6447,29 +6772,6 @@ static int MMAddFeatureRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, TRUE)) return 1; } - else - { - if (MMWriteValueToRecordDBXP( - hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + nIField + nNumPrivateMMField, - &hMMFeature->pRecords[nIRecord] - .pField[nIField] - .dValue, - FALSE)) - return 1; - } - } - else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == - 'D') - { - if (MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + nIField + - nNumPrivateMMField, - hMMFeature->pRecords[nIRecord] - .pField[nIField] - .pDinValue, - FALSE)) - return 1; } } @@ -6485,40 +6787,50 @@ static int MMAddFeatureRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, static int MMDetectAndFixDBFWidthChange( struct MiraMonVectLayerInfo *hMiraMonLayer, struct MiraMonFeature *hMMFeature, struct MMAdmDatabase *pMMAdmDB, - struct MM_FLUSH_INFO *pFlushRecList, MM_EXT_DBF_N_FIELDS nNumPrivateMMField, + MM_EXT_DBF_N_FIELDS nNumPrivateMMField, MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord, MM_EXT_DBF_N_FIELDS nIField) { if (!hMiraMonLayer) return 1; if (!hMMFeature) - return 0; + return 1; if (nIRecord >= hMMFeature->nNumMRecords) - return 0; + return 1; if (nIField >= hMMFeature->pRecords[nIRecord].nNumField) - return 0; + return 1; if (MMTestAndFixValueToRecordDBXP( hMiraMonLayer, pMMAdmDB, nIField + nNumPrivateMMField, hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue)) return 1; - // We analize next fields + // We analyze next fields if (nIField == hMMFeature->pRecords[nIRecord].nNumField - 1) { - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, pMMAdmDB, - pFlushRecList, nNumPrivateMMField, - nIRecord + 1, 0)) - return 1; + if (nIRecord + 1 < hMMFeature->nNumMRecords) + { + if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, + pMMAdmDB, nNumPrivateMMField, + nIRecord + 1, 0)) + return 1; + } + else + return 0; } else { - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, pMMAdmDB, - pFlushRecList, nNumPrivateMMField, - nIRecord, nIField + 1)) - return 1; + if (nIField + 1 < hMMFeature->pRecords[nIRecord].nNumField) + { + if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, + pMMAdmDB, nNumPrivateMMField, + nIRecord, nIField + 1)) + return 1; + } + else + return 0; } return 0; } // End of MMDetectAndFixDBFWidthChange() @@ -6532,11 +6844,22 @@ int MMAddDBFRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, { struct MM_DATA_BASE_XP *pBD_XP = nullptr; MM_EXT_DBF_N_FIELDS nNumPrivateMMField = 0; - char *pszRecordOnCourse; struct MM_FLUSH_INFO *pFlushRecList; if (!hMiraMonLayer) - return 1; + return MM_FATAL_ERROR_WRITING_FEATURES; + + pBD_XP = hMiraMonLayer->MMAdmDBWriting.pMMBDXP; + + // Test length + if (hMMFeature && hMMFeature->nNumMRecords && + hMMFeature->pRecords[0].nNumField) + { + if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, + &hMiraMonLayer->MMAdmDBWriting, + nNumPrivateMMField, 0, 0)) + return MM_FATAL_ERROR_WRITING_FEATURES; + } // Adding record to the MiraMon table (extended DBF) // Flush settings @@ -6544,25 +6867,13 @@ int MMAddDBFRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, pFlushRecList->pBlockWhereToSaveOrRead = (void *)hMiraMonLayer->MMAdmDBWriting.pRecList; - pszRecordOnCourse = hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - pBD_XP = hMiraMonLayer->MMAdmDBWriting.pMMBDXP; - - // Test lenght - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, - &hMiraMonLayer->MMAdmDBWriting, - pFlushRecList, nNumPrivateMMField, 0, 0)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Reassign the point because the function can realloc it. - pszRecordOnCourse = hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - + pFlushRecList->pBlockToBeSaved = + (void *)hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse; pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; + if (MMAddFeatureRecordToMMDB( hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMAdmDBWriting, - pszRecordOnCourse, pFlushRecList, + hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse, pFlushRecList, &hMiraMonLayer->MMAdmDBWriting.pMMBDXP->nRecords, nNumPrivateMMField)) return MM_FATAL_ERROR_WRITING_FEATURES; @@ -6581,45 +6892,66 @@ int MMAddPointRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, { struct MM_DATA_BASE_XP *pBD_XP = nullptr; MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_POINT_DB_FIELDS; - char *pszRecordOnCourse; struct MM_FLUSH_INFO *pFlushRecList; if (!hMiraMonLayer) - return 1; + return MM_FATAL_ERROR_WRITING_FEATURES; + + if (!hMMFeature) + return MM_FATAL_ERROR_WRITING_FEATURES; // In V1.1 only _UI32_MAX records number is allowed if (MMCheckVersionForFID(hMiraMonLayer, hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP->nRecords + hMMFeature->nNumMRecords)) + { + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in MMCheckVersionForFID() (6)"); return MM_STOP_WRITING_FEATURES; - - // Adding record to the MiraMon table (extended DBF) - // Flush settings - pFlushRecList = &hMiraMonLayer->MMPoint.MMAdmDB.FlushRecList; - pFlushRecList->pBlockWhereToSaveOrRead = - (void *)hMiraMonLayer->MMPoint.MMAdmDB.pRecList; + } pBD_XP = hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP; - // Test lenght - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, - &hMiraMonLayer->MMPoint.MMAdmDB, - pFlushRecList, nNumPrivateMMField, 0, 0)) + // Test length + // Private fields + // ID_GRAFIC + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField, + &nElemCount, TRUE)) return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, + &hMiraMonLayer->MMPoint.MMAdmDB, 0, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // GDAL fields + if (hMMFeature->nNumMRecords && hMMFeature->pRecords[0].nNumField) + { + if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, + &hMiraMonLayer->MMPoint.MMAdmDB, + nNumPrivateMMField, 0, 0)) + return MM_FATAL_ERROR_WRITING_FEATURES; + } - // Reassign the point because the function can realloc it. - pszRecordOnCourse = hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; + // Now length is sure, write + memset(hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse, 0, + pBD_XP->BytesPerRecord); + MMWriteValueToRecordDBXP(hMiraMonLayer, + hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse, + pBD_XP->pField, &nElemCount, TRUE); - // Now lenght is sure, write - memset(pszRecordOnCourse, 0, pBD_XP->BytesPerRecord); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, pBD_XP->pField, - &nElemCount, TRUE); + // Adding record to the MiraMon table (extended DBF) + // Flush settings + pFlushRecList = &hMiraMonLayer->MMPoint.MMAdmDB.FlushRecList; + pFlushRecList->pBlockWhereToSaveOrRead = + (void *)hMiraMonLayer->MMPoint.MMAdmDB.pRecList; + pFlushRecList->pBlockToBeSaved = + (void *)hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse; pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; + if (MMAddFeatureRecordToMMDB( hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMPoint.MMAdmDB, - pszRecordOnCourse, pFlushRecList, + hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse, pFlushRecList, &hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP->nRecords, nNumPrivateMMField)) return MM_FATAL_ERROR_WRITING_FEATURES; @@ -6632,80 +6964,128 @@ int MMAddArcRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, MM_INTERNAL_FID nElemCount, struct MM_AH *pArcHeader) { struct MM_DATA_BASE_XP *pBD_XP = nullptr; - char *pszRecordOnCourse; struct MiraMonArcLayer *pMMArcLayer; MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_ARC_DB_FIELDS; struct MM_FLUSH_INFO *pFlushRecList; if (!hMiraMonLayer) - return 1; + return MM_FATAL_ERROR_WRITING_FEATURES; if (hMiraMonLayer->bIsPolygon) pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; else pMMArcLayer = &hMiraMonLayer->MMArc; - if (!pMMArcLayer) - return 1; - // In V1.1 only _UI32_MAX records number is allowed if (hMiraMonLayer->bIsPolygon) { if (MMCheckVersionForFID(hMiraMonLayer, pMMArcLayer->MMAdmDB.pMMBDXP->nRecords + 1)) + { + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in MMCheckVersionForFID() (7)"); return MM_STOP_WRITING_FEATURES; + } } else { if (MMCheckVersionForFID(hMiraMonLayer, pMMArcLayer->MMAdmDB.pMMBDXP->nRecords + hMMFeature->nNumMRecords)) + { + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in MMCheckVersionForFID() (8)"); return MM_STOP_WRITING_FEATURES; + } } - // Adding record to the MiraMon table (extended DBF) - // Flush settings - pFlushRecList = &pMMArcLayer->MMAdmDB.FlushRecList; - pFlushRecList->pBlockWhereToSaveOrRead = - (void *)pMMArcLayer->MMAdmDB.pRecList; - pBD_XP = pMMArcLayer->MMAdmDB.pMMBDXP; - pszRecordOnCourse = pMMArcLayer->MMAdmDB.szRecordOnCourse; - pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; + // Test length + // Private fields + // ID_GRAFIC + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField, + &nElemCount, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 0, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // N_VERTEXS + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 1, + &pArcHeader->nElemCount, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 1, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; - // Test lenght + // LENGTH + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 2, + &pArcHeader->dfLength, FALSE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 2, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // NODE_INI + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 3, + &pArcHeader->nFirstIdNode, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 3, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // NODE_FI + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 4, + &pArcHeader->nLastIdNode, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMArcLayer->MMAdmDB, 4, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // GDAL fields if (!hMiraMonLayer->bIsPolygon) { - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, - &pMMArcLayer->MMAdmDB, pFlushRecList, - nNumPrivateMMField, 0, 0)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Reassign the point because the function can realloc it. - pszRecordOnCourse = pMMArcLayer->MMAdmDB.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; + if (hMMFeature->nNumMRecords && hMMFeature->pRecords[0].nNumField) + { + if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, + &pMMArcLayer->MMAdmDB, + nNumPrivateMMField, 0, 0)) + return MM_FATAL_ERROR_WRITING_FEATURES; + } } - // Now lenght is sure, write - memset(pszRecordOnCourse, 0, pBD_XP->BytesPerRecord); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, pBD_XP->pField, - &nElemCount, TRUE); + // Now length is sure, write + memset(pMMArcLayer->MMAdmDB.szRecordOnCourse, 0, pBD_XP->BytesPerRecord); + MMWriteValueToRecordDBXP(hMiraMonLayer, + pMMArcLayer->MMAdmDB.szRecordOnCourse, + pBD_XP->pField, &nElemCount, TRUE); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, + MMWriteValueToRecordDBXP(hMiraMonLayer, + pMMArcLayer->MMAdmDB.szRecordOnCourse, pBD_XP->pField + 1, &pArcHeader->nElemCount, TRUE); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 2, &pArcHeader->dfLenght, FALSE); + MMWriteValueToRecordDBXP(hMiraMonLayer, + pMMArcLayer->MMAdmDB.szRecordOnCourse, + pBD_XP->pField + 2, &pArcHeader->dfLength, FALSE); + + MMWriteValueToRecordDBXP( + hMiraMonLayer, pMMArcLayer->MMAdmDB.szRecordOnCourse, + pBD_XP->pField + 3, &pArcHeader->nFirstIdNode, TRUE); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 3, &pArcHeader->nFirstIdNode, - TRUE); + MMWriteValueToRecordDBXP( + hMiraMonLayer, pMMArcLayer->MMAdmDB.szRecordOnCourse, + pBD_XP->pField + 4, &pArcHeader->nLastIdNode, TRUE); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 4, &pArcHeader->nLastIdNode, - TRUE); + // Adding record to the MiraMon table (extended DBF) + // Flush settings + pFlushRecList = &pMMArcLayer->MMAdmDB.FlushRecList; + pFlushRecList->pBlockWhereToSaveOrRead = + (void *)pMMArcLayer->MMAdmDB.pRecList; + + pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; + pFlushRecList->pBlockToBeSaved = + (void *)pMMArcLayer->MMAdmDB.szRecordOnCourse; if (hMiraMonLayer->bIsPolygon) { @@ -6717,9 +7097,9 @@ int MMAddArcRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; if (MMAddFeatureRecordToMMDB( - hMiraMonLayer, hMMFeature, &pMMArcLayer->MMAdmDB, pszRecordOnCourse, - pFlushRecList, &pMMArcLayer->MMAdmDB.pMMBDXP->nRecords, - nNumPrivateMMField)) + hMiraMonLayer, hMMFeature, &pMMArcLayer->MMAdmDB, + pMMArcLayer->MMAdmDB.szRecordOnCourse, pFlushRecList, + &pMMArcLayer->MMAdmDB.pMMBDXP->nRecords, nNumPrivateMMField)) return MM_FATAL_ERROR_WRITING_FEATURES; return MM_CONTINUE_WRITING_FEATURES; } @@ -6729,7 +7109,6 @@ int MMAddNodeRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, MM_INTERNAL_FID nElemCount, struct MM_NH *pNodeHeader) { struct MM_DATA_BASE_XP *pBD_XP = nullptr; - char *pszRecordOnCourse; struct MiraMonNodeLayer *pMMNodeLayer; double nDoubleValue; @@ -6741,10 +7120,52 @@ int MMAddNodeRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, else pMMNodeLayer = &hMiraMonLayer->MMArc.MMNode; + if (!pMMNodeLayer) + { + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in pMMNodeLayer() (1)"); + return MM_STOP_WRITING_FEATURES; + } + // In V1.1 only _UI32_MAX records number is allowed if (MMCheckVersionForFID(hMiraMonLayer, pMMNodeLayer->MMAdmDB.pMMBDXP->nRecords + 1)) + { + MMCPLError(CE_Failure, CPLE_NotSupported, + "Error in MMCheckVersionForFID() (9)"); return MM_STOP_WRITING_FEATURES; + } + + // Test length + // Private fields + // ID_GRAFIC + if (MMWriteValueToszStringToOperate(hMiraMonLayer, + pMMNodeLayer->MMAdmDB.pMMBDXP->pField, + &nElemCount, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 0, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // ARCS_A_NOD + nDoubleValue = pNodeHeader->nArcsCount; + if (MMWriteValueToszStringToOperate( + hMiraMonLayer, pMMNodeLayer->MMAdmDB.pMMBDXP->pField + 1, + &nDoubleValue, FALSE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 1, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // TIPUS_NODE + nDoubleValue = pNodeHeader->cNodeType; + if (MMWriteValueToszStringToOperate( + hMiraMonLayer, pMMNodeLayer->MMAdmDB.pMMBDXP->pField + 2, + &nDoubleValue, FALSE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, &pMMNodeLayer->MMAdmDB, 2, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; // Adding record to the MiraMon table (extended DBF) // Flush settings @@ -6752,23 +7173,25 @@ int MMAddNodeRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, (void *)pMMNodeLayer->MMAdmDB.pRecList; pBD_XP = pMMNodeLayer->MMAdmDB.pMMBDXP; - pszRecordOnCourse = pMMNodeLayer->MMAdmDB.szRecordOnCourse; pMMNodeLayer->MMAdmDB.FlushRecList.SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; pMMNodeLayer->MMAdmDB.FlushRecList.pBlockToBeSaved = - (void *)pszRecordOnCourse; + (void *)pMMNodeLayer->MMAdmDB.szRecordOnCourse; - memset(pszRecordOnCourse, 0, pBD_XP->BytesPerRecord); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, pBD_XP->pField, - &nElemCount, TRUE); + memset(pMMNodeLayer->MMAdmDB.szRecordOnCourse, 0, pBD_XP->BytesPerRecord); + MMWriteValueToRecordDBXP(hMiraMonLayer, + pMMNodeLayer->MMAdmDB.szRecordOnCourse, + pBD_XP->pField, &nElemCount, TRUE); nDoubleValue = pNodeHeader->nArcsCount; - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, + MMWriteValueToRecordDBXP(hMiraMonLayer, + pMMNodeLayer->MMAdmDB.szRecordOnCourse, pBD_XP->pField + 1, &nDoubleValue, FALSE); nDoubleValue = pNodeHeader->cNodeType; - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, + MMWriteValueToRecordDBXP(hMiraMonLayer, + pMMNodeLayer->MMAdmDB.szRecordOnCourse, pBD_XP->pField + 2, &nDoubleValue, FALSE); if (MMAppendBlockToBuffer(&pMMNodeLayer->MMAdmDB.FlushRecList)) @@ -6786,12 +7209,11 @@ int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_PH *pPolHeader) { struct MM_DATA_BASE_XP *pBD_XP = nullptr; - char *pszRecordOnCourse; MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_POLYGON_DB_FIELDS; struct MM_FLUSH_INFO *pFlushRecList; if (!hMiraMonLayer) - return 1; + return MM_FATAL_ERROR_WRITING_FEATURES; // In V1.1 only _UI32_MAX records number is allowed if (MMCheckVersionForFID( @@ -6799,32 +7221,95 @@ int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, (hMMFeature ? hMMFeature->nNumMRecords : 0))) return MM_STOP_WRITING_FEATURES; + pBD_XP = hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP; + + // Test length + // Private fields + // ID_GRAFIC + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField, + &nElemCount, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, + &hMiraMonLayer->MMPolygon.MMAdmDB, 0, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // The other fields are valid if pPolHeader exists (it is not + // the universal polygon) + if (pPolHeader) + { + // N_VERTEXS + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 1, + &nVerticesCount, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, + &hMiraMonLayer->MMPolygon.MMAdmDB, 1, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // PERIMETER + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 2, + &pPolHeader->dfPerimeter, FALSE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, + &hMiraMonLayer->MMPolygon.MMAdmDB, 2, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // AREA + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 3, + &pPolHeader->dfArea, FALSE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, + &hMiraMonLayer->MMPolygon.MMAdmDB, 3, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // N_ARCS + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 4, + &pPolHeader->nArcsCount, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, + &hMiraMonLayer->MMPolygon.MMAdmDB, 4, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + + // N_POLIG + if (MMWriteValueToszStringToOperate(hMiraMonLayer, pBD_XP->pField + 5, + &pPolHeader->nRingsCount, TRUE)) + return MM_FATAL_ERROR_WRITING_FEATURES; + if (MMTestAndFixValueToRecordDBXP(hMiraMonLayer, + &hMiraMonLayer->MMPolygon.MMAdmDB, 5, + hMiraMonLayer->szStringToOperate)) + return MM_FATAL_ERROR_WRITING_FEATURES; + } + + // GDAL fields + if (hMMFeature && hMMFeature->nNumMRecords && + hMMFeature->pRecords[0].nNumField) + { + if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, + &hMiraMonLayer->MMPolygon.MMAdmDB, + nNumPrivateMMField, 0, 0)) + return MM_FATAL_ERROR_WRITING_FEATURES; + } + // Adding record to the MiraMon table (extended DBF) // Flush settings pFlushRecList = &hMiraMonLayer->MMPolygon.MMAdmDB.FlushRecList; pFlushRecList->pBlockWhereToSaveOrRead = (void *)hMiraMonLayer->MMPolygon.MMAdmDB.pRecList; - pBD_XP = hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP; - pszRecordOnCourse = hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse; - pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - // Test lenght - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, - &hMiraMonLayer->MMPolygon.MMAdmDB, - pFlushRecList, nNumPrivateMMField, 0, 0)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Reassign the point because the function can realloc it. - pszRecordOnCourse = hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - // Now lenght is sure, write - memset(pszRecordOnCourse, 0, pBD_XP->BytesPerRecord); - if (MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField, &nElemCount, TRUE)) + pFlushRecList->pBlockToBeSaved = + (void *)hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse; + + // Now length is sure, write + memset(hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, ' ', + pBD_XP->BytesPerRecord); + if (MMWriteValueToRecordDBXP( + hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, + pBD_XP->pField, &nElemCount, TRUE)) return MM_FATAL_ERROR_WRITING_FEATURES; if (!hMMFeature) @@ -6835,27 +7320,33 @@ int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, return MM_CONTINUE_WRITING_FEATURES; } - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 1, &nVerticesCount, TRUE); + if (pPolHeader) + { + MMWriteValueToRecordDBXP( + hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, + pBD_XP->pField + 1, &nVerticesCount, TRUE); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 2, &pPolHeader->dfPerimeter, - FALSE); + MMWriteValueToRecordDBXP( + hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, + pBD_XP->pField + 2, &pPolHeader->dfPerimeter, FALSE); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 3, &pPolHeader->dfArea, FALSE); + MMWriteValueToRecordDBXP( + hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, + pBD_XP->pField + 3, &pPolHeader->dfArea, FALSE); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 4, &pPolHeader->nArcsCount, TRUE); + MMWriteValueToRecordDBXP( + hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, + pBD_XP->pField + 4, &pPolHeader->nArcsCount, TRUE); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 5, &pPolHeader->nRingsCount, - TRUE); + MMWriteValueToRecordDBXP( + hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, + pBD_XP->pField + 5, &pPolHeader->nRingsCount, TRUE); + } pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; if (MMAddFeatureRecordToMMDB( hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMPolygon.MMAdmDB, - pszRecordOnCourse, pFlushRecList, + hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse, pFlushRecList, &hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords, nNumPrivateMMField)) return MM_FATAL_ERROR_WRITING_FEATURES; @@ -6866,10 +7357,11 @@ int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, static int MMCloseMMBD_XPFile(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MMAdmDatabase *MMAdmDB) { + int ret_code = 1; if (!hMiraMonLayer) return 1; - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) + if (hMiraMonLayer->ReadOrWrite == MM_WRITING_MODE) { if (!MMAdmDB->pFExtDBF) { @@ -6879,12 +7371,12 @@ static int MMCloseMMBD_XPFile(struct MiraMonVectLayerInfo *hMiraMonLayer, { if (hMiraMonLayer->TopHeader.nElemCount <= 1) { - if (MMCreateMMDB(hMiraMonLayer)) + if (MMCreateMMDB(hMiraMonLayer, nullptr)) { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMCreateMMDB())"); - return 1; + goto end_label; } } } @@ -6892,74 +7384,73 @@ static int MMCloseMMBD_XPFile(struct MiraMonVectLayerInfo *hMiraMonLayer, { if (hMiraMonLayer->TopHeader.nElemCount == 0) { - if (MMCreateMMDB(hMiraMonLayer)) + if (MMCreateMMDB(hMiraMonLayer, nullptr)) { MMCPLError(CE_Failure, CPLE_OutOfMemory, "Memory error in MiraMon " "driver (MMCreateMMDB())"); - return 1; + goto end_label; } } } } if (MM_WriteNRecordsMMBD_XPFile(MMAdmDB)) - return 1; + goto end_label; // Flushing all to be flushed MMAdmDB->FlushRecList.SizeOfBlockToBeSaved = 0; if (MMAppendBlockToBuffer(&MMAdmDB->FlushRecList)) - return 1; + goto end_label; } + ret_code = 0; +end_label: // Closing database files - if (MMAdmDB->pFExtDBF) - { - if (fclose_function(MMAdmDB->pFExtDBF)) - return 1; - MMAdmDB->pFExtDBF = nullptr; - } + fclose_and_nullify(&MMAdmDB->pFExtDBF); - return 0; + return ret_code; } int MMCloseMMBD_XP(struct MiraMonVectLayerInfo *hMiraMonLayer) { + int ret_code = 0; if (!hMiraMonLayer) return 1; - if (hMiraMonLayer->pMMBDXP && hMiraMonLayer->pMMBDXP->pfDataBase) + if (hMiraMonLayer->pMMBDXP) { - fclose_function(hMiraMonLayer->pMMBDXP->pfDataBase); - hMiraMonLayer->pMMBDXP->pfDataBase = nullptr; + fclose_and_nullify(&hMiraMonLayer->pMMBDXP->pfDataBase); } if (hMiraMonLayer->bIsPoint) - return MMCloseMMBD_XPFile(hMiraMonLayer, - &hMiraMonLayer->MMPoint.MMAdmDB); - if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) + ret_code = + MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB); + else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) { if (MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB)) - return 1; - return MMCloseMMBD_XPFile(hMiraMonLayer, - &hMiraMonLayer->MMArc.MMNode.MMAdmDB); + ret_code = 1; + if (MMCloseMMBD_XPFile(hMiraMonLayer, + &hMiraMonLayer->MMArc.MMNode.MMAdmDB)) + ret_code = 1; } - if (hMiraMonLayer->bIsPolygon) + else if (hMiraMonLayer->bIsPolygon) { if (MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMAdmDB)) - return 1; + ret_code = 1; if (MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB)) - return 1; - return MMCloseMMBD_XPFile( - hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB); + ret_code = 1; + if (MMCloseMMBD_XPFile(hMiraMonLayer, + &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB)) + ret_code = 1; } - if (hMiraMonLayer->bIsDBF) - return MMCloseMMBD_XPFile(hMiraMonLayer, - &hMiraMonLayer->MMAdmDBWriting); + else if (hMiraMonLayer->bIsDBF) + ret_code = + MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting); - return 0; + return ret_code; } // Destroys the memory used to create a MiraMon table associated diff --git a/ogr/ogrsf_frmts/miramon/mm_wrlayr.c.bak b/ogr/ogrsf_frmts/miramon/mm_wrlayr.c.bak deleted file mode 100644 index 29d4d96d2708..000000000000 --- a/ogr/ogrsf_frmts/miramon/mm_wrlayr.c.bak +++ /dev/null @@ -1,7021 +0,0 @@ -/****************************************************************************** - * - * Project: OpenGIS Simple Features Reference Implementation - * Purpose: C API to create a MiraMon layer - * Author: Abel Pau, a.pau@creaf.uab.cat, based on the MiraMon codes, - * mainly written by Xavier Pons, Joan Maso (correctly written - * "Mas0xF3"), Abel Pau, Nuria Julia (N0xFAria Juli0xE0), - * Xavier Calaf, Lluis (Llu0xEDs) Pesquer and Alaitz Zabala, from - * CREAF and Universitat Autonoma (Aut0xF2noma) de Barcelona. - * For a complete list of contributors: - * https://www.miramon.cat/eng/QuiSom.htm - ****************************************************************************** - * Copyright (c) 2024, Xavier Pons - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - ****************************************************************************/ - -#ifdef GDAL_COMPILATION -#include "mm_wrlayr.h" -#include "mm_gdal_functions.h" -#include "mm_gdal_constants.h" -#include "mm_rdlayr.h" // For MM_ReadExtendedDBFHeader() -#include "gdal.h" // For GDALDatasetH -#include "ogr_srs_api.h" // For OSRGetAuthorityCode -#else -#include "CmptCmp.h" // Compatibility between compilers -#include "PrjMMVGl.h" // For a DirectoriPrograma -#include "mm_gdal\mm_wrlayr.h" // For fseek_function() -#include "mm_gdal\mm_gdal_functions.h" // For MM_strnzcpy() -#include "mm_gdal\mm_rdlayr.h" // For MM_ReadExtendedDBFHeader() -#include "msg.h" // For ErrorMsg() -#endif - -#include "cpl_string.h" // For CPL_ENC_UTF8 - -static char local_message[MAX_LOCAL_MESSAGE]; - -#ifdef GDAL_COMPILATION -CPL_C_START // Necessary for compiling in GDAL project -#endif // GDAL_COMPILATION - - /* -------------------------------------------------------------------- */ - /* Header Functions */ - /* -------------------------------------------------------------------- */ - int - MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo); -void MMInitBoundingBox(struct MMBoundingBox *dfBB); -int MMWriteAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET DiskOffset); -int MMWriteNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET DiskOffset); -int MMWritePHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET DiskOffset); -int MMAppendIntegerDependingOnVersion( - struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo, - uint32_t *nUL32, GUInt64 nUI64); -int MMMoveFromFileToFile(FILE_TYPE *pSrcFile, FILE_TYPE *pDestFile, - MM_FILE_OFFSET *nOffset); -int MMResizeZSectionDescrPointer(struct MM_ZD **pZDescription, GUInt64 *nMax, - GUInt64 nNum, GUInt64 nIncr, - GUInt64 nProposedMax); -int MMResizeArcHeaderPointer(struct MM_AH **pArcHeader, GUInt64 *nMax, - GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax); -int MMResizeNodeHeaderPointer(struct MM_NH **pNodeHeader, GUInt64 *nMax, - GUInt64 nNum, GUInt64 nIncr, - GUInt64 nProposedMax); -int MMResizePolHeaderPointer(struct MM_PH **pPolHeader, GUInt64 *nMax, - GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax); -void MMUpdateBoundingBoxXY(struct MMBoundingBox *dfBB, - struct MM_POINT_2D *pCoord); -void MMUpdateBoundingBox(struct MMBoundingBox *dfBBToBeAct, - struct MMBoundingBox *dfBBWithData); -int MMCheckVersionFor3DOffset(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET nOffset, - MM_INTERNAL_FID nElemCount); -int MMCheckVersionOffset(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET OffsetToCheck); -int MMCheckVersionForFID(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_INTERNAL_FID FID); - -// Extended DBF functions -int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer); -int MMAddDBFRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature); -int MMAddPointRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature, - MM_INTERNAL_FID nElemCount); -int MMAddArcRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature, - MM_INTERNAL_FID nElemCount, struct MM_AH *pArcHeader); -int MMAddNodeRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_INTERNAL_FID nElemCount, - struct MM_NH *pNodeHeader); -int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature, - MM_INTERNAL_FID nElemCount, - MM_N_VERTICES_TYPE nVerticesCount, - struct MM_PH *pPolHeader); -int MMCloseMMBD_XP(struct MiraMonVectLayerInfo *hMiraMonLayer); -void MMDestroyMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer); - -/* -------------------------------------------------------------------- */ -/* Managing errors and warnings */ -/* -------------------------------------------------------------------- */ - -void MMCPLError(int level, int code, const char *message) -{ -#ifdef GDAL_COMPILATION - CPLError(level, code, "%s", message); -#else - sprintf(local_message, "level(%d), code(%d)", level, code); - InfoMsg(local_message); - ErrorMsg(message); -#endif -} - -void MMCPLWarning(int level, int code, const char *message) -{ -#ifdef GDAL_COMPILATION - CPLError(level, code, "%s", message); -#else - sprintf(local_message, "level(%d), code(%d)", level, code); - InfoMsg(local_message); - InfoMsg(message); -#endif -} - -void MMCPLDebug(const char *c, const char *message) -{ -#ifdef GDAL_COMPILATION - CPLDebug(c, "%s", message); -#else - sprintf(local_message, "Code(%s)\n", c); - printf(local_message); /*ok*/ - printf(message); /*ok*/ - printf("\n"); /*ok*/ -#endif -} - -#ifndef GDAL_COMPILATION -int snprintf(char *str, size_t size, const char *format, ...) -{ - int result; - va_list args; - - va_start(args, format); - result = vsnprintf(str, size, format, args); - va_end(args); - - return result; -} -#endif - -// Checks for potential arithmetic overflow when performing multiplication -// operations between two GUInt64 values and converting the result to size_t. -// Important for 32 vs. 64 bit compiling compatibility. -int MMCheckSize_t(GUInt64 nCount, GUInt64 nSize) -{ - size_t nMul; - if ((size_t)nCount != nCount) - return 1; - - if ((size_t)nSize != nSize) - return 1; - - nMul = (size_t)(nCount * nSize); - if (nCount != 0 && nMul / nCount != nSize) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, "Overflow in MMCheckSize_t()"); - return 1; - } - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Layer Functions: Version */ -/* -------------------------------------------------------------------- */ -int MMGetVectorVersion(struct MM_TH *pTopHeader) -{ - if ((pTopHeader->aLayerVersion[0] == ' ' || - pTopHeader->aLayerVersion[0] == '0') && - pTopHeader->aLayerVersion[1] == '1' && - pTopHeader->aLayerSubVersion == '1') - return MM_32BITS_VERSION; - - if ((pTopHeader->aLayerVersion[0] == ' ' || - pTopHeader->aLayerVersion[0] == '0') && - pTopHeader->aLayerVersion[1] == '2' && - pTopHeader->aLayerSubVersion == '0') - return MM_64BITS_VERSION; - - return MM_UNKNOWN_VERSION; -} - -static void MMSet1_1Version(struct MM_TH *pTopHeader) -{ - pTopHeader->aLayerVersion[0] = ' '; - pTopHeader->aLayerVersion[1] = '1'; - pTopHeader->aLayerSubVersion = '1'; -} - -static void MMSet2_0Version(struct MM_TH *pTopHeader) -{ - pTopHeader->aLayerVersion[0] = ' '; - pTopHeader->aLayerVersion[1] = '2'; - pTopHeader->aLayerSubVersion = '0'; -} - -/* -------------------------------------------------------------------- */ -/* Layer Functions: Header */ -/* -------------------------------------------------------------------- */ -int MMReadHeader(FILE_TYPE *pF, struct MM_TH *pMMHeader) -{ - char dot; - uint32_t NCount; - int32_t reservat4 = 0L; - - pMMHeader->Flag = 0x0; - if (fseek_function(pF, 0, SEEK_SET)) - return 1; - if (fread_function(pMMHeader->aFileType, 1, 3, pF) != 3) - return 1; - if (fread_function(pMMHeader->aLayerVersion, 1, 2, pF) != 2) - return 1; - if (fread_function(&dot, 1, 1, pF) != 1) - return 1; - if (fread_function(&pMMHeader->aLayerSubVersion, 1, 1, pF) != 1) - return 1; - if (fread_function(&pMMHeader->Flag, sizeof(pMMHeader->Flag), 1, pF) != 1) - return 1; - if (fread_function(&pMMHeader->hBB.dfMinX, sizeof(pMMHeader->hBB.dfMinX), 1, - pF) != 1) - return 1; - if (fread_function(&pMMHeader->hBB.dfMaxX, sizeof(pMMHeader->hBB.dfMaxX), 1, - pF) != 1) - return 1; - if (fread_function(&pMMHeader->hBB.dfMinY, sizeof(pMMHeader->hBB.dfMinY), 1, - pF) != 1) - return 1; - if (fread_function(&pMMHeader->hBB.dfMaxY, sizeof(pMMHeader->hBB.dfMaxY), 1, - pF) != 1) - return 1; - if (pMMHeader->aLayerVersion[0] == ' ' && - pMMHeader->aLayerVersion[1] == '1') - { - if (fread_function(&NCount, sizeof(NCount), 1, pF) != 1) - return 1; - - pMMHeader->nElemCount = (MM_INTERNAL_FID)NCount; - - if (fread_function(&reservat4, 4, 1, pF) != 1) - return 1; - } - else if (pMMHeader->aLayerVersion[0] == ' ' && - pMMHeader->aLayerVersion[1] == '2') - { - if (fread_function(&(pMMHeader->nElemCount), - sizeof(pMMHeader->nElemCount), 1, pF) != 1) - return 1; - - if (fread_function(&reservat4, 4, 1, pF) != 1) - return 1; - if (fread_function(&reservat4, 4, 1, pF) != 1) - return 1; - } - - if (pMMHeader->Flag & MM_LAYER_3D_INFO) - pMMHeader->bIs3d = 1; - - if (pMMHeader->Flag & MM_LAYER_MULTIPOLYGON) - pMMHeader->bIsMultipolygon = 1; - - return 0; -} - -static int MMWriteHeader(FILE_TYPE *pF, struct MM_TH *pMMHeader) -{ - char dot = '.'; - uint32_t NCount; - int32_t reservat4 = 0L; - MM_INTERNAL_FID nNumber1 = 1, nNumber0 = 0; - - if (!pF) - return 0; - - pMMHeader->Flag = MM_CREATED_USING_MIRAMON; // Created from MiraMon - if (pMMHeader->bIs3d) - pMMHeader->Flag |= MM_LAYER_3D_INFO; // 3D - - if (pMMHeader->bIsMultipolygon) - pMMHeader->Flag |= MM_LAYER_MULTIPOLYGON; // Multipolygon. - - if (pMMHeader->aFileType[0] == 'P' && pMMHeader->aFileType[1] == 'O' && - pMMHeader->aFileType[2] == 'L') - pMMHeader->Flag |= MM_BIT_5_ON; // Explicital polygons - - if (fseek_function(pF, 0, SEEK_SET)) - return 1; - if (fwrite_function(pMMHeader->aFileType, 1, 3, pF) != 3) - return 1; - if (fwrite_function(pMMHeader->aLayerVersion, 1, 2, pF) != 2) - return 1; - if (fwrite_function(&dot, 1, 1, pF) != 1) - return 1; - if (fwrite_function(&pMMHeader->aLayerSubVersion, 1, 1, pF) != 1) - return 1; - if (fwrite_function(&pMMHeader->Flag, sizeof(pMMHeader->Flag), 1, pF) != 1) - return 1; - if (fwrite_function(&pMMHeader->hBB.dfMinX, sizeof(pMMHeader->hBB.dfMinX), - 1, pF) != 1) - return 1; - if (fwrite_function(&pMMHeader->hBB.dfMaxX, sizeof(pMMHeader->hBB.dfMaxX), - 1, pF) != 1) - return 1; - if (fwrite_function(&pMMHeader->hBB.dfMinY, sizeof(pMMHeader->hBB.dfMinY), - 1, pF) != 1) - return 1; - if (fwrite_function(&pMMHeader->hBB.dfMaxY, sizeof(pMMHeader->hBB.dfMaxY), - 1, pF) != 1) - return 1; - if (pMMHeader->aLayerVersion[0] == ' ' && - pMMHeader->aLayerVersion[1] == '1') - { - NCount = (uint32_t)pMMHeader->nElemCount; - if (fwrite_function(&NCount, sizeof(NCount), 1, pF) != 1) - return 1; - - if (fwrite_function(&reservat4, 4, 1, pF) != 1) - return 1; - } - else if (pMMHeader->aLayerVersion[0] == ' ' && - pMMHeader->aLayerVersion[1] == '2') - { - if (fwrite_function(&(pMMHeader->nElemCount), - sizeof(pMMHeader->nElemCount), 1, pF) != 1) - return 1; - - // Next part of the file (don't apply for the moment) - if (fwrite_function(&nNumber1, sizeof(nNumber1), 1, pF) != 1) - return 1; - if (fwrite_function(&nNumber0, sizeof(nNumber0), 1, pF) != 1) - return 1; - - // Reserved bytes - if (fwrite_function(&reservat4, 4, 1, pF) != 1) - return 1; - if (fwrite_function(&reservat4, 4, 1, pF) != 1) - return 1; - } - return 0; -} - -void MMInitHeader(struct MM_TH *pMMHeader, int layerType, int nVersion) -{ - memset(pMMHeader, 0, sizeof(*pMMHeader)); - switch (nVersion) - { - case MM_32BITS_VERSION: - pMMHeader->aLayerVersion[0] = '0'; - pMMHeader->aLayerVersion[1] = '1'; - pMMHeader->aLayerSubVersion = '1'; - break; - case MM_64BITS_VERSION: - case MM_LAST_VERSION: - default: - pMMHeader->aLayerVersion[0] = '0'; - pMMHeader->aLayerVersion[1] = '2'; - pMMHeader->aLayerSubVersion = '0'; - break; - } - switch (layerType) - { - case MM_LayerType_Point: - pMMHeader->aFileType[0] = 'P'; - pMMHeader->aFileType[1] = 'N'; - pMMHeader->aFileType[2] = 'T'; - break; - case MM_LayerType_Point3d: - pMMHeader->aFileType[0] = 'P'; - pMMHeader->aFileType[1] = 'N'; - pMMHeader->aFileType[2] = 'T'; - pMMHeader->bIs3d = 1; - break; - case MM_LayerType_Arc: - pMMHeader->aFileType[0] = 'A'; - pMMHeader->aFileType[1] = 'R'; - pMMHeader->aFileType[2] = 'C'; - break; - case MM_LayerType_Arc3d: - pMMHeader->aFileType[0] = 'A'; - pMMHeader->aFileType[1] = 'R'; - pMMHeader->aFileType[2] = 'C'; - pMMHeader->bIs3d = 1; - break; - case MM_LayerType_Pol: - pMMHeader->aFileType[0] = 'P'; - pMMHeader->aFileType[1] = 'O'; - pMMHeader->aFileType[2] = 'L'; - break; - case MM_LayerType_Pol3d: - pMMHeader->aFileType[0] = 'P'; - pMMHeader->aFileType[1] = 'O'; - pMMHeader->aFileType[2] = 'L'; - pMMHeader->bIs3d = 1; - break; - default: - break; - } - pMMHeader->nElemCount = 0; - pMMHeader->hBB.dfMinX = MM_UNDEFINED_STATISTICAL_VALUE; - pMMHeader->hBB.dfMaxX = -MM_UNDEFINED_STATISTICAL_VALUE; - pMMHeader->hBB.dfMinY = MM_UNDEFINED_STATISTICAL_VALUE; - pMMHeader->hBB.dfMaxY = -MM_UNDEFINED_STATISTICAL_VALUE; - - pMMHeader->Flag = MM_CREATED_USING_MIRAMON; // Created from MiraMon - if (pMMHeader->bIs3d) - pMMHeader->Flag |= MM_LAYER_3D_INFO; // 3D - - if (pMMHeader->bIsMultipolygon) - pMMHeader->Flag |= MM_LAYER_MULTIPOLYGON; // Multipolygon. - - if (pMMHeader->aFileType[0] == 'P' && pMMHeader->aFileType[1] == 'O' && - pMMHeader->aFileType[2] == 'L') - pMMHeader->Flag |= MM_BIT_5_ON; // Explicital polygons -} - -int MMWriteEmptyHeader(FILE_TYPE *pF, int layerType, int nVersion) -{ - struct MM_TH pMMHeader; - - memset(&pMMHeader, 0, sizeof(pMMHeader)); - switch (nVersion) - { - case MM_32BITS_VERSION: - pMMHeader.aLayerVersion[0] = '0'; - pMMHeader.aLayerVersion[1] = '1'; - pMMHeader.aLayerSubVersion = '1'; - break; - case MM_64BITS_VERSION: - case MM_LAST_VERSION: - default: - pMMHeader.aLayerVersion[0] = '0'; - pMMHeader.aLayerVersion[1] = '2'; - pMMHeader.aLayerSubVersion = '0'; - break; - } - switch (layerType) - { - case MM_LayerType_Point: - pMMHeader.aFileType[0] = 'P'; - pMMHeader.aFileType[1] = 'N'; - pMMHeader.aFileType[2] = 'T'; - break; - case MM_LayerType_Point3d: - pMMHeader.aFileType[0] = 'P'; - pMMHeader.aFileType[1] = 'N'; - pMMHeader.aFileType[2] = 'T'; - pMMHeader.bIs3d = 1; - break; - case MM_LayerType_Arc: - pMMHeader.aFileType[0] = 'A'; - pMMHeader.aFileType[1] = 'R'; - pMMHeader.aFileType[2] = 'C'; - break; - case MM_LayerType_Arc3d: - pMMHeader.aFileType[0] = 'A'; - pMMHeader.aFileType[1] = 'R'; - pMMHeader.aFileType[2] = 'C'; - pMMHeader.bIs3d = 1; - break; - case MM_LayerType_Pol: - pMMHeader.aFileType[0] = 'P'; - pMMHeader.aFileType[1] = 'O'; - pMMHeader.aFileType[2] = 'L'; - break; - case MM_LayerType_Pol3d: - pMMHeader.aFileType[0] = 'P'; - pMMHeader.aFileType[1] = 'O'; - pMMHeader.aFileType[2] = 'L'; - pMMHeader.bIs3d = 1; - break; - default: - break; - } - pMMHeader.nElemCount = 0; - pMMHeader.hBB.dfMinX = MM_UNDEFINED_STATISTICAL_VALUE; - pMMHeader.hBB.dfMaxX = -MM_UNDEFINED_STATISTICAL_VALUE; - pMMHeader.hBB.dfMinY = MM_UNDEFINED_STATISTICAL_VALUE; - pMMHeader.hBB.dfMaxY = -MM_UNDEFINED_STATISTICAL_VALUE; - - return MMWriteHeader(pF, &pMMHeader); -} - -/* -------------------------------------------------------------------- */ -/* Layer Functions: Z section */ -/* -------------------------------------------------------------------- */ -int MMReadZSection(struct MiraMonVectLayerInfo *hMiraMonLayer, FILE_TYPE *pF, - struct MM_ZSection *pZSection) -{ - int32_t reservat4 = 0L; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPoint) - { - pZSection->ZSectionOffset = - hMiraMonLayer->nHeaderDiskSize + - hMiraMonLayer->TopHeader.nElemCount * MM_SIZE_OF_TL; - } - else if (hMiraMonLayer->bIsArc && !(hMiraMonLayer->bIsPolygon) && - hMiraMonLayer->TopHeader.nElemCount > 0) - { - // Z section begins just after last coordinate of the last arc - pZSection->ZSectionOffset = - hMiraMonLayer->MMArc - .pArcHeader[hMiraMonLayer->TopHeader.nElemCount - 1] - .nOffset + - hMiraMonLayer->MMArc - .pArcHeader[hMiraMonLayer->TopHeader.nElemCount - 1] - .nElemCount * - MM_SIZE_OF_COORDINATE; - } - else if (hMiraMonLayer->bIsPolygon) - { - // Z section begins just after last coordinate of the last arc - pZSection->ZSectionOffset = - hMiraMonLayer->MMPolygon.MMArc - .pArcHeader[hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount - - 1] - .nOffset + - hMiraMonLayer->MMPolygon.MMArc - .pArcHeader - [hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount - 1] - .nElemCount * - MM_SIZE_OF_COORDINATE; - } - else - return 1; - - if (pF) - { - if (fseek_function(pF, pZSection->ZSectionOffset, SEEK_SET)) - return 1; - - if (fread_function(&reservat4, 4, 1, pF) != 1) - return 1; - pZSection->ZSectionOffset += 4; - if (fread_function(&reservat4, 4, 1, pF) != 1) - return 1; - pZSection->ZSectionOffset += 4; - if (fread_function(&reservat4, 4, 1, pF) != 1) - return 1; - pZSection->ZSectionOffset += 4; - if (fread_function(&reservat4, 4, 1, pF) != 1) - return 1; - pZSection->ZSectionOffset += 4; - - if (fread_function(&pZSection->ZHeader.dfBBminz, - sizeof(pZSection->ZHeader.dfBBminz), 1, pF) != 1) - return 1; - pZSection->ZSectionOffset += sizeof(pZSection->ZHeader.dfBBminz); - - if (fread_function(&pZSection->ZHeader.dfBBmaxz, - sizeof(pZSection->ZHeader.dfBBmaxz), 1, pF) != 1) - return 1; - pZSection->ZSectionOffset += sizeof(pZSection->ZHeader.dfBBmaxz); - } - return 0; -} - -static int MMWriteZSection(FILE_TYPE *pF, struct MM_ZSection *pZSection) -{ - int32_t reservat4 = 0L; - - if (fseek_function(pF, pZSection->ZSectionOffset, SEEK_SET)) - return 1; - - if (fwrite_function(&reservat4, 4, 1, pF) != 1) - return 1; - if (fwrite_function(&reservat4, 4, 1, pF) != 1) - return 1; - if (fwrite_function(&reservat4, 4, 1, pF) != 1) - return 1; - if (fwrite_function(&reservat4, 4, 1, pF) != 1) - return 1; - - pZSection->ZSectionOffset += 16; - - if (fwrite_function(&pZSection->ZHeader.dfBBminz, - sizeof(pZSection->ZHeader.dfBBminz), 1, pF) != 1) - return 1; - pZSection->ZSectionOffset += sizeof(pZSection->ZHeader.dfBBminz); - if (fwrite_function(&pZSection->ZHeader.dfBBmaxz, - sizeof(pZSection->ZHeader.dfBBmaxz), 1, pF) != 1) - return 1; - pZSection->ZSectionOffset += sizeof(pZSection->ZHeader.dfBBmaxz); - return 0; -} - -int MMReadZDescriptionHeaders(struct MiraMonVectLayerInfo *hMiraMonLayer, - FILE_TYPE *pF, MM_INTERNAL_FID nElements, - struct MM_ZSection *pZSection) -{ - struct MM_FLUSH_INFO FlushTMP; - char *pBuffer = nullptr; - MM_INTERNAL_FID nIndex = 0; - MM_FILE_OFFSET nBlockSize; - struct MM_ZD *pZDescription; - - if (!hMiraMonLayer) - return 1; - - if (!pZSection) - return 1; - - if (!nElements) - return 0; // No elements to read - - pZDescription = pZSection->pZDescription; - - nBlockSize = nElements * pZSection->nZDDiskSize; - - if (MMInitFlush(&FlushTMP, pF, nBlockSize, &pBuffer, - pZSection->ZSectionOffset, 0)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer; - if (MMReadFlush(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - for (nIndex = 0; nIndex < nElements; nIndex++) - { - FlushTMP.SizeOfBlockToBeSaved = - sizeof((pZDescription + nIndex)->dfBBminz); - FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->dfBBminz; - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.SizeOfBlockToBeSaved = - sizeof((pZDescription + nIndex)->dfBBmaxz); - FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->dfBBmaxz; - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.SizeOfBlockToBeSaved = - sizeof((pZDescription + nIndex)->nZCount); - FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->nZCount; - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - if (hMiraMonLayer->LayerVersion == MM_64BITS_VERSION) - { - FlushTMP.SizeOfBlockToBeSaved = 4; - FlushTMP.pBlockToBeSaved = (void *)nullptr; - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - - if (MMReadOffsetDependingOnVersion(hMiraMonLayer, &FlushTMP, - &(pZDescription + nIndex)->nOffsetZ)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - if (pBuffer) - free_function(pBuffer); - - return 0; -} - -static int -MMWriteZDescriptionHeaders(struct MiraMonVectLayerInfo *hMiraMonLayer, - FILE_TYPE *pF, MM_INTERNAL_FID nElements, - struct MM_ZSection *pZSection) -{ - struct MM_FLUSH_INFO FlushTMP; - char *pBuffer = nullptr; - uint32_t nUL32; - MM_INTERNAL_FID nIndex = 0; - MM_FILE_OFFSET nOffsetDiff; - struct MM_ZD *pZDescription; - - if (!hMiraMonLayer) - return 1; - - if (!pF) - return 1; - - if (!pZSection) - return 1; - - pZDescription = pZSection->pZDescription; - - nOffsetDiff = - pZSection->ZSectionOffset + - nElements * - (sizeof(pZDescription->dfBBminz) + sizeof(pZDescription->dfBBmaxz) + - sizeof(pZDescription->nZCount) + - ((hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - ? sizeof(nUL32) - : sizeof(pZDescription->nOffsetZ))); - - if (MMInitFlush(&FlushTMP, pF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pBuffer, pZSection->ZSectionOffset, 0)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer; - for (nIndex = 0; nIndex < nElements; nIndex++) - { - FlushTMP.SizeOfBlockToBeSaved = - sizeof((pZDescription + nIndex)->dfBBminz); - FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->dfBBminz; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.SizeOfBlockToBeSaved = - sizeof((pZDescription + nIndex)->dfBBmaxz); - FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->dfBBmaxz; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.SizeOfBlockToBeSaved = - sizeof((pZDescription + nIndex)->nZCount); - FlushTMP.pBlockToBeSaved = (void *)&(pZDescription + nIndex)->nZCount; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - if (hMiraMonLayer->LayerVersion == MM_64BITS_VERSION) - { - FlushTMP.SizeOfBlockToBeSaved = 4; - FlushTMP.pBlockToBeSaved = (void *)nullptr; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - (pZDescription + nIndex)->nOffsetZ + nOffsetDiff)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - FlushTMP.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - pZSection->ZSectionOffset += FlushTMP.TotalSavedBytes; - - if (pBuffer) - free_function(pBuffer); - - return 0; -} - -static void MMDestroyZSectionDescription(struct MM_ZSection *pZSection) -{ - if (pZSection->pZL) - { - free_function(pZSection->pZL); - pZSection->pZL = nullptr; - } - - if (pZSection->pZDescription) - { - free_function(pZSection->pZDescription); - pZSection->pZDescription = nullptr; - } -} - -static int MMInitZSectionDescription(struct MM_ZSection *pZSection) -{ - if (MMCheckSize_t( - pZSection->nMaxZDescription * sizeof(*pZSection->pZDescription), 1)) - return 1; - - if (!pZSection->nMaxZDescription) - { - pZSection->pZDescription = nullptr; - return 0; // No elements to read (or write) - } - - pZSection->pZDescription = - (struct MM_ZD *)calloc_function((size_t)pZSection->nMaxZDescription * - sizeof(*pZSection->pZDescription)); - if (!pZSection->pZDescription) - return 1; - return 0; -} - -static int MMInitZSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, - FILE_TYPE *pF3d, struct MM_ZSection *pZSection) -{ - if (!hMiraMonLayer) - return 1; - - // Zsection - if (!hMiraMonLayer->TopHeader.bIs3d) - { - pZSection->pZDescription = nullptr; - return 0; - } - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - pZSection->ZHeader.dfBBminz = STATISTICAL_UNDEF_VALUE; - pZSection->ZHeader.dfBBmaxz = -STATISTICAL_UNDEF_VALUE; - } - - // ZH - pZSection->ZHeader.nMyDiskSize = 32; - pZSection->ZSectionOffset = 0; - - // ZD - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - pZSection->nMaxZDescription = - MM_FIRST_NUMBER_OF_VERTICES * sizeof(double); - if (MMInitZSectionDescription(pZSection)) - return 1; - } - else - { - pZSection->nMaxZDescription = - hMiraMonLayer->TopHeader.nElemCount * sizeof(double); - if (MMInitZSectionDescription(pZSection)) - return 1; - } - - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - pZSection->nZDDiskSize = MM_SIZE_OF_ZD_32_BITS; - else - pZSection->nZDDiskSize = MM_SIZE_OF_ZD_64_BITS; - - pZSection->ZDOffset = 0; - - // ZL - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - if (MMInitFlush(&pZSection->FlushZL, pF3d, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pZSection->pZL, 0, sizeof(double))) - return 1; - } - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Layer Functions: Extensions */ -/* -------------------------------------------------------------------- */ - -/* Find the last ocurrence of pszFinalPart in pszName - and changes it by pszNewPart. - - Examples of desired behaviour - AA.pnt -> AAT.rel - AA.nod -> N.~idx - AA.nod -> N.dbf - AA.nod -> N.rel -*/ - -static int MMChangeFinalPartOfTheName(char *pszName, size_t nMaxSizeOfName, - const char *pszFinalPart, - const char *pszNewPart) -{ - char *pAux, *pszWhereToFind, *pszLastFound = nullptr; - ; - - if (!pszName || !pszFinalPart || !pszNewPart) - return 0; - if (MMIsEmptyString(pszName) || MMIsEmptyString(pszFinalPart) || - MMIsEmptyString(pszNewPart)) - return 0; - - if (strlen(pszName) - strlen(pszFinalPart) + strlen(pszNewPart) >= - nMaxSizeOfName) - return 1; // It's not possible to change the final part - - pszWhereToFind = pszName; - while (nullptr != (pAux = strstr(pszWhereToFind, pszFinalPart))) - { - pszLastFound = pAux; - pszWhereToFind = pAux + strlen(pAux); - } - - if (!pszLastFound) - return 1; // Not found not changed - - memcpy(pszLastFound, pszNewPart, strlen(pszNewPart)); - - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Layer Functions: initializing MiraMon layers */ -/* -------------------------------------------------------------------- */ -static int MMInitPointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - if (!hMiraMonLayer) - return 1; - - hMiraMonLayer->bIsPoint = 1; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - // Geometrical part - // Init header structure - hMiraMonLayer->TopHeader.nElemCount = 0; - MMInitBoundingBox(&hMiraMonLayer->TopHeader.hBB); - - hMiraMonLayer->TopHeader.bIs3d = 1; // Read description of bRealIs3d - hMiraMonLayer->TopHeader.aFileType[0] = 'P'; - hMiraMonLayer->TopHeader.aFileType[1] = 'N'; - hMiraMonLayer->TopHeader.aFileType[2] = 'T'; - - // Opening the binary file where sections TH, TL[...] and ZH-ZD[...]-ZL[...] - // are going to be written. - - strcpy(hMiraMonLayer->MMPoint.pszLayerName, - hMiraMonLayer->pszSrcLayerName); - strcat(hMiraMonLayer->MMPoint.pszLayerName, ".pnt"); - } - if (nullptr == (hMiraMonLayer->MMPoint.pF = - fopen_function(hMiraMonLayer->MMPoint.pszLayerName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, "Error MMPoint.pF: Cannot open file %s.", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(hMiraMonLayer->MMPoint.pF, 0, SEEK_SET); - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - // TL - strcpy(hMiraMonLayer->MMPoint.pszTLName, - hMiraMonLayer->pszSrcLayerName); - strcat(hMiraMonLayer->MMPoint.pszTLName, "T.~xy"); - - if (nullptr == (hMiraMonLayer->MMPoint.pFTL = - fopen_function(hMiraMonLayer->MMPoint.pszTLName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, "Error MMPoint.pFTL: Cannot open file %s.", - hMiraMonLayer->MMPoint.pszTLName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(hMiraMonLayer->MMPoint.pFTL, 0, SEEK_SET); - - if (MMInitFlush(&hMiraMonLayer->MMPoint.FlushTL, - hMiraMonLayer->MMPoint.pFTL, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &hMiraMonLayer->MMPoint.pTL, 0, MM_SIZE_OF_TL)) - return 1; - - // 3D part - if (hMiraMonLayer->TopHeader.bIs3d) - { - strcpy(hMiraMonLayer->MMPoint.psz3DLayerName, - hMiraMonLayer->pszSrcLayerName); - strcat(hMiraMonLayer->MMPoint.psz3DLayerName, "T.~z"); - - if (nullptr == (hMiraMonLayer->MMPoint.pF3d = fopen_function( - hMiraMonLayer->MMPoint.psz3DLayerName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, - "Error MMPoint.pF3d: Cannot open file %s.", - hMiraMonLayer->MMPoint.psz3DLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(hMiraMonLayer->MMPoint.pF3d, 0, SEEK_SET); - } - } - // Zsection - if (hMiraMonLayer->TopHeader.bIs3d) - { - if (MMInitZSectionLayer(hMiraMonLayer, hMiraMonLayer->MMPoint.pF3d, - &hMiraMonLayer->MMPoint.pZSection)) - return 1; - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - if (MMReadZSection(hMiraMonLayer, hMiraMonLayer->MMPoint.pF, - &hMiraMonLayer->MMPoint.pZSection)) - return 1; - - if (MMReadZDescriptionHeaders(hMiraMonLayer, - hMiraMonLayer->MMPoint.pF, - hMiraMonLayer->TopHeader.nElemCount, - &hMiraMonLayer->MMPoint.pZSection)) - return 1; - } - } - - // MiraMon metadata - strcpy(hMiraMonLayer->MMPoint.pszREL_LayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(hMiraMonLayer->MMPoint.pszREL_LayerName, "T.rel"); - else - { - if (MMChangeFinalPartOfTheName(hMiraMonLayer->MMPoint.pszREL_LayerName, - MM_CPL_PATH_BUF_SIZE, ".pnt", "T.rel")) - return 1; - } - - hMiraMonLayer->pszMainREL_LayerName = - hMiraMonLayer->MMPoint.pszREL_LayerName; - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - // This file has to exist and be the appropriate version. - if (MMCheck_REL_FILE(hMiraMonLayer->MMPoint.pszREL_LayerName)) - return 1; - } - - // MIRAMON DATA BASE - // Creating the DBF file name - strcpy(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName, "T.dbf"); - else - { - if (MMChangeFinalPartOfTheName( - hMiraMonLayer->MMPoint.MMAdmDB.pszExtDBFLayerName, - MM_CPL_PATH_BUF_SIZE, ".pnt", "T.dbf")) - return 1; - } - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - if (MM_ReadExtendedDBFHeader(hMiraMonLayer)) - return 1; - } - - return 0; -} - -static int MMInitNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonArcLayer *pMMArcLayer; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - else - pMMArcLayer = &hMiraMonLayer->MMArc; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - // Init header structure - pMMArcLayer->TopNodeHeader.aFileType[0] = 'N'; - pMMArcLayer->TopNodeHeader.aFileType[1] = 'O'; - pMMArcLayer->TopNodeHeader.aFileType[2] = 'D'; - - pMMArcLayer->TopNodeHeader.bIs3d = 1; // Read description of bRealIs3d - MMInitBoundingBox(&pMMArcLayer->TopNodeHeader.hBB); - } - - // Opening the binary file where sections TH, NH and NL[...] - // are going to be written. - strcpy(pMMArcLayer->MMNode.pszLayerName, pMMArcLayer->pszLayerName); - strcpy(pMMArcLayer->MMNode.pszLayerName, - reset_extension(pMMArcLayer->MMNode.pszLayerName, "nod")); - - if (nullptr == (pMMArcLayer->MMNode.pF = - fopen_function(pMMArcLayer->MMNode.pszLayerName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, "Error MMNode.pF: Cannot open file %s.", - pMMArcLayer->MMNode.pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(pMMArcLayer->MMNode.pF, 0, SEEK_SET); - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - // Node Header - pMMArcLayer->MMNode.nMaxNodeHeader = MM_FIRST_NUMBER_OF_NODES; - if (MMCheckSize_t(pMMArcLayer->MMNode.nMaxNodeHeader * - sizeof(*pMMArcLayer->MMNode.pNodeHeader), - 1)) - return 1; - - if (!pMMArcLayer->MMNode.nMaxNodeHeader) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Error in MiraMon " - "driver: no nodes to write?"); - return 1; - } - - if (nullptr == - (pMMArcLayer->MMNode.pNodeHeader = (struct MM_NH *)calloc_function( - (size_t)pMMArcLayer->MMNode.nMaxNodeHeader * - sizeof(*pMMArcLayer->MMNode.pNodeHeader)))) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMInitNodeLayer())"); - return 1; - } - - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - pMMArcLayer->MMNode.nSizeNodeHeader = MM_SIZE_OF_NH_32BITS; - else - pMMArcLayer->MMNode.nSizeNodeHeader = MM_SIZE_OF_NH_64BITS; - - // NL Section - strcpy(pMMArcLayer->MMNode.pszNLName, pMMArcLayer->MMNode.pszLayerName); - if (MMChangeFinalPartOfTheName(pMMArcLayer->MMNode.pszNLName, - MM_CPL_PATH_BUF_SIZE, ".nod", "N.~idx")) - return 1; - - if (nullptr == (pMMArcLayer->MMNode.pFNL = - fopen_function(pMMArcLayer->MMNode.pszNLName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, "Error MMNode.pFNL: Cannot open file %s.", - pMMArcLayer->MMNode.pszNLName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(pMMArcLayer->MMNode.pFNL, 0, SEEK_SET); - - if (MMInitFlush(&pMMArcLayer->MMNode.FlushNL, pMMArcLayer->MMNode.pFNL, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pMMArcLayer->MMNode.pNL, 0, 0)) - return 1; - - // Creating the DBF file name - strcpy(pMMArcLayer->MMNode.MMAdmDB.pszExtDBFLayerName, - pMMArcLayer->MMNode.pszLayerName); - if (MMChangeFinalPartOfTheName( - pMMArcLayer->MMNode.MMAdmDB.pszExtDBFLayerName, - MM_CPL_PATH_BUF_SIZE, ".nod", "N.dbf")) - return 1; - - // MiraMon metadata - strcpy(pMMArcLayer->MMNode.pszREL_LayerName, - pMMArcLayer->MMNode.pszLayerName); - if (MMChangeFinalPartOfTheName(pMMArcLayer->MMNode.pszREL_LayerName, - MM_CPL_PATH_BUF_SIZE, ".nod", "N.rel")) - return 1; - } - return 0; -} - -static int MMInitArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonArcLayer *pMMArcLayer; - struct MM_TH *pArcTopHeader; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - { - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - pArcTopHeader = &hMiraMonLayer->MMPolygon.TopArcHeader; - } - else - { - pMMArcLayer = &hMiraMonLayer->MMArc; - pArcTopHeader = &hMiraMonLayer->TopHeader; - } - - // Init header structure - hMiraMonLayer->bIsArc = 1; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - pArcTopHeader->bIs3d = 1; // Read description of bRealIs3d - MMInitBoundingBox(&pArcTopHeader->hBB); - - pArcTopHeader->aFileType[0] = 'A'; - pArcTopHeader->aFileType[1] = 'R'; - pArcTopHeader->aFileType[2] = 'C'; - - strcpy(pMMArcLayer->pszLayerName, hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->bIsPolygon) - strcat(pMMArcLayer->pszLayerName, "_bound.arc"); - else - strcat(pMMArcLayer->pszLayerName, ".arc"); - } - - if (nullptr == (pMMArcLayer->pF = fopen_function(pMMArcLayer->pszLayerName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, "Error pMMArcLayer->pF: Cannot open file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE && - hMiraMonLayer->bIsPolygon) - { - fseek_function(pMMArcLayer->pF, 0, SEEK_SET); - if (MMReadHeader(pMMArcLayer->pF, - &hMiraMonLayer->MMPolygon.TopArcHeader)) - { - sprintf(local_message, "Error reading the format in file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); - return 1; - } - // 3D information is in arcs file - hMiraMonLayer->TopHeader.bIs3d = - hMiraMonLayer->MMPolygon.TopArcHeader.bIs3d; - } - - // AH - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - pMMArcLayer->nSizeArcHeader = MM_SIZE_OF_AH_32BITS; - else - pMMArcLayer->nSizeArcHeader = MM_SIZE_OF_AH_64BITS; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - pMMArcLayer->nMaxArcHeader = MM_FIRST_NUMBER_OF_ARCS; - else - pMMArcLayer->nMaxArcHeader = pArcTopHeader->nElemCount; - - if (pMMArcLayer->nMaxArcHeader) - { - if (MMCheckSize_t(pMMArcLayer->nMaxArcHeader * - sizeof(*pMMArcLayer->pArcHeader), - 1)) - return 1; - if (nullptr == (pMMArcLayer->pArcHeader = (struct MM_AH *) - calloc_function((size_t)pMMArcLayer->nMaxArcHeader * - sizeof(*pMMArcLayer->pArcHeader)))) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMInitArcLayer())"); - return 1; - } - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - if (MMReadAHArcSection(hMiraMonLayer)) - { - sprintf(local_message, "Error reading the format in file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); - return 1; - } - } - } - else - pMMArcLayer->pArcHeader = nullptr; - - // AL - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - pMMArcLayer->nALElementSize = MM_SIZE_OF_AL; - - strcpy(pMMArcLayer->pszALName, hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->bIsPolygon) - strcat(pMMArcLayer->pszALName, "_boundA.~xy"); - else - strcat(pMMArcLayer->pszALName, "A.~xy"); - - if (nullptr == (pMMArcLayer->pFAL = fopen_function( - pMMArcLayer->pszALName, hMiraMonLayer->pszFlags))) - { - sprintf(local_message, - "Error pMMArcLayer->pFAL: Cannot open file %s.", - pMMArcLayer->pszALName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(pMMArcLayer->pFAL, 0, SEEK_SET); - - if (MMInitFlush(&pMMArcLayer->FlushAL, pMMArcLayer->pFAL, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pMMArcLayer->pAL, 0, 0)) - return 1; - } - - // 3D - if (pArcTopHeader->bIs3d) - { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - strcpy(pMMArcLayer->psz3DLayerName, hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->bIsPolygon) - strcat(pMMArcLayer->psz3DLayerName, "_boundA.~z"); - else - strcat(pMMArcLayer->psz3DLayerName, "A.~z"); - - if (nullptr == - (pMMArcLayer->pF3d = fopen_function(pMMArcLayer->psz3DLayerName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, - "Error pMMArcLayer->pF3d: Cannot open file %s.", - pMMArcLayer->psz3DLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(pMMArcLayer->pF3d, 0, SEEK_SET); - } - - if (MMInitZSectionLayer(hMiraMonLayer, pMMArcLayer->pF3d, - &pMMArcLayer->pZSection)) - { - sprintf(local_message, "Error reading the format in file %s %d.", - pMMArcLayer->pszLayerName, 6); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); - return 1; - } - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - if (MMReadZSection(hMiraMonLayer, pMMArcLayer->pF, - &pMMArcLayer->pZSection)) - { - sprintf(local_message, "Error reading the format in file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); - return 1; - } - - if (MMReadZDescriptionHeaders(hMiraMonLayer, pMMArcLayer->pF, - pArcTopHeader->nElemCount, - &pMMArcLayer->pZSection)) - { - sprintf(local_message, "Error reading the format in file %s.", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); - return 1; - } - } - } - // MiraMon metadata - strcpy(pMMArcLayer->pszREL_LayerName, hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->bIsPolygon) - { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->pszREL_LayerName, "_boundA.rel"); - else - { - strcpy(pMMArcLayer->pszREL_LayerName, pMMArcLayer->pszLayerName); - if (MMChangeFinalPartOfTheName(pMMArcLayer->pszREL_LayerName, - MM_CPL_PATH_BUF_SIZE, ".arc", - "A.rel")) - return 1; - } - } - else - { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->pszREL_LayerName, "A.rel"); - else - { - if (MMChangeFinalPartOfTheName(pMMArcLayer->pszREL_LayerName, - MM_CPL_PATH_BUF_SIZE, ".arc", - "A.rel")) - return 1; - } - } - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - // This file has to exist and be the appropriate version. - if (MMCheck_REL_FILE(pMMArcLayer->pszREL_LayerName)) - return 1; - } - - if (!hMiraMonLayer->bIsPolygon) - hMiraMonLayer->pszMainREL_LayerName = pMMArcLayer->pszREL_LayerName; - - // MIRAMON DATA BASE - // Creating the DBF file name - strcpy(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->bIsPolygon) - { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, "_boundA.dbf"); - else - { - strcpy(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, - pMMArcLayer->pszLayerName); - if (MMChangeFinalPartOfTheName( - pMMArcLayer->MMAdmDB.pszExtDBFLayerName, - MM_CPL_PATH_BUF_SIZE, ".arc", "A.dbf")) - return 1; - } - } - else - { - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->MMAdmDB.pszExtDBFLayerName, "A.dbf"); - else - { - if (MMChangeFinalPartOfTheName( - pMMArcLayer->MMAdmDB.pszExtDBFLayerName, - MM_CPL_PATH_BUF_SIZE, ".arc", "A.dbf")) - return 1; - } - } - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - if (MM_ReadExtendedDBFHeader(hMiraMonLayer)) - return 1; - } - - // Node part - if (MMInitNodeLayer(hMiraMonLayer)) - return 1; - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - MMSet1_1Version(&pMMArcLayer->TopNodeHeader); - else - MMSet2_0Version(&pMMArcLayer->TopNodeHeader); - - return 0; -} - -static int MMInitPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonPolygonLayer *pMMPolygonLayer; - - if (!hMiraMonLayer) - return 1; - - pMMPolygonLayer = &hMiraMonLayer->MMPolygon; - - // Init header structure - hMiraMonLayer->bIsPolygon = 1; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - hMiraMonLayer->TopHeader.bIs3d = 1; // Read description of bRealIs3d - MMInitBoundingBox(&hMiraMonLayer->TopHeader.hBB); - - hMiraMonLayer->TopHeader.aFileType[0] = 'P'; - hMiraMonLayer->TopHeader.aFileType[1] = 'O'; - hMiraMonLayer->TopHeader.aFileType[2] = 'L'; - - strcpy(pMMPolygonLayer->pszLayerName, hMiraMonLayer->pszSrcLayerName); - strcat(pMMPolygonLayer->pszLayerName, ".pol"); - } - - if (nullptr == - (pMMPolygonLayer->pF = fopen_function(pMMPolygonLayer->pszLayerName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, - "Error pMMPolygonLayer->pF: Cannot open file %s.", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - - // PS - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - pMMPolygonLayer->nPSElementSize = MM_SIZE_OF_PS_32BITS; - else - pMMPolygonLayer->nPSElementSize = MM_SIZE_OF_PS_64BITS; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - strcpy(pMMPolygonLayer->pszPSName, hMiraMonLayer->pszSrcLayerName); - strcat(pMMPolygonLayer->pszPSName, "P.~PS"); - - if (nullptr == - (pMMPolygonLayer->pFPS = fopen_function(pMMPolygonLayer->pszPSName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, - "Error pMMPolygonLayer->pFPS: Cannot open file %s.", - pMMPolygonLayer->pszPSName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(pMMPolygonLayer->pFPS, 0, SEEK_SET); - - if (MMInitFlush(&pMMPolygonLayer->FlushPS, pMMPolygonLayer->pFPS, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pMMPolygonLayer->pPS, 0, - pMMPolygonLayer->nPSElementSize)) - return 1; - } - - // PH - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - pMMPolygonLayer->nPHElementSize = MM_SIZE_OF_PH_32BITS; - else - pMMPolygonLayer->nPHElementSize = MM_SIZE_OF_PH_64BITS; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - pMMPolygonLayer->nMaxPolHeader = MM_FIRST_NUMBER_OF_POLYGONS + 1; - else - pMMPolygonLayer->nMaxPolHeader = hMiraMonLayer->TopHeader.nElemCount; - - if (pMMPolygonLayer->nMaxPolHeader) - { - if (MMCheckSize_t(pMMPolygonLayer->nMaxPolHeader * - sizeof(*pMMPolygonLayer->pPolHeader), - 1)) - return 1; - if (nullptr == - (pMMPolygonLayer->pPolHeader = (struct MM_PH *)calloc_function( - (size_t)pMMPolygonLayer->nMaxPolHeader * - sizeof(*pMMPolygonLayer->pPolHeader)))) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMInitPolygonLayer())"); - return 1; - } - } - else - pMMPolygonLayer->pPolHeader = nullptr; - - // PAL - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - pMMPolygonLayer->nPALElementSize = MM_SIZE_OF_PAL_32BITS; - else - pMMPolygonLayer->nPALElementSize = MM_SIZE_OF_PAL_64BITS; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - // Universal polygon. - memset(pMMPolygonLayer->pPolHeader, 0, - sizeof(*pMMPolygonLayer->pPolHeader)); - hMiraMonLayer->TopHeader.nElemCount = 1; - - // PAL - strcpy(pMMPolygonLayer->pszPALName, hMiraMonLayer->pszSrcLayerName); - strcat(pMMPolygonLayer->pszPALName, "P.~idx"); - - if (nullptr == (pMMPolygonLayer->pFPAL = - fopen_function(pMMPolygonLayer->pszPALName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, - "Error pMMPolygonLayer->pFPAL: Cannot open file %s.", - pMMPolygonLayer->pszPALName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(pMMPolygonLayer->pFPAL, 0, SEEK_SET); - - if (MMInitFlush(&pMMPolygonLayer->FlushPAL, pMMPolygonLayer->pFPAL, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pMMPolygonLayer->pPAL, 0, 0)) - return 1; - } - - // MiraMon metadata - strcpy(hMiraMonLayer->MMPolygon.pszREL_LayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(hMiraMonLayer->MMPolygon.pszREL_LayerName, "P.rel"); - else - { - if (MMChangeFinalPartOfTheName( - hMiraMonLayer->MMPolygon.pszREL_LayerName, MM_CPL_PATH_BUF_SIZE, - ".pol", "P.rel")) - return 1; - } - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - // This file has to exist and be the appropriate version. - if (MMCheck_REL_FILE(hMiraMonLayer->MMPolygon.pszREL_LayerName)) - return 1; - } - - hMiraMonLayer->pszMainREL_LayerName = - hMiraMonLayer->MMPolygon.pszREL_LayerName; - - // MIRAMON DATA BASE - strcpy(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName, "P.dbf"); - else - { - if (MMChangeFinalPartOfTheName( - pMMPolygonLayer->MMAdmDB.pszExtDBFLayerName, - MM_CPL_PATH_BUF_SIZE, ".pol", "P.dbf")) - return 1; - } - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - if (MM_ReadExtendedDBFHeader(hMiraMonLayer)) - return 1; - } - - return 0; -} - -int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->eLT == MM_LayerType_Point || - hMiraMonLayer->eLT == MM_LayerType_Point3d) - { - strcpy(hMiraMonLayer->MMPoint.pszLayerName, - hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(hMiraMonLayer->MMPoint.pszLayerName, ".pnt"); - if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap) - { - hMiraMonLayer->MMMap->nNumberOfLayers++; - fprintf_function(hMiraMonLayer->MMMap->fMMMap, "[VECTOR_%d]\n", - hMiraMonLayer->MMMap->nNumberOfLayers); - fprintf_function(hMiraMonLayer->MMMap->fMMMap, "Fitxer=%s.pnt\n", - MM_CPLGetBasename(hMiraMonLayer->pszSrcLayerName)); - } - - if (MMInitPointLayer(hMiraMonLayer)) - { - // Error specified inside the function - return 1; - } - return 0; - } - if (hMiraMonLayer->eLT == MM_LayerType_Arc || - hMiraMonLayer->eLT == MM_LayerType_Arc3d) - { - struct MiraMonArcLayer *pMMArcLayer = &hMiraMonLayer->MMArc; - - strcpy(pMMArcLayer->pszLayerName, hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMArcLayer->pszLayerName, ".arc"); - - if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap) - { - hMiraMonLayer->MMMap->nNumberOfLayers++; - fprintf_function(hMiraMonLayer->MMMap->fMMMap, "[VECTOR_%d]\n", - hMiraMonLayer->MMMap->nNumberOfLayers); - fprintf_function(hMiraMonLayer->MMMap->fMMMap, "Fitxer=%s.arc\n", - MM_CPLGetBasename(hMiraMonLayer->pszSrcLayerName)); - } - - if (MMInitArcLayer(hMiraMonLayer)) - { - // Error specified inside the function - return 1; - } - return 0; - } - if (hMiraMonLayer->eLT == MM_LayerType_Pol || - hMiraMonLayer->eLT == MM_LayerType_Pol3d) - { - struct MiraMonPolygonLayer *pMMPolygonLayer = &hMiraMonLayer->MMPolygon; - - strcpy(pMMPolygonLayer->pszLayerName, hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - strcat(pMMPolygonLayer->pszLayerName, ".pol"); - - if (hMiraMonLayer->MMMap && hMiraMonLayer->MMMap->fMMMap) - { - hMiraMonLayer->MMMap->nNumberOfLayers++; - fprintf_function(hMiraMonLayer->MMMap->fMMMap, "[VECTOR_%d]\n", - hMiraMonLayer->MMMap->nNumberOfLayers); - fprintf_function(hMiraMonLayer->MMMap->fMMMap, "Fitxer=%s.pol\n", - MM_CPLGetBasename(hMiraMonLayer->pszSrcLayerName)); - } - - if (MMInitPolygonLayer(hMiraMonLayer)) - { - // Error specified inside the function - return 1; - } - - if (hMiraMonLayer->ReadOrWrite == MM_READING_MODE) - { - char *pszArcLayerName; - const char *pszExt; - // StringLine associated to the polygon - pszArcLayerName = MMReturnValueFromSectionINIFile( - pMMPolygonLayer->pszREL_LayerName, - SECTION_OVVW_ASPECTES_TECNICS, KEY_ArcSource); - MM_RemoveInitial_and_FinalQuotationMarks(pszArcLayerName); - - // If extension is not specified ".arc" will be used - pszExt = get_extension_function(pszArcLayerName); - if (MMIsEmptyString(pszExt)) - { - char *pszArcLayerNameAux = - calloc_function(strlen(pszArcLayerName) + 5); - if (!pszArcLayerNameAux) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMInitLayerByType())"); - return 1; - } - strcpy(pszArcLayerNameAux, pszArcLayerName); - strcat(pszArcLayerNameAux, ".arc"); - free_function(pszArcLayerName); - pszArcLayerName = pszArcLayerNameAux; - } - - strcpy(pMMPolygonLayer->MMArc.pszLayerName, - form_filename_function( - get_path_function(hMiraMonLayer->pszSrcLayerName), - pszArcLayerName)); - - free_function(pszArcLayerName); - - if (nullptr == (hMiraMonLayer->MMPolygon.MMArc.pF = fopen_function( - pMMPolygonLayer->MMArc.pszLayerName, - hMiraMonLayer->pszFlags))) - { - sprintf(local_message, - "Error pMMPolygonLayer.MMArc.pF: Cannot open file %s.", - pMMPolygonLayer->MMArc.pszLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - - if (MMReadHeader(hMiraMonLayer->MMPolygon.MMArc.pF, - &hMiraMonLayer->MMPolygon.TopArcHeader)) - { - sprintf(local_message, "Error reading the format in file %s.", - pMMPolygonLayer->MMArc.pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); - return 1; - } - - if (MMReadPHPolygonSection(hMiraMonLayer)) - { - sprintf(local_message, "Error reading the format in file %s.", - pMMPolygonLayer->MMArc.pszLayerName); - MMCPLError(CE_Failure, CPLE_NotSupported, local_message); - return 1; - } - - fclose_function(hMiraMonLayer->MMPolygon.MMArc.pF); - hMiraMonLayer->MMPolygon.MMArc.pF = nullptr; - } - else - { - // Creating the stringLine file associated to the polygon - strcpy(pMMPolygonLayer->MMArc.pszLayerName, - hMiraMonLayer->pszSrcLayerName); - strcat(pMMPolygonLayer->MMArc.pszLayerName, ".arc"); - } - - if (MMInitArcLayer(hMiraMonLayer)) - { - // Error specified inside the function - return 1; - } - - // Polygon is 3D if Arc is 3D, by definition. - hMiraMonLayer->TopHeader.bIs3d = - hMiraMonLayer->MMPolygon.TopArcHeader.bIs3d; - - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - MMSet1_1Version(&pMMPolygonLayer->TopArcHeader); - else - MMSet2_0Version(&pMMPolygonLayer->TopArcHeader); - } - else if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - // Trying to get DBF information - strcpy(hMiraMonLayer->MMAdmDBWriting.pszExtDBFLayerName, - hMiraMonLayer->pszSrcLayerName); - strcat(hMiraMonLayer->MMAdmDBWriting.pszExtDBFLayerName, ".dbf"); - } - - return 0; -} - -int MMInitLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, - const char *pzFileName, int LayerVersion, char nMMRecode, - char nMMLanguage, double nMMMemoryRatio, - struct MiraMonDataBase *pLayerDB, MM_BOOLEAN ReadOrWrite, - struct MiraMonVectMapInfo *MMMap) -{ - if (!hMiraMonLayer) - return 1; - - // Some variables must be initialized - MM_FillFieldDescriptorByLanguage(); - - memset(hMiraMonLayer, 0, sizeof(*hMiraMonLayer)); - - //hMiraMonLayer->Version = MM_VECTOR_LAYER_LAST_VERSION; - hMiraMonLayer->nMemoryRatio = nMMMemoryRatio; - - hMiraMonLayer->ReadOrWrite = ReadOrWrite; - hMiraMonLayer->MMMap = MMMap; - - // Don't free in destructor - hMiraMonLayer->pLayerDB = pLayerDB; - - // Opening mode - strcpy(hMiraMonLayer->pszFlags, "wb+"); - - if (LayerVersion == MM_UNKNOWN_VERSION) - { - MMCPLError(CE_Failure, CPLE_NotSupported, - "Unknown version in MiraMon driver."); - return 1; - } - if (LayerVersion == MM_LAST_VERSION) - { - MMSet1_1Version(&hMiraMonLayer->TopHeader); - hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS; - hMiraMonLayer->LayerVersion = MM_64BITS_VERSION; - } - else if (LayerVersion == MM_32BITS_VERSION) - { - MMSet1_1Version(&hMiraMonLayer->TopHeader); - hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_32_BITS; - hMiraMonLayer->LayerVersion = MM_32BITS_VERSION; - } - else - { - MMSet2_0Version(&hMiraMonLayer->TopHeader); - hMiraMonLayer->nHeaderDiskSize = MM_HEADER_SIZE_64_BITS; - hMiraMonLayer->LayerVersion = MM_64BITS_VERSION; - } - - hMiraMonLayer->pszSrcLayerName = strdup_function(pzFileName); - hMiraMonLayer->szLayerTitle = - strdup_function(get_filename_function(pzFileName)); - - if (!hMiraMonLayer->bIsBeenInit && - hMiraMonLayer->eLT != MM_LayerType_Unknown) - { - if (MMInitLayerByType(hMiraMonLayer)) - { - // Error specified inside the function - return 1; - } - hMiraMonLayer->bIsBeenInit = 1; - } - - // If more nNumStringToOperate is needed, it'll be increased. - hMiraMonLayer->nNumStringToOperate = 0; - if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, 500)) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMInitLayer())"); - return 1; - } - - hMiraMonLayer->nMMLanguage = nMMLanguage; - - if (nMMRecode == MM_RECODE_UTF8) - hMiraMonLayer->nCharSet = MM_JOC_CARAC_UTF8_DBF; - else //if(nMMRecode==MM_RECODE_ANSI) - hMiraMonLayer->nCharSet = MM_JOC_CARAC_ANSI_DBASE; - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Layer Functions: Closing MiraMon layers */ -/* -------------------------------------------------------------------- */ -static int MMClose3DSectionLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_INTERNAL_FID nElements, FILE_TYPE *pF, - FILE_TYPE *pF3d, const char *pszF3d, - struct MM_ZSection *pZSection, - MM_FILE_OFFSET FinalOffset) -{ - if (!hMiraMonLayer) - return 1; - - // Flushing if there is something to flush on the disk - if (!pF || !pF3d || !pszF3d || !pZSection) - return 0; - - if (hMiraMonLayer->bIsReal3d) - { - pZSection->ZSectionOffset = FinalOffset; - if (MMWriteZSection(pF, pZSection)) - return 1; - - // Header 3D. Writes it after header - if (MMWriteZDescriptionHeaders(hMiraMonLayer, pF, nElements, pZSection)) - return 1; - - // ZL section - pZSection->FlushZL.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&pZSection->FlushZL)) - return 1; - - if (MMMoveFromFileToFile(pF3d, pF, &pZSection->ZSectionOffset)) - return 1; - } - - if (pF3d) - fclose_function(pF3d); - if (pszF3d && *pszF3d != '\0') - remove_function(pszF3d); - - return 0; -} - -static int MMClosePointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - hMiraMonLayer->nFinalElemCount = hMiraMonLayer->TopHeader.nElemCount; - hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d; - - if (MMWriteHeader(hMiraMonLayer->MMPoint.pF, &hMiraMonLayer->TopHeader)) - { - sprintf(local_message, "Error writing to file %s", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize; - - // TL Section - hMiraMonLayer->MMPoint.FlushTL.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL)) - { - sprintf(local_message, "Error writing to file %s", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - if (MMMoveFromFileToFile(hMiraMonLayer->MMPoint.pFTL, - hMiraMonLayer->MMPoint.pF, - &hMiraMonLayer->OffsetCheck)) - { - sprintf(local_message, "Error writing to file %s", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - - fclose_function(hMiraMonLayer->MMPoint.pFTL); - if (*hMiraMonLayer->MMPoint.pszTLName != '\0') - remove_function(hMiraMonLayer->MMPoint.pszTLName); - - if (MMClose3DSectionLayer( - hMiraMonLayer, hMiraMonLayer->TopHeader.nElemCount, - hMiraMonLayer->MMPoint.pF, hMiraMonLayer->MMPoint.pF3d, - hMiraMonLayer->MMPoint.psz3DLayerName, - &hMiraMonLayer->MMPoint.pZSection, hMiraMonLayer->OffsetCheck)) - { - sprintf(local_message, "Error writing to file %s", - hMiraMonLayer->MMPoint.pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - } - if (hMiraMonLayer->MMPoint.pF) - fclose_function(hMiraMonLayer->MMPoint.pF); - return 0; -} - -static int MMCloseNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonArcLayer *pMMArcLayer; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - else - pMMArcLayer = &hMiraMonLayer->MMArc; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d; - - if (MMWriteHeader(pMMArcLayer->MMNode.pF, &pMMArcLayer->TopNodeHeader)) - return 1; - hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize; - - // NH Section - if (MMWriteNHNodeSection(hMiraMonLayer, hMiraMonLayer->nHeaderDiskSize)) - return 1; - - // NL Section - pMMArcLayer->MMNode.FlushNL.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&pMMArcLayer->MMNode.FlushNL)) - return 1; - if (MMMoveFromFileToFile(pMMArcLayer->MMNode.pFNL, - pMMArcLayer->MMNode.pF, - &hMiraMonLayer->OffsetCheck)) - return 1; - - if (pMMArcLayer->MMNode.pFNL) - fclose_function(pMMArcLayer->MMNode.pFNL); - if (*pMMArcLayer->MMNode.pszNLName != '\0') - remove_function(pMMArcLayer->MMNode.pszNLName); - } - - if (pMMArcLayer->MMNode.pF) - fclose_function(pMMArcLayer->MMNode.pF); - - return 0; -} - -static int MMCloseArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonArcLayer *pMMArcLayer; - struct MM_TH *pArcTopHeader; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - { - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - pArcTopHeader = &hMiraMonLayer->MMPolygon.TopArcHeader; - } - else - { - pMMArcLayer = &hMiraMonLayer->MMArc; - pArcTopHeader = &hMiraMonLayer->TopHeader; - } - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - hMiraMonLayer->nFinalElemCount = pArcTopHeader->nElemCount; - pArcTopHeader->bIs3d = hMiraMonLayer->bIsReal3d; - - if (MMWriteHeader(pMMArcLayer->pF, pArcTopHeader)) - { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize; - - // AH Section - if (MMWriteAHArcSection(hMiraMonLayer, hMiraMonLayer->OffsetCheck)) - { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - - // AL Section - pMMArcLayer->FlushAL.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&pMMArcLayer->FlushAL)) - { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - if (MMMoveFromFileToFile(pMMArcLayer->pFAL, pMMArcLayer->pF, - &hMiraMonLayer->OffsetCheck)) - { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - if (pMMArcLayer->pFAL) - fclose_function(pMMArcLayer->pFAL); - if (*pMMArcLayer->pszALName != '\0') - remove_function(pMMArcLayer->pszALName); - - // 3D Section - if (MMClose3DSectionLayer( - hMiraMonLayer, pArcTopHeader->nElemCount, pMMArcLayer->pF, - pMMArcLayer->pF3d, pMMArcLayer->psz3DLayerName, - &pMMArcLayer->pZSection, hMiraMonLayer->OffsetCheck)) - { - sprintf(local_message, "Error writing to file %s", - pMMArcLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - } - - if (pMMArcLayer->pF) - fclose_function(pMMArcLayer->pF); - - if (MMCloseNodeLayer(hMiraMonLayer)) - return 1; - - return 0; -} - -static int MMClosePolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonPolygonLayer *pMMPolygonLayer; - - if (!hMiraMonLayer) - return 1; - - pMMPolygonLayer = &hMiraMonLayer->MMPolygon; - - MMCloseArcLayer(hMiraMonLayer); - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - hMiraMonLayer->nFinalElemCount = hMiraMonLayer->TopHeader.nElemCount; - hMiraMonLayer->TopHeader.bIs3d = hMiraMonLayer->bIsReal3d; - - if (MMWriteHeader(pMMPolygonLayer->pF, &hMiraMonLayer->TopHeader)) - { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - hMiraMonLayer->OffsetCheck = hMiraMonLayer->nHeaderDiskSize; - - // PS Section - pMMPolygonLayer->FlushPS.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&pMMPolygonLayer->FlushPS)) - { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - if (MMMoveFromFileToFile(pMMPolygonLayer->pFPS, pMMPolygonLayer->pF, - &hMiraMonLayer->OffsetCheck)) - { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - - if (pMMPolygonLayer->pFPS) - fclose_function(pMMPolygonLayer->pFPS); - if (*pMMPolygonLayer->pszPSName != '\0') - remove_function(pMMPolygonLayer->pszPSName); - - // AH Section - if (MMWritePHPolygonSection(hMiraMonLayer, hMiraMonLayer->OffsetCheck)) - { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - - // PAL Section - pMMPolygonLayer->FlushPAL.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&pMMPolygonLayer->FlushPAL)) - { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - if (MMMoveFromFileToFile(pMMPolygonLayer->pFPAL, pMMPolygonLayer->pF, - &hMiraMonLayer->OffsetCheck)) - { - sprintf(local_message, "Error writing to file %s", - pMMPolygonLayer->pszLayerName); - MMCPLError(CE_Failure, CPLE_NoWriteAccess, local_message); - return 1; - } - if (pMMPolygonLayer->pFPAL) - fclose_function(pMMPolygonLayer->pFPAL); - if (*pMMPolygonLayer->pszPALName != '\0') - remove_function(pMMPolygonLayer->pszPALName); - } - - if (pMMPolygonLayer->pF) - fclose_function(pMMPolygonLayer->pF); - - return 0; -} - -int MMCloseLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - //CheckMMVectorLayerVersion(hMiraMonLayer, 1) - - if (!hMiraMonLayer) - return 0; - - if (hMiraMonLayer->bIsPoint) - { - if (MMClosePointLayer(hMiraMonLayer)) - return 1; - } - else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) - { - if (MMCloseArcLayer(hMiraMonLayer)) - return 1; - } - else if (hMiraMonLayer->bIsPolygon) - { - if (MMClosePolygonLayer(hMiraMonLayer)) - return 1; - } - else if (hMiraMonLayer->bIsDBF) - { - // If no geometry, remove all created files - if (hMiraMonLayer->pszSrcLayerName) - remove_function(hMiraMonLayer->pszSrcLayerName); - if (hMiraMonLayer->szLayerTitle) - remove_function(hMiraMonLayer->szLayerTitle); - } - - // MiraMon metadata files - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - if (MMWriteVectorMetadata(hMiraMonLayer)) - { - MMCPLError(CE_Failure, CPLE_NoWriteAccess, - "Some error writing in metadata file of the layer"); - return 1; - } - } - - // MiraMon database files - if (MMCloseMMBD_XP(hMiraMonLayer)) - { - MMCPLError(CE_Failure, CPLE_NoWriteAccess, - "Some error writing in DBF file of the layer"); - return 1; - } - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Layer Functions: Destroying (allocated memory) */ -/* -------------------------------------------------------------------- */ -static void MMDestroyMMAdmDB(struct MMAdmDatabase *pMMAdmDB) -{ - if (pMMAdmDB->pRecList) - { - free_function(pMMAdmDB->pRecList); - pMMAdmDB->pRecList = nullptr; - } - - if (pMMAdmDB->szRecordOnCourse) - { - free_function(pMMAdmDB->szRecordOnCourse); - pMMAdmDB->szRecordOnCourse = nullptr; - pMMAdmDB->nNumRecordOnCourse = 0; - } -} -static int MMDestroyPointLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->MMPoint.pTL) - { - free_function(hMiraMonLayer->MMPoint.pTL); - hMiraMonLayer->MMPoint.pTL = nullptr; - } - - MMDestroyZSectionDescription(&hMiraMonLayer->MMPoint.pZSection); - MMDestroyMMAdmDB(&hMiraMonLayer->MMPoint.MMAdmDB); - - return 0; -} - -static int MMDestroyNodeLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonArcLayer *pMMArcLayer; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - else - pMMArcLayer = &hMiraMonLayer->MMArc; - - if (pMMArcLayer->MMNode.pNL) - { - free_function(pMMArcLayer->MMNode.pNL); - pMMArcLayer->MMNode.pNL = nullptr; - } - - if (pMMArcLayer->MMNode.pNodeHeader) - { - free_function(pMMArcLayer->MMNode.pNodeHeader); - pMMArcLayer->MMNode.pNodeHeader = nullptr; - } - - MMDestroyMMAdmDB(&hMiraMonLayer->MMArc.MMNode.MMAdmDB); - return 0; -} - -static int MMDestroyArcLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonArcLayer *pMMArcLayer; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - else - pMMArcLayer = &hMiraMonLayer->MMArc; - - if (pMMArcLayer->pAL) - { - free_function(pMMArcLayer->pAL); - pMMArcLayer->pAL = nullptr; - } - if (pMMArcLayer->pArcHeader) - { - free_function(pMMArcLayer->pArcHeader); - pMMArcLayer->pArcHeader = nullptr; - } - - MMDestroyZSectionDescription(&pMMArcLayer->pZSection); - MMDestroyMMAdmDB(&pMMArcLayer->MMAdmDB); - - MMDestroyNodeLayer(hMiraMonLayer); - return 0; -} - -static int MMDestroyPolygonLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MiraMonPolygonLayer *pMMPolygonLayer; - - if (!hMiraMonLayer) - return 1; - - pMMPolygonLayer = &hMiraMonLayer->MMPolygon; - - MMDestroyArcLayer(hMiraMonLayer); - - if (pMMPolygonLayer->pPAL) - { - free_function(pMMPolygonLayer->pPAL); - pMMPolygonLayer->pPAL = nullptr; - } - - if (pMMPolygonLayer->pPS) - { - free_function(pMMPolygonLayer->pPS); - pMMPolygonLayer->pPS = nullptr; - } - - if (pMMPolygonLayer->pPolHeader) - { - free_function(pMMPolygonLayer->pPolHeader); - pMMPolygonLayer->pPolHeader = nullptr; - } - - MMDestroyMMAdmDB(&pMMPolygonLayer->MMAdmDB); - - return 0; -} - -int MMDestroyLayer(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - //CheckMMVectorLayerVersion(hMiraMonLayer, 1) - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPoint) - MMDestroyPointLayer(hMiraMonLayer); - else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) - MMDestroyArcLayer(hMiraMonLayer); - else if (hMiraMonLayer->bIsPolygon) - MMDestroyPolygonLayer(hMiraMonLayer); - - if (hMiraMonLayer->pszSrcLayerName) - { - free_function(hMiraMonLayer->pszSrcLayerName); - hMiraMonLayer->pszSrcLayerName = nullptr; - } - if (hMiraMonLayer->szLayerTitle) - { - free_function(hMiraMonLayer->szLayerTitle); - hMiraMonLayer->szLayerTitle = nullptr; - } - if (hMiraMonLayer->pSRS) - { - free_function(hMiraMonLayer->pSRS); - hMiraMonLayer->pSRS = nullptr; - } - - if (hMiraMonLayer->pMultRecordIndex) - { - free_function(hMiraMonLayer->pMultRecordIndex); - hMiraMonLayer->pMultRecordIndex = nullptr; - } - - if (hMiraMonLayer->ReadFeature.pNCoordRing) - { - free(hMiraMonLayer->ReadFeature.pNCoordRing); - hMiraMonLayer->ReadFeature.pNCoordRing = nullptr; - } - if (hMiraMonLayer->ReadFeature.pCoord) - { - free(hMiraMonLayer->ReadFeature.pCoord); - hMiraMonLayer->ReadFeature.pCoord = nullptr; - } - if (hMiraMonLayer->ReadFeature.pZCoord) - { - free(hMiraMonLayer->ReadFeature.pZCoord); - hMiraMonLayer->ReadFeature.pZCoord = nullptr; - } - if (hMiraMonLayer->ReadFeature.pRecords) - { - free(hMiraMonLayer->ReadFeature.pRecords); - hMiraMonLayer->ReadFeature.pRecords = nullptr; - } - if (hMiraMonLayer->ReadFeature.flag_VFG) - { - free(hMiraMonLayer->ReadFeature.flag_VFG); - hMiraMonLayer->ReadFeature.flag_VFG = nullptr; - } - - if (hMiraMonLayer->pArcs) - { - free_function(hMiraMonLayer->pArcs); - hMiraMonLayer->pArcs = nullptr; - } - - if (hMiraMonLayer->szStringToOperate) - { - free_function(hMiraMonLayer->szStringToOperate); - hMiraMonLayer->szStringToOperate = nullptr; - hMiraMonLayer->nNumStringToOperate = 0; - } - - if (hMiraMonLayer->pLayerDB) - { - if (hMiraMonLayer->pLayerDB->pFields) - { - free_function(hMiraMonLayer->pLayerDB->pFields); - hMiraMonLayer->pLayerDB->pFields = nullptr; - } - free_function(hMiraMonLayer->pLayerDB); - hMiraMonLayer->pLayerDB = nullptr; - } - - // Destroys all database objects - MMDestroyMMDB(hMiraMonLayer); - - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Flush Layer Functions */ -/* -------------------------------------------------------------------- */ - -// Initializes a MM_FLUSH_INFO structure, which is used for buffering -// data before writing it to a file. -int MMInitFlush(struct MM_FLUSH_INFO *pFlush, FILE_TYPE *pF, GUInt64 nBlockSize, - char **pBuffer, MM_FILE_OFFSET DiskOffsetWhereToFlush, - GInt32 nMyDiskSize) -{ - memset(pFlush, 0, sizeof(*pFlush)); - *pBuffer = nullptr; - - pFlush->nMyDiskSize = nMyDiskSize; - pFlush->pF = pF; - pFlush->nBlockSize = nBlockSize; - pFlush->nNumBytes = 0; - if (MMCheckSize_t(nBlockSize, 1)) - return 1; - - if (!nBlockSize) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Error in MiraMon " - "driver: MMInitFlush() with no bytes to process"); - return 1; - } - - if (nullptr == (*pBuffer = (char *)calloc_function((size_t)nBlockSize))) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMInitFlush())"); - return 1; - } - pFlush->OffsetWhereToFlush = DiskOffsetWhereToFlush; - pFlush->CurrentOffset = 0; - return 0; -} - -// Reads data from a file into a buffer. -int MMReadFlush(struct MM_FLUSH_INFO *pFlush) -{ - fseek_function(pFlush->pF, pFlush->OffsetWhereToFlush, SEEK_SET); - if (pFlush->nBlockSize != - (GUInt64)(fread_function(pFlush->pBlockWhereToSaveOrRead, 1, - (size_t)pFlush->nBlockSize, pFlush->pF))) - return 1; - return 0; -} - -// Flushes data from a buffer to a disk file. -static int MMFlushToDisk(struct MM_FLUSH_INFO *FlushInfo) -{ - if (!FlushInfo->nNumBytes) - return 0; - // Just flush to the disk at the correct place. - fseek_function(FlushInfo->pF, FlushInfo->OffsetWhereToFlush, SEEK_SET); - - if (FlushInfo->nNumBytes != - (GUInt64)fwrite_function(FlushInfo->pBlockWhereToSaveOrRead, 1, - (size_t)FlushInfo->nNumBytes, FlushInfo->pF)) - return 1; - FlushInfo->OffsetWhereToFlush += FlushInfo->nNumBytes; - FlushInfo->NTimesFlushed++; - FlushInfo->TotalSavedBytes += FlushInfo->nNumBytes; - FlushInfo->nNumBytes = 0; - - return 0; -} - -// Reads a block of data from a buffer in memory -int MMReadBlockFromBuffer(struct MM_FLUSH_INFO *FlushInfo) -{ - if (!FlushInfo->SizeOfBlockToBeSaved) - return 0; - - if (FlushInfo->pBlockToBeSaved) - { - memcpy(FlushInfo->pBlockToBeSaved, - (void *)((char *)FlushInfo->pBlockWhereToSaveOrRead + - FlushInfo->CurrentOffset), - FlushInfo->SizeOfBlockToBeSaved); - } - FlushInfo->CurrentOffset += FlushInfo->SizeOfBlockToBeSaved; - - return 0; -} - -// Appends a block of data to a buffer in memory, which is -// used for later flushing to disk. -int MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo) -{ - if (FlushInfo->SizeOfBlockToBeSaved) - { - // If all the bloc itselfs does not fit to the buffer, - // then all the block is written directly to the disk - if (FlushInfo->nNumBytes == 0 && - FlushInfo->SizeOfBlockToBeSaved >= FlushInfo->nBlockSize) - { - if (MMFlushToDisk(FlushInfo)) - return 1; - return 0; - } - - // There is space in FlushInfo->pBlockWhereToSaveOrRead? - if (FlushInfo->nNumBytes + FlushInfo->SizeOfBlockToBeSaved <= - FlushInfo->nBlockSize) - { - if (FlushInfo->pBlockToBeSaved) - { - memcpy((void *)((char *)FlushInfo->pBlockWhereToSaveOrRead + - FlushInfo->nNumBytes), - FlushInfo->pBlockToBeSaved, - FlushInfo->SizeOfBlockToBeSaved); - } - else // Add zero caracters - { - char zero_caracters[8] = "\0\0\0\0\0\0\0"; - memcpy((char *)FlushInfo->pBlockWhereToSaveOrRead + - FlushInfo->nNumBytes, - zero_caracters, FlushInfo->SizeOfBlockToBeSaved); - } - - FlushInfo->nNumBytes += FlushInfo->SizeOfBlockToBeSaved; - } - else - { - // Empty the buffer - if (MMFlushToDisk(FlushInfo)) - return 1; - // Append the pendant bytes - if (MMAppendBlockToBuffer(FlushInfo)) - return 1; - } - return 0; - } - // Just flush to the disc. - return MMFlushToDisk(FlushInfo); -} - -// Copy the contents of a temporary file to a final file. -// Used everywhere when closing layers. -int MMMoveFromFileToFile(FILE_TYPE *pSrcFile, FILE_TYPE *pDestFile, - MM_FILE_OFFSET *nOffset) -{ - size_t bufferSize = 100 * 1024 * 1024; // 100 MB buffer; - unsigned char *buffer; - size_t bytesRead, bytesWritten; - MM_FILE_OFFSET size_of_dst_file; - - if (!pSrcFile || !pDestFile || !nOffset) - return 0; - - fseek_function(pDestFile, 0, SEEK_END); - size_of_dst_file = ftell_function(pDestFile); - - if (!size_of_dst_file) - return 0; - - if (size_of_dst_file < bufferSize) - bufferSize = (size_t)size_of_dst_file; - - buffer = (unsigned char *)calloc_function(bufferSize); - - if (!buffer) - return 1; - - fseek_function(pSrcFile, 0, SEEK_SET); - while ((bytesRead = fread_function(buffer, sizeof(unsigned char), - bufferSize, pSrcFile)) > 0) - { - bytesWritten = fwrite_function(buffer, sizeof(unsigned char), bytesRead, - pDestFile); - if (bytesWritten != bytesRead) - { - free_function(buffer); - return 1; - } - if (nOffset) - (*nOffset) += bytesWritten; - } - free_function(buffer); - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Layer: Offsets and variables types managing */ -/* -------------------------------------------------------------------- */ - -// Alineation described in format documents. -static void MMGetOffsetAlignedTo8(MM_FILE_OFFSET *Offset) -{ - MM_FILE_OFFSET reajust; - - if ((*Offset) % 8L) - { - reajust = 8 - ((*Offset) % 8L); - (*Offset) += reajust; - } -} - -// Reading integers depending on the version being read. -int MMReadGUInt64DependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MM_FLUSH_INFO *FlushInfo, - GUInt64 *nUI64) -{ - uint32_t nUL32; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - { - FlushInfo->pBlockToBeSaved = (void *)&nUL32; - FlushInfo->SizeOfBlockToBeSaved = sizeof(nUL32); - if (MMReadBlockFromBuffer(FlushInfo)) - { - FlushInfo->pBlockToBeSaved = nullptr; - return 1; - } - *nUI64 = (GUInt64)nUL32; - } - else - { - FlushInfo->pBlockToBeSaved = (void *)nUI64; - FlushInfo->SizeOfBlockToBeSaved = sizeof(&nUI64); - if (MMReadBlockFromBuffer(FlushInfo)) - { - FlushInfo->pBlockToBeSaved = nullptr; - return 1; - } - } - FlushInfo->pBlockToBeSaved = nullptr; - return 0; -} - -// Reading offsets depending on the version is being read. -int MMReadOffsetDependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MM_FLUSH_INFO *FlushInfo, - MM_FILE_OFFSET *nUI64) -{ - uint32_t nUL32; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - { - FlushInfo->pBlockToBeSaved = (void *)&nUL32; - FlushInfo->SizeOfBlockToBeSaved = sizeof(nUL32); - if (MMReadBlockFromBuffer(FlushInfo)) - { - FlushInfo->pBlockToBeSaved = nullptr; - return 1; - } - *nUI64 = (MM_FILE_OFFSET)nUL32; - } - else - { - FlushInfo->pBlockToBeSaved = (void *)nUI64; - FlushInfo->SizeOfBlockToBeSaved = sizeof(&nUI64); - if (MMReadBlockFromBuffer(FlushInfo)) - { - FlushInfo->pBlockToBeSaved = nullptr; - return 1; - } - } - FlushInfo->pBlockToBeSaved = nullptr; - return 0; -} - -// Appending integers depending on the version. -int MMAppendIntegerDependingOnVersion( - struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo, - uint32_t *nUL32, GUInt64 nUI64) -{ - int result; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - { - *nUL32 = (uint32_t)nUI64; - FlushInfo->SizeOfBlockToBeSaved = sizeof(*nUL32); - hMiraMonLayer->OffsetCheck += FlushInfo->SizeOfBlockToBeSaved; - FlushInfo->pBlockToBeSaved = (void *)nUL32; - } - else - { - FlushInfo->SizeOfBlockToBeSaved = sizeof(nUI64); - hMiraMonLayer->OffsetCheck += FlushInfo->SizeOfBlockToBeSaved; - FlushInfo->pBlockToBeSaved = (void *)&nUI64; - } - result = MMAppendBlockToBuffer(FlushInfo); - FlushInfo->pBlockToBeSaved = nullptr; - return result; -} - -/* -------------------------------------------------------------------- */ -/* Layer: Reading and writing layer sections */ -/* This code follows the specifications of the following document: */ -/* https://www.miramon.cat/new_note/usa/notes/ \ */ -/* FormatFitxersTopologicsMiraMon.pdf */ -/* -------------------------------------------------------------------- */ -int MMReadAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - MM_INTERNAL_FID iElem, nElem; - struct MM_FLUSH_INFO FlushTMP; - char *pBuffer = nullptr; - MM_FILE_OFFSET nBlockSize; - struct MiraMonArcLayer *pMMArcLayer; - MM_N_VERTICES_TYPE nElementCount; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - { - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - nElem = hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount; - } - else - { - pMMArcLayer = &hMiraMonLayer->MMArc; - nElem = hMiraMonLayer->TopHeader.nElemCount; - } - - nBlockSize = nElem * (pMMArcLayer->nSizeArcHeader); - - if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, nBlockSize, &pBuffer, - hMiraMonLayer->nHeaderDiskSize, 0)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer; - if (MMReadFlush(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - for (iElem = 0; iElem < nElem; iElem++) - { - // Bounding box - FlushTMP.pBlockToBeSaved = - (void *)&(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX); - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Element count: number of vertices of the arc - nElementCount = pMMArcLayer->pArcHeader[iElem].nElemCount; - if (MMReadGUInt64DependingOnVersion(hMiraMonLayer, &FlushTMP, - &nElementCount)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - pMMArcLayer->pArcHeader[iElem].nElemCount = nElementCount; - - // Offset: offset of the first vertice of the arc - if (MMReadOffsetDependingOnVersion( - hMiraMonLayer, &FlushTMP, - &pMMArcLayer->pArcHeader[iElem].nOffset)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - // First node: first node of the arc - if (MMReadGUInt64DependingOnVersion( - hMiraMonLayer, &FlushTMP, - &pMMArcLayer->pArcHeader[iElem].nFirstIdNode)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - // Last node: first node of the arc - if (MMReadGUInt64DependingOnVersion( - hMiraMonLayer, &FlushTMP, - &pMMArcLayer->pArcHeader[iElem].nLastIdNode)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - // Lenght of the arc - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfLenght; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfLenght); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - - if (pBuffer) - free_function(pBuffer); - return 0; -} - -int MMWriteAHArcSection(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET DiskOffset) -{ - MM_INTERNAL_FID iElem; - struct MM_FLUSH_INFO FlushTMP; - char *pBuffer = nullptr; - uint32_t nUL32; - MM_FILE_OFFSET nOffsetDiff; - struct MiraMonArcLayer *pMMArcLayer; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - else - pMMArcLayer = &hMiraMonLayer->MMArc; - - nOffsetDiff = - hMiraMonLayer->nHeaderDiskSize + - hMiraMonLayer->nFinalElemCount * (pMMArcLayer->nSizeArcHeader); - - if (MMInitFlush(&FlushTMP, pMMArcLayer->pF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pBuffer, DiskOffset, 0)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer; - for (iElem = 0; iElem < hMiraMonLayer->nFinalElemCount; iElem++) - { - // Bounding box - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX); - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinX; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxX; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMinY; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfBB.dfMaxY; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Element count: number of vertices of the arc - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMArcLayer->pArcHeader[iElem].nElemCount)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Offset: offset of the first vertice of the arc - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMArcLayer->pArcHeader[iElem].nOffset + nOffsetDiff)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - // First node: first node of the arc - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMArcLayer->pArcHeader[iElem].nFirstIdNode)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - // Last node: first node of the arc - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMArcLayer->pArcHeader[iElem].nLastIdNode)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - // Lenght of the arc - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->pArcHeader[iElem].dfLenght); - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->pArcHeader[iElem].dfLenght; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - FlushTMP.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - if (pBuffer) - free_function(pBuffer); - return 0; -} - -#ifdef JUST_IN_CASE_WE_NEED_IT_SOMEDAY -static int MMReadNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - MM_INTERNAL_FID iElem, nElem; - struct MM_FLUSH_INFO FlushTMP; - char *pBuffer = nullptr; - MM_FILE_OFFSET nBlockSize; - struct MiraMonArcLayer *pMMArcLayer; - - if (hMiraMonLayer->bIsPolygon) - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - else - pMMArcLayer = &hMiraMonLayer->MMArc; - - nElem = pMMArcLayer->TopNodeHeader.nElemCount; - - nBlockSize = nElem * pMMArcLayer->MMNode.nSizeNodeHeader; - - if (MMInitFlush(&FlushTMP, pMMArcLayer->MMNode.pF, nBlockSize, &pBuffer, - hMiraMonLayer->nHeaderDiskSize, 0)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer; - if (MMReadFlush(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - for (iElem = 0; iElem < nElem; iElem++) - { - // Arcs count - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - // Node type - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.SizeOfBlockToBeSaved = 1; - FlushTMP.pBlockToBeSaved = (void *)nullptr; - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Offset: offset of the first arc to the node - if (MMReadOffsetDependingOnVersion( - hMiraMonLayer, &FlushTMP, - &pMMArcLayer->MMNode.pNodeHeader[iElem].nOffset)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - - if (pBuffer) - free_function(pBuffer); - return 0; -} -#endif // JUST_IN_CASE_WE_NEED_IT_SOMEDAY - -int MMWriteNHNodeSection(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET DiskOffset) -{ - MM_INTERNAL_FID iElem; - struct MM_FLUSH_INFO FlushTMP; - char *pBuffer = nullptr; - uint32_t nUL32; - MM_FILE_OFFSET nOffsetDiff; - struct MiraMonArcLayer *pMMArcLayer; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - else - pMMArcLayer = &hMiraMonLayer->MMArc; - - nOffsetDiff = hMiraMonLayer->nHeaderDiskSize + - (pMMArcLayer->TopNodeHeader.nElemCount * - pMMArcLayer->MMNode.nSizeNodeHeader); - - if (MMInitFlush(&FlushTMP, pMMArcLayer->MMNode.pF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pBuffer, DiskOffset, 0)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer; - for (iElem = 0; iElem < pMMArcLayer->TopNodeHeader.nElemCount; iElem++) - { - // Arcs count - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount); - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].nArcsCount; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - // Node type - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType); - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - FlushTMP.pBlockToBeSaved = - (void *)&pMMArcLayer->MMNode.pNodeHeader[iElem].cNodeType; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.SizeOfBlockToBeSaved = 1; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - FlushTMP.pBlockToBeSaved = (void *)nullptr; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Offset: offset of the first arc to the node - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMArcLayer->MMNode.pNodeHeader[iElem].nOffset + nOffsetDiff)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - FlushTMP.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - if (pBuffer) - free_function(pBuffer); - return 0; -} - -int MMReadPHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - MM_INTERNAL_FID iElem; - struct MM_FLUSH_INFO FlushTMP; - char *pBuffer = nullptr; - MM_FILE_OFFSET nBlockSize; - struct MiraMonPolygonLayer *pMMPolygonLayer; - - if (!hMiraMonLayer) - return 1; - - pMMPolygonLayer = &hMiraMonLayer->MMPolygon; - - nBlockSize = - hMiraMonLayer->TopHeader.nElemCount * (pMMPolygonLayer->nPHElementSize); - - if (MMInitFlush(&FlushTMP, pMMPolygonLayer->pF, nBlockSize, &pBuffer, - hMiraMonLayer->nHeaderDiskSize + - (hMiraMonLayer->MMPolygon.TopArcHeader.nElemCount * - hMiraMonLayer->MMPolygon.nPSElementSize), - 0)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer; - if (MMReadFlush(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - for (iElem = 0; iElem < hMiraMonLayer->TopHeader.nElemCount; iElem++) - { - // Bounding box - FlushTMP.pBlockToBeSaved = - (void *)&(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX); - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY; - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY); - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Arcs count: number of arcs of the polygon - if (MMReadGUInt64DependingOnVersion( - hMiraMonLayer, &FlushTMP, - &pMMPolygonLayer->pPolHeader[iElem].nArcsCount)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // External arcs count: number of external arcs of the polygon - if (MMReadGUInt64DependingOnVersion( - hMiraMonLayer, &FlushTMP, - &pMMPolygonLayer->pPolHeader[iElem].nExternalRingsCount)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Rings count: number of rings of the polygon - if (MMReadGUInt64DependingOnVersion( - hMiraMonLayer, &FlushTMP, - &pMMPolygonLayer->pPolHeader[iElem].nRingsCount)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Offset: offset of the first vertex of the arc - if (MMReadOffsetDependingOnVersion( - hMiraMonLayer, &FlushTMP, - &pMMPolygonLayer->pPolHeader[iElem].nOffset)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Perimeter of the arc - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfPerimeter); - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfPerimeter; - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Area of the arc - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfArea); - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfArea; - if (MMReadBlockFromBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - - if (pBuffer) - free_function(pBuffer); - return 0; -} - -int MMWritePHPolygonSection(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET DiskOffset) -{ - MM_INTERNAL_FID iElem; - struct MM_FLUSH_INFO FlushTMP; - char *pBuffer = nullptr; - uint32_t nUL32; - MM_FILE_OFFSET nOffsetDiff; - struct MiraMonPolygonLayer *pMMPolygonLayer; - - if (!hMiraMonLayer) - return 1; - - pMMPolygonLayer = &hMiraMonLayer->MMPolygon; - - if (!pMMPolygonLayer->pF) - return 0; - - if (!hMiraMonLayer->nFinalElemCount) - return 0; - - nOffsetDiff = DiskOffset + hMiraMonLayer->TopHeader.nElemCount * - (pMMPolygonLayer->nPHElementSize); - - if (MMInitFlush(&FlushTMP, pMMPolygonLayer->pF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pBuffer, DiskOffset, 0)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - FlushTMP.pBlockWhereToSaveOrRead = (void *)pBuffer; - for (iElem = 0; iElem < hMiraMonLayer->nFinalElemCount; iElem++) - { - // Bounding box - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX); - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinX; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxX; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMinY; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfBB.dfMaxY; - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Arcs count: number of the arcs of the polygon - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMPolygonLayer->pPolHeader[iElem].nArcsCount)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // External arcs count: number of external arcs of the polygon - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMPolygonLayer->pPolHeader[iElem].nExternalRingsCount)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Rings count: number of rings of the polygon - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMPolygonLayer->pPolHeader[iElem].nRingsCount)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Offset: offset of the first vertex of the arc - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, &FlushTMP, &nUL32, - pMMPolygonLayer->pPolHeader[iElem].nOffset + nOffsetDiff)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Perimeter of the arc - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfPerimeter); - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfPerimeter; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - // Area of the arc - FlushTMP.SizeOfBlockToBeSaved = - sizeof(pMMPolygonLayer->pPolHeader[iElem].dfArea); - hMiraMonLayer->OffsetCheck += FlushTMP.SizeOfBlockToBeSaved; - FlushTMP.pBlockToBeSaved = - (void *)&pMMPolygonLayer->pPolHeader[iElem].dfArea; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - } - FlushTMP.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&FlushTMP)) - { - if (pBuffer) - free_function(pBuffer); - return 1; - } - - if (pBuffer) - free_function(pBuffer); - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Feature Functions */ -/* -------------------------------------------------------------------- */ -int MMInitFeature(struct MiraMonFeature *hMMFeature) -{ - memset(hMMFeature, 0, sizeof(*hMMFeature)); - - hMMFeature->nMaxMRecords = MM_INIT_NUMBER_OF_RECORDS; - if (MMCheckSize_t( - hMMFeature->nMaxMRecords * sizeof(*(hMMFeature->pRecords)), 1)) - return 1; - - if (!hMMFeature->nMaxMRecords) - return 0; // No elements nothing to do. - - if ((hMMFeature->pRecords = - calloc_function((size_t)hMMFeature->nMaxMRecords * - sizeof(*(hMMFeature->pRecords)))) == nullptr) - return 1; - - hMMFeature->pRecords[0].nMaxField = MM_INIT_NUMBER_OF_FIELDS; - hMMFeature->pRecords[0].nNumField = 0; - if (MMCheckSize_t(hMMFeature->pRecords[0].nMaxField * - sizeof(*(hMMFeature->pRecords[0].pField)), - 1)) - return 1; - if (nullptr == (hMMFeature->pRecords[0].pField = calloc_function( - (size_t)hMMFeature->pRecords[0].nMaxField * - sizeof(*(hMMFeature->pRecords[0].pField))))) - return 1; - - return 0; -} - -// Conserves all allocated memory but resets the information -void MMResetFeatureGeometry(struct MiraMonFeature *hMMFeature) -{ - if (hMMFeature->pNCoordRing) - { - memset(hMMFeature->pNCoordRing, 0, - (size_t)hMMFeature->nMaxpNCoordRing * - sizeof(*(hMMFeature->pNCoordRing))); - } - if (hMMFeature->pCoord) - { - memset(hMMFeature->pCoord, 0, - (size_t)hMMFeature->nMaxpCoord * sizeof(*(hMMFeature->pCoord))); - } - hMMFeature->nICoord = 0; - if (hMMFeature->pZCoord) - { - memset(hMMFeature->pZCoord, 0, - (size_t)hMMFeature->nMaxpZCoord * - sizeof(*(hMMFeature->pZCoord))); - } - hMMFeature->nNRings = 0; - hMMFeature->nIRing = 0; - - if (hMMFeature->flag_VFG) - { - memset(hMMFeature->flag_VFG, 0, - (size_t)hMMFeature->nMaxVFG * sizeof(*(hMMFeature->flag_VFG))); - } -} - -// Preserves all allocated memory but initializes it to zero. -void MMResetFeatureRecord(struct MiraMonFeature *hMMFeature) -{ - MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord; - MM_EXT_DBF_N_FIELDS nIField; - - if (!hMMFeature->pRecords) - return; - - for (nIRecord = 0; nIRecord < hMMFeature->nMaxMRecords; nIRecord++) - { - if (!hMMFeature->pRecords[nIRecord].pField) - continue; - for (nIField = 0; nIField < hMMFeature->pRecords[nIRecord].nMaxField; - nIField++) - { - if (hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue) - *(hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue) = - '\0'; - hMMFeature->pRecords[nIRecord].pField[nIField].bIsValid = 0; - } - } -} - -// Destroys all allocated memory -void MMDestroyFeature(struct MiraMonFeature *hMMFeature) -{ - if (hMMFeature->pCoord) - { - free_function(hMMFeature->pCoord); - hMMFeature->pCoord = nullptr; - } - if (hMMFeature->pZCoord) - { - free_function(hMMFeature->pZCoord); - hMMFeature->pZCoord = nullptr; - } - if (hMMFeature->pNCoordRing) - { - free_function(hMMFeature->pNCoordRing); - hMMFeature->pNCoordRing = nullptr; - } - - if (hMMFeature->flag_VFG) - { - free_function(hMMFeature->flag_VFG); - hMMFeature->flag_VFG = nullptr; - } - - if (hMMFeature->pRecords) - { - MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord; - MM_EXT_DBF_N_FIELDS nIField; - - for (nIRecord = 0; nIRecord < hMMFeature->nMaxMRecords; nIRecord++) - { - if (!hMMFeature->pRecords[nIRecord].pField) - continue; - for (nIField = 0; - nIField < hMMFeature->pRecords[nIRecord].nMaxField; nIField++) - { - if (hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue) - free_function(hMMFeature->pRecords[nIRecord] - .pField[nIField] - .pDinValue); - } - free_function(hMMFeature->pRecords[nIRecord].pField); - } - free_function(hMMFeature->pRecords); - hMMFeature->pRecords = nullptr; - } - - hMMFeature->nNRings = 0; - hMMFeature->nNumMRecords = 0; - hMMFeature->nMaxMRecords = 0; -} - -// Creates a MiraMon polygon, multipolygon, or linestring (arc) feature. -static int MMCreateFeaturePolOrArc(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature) -{ - double *pZ = nullptr; - struct MM_POINT_2D *pCoord, *pCoordReal; - MM_POLYGON_RINGS_COUNT nIPart; - MM_N_VERTICES_TYPE nIVertice; - double dtempx, dtempy; - MM_POLYGON_RINGS_COUNT nExternalRingsCount; - struct MM_PH *pCurrentPolHeader = nullptr; - struct MM_AH *pCurrentArcHeader; - struct MM_NH *pCurrentNodeHeader, *pCurrentNodeHeaderPlus1 = nullptr; - uint32_t UnsignedLongNumber; - struct MiraMonArcLayer *pMMArc; - struct MiraMonNodeLayer *pMMNode; - struct MM_TH *pArcTopHeader; - struct MM_TH *pNodeTopHeader; - char VFG = 0; - MM_FILE_OFFSET nOffsetTmp; - struct MM_ZD *pZDesc = nullptr; - struct MM_FLUSH_INFO *pFlushAL, *pFlushNL, *pFlushZL, *pFlushPS, *pFlushPAL; - MM_N_VERTICES_TYPE nPolVertices = 0; - MM_BOOLEAN bReverseArc; - int prevCoord = -1; - - if (!hMiraMonLayer) - return MM_FATAL_ERROR_WRITING_FEATURES; - - if (!hMMFeature) - return MM_FATAL_ERROR_WRITING_FEATURES; - - if (!hMMFeature->pCoord) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Setting pointer to 3D structure (if exists). - if (hMiraMonLayer->TopHeader.bIs3d) - pZ = hMMFeature->pZCoord; - - // Setting pointers to arc/node structures. - if (hMiraMonLayer->bIsPolygon) - { - pMMArc = &hMiraMonLayer->MMPolygon.MMArc; - pArcTopHeader = &hMiraMonLayer->MMPolygon.TopArcHeader; - - pMMNode = &hMiraMonLayer->MMPolygon.MMArc.MMNode; - pNodeTopHeader = &hMiraMonLayer->MMPolygon.MMArc.TopNodeHeader; - } - else - { - pMMArc = &hMiraMonLayer->MMArc; - pArcTopHeader = &hMiraMonLayer->TopHeader; - - pMMNode = &hMiraMonLayer->MMArc.MMNode; - pNodeTopHeader = &hMiraMonLayer->MMArc.TopNodeHeader; - } - - // Setting pointers to polygon structures - if (hMiraMonLayer->bIsPolygon) - { - if (MMResizePolHeaderPointer(&hMiraMonLayer->MMPolygon.pPolHeader, - &hMiraMonLayer->MMPolygon.nMaxPolHeader, - pNodeTopHeader->nElemCount + 2, - MM_INCR_NUMBER_OF_POLYGONS, 0)) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizePolHeaderPointer())"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - pCurrentPolHeader = hMiraMonLayer->MMPolygon.pPolHeader + - hMiraMonLayer->TopHeader.nElemCount; - MMInitBoundingBox(&pCurrentPolHeader->dfBB); - - pCurrentPolHeader->dfPerimeter = 0; - pCurrentPolHeader->dfArea = 0L; - } - - // Setting flushes to all sections described in - // format specifications document. - pFlushAL = &pMMArc->FlushAL; - pFlushNL = &pMMNode->FlushNL; - pFlushZL = &pMMArc->pZSection.FlushZL; - pFlushPS = &hMiraMonLayer->MMPolygon.FlushPS; - pFlushPAL = &hMiraMonLayer->MMPolygon.FlushPAL; - - pFlushNL->pBlockWhereToSaveOrRead = (void *)pMMNode->pNL; - pFlushAL->pBlockWhereToSaveOrRead = (void *)pMMArc->pAL; - if (hMiraMonLayer->TopHeader.bIs3d) - pFlushZL->pBlockWhereToSaveOrRead = (void *)pMMArc->pZSection.pZL; - if (hMiraMonLayer->bIsPolygon) - { - pFlushPS->pBlockWhereToSaveOrRead = - (void *)hMiraMonLayer->MMPolygon.pPS; - pFlushPAL->pBlockWhereToSaveOrRead = - (void *)hMiraMonLayer->MMPolygon.pPAL; - } - - // Creation of the MiraMon extended database - if (!hMiraMonLayer->bIsPolygon) - { - if (hMiraMonLayer->TopHeader.nElemCount == 0) - { - MMCPLDebug("MiraMon", "Creating MiraMon database"); - if (MMCreateMMDB(hMiraMonLayer)) - return MM_FATAL_ERROR_WRITING_FEATURES; - MMCPLDebug("MiraMon", "MiraMon database created"); - } - } - else - { // Universal polygon has been created - if (hMiraMonLayer->TopHeader.nElemCount == 1) - { - MMCPLDebug("MiraMon", "Creating MiraMon database"); - if (MMCreateMMDB(hMiraMonLayer)) - return MM_FATAL_ERROR_WRITING_FEATURES; - MMCPLDebug("MiraMon", "MiraMon database created"); - - // Universal polygon have a record with ID_GRAFIC=0 and blancs - if (MMAddPolygonRecordToMMDB(hMiraMonLayer, nullptr, 0, 0, nullptr)) - return MM_FATAL_ERROR_WRITING_FEATURES; - } - } - - // Checking if its possible continue writing the file due - // to version limitations. - if (hMiraMonLayer->LayerVersion == MM_32BITS_VERSION) - { - MM_FILE_OFFSET nNodeOffset, nArcOffset; - MM_INTERNAL_FID nArcElemCount, nNodeElemCount; - nNodeOffset = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes; - nArcOffset = pMMArc->nOffsetArc; - - nArcElemCount = pArcTopHeader->nElemCount; - nNodeElemCount = pNodeTopHeader->nElemCount; - for (nIPart = 0; nIPart < hMMFeature->nNRings; nIPart++, - nArcElemCount++, - nNodeElemCount += (hMiraMonLayer->bIsPolygon ? 1 : 2)) - { - // There is space for the element that is going to be written? - // Polygon or arc - if (MMCheckVersionForFID(hMiraMonLayer, - hMiraMonLayer->TopHeader.nElemCount)) - { - MMCPLDebug("MiraMon", "Error in MMCheckVersionForFID() (1)"); - return MM_STOP_WRITING_FEATURES; - } - - // Arc if there is no polygon - if (MMCheckVersionForFID(hMiraMonLayer, nArcElemCount)) - { - MMCPLDebug("MiraMon", "Error in MMCheckVersionForFID() (2)"); - return MM_STOP_WRITING_FEATURES; - } - - // Nodes - if (MMCheckVersionForFID(hMiraMonLayer, nNodeElemCount)) - { - MMCPLDebug("MiraMon", "Error in MMCheckVersionForFID() (3)"); - return MM_STOP_WRITING_FEATURES; - } - - // There is space for the last node(s) that is(are) going to be written? - if (!hMiraMonLayer->bIsPolygon) - { - if (MMCheckVersionForFID(hMiraMonLayer, nNodeElemCount + 1)) - { - MMCPLDebug("MiraMon", - "Error in MMCheckVersionForFID() (4)"); - return MM_STOP_WRITING_FEATURES; - } - } - - // Checking offsets - // AL: check the last point - if (MMCheckVersionOffset(hMiraMonLayer, nArcOffset)) - { - MMCPLDebug("MiraMon", "Error in MMCheckVersionOffset() (0)"); - return MM_STOP_WRITING_FEATURES; - } - // Setting next offset - nArcOffset += - (hMMFeature->pNCoordRing[nIPart]) * pMMArc->nALElementSize; - - // NL: check the last node - if (hMiraMonLayer->bIsPolygon) - nNodeOffset += (hMMFeature->nNRings) * MM_SIZE_OF_NL_32BITS; - else - nNodeOffset += (2 * hMMFeature->nNRings) * MM_SIZE_OF_NL_32BITS; - - if (MMCheckVersionOffset(hMiraMonLayer, nNodeOffset)) - { - MMCPLDebug("MiraMon", "Error in MMCheckVersionOffset() (1)"); - return MM_STOP_WRITING_FEATURES; - } - // Setting next offset - nNodeOffset += MM_SIZE_OF_NL_32BITS; - - if (!hMiraMonLayer->bIsPolygon) - { - if (MMCheckVersionOffset(hMiraMonLayer, nNodeOffset)) - { - MMCPLDebug("MiraMon", - "Error in MMCheckVersionOffset() (2)"); - return MM_STOP_WRITING_FEATURES; - } - // Setting next offset - nNodeOffset += MM_SIZE_OF_NL_32BITS; - } - - // Where 3D part is going to start - if (hMiraMonLayer->TopHeader.bIs3d) - { - nArcOffset += - hMMFeature->pNCoordRing[nIPart] * pMMArc->nALElementSize; - if (MMCheckVersionFor3DOffset( - hMiraMonLayer, nArcOffset, - hMiraMonLayer->TopHeader.nElemCount + - hMMFeature->nNRings)) - { - MMCPLDebug("MiraMon", - "Error in MMCheckVersionFor3DOffset()"); - return MM_STOP_WRITING_FEATURES; - } - } - } - } - - // Going through parts of the feature. - nExternalRingsCount = 0; - pCoord = hMMFeature->pCoord; - - // Doing real job - for (nIPart = 0; nIPart < hMMFeature->nNRings; nIPart++, - pArcTopHeader->nElemCount++, - pNodeTopHeader->nElemCount += (hMiraMonLayer->bIsPolygon ? 1 : 2)) - { - // Resize structures if necessary - if (MMResizeArcHeaderPointer( - &pMMArc->pArcHeader, &pMMArc->nMaxArcHeader, - pArcTopHeader->nElemCount + 1, MM_INCR_NUMBER_OF_ARCS, 0)) - { - MMCPLDebug("MiraMon", "Error in MMResizeArcHeaderPointer()"); - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMCreateFeaturePolOrArc())"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - if (MMResizeNodeHeaderPointer( - &pMMNode->pNodeHeader, &pMMNode->nMaxNodeHeader, - hMiraMonLayer->bIsPolygon ? pNodeTopHeader->nElemCount + 1 - : pNodeTopHeader->nElemCount + 2, - MM_INCR_NUMBER_OF_NODES, 0)) - { - MMCPLDebug("MiraMon", "Error in MMResizeNodeHeaderPointer()"); - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMCreateFeaturePolOrArc())"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - if (hMiraMonLayer->TopHeader.bIs3d) - { - if (MMResizeZSectionDescrPointer( - &pMMArc->pZSection.pZDescription, - &pMMArc->pZSection.nMaxZDescription, pMMArc->nMaxArcHeader, - MM_INCR_NUMBER_OF_ARCS, 0)) - { - MMCPLDebug("MiraMon", - "Error in MMResizeZSectionDescrPointer()"); - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMCreateFeaturePolOrArc())"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - pZDesc = pMMArc->pZSection.pZDescription; - } - - // Setting pointers to current headers - pCurrentArcHeader = pMMArc->pArcHeader + pArcTopHeader->nElemCount; - MMInitBoundingBox(&pCurrentArcHeader->dfBB); - - pCurrentNodeHeader = pMMNode->pNodeHeader + pNodeTopHeader->nElemCount; - if (!hMiraMonLayer->bIsPolygon) - pCurrentNodeHeaderPlus1 = pCurrentNodeHeader + 1; - - // Initialiting feature information (section AH/PH) - pCurrentArcHeader->nElemCount = hMMFeature->pNCoordRing[nIPart]; - pCurrentArcHeader->dfLenght = 0.0; - pCurrentArcHeader->nOffset = - pFlushAL->TotalSavedBytes + pFlushAL->nNumBytes; - - // Dumping vertices and calculating stuff that - // MiraMon needs (longitude/perimeter, area) - bReverseArc = FALSE; - if (hMiraMonLayer->bIsPolygon) - { - VFG = hMMFeature->flag_VFG[nIPart]; - bReverseArc = (VFG & MM_ROTATE_ARC) ? TRUE : FALSE; - } - - if (bReverseArc) - { - prevCoord = 1; // to find previous coordinate - pCoordReal = pCoord + pCurrentArcHeader->nElemCount - 1; - } - else - { - prevCoord = -1; // to find previous coordinate - pCoordReal = pCoord; - } - - for (nIVertice = 0; nIVertice < pCurrentArcHeader->nElemCount; - nIVertice++, (bReverseArc) ? pCoordReal-- : pCoordReal++) - { - // Writing the arc in the normal way - pFlushAL->SizeOfBlockToBeSaved = sizeof(pCoordReal->dfX); - pFlushAL->pBlockToBeSaved = (void *)&(pCoord + nIVertice)->dfX; - if (MMAppendBlockToBuffer(pFlushAL)) - { - MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer() (1)"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - pFlushAL->pBlockToBeSaved = (void *)&(pCoord + nIVertice)->dfY; - if (MMAppendBlockToBuffer(pFlushAL)) - { - MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer() (2)"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - // Calculating stuff using the inverse coordinates if it's needed - MMUpdateBoundingBoxXY(&pCurrentArcHeader->dfBB, pCoordReal); - if (nIVertice == 0 || - nIVertice == pCurrentArcHeader->nElemCount - 1) - MMUpdateBoundingBoxXY(&pNodeTopHeader->hBB, pCoordReal); - if (nIVertice > 0) - { - dtempx = pCoordReal->dfX - (pCoordReal + prevCoord)->dfX; - dtempy = pCoordReal->dfY - (pCoordReal + prevCoord)->dfY; - pCurrentArcHeader->dfLenght += - sqrt(dtempx * dtempx + dtempy * dtempy); - if (hMiraMonLayer->bIsPolygon && pCurrentPolHeader) - { - pCurrentPolHeader->dfArea += - (pCoordReal->dfX * (pCoordReal + prevCoord)->dfY - - (pCoordReal + prevCoord)->dfX * pCoordReal->dfY); - } - } - } - if (bReverseArc) - pCoord = pCoordReal + pCurrentArcHeader->nElemCount; - else - pCoord += pCurrentArcHeader->nElemCount; - - nPolVertices += pCurrentArcHeader->nElemCount; - - // Updating bounding boxes - MMUpdateBoundingBox(&pArcTopHeader->hBB, &pCurrentArcHeader->dfBB); - if (hMiraMonLayer->bIsPolygon) - MMUpdateBoundingBox(&hMiraMonLayer->TopHeader.hBB, - &pCurrentArcHeader->dfBB); - - pMMArc->nOffsetArc += - (pCurrentArcHeader->nElemCount) * pMMArc->nALElementSize; - - pCurrentArcHeader->nFirstIdNode = (2 * pArcTopHeader->nElemCount); - if (hMiraMonLayer->bIsPolygon) - { - pCurrentArcHeader->nFirstIdNode = pArcTopHeader->nElemCount; - pCurrentArcHeader->nLastIdNode = pArcTopHeader->nElemCount; - } - else - { - pCurrentArcHeader->nFirstIdNode = (2 * pArcTopHeader->nElemCount); - pCurrentArcHeader->nLastIdNode = - (2 * pArcTopHeader->nElemCount + 1); - } - if (MMAddArcRecordToMMDB(hMiraMonLayer, hMMFeature, - pArcTopHeader->nElemCount, pCurrentArcHeader)) - { - MMCPLDebug("MiraMon", "Error in MMAddArcRecordToMMDB()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - // Node Stuff: writting NL section - pCurrentNodeHeader->nArcsCount = 1; - if (hMiraMonLayer->bIsPolygon) - pCurrentNodeHeader->cNodeType = MM_RING_NODE; - else - pCurrentNodeHeader->cNodeType = MM_FINAL_NODE; - - pCurrentNodeHeader->nOffset = - pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes; - if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushNL, - &UnsignedLongNumber, - pArcTopHeader->nElemCount)) - { - MMCPLDebug("MiraMon", - "Error in MMAppendIntegerDependingOnVersion()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - // 8bytes alignment - nOffsetTmp = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes; - MMGetOffsetAlignedTo8(&nOffsetTmp); - if (nOffsetTmp != pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes) - { - pFlushNL->SizeOfBlockToBeSaved = - (size_t)(nOffsetTmp - - (pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes)); - pFlushNL->pBlockToBeSaved = (void *)nullptr; - if (MMAppendBlockToBuffer(pFlushNL)) - { - MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer() (3)"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - } - if (MMAddNodeRecordToMMDB(hMiraMonLayer, pNodeTopHeader->nElemCount, - pCurrentNodeHeader)) - { - MMCPLDebug("MiraMon", "Error in MMAddNodeRecordToMMDB()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - if (!hMiraMonLayer->bIsPolygon) - { - pCurrentNodeHeaderPlus1->nArcsCount = 1; - if (hMiraMonLayer->bIsPolygon) - pCurrentNodeHeaderPlus1->cNodeType = MM_RING_NODE; - else - pCurrentNodeHeaderPlus1->cNodeType = MM_FINAL_NODE; - - pCurrentNodeHeaderPlus1->nOffset = - pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes; - - if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushNL, - &UnsignedLongNumber, - pArcTopHeader->nElemCount)) - { - MMCPLDebug("MiraMon", - "Error in MMAppendIntegerDependingOnVersion()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - // 8bytes alignment - nOffsetTmp = pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes; - MMGetOffsetAlignedTo8(&nOffsetTmp); - if (nOffsetTmp != pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes) - { - pFlushNL->SizeOfBlockToBeSaved = - (size_t)(nOffsetTmp - - (pFlushNL->TotalSavedBytes + pFlushNL->nNumBytes)); - pFlushNL->pBlockToBeSaved = (void *)nullptr; - if (MMAppendBlockToBuffer(pFlushNL)) - { - MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - } - if (MMAddNodeRecordToMMDB(hMiraMonLayer, - pNodeTopHeader->nElemCount + 1, - pCurrentNodeHeaderPlus1)) - { - MMCPLDebug("MiraMon", "Error in MMAddNodeRecordToMMDB()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - } - - // 3D stuff - if (hMiraMonLayer->TopHeader.bIs3d && pZDesc) - { - pZDesc[pArcTopHeader->nElemCount].dfBBminz = - STATISTICAL_UNDEF_VALUE; - pZDesc[pArcTopHeader->nElemCount].dfBBmaxz = - -STATISTICAL_UNDEF_VALUE; - for (nIVertice = 0; nIVertice < pCurrentArcHeader->nElemCount; - nIVertice++, pZ++) - { - pFlushZL->SizeOfBlockToBeSaved = sizeof(*pZ); - pFlushZL->pBlockToBeSaved = (void *)pZ; - if (MMAppendBlockToBuffer(pFlushZL)) - { - MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - if (pZDesc[pArcTopHeader->nElemCount].dfBBminz > *pZ) - pZDesc[pArcTopHeader->nElemCount].dfBBminz = *pZ; - if (pZDesc[pArcTopHeader->nElemCount].dfBBmaxz < *pZ) - pZDesc[pArcTopHeader->nElemCount].dfBBmaxz = *pZ; - } - pZDesc[pArcTopHeader->nElemCount].nZCount = 1; - if (hMiraMonLayer->TopHeader.nElemCount == 0) - pZDesc[hMiraMonLayer->TopHeader.nElemCount].nOffsetZ = 0; - else - pZDesc[hMiraMonLayer->TopHeader.nElemCount].nOffsetZ = - pZDesc[hMiraMonLayer->TopHeader.nElemCount - 1].nOffsetZ + - sizeof(*pZ); - } - - // Exclusive polygon stuff - if (hMiraMonLayer->bIsPolygon && pCurrentPolHeader) - { - // PS SECTION - if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushPS, - &UnsignedLongNumber, 0)) - { - MMCPLDebug("MiraMon", - "Error in MMAppendIntegerDependingOnVersion()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - if (MMAppendIntegerDependingOnVersion( - hMiraMonLayer, pFlushPS, &UnsignedLongNumber, - hMiraMonLayer->TopHeader.nElemCount)) - { - MMCPLDebug("MiraMon", - "Error in MMAppendIntegerDependingOnVersion()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - // PAL SECTION - // Vertices of rings defining - // holes in polygons are in a counterclockwise direction. - // Holes are at the end of all external rings that contain the holes!! - if (VFG & MM_EXTERIOR_ARC_SIDE) - nExternalRingsCount++; - - pCurrentPolHeader->nArcsCount = - (MM_POLYGON_ARCS_COUNT)hMMFeature->nNRings; - pCurrentPolHeader->nExternalRingsCount = nExternalRingsCount; - pCurrentPolHeader->nRingsCount = hMMFeature->nNRings; - if (nIPart == 0) - { - pCurrentPolHeader->nOffset = - pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes; - } - - if (nIPart == hMMFeature->nNRings - 1) - pCurrentPolHeader->dfArea /= 2; - - pFlushPAL->SizeOfBlockToBeSaved = 1; - pFlushPAL->pBlockToBeSaved = (void *)&VFG; - if (MMAppendBlockToBuffer(pFlushPAL)) - { - MMCPLDebug("MiraMon", "Error in MMAppendBlockToBuffer()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - if (MMAppendIntegerDependingOnVersion(hMiraMonLayer, pFlushPAL, - &UnsignedLongNumber, - pArcTopHeader->nElemCount)) - { - MMCPLDebug("MiraMon", - "Error in MMAppendIntegerDependingOnVersion()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - // 8bytes alignment - if (nIPart == hMMFeature->nNRings - 1) - { - nOffsetTmp = pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes; - MMGetOffsetAlignedTo8(&nOffsetTmp); - - if (nOffsetTmp != - pFlushPAL->TotalSavedBytes + pFlushPAL->nNumBytes) - { - pFlushPAL->SizeOfBlockToBeSaved = - (size_t)(nOffsetTmp - (pFlushPAL->TotalSavedBytes + - pFlushPAL->nNumBytes)); - pFlushPAL->pBlockToBeSaved = (void *)nullptr; - if (MMAppendBlockToBuffer(pFlushPAL)) - { - MMCPLDebug("MiraMon", - "Error in MMAppendBlockToBuffer()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - } - } - - MMUpdateBoundingBox(&pCurrentPolHeader->dfBB, - &pCurrentArcHeader->dfBB); - pCurrentPolHeader->dfPerimeter += pCurrentArcHeader->dfLenght; - } - } - - // Updating element count and if the polygon is multipart. - // MiraMon does not accept multipoints or multilines, only multipolygons. - if (hMiraMonLayer->bIsPolygon) - { - if (MMAddPolygonRecordToMMDB(hMiraMonLayer, hMMFeature, - hMiraMonLayer->TopHeader.nElemCount, - nPolVertices, pCurrentPolHeader)) - { - MMCPLDebug("MiraMon", "Error in MMAddPolygonRecordToMMDB()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - hMiraMonLayer->TopHeader.nElemCount++; - - if (nExternalRingsCount > 1) - hMiraMonLayer->TopHeader.bIsMultipolygon = TRUE; - } - - return MM_CONTINUE_WRITING_FEATURES; -} // End of de MMCreateFeaturePolOrArc() - -// Creates a MiraMon DBF record when not associated with a geometric feature. -static int MMCreateRecordDBF(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature) -{ - int result; - - if (!hMiraMonLayer) - return MM_FATAL_ERROR_WRITING_FEATURES; - - if (hMiraMonLayer->TopHeader.nElemCount == 0) - { - if (MMCreateMMDB(hMiraMonLayer)) - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - result = MMAddDBFRecordToMMDB(hMiraMonLayer, hMMFeature); - if (result == MM_FATAL_ERROR_WRITING_FEATURES || - result == MM_STOP_WRITING_FEATURES) - return result; - - // Everything OK. - return MM_CONTINUE_WRITING_FEATURES; -} // End of de MMCreateRecordDBF() - -// Creates a MiraMon point feature. -static int MMCreateFeaturePoint(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature) -{ - double *pZ = nullptr; - struct MM_POINT_2D *pCoord; - MM_POLYGON_RINGS_COUNT nIPart; - MM_N_VERTICES_TYPE nIVertice, nCoord; - struct MM_ZD *pZDescription = nullptr; - MM_INTERNAL_FID nElemCount; - int result; - - if (!hMiraMonLayer) - return MM_FATAL_ERROR_WRITING_FEATURES; - - if (!hMMFeature) - return MM_STOP_WRITING_FEATURES; - - if (hMiraMonLayer->TopHeader.bIs3d) - pZ = hMMFeature->pZCoord; - - nElemCount = hMiraMonLayer->TopHeader.nElemCount; - for (nIPart = 0, pCoord = hMMFeature->pCoord; nIPart < hMMFeature->nNRings; - nIPart++, nElemCount++) - { - nCoord = hMMFeature->pNCoordRing[nIPart]; - - // Checking if its possible continue writing the file due - // to version limitations. - if (MMCheckVersionForFID(hMiraMonLayer, - hMiraMonLayer->TopHeader.nElemCount + nCoord)) - return MM_STOP_WRITING_FEATURES; - - if (hMiraMonLayer->TopHeader.bIs3d) - { - if (nElemCount == 0) - { - if (MMCheckVersionFor3DOffset(hMiraMonLayer, 0, nElemCount + 1)) - return MM_STOP_WRITING_FEATURES; - } - else - { - pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription; - if (MMCheckVersionFor3DOffset( - hMiraMonLayer, - pZDescription[nElemCount - 1].nOffsetZ + sizeof(*pZ), - nElemCount + 1)) - return MM_STOP_WRITING_FEATURES; - } - } - - // Doing real job - // Memory issues - if (hMiraMonLayer->TopHeader.bIs3d && pZ) - { - if (MMResizeZSectionDescrPointer( - &hMiraMonLayer->MMPoint.pZSection.pZDescription, - &hMiraMonLayer->MMPoint.pZSection.nMaxZDescription, - nElemCount, MM_INCR_NUMBER_OF_POINTS, 0)) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMCreateFeaturePoint())"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - pZDescription = hMiraMonLayer->MMPoint.pZSection.pZDescription; - - pZDescription[nElemCount].dfBBminz = *pZ; - pZDescription[nElemCount].dfBBmaxz = *pZ; - pZDescription[nElemCount].nZCount = 1; - if (nElemCount == 0) - pZDescription[nElemCount].nOffsetZ = 0; - else - pZDescription[nElemCount].nOffsetZ = - pZDescription[nElemCount - 1].nOffsetZ + sizeof(*pZ); - } - - // Flush settings - hMiraMonLayer->MMPoint.FlushTL.pBlockWhereToSaveOrRead = - (void *)hMiraMonLayer->MMPoint.pTL; - if (hMiraMonLayer->TopHeader.bIs3d) - hMiraMonLayer->MMPoint.pZSection.FlushZL.pBlockWhereToSaveOrRead = - (void *)hMiraMonLayer->MMPoint.pZSection.pZL; - - // Dump point or points (MiraMon does not have multiple points) - for (nIVertice = 0; nIVertice < nCoord; nIVertice++, pCoord++, pZ++) - { - // Updating the bounding box of the layer - MMUpdateBoundingBoxXY(&hMiraMonLayer->TopHeader.hBB, pCoord); - - // Adding the point at the memory block - hMiraMonLayer->MMPoint.FlushTL.SizeOfBlockToBeSaved = - sizeof(pCoord->dfX); - hMiraMonLayer->MMPoint.FlushTL.pBlockToBeSaved = - (void *)&pCoord->dfX; - if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL)) - return MM_FATAL_ERROR_WRITING_FEATURES; - hMiraMonLayer->MMPoint.FlushTL.pBlockToBeSaved = - (void *)&pCoord->dfY; - if (MMAppendBlockToBuffer(&hMiraMonLayer->MMPoint.FlushTL)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Adding the 3D part, if exists, at the memory block - if (hMiraMonLayer->TopHeader.bIs3d && pZ) - { - hMiraMonLayer->MMPoint.pZSection.FlushZL.SizeOfBlockToBeSaved = - sizeof(*pZ); - hMiraMonLayer->MMPoint.pZSection.FlushZL.pBlockToBeSaved = - (void *)pZ; - if (MMAppendBlockToBuffer( - &hMiraMonLayer->MMPoint.pZSection.FlushZL)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - if (pZDescription[nElemCount].dfBBminz > *pZ) - pZDescription[nElemCount].dfBBminz = *pZ; - if (pZDescription[nElemCount].dfBBmaxz < *pZ) - pZDescription[nElemCount].dfBBmaxz = *pZ; - - if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz > *pZ) - hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBminz = *pZ; - if (hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz < *pZ) - hMiraMonLayer->MMPoint.pZSection.ZHeader.dfBBmaxz = *pZ; - } - } - - if (hMiraMonLayer->TopHeader.nElemCount == 0) - { - if (MMCreateMMDB(hMiraMonLayer)) - return MM_FATAL_ERROR_WRITING_FEATURES; - } - - result = MMAddPointRecordToMMDB(hMiraMonLayer, hMMFeature, nElemCount); - if (result == MM_FATAL_ERROR_WRITING_FEATURES || - result == MM_STOP_WRITING_FEATURES) - return result; - } - // Updating nElemCount at the header of the layer - hMiraMonLayer->TopHeader.nElemCount = nElemCount; - - // Everything OK. - return MM_CONTINUE_WRITING_FEATURES; -} // End of de MMCreateFeaturePoint() - -// Checks whether a given Feature ID (FID) exceeds the maximum allowed -// index for 2 GB vectors in a specific MiraMon layer. -int MMCheckVersionForFID(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_INTERNAL_FID FID) -{ - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION) - return 0; - - if (FID >= MAXIMUM_OBJECT_INDEX_IN_2GB_VECTORS) - return 1; - return 0; -} - -// Checks whether a given offset exceeds the maximum allowed -// index for 2 GB vectors in a specific MiraMon layer. -int MMCheckVersionOffset(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET OffsetToCheck) -{ - if (!hMiraMonLayer) - return 1; - - // Checking if the final version is 1.1 or 2.0 - if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION) - return 0; - - // User decided that if necessary, output version can be 2.0 - if (OffsetToCheck < MAXIMUM_OFFSET_IN_2GB_VECTORS) - return 0; - - return 1; -} - -// Checks whether a given offset in 3D section exceeds the maximum allowed -// index for 2 GB vectors in a specific MiraMon layer. -int MMCheckVersionFor3DOffset(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_FILE_OFFSET nOffset, - MM_INTERNAL_FID nElemCount) -{ - MM_FILE_OFFSET LastOffset; - - if (!hMiraMonLayer) - return 1; - - // Checking if the final version is 1.1 or 2.0 - if (hMiraMonLayer->LayerVersion != MM_32BITS_VERSION) - return 0; - - // User decided that if necessary, output version can be 2.0 - LastOffset = nOffset + MM_HEADER_SIZE_32_BITS + nElemCount * MM_SIZE_OF_TL; - - LastOffset += MM_SIZE_OF_ZH; - LastOffset += nElemCount * MM_SIZE_OF_ZD_32_BITS; - - if (LastOffset < MAXIMUM_OFFSET_IN_2GB_VECTORS) - return 0; - - return 1; -} - -// Adds a feature in a MiraMon layer. -int MMAddFeature(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMiraMonFeature) -{ - int re; - MM_INTERNAL_FID previusFID = 0; - - if (!hMiraMonLayer) - return MM_FATAL_ERROR_WRITING_FEATURES; - - if (!hMiraMonLayer->bIsBeenInit) - { - if (MMInitLayerByType(hMiraMonLayer)) - { - MMCPLDebug("MiraMon", "Error in MMInitLayerByType()"); - return MM_FATAL_ERROR_WRITING_FEATURES; - } - hMiraMonLayer->bIsBeenInit = 1; - } - - if (hMiraMonFeature) - previusFID = hMiraMonLayer->TopHeader.nElemCount; - - if (hMiraMonLayer->bIsPoint) - { - re = LOG_ACTION(MMCreateFeaturePoint(hMiraMonLayer, hMiraMonFeature)); - if (hMiraMonFeature) - { - hMiraMonFeature->nReadFeatures = - hMiraMonLayer->TopHeader.nElemCount - previusFID; - } - return re; - } - if (hMiraMonLayer->bIsArc || hMiraMonLayer->bIsPolygon) - { - re = - LOG_ACTION(MMCreateFeaturePolOrArc(hMiraMonLayer, hMiraMonFeature)); - if (hMiraMonFeature) - { - hMiraMonFeature->nReadFeatures = - hMiraMonLayer->TopHeader.nElemCount - previusFID; - } - return re; - } - if (hMiraMonLayer->bIsDBF) - { - // Adding a record to DBF file - re = LOG_ACTION(MMCreateRecordDBF(hMiraMonLayer, hMiraMonFeature)); - if (hMiraMonFeature) - { - hMiraMonFeature->nReadFeatures = - hMiraMonLayer->TopHeader.nElemCount - previusFID; - } - return re; - } - - return MM_CONTINUE_WRITING_FEATURES; -} - -/* -------------------------------------------------------------------- */ -/* Tools used by MiraMon. */ -/* -------------------------------------------------------------------- */ - -void MMInitBoundingBox(struct MMBoundingBox *dfBB) -{ - if (!dfBB) - return; - dfBB->dfMinX = STATISTICAL_UNDEF_VALUE; - dfBB->dfMaxX = -STATISTICAL_UNDEF_VALUE; - dfBB->dfMinY = STATISTICAL_UNDEF_VALUE; - dfBB->dfMaxY = -STATISTICAL_UNDEF_VALUE; -} - -void MMUpdateBoundingBox(struct MMBoundingBox *dfBBToBeAct, - struct MMBoundingBox *dfBBWithData) -{ - if (!dfBBToBeAct) - return; - - if (dfBBToBeAct->dfMinX > dfBBWithData->dfMinX) - dfBBToBeAct->dfMinX = dfBBWithData->dfMinX; - - if (dfBBToBeAct->dfMinY > dfBBWithData->dfMinY) - dfBBToBeAct->dfMinY = dfBBWithData->dfMinY; - - if (dfBBToBeAct->dfMaxX < dfBBWithData->dfMaxX) - dfBBToBeAct->dfMaxX = dfBBWithData->dfMaxX; - - if (dfBBToBeAct->dfMaxY < dfBBWithData->dfMaxY) - dfBBToBeAct->dfMaxY = dfBBWithData->dfMaxY; -} - -void MMUpdateBoundingBoxXY(struct MMBoundingBox *dfBB, - struct MM_POINT_2D *pCoord) -{ - if (!pCoord) - return; - - if (pCoord->dfX < dfBB->dfMinX) - dfBB->dfMinX = pCoord->dfX; - - if (pCoord->dfY < dfBB->dfMinY) - dfBB->dfMinY = pCoord->dfY; - - if (pCoord->dfX > dfBB->dfMaxX) - dfBB->dfMaxX = pCoord->dfX; - - if (pCoord->dfY > dfBB->dfMaxY) - dfBB->dfMaxY = pCoord->dfY; -} - -/* -------------------------------------------------------------------- */ -/* Resize structures for reuse */ -/* -------------------------------------------------------------------- */ -int MMResizeMiraMonFieldValue(struct MiraMonFieldValue **pFieldValue, - MM_EXT_DBF_N_MULTIPLE_RECORDS *nMax, - MM_EXT_DBF_N_MULTIPLE_RECORDS nNum, - MM_EXT_DBF_N_MULTIPLE_RECORDS nIncr, - MM_EXT_DBF_N_MULTIPLE_RECORDS nProposedMax) -{ - MM_EXT_DBF_N_MULTIPLE_RECORDS nPrevMax; - - if (nNum < *nMax) - return 0; - - nPrevMax = *nMax; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pFieldValue) = realloc_function( - *pFieldValue, (size_t)*nMax * sizeof(**pFieldValue))) == nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeMiraMonFieldValue())"); - return 1; - } - - memset((*pFieldValue) + nPrevMax, 0, - (size_t)(*nMax - nPrevMax) * sizeof(**pFieldValue)); - return 0; -} - -int MMResizeMiraMonPolygonArcs(struct MM_PAL_MEM **pFID, - MM_POLYGON_ARCS_COUNT *nMax, - MM_POLYGON_ARCS_COUNT nNum, - MM_POLYGON_ARCS_COUNT nIncr, - MM_POLYGON_ARCS_COUNT nProposedMax) -{ - MM_POLYGON_ARCS_COUNT nPrevMax; - - if (nNum < *nMax) - return 0; - - nPrevMax = *nMax; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pFID) = realloc_function(*pFID, (size_t)*nMax * sizeof(**pFID))) == - nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeMiraMonPolygonArcs())"); - return 1; - } - - memset((*pFID) + nPrevMax, 0, (size_t)(*nMax - nPrevMax) * sizeof(**pFID)); - return 0; -} - -int MMResizeMiraMonRecord(struct MiraMonRecord **pMiraMonRecord, - MM_EXT_DBF_N_MULTIPLE_RECORDS *nMax, - MM_EXT_DBF_N_MULTIPLE_RECORDS nNum, - MM_EXT_DBF_N_MULTIPLE_RECORDS nIncr, - MM_EXT_DBF_N_MULTIPLE_RECORDS nProposedMax) -{ - MM_EXT_DBF_N_MULTIPLE_RECORDS nPrevMax; - - if (nNum < *nMax) - return 0; - - nPrevMax = *nMax; - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pMiraMonRecord) = realloc_function( - *pMiraMonRecord, (size_t)*nMax * sizeof(**pMiraMonRecord))) == - nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeMiraMonRecord())"); - return 1; - } - - memset((*pMiraMonRecord) + nPrevMax, 0, - (size_t)(*nMax - nPrevMax) * sizeof(**pMiraMonRecord)); - return 0; -} - -int MMResizeZSectionDescrPointer(struct MM_ZD **pZDescription, GUInt64 *nMax, - GUInt64 nNum, GUInt64 nIncr, - GUInt64 nProposedMax) -{ - if (nNum < *nMax) - return 0; - - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pZDescription) = realloc_function( - *pZDescription, (size_t)*nMax * sizeof(**pZDescription))) == - nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeZSectionDescrPointer())"); - return 1; - } - return 0; -} - -int MMResizeNodeHeaderPointer(struct MM_NH **pNodeHeader, GUInt64 *nMax, - GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax) -{ - if (nNum < *nMax) - return 0; - - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pNodeHeader) = realloc_function( - *pNodeHeader, (size_t)*nMax * sizeof(**pNodeHeader))) == nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeNodeHeaderPointer())"); - return 1; - } - return 0; -} - -int MMResizeArcHeaderPointer(struct MM_AH **pArcHeader, GUInt64 *nMax, - GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax) -{ - if (nNum < *nMax) - return 0; - - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pArcHeader) = realloc_function( - *pArcHeader, (size_t)*nMax * sizeof(**pArcHeader))) == nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeArcHeaderPointer())"); - return 1; - } - return 0; -} - -int MMResizePolHeaderPointer(struct MM_PH **pPolHeader, GUInt64 *nMax, - GUInt64 nNum, GUInt64 nIncr, GUInt64 nProposedMax) -{ - if (nNum < *nMax) - return 0; - - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pPolHeader) = realloc_function( - *pPolHeader, (size_t)*nMax * sizeof(**pPolHeader))) == nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizePolHeaderPointer())"); - return 1; - } - return 0; -} - -int MMResize_MM_N_VERTICES_TYPE_Pointer(MM_N_VERTICES_TYPE **pVrt, - MM_N_VERTICES_TYPE *nMax, - MM_N_VERTICES_TYPE nNum, - MM_N_VERTICES_TYPE nIncr, - MM_N_VERTICES_TYPE nProposedMax) -{ - if (nNum < *nMax) - return 0; - - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pVrt) = realloc_function(*pVrt, (size_t)*nMax * sizeof(**pVrt))) == - nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResize_MM_N_VERTICES_TYPE_Pointer())"); - return 1; - } - return 0; -} - -int MMResizeVFGPointer(char **pInt, MM_INTERNAL_FID *nMax, MM_INTERNAL_FID nNum, - MM_INTERNAL_FID nIncr, MM_INTERNAL_FID nProposedMax) -{ - if (nNum < *nMax) - return 0; - - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pInt) = realloc_function(*pInt, (size_t)*nMax * sizeof(**pInt))) == - nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeVFGPointer())"); - return 1; - } - return 0; -} - -int MMResizeMM_POINT2DPointer(struct MM_POINT_2D **pPoint2D, - MM_N_VERTICES_TYPE *nMax, MM_N_VERTICES_TYPE nNum, - MM_N_VERTICES_TYPE nIncr, - MM_N_VERTICES_TYPE nProposedMax) -{ - if (nNum < *nMax) - return 0; - - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pPoint2D) = realloc_function( - *pPoint2D, (size_t)*nMax * sizeof(**pPoint2D))) == nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeMM_POINT2DPointer())"); - return 1; - } - return 0; -} - -int MMResizeDoublePointer(MM_COORD_TYPE **pDouble, MM_N_VERTICES_TYPE *nMax, - MM_N_VERTICES_TYPE nNum, MM_N_VERTICES_TYPE nIncr, - MM_N_VERTICES_TYPE nProposedMax) -{ - if (nNum < *nMax) - return 0; - - *nMax = max_function(nNum + nIncr, nProposedMax); - if (((*pDouble) = realloc_function( - *pDouble, (size_t)*nMax * sizeof(**pDouble))) == nullptr) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeDoublePointer())"); - return 1; - } - return 0; -} - -int MMResizeStringToOperateIfNeeded(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_EXT_DBF_N_FIELDS nNewSize) -{ - if (!hMiraMonLayer) - return 1; - - if (nNewSize >= hMiraMonLayer->nNumStringToOperate) - { - char *p; - if (MMCheckSize_t(nNewSize, 1)) - return 1; - p = (char *)calloc_function((size_t)nNewSize); - if (!p) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMResizeStringToOperateIfNeeded())"); - return 1; - } - hMiraMonLayer->szStringToOperate = p; - hMiraMonLayer->nNumStringToOperate = nNewSize; - } - return 0; -} - -// Checks if a string is empty -int MMIsEmptyString(const char *string) -{ - char *ptr; - - for (ptr = (char *)string; *ptr; ptr++) - if (*ptr != ' ' && *ptr != '\t') - return 0; - - return 1; -} - -/* -------------------------------------------------------------------- */ -/* Metadata Functions */ -/* -------------------------------------------------------------------- */ - -// Returns the value of an INI file. Used to read MiraMon metadata -char *MMReturnValueFromSectionINIFile(const char *filename, const char *section, - const char *key) -{ - char *value = nullptr; - char line[16000]; - char *section_header = nullptr; - size_t key_len = 0; - size_t bytes_read; - char *pszString; - char *start; - char *end; - - FILE_TYPE *file = fopen_function(filename, "rb"); - if (file == nullptr) - { - sprintf(local_message, "Cannot open INI file %s.", filename); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return nullptr; - } - - if (key) - key_len = strlen(key); - - while ((bytes_read = fread_function(line, 1, sizeof(line), file)) > 0) - { - // As MiraMon is written in ANSI convertion to UTF-8 must be done - line[bytes_read - 1] = '\0'; - pszString = CPLRecode_function(line, CPL_ENC_ISO8859_1, CPL_ENC_UTF8); - MM_strnzcpy(line, pszString, 16000); - CPLFree_function(pszString); - - // Iterate through the read buffer - start = line; - end = line + bytes_read; - while (start < end) - { - if (!start) - return nullptr; - - // Skip comments and empty lines - if (*start == ';' || *start == '#' || *start == '\n' || - *start == '\r') - { - while (start < end && *start != '\n') - start++; - start++; // Move to next line - continue; - } - - if (!start) - return nullptr; - - // Check for section header - if (*start == '[') - { - char *section_end = strchr(start, ']'); - if (section_end != nullptr) - { - *section_end = '\0'; // Terminate the string at ']' - if (section_header) - free_function(section_header); - section_header = - strdup_function(start + 1); // Skip the '[' - } - start = section_end + 1; - continue; - } - - if (!start) - return nullptr; - - if (key) - { - // If the current line belongs to the desired section - if (section_header != nullptr && - strcmp(section_header, section) == 0) - { - // Check if the line contains the desired key - if (strncmp(start, key, key_len) == 0 && - start[key_len] == '=') - { - // Extract the value - char *value_start = start + key_len + 1; - char *value_end = strstr(value_start, "\r\n"); - if (value_end != nullptr) - { - *value_end = - '\0'; // Terminate the string at newline character if found - } - else - { - value_end = strstr(value_start, "\n"); - if (value_end != nullptr) - { - *value_end = - '\0'; // Terminate the string at newline character if found - } - else - { - value_end = strstr(value_start, "\r"); - if (value_end != nullptr) - { - *value_end = - '\0'; // Terminate the string at newline character if found - } - } - } - - value = strdup_function(value_start); - fclose_function(file); - free_function(section_header); // Free allocated memory - return value; - } - } - } - else - { - value = section_header; // Freed out - fclose_function(file); - return value; - } - - // Move to the next line - while (start < end && *start != '\n') - start++; - start++; - } - } - - if (section_header) - free_function(section_header); // Free allocated memory - fclose_function(file); - return value; -} - -// Retrieves EPSG codes from a CSV file based on provided geodetic identifiers. -int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult, - MM_BYTE direction) -{ - static char aEPSGCodeSRS[MM_MAX_ID_SNY]; - char *aMMIDDBFFile = nullptr; //m_idofic.dbf - FILE *pfMMSRS; - size_t nLong; - int nLongBuffer = 5000; - char *pszBuffer = calloc_function(nLongBuffer); - char *id_geodes, *psidgeodes, *epsg; - - if (!pszBuffer) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMReturnCodeFromMM_m_idofic())"); - return 1; - } - if (!pMMSRS_or_pSRS) - { - free_function(pszBuffer); - return 1; - } - memset(aEPSGCodeSRS, '\0', sizeof(*aEPSGCodeSRS)); - -#ifdef GDAL_COMPILATION - aMMIDDBFFile = strdup_function(CPLFindFile("gdal", "MM_m_idofic.csv")); -#else - { - char temp_file[MM_CPL_PATH_BUF_SIZE]; - MuntaPath(DirectoriPrograma, strcpy(temp_file, "m_idofic.csv"), TRUE); - aMMIDDBFFile = strdup_function(temp_file); - } -#endif - - if (!aMMIDDBFFile) - { - free_function(pszBuffer); - MMCPLError(CE_Failure, CPLE_OpenFailed, - "Error opening data\\MM_m_idofic.csv.\n"); - return 1; - } - - // Opening the file with SRS information - if (nullptr == (pfMMSRS = fopen(aMMIDDBFFile, "r"))) - { - free_function(aMMIDDBFFile); - free_function(pszBuffer); - MMCPLError(CE_Failure, CPLE_OpenFailed, - "Error opening data\\MM_m_idofic.csv.\n"); - return 1; - } - free_function(aMMIDDBFFile); - - // Checking the header of the csv file - memset(pszBuffer, 0, nLongBuffer); - if (!fgets(pszBuffer, nLongBuffer, pfMMSRS)) - { - free_function(pszBuffer); - fclose(pfMMSRS); - MMCPLError(CE_Failure, CPLE_NotSupported, - "Wrong format in data\\MM_m_idofic.csv.\n"); - return 1; - } - id_geodes = strstr(pszBuffer, "ID_GEODES"); - if (!id_geodes) - { - free_function(pszBuffer); - fclose(pfMMSRS); - MMCPLError(CE_Failure, CPLE_NotSupported, - "Wrong format in data\\MM_m_idofic.csv.\n"); - return 1; - } - id_geodes[strlen("ID_GEODES")] = '\0'; - psidgeodes = strstr(pszBuffer, "PSIDGEODES"); - if (!psidgeodes) - { - free_function(pszBuffer); - fclose(pfMMSRS); - MMCPLError(CE_Failure, CPLE_NotSupported, - "Wrong format in data\\MM_m_idofic.csv.\n"); - return 1; - } - psidgeodes[strlen("PSIDGEODES")] = '\0'; - - // Is PSIDGEODES in first place? - if (strncmp(pszBuffer, psidgeodes, strlen("PSIDGEODES"))) - { - free_function(pszBuffer); - fclose(pfMMSRS); - MMCPLError(CE_Failure, CPLE_NotSupported, - "Wrong format in data\\MM_m_idofic.csv.\n"); - return 1; - } - // Is ID_GEODES after PSIDGEODES? - if (strncmp(pszBuffer + strlen("PSIDGEODES") + 1, "ID_GEODES", - strlen("ID_GEODES"))) - { - free_function(pszBuffer); - fclose(pfMMSRS); - MMCPLError(CE_Failure, CPLE_NotSupported, - "Wrong format in data\\MM_m_idofic.csv.\n"); - return 1; - } - - // Looking for the information - while (fgets(pszBuffer, nLongBuffer, pfMMSRS)) - { - id_geodes = strstr(pszBuffer, ";"); - if (!id_geodes || (id_geodes + 1)[0] == '\n') - { - free_function(pszBuffer); - fclose(pfMMSRS); - MMCPLError(CE_Failure, CPLE_NotSupported, - "Wrong format in data\\MM_m_idofic.csv.\n"); - return 1; - } - - psidgeodes = strstr(id_geodes + 1, ";"); - if (!psidgeodes) - { - free_function(pszBuffer); - fclose(pfMMSRS); - MMCPLError(CE_Failure, CPLE_NotSupported, - "Wrong format in data\\MM_m_idofic.csv.\n"); - return 1; - } - - id_geodes[(ptrdiff_t)psidgeodes - (ptrdiff_t)id_geodes] = '\0'; - psidgeodes = pszBuffer; - psidgeodes[(ptrdiff_t)id_geodes - (ptrdiff_t)psidgeodes] = '\0'; - id_geodes++; - - if (direction == EPSG_FROM_MMSRS) - { - // I have pMMSRS and I want pSRS - if (strcmp(pMMSRS_or_pSRS, id_geodes)) - continue; - - epsg = strstr(psidgeodes, "EPSG:"); - nLong = strlen("EPSG:"); - if (epsg && !strncmp(epsg, psidgeodes, nLong)) - { - if (epsg[nLong] != '\0') - { - strcpy(szResult, epsg + nLong); - free_function(pszBuffer); - fclose(pfMMSRS); - return 0; // found - } - else - { - free_function(pszBuffer); - fclose(pfMMSRS); - *szResult = '\0'; - return 1; // not found - } - } - } - else - { - // I have pSRS and I want pMMSRS - epsg = strstr(psidgeodes, "EPSG:"); - nLong = strlen("EPSG:"); - if (epsg && !strncmp(epsg, psidgeodes, nLong)) - { - if (epsg[nLong] != '\0') - { - if (!strcmp(pMMSRS_or_pSRS, epsg + nLong)) - { - strcpy(szResult, id_geodes); - free_function(pszBuffer); - fclose(pfMMSRS); - return 0; // found - } - } - } - } - } - - free_function(pszBuffer); - fclose(pfMMSRS); - return 1; // not found -} - -#define LineReturn "\r\n" - -// Generates an idientifier that REL 4 MiraMon metadata needs. -static char *MMGenerateFileIdentifierFromMetadataFileName(char *pMMFN) -{ - static char aCharRand[8], - aCharset[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - int i, len_charset; - static char aFileIdentifier[MM_MAX_LEN_LAYER_IDENTIFIER]; - - memset(aFileIdentifier, '\0', MM_MAX_LEN_LAYER_IDENTIFIER); - - aCharRand[0] = '_'; - len_charset = (int)strlen(aCharset); - for (i = 1; i < 7; i++) - aCharRand[i] = aCharset[rand() % (len_charset - 1)]; - aCharRand[7] = '\0'; - MM_strnzcpy(aFileIdentifier, pMMFN, MM_MAX_LEN_LAYER_IDENTIFIER - 7); - strcat(aFileIdentifier, aCharRand); - return aFileIdentifier; -} - -// Converts a string from UTF-8 to ANSI to be written in a REL 4 file -static void -MMWrite_ANSI_MetadataKeyDescriptor(struct MiraMonVectorMetaData *hMMMD, - FILE_TYPE *pF, const char *pszEng, - const char *pszCat, const char *pszEsp) -{ - char *pszString = nullptr; - - switch (hMMMD->nMMLanguage) - { - case MM_CAT_LANGUAGE: - pszString = - CPLRecode_function(pszCat, CPL_ENC_UTF8, CPL_ENC_ISO8859_1); - break; - case MM_SPA_LANGUAGE: - pszString = - CPLRecode_function(pszEsp, CPL_ENC_UTF8, CPL_ENC_ISO8859_1); - break; - default: - case MM_ENG_LANGUAGE: - pszString = - CPLRecode_function(pszEng, CPL_ENC_UTF8, CPL_ENC_ISO8859_1); - break; - } - if (pszString) - { - fprintf_function(pF, "%s", KEY_descriptor); - fprintf_function(pF, "="); - fprintf_function(pF, "%s", pszString); - fprintf_function(pF, "%s", LineReturn); - CPLFree_function(pszString); - } -} - -/* - Writes a MiraMon REL 4 metadata file. Next sections are included: - VERSION, METADADES, IDENTIFICATION, EXTENT, OVERVIEW, - TAULA_PRINCIPAL and GEOMETRIA_I_TOPOLOGIA - - Please, consult the meaning of all them at: - https://www.miramon.cat/help/eng/GeMPlus/ClausREL.htm -*/ -static int MMWriteMetadataFile(struct MiraMonVectorMetaData *hMMMD) -{ - char aMessage[MM_MESSAGE_LENGHT], - aFileIdentifier[MM_MAX_LEN_LAYER_IDENTIFIER], aMMIDSRS[MM_MAX_ID_SNY]; - MM_EXT_DBF_N_FIELDS nIField; - FILE_TYPE *pF; - time_t currentTime; - struct tm *pLocalTime; - char aTimeString[200]; - - if (!hMMMD->aLayerName) - return 0; - - if (nullptr == (pF = fopen_function(hMMMD->aLayerName, "wb"))) - { - sprintf(local_message, "The file %s must exist.", hMMMD->aLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - - // Writing MiraMon version section - fprintf_function(pF, "[%s]" LineReturn, SECTION_VERSIO); - - fprintf_function(pF, "%s=%u" LineReturn, KEY_Vers, (unsigned)MM_VERS); - fprintf_function(pF, "%s=%u" LineReturn, KEY_SubVers, (unsigned)MM_SUBVERS); - - fprintf_function(pF, "%s=%u" LineReturn, KEY_VersMetaDades, - (unsigned)MM_VERS_METADADES); - fprintf_function(pF, "%s=%u" LineReturn, KEY_SubVersMetaDades, - (unsigned)MM_SUBVERS_METADADES); - - // Writing METADADES section - fprintf_function(pF, "\r\n[%s]" LineReturn, SECTION_METADADES); - strcpy(aMessage, hMMMD->aLayerName); - strcpy(aFileIdentifier, - MMGenerateFileIdentifierFromMetadataFileName(aMessage)); - fprintf_function(pF, "%s=%s" LineReturn, KEY_FileIdentifier, - aFileIdentifier); - fprintf_function(pF, "%s=%s" LineReturn, KEY_language, KEY_Value_eng); - fprintf_function(pF, "%s=%s" LineReturn, KEY_MDIdiom, KEY_Value_eng); - fprintf_function(pF, "%s=%s" LineReturn, KEY_characterSet, - KEY_Value_characterSet); - - // Writing IDENTIFICATION section - fprintf_function(pF, LineReturn "[%s]" LineReturn, SECTION_IDENTIFICATION); - fprintf_function(pF, "%s=%s" LineReturn, KEY_code, aFileIdentifier); - fprintf_function(pF, "%s=" LineReturn, KEY_codeSpace); - if (hMMMD->szLayerTitle && !MMIsEmptyString(hMMMD->szLayerTitle)) - { - if (hMMMD->ePlainLT == MM_LayerType_Point) - fprintf_function(pF, "%s=%s (pnt)" LineReturn, KEY_DatasetTitle, - hMMMD->szLayerTitle); - if (hMMMD->ePlainLT == MM_LayerType_Arc) - fprintf_function(pF, "%s=%s (arc)" LineReturn, KEY_DatasetTitle, - hMMMD->szLayerTitle); - if (hMMMD->ePlainLT == MM_LayerType_Pol) - fprintf_function(pF, "%s=%s (pol)" LineReturn, KEY_DatasetTitle, - hMMMD->szLayerTitle); - } - fprintf_function(pF, "%s=%s" LineReturn, KEY_language, KEY_Value_eng); - - if (hMMMD->ePlainLT != MM_LayerType_Node) - { - if (hMMMD->pSRS && hMMMD->ePlainLT != MM_LayerType_Pol) - { - fprintf_function(pF, LineReturn "[%s:%s]" LineReturn, - SECTION_SPATIAL_REFERENCE_SYSTEM, - SECTION_HORIZONTAL); - if (!ReturnMMIDSRSFromEPSGCodeSRS(hMMMD->pSRS, aMMIDSRS) && - !MMIsEmptyString(aMMIDSRS)) - fprintf_function(pF, "%s=%s" LineReturn, - KEY_HorizontalSystemIdentifier, aMMIDSRS); - else - { - MMCPLWarning(CE_Warning, CPLE_NotSupported, - "The MiraMon driver cannot assign any HRS."); - // Horizontal Reference System - fprintf_function(pF, "%s=plane" LineReturn, - KEY_HorizontalSystemIdentifier); - fprintf_function(pF, "%s=local" LineReturn, - KEY_HorizontalSystemDefinition); - if (hMMMD->pXUnit) - fprintf_function(pF, "%s=%s" LineReturn, KEY_unitats, - hMMMD->pXUnit); - if (hMMMD->pYUnit) - { - if (!hMMMD->pXUnit || - strcasecmp(hMMMD->pXUnit, hMMMD->pYUnit)) - fprintf_function(pF, "%s=%s" LineReturn, KEY_unitatsY, - hMMMD->pYUnit); - } - } - } - else - { - fprintf_function(pF, "%s=plane" LineReturn, - KEY_HorizontalSystemIdentifier); - fprintf_function(pF, "%s=local" LineReturn, - KEY_HorizontalSystemDefinition); - if (hMMMD->pXUnit) - { - fprintf_function(pF, "%s=%s" LineReturn, KEY_unitats, - hMMMD->pXUnit); - if (hMMMD->pYUnit) - { - if (!hMMMD->pXUnit || - strcasecmp(hMMMD->pXUnit, hMMMD->pYUnit)) - fprintf_function(pF, "%s=%s" LineReturn, KEY_unitatsY, - hMMMD->pYUnit); - } - } - } - } - - // Writing OVERVIEW:ASPECTES_TECNICS in polygon metadata file. - // ArcSource=fitx_pol.arc - if (hMMMD->ePlainLT == MM_LayerType_Pol) - { - fprintf_function(pF, LineReturn "[%s]" LineReturn, - SECTION_OVVW_ASPECTES_TECNICS); - fprintf_function(pF, "%s=\"%s\"" LineReturn, KEY_ArcSource, - hMMMD->aArcFile); - } - - // Writing EXTENT section - fprintf_function(pF, LineReturn "[%s]" LineReturn, SECTION_EXTENT); - fprintf_function(pF, "%s=0" LineReturn, KEY_toler_env); - - if (hMMMD->hBB.dfMinX != MM_UNDEFINED_STATISTICAL_VALUE && - hMMMD->hBB.dfMaxX != -MM_UNDEFINED_STATISTICAL_VALUE && - hMMMD->hBB.dfMinY != MM_UNDEFINED_STATISTICAL_VALUE && - hMMMD->hBB.dfMaxY != -MM_UNDEFINED_STATISTICAL_VALUE) - { - fprintf_function(pF, "%s=%lf" LineReturn, KEY_MinX, hMMMD->hBB.dfMinX); - fprintf_function(pF, "%s=%lf" LineReturn, KEY_MaxX, hMMMD->hBB.dfMaxX); - fprintf_function(pF, "%s=%lf" LineReturn, KEY_MinY, hMMMD->hBB.dfMinY); - fprintf_function(pF, "%s=%lf" LineReturn, KEY_MaxY, hMMMD->hBB.dfMaxY); - } - - // Writing OVERVIEW section - fprintf_function(pF, LineReturn "[%s]" LineReturn, SECTION_OVERVIEW); - - currentTime = time(nullptr); - pLocalTime = localtime(¤tTime); - snprintf(aTimeString, sizeof(aTimeString), - "%04d%02d%02d %02d%02d%02d%02d+00:00", pLocalTime->tm_year + 1900, - pLocalTime->tm_mon + 1, pLocalTime->tm_mday, pLocalTime->tm_hour, - pLocalTime->tm_min, pLocalTime->tm_sec, 0); - fprintf_function(pF, "%s=%s" LineReturn, KEY_CreationDate, aTimeString); - - fprintf_function(pF, LineReturn); - - // Writing TAULA_PRINCIPAL section - fprintf_function(pF, "[%s]" LineReturn, SECTION_TAULA_PRINCIPAL); - fprintf_function(pF, "IdGrafic=%s" LineReturn, szMMNomCampIdGraficDefecte); - fprintf_function(pF, "TipusRelacio=RELACIO_1_1_DICC" LineReturn); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampIdGraficDefecte); - fprintf_function(pF, "visible=1" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - - MMWrite_ANSI_MetadataKeyDescriptor( - hMMMD, pF, szInternalGraphicIdentifierEng, - szInternalGraphicIdentifierCat, szInternalGraphicIdentifierEsp); - - if (hMMMD->ePlainLT == MM_LayerType_Arc) - { - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampNVertexsDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfVerticesEng, - szNumberOfVerticesCat, - szNumberOfVerticesEsp); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampLongitudArcDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor( - hMMMD, pF, szLenghtOfAarcEng, szLenghtOfAarcCat, szLenghtOfAarcEsp); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampNodeIniDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szInitialNodeEng, - szInitialNodeCat, szInitialNodeEsp); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampNodeFiDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szFinalNodeEng, - szFinalNodeCat, szFinalNodeEsp); - - fprintf_function(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn); - fprintf_function(pF, "NomCampNVertexs=%s" LineReturn, - szMMNomCampNVertexsDefecte); - fprintf_function(pF, "NomCampLongitudArc=%s" LineReturn, - szMMNomCampLongitudArcDefecte); - fprintf_function(pF, "NomCampNodeIni=%s" LineReturn, - szMMNomCampNodeIniDefecte); - fprintf_function(pF, "NomCampNodeFi=%s" LineReturn, - szMMNomCampNodeFiDefecte); - } - else if (hMMMD->ePlainLT == MM_LayerType_Node) - { - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampArcsANodeDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfArcsToNodeEng, - szNumberOfArcsToNodeCat, - szNumberOfArcsToNodeEsp); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampTipusNodeDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNodeTypeEng, - szNodeTypeCat, szNodeTypeEsp); - } - else if (hMMMD->ePlainLT == MM_LayerType_Pol) - { - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampNVertexsDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szNumberOfVerticesEng, - szNumberOfVerticesCat, - szNumberOfVerticesEsp); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampPerimetreDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor( - hMMMD, pF, szPerimeterOfThePolygonEng, szPerimeterOfThePolygonCat, - szPerimeterOfThePolygonEsp); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampAreaDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor(hMMMD, pF, szAreaOfThePolygonEng, - szAreaOfThePolygonCat, - szAreaOfThePolygonEsp); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampNArcsDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor( - hMMMD, pF, szNumberOfArcsEng, szNumberOfArcsCat, szNumberOfArcsEsp); - - fprintf_function(pF, LineReturn); - fprintf_function(pF, "[%s:%s]" LineReturn, SECTION_TAULA_PRINCIPAL, - szMMNomCampNPoligonsDefecte); - fprintf_function(pF, "visible=0" LineReturn); - fprintf_function(pF, "simbolitzable=0" LineReturn); - fprintf_function(pF, "MostrarUnitats=0" LineReturn); - MMWrite_ANSI_MetadataKeyDescriptor( - hMMMD, pF, szNumberOfElementaryPolygonsEng, - szNumberOfElementaryPolygonsCat, szNumberOfElementaryPolygonsEsp); - - fprintf_function(pF, "[GEOMETRIA_I_TOPOLOGIA]" LineReturn); - fprintf_function(pF, "NomCampNVertexs=%s" LineReturn, - szMMNomCampNVertexsDefecte); - fprintf_function(pF, "NomCampPerimetre=%s" LineReturn, - szMMNomCampPerimetreDefecte); - fprintf_function(pF, "NomCampArea=%s" LineReturn, - szMMNomCampAreaDefecte); - fprintf_function(pF, "NomCampNArcs=%s" LineReturn, - szMMNomCampNArcsDefecte); - fprintf_function(pF, "NomCampNPoligons=%s" LineReturn, - szMMNomCampNPoligonsDefecte); - } - - if (hMMMD->pLayerDB && hMMMD->pLayerDB->nNFields > 0) - { - // For each field of the databes - for (nIField = 0; nIField < hMMMD->pLayerDB->nNFields; nIField++) - { - if (!MMIsEmptyString( - hMMMD->pLayerDB->pFields[nIField].pszFieldDescription) && - !MMIsEmptyString( - hMMMD->pLayerDB->pFields[nIField].pszFieldName)) - { - fprintf_function( - pF, LineReturn "[%s:%s]" LineReturn, - SECTION_TAULA_PRINCIPAL, - hMMMD->pLayerDB->pFields[nIField].pszFieldName); - - MMWrite_ANSI_MetadataKeyDescriptor( - hMMMD, pF, - hMMMD->pLayerDB->pFields[nIField].pszFieldDescription, - hMMMD->pLayerDB->pFields[nIField].pszFieldDescription, - hMMMD->pLayerDB->pFields[nIField].pszFieldDescription); - } - } - } - fclose_function(pF); - return 0; -} - -// Writes metadata files for MiraMon vector layers -static int MMWriteVectorMetadataFile(struct MiraMonVectLayerInfo *hMiraMonLayer, - int layerPlainType, int layerMainPlainType) -{ - struct MiraMonVectorMetaData hMMMD; - - if (!hMiraMonLayer) - return 1; - - // MiraMon writes a REL file of each .pnt, .arc, .nod or .pol - memset(&hMMMD, 0, sizeof(hMMMD)); - hMMMD.ePlainLT = layerPlainType; - hMMMD.pSRS = hMiraMonLayer->pSRS; - hMMMD.nMMLanguage = hMiraMonLayer->nMMLanguage; - - hMMMD.szLayerTitle = hMiraMonLayer->szLayerTitle; - if (layerPlainType == MM_LayerType_Point) - { - hMMMD.aLayerName = hMiraMonLayer->MMPoint.pszREL_LayerName; - if (MMIsEmptyString(hMMMD.aLayerName)) - return 0; // If no file, no error. Just continue. - memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB, sizeof(hMMMD.hBB)); - hMMMD.pLayerDB = hMiraMonLayer->pLayerDB; - return MMWriteMetadataFile(&hMMMD); - } - else if (layerPlainType == MM_LayerType_Arc) - { - // Arcs and not polygons - if (layerMainPlainType == MM_LayerType_Arc) - { - hMMMD.aLayerName = hMiraMonLayer->MMArc.pszREL_LayerName; - if (MMIsEmptyString(hMMMD.aLayerName)) - return 0; // If no file, no error. Just continue. - memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB, - sizeof(hMMMD.hBB)); - hMMMD.pLayerDB = hMiraMonLayer->pLayerDB; - } - // Arcs and polygons - else - { - // Arc from polygon - hMMMD.aLayerName = hMiraMonLayer->MMPolygon.MMArc.pszREL_LayerName; - if (MMIsEmptyString(hMMMD.aLayerName)) - return 0; // If no file, no error. Just continue. - - memcpy(&hMMMD.hBB, &hMiraMonLayer->MMPolygon.TopArcHeader.hBB, - sizeof(hMMMD.hBB)); - hMMMD.pLayerDB = nullptr; - } - return MMWriteMetadataFile(&hMMMD); - } - else if (layerPlainType == MM_LayerType_Pol) - { - int nResult; - - hMMMD.aLayerName = hMiraMonLayer->MMPolygon.pszREL_LayerName; - - if (MMIsEmptyString(hMMMD.aLayerName)) - return 0; // If no file, no error. Just continue. - - memcpy(&hMMMD.hBB, &hMiraMonLayer->TopHeader.hBB, sizeof(hMMMD.hBB)); - hMMMD.pLayerDB = hMiraMonLayer->pLayerDB; - hMMMD.aArcFile = strdup_function( - get_filename_function(hMiraMonLayer->MMPolygon.MMArc.pszLayerName)); - nResult = MMWriteMetadataFile(&hMMMD); - free_function(hMMMD.aArcFile); - return nResult; - } - else if (layerPlainType == MM_LayerType_Node) - { - // Node from arc - if (layerMainPlainType == MM_LayerType_Arc) - { - hMMMD.aLayerName = hMiraMonLayer->MMArc.MMNode.pszREL_LayerName; - if (MMIsEmptyString(hMMMD.aLayerName)) - return 0; // If no file, no error. Just continue. - memcpy(&hMMMD.hBB, &hMiraMonLayer->MMArc.TopNodeHeader.hBB, - sizeof(hMMMD.hBB)); - } - else // Node from polygon - { - hMMMD.aLayerName = - hMiraMonLayer->MMPolygon.MMArc.MMNode.pszREL_LayerName; - if (MMIsEmptyString(hMMMD.aLayerName)) - return 0; // If no file, no error. Just continue. - memcpy(&hMMMD.hBB, - &hMiraMonLayer->MMPolygon.MMArc.TopNodeHeader.hBB, - sizeof(hMMMD.hBB)); - } - hMMMD.pLayerDB = nullptr; - return MMWriteMetadataFile(&hMMMD); - } - return 0; -} - -int MMWriteVectorMetadata(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPoint) - return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Point, - MM_LayerType_Point); - if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) - { - if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Node, - MM_LayerType_Arc)) - return 1; - return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Arc, - MM_LayerType_Arc); - } - if (hMiraMonLayer->bIsPolygon) - { - if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Node, - MM_LayerType_Pol)) - return 1; - if (MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Arc, - MM_LayerType_Pol)) - return 1; - return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Pol, - MM_LayerType_Pol); - } - if (hMiraMonLayer->bIsDBF) - { - return MMWriteVectorMetadataFile(hMiraMonLayer, MM_LayerType_Unknown, - MM_LayerType_Unknown); - } - return 0; -} - -// Verifies the version of a MiraMon REL 4 file. -int MMCheck_REL_FILE(char *szREL_file) -{ - char *pszLine; - FILE_TYPE *pF; - - // Does the REL file exist? - pF = fopen_function(szREL_file, "r"); - if (!pF) - { - sprintf(local_message, "The file %s must exist.", szREL_file); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fclose_function(pF); - - // Does the REL file have VERSION? - pszLine = - MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, nullptr); - if (!pszLine) - { - sprintf(local_message, - "The file \"%s\" must be REL4. " - "You can use ConvREL.exe from MiraMon software " - "to convert this file to REL4.", - szREL_file); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - free_function(pszLine); - - // Does the REL file have the correct VERSION? - // Vers>=4? - pszLine = - MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, KEY_Vers); - if (pszLine) - { - if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS) - { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", - szREL_file, KEY_Vers, MM_VERS); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - free_function(pszLine); - } - else - { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", szREL_file, - KEY_Vers, MM_VERS); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - - // SubVers>=3? - pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, - KEY_SubVers); - if (pszLine) - { - if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS) - { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", - szREL_file, KEY_SubVers, MM_SUBVERS); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - free_function(pszLine); - } - else - { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", szREL_file, - KEY_SubVers, MM_SUBVERS); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - - // VersMetaDades>=5? - pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, - KEY_VersMetaDades); - if (pszLine) - { - if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS_METADADES) - { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", - szREL_file, KEY_VersMetaDades, MM_VERS_METADADES); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - free_function(pszLine); - } - else - { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", szREL_file, - KEY_VersMetaDades, MM_VERS_METADADES); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - - // SubVersMetaDades>=0? - pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, - KEY_SubVersMetaDades); - if (pszLine) - { - if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_METADADES) - { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", - szREL_file, KEY_SubVersMetaDades, MM_SUBVERS_METADADES); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - - return 1; - } - free_function(pszLine); - } - else - { - sprintf(local_message, "The file \"%s\" must have %s>=%d.", szREL_file, - KEY_SubVersMetaDades, MM_SUBVERS_METADADES); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - return 0; -} - -/* -------------------------------------------------------------------- */ -/* MiraMon database functions */ -/* -------------------------------------------------------------------- */ - -// Initializes a MiraMon database associated with a vector layer: -// Sets the usual fields that MiraMon needs and after them, adds -// all fields of the input layer -static int MMInitMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MMAdmDatabase *pMMAdmDB) -{ - if (!hMiraMonLayer) - return 1; - - if (!pMMAdmDB) - return 1; - - if (MMIsEmptyString(pMMAdmDB->pszExtDBFLayerName)) - return 0; // No file, no error. Just continue - - strcpy(pMMAdmDB->pMMBDXP->ReadingMode, "wb+"); - if (FALSE == - MM_CreateDBFFile(pMMAdmDB->pMMBDXP, pMMAdmDB->pszExtDBFLayerName)) - return 1; - - // Opening the file - if (nullptr == (pMMAdmDB->pFExtDBF = - fopen_function(pMMAdmDB->pszExtDBFLayerName, - "r+b"))) //hMiraMonLayer->pszFlags))) - { - sprintf(local_message, "Error pMMAdmDB: Cannot open file %s.", - pMMAdmDB->pszExtDBFLayerName); - MMCPLError(CE_Failure, CPLE_OpenFailed, local_message); - return 1; - } - fseek_function(pMMAdmDB->pFExtDBF, pMMAdmDB->pMMBDXP->FirstRecordOffset, - SEEK_SET); - - if (MMInitFlush(&pMMAdmDB->FlushRecList, pMMAdmDB->pFExtDBF, - (hMiraMonLayer->nMemoryRatio != 1) - ? (GUInt64)(hMiraMonLayer->nMemoryRatio * MM_25MB) - : MM_25MB, - &pMMAdmDB->pRecList, pMMAdmDB->pMMBDXP->FirstRecordOffset, - 0)) - return 1; - - pMMAdmDB->nNumRecordOnCourse = - (GUInt64)pMMAdmDB->pMMBDXP->BytesPerRecord + 1; - if (MMCheckSize_t(pMMAdmDB->nNumRecordOnCourse, 1)) - return 1; - pMMAdmDB->szRecordOnCourse = - calloc_function((size_t)pMMAdmDB->nNumRecordOnCourse); - if (!pMMAdmDB->szRecordOnCourse) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMInitMMDB())"); - return 1; - } - return 0; -} - -// Creates a MiraMon database associated with a vector layer. -// It determines the number of fields and initializes the database header -// accordingly. Depending on the layer type (point, arc, polygon, or generic), -// it defines the fields and initializes the corresponding MiraMon database -// structures. -int MMCreateMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - struct MM_DATA_BASE_XP *pBD_XP = nullptr, *pBD_XP_Aux = nullptr; - struct MM_FIELD MMField; - size_t nIFieldLayer; - MM_EXT_DBF_N_FIELDS nIField = 0; - MM_EXT_DBF_N_FIELDS nNFields; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPoint) - { - if (hMiraMonLayer->pLayerDB) - nNFields = - MM_PRIVATE_POINT_DB_FIELDS + hMiraMonLayer->pLayerDB->nNFields; - else - nNFields = MM_PRIVATE_POINT_DB_FIELDS; - pBD_XP = hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP = - MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet); - - if (!pBD_XP) - return 1; - - if (0 == (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstPointFieldsDB_XP( - pBD_XP))) - return 1; - } - else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) - { - if (hMiraMonLayer->pLayerDB) - nNFields = - MM_PRIVATE_ARC_DB_FIELDS + hMiraMonLayer->pLayerDB->nNFields; - else - nNFields = MM_PRIVATE_ARC_DB_FIELDS; - - pBD_XP = hMiraMonLayer->MMArc.MMAdmDB.pMMBDXP = - MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet); - - if (!pBD_XP) - return 1; - - if (0 == (nIField = (MM_EXT_DBF_N_FIELDS)MM_DefineFirstArcFieldsDB_XP( - pBD_XP, 0))) - return 1; - - pBD_XP_Aux = hMiraMonLayer->MMArc.MMNode.MMAdmDB.pMMBDXP = - MM_CreateDBFHeader(3, hMiraMonLayer->nCharSet); - - if (!pBD_XP_Aux) - return 1; - - if (0 == MM_DefineFirstNodeFieldsDB_XP(pBD_XP_Aux)) - return 1; - } - else if (hMiraMonLayer->bIsPolygon) - { - if (hMiraMonLayer->pLayerDB) - nNFields = MM_PRIVATE_POLYGON_DB_FIELDS + - hMiraMonLayer->pLayerDB->nNFields; - else - nNFields = MM_PRIVATE_POLYGON_DB_FIELDS; - - pBD_XP = hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP = - MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet); - - if (!pBD_XP) - return 1; - - if (0 == (nIField = (MM_EXT_DBF_N_FIELDS) - MM_DefineFirstPolygonFieldsDB_XP(pBD_XP, 6))) - return 1; - - pBD_XP_Aux = hMiraMonLayer->MMPolygon.MMArc.MMAdmDB.pMMBDXP = - MM_CreateDBFHeader(5, hMiraMonLayer->nCharSet); - - if (!pBD_XP_Aux) - return 1; - - if (0 == MM_DefineFirstArcFieldsDB_XP(pBD_XP_Aux, 6)) - return 1; - - pBD_XP_Aux = hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB.pMMBDXP = - MM_CreateDBFHeader(3, hMiraMonLayer->nCharSet); - - if (!pBD_XP_Aux) - return 1; - - if (0 == MM_DefineFirstNodeFieldsDB_XP(pBD_XP_Aux)) - return 1; - } - else if (hMiraMonLayer->bIsDBF) - { - // Creating only a DBF - if (hMiraMonLayer->pLayerDB) - nNFields = hMiraMonLayer->pLayerDB->nNFields; - else - nNFields = 0; - - pBD_XP = hMiraMonLayer->MMAdmDBWriting.pMMBDXP = - MM_CreateDBFHeader(nNFields, hMiraMonLayer->nCharSet); - - if (!pBD_XP) - return 1; - } - else - return 0; - - // After private MiraMon fields, other fields are added. - // If names are no compatible, some changes are done. - if (hMiraMonLayer->pLayerDB) - { - for (nIFieldLayer = 0; nIField < nNFields; nIField++, nIFieldLayer++) - { - MM_InitializeField(&MMField); - MM_strnzcpy( - MMField.FieldName, - hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].pszFieldName, - MM_MAX_LON_FIELD_NAME_DBF); - - MM_strnzcpy(MMField.FieldDescription[0], - hMiraMonLayer->pLayerDB->pFields[nIFieldLayer] - .pszFieldDescription, - MM_MAX_BYTES_FIELD_DESC); - - MMField.BytesPerField = - hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].nFieldSize; - switch (hMiraMonLayer->pLayerDB->pFields[nIFieldLayer].eFieldType) - { - case MM_Numeric: - MMField.FieldType = 'N'; - if (hMiraMonLayer->pLayerDB->pFields[nIFieldLayer] - .bIs64BitInteger) - MMField.Is64 = 1; - if (MMField.BytesPerField == 0) - MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_N_DBF; - break; - case MM_Character: - MMField.FieldType = 'C'; - if (MMField.BytesPerField == 0) - MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_C_DBF; - break; - case MM_Data: - MMField.FieldType = 'D'; - if (MMField.BytesPerField == 0) - MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_D_DBF; - break; - case MM_Logic: - MMField.FieldType = 'L'; - if (MMField.BytesPerField == 0) - MMField.BytesPerField = 1; - break; - default: - MMField.FieldType = 'C'; - if (MMField.BytesPerField == 0) - MMField.BytesPerField = MM_MAX_AMPLADA_CAMP_C_DBF; - }; - - MMField.DecimalsIfFloat = - (MM_BYTE)hMiraMonLayer->pLayerDB->pFields[nIFieldLayer] - .nNumberOfDecimals; - - MM_DuplicateFieldDBXP(pBD_XP->pField + nIField, &MMField); - MM_ModifyFieldNameAndDescriptorIfPresentBD_XP( - pBD_XP->pField + nIField, pBD_XP, FALSE, 0); - if (pBD_XP->pField[nIField].FieldType == 'F') - pBD_XP->pField[nIField].FieldType = 'N'; - } - } - - if (hMiraMonLayer->bIsPoint) - { - if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB)) - return 1; - } - else if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) - { - if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB)) - return 1; - - if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMArc.MMNode.MMAdmDB)) - return 1; - } - else if (hMiraMonLayer->bIsPolygon) - { - if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMAdmDB)) - return 1; - - if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB)) - return 1; - - if (MMInitMMDB(hMiraMonLayer, - &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB)) - return 1; - } - else if (hMiraMonLayer->bIsDBF) - { - if (MMInitMMDB(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting)) - return 1; - } - return 0; -} - -// Checks and fits the width of a specific field in a MiraMon database -// associated with a vector layer. It examines the length of the provided -// value and resizes the field width, if necessary, to accommodate the new -// value. If the new width exceeds the current width of the field, -// it updates the database structure, including the field width and -// the size of the record. Additionally, it reallocates memory if needed -// for the record handling buffer. - -static int -MMTestAndFixValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MMAdmDatabase *pMMAdmDB, - MM_EXT_DBF_N_FIELDS nIField, char *szValue) -{ - struct MM_FIELD *camp; - MM_BYTES_PER_FIELD_TYPE_DBF nNewWidth; - - if (!hMiraMonLayer) - return 1; - - camp = pMMAdmDB->pMMBDXP->pField + nIField; - - if (!szValue) - return 0; - - nNewWidth = (MM_BYTES_PER_FIELD_TYPE_DBF)strlen(szValue); - if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, nNewWidth + 1)) - return 1; - - if (nNewWidth > camp->BytesPerField) - { - if (MM_WriteNRecordsMMBD_XPFile(pMMAdmDB)) - return 1; - - // Flushing all to be flushed - pMMAdmDB->FlushRecList.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&pMMAdmDB->FlushRecList)) - return 1; - - pMMAdmDB->pMMBDXP->pfDataBase = pMMAdmDB->pFExtDBF; - - if (MM_ChangeDBFWidthField( - pMMAdmDB->pMMBDXP, nIField, nNewWidth, - pMMAdmDB->pMMBDXP->pField[nIField].DecimalsIfFloat, - (MM_BYTE)MM_NOU_N_DECIMALS_NO_APLICA)) - return 1; - - // The record on course also has to change its size. - if ((GUInt64)pMMAdmDB->pMMBDXP->BytesPerRecord + 1 >= - pMMAdmDB->nNumRecordOnCourse) - { - if (nullptr == (pMMAdmDB->szRecordOnCourse = realloc_function( - pMMAdmDB->szRecordOnCourse, - (size_t)pMMAdmDB->pMMBDXP->BytesPerRecord + 1))) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMTestAndFixValueToRecordDBXP())"); - return 1; - } - } - - // File has changed it's size, so it has to be updated - // at the Flush tool - fseek_function(pMMAdmDB->pFExtDBF, 0, SEEK_END); - pMMAdmDB->FlushRecList.OffsetWhereToFlush = - ftell_function(pMMAdmDB->pFExtDBF); - } - return 0; -} - -int MMWriteValueToRecordDBXP(struct MiraMonVectLayerInfo *hMiraMonLayer, - char *registre, const struct MM_FIELD *camp, - const void *valor, MM_BOOLEAN is_64) -{ - if (!hMiraMonLayer) - return 1; - - if (!camp) - return 0; - - if (MMResizeStringToOperateIfNeeded(hMiraMonLayer, - camp->BytesPerField + 10)) - return 1; - - if (!valor) - *hMiraMonLayer->szStringToOperate = '\0'; - else - { - if (camp->FieldType == 'N') - { - if (!is_64) - { - sprintf(hMiraMonLayer->szStringToOperate, "%*.*f", - camp->BytesPerField, camp->DecimalsIfFloat, - *(const double *)valor); - } - else - { - sprintf(hMiraMonLayer->szStringToOperate, "%*lld", - camp->BytesPerField, *(const GInt64 *)valor); - } - } - else - { - sprintf(hMiraMonLayer->szStringToOperate, "%-*s", - camp->BytesPerField, (const char *)valor); - } - } - - memcpy(registre + camp->AcumulatedBytes, hMiraMonLayer->szStringToOperate, - camp->BytesPerField); - return 0; -} - -// Gets the n-th value of the format (number_of_values:val1,val2,...,valN) -char *MMGetNFieldValue(const char *pszStringList, GUInt32 nIRecord) -{ - char *p, *q; - GUInt32 nNValues, nIValues; - char *pszAux; - - if (!pszStringList) - return nullptr; - - pszAux = strdup_function(pszStringList); - p = strstr(pszAux, "("); - if (!p) - return nullptr; - p++; - if (!p) - return nullptr; - q = strstr(p, ":"); - p[(ptrdiff_t)q - (ptrdiff_t)p] = '\0'; - nNValues = atoi(p); - if (nIRecord > nNValues) - return nullptr; - - q++; - nIValues = 0; - while (nIValues <= nIRecord) - { - if (!q) - return nullptr; - p = strstr(q, ","); - if (!p) - { - p = strstr(q, ")"); - if (!p) - return nullptr; - q[(ptrdiff_t)p - (ptrdiff_t)q] = '\0'; - return q; - } - if (nIValues == nIRecord) - { - p = strstr(q, ","); - q[(ptrdiff_t)p - (ptrdiff_t)q] = '\0'; - - return q; - } - q = p + 1; - } - - return q; -} - -static int MMAddFeatureRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature, - struct MMAdmDatabase *pMMAdmDB, - char *pszRecordOnCourse, - struct MM_FLUSH_INFO *pFlushRecList, - MM_EXT_DBF_N_RECORDS *nNumRecords, - MM_EXT_DBF_N_FIELDS nNumPrivateMMField) -{ - MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord; - MM_EXT_DBF_N_FIELDS nIField; - struct MM_DATA_BASE_XP *pBD_XP = nullptr; - - if (!hMiraMonLayer) - return 1; - - if (!hMMFeature) - return 1; - - pBD_XP = pMMAdmDB->pMMBDXP; - for (nIRecord = 0; nIRecord < hMMFeature->nNumMRecords; nIRecord++) - { - for (nIField = 0; nIField < hMMFeature->pRecords[nIRecord].nNumField; - nIField++) - { - // A field with no valid value is written as blank - if (!hMMFeature->pRecords[nIRecord].pField[nIField].bIsValid) - { - MM_ACUMULATED_BYTES_TYPE_DBF i = 0; - while ( - i < - pBD_XP->pField[nIField + nNumPrivateMMField].BytesPerField) - { - memcpy(pszRecordOnCourse + - pBD_XP->pField[nIField + nNumPrivateMMField] - .AcumulatedBytes + - i, - " ", 1); - i++; - } - continue; - } - if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == 'C') - { - if (MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + nIField + - nNumPrivateMMField, - hMMFeature->pRecords[nIRecord] - .pField[nIField] - .pDinValue, - FALSE)) - return 1; - } - else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == - 'N') - { - if (pBD_XP->pField[nIField + nNumPrivateMMField].Is64) - { - if (MMWriteValueToRecordDBXP( - hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + nIField + nNumPrivateMMField, - &hMMFeature->pRecords[nIRecord] - .pField[nIField] - .iValue, - TRUE)) - return 1; - } - else - { - if (MMWriteValueToRecordDBXP( - hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + nIField + nNumPrivateMMField, - &hMMFeature->pRecords[nIRecord] - .pField[nIField] - .dValue, - FALSE)) - return 1; - } - } - else if (pBD_XP->pField[nIField + nNumPrivateMMField].FieldType == - 'D') - { - if (MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + nIField + - nNumPrivateMMField, - hMMFeature->pRecords[nIRecord] - .pField[nIField] - .pDinValue, - FALSE)) - return 1; - } - } - - if (MMAppendBlockToBuffer(pFlushRecList)) - return 1; - - (*nNumRecords)++; - } - return 0; -} - -// Adds feature records to a MiraMon database associated with a vector layer. -static int MMDetectAndFixDBFWidthChange( - struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature, struct MMAdmDatabase *pMMAdmDB, - struct MM_FLUSH_INFO *pFlushRecList, MM_EXT_DBF_N_FIELDS nNumPrivateMMField, - MM_EXT_DBF_N_MULTIPLE_RECORDS nIRecord, MM_EXT_DBF_N_FIELDS nIField) -{ - if (!hMiraMonLayer) - return 1; - - if (!hMMFeature) - return 0; - - if (nIRecord >= hMMFeature->nNumMRecords) - return 0; - - if (nIField >= hMMFeature->pRecords[nIRecord].nNumField) - return 0; - - if (MMTestAndFixValueToRecordDBXP( - hMiraMonLayer, pMMAdmDB, nIField + nNumPrivateMMField, - hMMFeature->pRecords[nIRecord].pField[nIField].pDinValue)) - return 1; - - // We analize next fields - if (nIField == hMMFeature->pRecords[nIRecord].nNumField - 1) - { - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, pMMAdmDB, - pFlushRecList, nNumPrivateMMField, - nIRecord + 1, 0)) - return 1; - } - else - { - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, pMMAdmDB, - pFlushRecList, nNumPrivateMMField, - nIRecord, nIField + 1)) - return 1; - } - return 0; -} // End of MMDetectAndFixDBFWidthChange() - -// Adds a DBF record to a MiraMon table associated with a vector layer. -// It sets up flush settings for writing to the table and initializes -// variables needed for the process. Then, it checks and fixes the width -// change if necessary. -int MMAddDBFRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature) -{ - struct MM_DATA_BASE_XP *pBD_XP = nullptr; - MM_EXT_DBF_N_FIELDS nNumPrivateMMField = 0; - char *pszRecordOnCourse; - struct MM_FLUSH_INFO *pFlushRecList; - - if (!hMiraMonLayer) - return 1; - - // Adding record to the MiraMon table (extended DBF) - // Flush settings - pFlushRecList = &hMiraMonLayer->MMAdmDBWriting.FlushRecList; - pFlushRecList->pBlockWhereToSaveOrRead = - (void *)hMiraMonLayer->MMAdmDBWriting.pRecList; - - pszRecordOnCourse = hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - pBD_XP = hMiraMonLayer->MMAdmDBWriting.pMMBDXP; - - // Test lenght - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, - &hMiraMonLayer->MMAdmDBWriting, - pFlushRecList, nNumPrivateMMField, 0, 0)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Reassign the point because the function can realloc it. - pszRecordOnCourse = hMiraMonLayer->MMAdmDBWriting.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; - if (MMAddFeatureRecordToMMDB( - hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMAdmDBWriting, - pszRecordOnCourse, pFlushRecList, - &hMiraMonLayer->MMAdmDBWriting.pMMBDXP->nRecords, - nNumPrivateMMField)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // In this case, the number of features is also updated - hMiraMonLayer->TopHeader.nElemCount = - hMiraMonLayer->MMAdmDBWriting.pMMBDXP->nRecords; - - return MM_CONTINUE_WRITING_FEATURES; -} - -// Adds a point record to a MiraMon table associated with a vector layer. -int MMAddPointRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature, - MM_INTERNAL_FID nElemCount) -{ - struct MM_DATA_BASE_XP *pBD_XP = nullptr; - MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_POINT_DB_FIELDS; - char *pszRecordOnCourse; - struct MM_FLUSH_INFO *pFlushRecList; - - if (!hMiraMonLayer) - return 1; - - // In V1.1 only _UI32_MAX records number is allowed - if (MMCheckVersionForFID(hMiraMonLayer, - hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP->nRecords + - hMMFeature->nNumMRecords)) - return MM_STOP_WRITING_FEATURES; - - // Adding record to the MiraMon table (extended DBF) - // Flush settings - pFlushRecList = &hMiraMonLayer->MMPoint.MMAdmDB.FlushRecList; - pFlushRecList->pBlockWhereToSaveOrRead = - (void *)hMiraMonLayer->MMPoint.MMAdmDB.pRecList; - - pBD_XP = hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP; - - // Test lenght - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, - &hMiraMonLayer->MMPoint.MMAdmDB, - pFlushRecList, nNumPrivateMMField, 0, 0)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Reassign the point because the function can realloc it. - pszRecordOnCourse = hMiraMonLayer->MMPoint.MMAdmDB.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - // Now lenght is sure, write - memset(pszRecordOnCourse, 0, pBD_XP->BytesPerRecord); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, pBD_XP->pField, - &nElemCount, TRUE); - - pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; - if (MMAddFeatureRecordToMMDB( - hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMPoint.MMAdmDB, - pszRecordOnCourse, pFlushRecList, - &hMiraMonLayer->MMPoint.MMAdmDB.pMMBDXP->nRecords, - nNumPrivateMMField)) - return MM_FATAL_ERROR_WRITING_FEATURES; - return MM_CONTINUE_WRITING_FEATURES; -} - -// Adds a stringline record to a MiraMon table associated with a vector layer. -int MMAddArcRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature, - MM_INTERNAL_FID nElemCount, struct MM_AH *pArcHeader) -{ - struct MM_DATA_BASE_XP *pBD_XP = nullptr; - char *pszRecordOnCourse; - struct MiraMonArcLayer *pMMArcLayer; - MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_ARC_DB_FIELDS; - struct MM_FLUSH_INFO *pFlushRecList; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - pMMArcLayer = &hMiraMonLayer->MMPolygon.MMArc; - else - pMMArcLayer = &hMiraMonLayer->MMArc; - - if (!pMMArcLayer) - return 1; - - // In V1.1 only _UI32_MAX records number is allowed - if (hMiraMonLayer->bIsPolygon) - { - if (MMCheckVersionForFID(hMiraMonLayer, - pMMArcLayer->MMAdmDB.pMMBDXP->nRecords + 1)) - return MM_STOP_WRITING_FEATURES; - } - else - { - if (MMCheckVersionForFID(hMiraMonLayer, - pMMArcLayer->MMAdmDB.pMMBDXP->nRecords + - hMMFeature->nNumMRecords)) - return MM_STOP_WRITING_FEATURES; - } - - // Adding record to the MiraMon table (extended DBF) - // Flush settings - pFlushRecList = &pMMArcLayer->MMAdmDB.FlushRecList; - pFlushRecList->pBlockWhereToSaveOrRead = - (void *)pMMArcLayer->MMAdmDB.pRecList; - - pBD_XP = pMMArcLayer->MMAdmDB.pMMBDXP; - pszRecordOnCourse = pMMArcLayer->MMAdmDB.szRecordOnCourse; - - pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - // Test lenght - if (!hMiraMonLayer->bIsPolygon) - { - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, - &pMMArcLayer->MMAdmDB, pFlushRecList, - nNumPrivateMMField, 0, 0)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Reassign the point because the function can realloc it. - pszRecordOnCourse = pMMArcLayer->MMAdmDB.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - } - - // Now lenght is sure, write - memset(pszRecordOnCourse, 0, pBD_XP->BytesPerRecord); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, pBD_XP->pField, - &nElemCount, TRUE); - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 1, &pArcHeader->nElemCount, TRUE); - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 2, &pArcHeader->dfLenght, FALSE); - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 3, &pArcHeader->nFirstIdNode, - TRUE); - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 4, &pArcHeader->nLastIdNode, - TRUE); - - if (hMiraMonLayer->bIsPolygon) - { - if (MMAppendBlockToBuffer(pFlushRecList)) - return MM_FATAL_ERROR_WRITING_FEATURES; - pMMArcLayer->MMAdmDB.pMMBDXP->nRecords++; - return MM_CONTINUE_WRITING_FEATURES; - } - - pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; - if (MMAddFeatureRecordToMMDB( - hMiraMonLayer, hMMFeature, &pMMArcLayer->MMAdmDB, pszRecordOnCourse, - pFlushRecList, &pMMArcLayer->MMAdmDB.pMMBDXP->nRecords, - nNumPrivateMMField)) - return MM_FATAL_ERROR_WRITING_FEATURES; - return MM_CONTINUE_WRITING_FEATURES; -} - -// Adds a node record to a MiraMon table associated with a vector layer. -int MMAddNodeRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - MM_INTERNAL_FID nElemCount, struct MM_NH *pNodeHeader) -{ - struct MM_DATA_BASE_XP *pBD_XP = nullptr; - char *pszRecordOnCourse; - struct MiraMonNodeLayer *pMMNodeLayer; - double nDoubleValue; - - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->bIsPolygon) - pMMNodeLayer = &hMiraMonLayer->MMPolygon.MMArc.MMNode; - else - pMMNodeLayer = &hMiraMonLayer->MMArc.MMNode; - - // In V1.1 only _UI32_MAX records number is allowed - if (MMCheckVersionForFID(hMiraMonLayer, - pMMNodeLayer->MMAdmDB.pMMBDXP->nRecords + 1)) - return MM_STOP_WRITING_FEATURES; - - // Adding record to the MiraMon table (extended DBF) - // Flush settings - pMMNodeLayer->MMAdmDB.FlushRecList.pBlockWhereToSaveOrRead = - (void *)pMMNodeLayer->MMAdmDB.pRecList; - - pBD_XP = pMMNodeLayer->MMAdmDB.pMMBDXP; - pszRecordOnCourse = pMMNodeLayer->MMAdmDB.szRecordOnCourse; - - pMMNodeLayer->MMAdmDB.FlushRecList.SizeOfBlockToBeSaved = - pBD_XP->BytesPerRecord; - pMMNodeLayer->MMAdmDB.FlushRecList.pBlockToBeSaved = - (void *)pszRecordOnCourse; - - memset(pszRecordOnCourse, 0, pBD_XP->BytesPerRecord); - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, pBD_XP->pField, - &nElemCount, TRUE); - - nDoubleValue = pNodeHeader->nArcsCount; - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 1, &nDoubleValue, FALSE); - - nDoubleValue = pNodeHeader->cNodeType; - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 2, &nDoubleValue, FALSE); - - if (MMAppendBlockToBuffer(&pMMNodeLayer->MMAdmDB.FlushRecList)) - return MM_FATAL_ERROR_WRITING_FEATURES; - pMMNodeLayer->MMAdmDB.pMMBDXP->nRecords++; - return MM_CONTINUE_WRITING_FEATURES; -} - -// Adds a polygon or multipolygon record to a MiraMon table -// associated with a vector layer. -int MMAddPolygonRecordToMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MiraMonFeature *hMMFeature, - MM_INTERNAL_FID nElemCount, - MM_N_VERTICES_TYPE nVerticesCount, - struct MM_PH *pPolHeader) -{ - struct MM_DATA_BASE_XP *pBD_XP = nullptr; - char *pszRecordOnCourse; - MM_EXT_DBF_N_FIELDS nNumPrivateMMField = MM_PRIVATE_POLYGON_DB_FIELDS; - struct MM_FLUSH_INFO *pFlushRecList; - - if (!hMiraMonLayer) - return 1; - - // In V1.1 only _UI32_MAX records number is allowed - if (MMCheckVersionForFID( - hMiraMonLayer, hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords + - (hMMFeature ? hMMFeature->nNumMRecords : 0))) - return MM_STOP_WRITING_FEATURES; - - // Adding record to the MiraMon table (extended DBF) - // Flush settings - pFlushRecList = &hMiraMonLayer->MMPolygon.MMAdmDB.FlushRecList; - pFlushRecList->pBlockWhereToSaveOrRead = - (void *)hMiraMonLayer->MMPolygon.MMAdmDB.pRecList; - - pBD_XP = hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP; - pszRecordOnCourse = hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse; - - pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - // Test lenght - if (MMDetectAndFixDBFWidthChange(hMiraMonLayer, hMMFeature, - &hMiraMonLayer->MMPolygon.MMAdmDB, - pFlushRecList, nNumPrivateMMField, 0, 0)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - // Reassign the point because the function can realloc it. - pszRecordOnCourse = hMiraMonLayer->MMPolygon.MMAdmDB.szRecordOnCourse; - pFlushRecList->pBlockToBeSaved = (void *)pszRecordOnCourse; - - // Now lenght is sure, write - memset(pszRecordOnCourse, 0, pBD_XP->BytesPerRecord); - if (MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField, &nElemCount, TRUE)) - return MM_FATAL_ERROR_WRITING_FEATURES; - - if (!hMMFeature) - { - if (MMAppendBlockToBuffer(pFlushRecList)) - return MM_FATAL_ERROR_WRITING_FEATURES; - hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords++; - return MM_CONTINUE_WRITING_FEATURES; - } - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 1, &nVerticesCount, TRUE); - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 2, &pPolHeader->dfPerimeter, - FALSE); - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 3, &pPolHeader->dfArea, FALSE); - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 4, &pPolHeader->nArcsCount, TRUE); - - MMWriteValueToRecordDBXP(hMiraMonLayer, pszRecordOnCourse, - pBD_XP->pField + 5, &pPolHeader->nRingsCount, - TRUE); - - pFlushRecList->SizeOfBlockToBeSaved = pBD_XP->BytesPerRecord; - if (MMAddFeatureRecordToMMDB( - hMiraMonLayer, hMMFeature, &hMiraMonLayer->MMPolygon.MMAdmDB, - pszRecordOnCourse, pFlushRecList, - &hMiraMonLayer->MMPolygon.MMAdmDB.pMMBDXP->nRecords, - nNumPrivateMMField)) - return MM_FATAL_ERROR_WRITING_FEATURES; - return MM_CONTINUE_WRITING_FEATURES; -} - -// Close the MiraMon database associated with a vector layer. -static int MMCloseMMBD_XPFile(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MMAdmDatabase *MMAdmDB) -{ - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->ReadOrWrite == MM_WRITTING_MODE) - { - if (!MMAdmDB->pFExtDBF) - { - // In case of 0 elements created we have to - // create an empty DBF - if (hMiraMonLayer->bIsPolygon) - { - if (hMiraMonLayer->TopHeader.nElemCount <= 1) - { - if (MMCreateMMDB(hMiraMonLayer)) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMCreateMMDB())"); - return 1; - } - } - } - else if (hMiraMonLayer->bIsPoint || hMiraMonLayer->bIsArc) - { - if (hMiraMonLayer->TopHeader.nElemCount == 0) - { - if (MMCreateMMDB(hMiraMonLayer)) - { - MMCPLError(CE_Failure, CPLE_OutOfMemory, - "Memory error in MiraMon " - "driver (MMCreateMMDB())"); - return 1; - } - } - } - } - - if (MM_WriteNRecordsMMBD_XPFile(MMAdmDB)) - return 1; - - // Flushing all to be flushed - MMAdmDB->FlushRecList.SizeOfBlockToBeSaved = 0; - if (MMAppendBlockToBuffer(&MMAdmDB->FlushRecList)) - return 1; - } - - // Closing database files - if (MMAdmDB->pFExtDBF) - { - if (fclose_function(MMAdmDB->pFExtDBF)) - return 1; - MMAdmDB->pFExtDBF = nullptr; - } - - return 0; -} - -int MMCloseMMBD_XP(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - if (!hMiraMonLayer) - return 1; - - if (hMiraMonLayer->pMMBDXP && hMiraMonLayer->pMMBDXP->pfDataBase) - { - fclose_function(hMiraMonLayer->pMMBDXP->pfDataBase); - hMiraMonLayer->pMMBDXP->pfDataBase = nullptr; - } - - if (hMiraMonLayer->bIsPoint) - return MMCloseMMBD_XPFile(hMiraMonLayer, - &hMiraMonLayer->MMPoint.MMAdmDB); - if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) - { - if (MMCloseMMBD_XPFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB)) - return 1; - return MMCloseMMBD_XPFile(hMiraMonLayer, - &hMiraMonLayer->MMArc.MMNode.MMAdmDB); - } - if (hMiraMonLayer->bIsPolygon) - { - if (MMCloseMMBD_XPFile(hMiraMonLayer, - &hMiraMonLayer->MMPolygon.MMAdmDB)) - return 1; - if (MMCloseMMBD_XPFile(hMiraMonLayer, - &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB)) - return 1; - return MMCloseMMBD_XPFile( - hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB); - } - if (hMiraMonLayer->bIsDBF) - return MMCloseMMBD_XPFile(hMiraMonLayer, - &hMiraMonLayer->MMAdmDBWriting); - - return 0; -} - -// Destroys the memory used to create a MiraMon table associated -// with a vector layer. -static void MMDestroyMMDBFile(struct MiraMonVectLayerInfo *hMiraMonLayer, - struct MMAdmDatabase *pMMAdmDB) -{ - if (!hMiraMonLayer) - return; - - if (pMMAdmDB && pMMAdmDB->szRecordOnCourse) - { - free_function(pMMAdmDB->szRecordOnCourse); - pMMAdmDB->szRecordOnCourse = nullptr; - } - if (hMiraMonLayer->szStringToOperate) - { - free_function(hMiraMonLayer->szStringToOperate); - hMiraMonLayer->szStringToOperate = nullptr; - hMiraMonLayer->nNumStringToOperate = 0; - } - - if (pMMAdmDB && pMMAdmDB->pMMBDXP) - { - MM_ReleaseDBFHeader(pMMAdmDB->pMMBDXP); - hMiraMonLayer->pMMBDXP = pMMAdmDB->pMMBDXP = nullptr; - } - if (pMMAdmDB && pMMAdmDB->pRecList) - { - free_function(pMMAdmDB->pRecList); - pMMAdmDB->pRecList = nullptr; - } -} - -void MMDestroyMMDB(struct MiraMonVectLayerInfo *hMiraMonLayer) -{ - if (!hMiraMonLayer) - return; - - if (hMiraMonLayer->bIsPoint) - { - MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMPoint.MMAdmDB); - return; - } - if (hMiraMonLayer->bIsArc && !hMiraMonLayer->bIsPolygon) - { - MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMAdmDB); - MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMArc.MMNode.MMAdmDB); - return; - } - if (hMiraMonLayer->bIsPolygon) - { - MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMPolygon.MMAdmDB); - MMDestroyMMDBFile(hMiraMonLayer, - &hMiraMonLayer->MMPolygon.MMArc.MMAdmDB); - MMDestroyMMDBFile(hMiraMonLayer, - &hMiraMonLayer->MMPolygon.MMArc.MMNode.MMAdmDB); - } - if (hMiraMonLayer->bIsDBF) - MMDestroyMMDBFile(hMiraMonLayer, &hMiraMonLayer->MMAdmDBWriting); -} -#ifdef GDAL_COMPILATION -CPL_C_END // Necessary for compiling in GDAL project -#endif diff --git a/ogr/ogrsf_frmts/miramon/mm_wrlayr.h b/ogr/ogrsf_frmts/miramon/mm_wrlayr.h index fe3c9dd9afaa..a1d7bbea6307 100644 --- a/ogr/ogrsf_frmts/miramon/mm_wrlayr.h +++ b/ogr/ogrsf_frmts/miramon/mm_wrlayr.h @@ -10,7 +10,7 @@ #include "gdalmmf.h" // For PTR_MM_CPLRecode, ptr_MM_CPLRecode(), ... #else #include "ogr_api.h" // For OGRLayerH -CPL_C_START // Necessary for compiling in GDAL project +CPL_C_START // Necessary for compiling in GDAL project #endif #ifndef GDAL_COMPILATION @@ -61,11 +61,11 @@ CPL_C_START // Necessary for compiling in GDAL project #define form_filename_function(a, b) MuntaPath((a), (b), TRUE) #define MM_CPLGetBasename(a) TreuAdreca((a)) #define MM_IsNANDouble(x) EsNANDouble((x)) -#define MM_IsDoubleInfinit(x) EsDoubleInfinit((x)) +#define MM_IsDoubleInfinite(x) EsDoubleInfinit((x)) #else -#define calloc_function(a) CPLCalloc(1, (a)) -#define realloc_function CPLRealloc -#define free_function(a) CPLFree((a)) +#define calloc_function(a) VSICalloc(1, (a)) +#define realloc_function VSIRealloc +#define free_function(a) VSIFree((a)) #define fopen_function(f, a) VSIFOpenL((f), (a)) #define fflush_function VSIFFlushL #define fclose_function(f) VSIFCloseL((f)) @@ -98,24 +98,29 @@ CPL_C_START // Necessary for compiling in GDAL project #define form_filename_function(a, b) CPLFormFilename((a), (b), "") #define MM_CPLGetBasename(a) CPLGetBasename((a)) #define MM_IsNANDouble(x) CPLIsNan((x)) -#define MM_IsDoubleInfinit(x) CPLIsInf((x)) +#define MM_IsDoubleInfinite(x) CPLIsInf((x)) #endif /* -------------------------------------------------------------------- */ /* Functions */ /* -------------------------------------------------------------------- */ // MM-GDAL functions -void MMCPLError(int level, int code, const char *message); - -void MMCPLWarning(int level, int code, const char *message); -void MMCPLDebug(const char *c, const char *message); +#ifdef GDAL_COMPILATION +#define MMCPLError CPLError +#define MMCPLWarning CPLError +#define MMCPLDebug CPLDebugOnly +#else + void + MMCPLError(int code, const char *fmt, ...); +void MMCPLWarning(int code, const char *fmt, ...); +void MMCPLDebug(int code, const char *fmt, ...); +#endif // Layer functions int MMInitLayer(struct MiraMonVectLayerInfo *hMiraMonLayer, const char *pzFileName, int LayerVersion, char nMMRecode, - char nMMLanguage, double nMMMemoryRatio, - struct MiraMonDataBase *pLayerDB, MM_BOOLEAN ReadOrWrite, - struct MiraMonVectMapInfo *MMMap); + char nMMLanguage, struct MiraMonDataBase *pLayerDB, + MM_BOOLEAN ReadOrWrite, struct MiraMonVectMapInfo *MMMap); int MMInitLayerByType(struct MiraMonVectLayerInfo *hMiraMonLayer); int MMDestroyLayer(struct MiraMonVectLayerInfo *hMiraMonLayer); int MMCloseLayer(struct MiraMonVectLayerInfo *hMiraMonLayer); @@ -146,7 +151,7 @@ int MMReadFlush(struct MM_FLUSH_INFO *pFlush); int MMReadBlockFromBuffer(struct MM_FLUSH_INFO *FlushInfo); int MMReadGUInt64DependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo, - GUInt64 *nUI64); + GUInt64 *pnUI64); int MMReadOffsetDependingOnVersion(struct MiraMonVectLayerInfo *hMiraMonLayer, struct MM_FLUSH_INFO *FlushInfo, MM_FILE_OFFSET *nUI64); @@ -195,7 +200,8 @@ int MMResizeDoublePointer(MM_COORD_TYPE **pDouble, MM_N_VERTICES_TYPE *nMax, int MMResizeStringToOperateIfNeeded(struct MiraMonVectLayerInfo *hMiraMonLayer, MM_EXT_DBF_N_FIELDS nNewSize); int MMIsEmptyString(const char *string); -char *MMGetNFieldValue(const char *pszStringList, GUInt32 nIRecord); +int MMGetNFieldValue(const char *pszStringList, GUInt32 nIRecord, + char *pszPartOfRawValue, size_t nSizeOfRawValue); // Metadata functions int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *result, MM_BYTE direction); @@ -208,7 +214,7 @@ int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *result, MMReturnCodeFromMM_m_idofic((pSRS), (szResult), MMSRS_FROM_EPSG) int MMWriteVectorMetadata(struct MiraMonVectLayerInfo *hMiraMonLayer); -int MMCheck_REL_FILE(char *szREL_file); +int MMCheck_REL_FILE(const char *szREL_file); #ifdef GDAL_COMPILATION CPL_C_END // Necessary for compiling in GDAL project diff --git a/ogr/ogrsf_frmts/miramon/ogrmiramon.h b/ogr/ogrsf_frmts/miramon/ogrmiramon.h index d7516daa3c36..cbef1169a460 100644 --- a/ogr/ogrsf_frmts/miramon/ogrmiramon.h +++ b/ogr/ogrsf_frmts/miramon/ogrmiramon.h @@ -2,7 +2,7 @@ * $Id$ * * Project: OpenGIS Simple Features Reference Implementation - * Purpose: C API to create a MiraMon layer + * Purpose: C++ classes for the MiraMon driver * Author: Abel Pau ****************************************************************************** * Copyright (c) 2024, Xavier Pons @@ -23,7 +23,7 @@ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef OGRMIRAMON_H_INCLUDED @@ -42,14 +42,15 @@ class OGRMiraMonLayer final : public OGRLayer, public OGRGetNextFeatureThroughRaw { - OGRSpatialReference *m_poSRS = nullptr; - OGRFeatureDefn *poFeatureDefn; + GDALDataset *m_poDS; + OGRSpatialReference *m_poSRS; + OGRFeatureDefn *m_poFeatureDefn; - GUIntBig iNextFID; + GUIntBig m_iNextFID; // Pointer to one of three possible MiraMon layers: points, // arcs or polygons. Every time a feature is read this pointer - // points to the appropiate layer + // points to the appropriate layer struct MiraMonVectLayerInfo *phMiraMonLayer; // When writing a layer @@ -62,22 +63,11 @@ class OGRMiraMonLayer final struct MiraMonFeature hMMFeature; // Feature reading/writing - bool bUpdate; - - // Ratio used to enhance certain aspects of memory - // In some memory settings, a block of 256 or 512 bytes is used. - // This parameter can be adjusted to achieve - // nMemoryRatio*256 or nMemoryRatio*512. - // For example, nMemoryRatio=2 in powerful computers and - // nMemoryRatio=0.5 in less powerful computers. - // By increasing this parameter, more memory will be required, - // but there will be fewer read/write operations to the disk. - double nMMMemoryRatio; + bool m_bUpdate; VSILFILE *m_fp = nullptr; - // Array of string or doubles used in the field features processing - char **papszValues; + // Array of doubles used in the field features processing double *padfValues; OGRFeature *GetNextRawFeature(); @@ -98,7 +88,7 @@ class OGRMiraMonLayer final public: bool bValidFile; - OGRMiraMonLayer(const char *pszFilename, VSILFILE *fp, + OGRMiraMonLayer(GDALDataset *poDS, const char *pszFilename, VSILFILE *fp, const OGRSpatialReference *poSRS, int bUpdate, CSLConstList papszOpenOptions, struct MiraMonVectMapInfo *MMMap); @@ -125,10 +115,16 @@ class OGRMiraMonLayer final int bApproxOK = TRUE) override; int TestCapability(const char *) override; + void AddToFileList(CPLStringList &oFileList); + + GDALDataset *GetDataset() override + { + return m_poDS; + } }; /************************************************************************/ -/* OGRMiraMonDataSource */ +/* OGRMiraMonDataSource */ /************************************************************************/ class OGRMiraMonDataSource final : public OGRDataSource @@ -160,6 +156,7 @@ class OGRMiraMonDataSource final : public OGRDataSource } OGRLayer *GetLayer(int) override; + char **GetFileList() override; OGRLayer *ICreateLayer(const char *pszLayerName, const OGRGeomFieldDefn *poGeomFieldDefn, diff --git a/ogr/ogrsf_frmts/miramon/ogrmiramondatasource.cpp b/ogr/ogrsf_frmts/miramon/ogrmiramondatasource.cpp index 6d842662993d..92b2572c29dd 100644 --- a/ogr/ogrsf_frmts/miramon/ogrmiramondatasource.cpp +++ b/ogr/ogrsf_frmts/miramon/ogrmiramondatasource.cpp @@ -22,7 +22,7 @@ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "ogrmiramon.h" @@ -68,7 +68,7 @@ int OGRMiraMonDataSource::Open(const char *pszFilename, VSILFILE *fp, bUpdate = CPL_TO_BOOL(bUpdateIn); OGRMiraMonLayer *poLayer = new OGRMiraMonLayer( - pszFilename, fp, poSRS, bUpdate, papszOpenOptionsUsr, &MMMap); + this, pszFilename, fp, poSRS, bUpdate, papszOpenOptionsUsr, &MMMap); if (!poLayer->bValidFile) { delete poLayer; @@ -86,21 +86,33 @@ int OGRMiraMonDataSource::Open(const char *pszFilename, VSILFILE *fp, if (!EQUAL(pszExtension, "pol") && !EQUAL(pszExtension, "arc") && !EQUAL(pszExtension, "pnt")) { - strcpy( + CPLStrlcpy( MMMap.pszMapName, - CPLFormFilename(pszDSName, CPLGetBasename(pszDSName), "mmm")); + CPLFormFilename(pszDSName, CPLGetBasename(pszDSName), "mmm"), + sizeof(MMMap.pszMapName)); if (!MMMap.nNumberOfLayers) { MMMap.fMMMap = VSIFOpenL(MMMap.pszMapName, "w+"); - VSIFPrintfL(MMMap.fMMMap, "[VERSIO]\n"); - VSIFPrintfL(MMMap.fMMMap, "Vers=2\n"); - VSIFPrintfL(MMMap.fMMMap, "SubVers=0\n"); - VSIFPrintfL(MMMap.fMMMap, "variant=b\n"); - VSIFPrintfL(MMMap.fMMMap, "\n"); - VSIFPrintfL(MMMap.fMMMap, "[DOCUMENT]\n"); - VSIFPrintfL(MMMap.fMMMap, "Titol= %s(map)\n", - CPLGetBasename(poLayer->GetName())); - VSIFPrintfL(MMMap.fMMMap, "\n"); + if (!MMMap.fMMMap) + { + // It could be an error but it is not so important + // to stop the process. This map is an extra element + // to open all layers in one click, at least in MiraMon + // software. + *MMMap.pszMapName = '\0'; + } + else + { + VSIFPrintfL(MMMap.fMMMap, "[VERSIO]\n"); + VSIFPrintfL(MMMap.fMMMap, "Vers=2\n"); + VSIFPrintfL(MMMap.fMMMap, "SubVers=0\n"); + VSIFPrintfL(MMMap.fMMMap, "variant=b\n"); + VSIFPrintfL(MMMap.fMMMap, "\n"); + VSIFPrintfL(MMMap.fMMMap, "[DOCUMENT]\n"); + VSIFPrintfL(MMMap.fMMMap, "Titol= %s(map)\n", + CPLGetBasename(poLayer->GetName())); + VSIFPrintfL(MMMap.fMMMap, "\n"); + } } } else @@ -127,6 +139,7 @@ int OGRMiraMonDataSource::Create(const char *pszDataSetName, char ** /* papszOptions */) { + bUpdate = TRUE; pszDSName = CPLStrdup(pszDataSetName); pszRootName = CPLStrdup(pszDataSetName); @@ -148,47 +161,14 @@ OGRMiraMonDataSource::ICreateLayer(const char *pszLayerName, const auto poSRS = poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr; - switch (eType) + // It's a seed to be able to generate a random identifier in + // MMGenerateFileIdentifierFromMetadataFileName() function + srand((unsigned int)time(nullptr)); + + if (OGR_GT_HasM(eType)) { - case wkbPointM: - case wkbLineStringM: - case wkbPolygonM: - case wkbMultiPointM: - case wkbMultiLineStringM: - case wkbMultiPolygonM: - case wkbGeometryCollectionM: - case wkbCircularStringM: - case wkbCompoundCurveM: - case wkbCurvePolygonM: - case wkbMultiCurveM: - case wkbMultiSurfaceM: - case wkbCurveM: - case wkbSurfaceM: - case wkbPolyhedralSurfaceM: - case wkbTINM: - case wkbTriangleM: - case wkbPointZM: - case wkbLineStringZM: - case wkbPolygonZM: - case wkbMultiPointZM: - case wkbMultiLineStringZM: - case wkbMultiPolygonZM: - case wkbGeometryCollectionZM: - case wkbCircularStringZM: - case wkbCompoundCurveZM: - case wkbCurvePolygonZM: - case wkbMultiCurveZM: - case wkbMultiSurfaceZM: - case wkbCurveZM: - case wkbSurfaceZM: - case wkbPolyhedralSurfaceZM: - case wkbTINZM: - case wkbTriangleZM: - CPLError(CE_Warning, CPLE_NotSupported, - "Measures in this layer will be ignored."); - break; - default: - break; + CPLError(CE_Warning, CPLE_NotSupported, + "Measures in this layer will be ignored."); } /* -------------------------------------------------------------------- */ @@ -209,18 +189,19 @@ OGRMiraMonDataSource::ICreateLayer(const char *pszLayerName, // Checking that the folder where to write exists const char *szDestFolder = CPLGetDirname(pszFullMMLayerName); - char **papszDirContent = nullptr; - papszDirContent = VSIReadDir(szDestFolder); - if (!papszDirContent) + if (!STARTS_WITH(szDestFolder, "/vsimem")) { - CPLFree(pszMMLayerName); - CPLFree(pszFullMMLayerName); - CPLError(CE_Failure, CPLE_AppDefined, - "The folder %s does not exist.", szDestFolder); - return nullptr; + VSIStatBufL sStat; + if (VSIStatL(szDestFolder, &sStat) != 0 || + !VSI_ISDIR(sStat.st_mode)) + { + CPLFree(pszMMLayerName); + CPLFree(pszFullMMLayerName); + CPLError(CE_Failure, CPLE_AppDefined, + "The folder %s does not exist.", szDestFolder); + return nullptr; + } } - else - CSLDestroy(papszDirContent); CPLFree(pszMMLayerName); } else @@ -235,20 +216,20 @@ OGRMiraMonDataSource::ICreateLayer(const char *pszLayerName, /* Let's create the folder if it's not already created. */ /* (only the las level of the folder) */ /* -------------------------------------------------------------------- */ - char **papszDirContent = nullptr; - papszDirContent = VSIReadDir(osPath); - if (!papszDirContent) + if (!STARTS_WITH(osPath, "/vsimem")) { - if (VSIMkdir(osPath, 0755) != 0) + VSIStatBufL sStat; + if (VSIStatL(osPath, &sStat) != 0 || !VSI_ISDIR(sStat.st_mode)) { - CPLFree(pszFullMMLayerName); - CPLError(CE_Failure, CPLE_AppDefined, - "Unable to create the folder %s.", pszRootName); - return nullptr; + if (VSIMkdir(osPath, 0755) != 0) + { + CPLFree(pszFullMMLayerName); + CPLError(CE_Failure, CPLE_AppDefined, + "Unable to create the folder %s.", pszRootName); + return nullptr; + } } } - else - CSLDestroy(papszDirContent); } /* -------------------------------------------------------------------- */ @@ -273,7 +254,7 @@ int OGRMiraMonDataSource::TestCapability(const char *pszCap) { if (EQUAL(pszCap, ODsCCreateLayer)) - return TRUE; + return bUpdate; else if (EQUAL(pszCap, ODsCZGeometries)) return TRUE; @@ -292,3 +273,19 @@ OGRLayer *OGRMiraMonDataSource::GetLayer(int iLayer) return papoLayers[iLayer]; } + +/************************************************************************/ +/* GetFileList() */ +/************************************************************************/ + +char **OGRMiraMonDataSource::GetFileList() +{ + CPLStringList oFileList; + GetLayerCount(); + for (int i = 0; i < nLayers; i++) + { + OGRMiraMonLayer *poLayer = papoLayers[i]; + poLayer->AddToFileList(oFileList); + } + return oFileList.StealList(); +} diff --git a/ogr/ogrsf_frmts/miramon/ogrmiramondriver.cpp b/ogr/ogrsf_frmts/miramon/ogrmiramondriver.cpp index e366c5356633..26884ba0ae4c 100644 --- a/ogr/ogrsf_frmts/miramon/ogrmiramondriver.cpp +++ b/ogr/ogrsf_frmts/miramon/ogrmiramondriver.cpp @@ -22,7 +22,7 @@ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "ogrmiramon.h" @@ -40,9 +40,6 @@ static int OGRMiraMonDriverIdentify(GDALOpenInfo *poOpenInfo) EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "ARC") || EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "POL")) { - if (!poOpenInfo->TryToIngest(7)) - return FALSE; - // Format if ((poOpenInfo->pabyHeader[0] == 'P' && poOpenInfo->pabyHeader[1] == 'N' && @@ -79,27 +76,28 @@ static int OGRMiraMonDriverIdentify(GDALOpenInfo *poOpenInfo) static GDALDataset *OGRMiraMonDriverOpen(GDALOpenInfo *poOpenInfo) { - if (!poOpenInfo->bStatOK) + if (OGRMiraMonDriverIdentify(poOpenInfo) == FALSE) return nullptr; OGRMiraMonDataSource *poDS = new OGRMiraMonDataSource(); - if (!poDS->Open(poOpenInfo->pszFilename, nullptr, nullptr, - poOpenInfo->eAccess == GA_Update, - poOpenInfo->papszOpenOptions)) - { - delete poDS; - return nullptr; - } - - /* Not sure when use that if (poDS != nullptr && poOpenInfo->eAccess == GA_Update) { CPLError(CE_Failure, CPLE_OpenFailed, "MiraMonVector driver does not support update."); delete poDS; poDS = nullptr; - }*/ + } + else + { + if (!poDS->Open(poOpenInfo->pszFilename, nullptr, nullptr, + poOpenInfo->eAccess == GA_Update, + poOpenInfo->papszOpenOptions)) + { + delete poDS; + poDS = nullptr; + } + } return poDS; } @@ -139,7 +137,6 @@ void RegisterOGRMiraMon() poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES"); poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "MiraMon Vectors (.pol, .arc, .pnt)"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "pol"); poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "pol arc pnt"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/miramon.html"); @@ -149,39 +146,22 @@ void RegisterOGRMiraMon() poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "" - " " " " - " " - "