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, VSILFILE *fpSHPXML,
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 6951 : OGRShapeGeomFieldDefn(const char *pszFullNameIn, OGRwkbGeometryType eType,
68 : int bSRSSetIn, OGRSpatialReference *poSRSIn)
69 6951 : : OGRGeomFieldDefn("", eType), m_osFullName(pszFullNameIn),
70 6951 : m_bSRSSet(CPL_TO_BOOL(bSRSSetIn))
71 : {
72 6951 : SetSpatialRef(poSRSIn);
73 6951 : }
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 : bool m_bHasShpXML = false;
116 :
117 : OGRwkbGeometryType m_eRequestedGeomType = wkbUnknown;
118 : int ResetGeomType(int nNewType);
119 :
120 : bool ScanIndices();
121 :
122 : GIntBig *m_panMatchingFIDs = nullptr;
123 : int m_iMatchingFID = 0;
124 : void ClearMatchingFIDs();
125 :
126 : OGRGeometry *m_poFilterGeomLastValid = nullptr;
127 : int m_nSpatialFIDCount = 0;
128 : int *m_panSpatialFIDs = nullptr;
129 : void ClearSpatialFIDs();
130 :
131 : bool m_bHeaderDirty = false;
132 : bool m_bSHPNeedsRepack = false;
133 : bool m_bCheckedForQIX = false;
134 : SHPTreeDiskHandle m_hQIX = nullptr;
135 : bool CheckForQIX();
136 :
137 : bool m_bCheckedForSBN = false;
138 : SBNSearchHandle m_hSBN = nullptr;
139 : bool CheckForSBN();
140 :
141 : bool m_bSbnSbxDeleted = false;
142 :
143 : CPLString ConvertCodePage(const char *);
144 : CPLString m_osEncoding{};
145 :
146 : bool m_bTruncationWarningEmitted = false;
147 :
148 : bool m_bHSHPWasNonNULL = false; // Must try to reopen a .shp?
149 : bool m_bHDBFWasNonNULL = false; // Must try to reopen a .dbf
150 :
151 : // Current state of opening of file descriptor to .shp and .dbf.
152 :
153 : typedef enum
154 : {
155 : FD_OPENED,
156 : FD_CLOSED,
157 : FD_CANNOT_REOPEN
158 : } FileDescriptorState;
159 :
160 : FileDescriptorState m_eFileDescriptorsState = FD_OPENED;
161 :
162 : bool TouchLayer();
163 : bool ReopenFileDescriptors();
164 :
165 : bool m_bResizeAtClose = false;
166 :
167 : void TruncateDBF();
168 :
169 : bool m_bCreateSpatialIndexAtClose = false;
170 : bool m_bRewindOnWrite = false;
171 : bool m_bHasWarnedWrongWindingOrder = false;
172 : bool m_bLastGetNextArrowArrayUsedOptimizedCodePath = false;
173 :
174 : bool m_bAutoRepack = false;
175 :
176 : typedef enum
177 : {
178 : YES,
179 : NO,
180 : MAYBE
181 : } NormandyState; /* French joke. "Peut'et' ben que oui, peut'et' ben que
182 : non." Sorry :-) */
183 :
184 : NormandyState m_eNeedRepack = MAYBE;
185 :
186 : // Set of field names (in upper case). Built and invalidated when convenient
187 : std::set<CPLString> m_oSetUCFieldName{};
188 :
189 : bool StartUpdate(const char *pszOperation);
190 :
191 : void CloseUnderlyingLayer() override;
192 :
193 : // WARNING: Each of the below public methods should start with a call to
194 : // TouchLayer() and test its return value, so as to make sure that
195 : // the layer is properly re-opened if necessary.
196 :
197 : public:
198 : OGRErr CreateSpatialIndex(int nMaxDepth);
199 : OGRErr DropSpatialIndex();
200 : OGRErr Repack();
201 : OGRErr RecomputeExtent();
202 : OGRErr ResizeDBF();
203 :
204 1684 : void SetResizeAtClose(bool bFlag)
205 : {
206 1684 : m_bResizeAtClose = bFlag;
207 1684 : }
208 :
209 580 : const char *GetFullName()
210 : {
211 580 : return m_osFullName.c_str();
212 : }
213 :
214 : void UpdateFollowingDeOrRecompression();
215 :
216 : OGRFeature *FetchShape(int iShapeId);
217 : int GetFeatureCountWithSpatialFilterOnly();
218 :
219 : OGRShapeLayer(OGRShapeDataSource *poDSIn, const char *pszName,
220 : SHPHandle hSHP, DBFHandle hDBF,
221 : const OGRSpatialReference *poSRS, bool bSRSSet,
222 : const std::string &osPrjFilename, bool bUpdate,
223 : OGRwkbGeometryType eReqType,
224 : CSLConstList papszCreateOptions = nullptr);
225 : ~OGRShapeLayer() override;
226 :
227 : GDALDataset *GetDataset() override;
228 :
229 : void ResetReading() override;
230 : OGRFeature *GetNextFeature() override;
231 : OGRErr SetNextByIndex(GIntBig nIndex) override;
232 :
233 : int GetNextArrowArray(struct ArrowArrayStream *,
234 : struct ArrowArray *out_array) override;
235 : const char *GetMetadataItem(const char *pszName,
236 : const char *pszDomain) override;
237 :
238 : OGRFeature *GetFeature(GIntBig nFeatureId) override;
239 : OGRErr ISetFeature(OGRFeature *poFeature) override;
240 : OGRErr DeleteFeature(GIntBig nFID) override;
241 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
242 : OGRErr SyncToDisk() override;
243 :
244 : using OGRAbstractProxiedLayer::GetLayerDefn;
245 :
246 1714250 : const OGRFeatureDefn *GetLayerDefn() const override
247 : {
248 1714250 : return m_poFeatureDefn;
249 : }
250 :
251 : GIntBig GetFeatureCount(int) override;
252 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
253 : bool bForce) override;
254 :
255 : OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
256 : bool bForce) override;
257 :
258 : OGRErr CreateField(const OGRFieldDefn *poField,
259 : int bApproxOK = TRUE) override;
260 : OGRErr DeleteField(int iField) override;
261 : OGRErr ReorderFields(int *panMap) override;
262 : OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
263 : int nFlags) override;
264 : OGRErr AlterGeomFieldDefn(int iGeomField,
265 : const OGRGeomFieldDefn *poNewGeomFieldDefn,
266 : int nFlagsIn) override;
267 :
268 : int TestCapability(const char *) const override;
269 :
270 : OGRErr ISetSpatialFilter(int iGeomField,
271 : const OGRGeometry *poGeom) override;
272 :
273 : OGRErr SetAttributeFilter(const char *) override;
274 :
275 : OGRErr Rename(const char *pszNewName) override;
276 :
277 : void AddToFileList(CPLStringList &oFileList);
278 :
279 1684 : void CreateSpatialIndexAtClose(int bFlag)
280 : {
281 1684 : m_bCreateSpatialIndexAtClose = CPL_TO_BOOL(bFlag);
282 1684 : }
283 :
284 : void SetModificationDate(const char *pszStr);
285 :
286 7739 : void SetAutoRepack(bool b)
287 : {
288 7739 : m_bAutoRepack = b;
289 7739 : }
290 :
291 : void SetWriteDBFEOFChar(bool b);
292 : };
293 :
294 : /************************************************************************/
295 : /* OGRShapeDataSource */
296 : /************************************************************************/
297 :
298 : class OGRShapeDataSource final : public GDALDataset
299 : {
300 : std::vector<std::unique_ptr<OGRShapeLayer>> m_apoLayers{};
301 : bool m_bSingleFileDataSource = false;
302 : std::unique_ptr<OGRLayerPool> m_poPool{};
303 :
304 : mutable std::vector<CPLString> m_oVectorLayerName{};
305 :
306 : bool m_b2GBLimit = false;
307 : bool m_bIsZip = false;
308 : bool m_bSingleLayerZip = false;
309 : CPLString m_osTemporaryUnzipDir{};
310 : CPLMutex *m_poRefreshLockFileMutex = nullptr;
311 : CPLCond *m_poRefreshLockFileCond = nullptr;
312 : VSILFILE *m_psLockFile = nullptr;
313 : CPLJoinableThread *m_hRefreshLockFileThread = nullptr;
314 : bool m_bExitRefreshLockFileThread = false;
315 : bool m_bRefreshLockFileThreadStarted = false;
316 : double m_dfRefreshLockDelay = 0;
317 :
318 : std::vector<CPLString> GetLayerNames() const;
319 : void AddLayer(std::unique_ptr<OGRShapeLayer> poLayer);
320 : static void RefreshLockFile(void *_self);
321 : void RemoveLockFile();
322 : bool RecompressIfNeeded(const std::vector<CPLString> &layerNames);
323 :
324 : CPL_DISALLOW_COPY_ASSIGN(OGRShapeDataSource)
325 :
326 : public:
327 : OGRShapeDataSource();
328 : ~OGRShapeDataSource() override;
329 :
330 : CPLErr Close() override;
331 :
332 7739 : OGRLayerPool *GetPool() const
333 : {
334 7739 : return m_poPool.get();
335 : }
336 :
337 : bool Open(GDALOpenInfo *poOpenInfo, bool bTestOpen,
338 : bool bForceSingleFileDataSource = false);
339 : bool OpenFile(const char *, bool bUpdate);
340 : bool OpenZip(GDALOpenInfo *poOpenInfo, const char *pszOriFilename);
341 : bool CreateZip(const char *pszOriFilename);
342 :
343 : int GetLayerCount() const override;
344 : const OGRLayer *GetLayer(int) const override;
345 : OGRLayer *GetLayerByName(const char *) override;
346 :
347 : OGRLayer *ICreateLayer(const char *pszName,
348 : const OGRGeomFieldDefn *poGeomFieldDefn,
349 : CSLConstList papszOptions) override;
350 :
351 : OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
352 : const char *pszDialect) override;
353 :
354 : int TestCapability(const char *) const override;
355 : OGRErr DeleteLayer(int iLayer) override;
356 :
357 : char **GetFileList() override;
358 :
359 : void SetLastUsedLayer(OGRShapeLayer *poLayer);
360 : void UnchainLayer(OGRShapeLayer *poLayer);
361 :
362 : bool UncompressIfNeeded();
363 :
364 : SHPHandle DS_SHPOpen(const char *pszShapeFile, const char *pszAccess);
365 : DBFHandle DS_DBFOpen(const char *pszDBFFile, const char *pszAccess);
366 :
367 20808 : char **GetOpenOptions()
368 : {
369 20808 : return papszOpenOptions;
370 : }
371 :
372 : static const char *const *GetExtensionsForDeletion();
373 :
374 3480 : bool IsZip() const
375 : {
376 3480 : return m_bIsZip;
377 : }
378 :
379 6 : CPLString GetVSIZipPrefixeDir() const
380 : {
381 12 : return CPLString("/vsizip/{").append(GetDescription()).append("}");
382 : }
383 :
384 13 : const CPLString &GetTemporaryUnzipDir() const
385 : {
386 13 : return m_osTemporaryUnzipDir;
387 : }
388 :
389 : static bool CopyInPlace(VSILFILE *fpTarget,
390 : const CPLString &osSourceFilename);
391 : };
392 :
393 : #endif /* ndef OGRSHAPE_H_INCLUDED */
|