LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/selafin - ogrselafindriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 86 140 61.4 %
Date: 2024-05-02 22:57:13 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * Project:  Selafin importer
       3             :  * Purpose:  Implementation of OGR driver for Selafin files.
       4             :  * Author:   François Hissel, francois.hissel@gmail.com
       5             :  *
       6             :  ******************************************************************************
       7             :  * Copyright (c) 2014,  François Hissel <francois.hissel@gmail.com>
       8             :  *
       9             :  * Permission is hereby granted, free of charge, to any person obtaining a
      10             :  * copy of this software and associated documentation files (the "Software"),
      11             :  * to deal in the Software without restriction, including without limitation
      12             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      13             :  * and/or sell copies of the Software, and to permit persons to whom the
      14             :  * Software is furnished to do so, subject to the following conditions:
      15             :  *
      16             :  * The above copyright notice and this permission notice shall be included
      17             :  * in all copies or substantial portions of the Software.
      18             :  *
      19             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      20             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      22             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      24             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      25             :  * DEALINGS IN THE SOFTWARE.
      26             :  ****************************************************************************/
      27             : 
      28             : #include "ogr_selafin.h"
      29             : #include "cpl_conv.h"
      30             : #include "cpl_string.h"
      31             : #include "io_selafin.h"
      32             : 
      33             : /************************************************************************/
      34             : /*                     OGRSelafinDriverIdentify()                       */
      35             : /************************************************************************/
      36             : 
      37       62069 : static int OGRSelafinDriverIdentify(GDALOpenInfo *poOpenInfo)
      38             : {
      39       62069 :     if (poOpenInfo->pabyHeader != nullptr)
      40             :     {
      41        2116 :         if (poOpenInfo->nHeaderBytes < 84 + 8)
      42         194 :             return FALSE;
      43        1922 :         if (poOpenInfo->pabyHeader[0] != 0 || poOpenInfo->pabyHeader[1] != 0 ||
      44         113 :             poOpenInfo->pabyHeader[2] != 0 || poOpenInfo->pabyHeader[3] != 0x50)
      45        1916 :             return FALSE;
      46             : 
      47           6 :         if (poOpenInfo->pabyHeader[84 + 0] != 0 ||
      48           6 :             poOpenInfo->pabyHeader[84 + 1] != 0 ||
      49           6 :             poOpenInfo->pabyHeader[84 + 2] != 0 ||
      50           6 :             poOpenInfo->pabyHeader[84 + 3] != 0x50 ||
      51           6 :             poOpenInfo->pabyHeader[84 + 4] != 0 ||
      52           6 :             poOpenInfo->pabyHeader[84 + 5] != 0 ||
      53           6 :             poOpenInfo->pabyHeader[84 + 6] != 0 ||
      54           6 :             poOpenInfo->pabyHeader[84 + 7] != 8)
      55           0 :             return FALSE;
      56             : 
      57           6 :         return TRUE;
      58             :     }
      59             : 
      60             :     // We can stat() the file but it is not a regular file or we did not
      61             :     // get access to its content
      62       59953 :     if (poOpenInfo->bStatOK)
      63         492 :         return FALSE;
      64             : 
      65       59461 :     return -1;
      66             : }
      67             : 
      68             : /************************************************************************/
      69             : /*                      OGRSelafinDriverOpen()                          */
      70             : /************************************************************************/
      71             : 
      72       20043 : static GDALDataset *OGRSelafinDriverOpen(GDALOpenInfo *poOpenInfo)
      73             : {
      74             : 
      75       20043 :     if (OGRSelafinDriverIdentify(poOpenInfo) == 0)
      76           0 :         return nullptr;
      77             : 
      78       20043 :     OGRSelafinDataSource *poDS = new OGRSelafinDataSource();
      79       20042 :     if (!poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update,
      80             :                     FALSE))
      81             :     {
      82       20040 :         delete poDS;
      83       20040 :         poDS = nullptr;
      84             :     }
      85       20043 :     return poDS;
      86             : }
      87             : 
      88             : /************************************************************************/
      89             : /*                       OGRSelafinDriverCreate()                       */
      90             : /************************************************************************/
      91             : 
      92             : static GDALDataset *
      93          19 : OGRSelafinDriverCreate(const char *pszName, CPL_UNUSED int nXSize,
      94             :                        CPL_UNUSED int nYSize, CPL_UNUSED int nBands,
      95             :                        CPL_UNUSED GDALDataType eDT, char **papszOptions)
      96             : {
      97             :     // First, ensure there isn't any such file yet.
      98             :     VSIStatBufL sStatBuf;
      99          19 :     if (strcmp(pszName, "/dev/stdout") == 0)
     100           0 :         pszName = "/vsistdout/";
     101          19 :     if (VSIStatL(pszName, &sStatBuf) == 0)
     102             :     {
     103           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     104             :                  "It seems a file system object called '%s' already exists.",
     105             :                  pszName);
     106           0 :         return nullptr;
     107             :     }
     108             :     // Parse options
     109          19 :     const char *pszTemp = CSLFetchNameValue(papszOptions, "TITLE");
     110             :     char pszTitle[81];
     111          19 :     int pnDate[6] = {-1, 0};
     112          19 :     if (pszTemp != nullptr)
     113           0 :         strncpy(pszTitle, pszTemp, 72);
     114             :     else
     115          19 :         memset(pszTitle, ' ', 72);
     116          19 :     pszTemp = CSLFetchNameValue(papszOptions, "DATE");
     117          19 :     if (pszTemp != nullptr)
     118             :     {
     119           0 :         const char *pszErrorMessage = "Wrong format for date parameter: must "
     120             :                                       "be \"%%Y-%%m-%%d_%%H:%%M:%%S\", ignored";
     121           0 :         const char *pszc = pszTemp;
     122           0 :         pnDate[0] = atoi(pszTemp);
     123           0 :         if (pnDate[0] <= 0)
     124           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     125             :         else
     126             :         {
     127           0 :             if (pnDate[0] < 100)
     128           0 :                 pnDate[0] += 2000;
     129             :         }
     130           0 :         while (*pszc != 0 && *pszc != '-')
     131           0 :             ++pszc;
     132           0 :         pnDate[1] = atoi(pszc);
     133           0 :         if (pnDate[1] < 0 || pnDate[1] > 12)
     134           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     135           0 :         while (*pszc != 0 && *pszc != '_')
     136           0 :             ++pszc;
     137           0 :         pnDate[2] = atoi(pszc);
     138           0 :         if (pnDate[2] < 0 || pnDate[2] > 59)
     139           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     140           0 :         while (*pszc != 0 && *pszc != '_')
     141           0 :             ++pszc;
     142           0 :         pnDate[3] = atoi(pszc);
     143           0 :         if (pnDate[3] < 0 || pnDate[3] > 23)
     144           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     145           0 :         while (*pszc != 0 && *pszc != ':')
     146           0 :             ++pszc;
     147           0 :         pnDate[4] = atoi(pszc);
     148           0 :         if (pnDate[4] < 0 || pnDate[4] > 59)
     149           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     150           0 :         while (*pszc != 0 && *pszc != ':')
     151           0 :             ++pszc;
     152           0 :         pnDate[5] = atoi(pszc);
     153           0 :         if (pnDate[5] < 0 || pnDate[5] > 59)
     154           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     155             :     }
     156             :     // Create the skeleton of a Selafin file
     157          19 :     VSILFILE *fp = VSIFOpenL(pszName, "wb");
     158          19 :     if (fp == nullptr)
     159             :     {
     160           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     161             :                  "Unable to open %s with write access.", pszName);
     162           1 :         return nullptr;
     163             :     }
     164          18 :     strncpy(pszTitle + 72, "SERAPHIN", 9);
     165          18 :     bool bError = false;
     166          18 :     if (Selafin::write_string(fp, pszTitle, 80) == 0)
     167           0 :         bError = true;
     168          18 :     int pnTemp[10] = {0};
     169          18 :     if (Selafin::write_intarray(fp, pnTemp, 2) == 0)
     170           0 :         bError = true;
     171          18 :     if (pnDate[0] >= 0)
     172           0 :         pnTemp[9] = 1;
     173          18 :     if (Selafin::write_intarray(fp, pnTemp, 10) == 0)
     174           0 :         bError = true;
     175          18 :     if (pnDate[0] >= 0)
     176             :     {
     177           0 :         if (Selafin::write_intarray(fp, pnTemp, 6) == 0)
     178           0 :             bError = true;
     179             :     }
     180          18 :     pnTemp[3] = 1;
     181          18 :     if (Selafin::write_intarray(fp, pnTemp, 4) == 0)
     182           0 :         bError = true;
     183          18 :     if (Selafin::write_intarray(fp, pnTemp, 0) == 0)
     184           0 :         bError = true;
     185          18 :     if (Selafin::write_intarray(fp, pnTemp, 0) == 0)
     186           0 :         bError = true;
     187          18 :     if (Selafin::write_floatarray(fp, nullptr, 0) == 0)
     188           0 :         bError = true;
     189          18 :     if (Selafin::write_floatarray(fp, nullptr, 0) == 0)
     190           0 :         bError = true;
     191          18 :     VSIFCloseL(fp);
     192          18 :     if (bError)
     193             :     {
     194           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Error writing to file %s.",
     195             :                  pszName);
     196           0 :         return nullptr;
     197             :     }
     198             :     // Force it to open as a datasource
     199          18 :     OGRSelafinDataSource *poDS = new OGRSelafinDataSource();
     200          18 :     if (!poDS->Open(pszName, TRUE, TRUE))
     201             :     {
     202           0 :         delete poDS;
     203           0 :         return nullptr;
     204             :     }
     205          18 :     return poDS;
     206             : }
     207             : 
     208             : /************************************************************************/
     209             : /*                      OGRSelafinDriverDelete()                        */
     210             : /************************************************************************/
     211          16 : static CPLErr OGRSelafinDriverDelete(const char *pszFilename)
     212             : {
     213          16 :     if (CPLUnlinkTree(pszFilename) == 0)
     214          16 :         return CE_None;
     215             :     else
     216           0 :         return CE_Failure;
     217             : }
     218             : 
     219             : /************************************************************************/
     220             : /*                           RegisterOGRSelafin()                       */
     221             : /************************************************************************/
     222             : 
     223        1512 : void RegisterOGRSelafin()
     224             : {
     225             : 
     226        1512 :     if (GDALGetDriverByName("Selafin") != nullptr)
     227         295 :         return;
     228             : 
     229        1217 :     GDALDriver *poDriver = new GDALDriver();
     230             : 
     231        1217 :     poDriver->SetDescription("Selafin");
     232        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     233        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
     234        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_DELETE_LAYER, "YES");
     235        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
     236        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_DELETE_FIELD, "YES");
     237        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_REORDER_FIELDS, "YES");
     238        1217 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     239             : 
     240        1217 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Selafin");
     241        1217 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
     242        1217 :                               "drivers/vector/selafin.html");
     243             : 
     244        1217 :     poDriver->SetMetadataItem(
     245             :         GDAL_DMD_CREATIONOPTIONLIST,
     246             :         "<CreationOptionList>"
     247             :         "  <Option name='TITLE' type='string' description='Title of the "
     248             :         "datasource, stored in the Selafin file. The title must not hold more "
     249             :         "than 72 characters.'/>"
     250             :         "  <Option name='DATE' type='string' description='Starting date of the "
     251             :         "simulation. Each layer in a Selafin file is characterized by a date, "
     252             :         "counted in seconds since a reference date. This option allows "
     253             :         "providing the reference date. The format of this field must be "
     254             :         "YYYY-MM-DD_hh:mm:ss'/>"
     255        1217 :         "</CreationOptionList>");
     256        1217 :     poDriver->SetMetadataItem(
     257             :         GDAL_DS_LAYER_CREATIONOPTIONLIST,
     258             :         "<LayerCreationOptionList>"
     259             :         "  <Option name='DATE' type='float' description='Date of the time "
     260             :         "step, in seconds, relative to the starting date of the simulation.'/>"
     261        1217 :         "</LayerCreationOptionList>");
     262             : 
     263        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     264             : 
     265        1217 :     poDriver->pfnOpen = OGRSelafinDriverOpen;
     266        1217 :     poDriver->pfnIdentify = OGRSelafinDriverIdentify;
     267        1217 :     poDriver->pfnCreate = OGRSelafinDriverCreate;
     268        1217 :     poDriver->pfnDelete = OGRSelafinDriverDelete;
     269             : 
     270        1217 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     271             : }

Generated by: LCOV version 1.14