LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/ili - ili1reader.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 293 367 79.8 %
Date: 2024-11-21 22:18:42 Functions: 17 18 94.4 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Interlis 1 Reader
       4             :  * Purpose:  Implementation of ILI1Reader class.
       5             :  * Author:   Pirmin Kalberer, Sourcepole AG
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
       9             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_conv.h"
      15             : #include "cpl_string.h"
      16             : #include "ogr_api.h"
      17             : #include "ogr_ili1.h"
      18             : #include "ogr_geos.h"
      19             : 
      20             : #include "ili1reader.h"
      21             : #include "ili1readerp.h"
      22             : 
      23             : #include <vector>
      24             : 
      25             : #ifdef HAVE_GEOS
      26             : #define POLYGONIZE_AREAS
      27             : #endif
      28             : 
      29             : #ifndef POLYGONIZE_AREAS
      30             : #if defined(__GNUC_PREREQ)
      31             : // #    warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 3.1.0
      32             : #endif
      33             : #endif
      34             : 
      35             : //
      36             : // ILI1Reader
      37             : //
      38          48 : IILI1Reader::~IILI1Reader()
      39             : {
      40          48 : }
      41             : 
      42          48 : ILI1Reader::ILI1Reader()
      43             :     : fpItf(nullptr), nLayers(0), papoLayers(nullptr), curLayer(nullptr),
      44          48 :       codeBlank('_'), codeUndefined('@'), codeContinue('\\')
      45             : {
      46          48 : }
      47             : 
      48          96 : ILI1Reader::~ILI1Reader()
      49             : {
      50          48 :     if (fpItf)
      51          48 :         VSIFCloseL(fpItf);
      52             : 
      53         163 :     for (int i = 0; i < nLayers; i++)
      54         115 :         delete papoLayers[i];
      55          48 :     CPLFree(papoLayers);
      56          96 : }
      57             : 
      58             : /* -------------------------------------------------------------------- */
      59             : /*      Open the source file.                                           */
      60             : /* -------------------------------------------------------------------- */
      61          48 : int ILI1Reader::OpenFile(const char *pszFilename)
      62             : {
      63          48 :     fpItf = VSIFOpenL(pszFilename, "r");
      64          48 :     if (fpItf == nullptr)
      65             :     {
      66           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Failed to open ILI file `%s'.",
      67             :                  pszFilename);
      68             : 
      69           0 :         return FALSE;
      70             :     }
      71          48 :     return TRUE;
      72             : }
      73             : 
      74         171 : const char *ILI1Reader::GetLayerNameString(const char *topicname,
      75             :                                            const char *tablename)
      76             : {
      77             : 
      78         171 :     return CPLSPrintf("%s__%s", topicname, tablename);
      79             : }
      80             : 
      81          16 : int ILI1Reader::ReadModel(ImdReader *poImdReader, const char *pszModelFilename,
      82             :                           OGRILI1DataSource *poDS)
      83             : {
      84             : 
      85          16 :     poImdReader->ReadModel(pszModelFilename);
      86          37 :     for (FeatureDefnInfos::const_iterator it =
      87          16 :              poImdReader->featureDefnInfos.begin();
      88          90 :          it != poImdReader->featureDefnInfos.end(); ++it)
      89             :     {
      90             : #if DEBUG_VERBOSE
      91             :         CPLDebug("OGR_ILI", "Adding OGRILI1Layer with table '%s'",
      92             :                  it->GetTableDefnRef()->GetName());
      93             : #endif
      94             :         OGRILI1Layer *layer =
      95          37 :             new OGRILI1Layer(it->GetTableDefnRef(), it->poGeomFieldInfos, poDS);
      96          37 :         AddLayer(layer);
      97             :         // Create additional layers for surface and area geometries.
      98          59 :         for (GeomFieldInfos::const_iterator it2 = it->poGeomFieldInfos.begin();
      99          81 :              it2 != it->poGeomFieldInfos.end(); ++it2)
     100             :         {
     101          22 :             if (it2->second.GetGeomTableDefnRef())
     102             :             {
     103             :                 OGRFeatureDefn *poGeomTableDefn =
     104          15 :                     it2->second.GetGeomTableDefnRef();
     105             :                 OGRGeomFieldDefn *poOGRGeomFieldDefn =
     106          15 :                     poGeomTableDefn->GetGeomFieldDefn(0);
     107          30 :                 GeomFieldInfos oGeomFieldInfos;
     108             :                 // We add iliGeomType to recognize Ili1 geom tables
     109          30 :                 oGeomFieldInfos[poOGRGeomFieldDefn->GetNameRef()].iliGeomType =
     110          30 :                     it2->second.iliGeomType;
     111             : #if DEBUG_VERBOSE
     112             :                 CPLDebug("OGR_ILI",
     113             :                          "Adding OGRILI1Layer with geometry table '%s'",
     114             :                          poGeomTableDefn->GetName());
     115             : #endif
     116             :                 OGRILI1Layer *geomlayer =
     117          15 :                     new OGRILI1Layer(poGeomTableDefn, oGeomFieldInfos, poDS);
     118          15 :                 AddLayer(geomlayer);
     119             :             }
     120             :         }
     121             :     }
     122             : 
     123          16 :     codeBlank = poImdReader->codeBlank;
     124          16 :     CPLDebug("OGR_ILI", "Ili1Format blankCode '%c'", poImdReader->codeBlank);
     125          16 :     codeUndefined = poImdReader->codeUndefined;
     126          16 :     CPLDebug("OGR_ILI", "Ili1Format undefinedCode '%c'",
     127          16 :              poImdReader->codeUndefined);
     128          16 :     codeContinue = poImdReader->codeContinue;
     129          16 :     CPLDebug("OGR_ILI", "Ili1Format continueCode '%c'",
     130          16 :              poImdReader->codeContinue);
     131          16 :     return 0;
     132             : }
     133             : 
     134          48 : int ILI1Reader::ReadFeatures()
     135             : {
     136          48 :     char **tokens = nullptr;
     137          48 :     const char *pszLine = nullptr;
     138          48 :     char *topic = CPLStrdup("(null)");
     139          48 :     int ret = TRUE;
     140             : 
     141         475 :     while (ret && (tokens = ReadParseLine()) != nullptr)
     142             :     {
     143         475 :         const char *firsttok = tokens[0];
     144         475 :         if (EQUAL(firsttok, "SCNT"))
     145             :         {
     146             :             // read description
     147          45 :             do
     148             :             {
     149          93 :                 pszLine = CPLReadLineL(fpItf);
     150          93 :             } while (pszLine && !STARTS_WITH_CI(pszLine, "////"));
     151          48 :             ret = (pszLine != nullptr);
     152             :         }
     153         427 :         else if (EQUAL(firsttok, "MOTR"))
     154             :         {
     155             :             // read model
     156           0 :             do
     157             :             {
     158           0 :                 pszLine = CPLReadLineL(fpItf);
     159           0 :             } while (pszLine && !STARTS_WITH_CI(pszLine, "////"));
     160           0 :             ret = (pszLine != nullptr);
     161             :         }
     162         427 :         else if (EQUAL(firsttok, "MTID"))
     163             :         {
     164             :         }
     165         379 :         else if (EQUAL(firsttok, "MODL"))
     166             :         {
     167             :         }
     168         331 :         else if (EQUAL(firsttok, "TOPI") && CSLCount(tokens) >= 2)
     169             :         {
     170          79 :             CPLFree(topic);
     171          79 :             topic = CPLStrdup(CSLGetField(tokens, 1));
     172             :         }
     173         252 :         else if (EQUAL(firsttok, "TABL") && CSLCount(tokens) >= 2)
     174             :         {
     175             :             const char *layername =
     176         108 :                 GetLayerNameString(topic, CSLGetField(tokens, 1));
     177         108 :             CPLDebug("OGR_ILI", "Reading table '%s'", layername);
     178         108 :             curLayer = GetLayerByName(layername);
     179             : 
     180         108 :             if (curLayer == nullptr)
     181             :             {  // create one
     182          63 :                 CPLError(CE_Warning, CPLE_AppDefined,
     183             :                          "No model definition for table '%s' found, "
     184             :                          "using default field names.",
     185             :                          layername);
     186             :                 OGRFeatureDefn *poFeatureDefn = new OGRFeatureDefn(
     187          63 :                     GetLayerNameString(topic, CSLGetField(tokens, 1)));
     188          63 :                 poFeatureDefn->SetGeomType(wkbUnknown);
     189         126 :                 GeomFieldInfos oGeomFieldInfos;
     190          63 :                 curLayer =
     191          63 :                     new OGRILI1Layer(poFeatureDefn, oGeomFieldInfos, nullptr);
     192          63 :                 AddLayer(curLayer);
     193             :             }
     194         108 :             if (curLayer != nullptr)
     195             :             {
     196         263 :                 for (int i = 0; i < curLayer->GetLayerDefn()->GetFieldCount();
     197             :                      i++)
     198             :                 {
     199         155 :                     CPLDebug("OGR_ILI", "Field %d: %s", i,
     200         155 :                              curLayer->GetLayerDefn()
     201         155 :                                  ->GetFieldDefn(i)
     202             :                                  ->GetNameRef());
     203             :                 }
     204             :             }
     205         108 :             ret = ReadTable(layername);
     206             :         }
     207         144 :         else if (EQUAL(firsttok, "ETOP"))
     208             :         {
     209             :         }
     210          96 :         else if (EQUAL(firsttok, "EMOD"))
     211             :         {
     212             :         }
     213          48 :         else if (EQUAL(firsttok, "ENDE"))
     214             :         {
     215          48 :             CSLDestroy(tokens);
     216          48 :             CPLFree(topic);
     217          48 :             return TRUE;
     218             :         }
     219             :         else
     220             :         {
     221           0 :             CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s",
     222             :                      firsttok);
     223             :         }
     224             : 
     225         427 :         CSLDestroy(tokens);
     226         427 :         tokens = nullptr;
     227             :     }
     228             : 
     229           0 :     CSLDestroy(tokens);
     230           0 :     CPLFree(topic);
     231             : 
     232           0 :     return ret;
     233             : }
     234             : 
     235         108 : int ILI1Reader::ReadTable(CPL_UNUSED const char *layername)
     236             : {
     237         108 :     char **tokens = nullptr;
     238         108 :     int warned = FALSE;
     239         108 :     int geomIdx = -1;
     240             : 
     241         108 :     OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
     242         108 :     OGRFeature *feature = nullptr;
     243         108 :     bool bFeatureAdded = false;
     244             : 
     245         508 :     while ((tokens = ReadParseLine()) != nullptr)
     246             :     {
     247         508 :         const char *firsttok = CSLGetField(tokens, 0);
     248         508 :         if (EQUAL(firsttok, "OBJE"))
     249             :         {
     250         328 :             if (featureDef->GetFieldCount() == 0 &&
     251          62 :                 curLayer->GetFeatureCount() == 0)
     252             :             {
     253          62 :                 CPLError(CE_Warning, CPLE_AppDefined,
     254             :                          "No field definition found for table: %s",
     255          62 :                          featureDef->GetName());
     256             :                 // Model not read - use heuristics.
     257         322 :                 for (int fIndex = 1; tokens[fIndex] != nullptr; fIndex++)
     258             :                 {
     259             :                     char szFieldName[32];
     260         260 :                     snprintf(szFieldName, sizeof(szFieldName), "Field%02d",
     261             :                              fIndex);
     262         520 :                     OGRFieldDefn oFieldDefn(szFieldName, OFTString);
     263         260 :                     featureDef->AddFieldDefn(&oFieldDefn);
     264             :                 }
     265             :             }
     266             :             // start new feature
     267         266 :             if (!bFeatureAdded)
     268         107 :                 delete feature;
     269         266 :             feature = new OGRFeature(featureDef);
     270             : 
     271        1437 :             for (int fIndex = 1, fieldno = 0;
     272        2707 :                  tokens[fIndex] != nullptr &&
     273        1270 :                  fieldno < featureDef->GetFieldCount();
     274             :                  fIndex++, fieldno++)
     275             :             {
     276        1171 :                 if (!(tokens[fIndex][0] == codeUndefined &&
     277         191 :                       tokens[fIndex][1] == '\0'))
     278             :                 {
     279             : #ifdef DEBUG_VERBOSE
     280             :                     CPLDebug("READ TABLE OGR_ILI",
     281             :                              "Setting Field %d (Type %d): %s", fieldno,
     282             :                              featureDef->GetFieldDefn(fieldno)->GetType(),
     283             :                              tokens[fIndex]);
     284             : #endif
     285         980 :                     if (featureDef->GetFieldDefn(fieldno)->GetType() ==
     286             :                         OFTString)
     287             :                     {
     288             :                         // Interlis 1 encoding is ISO 8859-1 (Latin1) -> Recode
     289             :                         // to UTF-8
     290        1606 :                         char *pszRecoded = CPLRecode(
     291         803 :                             tokens[fIndex], CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
     292             :                         // Replace space marks
     293        4427 :                         for (char *pszString = pszRecoded; *pszString != '\0';
     294             :                              pszString++)
     295             :                         {
     296        3624 :                             if (*pszString == codeBlank)
     297          27 :                                 *pszString = ' ';
     298             :                         }
     299         803 :                         feature->SetField(fieldno, pszRecoded);
     300         803 :                         CPLFree(pszRecoded);
     301             :                     }
     302             :                     else
     303             :                     {
     304         177 :                         feature->SetField(fieldno, tokens[fIndex]);
     305             :                     }
     306         980 :                     if (featureDef->GetFieldDefn(fieldno)->GetType() ==
     307         159 :                             OFTReal &&
     308        1139 :                         fieldno > 0 &&
     309         159 :                         featureDef->GetFieldDefn(fieldno - 1)->GetType() ==
     310             :                             OFTReal)
     311             :                     {
     312             :                         // Check for Point geometry (Coord type).
     313             :                         // If there is no ili model read,
     314             :                         // we have no chance to detect the
     315             :                         // geometry column.
     316             :                         CPLString geomfldname =
     317         214 :                             featureDef->GetFieldDefn(fieldno)->GetNameRef();
     318             :                         // Check if name ends with _1.
     319         214 :                         if (geomfldname.size() >= 2 &&
     320         107 :                             geomfldname[geomfldname.size() - 2] == '_')
     321             :                         {
     322             :                             geomfldname =
     323          30 :                                 geomfldname.substr(0, geomfldname.size() - 2);
     324          30 :                             geomIdx = featureDef->GetGeomFieldIndex(
     325          30 :                                 geomfldname.c_str());
     326          30 :                             if (geomIdx == -1)
     327             :                             {
     328           0 :                                 CPLError(
     329             :                                     CE_Warning, CPLE_AppDefined,
     330             :                                     "No matching definition for field '%s' of "
     331             :                                     "table %s found",
     332           0 :                                     geomfldname.c_str(), featureDef->GetName());
     333             :                             }
     334             :                         }
     335             :                         else
     336             :                         {
     337          77 :                             geomIdx = -1;
     338             :                         }
     339         107 :                         if (geomIdx >= 0)
     340             :                         {
     341          60 :                             if (featureDef->GetGeomFieldDefn(geomIdx)
     342          30 :                                     ->GetType() == wkbPoint)
     343             :                             {
     344             :                                 // Add Point geometry.
     345             :                                 OGRPoint *ogrPoint =
     346          27 :                                     new OGRPoint(CPLAtof(tokens[fIndex - 1]),
     347          27 :                                                  CPLAtof(tokens[fIndex]));
     348          27 :                                 feature->SetGeomFieldDirectly(geomIdx,
     349             :                                                               ogrPoint);
     350             :                             }
     351           6 :                             else if (featureDef->GetGeomFieldDefn(geomIdx)
     352           6 :                                              ->GetType() == wkbPoint25D &&
     353           6 :                                      fieldno > 1 &&
     354           3 :                                      featureDef->GetFieldDefn(fieldno - 2)
     355           3 :                                              ->GetType() == OFTReal)
     356             :                             {
     357             :                                 // Add 3D Point geometry.
     358             :                                 OGRPoint *ogrPoint =
     359           3 :                                     new OGRPoint(CPLAtof(tokens[fIndex - 2]),
     360           3 :                                                  CPLAtof(tokens[fIndex - 1]),
     361           3 :                                                  CPLAtof(tokens[fIndex]));
     362           3 :                                 feature->SetGeomFieldDirectly(geomIdx,
     363             :                                                               ogrPoint);
     364             :                             }
     365             :                         }
     366             :                     }
     367             :                 }
     368             :             }
     369         266 :             if (!warned && featureDef->GetFieldCount() != CSLCount(tokens) - 1)
     370             :             {
     371          33 :                 CPLError(CE_Warning, CPLE_AppDefined,
     372             :                          "Field count of table %s doesn't match. %d declared, "
     373             :                          "%d found (e.g. ignored LINEATTR)",
     374          33 :                          featureDef->GetName(), featureDef->GetFieldCount(),
     375          33 :                          CSLCount(tokens) - 1);
     376          33 :                 warned = TRUE;
     377             :             }
     378         266 :             if (feature->GetFieldCount() > 0)
     379             :             {
     380             :                 // USE _TID as FID. TODO: respect IDENT field from model.
     381         266 :                 feature->SetFID(feature->GetFieldAsInteger64(0));
     382             :             }
     383         266 :             curLayer->AddFeature(feature);
     384         266 :             bFeatureAdded = true;
     385         266 :             geomIdx = -1;  // Reset
     386             :         }
     387         242 :         else if (EQUAL(firsttok, "STPT") && feature != nullptr)
     388             :         {
     389             :             // Find next non-Point geometry
     390         133 :             if (geomIdx < 0)
     391         121 :                 geomIdx = 0;
     392         266 :             while (geomIdx < featureDef->GetGeomFieldCount() &&
     393         133 :                    featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint)
     394             :             {
     395           0 :                 geomIdx++;
     396             :             }
     397             :             OGRwkbGeometryType geomType =
     398         133 :                 (geomIdx < featureDef->GetGeomFieldCount())
     399         133 :                     ? featureDef->GetGeomFieldDefn(geomIdx)->GetType()
     400         133 :                     : wkbNone;
     401         133 :             if (CSLCount(tokens) >= 3)
     402         133 :                 ReadGeom(tokens, geomIdx, geomType, feature);
     403             :         }
     404         109 :         else if (EQUAL(firsttok, "ELIN"))
     405             :         {
     406             :             // Empty geom.
     407             :         }
     408         108 :         else if (EQUAL(firsttok, "EDGE") && feature != nullptr)
     409             :         {
     410           0 :             CSLDestroy(tokens);
     411           0 :             tokens = ReadParseLine();  // STPT
     412             :             // Find next non-Point geometry
     413           0 :             do
     414             :             {
     415           0 :                 geomIdx++;
     416           0 :             } while (geomIdx < featureDef->GetGeomFieldCount() &&
     417           0 :                      featureDef->GetGeomFieldDefn(geomIdx)->GetType() ==
     418             :                          wkbPoint);
     419           0 :             if (CSLCount(tokens) >= 3)
     420           0 :                 ReadGeom(tokens, geomIdx, wkbMultiLineString, feature);
     421             :         }
     422         108 :         else if (EQUAL(firsttok, "PERI"))
     423             :         {
     424             :         }
     425         108 :         else if (EQUAL(firsttok, "ETAB"))
     426             :         {
     427         108 :             CPLDebug("OGR_ILI", "Total features: " CPL_FRMT_GIB,
     428         108 :                      curLayer->GetFeatureCount());
     429         108 :             CSLDestroy(tokens);
     430         108 :             if (!bFeatureAdded)
     431           1 :                 delete feature;
     432         108 :             return TRUE;
     433             :         }
     434             :         else
     435             :         {
     436           0 :             CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s",
     437             :                      firsttok);
     438             :         }
     439             : 
     440         400 :         CSLDestroy(tokens);
     441             :     }
     442             : 
     443           0 :     if (!bFeatureAdded)
     444           0 :         delete feature;
     445             : 
     446           0 :     return TRUE;
     447             : }
     448             : 
     449         133 : void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType,
     450             :                           OGRFeature *feature)
     451             : {
     452             : #ifdef DEBUG_VERBOSE
     453             :     CPLDebug("OGR_ILI", "ILI1Reader::ReadGeom geomIdx: %d OGRGeometryType: %s",
     454             :              geomIdx, OGRGeometryTypeToName(eType));
     455             : #endif
     456         133 :     if (eType == wkbNone)
     457             :     {
     458           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     459             :                  "Calling ILI1Reader::ReadGeom with wkbNone");
     460             :     }
     461             : 
     462             :     // Initialize geometry.
     463             : 
     464         133 :     OGRCompoundCurve *ogrCurve = new OGRCompoundCurve();
     465         133 :     OGRCurvePolygon *ogrPoly = nullptr;     // current polygon
     466         133 :     OGRMultiCurve *ogrMultiLine = nullptr;  // current multi line
     467             : 
     468         133 :     if (eType == wkbMultiCurve || eType == wkbMultiLineString)
     469             :     {
     470          60 :         ogrMultiLine = new OGRMultiCurve();
     471             :     }
     472          73 :     else if (eType == wkbPolygon || eType == wkbCurvePolygon)
     473             :     {
     474           0 :         ogrPoly = new OGRCurvePolygon();
     475             :     }
     476             : 
     477         266 :     OGRPoint ogrPoint;  // Current point.
     478         133 :     ogrPoint.setX(CPLAtof(stgeom[1]));
     479         133 :     ogrPoint.setY(CPLAtof(stgeom[2]));
     480             : 
     481         133 :     OGRLineString *ogrLine = new OGRLineString();
     482         133 :     ogrLine->addPoint(&ogrPoint);
     483             : 
     484             :     // Parse geometry.
     485             : 
     486         133 :     char **tokens = nullptr;
     487         133 :     bool end = false;
     488         133 :     OGRCircularString *arc = nullptr;  // current arc
     489             : 
     490         780 :     while (!end && (tokens = ReadParseLine()) != nullptr)
     491             :     {
     492         647 :         const char *firsttok = CSLGetField(tokens, 0);
     493         647 :         if (firsttok == nullptr)
     494             :         {
     495             :             // do nothing
     496             :         }
     497         647 :         else if (EQUAL(firsttok, "LIPT") && CSLCount(tokens) >= 3)
     498             :         {
     499         491 :             ogrPoint.setX(CPLAtof(tokens[1]));
     500         491 :             ogrPoint.setY(CPLAtof(tokens[2]));
     501         491 :             if (arc)
     502             :             {
     503          23 :                 arc->addPoint(&ogrPoint);
     504          23 :                 OGRErr error = ogrCurve->addCurveDirectly(arc);
     505          23 :                 if (error != OGRERR_NONE)
     506             :                 {
     507           0 :                     char *pszJSon = arc->exportToJson();
     508           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     509             :                              "Could not add geometry: %s",
     510             :                              pszJSon ? pszJSon : "(null)");
     511           0 :                     CPLFree(pszJSon);
     512           0 :                     delete arc;
     513             :                 }
     514          23 :                 arc = nullptr;
     515             :             }
     516         491 :             ogrLine->addPoint(&ogrPoint);
     517             :         }
     518         156 :         else if (EQUAL(firsttok, "ARCP") && CSLCount(tokens) >= 3)
     519             :         {
     520             :             // Finish line and start arc
     521          23 :             if (ogrLine->getNumPoints() > 1)
     522             :             {
     523          10 :                 OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
     524          10 :                 if (error != OGRERR_NONE)
     525             :                 {
     526           0 :                     char *pszJSon = ogrLine->exportToJson();
     527           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     528             :                              "Could not add geometry: %s",
     529             :                              pszJSon ? pszJSon : "(null)");
     530           0 :                     CPLFree(pszJSon);
     531           0 :                     delete ogrLine;
     532             :                 }
     533          10 :                 ogrLine = new OGRLineString();
     534             :             }
     535             :             else
     536             :             {
     537          13 :                 ogrLine->empty();
     538             :             }
     539          23 :             delete arc;
     540          23 :             arc = new OGRCircularString();
     541          23 :             arc->addPoint(&ogrPoint);
     542          23 :             ogrPoint.setX(CPLAtof(tokens[1]));
     543          23 :             ogrPoint.setY(CPLAtof(tokens[2]));
     544          23 :             arc->addPoint(&ogrPoint);
     545             :         }
     546         133 :         else if (EQUAL(firsttok, "ELIN"))
     547             :         {
     548         133 :             if (ogrLine->getNumPoints() > 1)
     549             :             {  // Ignore single LIPT after ARCP
     550         133 :                 OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
     551         133 :                 if (error != OGRERR_NONE)
     552             :                 {
     553           0 :                     char *pszJSon = ogrLine->exportToJson();
     554           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     555             :                              "Could not add geometry: %s",
     556             :                              pszJSon ? pszJSon : "(null)");
     557           0 :                     CPLFree(pszJSon);
     558           0 :                     delete ogrLine;
     559             :                 }
     560         133 :                 ogrLine = nullptr;
     561             :             }
     562         133 :             if (!ogrCurve->IsEmpty())
     563             :             {
     564         133 :                 if (ogrMultiLine)
     565             :                 {
     566          60 :                     OGRErr error = ogrMultiLine->addGeometryDirectly(ogrCurve);
     567          60 :                     if (error != OGRERR_NONE)
     568             :                     {
     569           0 :                         char *pszJSon = ogrCurve->exportToJson();
     570           0 :                         CPLError(CE_Warning, CPLE_AppDefined,
     571             :                                  "Could not add geometry: %s",
     572             :                                  pszJSon ? pszJSon : "(null)");
     573           0 :                         CPLFree(pszJSon);
     574           0 :                         delete ogrCurve;
     575             :                     }
     576          60 :                     ogrCurve = nullptr;
     577             :                 }
     578         133 :                 if (ogrPoly)
     579             :                 {
     580           0 :                     OGRErr error = ogrPoly->addRingDirectly(ogrCurve);
     581           0 :                     if (error != OGRERR_NONE)
     582             :                     {
     583           0 :                         char *pszJSon = ogrCurve->exportToJson();
     584           0 :                         CPLError(CE_Warning, CPLE_AppDefined,
     585             :                                  "Could not add geometry: %s",
     586             :                                  pszJSon ? pszJSon : "(null)");
     587           0 :                         CPLFree(pszJSon);
     588           0 :                         delete ogrCurve;
     589             :                     }
     590           0 :                     ogrCurve = nullptr;
     591             :                 }
     592             :             }
     593         133 :             end = true;
     594             :         }
     595           0 :         else if (EQUAL(firsttok, "EEDG"))
     596             :         {
     597           0 :             end = true;
     598             :         }
     599           0 :         else if (EQUAL(firsttok, "LATT"))
     600             :         {
     601             :             // Line Attributes (ignored)
     602             :         }
     603           0 :         else if (EQUAL(firsttok, "EFLA"))
     604             :         {
     605           0 :             end = true;
     606             :         }
     607           0 :         else if (EQUAL(firsttok, "ETAB"))
     608             :         {
     609           0 :             end = true;
     610             :         }
     611             :         else
     612             :         {
     613           0 :             CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s",
     614             :                      firsttok);
     615             :         }
     616             : 
     617         647 :         CSLDestroy(tokens);
     618             :     }
     619         133 :     delete arc;
     620             : 
     621         133 :     delete ogrLine;
     622             : 
     623             :     // Set feature geometry
     624         133 :     if (eType == wkbMultiCurve)
     625             :     {
     626          42 :         feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine);
     627          42 :         delete ogrCurve;
     628             :     }
     629          91 :     else if (eType == wkbMultiLineString)
     630             :     {
     631          18 :         feature->SetGeomFieldDirectly(geomIdx,
     632          18 :                                       ogrMultiLine->getLinearGeometry());
     633          18 :         delete ogrMultiLine;
     634          18 :         delete ogrCurve;
     635             :     }
     636          73 :     else if (eType == wkbCurvePolygon)
     637             :     {
     638           0 :         feature->SetGeomFieldDirectly(geomIdx, ogrPoly);
     639           0 :         delete ogrCurve;
     640             :     }
     641          73 :     else if (eType == wkbPolygon)
     642             :     {
     643           0 :         feature->SetGeomFieldDirectly(geomIdx, ogrPoly->getLinearGeometry());
     644           0 :         delete ogrPoly;
     645           0 :         delete ogrCurve;
     646             :     }
     647             :     else
     648             :     {
     649          73 :         feature->SetGeomFieldDirectly(geomIdx, ogrCurve);
     650             :     }
     651         133 : }
     652             : 
     653             : /************************************************************************/
     654             : /*                              AddLayer()                              */
     655             : /************************************************************************/
     656             : 
     657         115 : void ILI1Reader::AddLayer(OGRILI1Layer *poNewLayer)
     658             : 
     659             : {
     660         115 :     nLayers++;
     661             : 
     662         115 :     papoLayers = static_cast<OGRILI1Layer **>(
     663         115 :         CPLRealloc(papoLayers, sizeof(void *) * nLayers));
     664             : 
     665         115 :     papoLayers[nLayers - 1] = poNewLayer;
     666         115 : }
     667             : 
     668             : /************************************************************************/
     669             : /*                              GetLayer()                              */
     670             : /************************************************************************/
     671             : 
     672          23 : OGRILI1Layer *ILI1Reader::GetLayer(int iLayer)
     673             : 
     674             : {
     675          23 :     if (iLayer < 0 || iLayer >= nLayers)
     676           0 :         return nullptr;
     677             : 
     678          23 :     return papoLayers[iLayer];
     679             : }
     680             : 
     681         152 : OGRILI1Layer *ILI1Reader::GetLayerByName(const char *pszLayerName)
     682             : 
     683             : {
     684         347 :     for (int iLayer = 0; iLayer < nLayers; iLayer++)
     685             :     {
     686         269 :         if (EQUAL(pszLayerName, papoLayers[iLayer]->GetLayerDefn()->GetName()))
     687          74 :             return papoLayers[iLayer];
     688             :     }
     689          78 :     return nullptr;
     690             : }
     691             : 
     692             : /************************************************************************/
     693             : /*                           GetLayerCount()                            */
     694             : /************************************************************************/
     695             : 
     696          64 : int ILI1Reader::GetLayerCount()
     697             : 
     698             : {
     699          64 :     return nLayers;
     700             : }
     701             : 
     702             : /************************************************************************/
     703             : /*     Read one logical line, and return split into fields.  The return */
     704             : /*     result is a stringlist, in the sense of the CSL functions.       */
     705             : /************************************************************************/
     706             : 
     707        1630 : char **ILI1Reader::ReadParseLine()
     708             : {
     709        1630 :     CPLAssert(fpItf != nullptr);
     710        1630 :     if (fpItf == nullptr)
     711           0 :         return nullptr;
     712             : 
     713        1630 :     const char *pszLine = CPLReadLineL(fpItf);
     714        1630 :     if (pszLine == nullptr)
     715           0 :         return nullptr;
     716             : 
     717        1630 :     if (strlen(pszLine) == 0)
     718           0 :         return nullptr;
     719             : 
     720        1630 :     char **tokens = CSLTokenizeString2(pszLine, " ", CSLT_PRESERVEESCAPES);
     721        1630 :     int nCount = CSLCount(tokens);
     722        1630 :     if (nCount == 0)
     723             :     {
     724           0 :         CSLDestroy(tokens);
     725           0 :         return nullptr;
     726             :     }
     727        1630 :     const char *token = tokens[nCount - 1];
     728             : 
     729             :     // Append CONT lines
     730        1634 :     while (strlen(pszLine) && token[0] == codeContinue && token[1] == '\0')
     731             :     {
     732             :         // remove last token
     733           4 :         CPLFree(tokens[CSLCount(tokens) - 1]);
     734           4 :         tokens[CSLCount(tokens) - 1] = nullptr;
     735             : 
     736           4 :         pszLine = CPLReadLineL(fpItf);
     737           4 :         if (pszLine == nullptr)
     738             :         {
     739           0 :             break;
     740             :         }
     741           4 :         char **conttok = CSLTokenizeString2(pszLine, " ", CSLT_PRESERVEESCAPES);
     742           4 :         if (!conttok || conttok[0] == nullptr || !EQUAL(conttok[0], "CONT") ||
     743           4 :             conttok[1] == nullptr)
     744             :         {
     745           0 :             CSLDestroy(conttok);
     746           0 :             break;
     747             :         }
     748             : 
     749             :         // append
     750           4 :         tokens = CSLInsertStrings(tokens, -1, &conttok[1]);
     751           4 :         token = tokens[CSLCount(tokens) - 1];
     752             : 
     753           4 :         CSLDestroy(conttok);
     754             :     }
     755        1630 :     if (tokens[0] == nullptr)
     756             :     {
     757           0 :         CSLDestroy(tokens);
     758           0 :         tokens = nullptr;
     759             :     }
     760        1630 :     return tokens;
     761             : }
     762             : 
     763          48 : IILI1Reader *CreateILI1Reader()
     764             : {
     765          48 :     return new ILI1Reader();
     766             : }
     767             : 
     768         130 : void DestroyILI1Reader(IILI1Reader *reader)
     769             : {
     770         130 :     if (reader)
     771          48 :         delete reader;
     772         130 : }

Generated by: LCOV version 1.14