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 5142 : OGRShapeGeomFieldDefn(const char *pszFullNameIn, OGRwkbGeometryType eType,
67 : int bSRSSetIn, OGRSpatialReference *poSRSIn)
68 5142 : : OGRGeomFieldDefn("", eType), m_osFullName(pszFullNameIn),
69 5142 : m_bSRSSet(CPL_TO_BOOL(bSRSSetIn))
70 : {
71 5142 : SetSpatialRef(poSRSIn);
72 5142 : }
73 :
74 : const OGRSpatialReference *GetSpatialRef() const override;
75 :
76 3 : void SetSRSSet()
77 : {
78 3 : m_bSRSSet = true;
79 3 : }
80 :
81 23 : const CPLString &GetPrjFilename() const
82 : {
83 23 : return m_osPrjFile;
84 : }
85 :
86 222 : void SetPrjFilename(const std::string &osFilename)
87 : {
88 222 : m_osPrjFile = osFilename;
89 222 : }
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 1658 : void SetResizeAtClose(bool bFlag)
203 : {
204 1658 : m_bResizeAtClose = bFlag;
205 1658 : }
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 : 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 1423510 : OGRFeatureDefn *GetLayerDefn() override
243 : {
244 1423510 : return m_poFeatureDefn;
245 : }
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 1658 : void CreateSpatialIndexAtClose(int bFlag)
276 : {
277 1658 : m_bCreateSpatialIndexAtClose = CPL_TO_BOOL(bFlag);
278 1658 : }
279 :
280 : void SetModificationDate(const char *pszStr);
281 :
282 5523 : void SetAutoRepack(bool b)
283 : {
284 5523 : m_bAutoRepack = b;
285 5523 : }
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 5523 : OGRLayerPool *GetPool() const
327 : {
328 5523 : return m_poPool.get();
329 : }
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 14579 : char **GetOpenOptions()
362 : {
363 14579 : return papszOpenOptions;
364 : }
365 :
366 : static const char *const *GetExtensionsForDeletion();
367 :
368 1670 : bool IsZip() const
369 : {
370 1670 : return m_bIsZip;
371 : }
372 :
373 6 : CPLString GetVSIZipPrefixeDir() const
374 : {
375 12 : return CPLString("/vsizip/{").append(GetDescription()).append("}");
376 : }
377 :
378 13 : const CPLString &GetTemporaryUnzipDir() const
379 : {
380 13 : return m_osTemporaryUnzipDir;
381 : }
382 :
383 : static bool CopyInPlace(VSILFILE *fpTarget,
384 : const CPLString &osSourceFilename);
385 : };
386 :
387 : #endif /* ndef OGRSHAPE_H_INCLUDED */
|