LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/lvbag - ogrlvbagdriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 65 73 89.0 %
Date: 2025-07-08 21:33:46 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  LV BAG Translator
       4             :  * Purpose:  Implements OGRLVBAGDriver.
       5             :  * Author:   Laixer B.V., info at laixer dot com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2020, Laixer B.V. <info at laixer dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_lvbag.h"
      14             : #include "ogrsf_frmts.h"
      15             : 
      16             : /************************************************************************/
      17             : /*                             Identify()                               */
      18             : /************************************************************************/
      19             : 
      20       56987 : static int OGRLVBAGDriverIdentify(GDALOpenInfo *poOpenInfo)
      21             : {
      22       56987 :     if (!poOpenInfo->bStatOK)
      23             :     {
      24       49254 :         return FALSE;
      25             :     }
      26        7733 :     if (poOpenInfo->bIsDirectory)
      27             :     {
      28        1562 :         return -1;  // Check later
      29             :     }
      30        6171 :     if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes == 0)
      31             :     {
      32         157 :         return FALSE;
      33             :     }
      34             : 
      35        6014 :     auto pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
      36        6014 :     if (pszPtr[0] != '<')
      37             :     {
      38        4788 :         return FALSE;
      39             :     }
      40             : 
      41        1226 :     if (poOpenInfo->IsSingleAllowedDriver("LVBAG"))
      42             :     {
      43           2 :         return TRUE;
      44             :     }
      45             : 
      46             :     // Can't handle mutations just yet
      47        1224 :     if (strstr(pszPtr,
      48             :                "http://www.kadaster.nl/schemas/mutatielevering-generiek/1.0") !=
      49             :         nullptr)
      50             :     {
      51           0 :         return FALSE;
      52             :     }
      53             : 
      54        1224 :     if (strstr(pszPtr,
      55             :                "http://www.kadaster.nl/schemas/standlevering-generiek/1.0") ==
      56             :         nullptr)
      57             :     {
      58        1172 :         return FALSE;
      59             :     }
      60             : 
      61             :     // Pin the driver to XSD version 'v20200601'
      62          52 :     if (strstr(pszPtr, "http://www.kadaster.nl/schemas/lvbag/"
      63             :                        "extract-deelbestand-lvc/v20200601") == nullptr)
      64             :     {
      65           1 :         return FALSE;
      66             :     }
      67             : 
      68          51 :     return TRUE;
      69             : }
      70             : 
      71             : /************************************************************************/
      72             : /*                                Open()                                */
      73             : /************************************************************************/
      74             : 
      75         743 : GDALDataset *OGRLVBAGDriverOpen(GDALOpenInfo *poOpenInfo)
      76             : {
      77         743 :     if (!OGRLVBAGDriverIdentify(poOpenInfo) || poOpenInfo->eAccess == GA_Update)
      78             :     {
      79          87 :         return nullptr;
      80             :     }
      81             : 
      82         656 :     const char *pszFilename = poOpenInfo->pszFilename;
      83        1312 :     auto poDS = std::unique_ptr<OGRLVBAGDataSource>{new OGRLVBAGDataSource{}};
      84         656 :     poDS->SetDescription(pszFilename);
      85             : 
      86         656 :     if (!poOpenInfo->bIsDirectory && poOpenInfo->fpL != nullptr)
      87             :     {
      88          24 :         if (!poDS->Open(pszFilename, poOpenInfo->papszOpenOptions))
      89             :         {
      90           0 :             poDS.reset();
      91             :         }
      92             :     }
      93         632 :     else if (poOpenInfo->bIsDirectory && poOpenInfo->fpL == nullptr)
      94             :     {
      95         632 :         int nProbedFileCount = 0;
      96         632 :         bool bFound = false;
      97         632 :         char **papszNames = VSIReadDir(pszFilename);
      98       24937 :         for (int i = 0; papszNames != nullptr && papszNames[i] != nullptr; ++i)
      99             :         {
     100       24305 :             if (!EQUAL(CPLGetExtensionSafe(papszNames[i]).c_str(), "xml"))
     101       24300 :                 continue;
     102             : 
     103             :             const CPLString oSubFilename =
     104          27 :                 CPLFormFilenameSafe(pszFilename, papszNames[i], nullptr);
     105             : 
     106          27 :             if (EQUAL(papszNames[i], ".") || EQUAL(papszNames[i], ".."))
     107             :             {
     108           0 :                 continue;
     109             :             }
     110             : 
     111             :             // Give up on /vsi filesystems if after 10 files we haven't found
     112             :             // a single BAG file
     113          27 :             if (nProbedFileCount == 10 && !bFound &&
     114           1 :                 STARTS_WITH(pszFilename, "/vsi"))
     115             :             {
     116           0 :                 const bool bCheckAllFiles = CPLTestBool(
     117             :                     CPLGetConfigOption("OGR_LVBAG_CHECK_ALL_FILES", "NO"));
     118           0 :                 if (!bCheckAllFiles)
     119             :                 {
     120           0 :                     break;
     121             :                 }
     122             :             }
     123             : 
     124          27 :             nProbedFileCount++;
     125          27 :             GDALOpenInfo oOpenInfo{oSubFilename, GA_ReadOnly};
     126          27 :             if (!OGRLVBAGDriverIdentify(&oOpenInfo))
     127             :             {
     128          22 :                 continue;
     129             :             }
     130             : 
     131           5 :             if (poDS->Open(oSubFilename, poOpenInfo->papszOpenOptions))
     132             :             {
     133           5 :                 bFound = true;
     134             :             }
     135             :         }
     136             : 
     137         632 :         CSLDestroy(papszNames);
     138         632 :         if (!poDS->GetLayerCount())
     139             :         {
     140         630 :             poDS.reset();
     141         630 :             return nullptr;
     142           2 :         }
     143             :     }
     144             :     else
     145             :     {
     146           0 :         poDS.reset();
     147           0 :         return nullptr;
     148             :     }
     149             : 
     150          26 :     return poDS.release();
     151             : }
     152             : 
     153             : /************************************************************************/
     154             : /*                         RegisterOGRLVBAG()                           */
     155             : /************************************************************************/
     156             : 
     157        1935 : void RegisterOGRLVBAG()
     158             : {
     159        1935 :     if (GDALGetDriverByName("LVBAG"))
     160             :     {
     161         282 :         return;
     162             :     }
     163             : 
     164        3306 :     auto poDriver = std::make_unique<GDALDriver>();
     165             : 
     166        1653 :     poDriver->SetDescription("LVBAG");
     167        1653 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     168        1653 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Kadaster LV BAG Extract 2.0");
     169        1653 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xml");
     170        1653 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/lvbag.html");
     171        1653 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     172        1653 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     173             : 
     174        1653 :     poDriver->SetMetadataItem(
     175             :         GDAL_DMD_OPENOPTIONLIST,
     176             :         "<OpenOptionList>"
     177             :         "  <Option name='AUTOCORRECT_INVALID_DATA' type='boolean' "
     178             :         "description='whether driver should try to fix invalid data' "
     179             :         "default='NO'/>"
     180             :         "  <Option name='LEGACY_ID' type='boolean' description='whether driver "
     181             :         "should use the BAG 1.0 identifiers' default='NO'/>"
     182        1653 :         "</OpenOptionList>");
     183             : 
     184        1653 :     poDriver->pfnOpen = OGRLVBAGDriverOpen;
     185        1653 :     poDriver->pfnIdentify = OGRLVBAGDriverIdentify;
     186             : 
     187        1653 :     GetGDALDriverManager()->RegisterDriver(poDriver.release());
     188             : }

Generated by: LCOV version 1.14