LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/miramon - ogrmiramondatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 81 89 91.0 %
Date: 2025-09-10 17:48:50 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRMiraMonDataSource class.
       5             :  * Author:   Abel Pau
       6             :  ******************************************************************************
       7             :  * Copyright (c) 2024, Xavier Pons
       8             :  *
       9             :  * SPDX-License-Identifier: MIT
      10             :  ****************************************************************************/
      11             : 
      12             : #include "ogrmiramon.h"
      13             : 
      14             : /****************************************************************************/
      15             : /*                          OGRMiraMonDataSource()                          */
      16             : /****************************************************************************/
      17         190 : OGRMiraMonDataSource::OGRMiraMonDataSource()
      18             : {
      19         190 :     memset(&m_MMMap, 0, sizeof(m_MMMap));
      20         190 : }
      21             : 
      22             : /****************************************************************************/
      23             : /*                         ~OGRMiraMonDataSource()                          */
      24             : /****************************************************************************/
      25             : 
      26         380 : OGRMiraMonDataSource::~OGRMiraMonDataSource()
      27             : 
      28             : {
      29         190 :     m_apoLayers.clear();
      30             : 
      31         190 :     if (m_MMMap.fMMMap)
      32          46 :         VSIFCloseL(m_MMMap.fMMMap);
      33         380 : }
      34             : 
      35             : /****************************************************************************/
      36             : /*                                Open()                                    */
      37             : /****************************************************************************/
      38             : 
      39         205 : bool OGRMiraMonDataSource::Open(const char *pszFilename, VSILFILE *fp,
      40             :                                 const OGRSpatialReference *poSRS,
      41             :                                 CSLConstList papszOpenOptionsUsr)
      42             : 
      43             : {
      44             :     auto poLayer = std::make_unique<OGRMiraMonLayer>(
      45         410 :         this, pszFilename, fp, poSRS, m_bUpdate, papszOpenOptionsUsr, &m_MMMap);
      46         205 :     if (!poLayer->bValidFile)
      47             :     {
      48           8 :         return false;
      49             :     }
      50             : 
      51         197 :     if (!m_osRootName.empty())
      52             :     {
      53             :         const std::string osExtension =
      54         168 :             CPLGetExtensionSafe(m_osRootName.c_str());
      55          84 :         if (!EQUAL(osExtension.c_str(), "pol") &&
      56         156 :             !EQUAL(osExtension.c_str(), "arc") &&
      57          72 :             !EQUAL(osExtension.c_str(), "pnt"))
      58             :         {
      59          62 :             CPLStrlcpy(m_MMMap.pszMapName,
      60         124 :                        CPLFormFilenameSafe(
      61             :                            m_osRootName.c_str(),
      62         124 :                            CPLGetBasenameSafe(m_osRootName.c_str()).c_str(),
      63             :                            "mmm")
      64             :                            .c_str(),
      65             :                        sizeof(m_MMMap.pszMapName));
      66          62 :             if (!m_MMMap.nNumberOfLayers)
      67             :             {
      68          46 :                 m_MMMap.fMMMap = VSIFOpenL(m_MMMap.pszMapName, "w+");
      69          46 :                 if (!m_MMMap.fMMMap)
      70             :                 {
      71             :                     // It could be an error but it is not so important
      72             :                     // to stop the process. This map is an extra element
      73             :                     // to open all layers in one click, at least in MiraMon
      74             :                     // software.
      75           0 :                     *m_MMMap.pszMapName = '\0';
      76             :                 }
      77             :                 else
      78             :                 {
      79             :                     char *pszChaiCP1252;
      80             : 
      81          46 :                     VSIFPrintfL(m_MMMap.fMMMap, "[VERSIO]\n");
      82          46 :                     VSIFPrintfL(m_MMMap.fMMMap, "Vers=2\n");
      83          46 :                     VSIFPrintfL(m_MMMap.fMMMap, "SubVers=0\n");
      84          46 :                     VSIFPrintfL(m_MMMap.fMMMap, "variant=b\n");
      85          46 :                     VSIFPrintfL(m_MMMap.fMMMap, "\n");
      86          46 :                     VSIFPrintfL(m_MMMap.fMMMap, "[DOCUMENT]\n");
      87          46 :                     pszChaiCP1252 = CPLRecode(
      88          92 :                         CPLGetBasenameSafe(poLayer->GetName()).c_str(),
      89             :                         CPL_ENC_UTF8, "CP1252");
      90          46 :                     VSIFPrintfL(
      91             :                         m_MMMap.fMMMap, "Titol= %s(map)\n",
      92             :                         pszChaiCP1252
      93             :                             ? pszChaiCP1252
      94          46 :                             : CPLGetBasenameSafe(poLayer->GetName()).c_str());
      95          46 :                     CPLFree(pszChaiCP1252);
      96          46 :                     VSIFPrintfL(m_MMMap.fMMMap, "\n");
      97             :                 }
      98             :             }
      99             :         }
     100             :         else
     101          22 :             *m_MMMap.pszMapName = '\0';
     102             :     }
     103             :     else
     104         113 :         *m_MMMap.pszMapName = '\0';
     105             : 
     106         197 :     m_apoLayers.emplace_back(std::move(poLayer));
     107             : 
     108         197 :     return true;
     109             : }
     110             : 
     111             : /****************************************************************************/
     112             : /*                               Create()                                   */
     113             : /*                                                                          */
     114             : /*      Create a new datasource.  This does not really do anything          */
     115             : /*      currently but save the name.                                        */
     116             : /****************************************************************************/
     117             : 
     118          69 : bool OGRMiraMonDataSource::Create(const char *pszDataSetName,
     119             :                                   CSLConstList /* papszOptions */)
     120             : 
     121             : {
     122          69 :     m_bUpdate = true;
     123          69 :     m_osRootName = pszDataSetName;
     124             : 
     125          69 :     return true;
     126             : }
     127             : 
     128             : /****************************************************************************/
     129             : /*                           ICreateLayer()                                 */
     130             : /****************************************************************************/
     131             : 
     132             : OGRLayer *
     133          85 : OGRMiraMonDataSource::ICreateLayer(const char *pszLayerName,
     134             :                                    const OGRGeomFieldDefn *poGeomFieldDefn,
     135             :                                    CSLConstList papszOptions)
     136             : {
     137          85 :     CPLAssert(nullptr != pszLayerName);
     138             : 
     139          85 :     const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     140             :     const auto poSRS =
     141          85 :         poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
     142             : 
     143             :     // It's a seed to be able to generate a random identifier in
     144             :     // MMGenerateFileIdentifierFromMetadataFileName() function
     145          85 :     srand(static_cast<unsigned int>(time(nullptr)));
     146             : 
     147          85 :     if (OGR_GT_HasM(eType))
     148             :     {
     149           0 :         CPLError(CE_Warning, CPLE_NotSupported,
     150             :                  "Measures in this layer will be ignored.");
     151             :     }
     152             : 
     153             :     /* -------------------------------------------------------------------- */
     154             :     /*    If the dataset has an extension, it is understood that the path   */
     155             :     /*       of the file is where to write, and the layer name is the       */
     156             :     /*       dataset name (without extension).                              */
     157             :     /* -------------------------------------------------------------------- */
     158         170 :     const std::string osExtension = CPLGetExtensionSafe(m_osRootName.c_str());
     159         170 :     std::string osFullMMLayerName;
     160          85 :     if (EQUAL(osExtension.c_str(), "pol") ||
     161          85 :         EQUAL(osExtension.c_str(), "arc") || EQUAL(osExtension.c_str(), "pnt"))
     162             :     {
     163          22 :         osFullMMLayerName = CPLResetExtensionSafe(m_osRootName.c_str(), "");
     164          22 :         if (!osFullMMLayerName.empty())
     165          22 :             osFullMMLayerName.pop_back();
     166             : 
     167             :         // Checking that the folder where to write exists
     168             :         const std::string osDestFolder =
     169          22 :             CPLGetDirnameSafe(osFullMMLayerName.c_str());
     170          22 :         if (!STARTS_WITH(osDestFolder.c_str(), "/vsimem"))
     171             :         {
     172             :             VSIStatBufL sStat;
     173           0 :             if (VSIStatL(osDestFolder.c_str(), &sStat) != 0 ||
     174           0 :                 !VSI_ISDIR(sStat.st_mode))
     175             :             {
     176           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     177             :                          "The folder %s does not exist.", osDestFolder.c_str());
     178           0 :                 return nullptr;
     179             :             }
     180             :         }
     181             :     }
     182             :     else
     183             :     {
     184             :         osFullMMLayerName =
     185          63 :             CPLFormFilenameSafe(m_osRootName.c_str(), pszLayerName, "");
     186             : 
     187             :         /* -------------------------------------------------------------------- */
     188             :         /*      Let's create the folder if it's not already created.            */
     189             :         /*      (only the las level of the folder)                              */
     190             :         /* -------------------------------------------------------------------- */
     191          63 :         if (!STARTS_WITH(m_osRootName.c_str(), "/vsimem"))
     192             :         {
     193             :             VSIStatBufL sStat;
     194          14 :             if (VSIStatL(m_osRootName.c_str(), &sStat) != 0 ||
     195           0 :                 !VSI_ISDIR(sStat.st_mode))
     196             :             {
     197          14 :                 if (VSIMkdir(m_osRootName.c_str(), 0755) != 0)
     198             :                 {
     199           1 :                     CPLError(CE_Failure, CPLE_AppDefined,
     200             :                              "Unable to create the folder %s.",
     201             :                              m_osRootName.c_str());
     202           1 :                     return nullptr;
     203             :                 }
     204             :             }
     205             :         }
     206             :     }
     207             : 
     208             :     /* -------------------------------------------------------------------- */
     209             :     /*      Return open layer handle.                                       */
     210             :     /* -------------------------------------------------------------------- */
     211          84 :     if (Open(osFullMMLayerName.c_str(), nullptr, poSRS, papszOptions))
     212             :     {
     213          84 :         return m_apoLayers.back().get();
     214             :     }
     215             : 
     216           0 :     return nullptr;
     217             : }
     218             : 
     219             : /****************************************************************************/
     220             : /*                           TestCapability()                               */
     221             : /****************************************************************************/
     222             : 
     223         207 : int OGRMiraMonDataSource::TestCapability(const char *pszCap) const
     224             : 
     225             : {
     226         207 :     if (EQUAL(pszCap, ODsCCreateLayer))
     227          65 :         return m_bUpdate;
     228         142 :     else if (EQUAL(pszCap, ODsCZGeometries))
     229          20 :         return TRUE;
     230             : 
     231         122 :     return FALSE;
     232             : }
     233             : 
     234             : /****************************************************************************/
     235             : /*                              GetLayer()                                  */
     236             : /****************************************************************************/
     237             : 
     238         366 : const OGRLayer *OGRMiraMonDataSource::GetLayer(int iLayer) const
     239             : 
     240             : {
     241         366 :     if (iLayer < 0 || iLayer >= static_cast<int>(m_apoLayers.size()))
     242          20 :         return nullptr;
     243             : 
     244         346 :     return m_apoLayers[iLayer].get();
     245             : }
     246             : 
     247             : /************************************************************************/
     248             : /*                            GetFileList()                             */
     249             : /************************************************************************/
     250             : 
     251          10 : char **OGRMiraMonDataSource::GetFileList()
     252             : {
     253          20 :     CPLStringList oFileList;
     254          20 :     for (auto &poLayer : m_apoLayers)
     255             :     {
     256          10 :         poLayer->AddToFileList(oFileList);
     257             :     }
     258          20 :     return oFileList.StealList();
     259             : }

Generated by: LCOV version 1.14