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