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 */
|