Coverage Report

Created: 2025-06-13 06:18

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