LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/shape - ogrshape.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 36 36 100.0 %
Date: 2025-10-24 23:03:13 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Private definitions within the Shapefile driver to implement
       5             :  *           integration with OGR.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
      10             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #ifndef OGRSHAPE_H_INCLUDED
      16             : #define OGRSHAPE_H_INCLUDED
      17             : 
      18             : #ifdef RENAME_INTERNAL_SHAPELIB_SYMBOLS
      19             : #include "gdal_shapelib_symbol_rename.h"
      20             : #endif
      21             : 
      22             : #include "cpl_multiproc.h"
      23             : #include "ogrsf_frmts.h"
      24             : #include "shapefil.h"
      25             : #include "shp_vsi.h"
      26             : #include "ogrlayerpool.h"
      27             : #include <set>
      28             : #include <vector>
      29             : 
      30             : /* Was limited to 255 until OGR 1.10, but 254 seems to be a more */
      31             : /* conventional limit (http://en.wikipedia.org/wiki/Shapefile, */
      32             : /* http://www.clicketyclick.dk/databases/xbase/format/data_types.html, */
      33             : /* #5052 ) */
      34             : #define OGR_DBF_MAX_FIELD_WIDTH 254
      35             : 
      36             : /* ==================================================================== */
      37             : /*      Functions from Shape2ogr.cpp.                                   */
      38             : /* ==================================================================== */
      39             : OGRFeature *SHPReadOGRFeature(SHPHandle hSHP, DBFHandle hDBF,
      40             :                               OGRFeatureDefn *poDefn, int iShape,
      41             :                               SHPObject *psShape, const char *pszSHPEncoding,
      42             :                               bool &bHasWarnedWrongWindingOrder);
      43             : OGRGeometry *SHPReadOGRObject(SHPHandle hSHP, int iShape, SHPObject *psShape,
      44             :                               bool &bHasWarnedWrongWindingOrder);
      45             : OGRFeatureDefn *SHPReadOGRFeatureDefn(const char *pszName, SHPHandle hSHP,
      46             :                                       DBFHandle hDBF,
      47             :                                       const char *pszSHPEncoding,
      48             :                                       int bAdjustType);
      49             : OGRErr SHPWriteOGRFeature(SHPHandle hSHP, DBFHandle hDBF,
      50             :                           OGRFeatureDefn *m_poFeatureDefn,
      51             :                           OGRFeature *poFeature, const char *pszSHPEncoding,
      52             :                           bool *pbTruncationWarningEmitted, bool bRewind);
      53             : 
      54             : /************************************************************************/
      55             : /*                         OGRShapeGeomFieldDefn                        */
      56             : /************************************************************************/
      57             : 
      58             : class OGRShapeGeomFieldDefn final : public OGRGeomFieldDefn
      59             : {
      60             :     CPL_DISALLOW_COPY_ASSIGN(OGRShapeGeomFieldDefn)
      61             : 
      62             :     std::string m_osFullName{};
      63             :     mutable bool m_bSRSSet = false;
      64             :     mutable CPLString m_osPrjFile{};
      65             : 
      66             :   public:
      67        6932 :     OGRShapeGeomFieldDefn(const char *pszFullNameIn, OGRwkbGeometryType eType,
      68             :                           int bSRSSetIn, OGRSpatialReference *poSRSIn)
      69        6932 :         : OGRGeomFieldDefn("", eType), m_osFullName(pszFullNameIn),
      70        6932 :           m_bSRSSet(CPL_TO_BOOL(bSRSSetIn))
      71             :     {
      72        6932 :         SetSpatialRef(poSRSIn);
      73        6932 :     }
      74             : 
      75             :     const OGRSpatialReference *GetSpatialRef() const override;
      76             : 
      77           3 :     void SetSRSSet()
      78             :     {
      79           3 :         m_bSRSSet = true;
      80           3 :     }
      81             : 
      82          24 :     const CPLString &GetPrjFilename() const
      83             :     {
      84          24 :         return m_osPrjFile;
      85             :     }
      86             : 
      87         229 :     void SetPrjFilename(const std::string &osFilename)
      88             :     {
      89         229 :         m_osPrjFile = osFilename;
      90         229 :     }
      91             : };
      92             : 
      93             : /************************************************************************/
      94             : /*                            OGRShapeLayer                             */
      95             : /************************************************************************/
      96             : 
      97             : class OGRShapeDataSource;
      98             : 
      99             : class OGRShapeLayer final : public OGRAbstractProxiedLayer
     100             : {
     101             :     CPL_DISALLOW_COPY_ASSIGN(OGRShapeLayer)
     102             : 
     103             :     OGRShapeDataSource *m_poDS = nullptr;
     104             : 
     105             :     OGRFeatureDefn *m_poFeatureDefn = nullptr;
     106             :     int m_iNextShapeId = 0;
     107             :     int m_nTotalShapeCount = 0;
     108             : 
     109             :     std::string m_osFullName{};
     110             : 
     111             :     SHPHandle m_hSHP = nullptr;
     112             :     DBFHandle m_hDBF = nullptr;
     113             : 
     114             :     bool m_bUpdateAccess = false;
     115             : 
     116             :     OGRwkbGeometryType m_eRequestedGeomType = wkbUnknown;
     117             :     int ResetGeomType(int nNewType);
     118             : 
     119             :     bool ScanIndices();
     120             : 
     121             :     GIntBig *m_panMatchingFIDs = nullptr;
     122             :     int m_iMatchingFID = 0;
     123             :     void ClearMatchingFIDs();
     124             : 
     125             :     OGRGeometry *m_poFilterGeomLastValid = nullptr;
     126             :     int m_nSpatialFIDCount = 0;
     127             :     int *m_panSpatialFIDs = nullptr;
     128             :     void ClearSpatialFIDs();
     129             : 
     130             :     bool m_bHeaderDirty = false;
     131             :     bool m_bSHPNeedsRepack = false;
     132             :     bool m_bCheckedForQIX = false;
     133             :     SHPTreeDiskHandle m_hQIX = nullptr;
     134             :     bool CheckForQIX();
     135             : 
     136             :     bool m_bCheckedForSBN = false;
     137             :     SBNSearchHandle m_hSBN = nullptr;
     138             :     bool CheckForSBN();
     139             : 
     140             :     bool m_bSbnSbxDeleted = false;
     141             : 
     142             :     CPLString ConvertCodePage(const char *);
     143             :     CPLString m_osEncoding{};
     144             : 
     145             :     bool m_bTruncationWarningEmitted = false;
     146             : 
     147             :     bool m_bHSHPWasNonNULL = false;  // Must try to reopen a .shp?
     148             :     bool m_bHDBFWasNonNULL = false;  // Must try to reopen a .dbf
     149             : 
     150             :     // Current state of opening of file descriptor to .shp and .dbf.
     151             : 
     152             :     typedef enum
     153             :     {
     154             :         FD_OPENED,
     155             :         FD_CLOSED,
     156             :         FD_CANNOT_REOPEN
     157             :     } FileDescriptorState;
     158             : 
     159             :     FileDescriptorState m_eFileDescriptorsState = FD_OPENED;
     160             : 
     161             :     bool TouchLayer();
     162             :     bool ReopenFileDescriptors();
     163             : 
     164             :     bool m_bResizeAtClose = false;
     165             : 
     166             :     void TruncateDBF();
     167             : 
     168             :     bool m_bCreateSpatialIndexAtClose = false;
     169             :     bool m_bRewindOnWrite = false;
     170             :     bool m_bHasWarnedWrongWindingOrder = false;
     171             :     bool m_bLastGetNextArrowArrayUsedOptimizedCodePath = false;
     172             : 
     173             :     bool m_bAutoRepack = false;
     174             : 
     175             :     typedef enum
     176             :     {
     177             :         YES,
     178             :         NO,
     179             :         MAYBE
     180             :     } NormandyState; /* French joke. "Peut'et' ben que oui, peut'et' ben que
     181             :                         non." Sorry :-) */
     182             : 
     183             :     NormandyState m_eNeedRepack = MAYBE;
     184             : 
     185             :     // Set of field names (in upper case). Built and invalidated when convenient
     186             :     std::set<CPLString> m_oSetUCFieldName{};
     187             : 
     188             :     bool StartUpdate(const char *pszOperation);
     189             : 
     190             :     void CloseUnderlyingLayer() override;
     191             : 
     192             :     // WARNING: Each of the below public methods should start with a call to
     193             :     // TouchLayer() and test its return value, so as to make sure that
     194             :     // the layer is properly re-opened if necessary.
     195             : 
     196             :   public:
     197             :     OGRErr CreateSpatialIndex(int nMaxDepth);
     198             :     OGRErr DropSpatialIndex();
     199             :     OGRErr Repack();
     200             :     OGRErr RecomputeExtent();
     201             :     OGRErr ResizeDBF();
     202             : 
     203        1681 :     void SetResizeAtClose(bool bFlag)
     204             :     {
     205        1681 :         m_bResizeAtClose = bFlag;
     206        1681 :     }
     207             : 
     208         580 :     const char *GetFullName()
     209             :     {
     210         580 :         return m_osFullName.c_str();
     211             :     }
     212             : 
     213             :     void UpdateFollowingDeOrRecompression();
     214             : 
     215             :     OGRFeature *FetchShape(int iShapeId);
     216             :     int GetFeatureCountWithSpatialFilterOnly();
     217             : 
     218             :     OGRShapeLayer(OGRShapeDataSource *poDSIn, const char *pszName,
     219             :                   SHPHandle hSHP, DBFHandle hDBF,
     220             :                   const OGRSpatialReference *poSRS, bool bSRSSet,
     221             :                   const std::string &osPrjFilename, bool bUpdate,
     222             :                   OGRwkbGeometryType eReqType,
     223             :                   CSLConstList papszCreateOptions = nullptr);
     224             :     ~OGRShapeLayer() override;
     225             : 
     226             :     GDALDataset *GetDataset() override;
     227             : 
     228             :     void ResetReading() override;
     229             :     OGRFeature *GetNextFeature() override;
     230             :     OGRErr SetNextByIndex(GIntBig nIndex) override;
     231             : 
     232             :     int GetNextArrowArray(struct ArrowArrayStream *,
     233             :                           struct ArrowArray *out_array) override;
     234             :     const char *GetMetadataItem(const char *pszName,
     235             :                                 const char *pszDomain) override;
     236             : 
     237             :     OGRFeature *GetFeature(GIntBig nFeatureId) override;
     238             :     OGRErr ISetFeature(OGRFeature *poFeature) override;
     239             :     OGRErr DeleteFeature(GIntBig nFID) override;
     240             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     241             :     OGRErr SyncToDisk() override;
     242             : 
     243             :     using OGRAbstractProxiedLayer::GetLayerDefn;
     244             : 
     245     1714180 :     const OGRFeatureDefn *GetLayerDefn() const override
     246             :     {
     247     1714180 :         return m_poFeatureDefn;
     248             :     }
     249             : 
     250             :     GIntBig GetFeatureCount(int) override;
     251             :     OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
     252             :                       bool bForce) override;
     253             : 
     254             :     OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
     255             :                         bool bForce) override;
     256             : 
     257             :     OGRErr CreateField(const OGRFieldDefn *poField,
     258             :                        int bApproxOK = TRUE) override;
     259             :     OGRErr DeleteField(int iField) override;
     260             :     OGRErr ReorderFields(int *panMap) override;
     261             :     OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
     262             :                           int nFlags) override;
     263             :     OGRErr AlterGeomFieldDefn(int iGeomField,
     264             :                               const OGRGeomFieldDefn *poNewGeomFieldDefn,
     265             :                               int nFlagsIn) override;
     266             : 
     267             :     int TestCapability(const char *) const override;
     268             : 
     269             :     OGRErr ISetSpatialFilter(int iGeomField,
     270             :                              const OGRGeometry *poGeom) override;
     271             : 
     272             :     OGRErr SetAttributeFilter(const char *) override;
     273             : 
     274             :     OGRErr Rename(const char *pszNewName) override;
     275             : 
     276             :     void AddToFileList(CPLStringList &oFileList);
     277             : 
     278        1681 :     void CreateSpatialIndexAtClose(int bFlag)
     279             :     {
     280        1681 :         m_bCreateSpatialIndexAtClose = CPL_TO_BOOL(bFlag);
     281        1681 :     }
     282             : 
     283             :     void SetModificationDate(const char *pszStr);
     284             : 
     285        7720 :     void SetAutoRepack(bool b)
     286             :     {
     287        7720 :         m_bAutoRepack = b;
     288        7720 :     }
     289             : 
     290             :     void SetWriteDBFEOFChar(bool b);
     291             : };
     292             : 
     293             : /************************************************************************/
     294             : /*                          OGRShapeDataSource                          */
     295             : /************************************************************************/
     296             : 
     297             : class OGRShapeDataSource final : public GDALDataset
     298             : {
     299             :     std::vector<std::unique_ptr<OGRShapeLayer>> m_apoLayers{};
     300             :     bool m_bSingleFileDataSource = false;
     301             :     std::unique_ptr<OGRLayerPool> m_poPool{};
     302             : 
     303             :     mutable std::vector<CPLString> m_oVectorLayerName{};
     304             : 
     305             :     bool m_b2GBLimit = false;
     306             :     bool m_bIsZip = false;
     307             :     bool m_bSingleLayerZip = false;
     308             :     CPLString m_osTemporaryUnzipDir{};
     309             :     CPLMutex *m_poRefreshLockFileMutex = nullptr;
     310             :     CPLCond *m_poRefreshLockFileCond = nullptr;
     311             :     VSILFILE *m_psLockFile = nullptr;
     312             :     CPLJoinableThread *m_hRefreshLockFileThread = nullptr;
     313             :     bool m_bExitRefreshLockFileThread = false;
     314             :     bool m_bRefreshLockFileThreadStarted = false;
     315             :     double m_dfRefreshLockDelay = 0;
     316             : 
     317             :     std::vector<CPLString> GetLayerNames() const;
     318             :     void AddLayer(std::unique_ptr<OGRShapeLayer> poLayer);
     319             :     static void RefreshLockFile(void *_self);
     320             :     void RemoveLockFile();
     321             :     bool RecompressIfNeeded(const std::vector<CPLString> &layerNames);
     322             : 
     323             :     CPL_DISALLOW_COPY_ASSIGN(OGRShapeDataSource)
     324             : 
     325             :   public:
     326             :     OGRShapeDataSource();
     327             :     ~OGRShapeDataSource() override;
     328             : 
     329             :     CPLErr Close() override;
     330             : 
     331        7720 :     OGRLayerPool *GetPool() const
     332             :     {
     333        7720 :         return m_poPool.get();
     334             :     }
     335             : 
     336             :     bool Open(GDALOpenInfo *poOpenInfo, bool bTestOpen,
     337             :               bool bForceSingleFileDataSource = false);
     338             :     bool OpenFile(const char *, bool bUpdate);
     339             :     bool OpenZip(GDALOpenInfo *poOpenInfo, const char *pszOriFilename);
     340             :     bool CreateZip(const char *pszOriFilename);
     341             : 
     342             :     int GetLayerCount() const override;
     343             :     const OGRLayer *GetLayer(int) const override;
     344             :     OGRLayer *GetLayerByName(const char *) override;
     345             : 
     346             :     OGRLayer *ICreateLayer(const char *pszName,
     347             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     348             :                            CSLConstList papszOptions) override;
     349             : 
     350             :     OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
     351             :                          const char *pszDialect) override;
     352             : 
     353             :     int TestCapability(const char *) const override;
     354             :     OGRErr DeleteLayer(int iLayer) override;
     355             : 
     356             :     char **GetFileList() override;
     357             : 
     358             :     void SetLastUsedLayer(OGRShapeLayer *poLayer);
     359             :     void UnchainLayer(OGRShapeLayer *poLayer);
     360             : 
     361             :     bool UncompressIfNeeded();
     362             : 
     363             :     SHPHandle DS_SHPOpen(const char *pszShapeFile, const char *pszAccess);
     364             :     DBFHandle DS_DBFOpen(const char *pszDBFFile, const char *pszAccess);
     365             : 
     366       20754 :     char **GetOpenOptions()
     367             :     {
     368       20754 :         return papszOpenOptions;
     369             :     }
     370             : 
     371             :     static const char *const *GetExtensionsForDeletion();
     372             : 
     373        3478 :     bool IsZip() const
     374             :     {
     375        3478 :         return m_bIsZip;
     376             :     }
     377             : 
     378           6 :     CPLString GetVSIZipPrefixeDir() const
     379             :     {
     380          12 :         return CPLString("/vsizip/{").append(GetDescription()).append("}");
     381             :     }
     382             : 
     383          13 :     const CPLString &GetTemporaryUnzipDir() const
     384             :     {
     385          13 :         return m_osTemporaryUnzipDir;
     386             :     }
     387             : 
     388             :     static bool CopyInPlace(VSILFILE *fpTarget,
     389             :                             const CPLString &osSourceFilename);
     390             : };
     391             : 
     392             : #endif /* ndef OGRSHAPE_H_INCLUDED */

Generated by: LCOV version 1.14