LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mitab - mitab_ogr_driver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 104 106 98.1 %
Date: 2024-05-05 22:37:24 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  * Name:     mitab_ogr_driver.cpp
       4             :  * Project:  MapInfo Mid/Mif, Tab ogr support
       5             :  * Language: C++
       6             :  * Purpose:  Implementation of the MIDDATAFile class used to handle
       7             :  *           reading/writing of the MID/MIF files
       8             :  * Author:   Stephane Villeneuve, stephane.v@videotron.ca
       9             :  *
      10             :  **********************************************************************
      11             :  * Copyright (c) 1999, 2000, Stephane Villeneuve
      12             :  * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
      13             :  *
      14             :  * Permission is hereby granted, free of charge, to any person obtaining a
      15             :  * copy of this software and associated documentation files (the "Software"),
      16             :  * to deal in the Software without restriction, including without limitation
      17             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18             :  * and/or sell copies of the Software, and to permit persons to whom the
      19             :  * Software is furnished to do so, subject to the following conditions:
      20             :  *
      21             :  * The above copyright notice and this permission notice shall be included
      22             :  * in all copies or substantial portions of the Software.
      23             :  *
      24             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      25             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      27             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30             :  * DEALINGS IN THE SOFTWARE.
      31             :  **********************************************************************/
      32             : 
      33             : #include "mitab_ogr_driver.h"
      34             : 
      35             : /************************************************************************/
      36             : /*                  OGRTABDriverIdentify()                              */
      37             : /************************************************************************/
      38             : 
      39       51064 : static int OGRTABDriverIdentify(GDALOpenInfo *poOpenInfo)
      40             : 
      41             : {
      42             :     // Files not ending with .tab, .mif or .mid are not handled by this driver.
      43       51064 :     if (!poOpenInfo->bStatOK)
      44       40512 :         return FALSE;
      45       10552 :     if (poOpenInfo->bIsDirectory)
      46        1290 :         return -1;  // Unsure.
      47        9262 :     if (poOpenInfo->fpL == nullptr)
      48          82 :         return FALSE;
      49       16636 :     if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MIF") ||
      50        7456 :         EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MID"))
      51             :     {
      52        1724 :         return TRUE;
      53             :     }
      54        7456 :     if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "TAB"))
      55             :     {
      56      223530 :         for (int i = 0; i < poOpenInfo->nHeaderBytes; i++)
      57             :         {
      58      223530 :             const char *pszLine =
      59      223530 :                 reinterpret_cast<const char *>(poOpenInfo->pabyHeader) + i;
      60      223530 :             if (STARTS_WITH_CI(pszLine, "Fields"))
      61        2459 :                 return TRUE;
      62      221071 :             else if (STARTS_WITH_CI(pszLine, "create view"))
      63           4 :                 return TRUE;
      64      221067 :             else if (STARTS_WITH_CI(pszLine, "\"\\IsSeamless\" = \"TRUE\""))
      65           0 :                 return TRUE;
      66             :         }
      67             :     }
      68             : #ifdef DEBUG
      69             :     // For AFL, so that .cur_input is detected as the archive filename.
      70        9986 :     if (!STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
      71        4993 :         EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input"))
      72             :     {
      73           4 :         return -1;
      74             :     }
      75             : #endif
      76        4989 :     return FALSE;
      77             : }
      78             : 
      79             : /************************************************************************/
      80             : /*                  OGRTABDriver::Open()                                */
      81             : /************************************************************************/
      82             : 
      83        2760 : static GDALDataset *OGRTABDriverOpen(GDALOpenInfo *poOpenInfo)
      84             : 
      85             : {
      86        2760 :     if (OGRTABDriverIdentify(poOpenInfo) == FALSE)
      87             :     {
      88           2 :         return nullptr;
      89             :     }
      90             : 
      91        4652 :     if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MIF") ||
      92        1894 :         EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MID"))
      93             :     {
      94         864 :         if (poOpenInfo->eAccess == GA_Update)
      95           0 :             return nullptr;
      96             :     }
      97             : 
      98             : #ifdef DEBUG
      99             :     // For AFL, so that .cur_input is detected as the archive filename.
     100        7617 :     if (poOpenInfo->fpL != nullptr &&
     101        4859 :         !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
     102        2101 :         EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input"))
     103             :     {
     104             :         GDALOpenInfo oOpenInfo(
     105           4 :             (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
     106           6 :             poOpenInfo->nOpenFlags);
     107           2 :         oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
     108           2 :         return OGRTABDriverOpen(&oOpenInfo);
     109             :     }
     110             : #endif
     111             : 
     112        2756 :     OGRTABDataSource *poDS = new OGRTABDataSource();
     113        2756 :     if (!poDS->Open(poOpenInfo, TRUE))
     114             :     {
     115         686 :         delete poDS;
     116         686 :         return nullptr;
     117             :     }
     118             : 
     119        2070 :     return poDS;
     120             : }
     121             : 
     122             : /************************************************************************/
     123             : /*                              Create()                                */
     124             : /************************************************************************/
     125             : 
     126             : static GDALDataset *
     127         184 : OGRTABDriverCreate(const char *pszName, CPL_UNUSED int nBands,
     128             :                    CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
     129             :                    CPL_UNUSED GDALDataType eDT, char **papszOptions)
     130             : {
     131             :     // Try to create the data source.
     132         184 :     OGRTABDataSource *poDS = new OGRTABDataSource();
     133         184 :     if (!poDS->Create(pszName, papszOptions))
     134             :     {
     135           2 :         delete poDS;
     136           2 :         return nullptr;
     137             :     }
     138             : 
     139         182 :     return poDS;
     140             : }
     141             : 
     142             : /************************************************************************/
     143             : /*                              Delete()                                */
     144             : /************************************************************************/
     145             : 
     146          47 : static CPLErr OGRTABDriverDelete(const char *pszDataSource)
     147             : 
     148             : {
     149          47 :     GDALDataset *poDS = nullptr;
     150             :     {
     151             :         // Make sure that the file opened by GDALOpenInfo is closed
     152             :         // when the object goes out of scope
     153          47 :         GDALOpenInfo oOpenInfo(pszDataSource, GA_ReadOnly);
     154          47 :         poDS = OGRTABDriverOpen(&oOpenInfo);
     155             :     }
     156          47 :     if (poDS == nullptr)
     157          16 :         return CE_Failure;
     158          31 :     char **papszFileList = poDS->GetFileList();
     159          31 :     delete poDS;
     160             : 
     161          31 :     char **papszIter = papszFileList;
     162         211 :     while (papszIter && *papszIter)
     163             :     {
     164         180 :         VSIUnlink(*papszIter);
     165         180 :         papszIter++;
     166             :     }
     167          31 :     CSLDestroy(papszFileList);
     168             : 
     169             :     VSIStatBufL sStatBuf;
     170          31 :     if (VSIStatL(pszDataSource, &sStatBuf) == 0 && VSI_ISDIR(sStatBuf.st_mode))
     171             :     {
     172          16 :         VSIRmdir(pszDataSource);
     173             :     }
     174             : 
     175          31 :     return CE_None;
     176             : }
     177             : 
     178             : /************************************************************************/
     179             : /*                          OGRTABDriverUnload()                        */
     180             : /************************************************************************/
     181             : 
     182         852 : static void OGRTABDriverUnload(CPL_UNUSED GDALDriver *poDriver)
     183             : {
     184         852 :     MITABFreeCoordSysTable();
     185         852 : }
     186             : 
     187             : /************************************************************************/
     188             : /*              RegisterOGRTAB()                                        */
     189             : /************************************************************************/
     190             : 
     191        1520 : void RegisterOGRTAB()
     192             : 
     193             : {
     194        1520 :     if (GDALGetDriverByName("MapInfo File") != nullptr)
     195         301 :         return;
     196             : 
     197        1219 :     GDALDriver *poDriver = new GDALDriver();
     198             : 
     199        1219 :     poDriver->SetDescription("MapInfo File");
     200        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     201        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
     202        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
     203        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_DELETE_FIELD, "YES");
     204        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_REORDER_FIELDS, "YES");
     205        1219 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     206             : 
     207        1219 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "MapInfo File");
     208        1219 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "tab mif mid");
     209        1219 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/mitab.html");
     210        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     211        1219 :     poDriver->SetMetadataItem(GDAL_DMD_NUMERIC_FIELD_WIDTH_INCLUDES_SIGN,
     212        1219 :                               "YES");
     213        1219 :     poDriver->SetMetadataItem(
     214        1219 :         GDAL_DMD_NUMERIC_FIELD_WIDTH_INCLUDES_DECIMAL_SEPARATOR, "YES");
     215             : 
     216        1219 :     poDriver->SetMetadataItem(
     217             :         GDAL_DS_LAYER_CREATIONOPTIONLIST,
     218             :         "<LayerCreationOptionList>"
     219             :         "  <Option name='BOUNDS' type='string' "
     220             :         "description='Custom bounds. Expect format is "
     221             :         "xmin,ymin,xmax,ymax'/>"
     222             :         "  <Option name='ENCODING' type='string' "
     223             :         "description='to override the encoding "
     224             :         "interpretation of the DAT/MID with any encoding "
     225             :         "supported by CPLRecode or to \"\" to avoid any "
     226             :         "recoding (Neutral charset)'/>"
     227             :         "  <Option name='DESCRIPTION' type='string' "
     228             :         "description='Friendly name of table. Only for tab "
     229             :         "format.'/>"  // See
     230             :         // https://support.pitneybowes.com/SearchArticles/VFP05_KnowledgeWithSidebarHowTo?id=kA180000000CtuHCAS&popup=false&lang=en_US
     231        1219 :         "</LayerCreationOptionList>");
     232             : 
     233        1219 :     poDriver->SetMetadataItem(
     234             :         GDAL_DMD_CREATIONOPTIONLIST,
     235             :         "<CreationOptionList>"
     236             :         "  <Option name='FORMAT' type='string-select' description='type of "
     237             :         "MapInfo format'>"
     238             :         "    <Value>MIF</Value>"
     239             :         "    <Value>TAB</Value>"
     240             :         "  </Option>"
     241             :         "  <Option name='SPATIAL_INDEX_MODE' type='string-select' "
     242             :         "description='type of spatial index' default='QUICK'>"
     243             :         "    <Value>QUICK</Value>"
     244             :         "    <Value>OPTIMIZED</Value>"
     245             :         "  </Option>"
     246             :         "  <Option name='BLOCKSIZE' type='int' description='.map block size' "
     247             :         "min='512' max='32256' default='512'/>"
     248             :         "  <Option name='ENCODING' type='string' description='to override the "
     249             :         "encoding interpretation of the DAT/MID with any encoding supported by "
     250             :         "CPLRecode or to \"\" to avoid any recoding (Neutral charset)'/>"
     251        1219 :         "</CreationOptionList>");
     252             : 
     253        1219 :     poDriver->SetMetadataItem(
     254             :         GDAL_DMD_CREATIONFIELDDATATYPES,
     255        1219 :         "Integer Integer64 Real String Date DateTime Time");
     256        1219 :     poDriver->SetMetadataItem(GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
     257        1219 :                               "WidthPrecision");
     258        1219 :     poDriver->SetMetadataItem(GDAL_DMD_ALTER_FIELD_DEFN_FLAGS,
     259        1219 :                               "Name Type WidthPrecision");
     260        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES");
     261        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES");
     262        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_WRITE, "YES");
     263             : 
     264        1219 :     poDriver->pfnOpen = OGRTABDriverOpen;
     265        1219 :     poDriver->pfnIdentify = OGRTABDriverIdentify;
     266        1219 :     poDriver->pfnCreate = OGRTABDriverCreate;
     267        1219 :     poDriver->pfnDelete = OGRTABDriverDelete;
     268        1219 :     poDriver->pfnUnloadDriver = OGRTABDriverUnload;
     269             : 
     270        1219 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     271             : }

Generated by: LCOV version 1.14