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 "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 : #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 6896 : OGRShapeGeomFieldDefn(const char *pszFullNameIn, OGRwkbGeometryType eType,
67 : int bSRSSetIn, OGRSpatialReference *poSRSIn)
68 6896 : : OGRGeomFieldDefn("", eType), m_osFullName(pszFullNameIn),
69 6896 : m_bSRSSet(CPL_TO_BOOL(bSRSSetIn))
70 : {
71 6896 : SetSpatialRef(poSRSIn);
72 6896 : }
73 :
74 : const OGRSpatialReference *GetSpatialRef() const override;
75 :
76 3 : void SetSRSSet()
77 : {
78 3 : m_bSRSSet = true;
79 3 : }
80 :
81 24 : const CPLString &GetPrjFilename() const
82 : {
83 24 : return m_osPrjFile;
84 : }
85 :
86 227 : void SetPrjFilename(const std::string &osFilename)
87 : {
88 227 : m_osPrjFile = osFilename;
89 227 : }
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 1672 : void SetResizeAtClose(bool bFlag)
203 : {
204 1672 : m_bResizeAtClose = bFlag;
205 1672 : }
206 :
207 580 : const char *GetFullName()
208 : {
209 580 : return m_osFullName.c_str();
210 : }
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 : ~OGRShapeLayer() override;
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 : using OGRAbstractProxiedLayer::GetLayerDefn;
243 :
244 1715500 : const OGRFeatureDefn *GetLayerDefn() const override
245 : {
246 1715500 : return m_poFeatureDefn;
247 : }
248 :
249 : GIntBig GetFeatureCount(int) override;
250 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
251 : bool bForce) override;
252 :
253 : OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
254 : bool bForce) override;
255 :
256 : OGRErr CreateField(const OGRFieldDefn *poField,
257 : int bApproxOK = TRUE) override;
258 : OGRErr DeleteField(int iField) override;
259 : OGRErr ReorderFields(int *panMap) override;
260 : OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
261 : int nFlags) override;
262 : OGRErr AlterGeomFieldDefn(int iGeomField,
263 : const OGRGeomFieldDefn *poNewGeomFieldDefn,
264 : int nFlagsIn) override;
265 :
266 : int TestCapability(const char *) const override;
267 :
268 : OGRErr ISetSpatialFilter(int iGeomField,
269 : const OGRGeometry *poGeom) override;
270 :
271 : OGRErr SetAttributeFilter(const char *) override;
272 :
273 : OGRErr Rename(const char *pszNewName) override;
274 :
275 : void AddToFileList(CPLStringList &oFileList);
276 :
277 1672 : void CreateSpatialIndexAtClose(int bFlag)
278 : {
279 1672 : m_bCreateSpatialIndexAtClose = CPL_TO_BOOL(bFlag);
280 1672 : }
281 :
282 : void SetModificationDate(const char *pszStr);
283 :
284 7670 : void SetAutoRepack(bool b)
285 : {
286 7670 : m_bAutoRepack = b;
287 7670 : }
288 :
289 : void SetWriteDBFEOFChar(bool b);
290 : };
291 :
292 : /************************************************************************/
293 : /* OGRShapeDataSource */
294 : /************************************************************************/
295 :
296 : class OGRShapeDataSource final : public GDALDataset
297 : {
298 : std::vector<std::unique_ptr<OGRShapeLayer>> m_apoLayers{};
299 : bool m_bSingleFileDataSource = false;
300 : std::unique_ptr<OGRLayerPool> m_poPool{};
301 :
302 : mutable std::vector<CPLString> m_oVectorLayerName{};
303 :
304 : bool m_b2GBLimit = false;
305 : bool m_bIsZip = false;
306 : bool m_bSingleLayerZip = false;
307 : CPLString m_osTemporaryUnzipDir{};
308 : CPLMutex *m_poRefreshLockFileMutex = nullptr;
309 : CPLCond *m_poRefreshLockFileCond = nullptr;
310 : VSILFILE *m_psLockFile = nullptr;
311 : CPLJoinableThread *m_hRefreshLockFileThread = nullptr;
312 : bool m_bExitRefreshLockFileThread = false;
313 : bool m_bRefreshLockFileThreadStarted = false;
314 : double m_dfRefreshLockDelay = 0;
315 :
316 : std::vector<CPLString> GetLayerNames() const;
317 : void AddLayer(std::unique_ptr<OGRShapeLayer> poLayer);
318 : static void RefreshLockFile(void *_self);
319 : void RemoveLockFile();
320 : bool RecompressIfNeeded(const std::vector<CPLString> &layerNames);
321 :
322 : CPL_DISALLOW_COPY_ASSIGN(OGRShapeDataSource)
323 :
324 : public:
325 : OGRShapeDataSource();
326 : ~OGRShapeDataSource() override;
327 :
328 : CPLErr Close() override;
329 :
330 7670 : OGRLayerPool *GetPool() const
331 : {
332 7670 : return m_poPool.get();
333 : }
334 :
335 : bool Open(GDALOpenInfo *poOpenInfo, bool bTestOpen,
336 : bool bForceSingleFileDataSource = false);
337 : bool OpenFile(const char *, bool bUpdate);
338 : bool OpenZip(GDALOpenInfo *poOpenInfo, const char *pszOriFilename);
339 : bool CreateZip(const char *pszOriFilename);
340 :
341 : int GetLayerCount() const override;
342 : const OGRLayer *GetLayer(int) const override;
343 : OGRLayer *GetLayerByName(const char *) override;
344 :
345 : OGRLayer *ICreateLayer(const char *pszName,
346 : const OGRGeomFieldDefn *poGeomFieldDefn,
347 : CSLConstList papszOptions) override;
348 :
349 : OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
350 : const char *pszDialect) override;
351 :
352 : int TestCapability(const char *) const override;
353 : OGRErr DeleteLayer(int iLayer) override;
354 :
355 : char **GetFileList() override;
356 :
357 : void SetLastUsedLayer(OGRShapeLayer *poLayer);
358 : void UnchainLayer(OGRShapeLayer *poLayer);
359 :
360 : bool UncompressIfNeeded();
361 :
362 : SHPHandle DS_SHPOpen(const char *pszShapeFile, const char *pszAccess);
363 : DBFHandle DS_DBFOpen(const char *pszDBFFile, const char *pszAccess);
364 :
365 20620 : char **GetOpenOptions()
366 : {
367 20620 : return papszOpenOptions;
368 : }
369 :
370 : static const char *const *GetExtensionsForDeletion();
371 :
372 3478 : bool IsZip() const
373 : {
374 3478 : return m_bIsZip;
375 : }
376 :
377 6 : CPLString GetVSIZipPrefixeDir() const
378 : {
379 12 : return CPLString("/vsizip/{").append(GetDescription()).append("}");
380 : }
381 :
382 13 : const CPLString &GetTemporaryUnzipDir() const
383 : {
384 13 : return m_osTemporaryUnzipDir;
385 : }
386 :
387 : static bool CopyInPlace(VSILFILE *fpTarget,
388 : const CPLString &osSourceFilename);
389 : };
390 :
391 : #endif /* ndef OGRSHAPE_H_INCLUDED */
|