LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/ogdi - ogrogdidatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 86 121 71.1 %
Date: 2024-04-30 17:17:22 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OGDI Bridge
       4             :  * Purpose:  Implements OGROGDIDataSource class.
       5             :  * Author:   Daniel Morissette, danmo@videotron.ca
       6             :  *           (Based on some code contributed by Frank Warmerdam :)
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2000, Daniel Morissette
      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 "ogrogdi.h"
      31             : 
      32             : #include "cpl_conv.h"
      33             : #include "cpl_string.h"
      34             : 
      35             : /************************************************************************/
      36             : /*                         OGROGDIDataSource()                          */
      37             : /************************************************************************/
      38             : 
      39           4 : OGROGDIDataSource::OGROGDIDataSource()
      40             :     : m_papoLayers(nullptr), m_nLayers(0), m_nClientID(-1),
      41             :       m_poSpatialRef(nullptr), m_poCurrentLayer(nullptr),
      42             :       m_pszFullName(nullptr),
      43             :       m_bLaunderLayerNames(
      44           4 :           CPLTestBool(CPLGetConfigOption("OGR_OGDI_LAUNDER_LAYER_NAMES", "NO")))
      45             : {
      46           4 :     m_sGlobalBounds.north = 0.0;
      47           4 :     m_sGlobalBounds.south = 0.0;
      48           4 :     m_sGlobalBounds.east = 0.0;
      49           4 :     m_sGlobalBounds.west = 0.0;
      50           4 :     m_sGlobalBounds.ns_res = 0.0;
      51           4 :     m_sGlobalBounds.ew_res = 0.0;
      52           4 : }
      53             : 
      54             : /************************************************************************/
      55             : /*                         ~OGROGDIDataSource()                         */
      56             : /************************************************************************/
      57             : 
      58           8 : OGROGDIDataSource::~OGROGDIDataSource()
      59             : 
      60             : {
      61           4 :     CPLFree(m_pszFullName);
      62             : 
      63          23 :     for (int i = 0; i < m_nLayers; i++)
      64          19 :         delete m_papoLayers[i];
      65           4 :     CPLFree(m_papoLayers);
      66             : 
      67           4 :     if (m_nClientID != -1)
      68             :     {
      69           4 :         ecs_Result *psResult = cln_DestroyClient(m_nClientID);
      70           4 :         ecs_CleanUp(psResult);
      71             :     }
      72             : 
      73           4 :     if (m_poSpatialRef)
      74           4 :         m_poSpatialRef->Release();
      75           8 : }
      76             : 
      77             : /************************************************************************/
      78             : /*                                Open()                                */
      79             : /************************************************************************/
      80             : 
      81           4 : int OGROGDIDataSource::Open(const char *pszNewName)
      82             : 
      83             : {
      84           4 :     CPLAssert(m_nLayers == 0);
      85             : 
      86             :     /* -------------------------------------------------------------------- */
      87             :     /*      Parse the dataset name.                                         */
      88             :     /*      i.e.                                                            */
      89             :     /* gltp://<hostname>/<format>/<path_to_dataset>[:<layer_name>:<Family>] */
      90             :     /*                                                                      */
      91             :     /*      Where <Family> is one of: Line, Area, Point, and Text           */
      92             :     /* -------------------------------------------------------------------- */
      93           4 :     if (!STARTS_WITH_CI(pszNewName, "gltp:"))
      94           0 :         return FALSE;
      95             : 
      96           4 :     char *pszWorkingName = CPLStrdup(pszNewName);
      97             : 
      98           4 :     char *pszFamily = strrchr(pszWorkingName, ':');
      99           4 :     CPLAssert(pszFamily);
     100             : 
     101             :     // Don't treat drive name colon as family separator.  It is assumed
     102             :     // that drive names are on character long, and preceded by a
     103             :     // forward or backward slash.
     104           4 :     if (pszFamily < pszWorkingName + 2 || pszFamily[-2] == '/' ||
     105           4 :         pszFamily[-2] == '\\')
     106           0 :         pszFamily = nullptr;
     107             : 
     108           4 :     char *pszLyrName = nullptr;
     109           4 :     if (pszFamily && pszFamily != pszWorkingName + 4)
     110             :     {
     111           1 :         *pszFamily = '\0';
     112           1 :         pszFamily++;
     113             : 
     114           1 :         pszLyrName = strrchr(pszWorkingName, ':');
     115           1 :         if (pszLyrName == pszWorkingName + 4)
     116           0 :             pszLyrName = nullptr;
     117             : 
     118           1 :         if (pszLyrName != nullptr)
     119             :         {
     120           1 :             *pszLyrName = '\0';
     121           1 :             pszLyrName++;
     122             :         }
     123             :     }
     124             : 
     125             :     /* -------------------------------------------------------------------- */
     126             :     /*      Open the client interface.                                      */
     127             :     /* -------------------------------------------------------------------- */
     128           4 :     ecs_Result *psResult = cln_CreateClient(&m_nClientID, pszWorkingName);
     129             : 
     130           4 :     if (ECSERROR(psResult))
     131             :     {
     132           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     133             :                  "OGDI DataSource Open Failed: %s\n",
     134           0 :                  psResult->message ? psResult->message : "(no message string)");
     135           0 :         CPLFree(pszWorkingName);
     136           0 :         return FALSE;
     137             :     }
     138             : 
     139           4 :     m_pszFullName = CPLStrdup(pszNewName);
     140             : 
     141             :     /* -------------------------------------------------------------------- */
     142             :     /*      Capture some information from the file.                         */
     143             :     /* -------------------------------------------------------------------- */
     144           4 :     psResult = cln_GetGlobalBound(m_nClientID);
     145           4 :     if (ECSERROR(psResult))
     146             :     {
     147           0 :         CPLError(CE_Failure, CPLE_AppDefined, "GetGlobalBound failed: %s",
     148           0 :                  psResult->message ? psResult->message : "(no message string)");
     149           0 :         CPLFree(pszWorkingName);
     150           0 :         return FALSE;
     151             :     }
     152             : 
     153           4 :     m_sGlobalBounds = ECSREGION(psResult);
     154             : 
     155           4 :     psResult = cln_GetServerProjection(m_nClientID);
     156           4 :     if (ECSERROR(psResult))
     157             :     {
     158           0 :         CPLError(CE_Failure, CPLE_AppDefined, "GetServerProjection failed: %s",
     159           0 :                  psResult->message ? psResult->message : "(no message string)");
     160           0 :         CPLFree(pszWorkingName);
     161           0 :         return FALSE;
     162             :     }
     163             : 
     164           4 :     m_poSpatialRef = new OGRSpatialReference;
     165           4 :     m_poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     166             : 
     167           8 :     CPLString osProjString(ECSTEXT(psResult));
     168           4 :     osProjString.replaceAll("datum=wgs84", "datum=WGS84");
     169           4 :     if (m_poSpatialRef->importFromProj4(osProjString) != OGRERR_NONE)
     170             :     {
     171           0 :         CPLError(CE_Warning, CPLE_NotSupported,
     172             :                  "untranslatable PROJ.4 projection: %s\n",
     173           0 :                  ECSTEXT(psResult) ? ECSTEXT(psResult) : "(no message string)");
     174           0 :         delete m_poSpatialRef;
     175           0 :         m_poSpatialRef = nullptr;
     176             :     }
     177             : 
     178             :     /* -------------------------------------------------------------------- */
     179             :     /*      Select the global region.                                       */
     180             :     /* -------------------------------------------------------------------- */
     181           4 :     psResult = cln_SelectRegion(m_nClientID, &m_sGlobalBounds);
     182           4 :     if (ECSERROR(psResult))
     183             :     {
     184           0 :         CPLError(CE_Failure, CPLE_AppDefined, "SelectRegion failed: %s",
     185           0 :                  psResult->message ? psResult->message : "(no message string)");
     186           0 :         CPLFree(pszWorkingName);
     187           0 :         return FALSE;
     188             :     }
     189             : 
     190             :     /* -------------------------------------------------------------------- */
     191             :     /*      If an explicit layer was selected, just create that layer.      */
     192             :     /* -------------------------------------------------------------------- */
     193           4 :     m_poCurrentLayer = nullptr;
     194             : 
     195           4 :     if (pszLyrName != nullptr)
     196             :     {
     197             :         ecs_Family eFamily;
     198             : 
     199           1 :         if (EQUAL(pszFamily, "Line"))
     200           0 :             eFamily = Line;
     201           1 :         else if (EQUAL(pszFamily, "Area"))
     202           1 :             eFamily = Area;
     203           0 :         else if (EQUAL(pszFamily, "Point"))
     204           0 :             eFamily = Point;
     205           0 :         else if (EQUAL(pszFamily, "Text"))
     206           0 :             eFamily = Text;
     207             :         else
     208             :         {
     209           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     210             :                      "Invalid or unsupported family name (%s) in URL %s\n",
     211             :                      pszFamily, m_pszFullName);
     212           0 :             CPLFree(pszWorkingName);
     213           0 :             return FALSE;
     214             :         }
     215             : 
     216           1 :         IAddLayer(pszLyrName, eFamily);
     217             :     }
     218             : 
     219             :     /* -------------------------------------------------------------------- */
     220             :     /*      Otherwise create a layer for every layer in the capabilities.   */
     221             :     /* -------------------------------------------------------------------- */
     222             :     else
     223             :     {
     224             :         // Call cln_UpdateDictionary so as to be able to report errors
     225             :         // since cln_GetLayerCapabilities() cannot do that
     226             :         // Help in the case of DNC17/COA17A that has a missing env/fcs file
     227           3 :         char *szEmpty = CPLStrdup("");
     228           3 :         psResult = cln_UpdateDictionary(m_nClientID, szEmpty);
     229           3 :         CPLFree(szEmpty);
     230           3 :         if (ECSERROR(psResult))
     231             :         {
     232           0 :             CPLError(CE_Failure, CPLE_AppDefined, "UpdateDictionary failed: %s",
     233           0 :                      psResult->message ? psResult->message
     234             :                                        : "(no message string)");
     235           0 :             CPLFree(pszWorkingName);
     236           0 :             return FALSE;
     237             :         }
     238             : 
     239           3 :         const ecs_LayerCapabilities *psLayerCap = nullptr;
     240          21 :         for (int i = 0;
     241          21 :              (psLayerCap = cln_GetLayerCapabilities(m_nClientID, i)) != nullptr;
     242             :              i++)
     243             :         {
     244          18 :             if (psLayerCap->families[Point])
     245           3 :                 IAddLayer(psLayerCap->name, Point);
     246          18 :             if (psLayerCap->families[Line])
     247           3 :                 IAddLayer(psLayerCap->name, Line);
     248          18 :             if (psLayerCap->families[Area])
     249           6 :                 IAddLayer(psLayerCap->name, Area);
     250          18 :             if (psLayerCap->families[Text])
     251           6 :                 IAddLayer(psLayerCap->name, Text);
     252             :         }
     253             :     }
     254             : 
     255           4 :     CPLFree(pszWorkingName);
     256             : 
     257           4 :     return TRUE;
     258             : }
     259             : 
     260             : /************************************************************************/
     261             : /*                             IAddLayer()                              */
     262             : /*                                                                      */
     263             : /*      Internal helper function for adding one existing layer to       */
     264             : /*      the datasource.                                                 */
     265             : /************************************************************************/
     266             : 
     267          19 : void OGROGDIDataSource::IAddLayer(const char *pszLayerName, ecs_Family eFamily)
     268             : 
     269             : {
     270          38 :     m_papoLayers = (OGROGDILayer **)CPLRealloc(
     271          19 :         m_papoLayers, (m_nLayers + 1) * sizeof(OGROGDILayer *));
     272             : 
     273          19 :     m_papoLayers[m_nLayers++] = new OGROGDILayer(this, pszLayerName, eFamily);
     274          19 : }
     275             : 
     276             : /************************************************************************/
     277             : /*                           TestCapability()                           */
     278             : /************************************************************************/
     279             : 
     280          21 : int OGROGDIDataSource::TestCapability(CPL_UNUSED const char *pszCap)
     281             : 
     282             : {
     283          21 :     return FALSE;
     284             : }
     285             : 
     286             : /************************************************************************/
     287             : /*                              GetLayer()                              */
     288             : /************************************************************************/
     289             : 
     290         452 : OGRLayer *OGROGDIDataSource::GetLayer(int iLayer)
     291             : 
     292             : {
     293         452 :     if (iLayer < 0 || iLayer >= m_nLayers)
     294           2 :         return nullptr;
     295             :     else
     296         450 :         return m_papoLayers[iLayer];
     297             : }

Generated by: LCOV version 1.14