Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: FlatGeobuf driver
4 : * Purpose: Declaration of classes for OGR FlatGeobuf driver.
5 : * Author: Björn Harrtell <bjorn at wololo dot org>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2018-2020, Björn Harrtell <bjorn at wololo dot org>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef OGR_FLATGEOBUF_H_INCLUDED
14 : #define OGR_FLATGEOBUF_H_INCLUDED
15 :
16 : #include "ogrsf_frmts.h"
17 : #include "ogr_p.h"
18 : #include "ogreditablelayer.h"
19 :
20 : #include "header_generated.h"
21 : #include "feature_generated.h"
22 : #include "packedrtree.h"
23 :
24 : #include <deque>
25 : #include <limits>
26 :
27 : class OGRFlatGeobufDataset;
28 :
29 : static constexpr uint8_t magicbytes[8] = {0x66, 0x67, 0x62, 0x03,
30 : 0x66, 0x67, 0x62, 0x01};
31 :
32 : static constexpr uint32_t header_max_buffer_size = 1048576 * 10;
33 :
34 : // Cannot be larger than that, due to a x2 logic done in ensureFeatureBuf()
35 : static constexpr uint32_t feature_max_buffer_size =
36 : static_cast<uint32_t>(std::numeric_limits<int32_t>::max());
37 :
38 : // holds feature meta needed to build spatial index
39 : struct FeatureItem : FlatGeobuf::Item
40 : {
41 : uint32_t size;
42 : uint64_t offset;
43 : };
44 :
45 316 : class OGRFlatGeobufBaseLayerInterface CPL_NON_FINAL
46 : {
47 : public:
48 : virtual ~OGRFlatGeobufBaseLayerInterface();
49 :
50 : virtual const std::string &GetFilename() const = 0;
51 : virtual OGRLayer *GetLayer() = 0;
52 : virtual CPLErr Close() = 0;
53 : };
54 :
55 : class OGRFlatGeobufLayer final : public OGRLayer,
56 : public OGRFlatGeobufBaseLayerInterface
57 : {
58 : private:
59 : std::string m_osFilename;
60 : std::string m_osLayerName;
61 :
62 : VSILFILE *m_poFp = nullptr;
63 : vsi_l_offset m_nFileSize = 0;
64 :
65 : const FlatGeobuf::Header *m_poHeader = nullptr;
66 : GByte *m_headerBuf = nullptr;
67 : OGRwkbGeometryType m_eGType;
68 : FlatGeobuf::GeometryType m_geometryType;
69 : bool m_hasM = false;
70 : bool m_hasZ = false;
71 : bool m_hasT = false;
72 : bool m_hasTM = false;
73 : uint64_t m_featuresCount = 0;
74 : OGREnvelope m_sExtent;
75 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
76 : OGRSpatialReference *m_poSRS = nullptr;
77 :
78 : // iteration
79 : bool m_bEOF = false;
80 : size_t m_featuresPos = 0; // current iteration position
81 : uint64_t m_offset = 0; // current read offset
82 : uint64_t m_offsetFeatures = 0; // offset of feature data
83 : std::vector<FlatGeobuf::SearchResultItem>
84 : m_foundItems; // found node items in spatial index search
85 : bool m_queriedSpatialIndex = false;
86 : bool m_ignoreSpatialFilter = false;
87 : bool m_ignoreAttributeFilter = false;
88 :
89 : // creation
90 : GDALDataset *m_poDS = nullptr; // parent dataset to get metadata from it
91 : bool m_create = false;
92 : std::deque<FeatureItem> m_featureItems; // feature item description used to
93 : // create spatial index
94 : bool m_bCreateSpatialIndexAtClose = true;
95 : bool m_bVerifyBuffers = true;
96 : VSILFILE *m_poFpWrite = nullptr;
97 : CPLStringList m_aosCreationOption{}; // layer creation options
98 : uint64_t m_writeOffset = 0; // current write offset
99 : uint64_t m_offsetAfterHeader =
100 : 0; // offset after dummy header writing (when creating a file without
101 : // spatial index)
102 : uint16_t m_indexNodeSize = 0;
103 : std::string
104 : m_osTempFile; // holds generated temp file name for two pass writing
105 : uint32_t m_maxFeatureSize = 0;
106 : std::vector<uint8_t> m_writeProperties{};
107 :
108 : // shared
109 : GByte *m_featureBuf = nullptr; // reusable/resizable feature data buffer
110 : uint32_t m_featureBufSize = 0; // current feature buffer size
111 :
112 : // deserialize
113 : void ensurePadfBuffers(size_t count);
114 : OGRErr ensureFeatureBuf(uint32_t featureSize);
115 : OGRErr parseFeature(OGRFeature *poFeature);
116 : const std::vector<flatbuffers::Offset<FlatGeobuf::Column>>
117 : writeColumns(flatbuffers::FlatBufferBuilder &fbb);
118 : void readColumns();
119 : OGRErr readIndex();
120 : OGRErr readFeatureOffset(uint64_t index, uint64_t &featureOffset);
121 :
122 : // serialize
123 : bool CreateFinalFile();
124 : void writeHeader(VSILFILE *poFp, uint64_t featuresCount,
125 : std::vector<double> *extentVector);
126 :
127 : // construction
128 : OGRFlatGeobufLayer(const FlatGeobuf::Header *, GByte *headerBuf,
129 : const char *pszFilename, VSILFILE *poFp,
130 : uint64_t offset);
131 : OGRFlatGeobufLayer(GDALDataset *poDS, const char *pszLayerName,
132 : const char *pszFilename,
133 : const OGRSpatialReference *poSpatialRef,
134 : OGRwkbGeometryType eGType,
135 : bool bCreateSpatialIndexAtClose, VSILFILE *poFpWrite,
136 : std::string &osTempFile, CSLConstList papszOptions);
137 :
138 : protected:
139 : virtual int GetNextArrowArray(struct ArrowArrayStream *,
140 : struct ArrowArray *out_array) override;
141 :
142 : CPLErr Close() override;
143 :
144 : public:
145 : virtual ~OGRFlatGeobufLayer();
146 :
147 : static OGRFlatGeobufLayer *Open(const FlatGeobuf::Header *,
148 : GByte *headerBuf, const char *pszFilename,
149 : VSILFILE *poFp, uint64_t offset);
150 : static OGRFlatGeobufLayer *Open(const char *pszFilename, VSILFILE *fp,
151 : bool bVerifyBuffers);
152 : static OGRFlatGeobufLayer *
153 : Create(GDALDataset *poDS, const char *pszLayerName, const char *pszFilename,
154 : const OGRSpatialReference *poSpatialRef, OGRwkbGeometryType eGType,
155 : bool bCreateSpatialIndexAtClose, CSLConstList papszOptions);
156 :
157 : virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
158 : virtual OGRFeature *GetNextFeature() override;
159 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
160 : int bApproxOK = true) override;
161 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
162 : virtual int TestCapability(const char *) override;
163 :
164 : virtual void ResetReading() override;
165 :
166 1483 : virtual OGRFeatureDefn *GetLayerDefn() override
167 : {
168 1483 : return m_poFeatureDefn;
169 : }
170 :
171 : virtual GIntBig GetFeatureCount(int bForce) override;
172 : virtual OGRErr GetExtent(OGREnvelope *psExtent, int bForce) override;
173 :
174 7 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
175 : int bForce) override
176 : {
177 7 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
178 : }
179 :
180 147 : void VerifyBuffers(int bFlag)
181 : {
182 147 : m_bVerifyBuffers = CPL_TO_BOOL(bFlag);
183 147 : }
184 :
185 37 : GDALDataset *GetDataset() override
186 : {
187 37 : return m_poDS;
188 : }
189 :
190 4 : const std::string &GetFilename() const override
191 : {
192 4 : return m_osFilename;
193 : }
194 :
195 728 : OGRLayer *GetLayer() override
196 : {
197 728 : return this;
198 : }
199 :
200 : static std::string GetTempFilePath(const CPLString &fileName,
201 : CSLConstList papszOptions);
202 : static VSILFILE *CreateOutputFile(const CPLString &pszFilename,
203 : CSLConstList papszOptions, bool isTemp);
204 :
205 1 : uint16_t GetIndexNodeSize() const
206 : {
207 1 : return m_indexNodeSize;
208 : }
209 :
210 : OGRwkbGeometryType getOGRwkbGeometryType();
211 : };
212 :
213 : class OGRFlatGeobufEditableLayer final : public OGREditableLayer,
214 : public OGRFlatGeobufBaseLayerInterface
215 : {
216 : public:
217 : OGRFlatGeobufEditableLayer(OGRFlatGeobufLayer *poFlatGeobufLayer,
218 : char **papszOpenOptions);
219 :
220 : virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
221 :
222 0 : const std::string &GetFilename() const override
223 : {
224 0 : return static_cast<OGRFlatGeobufLayer *>(m_poDecoratedLayer)
225 0 : ->GetFilename();
226 : }
227 :
228 2 : OGRLayer *GetLayer() override
229 : {
230 2 : return this;
231 : }
232 :
233 : int TestCapability(const char *pszCap) override;
234 :
235 1 : CPLErr Close() override
236 : {
237 1 : return CE_None;
238 : }
239 : };
240 :
241 : class OGRFlatGeobufDataset final : public GDALDataset
242 : {
243 : private:
244 : std::vector<std::unique_ptr<OGRFlatGeobufBaseLayerInterface>> m_apoLayers;
245 : bool m_bCreate = false;
246 : bool m_bUpdate = false;
247 : bool m_bIsDir = false;
248 :
249 : bool OpenFile(const char *pszFilename, VSILFILE *fp, bool bVerifyBuffers);
250 :
251 : CPLErr Close() override;
252 :
253 : public:
254 : OGRFlatGeobufDataset(const char *pszName, bool bIsDir, bool bCreate,
255 : bool bUpdate);
256 : ~OGRFlatGeobufDataset();
257 :
258 : static GDALDataset *Open(GDALOpenInfo *);
259 : static GDALDataset *Create(const char *pszName, CPL_UNUSED int nBands,
260 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
261 : CPL_UNUSED GDALDataType eDT,
262 : char **papszOptions);
263 : virtual OGRLayer *GetLayer(int) override;
264 : int TestCapability(const char *pszCap) override;
265 :
266 : OGRLayer *ICreateLayer(const char *pszName,
267 : const OGRGeomFieldDefn *poGeomFieldDefn,
268 : CSLConstList papszOptions) override;
269 :
270 1757 : virtual int GetLayerCount() override
271 : {
272 1757 : return static_cast<int>(m_apoLayers.size());
273 : }
274 :
275 : char **GetFileList() override;
276 : };
277 :
278 : #endif /* ndef OGR_FLATGEOBUF_H_INCLUDED */
|