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