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