LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/ili - ogrili1datasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 127 142 89.4 %
Date: 2024-04-29 17:29:47 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Interlis 1 Translator
       4             :  * Purpose:  Implements OGRILI1DataSource class.
       5             :  * Author:   Pirmin Kalberer, Sourcepole AG
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
       9             :  * Copyright (c) 2007-2008, 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             : 
      33             : #include "ili1reader.h"
      34             : #include "ogr_ili1.h"
      35             : 
      36             : #include <string>
      37             : 
      38             : /************************************************************************/
      39             : /*                         OGRILI1DataSource()                         */
      40             : /************************************************************************/
      41             : 
      42         130 : OGRILI1DataSource::OGRILI1DataSource()
      43         130 :     : pszName(nullptr), poImdReader(new ImdReader(1)), poReader(nullptr),
      44         130 :       fpTransfer(nullptr), pszTopic(nullptr), nLayers(0), papoLayers(nullptr)
      45             : {
      46         130 : }
      47             : 
      48             : /************************************************************************/
      49             : /*                        ~OGRILI1DataSource()                         */
      50             : /************************************************************************/
      51             : 
      52         260 : OGRILI1DataSource::~OGRILI1DataSource()
      53             : 
      54             : {
      55         167 :     for (int i = 0; i < nLayers; i++)
      56             :     {
      57          37 :         delete papoLayers[i];
      58             :     }
      59         130 :     CPLFree(papoLayers);
      60             : 
      61         130 :     CPLFree(pszName);
      62         130 :     CPLFree(pszTopic);
      63         130 :     DestroyILI1Reader(poReader);
      64         130 :     delete poImdReader;
      65         130 :     if (fpTransfer)
      66             :     {
      67          21 :         VSIFPrintfL(fpTransfer, "ETAB\n");
      68          21 :         VSIFPrintfL(fpTransfer, "ETOP\n");
      69          21 :         VSIFPrintfL(fpTransfer, "EMOD\n");
      70          21 :         VSIFPrintfL(fpTransfer, "ENDE\n");
      71          21 :         VSIFCloseL(fpTransfer);
      72             :     }
      73         260 : }
      74             : 
      75             : /************************************************************************/
      76             : /*                                Open()                                */
      77             : /************************************************************************/
      78             : 
      79         108 : int OGRILI1DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn,
      80             :                             int bTestOpen)
      81             : 
      82             : {
      83         108 :     if (strlen(pszNewName) == 0)
      84             :     {
      85           0 :         return FALSE;
      86             :     }
      87             : 
      88         216 :     std::string osBasename;
      89         216 :     std::string osModelFilename;
      90         108 :     if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr)
      91             :     {
      92           0 :         osBasename = pszNewName;
      93           0 :         osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL");
      94             :     }
      95             :     else
      96             :     {
      97         108 :         char **filenames = CSLTokenizeString2(pszNewName, ",", 0);
      98         108 :         int nCount = CSLCount(filenames);
      99         108 :         if (nCount == 0)
     100             :         {
     101           0 :             CSLDestroy(filenames);
     102           0 :             return FALSE;
     103             :         }
     104         108 :         osBasename = filenames[0];
     105             : 
     106         108 :         if (nCount > 1)
     107          73 :             osModelFilename = filenames[1];
     108             : 
     109         108 :         CSLDestroy(filenames);
     110             :     }
     111             : 
     112             :     /* -------------------------------------------------------------------- */
     113             :     /*      Open the source file.                                           */
     114             :     /* -------------------------------------------------------------------- */
     115         108 :     VSILFILE *fp = VSIFOpenL(osBasename.c_str(), "r");
     116         108 :     if (fp == nullptr)
     117             :     {
     118          57 :         if (!bTestOpen)
     119           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
     120             :                      "Failed to open ILI1 file `%s'.", pszNewName);
     121             : 
     122          57 :         return FALSE;
     123             :     }
     124             : 
     125             :     /* -------------------------------------------------------------------- */
     126             :     /*      If we aren't sure it is ILI1, load a header chunk and check      */
     127             :     /*      for signs it is ILI1                                             */
     128             :     /* -------------------------------------------------------------------- */
     129             :     char szHeader[1000];
     130             : 
     131          51 :     if (bTestOpen)
     132             :     {
     133          51 :         int nLen = (int)VSIFReadL(szHeader, 1, sizeof(szHeader), fp);
     134          51 :         if (nLen == sizeof(szHeader))
     135           5 :             szHeader[sizeof(szHeader) - 1] = '\0';
     136             :         else
     137          46 :             szHeader[nLen] = '\0';
     138             : 
     139          51 :         if (strstr(szHeader, "SCNT") == nullptr)
     140             :         {
     141           3 :             VSIFCloseL(fp);
     142           3 :             return FALSE;
     143             :         }
     144             :     }
     145             : 
     146             :     /* -------------------------------------------------------------------- */
     147             :     /*      We assume now that it is ILI1.  Close and instantiate a          */
     148             :     /*      ILI1Reader on it.                                                */
     149             :     /* -------------------------------------------------------------------- */
     150          48 :     VSIFCloseL(fp);
     151             : 
     152          48 :     poReader = CreateILI1Reader();
     153          48 :     if (poReader == nullptr)
     154             :     {
     155           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     156             :                  "File %s appears to be ILI1 but the ILI1 reader cannot\n"
     157             :                  "be instantiated, likely because Xerces support was not\n"
     158             :                  "configured in.",
     159             :                  pszNewName);
     160           0 :         return FALSE;
     161             :     }
     162             : 
     163          48 :     poReader->OpenFile(osBasename.c_str());
     164             : 
     165          48 :     pszName = CPLStrdup(osBasename.c_str());
     166             : 
     167          48 :     if (osModelFilename.length() > 0)
     168          16 :         poReader->ReadModel(poImdReader, osModelFilename.c_str(), this);
     169             : 
     170          48 :     int bResetConfigOption = FALSE;
     171          48 :     if (EQUAL(CPLGetConfigOption("OGR_ARC_STEPSIZE", ""), ""))
     172             :     {
     173          48 :         bResetConfigOption = TRUE;
     174          48 :         CPLSetThreadLocalConfigOption("OGR_ARC_STEPSIZE", "0.96");
     175             :     }
     176             : 
     177             :     // Parse model and read data - without surface join and area polygonizing.
     178          48 :     poReader->ReadFeatures();
     179             : 
     180          48 :     if (bResetConfigOption)
     181          48 :         CPLSetThreadLocalConfigOption("OGR_ARC_STEPSIZE", nullptr);
     182             : 
     183          48 :     return TRUE;
     184             : }
     185             : 
     186             : /************************************************************************/
     187             : /*                               Create()                               */
     188             : /************************************************************************/
     189             : 
     190          22 : int OGRILI1DataSource::Create(const char *pszFilename,
     191             :                               char ** /* papszOptions */)
     192             : {
     193          22 :     char **filenames = CSLTokenizeString2(pszFilename, ",", 0);
     194             : 
     195          44 :     std::string osBasename = filenames[0];
     196             : 
     197          44 :     std::string osModelFilename;
     198          22 :     if (CSLCount(filenames) > 1)
     199           3 :         osModelFilename = filenames[1];
     200             : 
     201          22 :     CSLDestroy(filenames);
     202             : 
     203             :     /* -------------------------------------------------------------------- */
     204             :     /*      Create the empty file.                                          */
     205             :     /* -------------------------------------------------------------------- */
     206          22 :     fpTransfer = VSIFOpenL(osBasename.c_str(), "w+b");
     207             : 
     208          22 :     if (fpTransfer == nullptr)
     209             :     {
     210           1 :         CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create %s:\n%s",
     211           1 :                  osBasename.c_str(), VSIStrerror(errno));
     212             : 
     213           1 :         return FALSE;
     214             :     }
     215             : 
     216             :     /* -------------------------------------------------------------------- */
     217             :     /*      Parse model                                                     */
     218             :     /* -------------------------------------------------------------------- */
     219          21 :     if (osModelFilename.length() == 0)
     220             :     {
     221          18 :         CPLError(CE_Warning, CPLE_AppDefined,
     222             :                  "Creating Interlis transfer file without model definition.");
     223             :     }
     224             :     else
     225             :     {
     226           3 :         poImdReader->ReadModel(osModelFilename.c_str());
     227             :     }
     228             : 
     229          21 :     pszTopic = CPLStrdup(poImdReader->mainTopicName.c_str());
     230             : 
     231             :     /* -------------------------------------------------------------------- */
     232             :     /*      Write headers                                                   */
     233             :     /* -------------------------------------------------------------------- */
     234          21 :     VSIFPrintfL(fpTransfer, "SCNT\n");
     235          21 :     VSIFPrintfL(fpTransfer, "OGR/GDAL %s, INTERLIS Driver\n",
     236             :                 GDALVersionInfo("RELEASE_NAME"));
     237          21 :     VSIFPrintfL(fpTransfer, "////\n");
     238          21 :     VSIFPrintfL(fpTransfer, "MTID INTERLIS1\n");
     239          21 :     const char *modelname = poImdReader->mainModelName.c_str();
     240          21 :     VSIFPrintfL(fpTransfer, "MODL %s\n", modelname);
     241             : 
     242          21 :     return TRUE;
     243             : }
     244             : 
     245          37 : static char *ExtractTopic(const char *pszLayerName)
     246             : {
     247          37 :     const char *table = strchr(pszLayerName, '_');
     248          37 :     while (table && table[1] != '_')
     249           0 :         table = strchr(table + 1, '_');
     250          40 :     return (table) ? CPLScanString(pszLayerName,
     251           3 :                                    static_cast<int>(table - pszLayerName),
     252             :                                    FALSE, FALSE)
     253          37 :                    : nullptr;
     254             : }
     255             : 
     256             : /************************************************************************/
     257             : /*                           ICreateLayer()                             */
     258             : /************************************************************************/
     259             : 
     260             : OGRLayer *
     261          37 : OGRILI1DataSource::ICreateLayer(const char *pszLayerName,
     262             :                                 const OGRGeomFieldDefn *poGeomFieldDefn,
     263             :                                 CSLConstList /*papszOptions*/)
     264             : {
     265          37 :     const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     266             : 
     267             :     FeatureDefnInfo featureDefnInfo =
     268          37 :         poImdReader->GetFeatureDefnInfo(pszLayerName);
     269          37 :     const char *table = pszLayerName;
     270          37 :     char *topic = ExtractTopic(pszLayerName);
     271          37 :     if (nLayers)
     272          16 :         VSIFPrintfL(fpTransfer, "ETAB\n");
     273          37 :     if (topic)
     274             :     {
     275           3 :         table = pszLayerName + strlen(topic) + 2;  // after "__"
     276           3 :         if (pszTopic == nullptr || !EQUAL(topic, pszTopic))
     277             :         {
     278           1 :             if (pszTopic)
     279             :             {
     280           1 :                 VSIFPrintfL(fpTransfer, "ETOP\n");
     281           1 :                 CPLFree(pszTopic);
     282             :             }
     283           1 :             pszTopic = topic;
     284           1 :             VSIFPrintfL(fpTransfer, "TOPI %s\n", pszTopic);
     285             :         }
     286             :         else
     287             :         {
     288           2 :             CPLFree(topic);
     289             :         }
     290             :     }
     291             :     else
     292             :     {
     293          34 :         if (pszTopic == nullptr)
     294           0 :             pszTopic = CPLStrdup("Unknown");
     295          34 :         VSIFPrintfL(fpTransfer, "TOPI %s\n", pszTopic);
     296             :     }
     297          37 :     VSIFPrintfL(fpTransfer, "TABL %s\n", table);
     298             : 
     299          37 :     OGRFeatureDefn *poFeatureDefn = new OGRFeatureDefn(table);
     300          37 :     poFeatureDefn->SetGeomType(eType);
     301             :     OGRILI1Layer *poLayer =
     302          37 :         new OGRILI1Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
     303             : 
     304          37 :     nLayers++;
     305          37 :     papoLayers = static_cast<OGRILI1Layer **>(
     306          37 :         CPLRealloc(papoLayers, sizeof(OGRILI1Layer *) * nLayers));
     307          37 :     papoLayers[nLayers - 1] = poLayer;
     308             : 
     309          74 :     return poLayer;
     310             : }
     311             : 
     312             : /************************************************************************/
     313             : /*                           TestCapability()                           */
     314             : /************************************************************************/
     315             : 
     316          49 : int OGRILI1DataSource::TestCapability(const char *pszCap)
     317             : 
     318             : {
     319          49 :     if (EQUAL(pszCap, ODsCCreateLayer))
     320          32 :         return TRUE;
     321          17 :     else if (EQUAL(pszCap, ODsCCurveGeometries))
     322           1 :         return TRUE;
     323          16 :     else if (EQUAL(pszCap, ODsCZGeometries))
     324           0 :         return TRUE;
     325             : 
     326          16 :     return FALSE;
     327             : }
     328             : 
     329             : /************************************************************************/
     330             : /*                              GetLayer()                              */
     331             : /************************************************************************/
     332             : 
     333          23 : OGRLayer *OGRILI1DataSource::GetLayer(int iLayer)
     334             : {
     335          23 :     if (!poReader)
     336             :     {
     337           0 :         if (iLayer < 0 || iLayer >= nLayers)
     338           0 :             return nullptr;
     339           0 :         return papoLayers[iLayer];
     340             :     }
     341          23 :     return poReader->GetLayer(iLayer);
     342             : }
     343             : 
     344             : /************************************************************************/
     345             : /*                              GetLayerByName()                              */
     346             : /************************************************************************/
     347             : 
     348          44 : OGRILI1Layer *OGRILI1DataSource::GetLayerByName(const char *pszLayerName)
     349             : {
     350          44 :     if (!poReader)
     351             :     {
     352             :         return reinterpret_cast<OGRILI1Layer *>(
     353           0 :             OGRDataSource::GetLayerByName(pszLayerName));
     354             :     }
     355             : 
     356             :     return reinterpret_cast<OGRILI1Layer *>(
     357          44 :         poReader->GetLayerByName(pszLayerName));
     358             : }

Generated by: LCOV version 1.14