Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Private definitions within the Shapefile driver to implement
6 : * integration with OGR.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1999, Les Technologies SoftMap Inc.
11 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
12 : *
13 : * SPDX-License-Identifier: MIT
14 : ****************************************************************************/
15 :
16 : #ifndef OGRSHAPE_H_INCLUDED
17 : #define OGRSHAPE_H_INCLUDED
18 :
19 : #ifdef RENAME_INTERNAL_SHAPELIB_SYMBOLS
20 : #include "gdal_shapelib_symbol_rename.h"
21 : #endif
22 :
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 *poFeatureDefn, OGRFeature *poFeature,
51 : 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 : char *pszFullName = nullptr;
63 : mutable bool bSRSSet = false;
64 : mutable CPLString osPrjFile{};
65 :
66 : public:
67 4679 : OGRShapeGeomFieldDefn(const char *pszFullNameIn, OGRwkbGeometryType eType,
68 : int bSRSSetIn, OGRSpatialReference *poSRSIn)
69 14037 : : OGRGeomFieldDefn("", eType), pszFullName(CPLStrdup(pszFullNameIn)),
70 4679 : bSRSSet(CPL_TO_BOOL(bSRSSetIn))
71 : {
72 4679 : SetSpatialRef(poSRSIn);
73 4679 : }
74 :
75 9350 : virtual ~OGRShapeGeomFieldDefn()
76 4675 : {
77 4675 : CPLFree(pszFullName);
78 9350 : }
79 :
80 : const OGRSpatialReference *GetSpatialRef() const override;
81 :
82 3 : void SetSRSSet()
83 : {
84 3 : bSRSSet = true;
85 3 : }
86 :
87 23 : const CPLString &GetPrjFilename() const
88 : {
89 23 : return osPrjFile;
90 : }
91 :
92 166 : void SetPrjFilename(const std::string &osFilename)
93 : {
94 166 : osPrjFile = osFilename;
95 166 : }
96 : };
97 :
98 : /************************************************************************/
99 : /* OGRShapeLayer */
100 : /************************************************************************/
101 :
102 : class OGRShapeDataSource;
103 :
104 : class OGRShapeLayer final : public OGRAbstractProxiedLayer
105 : {
106 : CPL_DISALLOW_COPY_ASSIGN(OGRShapeLayer)
107 :
108 : OGRShapeDataSource *poDS;
109 :
110 : OGRFeatureDefn *poFeatureDefn;
111 : int iNextShapeId;
112 : int nTotalShapeCount;
113 :
114 : char *pszFullName;
115 :
116 : SHPHandle hSHP;
117 : DBFHandle hDBF;
118 :
119 : bool bUpdateAccess;
120 :
121 : OGRwkbGeometryType eRequestedGeomType;
122 : int ResetGeomType(int nNewType);
123 :
124 : bool ScanIndices();
125 :
126 : GIntBig *panMatchingFIDs;
127 : int iMatchingFID;
128 : void ClearMatchingFIDs();
129 :
130 : OGRGeometry *m_poFilterGeomLastValid;
131 : int nSpatialFIDCount;
132 : int *panSpatialFIDs;
133 : void ClearSpatialFIDs();
134 :
135 : bool bHeaderDirty;
136 : bool bSHPNeedsRepack;
137 : bool bCheckedForQIX;
138 : SHPTreeDiskHandle hQIX;
139 : bool CheckForQIX();
140 :
141 : bool bCheckedForSBN;
142 : SBNSearchHandle hSBN;
143 : bool CheckForSBN();
144 :
145 : bool bSbnSbxDeleted;
146 :
147 : CPLString ConvertCodePage(const char *);
148 : CPLString osEncoding{};
149 :
150 : bool bTruncationWarningEmitted;
151 :
152 : bool bHSHPWasNonNULL; // Must try to reopen a .shp?
153 : bool bHDBFWasNonNULL; // Must try to reopen a .dbf
154 :
155 : // Current state of opening of file descriptor to .shp and .dbf.
156 :
157 : typedef enum
158 : {
159 : FD_OPENED,
160 : FD_CLOSED,
161 : FD_CANNOT_REOPEN
162 : } FileDescriptorState;
163 :
164 : FileDescriptorState eFileDescriptorsState;
165 :
166 : bool TouchLayer();
167 : bool ReopenFileDescriptors();
168 :
169 : bool bResizeAtClose;
170 :
171 : void TruncateDBF();
172 :
173 : bool bCreateSpatialIndexAtClose;
174 : bool bRewindOnWrite;
175 : bool m_bHasWarnedWrongWindingOrder = false;
176 : bool m_bLastGetNextArrowArrayUsedOptimizedCodePath = false;
177 :
178 : bool m_bAutoRepack;
179 :
180 : typedef enum
181 : {
182 : YES,
183 : NO,
184 : MAYBE
185 : } NormandyState; /* French joke. "Peut'et' ben que oui, peut'et' ben que
186 : non." Sorry :-) */
187 :
188 : NormandyState m_eNeedRepack;
189 :
190 : // Set of field names (in upper case). Built and invalidated when convenient
191 : std::set<CPLString> m_oSetUCFieldName{};
192 :
193 : bool StartUpdate(const char *pszOperation);
194 :
195 : void CloseUnderlyingLayer() override;
196 :
197 : // WARNING: Each of the below public methods should start with a call to
198 : // TouchLayer() and test its return value, so as to make sure that
199 : // the layer is properly re-opened if necessary.
200 :
201 : public:
202 : OGRErr CreateSpatialIndex(int nMaxDepth);
203 : OGRErr DropSpatialIndex();
204 : OGRErr Repack();
205 : OGRErr RecomputeExtent();
206 : OGRErr ResizeDBF();
207 :
208 1562 : void SetResizeAtClose(bool bFlag)
209 : {
210 1562 : bResizeAtClose = bFlag;
211 1562 : }
212 :
213 577 : const char *GetFullName()
214 : {
215 577 : return pszFullName;
216 : }
217 :
218 : void UpdateFollowingDeOrRecompression();
219 :
220 : OGRFeature *FetchShape(int iShapeId);
221 : int GetFeatureCountWithSpatialFilterOnly();
222 :
223 : OGRShapeLayer(OGRShapeDataSource *poDSIn, const char *pszName,
224 : SHPHandle hSHP, DBFHandle hDBF,
225 : const OGRSpatialReference *poSRS, bool bSRSSet,
226 : const std::string &osPrjFilename, bool bUpdate,
227 : OGRwkbGeometryType eReqType,
228 : char **papszCreateOptions = nullptr);
229 : virtual ~OGRShapeLayer();
230 :
231 : GDALDataset *GetDataset() override;
232 :
233 : void ResetReading() override;
234 : OGRFeature *GetNextFeature() override;
235 : OGRErr SetNextByIndex(GIntBig nIndex) override;
236 :
237 : int GetNextArrowArray(struct ArrowArrayStream *,
238 : struct ArrowArray *out_array) override;
239 : const char *GetMetadataItem(const char *pszName,
240 : const char *pszDomain) override;
241 :
242 : OGRFeature *GetFeature(GIntBig nFeatureId) override;
243 : OGRErr ISetFeature(OGRFeature *poFeature) override;
244 : OGRErr DeleteFeature(GIntBig nFID) override;
245 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
246 : OGRErr SyncToDisk() override;
247 :
248 1380420 : OGRFeatureDefn *GetLayerDefn() override
249 : {
250 1380420 : return poFeatureDefn;
251 : }
252 :
253 : GIntBig GetFeatureCount(int) override;
254 : OGRErr GetExtent(OGREnvelope *psExtent, int bForce) override;
255 :
256 93 : OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
257 : {
258 93 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
259 : }
260 :
261 : OGRErr GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
262 : int bForce) override;
263 :
264 : OGRErr CreateField(const OGRFieldDefn *poField,
265 : int bApproxOK = TRUE) override;
266 : OGRErr DeleteField(int iField) override;
267 : OGRErr ReorderFields(int *panMap) override;
268 : OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
269 : int nFlags) override;
270 : OGRErr AlterGeomFieldDefn(int iGeomField,
271 : const OGRGeomFieldDefn *poNewGeomFieldDefn,
272 : int nFlagsIn) override;
273 :
274 : int TestCapability(const char *) override;
275 : void SetSpatialFilter(OGRGeometry *) override;
276 :
277 1462 : void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override
278 : {
279 1462 : OGRLayer::SetSpatialFilter(iGeomField, poGeom);
280 1462 : }
281 :
282 : OGRErr SetAttributeFilter(const char *) override;
283 :
284 : OGRErr Rename(const char *pszNewName) override;
285 :
286 : void AddToFileList(CPLStringList &oFileList);
287 :
288 1562 : void CreateSpatialIndexAtClose(int bFlag)
289 : {
290 1562 : bCreateSpatialIndexAtClose = CPL_TO_BOOL(bFlag);
291 1562 : }
292 :
293 : void SetModificationDate(const char *pszStr);
294 :
295 5046 : void SetAutoRepack(bool b)
296 : {
297 5046 : m_bAutoRepack = b;
298 5046 : }
299 :
300 : void SetWriteDBFEOFChar(bool b);
301 : };
302 :
303 : /************************************************************************/
304 : /* OGRShapeDataSource */
305 : /************************************************************************/
306 :
307 : class OGRShapeDataSource final : public GDALDataset
308 : {
309 : OGRShapeLayer **papoLayers;
310 : int nLayers;
311 : bool bSingleFileDataSource;
312 : OGRLayerPool *poPool;
313 :
314 : std::vector<CPLString> oVectorLayerName{};
315 :
316 : bool b2GBLimit;
317 : bool m_bIsZip = false;
318 : bool m_bSingleLayerZip = false;
319 : CPLString m_osTemporaryUnzipDir{};
320 : CPLMutex *m_poRefreshLockFileMutex = nullptr;
321 : CPLCond *m_poRefreshLockFileCond = nullptr;
322 : VSILFILE *m_psLockFile = nullptr;
323 : CPLJoinableThread *m_hRefreshLockFileThread = nullptr;
324 : bool m_bExitRefreshLockFileThread = false;
325 : bool m_bRefreshLockFileThreadStarted = false;
326 : double m_dfRefreshLockDelay = 0;
327 :
328 : std::vector<CPLString> GetLayerNames() const;
329 : void AddLayer(OGRShapeLayer *poLayer);
330 : static void RefreshLockFile(void *_self);
331 : void RemoveLockFile();
332 : bool RecompressIfNeeded(const std::vector<CPLString> &layerNames);
333 :
334 : CPL_DISALLOW_COPY_ASSIGN(OGRShapeDataSource)
335 :
336 : public:
337 : OGRShapeDataSource();
338 : virtual ~OGRShapeDataSource();
339 :
340 5046 : OGRLayerPool *GetPool() const
341 : {
342 5046 : return poPool;
343 : }
344 :
345 : bool Open(GDALOpenInfo *poOpenInfo, bool bTestOpen,
346 : bool bForceSingleFileDataSource = false);
347 : bool OpenFile(const char *, bool bUpdate);
348 : bool OpenZip(GDALOpenInfo *poOpenInfo, const char *pszOriFilename);
349 : bool CreateZip(const char *pszOriFilename);
350 :
351 : int GetLayerCount() override;
352 : OGRLayer *GetLayer(int) override;
353 : OGRLayer *GetLayerByName(const char *) override;
354 :
355 : OGRLayer *ICreateLayer(const char *pszName,
356 : const OGRGeomFieldDefn *poGeomFieldDefn,
357 : CSLConstList papszOptions) override;
358 :
359 : OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
360 : const char *pszDialect) override;
361 :
362 : int TestCapability(const char *) override;
363 : OGRErr DeleteLayer(int iLayer) override;
364 :
365 : char **GetFileList() override;
366 :
367 : void SetLastUsedLayer(OGRShapeLayer *poLayer);
368 : void UnchainLayer(OGRShapeLayer *poLayer);
369 :
370 : bool UncompressIfNeeded();
371 :
372 : SHPHandle DS_SHPOpen(const char *pszShapeFile, const char *pszAccess);
373 : DBFHandle DS_DBFOpen(const char *pszDBFFile, const char *pszAccess);
374 :
375 13253 : char **GetOpenOptions()
376 : {
377 13253 : return papszOpenOptions;
378 : }
379 :
380 : static const char *const *GetExtensionsForDeletion();
381 :
382 1643 : bool IsZip() const
383 : {
384 1643 : return m_bIsZip;
385 : }
386 :
387 5 : CPLString GetVSIZipPrefixeDir() const
388 : {
389 10 : return CPLString("/vsizip/{").append(GetDescription()).append("}");
390 : }
391 :
392 11 : const CPLString &GetTemporaryUnzipDir() const
393 : {
394 11 : return m_osTemporaryUnzipDir;
395 : }
396 :
397 : static bool CopyInPlace(VSILFILE *fpTarget,
398 : const CPLString &osSourceFilename);
399 : };
400 :
401 : #endif /* ndef OGRSHAPE_H_INCLUDED */
|