LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/s57 - ogrs57driver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 61 69 88.4 %
Date: 2024-04-29 01:40:10 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  S-57 Translator
       4             :  * Purpose:  Implements OGRS57Driver
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  * Copyright (c) 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 "ogr_s57.h"
      31             : #include "cpl_conv.h"
      32             : #include "cpl_multiproc.h"
      33             : 
      34             : S57ClassRegistrar *OGRS57Driver::poRegistrar = nullptr;
      35             : static CPLMutex *hS57RegistrarMutex = nullptr;
      36             : 
      37             : /************************************************************************/
      38             : /*                            OGRS57Driver()                            */
      39             : /************************************************************************/
      40             : 
      41        1217 : OGRS57Driver::OGRS57Driver()
      42             : {
      43        1217 : }
      44             : 
      45             : /************************************************************************/
      46             : /*                           ~OGRS57Driver()                            */
      47             : /************************************************************************/
      48             : 
      49        1704 : OGRS57Driver::~OGRS57Driver()
      50             : 
      51             : {
      52         852 :     if (poRegistrar != nullptr)
      53             :     {
      54           2 :         delete poRegistrar;
      55           2 :         poRegistrar = nullptr;
      56             :     }
      57             : 
      58         852 :     if (hS57RegistrarMutex != nullptr)
      59             :     {
      60           2 :         CPLDestroyMutex(hS57RegistrarMutex);
      61           2 :         hS57RegistrarMutex = nullptr;
      62             :     }
      63        1704 : }
      64             : 
      65             : /************************************************************************/
      66             : /*                          OGRS57DriverIdentify()                      */
      67             : /************************************************************************/
      68             : 
      69       46243 : static int OGRS57DriverIdentify(GDALOpenInfo *poOpenInfo)
      70             : 
      71             : {
      72       46243 :     if (poOpenInfo->nHeaderBytes < 10)
      73       41211 :         return false;
      74        5032 :     const char *pachLeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
      75        5032 :     if ((pachLeader[5] != '1' && pachLeader[5] != '2' &&
      76        4494 :          pachLeader[5] != '3') ||
      77         612 :         pachLeader[6] != 'L' || (pachLeader[8] != '1' && pachLeader[8] != ' '))
      78             :     {
      79        4958 :         return false;
      80             :     }
      81             :     // Test for S-57 DSID field structure (to distinguish it from S-101)
      82         148 :     return strstr(pachLeader, "DSID") != nullptr &&
      83          74 :            (strstr(pachLeader,
      84             :                    "RCNM!RCID!EXPP!INTU!DSNM!EDTN!UPDN!UADT!ISDT!"
      85           4 :                    "STED!PRSP!PSDN!PRED!PROF!AGEN!COMT") != nullptr ||
      86             :             // Below is for autotest/ogr/data/s57/fake_s57.000 fake dataset that has a shortened structure
      87          78 :             strstr(pachLeader, "RCNM!RCID!EXPP!xxxx") != nullptr);
      88             : }
      89             : 
      90             : /************************************************************************/
      91             : /*                                Open()                                */
      92             : /************************************************************************/
      93             : 
      94          37 : GDALDataset *OGRS57Driver::Open(GDALOpenInfo *poOpenInfo)
      95             : 
      96             : {
      97          37 :     if (!OGRS57DriverIdentify(poOpenInfo))
      98           0 :         return nullptr;
      99             : 
     100          37 :     OGRS57DataSource *poDS = new OGRS57DataSource(poOpenInfo->papszOpenOptions);
     101          37 :     if (!poDS->Open(poOpenInfo->pszFilename))
     102             :     {
     103           0 :         delete poDS;
     104           0 :         poDS = nullptr;
     105             :     }
     106             : 
     107          37 :     if (poDS && poOpenInfo->eAccess == GA_Update)
     108             :     {
     109           0 :         delete poDS;
     110           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
     111             :                  "S57 Driver doesn't support update.");
     112           0 :         return nullptr;
     113             :     }
     114             : 
     115          37 :     return poDS;
     116             : }
     117             : 
     118             : /************************************************************************/
     119             : /*                              Create()                                */
     120             : /************************************************************************/
     121             : 
     122          19 : GDALDataset *OGRS57Driver::Create(const char *pszName, int /* nBands */,
     123             :                                   int /* nXSize */, int /* nYSize */,
     124             :                                   GDALDataType /* eDT */, char **papszOptions)
     125             : {
     126          19 :     OGRS57DataSource *poDS = new OGRS57DataSource();
     127             : 
     128          19 :     if (poDS->Create(pszName, papszOptions))
     129          18 :         return poDS;
     130             : 
     131           1 :     delete poDS;
     132           1 :     return nullptr;
     133             : }
     134             : 
     135             : /************************************************************************/
     136             : /*                          GetS57Registrar()                           */
     137             : /************************************************************************/
     138             : 
     139        5447 : S57ClassRegistrar *OGRS57Driver::GetS57Registrar()
     140             : 
     141             : {
     142             :     /* -------------------------------------------------------------------- */
     143             :     /*      Instantiate the class registrar if possible.                    */
     144             :     /* -------------------------------------------------------------------- */
     145        5447 :     CPLMutexHolderD(&hS57RegistrarMutex);
     146             : 
     147        5447 :     if (poRegistrar == nullptr)
     148             :     {
     149           3 :         poRegistrar = new S57ClassRegistrar();
     150             : 
     151           3 :         if (!poRegistrar->LoadInfo(nullptr, nullptr, false))
     152             :         {
     153           0 :             delete poRegistrar;
     154           0 :             poRegistrar = nullptr;
     155             :         }
     156             :     }
     157             : 
     158       10894 :     return poRegistrar;
     159             : }
     160             : 
     161             : /************************************************************************/
     162             : /*                           RegisterOGRS57()                           */
     163             : /************************************************************************/
     164             : 
     165        1512 : void RegisterOGRS57()
     166             : 
     167             : {
     168        1512 :     if (GDALGetDriverByName("S57") != nullptr)
     169         295 :         return;
     170             : 
     171        1217 :     GDALDriver *poDriver = new OGRS57Driver();
     172             : 
     173        1217 :     poDriver->SetDescription("S57");
     174        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     175        1217 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "IHO S-57 (ENC)");
     176        1217 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "000");
     177        1217 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/s57.html");
     178        1217 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     179             : 
     180        1217 :     poDriver->SetMetadataItem(
     181             :         GDAL_DMD_OPENOPTIONLIST,
     182             :         "<OpenOptionList>"
     183             :         "  <Option name='" S57O_UPDATES
     184             :         "' type='string-select' description='Should update files be "
     185             :         "incorporated into the base data on the fly' default='APPLY'>"
     186             :         "    <Value>APPLY</Value>"
     187             :         "    <Value>IGNORE</Value>"
     188             :         "  </Option>"
     189             :         "  <Option name='" S57O_SPLIT_MULTIPOINT
     190             :         "' type='boolean' description='Should multipoint soundings be split "
     191             :         "into many single point sounding features' default='NO'/>"
     192             :         "  <Option name='" S57O_ADD_SOUNDG_DEPTH
     193             :         "' type='boolean' description='Should a DEPTH attribute be added on "
     194             :         "SOUNDG features and assign the depth of the sounding' default='NO'/>"
     195             :         "  <Option name='" S57O_RETURN_PRIMITIVES
     196             :         "' type='boolean' description='Should all the low level geometry "
     197             :         "primitives be returned as special IsolatedNode, ConnectedNode, Edge "
     198             :         "and Face layers' default='NO'/>"
     199             :         "  <Option name='" S57O_PRESERVE_EMPTY_NUMBERS
     200             :         "' type='boolean' description='If enabled, numeric attributes assigned "
     201             :         "an empty string as a value will be preserved as a special numeric "
     202             :         "value' default='NO'/>"
     203             :         "  <Option name='" S57O_LNAM_REFS
     204             :         "' type='boolean' description='Should LNAM and LNAM_REFS fields be "
     205             :         "attached to features capturing the feature to feature relationships "
     206             :         "in the FFPT group of the S-57 file' default='NO'/>"
     207             :         "  <Option name='" S57O_RETURN_LINKAGES
     208             :         "' type='boolean' description='Should additional attributes relating "
     209             :         "features to their underlying geometric primitives be attached' "
     210             :         "default='NO'/>"
     211             :         "  <Option name='" S57O_RECODE_BY_DSSI
     212             :         "' type='boolean' description='Should attribute values be recoded to "
     213             :         "UTF-8 from the character encoding specified in the S57 DSSI record.' "
     214             :         "default='YES'/>"
     215             :         "  <Option name='" S57O_LIST_AS_STRING
     216             :         "' type='boolean' description='Whether attributes tagged as list in "
     217             :         "S57 dictionaries should be reported as a String field' default='NO'/>"
     218        1217 :         "</OpenOptionList>");
     219        1217 :     poDriver->SetMetadataItem(
     220             :         GDAL_DMD_CREATIONOPTIONLIST,
     221             :         "<CreationOptionList>"
     222             :         "   <Option name='S57_EXPP' type='int' description='Exchange purpose' "
     223             :         "default='1'/>"
     224             :         "   <Option name='S57_INTU' type='int' description='Intended usage' "
     225             :         "default='4'/>"
     226             :         "   <Option name='S57_EDTN' type='string' description='Edition number' "
     227             :         "default='2'/>"
     228             :         "   <Option name='S57_UPDN' type='string' description='Update number' "
     229             :         "default='0'/>"
     230             :         "   <Option name='S57_UADT' type='string' description='Update "
     231             :         "application date' default='20030801'/>"
     232             :         "   <Option name='S57_ISDT' type='string' description='Issue date' "
     233             :         "default='20030801'/>"
     234             :         "   <Option name='S57_STED' type='string' description='Edition number "
     235             :         "of S-57' default='03.1'/>"
     236             :         "   <Option name='S57_AGEN' type='int' description='Producing agency' "
     237             :         "default='540'/>"
     238             :         "   <Option name='S57_COMT' type='string' description='Comment' "
     239             :         "default=''/>"
     240             :         "   <Option name='S57_AALL' type='int' description='Lexical level used "
     241             :         "for the ATTF fields' default='0'/>"
     242             :         "   <Option name='S57_NALL' type='int' description='Lexical level used "
     243             :         "for the NATF fields' default='0'/>"
     244             :         "   <Option name='S57_NOMR' type='int' description='Number of meta "
     245             :         "records (objects with acronym starting with \"M_\")' default='0'/>"
     246             :         "   <Option name='S57_NOGR' type='int' description='Number of geo "
     247             :         "records' default='0'/>"
     248             :         "   <Option name='S57_NOLR' type='int' description='Number of "
     249             :         "collection records' default='0'/>"
     250             :         "   <Option name='S57_NOIN' type='int' description='Number of isolated "
     251             :         "node records' default='0'/>"
     252             :         "   <Option name='S57_NOCN' type='int' description='Number of "
     253             :         "connected node records' default='0'/>"
     254             :         "   <Option name='S57_NOED' type='int' description='Number of edge "
     255             :         "records' default='0'/>"
     256             :         "   <Option name='S57_HDAT' type='int' description='Horizontal "
     257             :         "geodetic datum' default='2'/>"
     258             :         "   <Option name='S57_VDAT' type='int' description='Vertical datum' "
     259             :         "default='17'/>"
     260             :         "   <Option name='S57_SDAT' type='int' description='Sounding datum' "
     261             :         "default='23'/>"
     262             :         "   <Option name='S57_CSCL' type='int' description='Compilation scale "
     263             :         "of data (1:X)' default='52000'/>"
     264             :         "   <Option name='S57_COMF' type='int' description='Floating-point to "
     265             :         "integer multiplication factor for coordinate values' "
     266             :         "default='10000000'/>"
     267             :         "   <Option name='S57_SOMF' type='int' description='Floating point to "
     268             :         "integer multiplication factor for 3-D (sounding) values' "
     269             :         "default='10'/>"
     270        1217 :         "</CreationOptionList>");
     271             : 
     272        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     273        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES");
     274        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
     275             : 
     276        1217 :     poDriver->pfnOpen = OGRS57Driver::Open;
     277        1217 :     poDriver->pfnIdentify = OGRS57DriverIdentify;
     278        1217 :     poDriver->pfnCreate = OGRS57Driver::Create;
     279             : 
     280        1217 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     281             : }

Generated by: LCOV version 1.14