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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      10             :  ****************************************************************************/
      11             : 
      12             : #include "ogr_selafin.h"
      13             : #include "cpl_conv.h"
      14             : #include "cpl_string.h"
      15             : #include "io_selafin.h"
      16             : 
      17             : /************************************************************************/
      18             : /*                     OGRSelafinDriverIdentify()                       */
      19             : /************************************************************************/
      20             : 
      21       66595 : static int OGRSelafinDriverIdentify(GDALOpenInfo *poOpenInfo)
      22             : {
      23       66595 :     if (poOpenInfo->pabyHeader != nullptr)
      24             :     {
      25        2447 :         if (poOpenInfo->nHeaderBytes < 84 + 8)
      26         238 :             return FALSE;
      27        2209 :         if (poOpenInfo->pabyHeader[0] != 0 || poOpenInfo->pabyHeader[1] != 0 ||
      28         113 :             poOpenInfo->pabyHeader[2] != 0 || poOpenInfo->pabyHeader[3] != 0x50)
      29        2203 :             return FALSE;
      30             : 
      31           6 :         if (poOpenInfo->pabyHeader[84 + 0] != 0 ||
      32           6 :             poOpenInfo->pabyHeader[84 + 1] != 0 ||
      33           6 :             poOpenInfo->pabyHeader[84 + 2] != 0 ||
      34           6 :             poOpenInfo->pabyHeader[84 + 3] != 0x50 ||
      35           6 :             poOpenInfo->pabyHeader[84 + 4] != 0 ||
      36           6 :             poOpenInfo->pabyHeader[84 + 5] != 0 ||
      37           6 :             poOpenInfo->pabyHeader[84 + 6] != 0 ||
      38           6 :             poOpenInfo->pabyHeader[84 + 7] != 8)
      39           0 :             return FALSE;
      40             : 
      41           6 :         return TRUE;
      42             :     }
      43             : 
      44             :     // We can stat() the file but it is not a regular file or we did not
      45             :     // get access to its content
      46       64148 :     if (poOpenInfo->bStatOK)
      47         536 :         return FALSE;
      48             : 
      49       63612 :     return -1;
      50             : }
      51             : 
      52             : /************************************************************************/
      53             : /*                      OGRSelafinDriverOpen()                          */
      54             : /************************************************************************/
      55             : 
      56       21540 : static GDALDataset *OGRSelafinDriverOpen(GDALOpenInfo *poOpenInfo)
      57             : {
      58             : 
      59       21540 :     if (OGRSelafinDriverIdentify(poOpenInfo) == 0)
      60           0 :         return nullptr;
      61             : 
      62       21540 :     OGRSelafinDataSource *poDS = new OGRSelafinDataSource();
      63       21540 :     if (!poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update,
      64             :                     FALSE))
      65             :     {
      66       21537 :         delete poDS;
      67       21537 :         poDS = nullptr;
      68             :     }
      69       21540 :     return poDS;
      70             : }
      71             : 
      72             : /************************************************************************/
      73             : /*                       OGRSelafinDriverCreate()                       */
      74             : /************************************************************************/
      75             : 
      76             : static GDALDataset *
      77          19 : OGRSelafinDriverCreate(const char *pszName, CPL_UNUSED int nXSize,
      78             :                        CPL_UNUSED int nYSize, CPL_UNUSED int nBands,
      79             :                        CPL_UNUSED GDALDataType eDT, char **papszOptions)
      80             : {
      81             :     // First, ensure there isn't any such file yet.
      82             :     VSIStatBufL sStatBuf;
      83          19 :     if (strcmp(pszName, "/dev/stdout") == 0)
      84           0 :         pszName = "/vsistdout/";
      85          19 :     if (VSIStatL(pszName, &sStatBuf) == 0)
      86             :     {
      87           0 :         CPLError(CE_Failure, CPLE_AppDefined,
      88             :                  "It seems a file system object called '%s' already exists.",
      89             :                  pszName);
      90           0 :         return nullptr;
      91             :     }
      92             :     // Parse options
      93          19 :     const char *pszTemp = CSLFetchNameValue(papszOptions, "TITLE");
      94             :     char pszTitle[81];
      95          19 :     int pnDate[6] = {-1, 0};
      96          19 :     if (pszTemp != nullptr)
      97           0 :         strncpy(pszTitle, pszTemp, 72);
      98             :     else
      99          19 :         memset(pszTitle, ' ', 72);
     100          19 :     pszTemp = CSLFetchNameValue(papszOptions, "DATE");
     101          19 :     if (pszTemp != nullptr)
     102             :     {
     103           0 :         const char *pszErrorMessage = "Wrong format for date parameter: must "
     104             :                                       "be \"%%Y-%%m-%%d_%%H:%%M:%%S\", ignored";
     105           0 :         const char *pszc = pszTemp;
     106           0 :         pnDate[0] = atoi(pszTemp);
     107           0 :         if (pnDate[0] <= 0)
     108           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     109             :         else
     110             :         {
     111           0 :             if (pnDate[0] < 100)
     112           0 :                 pnDate[0] += 2000;
     113             :         }
     114           0 :         while (*pszc != 0 && *pszc != '-')
     115           0 :             ++pszc;
     116           0 :         pnDate[1] = atoi(pszc);
     117           0 :         if (pnDate[1] < 0 || pnDate[1] > 12)
     118           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     119           0 :         while (*pszc != 0 && *pszc != '_')
     120           0 :             ++pszc;
     121           0 :         pnDate[2] = atoi(pszc);
     122           0 :         if (pnDate[2] < 0 || pnDate[2] > 59)
     123           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     124           0 :         while (*pszc != 0 && *pszc != '_')
     125           0 :             ++pszc;
     126           0 :         pnDate[3] = atoi(pszc);
     127           0 :         if (pnDate[3] < 0 || pnDate[3] > 23)
     128           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     129           0 :         while (*pszc != 0 && *pszc != ':')
     130           0 :             ++pszc;
     131           0 :         pnDate[4] = atoi(pszc);
     132           0 :         if (pnDate[4] < 0 || pnDate[4] > 59)
     133           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     134           0 :         while (*pszc != 0 && *pszc != ':')
     135           0 :             ++pszc;
     136           0 :         pnDate[5] = atoi(pszc);
     137           0 :         if (pnDate[5] < 0 || pnDate[5] > 59)
     138           0 :             CPLError(CE_Warning, CPLE_AppDefined, "%s", pszErrorMessage);
     139             :     }
     140             :     // Create the skeleton of a Selafin file
     141          19 :     VSILFILE *fp = VSIFOpenL(pszName, "wb");
     142          19 :     if (fp == nullptr)
     143             :     {
     144           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     145             :                  "Unable to open %s with write access.", pszName);
     146           1 :         return nullptr;
     147             :     }
     148          18 :     strncpy(pszTitle + 72, "SERAPHIN", 9);
     149          18 :     bool bError = false;
     150          18 :     if (Selafin::write_string(fp, pszTitle, 80) == 0)
     151           0 :         bError = true;
     152          18 :     int pnTemp[10] = {0};
     153          18 :     if (Selafin::write_intarray(fp, pnTemp, 2) == 0)
     154           0 :         bError = true;
     155          18 :     if (pnDate[0] >= 0)
     156           0 :         pnTemp[9] = 1;
     157          18 :     if (Selafin::write_intarray(fp, pnTemp, 10) == 0)
     158           0 :         bError = true;
     159          18 :     if (pnDate[0] >= 0)
     160             :     {
     161           0 :         if (Selafin::write_intarray(fp, pnTemp, 6) == 0)
     162           0 :             bError = true;
     163             :     }
     164          18 :     pnTemp[3] = 1;
     165          18 :     if (Selafin::write_intarray(fp, pnTemp, 4) == 0)
     166           0 :         bError = true;
     167          18 :     if (Selafin::write_intarray(fp, pnTemp, 0) == 0)
     168           0 :         bError = true;
     169          18 :     if (Selafin::write_intarray(fp, pnTemp, 0) == 0)
     170           0 :         bError = true;
     171          18 :     if (Selafin::write_floatarray(fp, nullptr, 0) == 0)
     172           0 :         bError = true;
     173          18 :     if (Selafin::write_floatarray(fp, nullptr, 0) == 0)
     174           0 :         bError = true;
     175          18 :     VSIFCloseL(fp);
     176          18 :     if (bError)
     177             :     {
     178           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Error writing to file %s.",
     179             :                  pszName);
     180           0 :         return nullptr;
     181             :     }
     182             :     // Force it to open as a datasource
     183          18 :     OGRSelafinDataSource *poDS = new OGRSelafinDataSource();
     184          18 :     if (!poDS->Open(pszName, TRUE, TRUE))
     185             :     {
     186           0 :         delete poDS;
     187           0 :         return nullptr;
     188             :     }
     189          18 :     return poDS;
     190             : }
     191             : 
     192             : /************************************************************************/
     193             : /*                      OGRSelafinDriverDelete()                        */
     194             : /************************************************************************/
     195          16 : static CPLErr OGRSelafinDriverDelete(const char *pszFilename)
     196             : {
     197          16 :     if (CPLUnlinkTree(pszFilename) == 0)
     198          16 :         return CE_None;
     199             :     else
     200           0 :         return CE_Failure;
     201             : }
     202             : 
     203             : /************************************************************************/
     204             : /*                           RegisterOGRSelafin()                       */
     205             : /************************************************************************/
     206             : 
     207        1595 : void RegisterOGRSelafin()
     208             : {
     209             : 
     210        1595 :     if (GDALGetDriverByName("Selafin") != nullptr)
     211         302 :         return;
     212             : 
     213        1293 :     GDALDriver *poDriver = new GDALDriver();
     214             : 
     215        1293 :     poDriver->SetDescription("Selafin");
     216        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     217        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
     218        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_DELETE_LAYER, "YES");
     219        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
     220        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_DELETE_FIELD, "YES");
     221        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_REORDER_FIELDS, "YES");
     222        1293 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     223             : 
     224        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Selafin");
     225        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
     226        1293 :                               "drivers/vector/selafin.html");
     227             : 
     228        1293 :     poDriver->SetMetadataItem(
     229             :         GDAL_DMD_CREATIONOPTIONLIST,
     230             :         "<CreationOptionList>"
     231             :         "  <Option name='TITLE' type='string' description='Title of the "
     232             :         "datasource, stored in the Selafin file. The title must not hold more "
     233             :         "than 72 characters.'/>"
     234             :         "  <Option name='DATE' type='string' description='Starting date of the "
     235             :         "simulation. Each layer in a Selafin file is characterized by a date, "
     236             :         "counted in seconds since a reference date. This option allows "
     237             :         "providing the reference date. The format of this field must be "
     238             :         "YYYY-MM-DD_hh:mm:ss'/>"
     239        1293 :         "</CreationOptionList>");
     240        1293 :     poDriver->SetMetadataItem(
     241             :         GDAL_DS_LAYER_CREATIONOPTIONLIST,
     242             :         "<LayerCreationOptionList>"
     243             :         "  <Option name='DATE' type='float' description='Date of the time "
     244             :         "step, in seconds, relative to the starting date of the simulation.'/>"
     245        1293 :         "</LayerCreationOptionList>");
     246             : 
     247        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     248             : 
     249        1293 :     poDriver->pfnOpen = OGRSelafinDriverOpen;
     250        1293 :     poDriver->pfnIdentify = OGRSelafinDriverIdentify;
     251        1293 :     poDriver->pfnCreate = OGRSelafinDriverCreate;
     252        1293 :     poDriver->pfnDelete = OGRSelafinDriverDelete;
     253             : 
     254        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     255             : }

Generated by: LCOV version 1.14