1 /******************************************************************************
2  * $Id: ogrshape.h 74eca1110adf6e47b87fee110ad9bf5f322fef64 2021-03-15 14:38:32 +0100 Even Rouault $
3  *
4  * Project:  OpenGIS Simple Features Reference Implementation
5  * Purpose:  Private definitions within the Shapefile driver to implement
6  *           integration with OGR.
7  * Author:   Frank Warmerdam, warmerdam@pobox.com
8  *
9  ******************************************************************************
10  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
11  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a
14  * copy of this software and associated documentation files (the "Software"),
15  * to deal in the Software without restriction, including without limitation
16  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17  * and/or sell copies of the Software, and to permit persons to whom the
18  * Software is furnished to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included
21  * in all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29  * DEALINGS IN THE SOFTWARE.
30  ****************************************************************************/
31 
32 #ifndef OGRSHAPE_H_INCLUDED
33 #define OGRSHAPE_H_INCLUDED
34 
35 #ifdef RENAME_INTERNAL_SHAPELIB_SYMBOLS
36 #include "gdal_shapelib_symbol_rename.h"
37 #endif
38 
39 #include "ogrsf_frmts.h"
40 #include "shapefil.h"
41 #include "shp_vsi.h"
42 #include "ogrlayerpool.h"
43 #include <set>
44 #include <vector>
45 
46 /* Was limited to 255 until OGR 1.10, but 254 seems to be a more */
47 /* conventional limit (http://en.wikipedia.org/wiki/Shapefile, */
48 /* http://www.clicketyclick.dk/databases/xbase/format/data_types.html, */
49 /* #5052 ) */
50 #define OGR_DBF_MAX_FIELD_WIDTH 254
51 
52 /* ==================================================================== */
53 /*      Functions from Shape2ogr.cpp.                                   */
54 /* ==================================================================== */
55 OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
56                                OGRFeatureDefn * poDefn, int iShape,
57                                SHPObject *psShape, const char *pszSHPEncoding );
58 OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape );
59 OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
60                                        SHPHandle hSHP, DBFHandle hDBF,
61                                        const char *pszSHPEncoding,
62                                        int bAdjustType );
63 OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
64                            OGRFeatureDefn *poFeatureDefn,
65                            OGRFeature *poFeature, const char *pszSHPEncoding,
66                            bool* pbTruncationWarningEmitted,
67                            bool bRewind );
68 
69 /************************************************************************/
70 /*                         OGRShapeGeomFieldDefn                        */
71 /************************************************************************/
72 
73 class OGRShapeGeomFieldDefn final: public OGRGeomFieldDefn
74 {
75     CPL_DISALLOW_COPY_ASSIGN(OGRShapeGeomFieldDefn)
76 
77     char* pszFullName = nullptr;
78     mutable bool  bSRSSet = false;
79     mutable CPLString osPrjFile{};
80 
81     public:
OGRShapeGeomFieldDefn(const char * pszFullNameIn,OGRwkbGeometryType eType,int bSRSSetIn,OGRSpatialReference * poSRSIn)82         OGRShapeGeomFieldDefn( const char* pszFullNameIn,
83                                OGRwkbGeometryType eType,
84                                int bSRSSetIn, OGRSpatialReference *poSRSIn) :
85             OGRGeomFieldDefn("", eType),
86             pszFullName(CPLStrdup(pszFullNameIn)),
87             bSRSSet(CPL_TO_BOOL(bSRSSetIn))
88         {
89             SetSpatialRef(poSRSIn);
90         }
91 
~OGRShapeGeomFieldDefn()92         virtual ~OGRShapeGeomFieldDefn()
93         {
94             CPLFree(pszFullName);
95         }
96 
97         OGRSpatialReference* GetSpatialRef() const override;
98 
GetPrjFilename()99         const CPLString& GetPrjFilename() const { return osPrjFile; }
100 };
101 
102 /************************************************************************/
103 /*                            OGRShapeLayer                             */
104 /************************************************************************/
105 
106 class OGRShapeDataSource;
107 
108 class OGRShapeLayer final: public OGRAbstractProxiedLayer
109 {
110     CPL_DISALLOW_COPY_ASSIGN(OGRShapeLayer)
111 
112     OGRShapeDataSource  *poDS;
113 
114     OGRFeatureDefn     *poFeatureDefn;
115     int                 iNextShapeId;
116     int                 nTotalShapeCount;
117 
118     char                *pszFullName;
119 
120     SHPHandle           hSHP;
121     DBFHandle           hDBF;
122 
123     bool                bUpdateAccess;
124 
125     OGRwkbGeometryType  eRequestedGeomType;
126     int                 ResetGeomType( int nNewType );
127 
128     bool                ScanIndices();
129 
130     GIntBig            *panMatchingFIDs;
131     int                 iMatchingFID;
132     void                ClearMatchingFIDs();
133 
134     OGRGeometry        *m_poFilterGeomLastValid;
135     int                 nSpatialFIDCount;
136     int                *panSpatialFIDs;
137     void                ClearSpatialFIDs();
138 
139     bool                bHeaderDirty;
140     bool                bSHPNeedsRepack;
141     bool                bCheckedForQIX;
142     SHPTreeDiskHandle   hQIX;
143     bool                CheckForQIX();
144 
145     bool                bCheckedForSBN;
146     SBNSearchHandle     hSBN;
147     bool                CheckForSBN();
148 
149     bool                bSbnSbxDeleted;
150 
151     CPLString           ConvertCodePage( const char * );
152     CPLString           osEncoding{};
153 
154     bool                bTruncationWarningEmitted;
155 
156     bool                bHSHPWasNonNULL; // Must try to reopen a .shp?
157     bool                bHDBFWasNonNULL; // Must try to reopen a .dbf
158     // Current state of opening of file descriptor to .shp and .dbf.
159 
160     typedef enum
161     {
162         FD_OPENED,
163         FD_CLOSED,
164         FD_CANNOT_REOPEN
165     } FileDescriptorState;
166     FileDescriptorState eFileDescriptorsState;
167 
168     bool                TouchLayer();
169     bool                ReopenFileDescriptors();
170 
171     bool                bResizeAtClose;
172 
173     void                TruncateDBF();
174 
175     bool                bCreateSpatialIndexAtClose;
176     bool                bRewindOnWrite;
177 
178     bool                m_bAutoRepack;
179     typedef enum
180     {
181         YES,
182         NO,
183         MAYBE
184     } NormandyState; /* French joke. "Peut'et' ben que oui, peut'et' ben que non." Sorry :-) */
185     NormandyState       m_eNeedRepack;
186 
187     // Set of field names (in upper case). Built and invalidated when convenient
188     std::set<CPLString> m_oSetUCFieldName{};
189 
190     bool                StartUpdate( const char* pszOperation );
191 
192     void                CloseUnderlyingLayer() override;
193 
194 // WARNING: Each of the below public methods should start with a call to
195 // TouchLayer() and test its return value, so as to make sure that
196 // the layer is properly re-opened if necessary.
197 
198   public:
199     OGRErr              CreateSpatialIndex( int nMaxDepth );
200     OGRErr              DropSpatialIndex();
201     OGRErr              Repack();
202     OGRErr              RecomputeExtent();
203     OGRErr              ResizeDBF();
204 
SetResizeAtClose(bool bFlag)205     void                SetResizeAtClose( bool bFlag )
206         { bResizeAtClose = bFlag; }
207 
GetFullName()208     const char         *GetFullName() { return pszFullName; }
209     void                UpdateFollowingDeOrRecompression();
210 
211     OGRFeature *        FetchShape( int iShapeId );
212     int                 GetFeatureCountWithSpatialFilterOnly();
213 
214                         OGRShapeLayer( OGRShapeDataSource* poDSIn,
215                                        const char * pszName,
216                                        SHPHandle hSHP, DBFHandle hDBF,
217                                        const OGRSpatialReference *poSRS, bool bSRSSet,
218                                        bool bUpdate,
219                                        OGRwkbGeometryType eReqType,
220                                        char ** papszCreateOptions = nullptr);
221     virtual            ~OGRShapeLayer();
222 
223     void                ResetReading() override;
224     OGRFeature *        GetNextFeature() override;
225     OGRErr              SetNextByIndex( GIntBig nIndex ) override;
226 
227     OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
228     OGRErr              ISetFeature( OGRFeature *poFeature ) override;
229     OGRErr              DeleteFeature( GIntBig nFID ) override;
230     OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
231     OGRErr              SyncToDisk() override;
232 
GetLayerDefn()233     OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
234 
235     GIntBig             GetFeatureCount( int ) override;
236     OGRErr              GetExtent( OGREnvelope *psExtent, int bForce ) override;
GetExtent(int iGeomField,OGREnvelope * psExtent,int bForce)237     OGRErr              GetExtent( int iGeomField, OGREnvelope *psExtent,
238                                    int bForce ) override
239                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
240 
241     OGRErr              CreateField( OGRFieldDefn *poField,
242                                      int bApproxOK = TRUE ) override;
243     OGRErr              DeleteField( int iField ) override;
244     OGRErr              ReorderFields( int* panMap ) override;
245     OGRErr              AlterFieldDefn( int iField,
246                                         OGRFieldDefn* poNewFieldDefn,
247                                         int nFlags ) override;
248 
249     int                 TestCapability( const char * ) override;
250     void                SetSpatialFilter( OGRGeometry * ) override;
SetSpatialFilter(int iGeomField,OGRGeometry * poGeom)251     void                SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
252                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
253 
254     OGRErr              SetAttributeFilter( const char * ) override;
255 
256     void                AddToFileList( CPLStringList& oFileList );
CreateSpatialIndexAtClose(int bFlag)257     void                CreateSpatialIndexAtClose( int bFlag )
258         { bCreateSpatialIndexAtClose = CPL_TO_BOOL(bFlag); }
259     void                SetModificationDate( const char* pszStr );
SetAutoRepack(bool b)260     void                SetAutoRepack(bool b) { m_bAutoRepack = b; }
261     void                SetWriteDBFEOFChar(bool b);
262 };
263 
264 /************************************************************************/
265 /*                          OGRShapeDataSource                          */
266 /************************************************************************/
267 
268 class OGRShapeDataSource final: public OGRDataSource
269 {
270     OGRShapeLayer     **papoLayers;
271     int                 nLayers;
272     char                *pszName;
273     bool                bDSUpdate;
274     bool                bSingleFileDataSource;
275     OGRLayerPool       *poPool;
276 
277     std::vector<CPLString> oVectorLayerName{};
278 
279     bool                b2GBLimit;
280     bool                m_bIsZip = false;
281     bool                m_bSingleLayerZip = false;
282     CPLString           m_osTemporaryUnzipDir{};
283     CPLMutex           *m_poRefreshLockFileMutex = nullptr;
284     CPLCond            *m_poRefreshLockFileCond = nullptr;
285     VSILFILE           *m_psLockFile = nullptr;
286     CPLJoinableThread  *m_hRefreshLockFileThread = nullptr;
287     bool                m_bExitRefreshLockFileThread = false;
288     double              m_dfRefreshLockDelay = 0;
289 
290     std::vector<CPLString> GetLayerNames() const;
291     void                AddLayer( OGRShapeLayer* poLayer );
292     static void         RefreshLockFile(void* _self);
293     void                RemoveLockFile();
294     bool                RecompressIfNeeded(const std::vector<CPLString>& layerNames);
295 
296     CPL_DISALLOW_COPY_ASSIGN(OGRShapeDataSource)
297 
298   public:
299                         OGRShapeDataSource();
300     virtual            ~OGRShapeDataSource();
301 
GetPool()302     OGRLayerPool       *GetPool() const { return poPool; }
303 
304     bool                Open( GDALOpenInfo* poOpenInfo, bool bTestOpen,
305                               bool bForceSingleFileDataSource = false );
306     bool                OpenFile( const char *, bool bUpdate );
307     bool                OpenZip( GDALOpenInfo* poOpenInfo,
308                                  const char* pszOriFilename );
309     bool                CreateZip(const char* pszOriFilename );
310 
GetName()311     const char         *GetName() override { return pszName; }
312 
313     int                 GetLayerCount() override;
314     OGRLayer           *GetLayer( int ) override;
315     OGRLayer           *GetLayerByName( const char * ) override;
316 
317     OGRLayer           *ICreateLayer( const char *,
318                                        OGRSpatialReference * = nullptr,
319                                        OGRwkbGeometryType = wkbUnknown,
320                                        char ** = nullptr ) override;
321 
322     OGRLayer           *ExecuteSQL( const char *pszStatement,
323                                      OGRGeometry *poSpatialFilter,
324                                      const char *pszDialect ) override;
325 
326     int                 TestCapability( const char * ) override;
327     OGRErr              DeleteLayer( int iLayer ) override;
328 
329     char              **GetFileList() override;
330 
331     void                 SetLastUsedLayer( OGRShapeLayer* poLayer );
332     void                 UnchainLayer( OGRShapeLayer* poLayer );
333 
334     bool                 UncompressIfNeeded();
335 
336     SHPHandle            DS_SHPOpen( const char * pszShapeFile,
337                                      const char * pszAccess );
338     DBFHandle            DS_DBFOpen( const char * pszDBFFile,
339                                      const char * pszAccess );
GetOpenOptions()340     char               **GetOpenOptions() { return papszOpenOptions; }
341 
342     static const char* const* GetExtensionsForDeletion();
IsZip()343     bool                 IsZip() const { return m_bIsZip; }
GetVSIZipPrefixeDir()344     CPLString            GetVSIZipPrefixeDir() const { return CPLString("/vsizip/{") + pszName + '}'; }
GetTemporaryUnzipDir()345     const CPLString&     GetTemporaryUnzipDir() const { return m_osTemporaryUnzipDir; }
346 
347     static bool          CopyInPlace( VSILFILE* fpTarget,
348                                       const CPLString& osSourceFilename );
349 };
350 
351 #endif /* ndef OGRSHAPE_H_INCLUDED */
352