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

Generated by: LCOV version 1.14