/src/gdal/ogr/ogrsf_frmts/flatgeobuf/ogr_flatgeobuf.h
Line | Count | Source |
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 | | |
36 | | class OGRFlatGeobufDataset; |
37 | | |
38 | | static constexpr uint8_t magicbytes[8] = {0x66, 0x67, 0x62, 0x03, |
39 | | 0x66, 0x67, 0x62, 0x01}; |
40 | | |
41 | | static constexpr uint32_t header_max_buffer_size = 1048576 * 10; |
42 | | |
43 | | // Cannot be larger than that, due to a x2 logic done in ensureFeatureBuf() |
44 | | static constexpr uint32_t feature_max_buffer_size = |
45 | | static_cast<uint32_t>(std::numeric_limits<int32_t>::max()); |
46 | | |
47 | | // holds feature meta needed to build spatial index |
48 | | struct FeatureItem : FlatGeobuf::Item |
49 | | { |
50 | | uint32_t size; |
51 | | uint64_t offset; |
52 | | }; |
53 | | |
54 | | class OGRFlatGeobufBaseLayerInterface CPL_NON_FINAL |
55 | | { |
56 | | public: |
57 | | virtual ~OGRFlatGeobufBaseLayerInterface(); |
58 | | |
59 | | virtual const std::string &GetFilename() const = 0; |
60 | | virtual OGRLayer *GetLayer() = 0; |
61 | | virtual CPLErr Close() = 0; |
62 | | }; |
63 | | |
64 | | class OGRFlatGeobufLayer final : public OGRLayer, |
65 | | public OGRFlatGeobufBaseLayerInterface |
66 | | { |
67 | | private: |
68 | | std::string m_osFilename; |
69 | | std::string m_osLayerName; |
70 | | |
71 | | VSILFILE *m_poFp = nullptr; |
72 | | vsi_l_offset m_nFileSize = 0; |
73 | | |
74 | | const FlatGeobuf::Header *m_poHeader = nullptr; |
75 | | GByte *m_headerBuf = nullptr; |
76 | | OGRwkbGeometryType m_eGType; |
77 | | FlatGeobuf::GeometryType m_geometryType; |
78 | | bool m_hasM = false; |
79 | | bool m_hasZ = false; |
80 | | bool m_hasT = false; |
81 | | bool m_hasTM = false; |
82 | | uint64_t m_featuresCount = 0; |
83 | | OGREnvelope m_sExtent; |
84 | | OGRFeatureDefn *m_poFeatureDefn = nullptr; |
85 | | OGRSpatialReference *m_poSRS = nullptr; |
86 | | |
87 | | // iteration |
88 | | bool m_bEOF = false; |
89 | | size_t m_featuresPos = 0; // current iteration position |
90 | | uint64_t m_offset = 0; // current read offset |
91 | | uint64_t m_offsetFeatures = 0; // offset of feature data |
92 | | std::vector<FlatGeobuf::SearchResultItem> |
93 | | m_foundItems; // found node items in spatial index search |
94 | | bool m_queriedSpatialIndex = false; |
95 | | bool m_ignoreSpatialFilter = false; |
96 | | bool m_ignoreAttributeFilter = false; |
97 | | |
98 | | // creation |
99 | | GDALDataset *m_poDS = nullptr; // parent dataset to get metadata from it |
100 | | bool m_create = false; |
101 | | std::deque<FeatureItem> m_featureItems; // feature item description used to |
102 | | // create spatial index |
103 | | bool m_bCreateSpatialIndexAtClose = true; |
104 | | bool m_bVerifyBuffers = true; |
105 | | VSILFILE *m_poFpWrite = nullptr; |
106 | | CPLStringList m_aosCreationOption{}; // layer creation options |
107 | | uint64_t m_writeOffset = 0; // current write offset |
108 | | uint64_t m_offsetAfterHeader = |
109 | | 0; // offset after dummy header writing (when creating a file without |
110 | | // spatial index) |
111 | | uint16_t m_indexNodeSize = 0; |
112 | | std::string |
113 | | m_osTempFile; // holds generated temp file name for two pass writing |
114 | | uint32_t m_maxFeatureSize = 0; |
115 | | std::vector<uint8_t> m_writeProperties{}; |
116 | | |
117 | | // shared |
118 | | GByte *m_featureBuf = nullptr; // reusable/resizable feature data buffer |
119 | | uint32_t m_featureBufSize = 0; // current feature buffer size |
120 | | |
121 | | // deserialize |
122 | | void ensurePadfBuffers(size_t count); |
123 | | OGRErr ensureFeatureBuf(uint32_t featureSize); |
124 | | OGRErr parseFeature(OGRFeature *poFeature); |
125 | | const std::vector<flatbuffers::Offset<FlatGeobuf::Column>> |
126 | | writeColumns(flatbuffers::FlatBufferBuilder &fbb); |
127 | | void readColumns(); |
128 | | OGRErr readIndex(); |
129 | | OGRErr readFeatureOffset(uint64_t index, uint64_t &featureOffset); |
130 | | |
131 | | // serialize |
132 | | bool CreateFinalFile(); |
133 | | void writeHeader(VSILFILE *poFp, uint64_t featuresCount, |
134 | | std::vector<double> *extentVector); |
135 | | |
136 | | // construction |
137 | | OGRFlatGeobufLayer(const FlatGeobuf::Header *, GByte *headerBuf, |
138 | | const char *pszFilename, VSILFILE *poFp, |
139 | | uint64_t offset); |
140 | | OGRFlatGeobufLayer(GDALDataset *poDS, const char *pszLayerName, |
141 | | const char *pszFilename, |
142 | | const OGRSpatialReference *poSpatialRef, |
143 | | OGRwkbGeometryType eGType, |
144 | | bool bCreateSpatialIndexAtClose, VSILFILE *poFpWrite, |
145 | | std::string &osTempFile, CSLConstList papszOptions); |
146 | | |
147 | | protected: |
148 | | virtual int GetNextArrowArray(struct ArrowArrayStream *, |
149 | | struct ArrowArray *out_array) override; |
150 | | |
151 | | CPLErr Close() override; |
152 | | |
153 | | public: |
154 | | ~OGRFlatGeobufLayer() override; |
155 | | |
156 | | static OGRFlatGeobufLayer *Open(const FlatGeobuf::Header *, |
157 | | GByte *headerBuf, const char *pszFilename, |
158 | | VSILFILE *poFp, uint64_t offset); |
159 | | static OGRFlatGeobufLayer *Open(const char *pszFilename, VSILFILE *fp, |
160 | | bool bVerifyBuffers); |
161 | | static OGRFlatGeobufLayer * |
162 | | Create(GDALDataset *poDS, const char *pszLayerName, const char *pszFilename, |
163 | | const OGRSpatialReference *poSpatialRef, OGRwkbGeometryType eGType, |
164 | | bool bCreateSpatialIndexAtClose, CSLConstList papszOptions); |
165 | | |
166 | | OGRFeature *GetFeature(GIntBig nFeatureId) override; |
167 | | OGRFeature *GetNextFeature() override; |
168 | | virtual OGRErr CreateField(const OGRFieldDefn *poField, |
169 | | int bApproxOK = true) override; |
170 | | OGRErr ICreateFeature(OGRFeature *poFeature) override; |
171 | | int TestCapability(const char *) const override; |
172 | | |
173 | | void ResetReading() override; |
174 | | |
175 | | const OGRFeatureDefn *GetLayerDefn() const override |
176 | 38.1k | { |
177 | 38.1k | return m_poFeatureDefn; |
178 | 38.1k | } |
179 | | |
180 | | GIntBig GetFeatureCount(int bForce) override; |
181 | | OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent, |
182 | | bool bForce) override; |
183 | | |
184 | | void VerifyBuffers(int bFlag) |
185 | 12.2k | { |
186 | 12.2k | m_bVerifyBuffers = CPL_TO_BOOL(bFlag); |
187 | 12.2k | } |
188 | | |
189 | | GDALDataset *GetDataset() override |
190 | 0 | { |
191 | 0 | return m_poDS; |
192 | 0 | } |
193 | | |
194 | | const std::string &GetFilename() const override |
195 | 0 | { |
196 | 0 | return m_osFilename; |
197 | 0 | } |
198 | | |
199 | | OGRLayer *GetLayer() override |
200 | 25.5k | { |
201 | 25.5k | return this; |
202 | 25.5k | } |
203 | | |
204 | | static std::string GetTempFilePath(const CPLString &fileName, |
205 | | CSLConstList papszOptions); |
206 | | static VSILFILE *CreateOutputFile(const CPLString &pszFilename, |
207 | | CSLConstList papszOptions, bool isTemp); |
208 | | |
209 | | uint16_t GetIndexNodeSize() const |
210 | 0 | { |
211 | 0 | return m_indexNodeSize; |
212 | 0 | } |
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 | | const std::string &GetFilename() const override |
227 | 0 | { |
228 | 0 | return static_cast<OGRFlatGeobufLayer *>(m_poDecoratedLayer) |
229 | 0 | ->GetFilename(); |
230 | 0 | } |
231 | | |
232 | | OGRLayer *GetLayer() override |
233 | 0 | { |
234 | 0 | return this; |
235 | 0 | } |
236 | | |
237 | | int TestCapability(const char *pszCap) const override; |
238 | | |
239 | | CPLErr Close() override |
240 | 0 | { |
241 | 0 | return CE_None; |
242 | 0 | } |
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() 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 | | char **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 | | int GetLayerCount() const override |
276 | 55.9k | { |
277 | 55.9k | return static_cast<int>(m_apoLayers.size()); |
278 | 55.9k | } |
279 | | |
280 | | char **GetFileList() override; |
281 | | }; |
282 | | |
283 | | #endif /* ndef OGR_FLATGEOBUF_H_INCLUDED */ |