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 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #ifndef OGRSHAPE_H_INCLUDED
33 : #define OGRSHAPE_H_INCLUDED
34 :
35 : #ifdef RENAME_INTERNAL_SHAPELIB_SYMBOLS
36 : #include "gdal_shapelib_symbol_rename.h"
37 : #endif
38 :
39 : #include "ogrsf_frmts.h"
40 : #include "shapefil.h"
41 : #include "shp_vsi.h"
42 : #include "ogrlayerpool.h"
43 : #include <set>
44 : #include <vector>
45 :
46 : /* Was limited to 255 until OGR 1.10, but 254 seems to be a more */
47 : /* conventional limit (http://en.wikipedia.org/wiki/Shapefile, */
48 : /* http://www.clicketyclick.dk/databases/xbase/format/data_types.html, */
49 : /* #5052 ) */
50 : #define OGR_DBF_MAX_FIELD_WIDTH 254
51 :
52 : /* ==================================================================== */
53 : /* Functions from Shape2ogr.cpp. */
54 : /* ==================================================================== */
55 : OGRFeature *SHPReadOGRFeature(SHPHandle hSHP, DBFHandle hDBF,
56 : OGRFeatureDefn *poDefn, int iShape,
57 : SHPObject *psShape, const char *pszSHPEncoding,
58 : bool &bHasWarnedWrongWindingOrder);
59 : OGRGeometry *SHPReadOGRObject(SHPHandle hSHP, int iShape, SHPObject *psShape,
60 : bool &bHasWarnedWrongWindingOrder);
61 : OGRFeatureDefn *SHPReadOGRFeatureDefn(const char *pszName, SHPHandle hSHP,
62 : DBFHandle hDBF,
63 : const char *pszSHPEncoding,
64 : int bAdjustType);
65 : OGRErr SHPWriteOGRFeature(SHPHandle hSHP, DBFHandle hDBF,
66 : OGRFeatureDefn *poFeatureDefn, OGRFeature *poFeature,
67 : const char *pszSHPEncoding,
68 : bool *pbTruncationWarningEmitted, bool bRewind);
69 :
70 : /************************************************************************/
71 : /* OGRShapeGeomFieldDefn */
72 : /************************************************************************/
73 :
74 : class OGRShapeGeomFieldDefn final : public OGRGeomFieldDefn
75 : {
76 : CPL_DISALLOW_COPY_ASSIGN(OGRShapeGeomFieldDefn)
77 :
78 : char *pszFullName = nullptr;
79 : mutable bool bSRSSet = false;
80 : mutable CPLString osPrjFile{};
81 :
82 : public:
83 4644 : OGRShapeGeomFieldDefn(const char *pszFullNameIn, OGRwkbGeometryType eType,
84 : int bSRSSetIn, OGRSpatialReference *poSRSIn)
85 13932 : : OGRGeomFieldDefn("", eType), pszFullName(CPLStrdup(pszFullNameIn)),
86 4644 : bSRSSet(CPL_TO_BOOL(bSRSSetIn))
87 : {
88 4644 : SetSpatialRef(poSRSIn);
89 4644 : }
90 :
91 9256 : virtual ~OGRShapeGeomFieldDefn()
92 4628 : {
93 4628 : CPLFree(pszFullName);
94 9256 : }
95 :
96 : const OGRSpatialReference *GetSpatialRef() const override;
97 :
98 3 : void SetSRSSet()
99 : {
100 3 : bSRSSet = true;
101 3 : }
102 :
103 23 : const CPLString &GetPrjFilename() const
104 : {
105 23 : return osPrjFile;
106 : }
107 :
108 159 : void SetPrjFilename(const std::string &osFilename)
109 : {
110 159 : osPrjFile = osFilename;
111 159 : }
112 : };
113 :
114 : /************************************************************************/
115 : /* OGRShapeLayer */
116 : /************************************************************************/
117 :
118 : class OGRShapeDataSource;
119 :
120 : class OGRShapeLayer final : public OGRAbstractProxiedLayer
121 : {
122 : CPL_DISALLOW_COPY_ASSIGN(OGRShapeLayer)
123 :
124 : OGRShapeDataSource *poDS;
125 :
126 : OGRFeatureDefn *poFeatureDefn;
127 : int iNextShapeId;
128 : int nTotalShapeCount;
129 :
130 : char *pszFullName;
131 :
132 : SHPHandle hSHP;
133 : DBFHandle hDBF;
134 :
135 : bool bUpdateAccess;
136 :
137 : OGRwkbGeometryType eRequestedGeomType;
138 : int ResetGeomType(int nNewType);
139 :
140 : bool ScanIndices();
141 :
142 : GIntBig *panMatchingFIDs;
143 : int iMatchingFID;
144 : void ClearMatchingFIDs();
145 :
146 : OGRGeometry *m_poFilterGeomLastValid;
147 : int nSpatialFIDCount;
148 : int *panSpatialFIDs;
149 : void ClearSpatialFIDs();
150 :
151 : bool bHeaderDirty;
152 : bool bSHPNeedsRepack;
153 : bool bCheckedForQIX;
154 : SHPTreeDiskHandle hQIX;
155 : bool CheckForQIX();
156 :
157 : bool bCheckedForSBN;
158 : SBNSearchHandle hSBN;
159 : bool CheckForSBN();
160 :
161 : bool bSbnSbxDeleted;
162 :
163 : CPLString ConvertCodePage(const char *);
164 : CPLString osEncoding{};
165 :
166 : bool bTruncationWarningEmitted;
167 :
168 : bool bHSHPWasNonNULL; // Must try to reopen a .shp?
169 : bool bHDBFWasNonNULL; // Must try to reopen a .dbf
170 :
171 : // Current state of opening of file descriptor to .shp and .dbf.
172 :
173 : typedef enum
174 : {
175 : FD_OPENED,
176 : FD_CLOSED,
177 : FD_CANNOT_REOPEN
178 : } FileDescriptorState;
179 :
180 : FileDescriptorState eFileDescriptorsState;
181 :
182 : bool TouchLayer();
183 : bool ReopenFileDescriptors();
184 :
185 : bool bResizeAtClose;
186 :
187 : void TruncateDBF();
188 :
189 : bool bCreateSpatialIndexAtClose;
190 : bool bRewindOnWrite;
191 : bool m_bHasWarnedWrongWindingOrder = false;
192 : bool m_bLastGetNextArrowArrayUsedOptimizedCodePath = false;
193 :
194 : bool m_bAutoRepack;
195 :
196 : typedef enum
197 : {
198 : YES,
199 : NO,
200 : MAYBE
201 : } NormandyState; /* French joke. "Peut'et' ben que oui, peut'et' ben que
202 : non." Sorry :-) */
203 :
204 : NormandyState m_eNeedRepack;
205 :
206 : // Set of field names (in upper case). Built and invalidated when convenient
207 : std::set<CPLString> m_oSetUCFieldName{};
208 :
209 : bool StartUpdate(const char *pszOperation);
210 :
211 : void CloseUnderlyingLayer() override;
212 :
213 : // WARNING: Each of the below public methods should start with a call to
214 : // TouchLayer() and test its return value, so as to make sure that
215 : // the layer is properly re-opened if necessary.
216 :
217 : public:
218 : OGRErr CreateSpatialIndex(int nMaxDepth);
219 : OGRErr DropSpatialIndex();
220 : OGRErr Repack();
221 : OGRErr RecomputeExtent();
222 : OGRErr ResizeDBF();
223 :
224 1558 : void SetResizeAtClose(bool bFlag)
225 : {
226 1558 : bResizeAtClose = bFlag;
227 1558 : }
228 :
229 576 : const char *GetFullName()
230 : {
231 576 : return pszFullName;
232 : }
233 :
234 : void UpdateFollowingDeOrRecompression();
235 :
236 : OGRFeature *FetchShape(int iShapeId);
237 : int GetFeatureCountWithSpatialFilterOnly();
238 :
239 : OGRShapeLayer(OGRShapeDataSource *poDSIn, const char *pszName,
240 : SHPHandle hSHP, DBFHandle hDBF,
241 : const OGRSpatialReference *poSRS, bool bSRSSet,
242 : const std::string &osPrjFilename, bool bUpdate,
243 : OGRwkbGeometryType eReqType,
244 : char **papszCreateOptions = nullptr);
245 : virtual ~OGRShapeLayer();
246 :
247 : GDALDataset *GetDataset() override;
248 :
249 : void ResetReading() override;
250 : OGRFeature *GetNextFeature() override;
251 : OGRErr SetNextByIndex(GIntBig nIndex) override;
252 :
253 : int GetNextArrowArray(struct ArrowArrayStream *,
254 : struct ArrowArray *out_array) override;
255 : const char *GetMetadataItem(const char *pszName,
256 : const char *pszDomain) override;
257 :
258 : OGRFeature *GetFeature(GIntBig nFeatureId) override;
259 : OGRErr ISetFeature(OGRFeature *poFeature) override;
260 : OGRErr DeleteFeature(GIntBig nFID) override;
261 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
262 : OGRErr SyncToDisk() override;
263 :
264 1413480 : OGRFeatureDefn *GetLayerDefn() override
265 : {
266 1413480 : return poFeatureDefn;
267 : }
268 :
269 : GIntBig GetFeatureCount(int) override;
270 : OGRErr GetExtent(OGREnvelope *psExtent, int bForce) override;
271 :
272 92 : OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
273 : {
274 92 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
275 : }
276 :
277 : OGRErr GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
278 : int bForce) override;
279 :
280 : OGRErr CreateField(const OGRFieldDefn *poField,
281 : int bApproxOK = TRUE) override;
282 : OGRErr DeleteField(int iField) override;
283 : OGRErr ReorderFields(int *panMap) override;
284 : OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
285 : int nFlags) override;
286 : OGRErr AlterGeomFieldDefn(int iGeomField,
287 : const OGRGeomFieldDefn *poNewGeomFieldDefn,
288 : int nFlagsIn) override;
289 :
290 : int TestCapability(const char *) override;
291 : void SetSpatialFilter(OGRGeometry *) override;
292 :
293 1443 : void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override
294 : {
295 1443 : OGRLayer::SetSpatialFilter(iGeomField, poGeom);
296 1443 : }
297 :
298 : OGRErr SetAttributeFilter(const char *) override;
299 :
300 : OGRErr Rename(const char *pszNewName) override;
301 :
302 : void AddToFileList(CPLStringList &oFileList);
303 :
304 1558 : void CreateSpatialIndexAtClose(int bFlag)
305 : {
306 1558 : bCreateSpatialIndexAtClose = CPL_TO_BOOL(bFlag);
307 1558 : }
308 :
309 : void SetModificationDate(const char *pszStr);
310 :
311 5010 : void SetAutoRepack(bool b)
312 : {
313 5010 : m_bAutoRepack = b;
314 5010 : }
315 :
316 : void SetWriteDBFEOFChar(bool b);
317 : };
318 :
319 : /************************************************************************/
320 : /* OGRShapeDataSource */
321 : /************************************************************************/
322 :
323 : class OGRShapeDataSource final : public OGRDataSource
324 : {
325 : OGRShapeLayer **papoLayers;
326 : int nLayers;
327 : char *pszName;
328 : bool bSingleFileDataSource;
329 : OGRLayerPool *poPool;
330 :
331 : std::vector<CPLString> oVectorLayerName{};
332 :
333 : bool b2GBLimit;
334 : bool m_bIsZip = false;
335 : bool m_bSingleLayerZip = false;
336 : CPLString m_osTemporaryUnzipDir{};
337 : CPLMutex *m_poRefreshLockFileMutex = nullptr;
338 : CPLCond *m_poRefreshLockFileCond = nullptr;
339 : VSILFILE *m_psLockFile = nullptr;
340 : CPLJoinableThread *m_hRefreshLockFileThread = nullptr;
341 : bool m_bExitRefreshLockFileThread = false;
342 : double m_dfRefreshLockDelay = 0;
343 :
344 : std::vector<CPLString> GetLayerNames() const;
345 : void AddLayer(OGRShapeLayer *poLayer);
346 : static void RefreshLockFile(void *_self);
347 : void RemoveLockFile();
348 : bool RecompressIfNeeded(const std::vector<CPLString> &layerNames);
349 :
350 : CPL_DISALLOW_COPY_ASSIGN(OGRShapeDataSource)
351 :
352 : public:
353 : OGRShapeDataSource();
354 : virtual ~OGRShapeDataSource();
355 :
356 5010 : OGRLayerPool *GetPool() const
357 : {
358 5010 : return poPool;
359 : }
360 :
361 : bool Open(GDALOpenInfo *poOpenInfo, bool bTestOpen,
362 : bool bForceSingleFileDataSource = false);
363 : bool OpenFile(const char *, bool bUpdate);
364 : bool OpenZip(GDALOpenInfo *poOpenInfo, const char *pszOriFilename);
365 : bool CreateZip(const char *pszOriFilename);
366 :
367 0 : const char *GetName() override
368 : {
369 0 : return pszName;
370 : }
371 :
372 : int GetLayerCount() override;
373 : OGRLayer *GetLayer(int) override;
374 : OGRLayer *GetLayerByName(const char *) override;
375 :
376 : OGRLayer *ICreateLayer(const char *pszName,
377 : const OGRGeomFieldDefn *poGeomFieldDefn,
378 : CSLConstList papszOptions) override;
379 :
380 : OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
381 : const char *pszDialect) override;
382 :
383 : int TestCapability(const char *) override;
384 : OGRErr DeleteLayer(int iLayer) override;
385 :
386 : char **GetFileList() override;
387 :
388 : void SetLastUsedLayer(OGRShapeLayer *poLayer);
389 : void UnchainLayer(OGRShapeLayer *poLayer);
390 :
391 : bool UncompressIfNeeded();
392 :
393 : SHPHandle DS_SHPOpen(const char *pszShapeFile, const char *pszAccess);
394 : DBFHandle DS_DBFOpen(const char *pszDBFFile, const char *pszAccess);
395 :
396 13150 : char **GetOpenOptions()
397 : {
398 13150 : return papszOpenOptions;
399 : }
400 :
401 : static const char *const *GetExtensionsForDeletion();
402 :
403 1644 : bool IsZip() const
404 : {
405 1644 : return m_bIsZip;
406 : }
407 :
408 5 : CPLString GetVSIZipPrefixeDir() const
409 : {
410 10 : return CPLString("/vsizip/{") + pszName + '}';
411 : }
412 :
413 11 : const CPLString &GetTemporaryUnzipDir() const
414 : {
415 11 : return m_osTemporaryUnzipDir;
416 : }
417 :
418 : static bool CopyInPlace(VSILFILE *fpTarget,
419 : const CPLString &osSourceFilename);
420 : };
421 :
422 : #endif /* ndef OGRSHAPE_H_INCLUDED */
|