Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: S-101 driver
4 : * Purpose: Header file
5 : * Author: Even Rouault <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2026, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef OGR_S101_H_INCLUDED
14 : #define OGR_S101_H_INCLUDED
15 :
16 : #include "ogrsf_frmts.h"
17 : #include "iso8211.h"
18 : #include "ddfrecordindex.h"
19 :
20 : #include "cpl_int_wrapper.h"
21 : #include "cpl_string.h"
22 :
23 : #include <map>
24 : #include <set>
25 : #include <string_view>
26 :
27 : /************************************************************************/
28 : /* OGRS101Reader */
29 : /************************************************************************/
30 :
31 : class OGRS101FeatureCatalog;
32 :
33 : namespace OGRS101FeatureCatalogTypes
34 : {
35 : struct InformationType;
36 : struct FeatureType;
37 : } // namespace OGRS101FeatureCatalogTypes
38 :
39 1002 : class OGRS101Reader
40 : {
41 : public:
42 : struct CRSIdTag
43 : {
44 : };
45 :
46 : using CRSId = cpl::IntWrapper<CRSIdTag>;
47 :
48 : static constexpr CRSId INVALID_CRS_ID{-1};
49 : static constexpr CRSId HORIZONTAL_CRS_ID{1};
50 :
51 : struct RecordNameTag
52 : {
53 : };
54 :
55 : // Record "name" is a poor naming from the S100 spec. It is actually
56 : // a numeric value
57 : using RecordName = cpl::IntWrapper<RecordNameTag>;
58 :
59 : // Type for NATC subfield (numeric attribute code)
60 : struct AttrCodeTag
61 : {
62 : };
63 :
64 : using AttrCode = cpl::IntWrapper<AttrCodeTag>;
65 :
66 : // Type for PAIX subfield (parent index)
67 : struct AttrIndexTag
68 : {
69 : };
70 :
71 : using AttrIndex = cpl::IntWrapper<AttrIndexTag>;
72 :
73 : // Type for ATIX subfield (attribute index)
74 : struct AttrRepeatTag
75 : {
76 : };
77 :
78 : using AttrRepeat = cpl::IntWrapper<AttrRepeatTag>;
79 :
80 474 : inline static void AppendUInt8(std::string &s, uint8_t x)
81 : {
82 474 : s.append(reinterpret_cast<const char *>(&x), sizeof(x));
83 474 : }
84 :
85 321 : inline static void AppendUInt16(std::string &s, uint16_t x)
86 : {
87 321 : CPL_LSBPTR16(&x);
88 321 : s.append(reinterpret_cast<const char *>(&x), sizeof(x));
89 321 : }
90 :
91 192 : inline static void AppendInt32(std::string &s, int32_t x)
92 : {
93 192 : CPL_LSBPTR32(&x);
94 192 : s.append(reinterpret_cast<const char *>(&x), sizeof(x));
95 192 : }
96 :
97 : private:
98 : /////////////////////////////////////////////////////////////////////////
99 : // Members
100 : /////////////////////////////////////////////////////////////////////////
101 :
102 : bool m_bStrict = true;
103 :
104 : //! Whereas we are currently processing an update file (.001, .002, ...)
105 : bool m_bInUpdate = false;
106 :
107 : //! Whether an update file cancels the dataset.
108 : bool m_bCancelled = false;
109 :
110 : std::string m_osFilename{};
111 : DDFModule m_oMainModule{};
112 :
113 : CPLStringList m_aosMetadata{};
114 :
115 : // DSSI field
116 : static constexpr double S101_SHIFT = 0;
117 : double m_dfXShift = S101_SHIFT; // DCOX
118 : double m_dfYShift = S101_SHIFT; // DCOY
119 : double m_dfZShift = S101_SHIFT; // DCOZ
120 : static constexpr int S101_XSCALE = 10000000;
121 : int m_nXScale = S101_XSCALE; // CMFX
122 : static constexpr int S101_YSCALE = 10000000;
123 : int m_nYScale = S101_YSCALE; // CMFY
124 : static constexpr int S101_ZSCALE = 10;
125 : int m_nZScale = S101_ZSCALE; // CMFZ
126 : OGRGeomCoordinatePrecision m_coordinatePrecision{};
127 : int m_nCountInformationRecord = 0; // NOIR
128 : int m_nCountPointRecord = 0; // NOPN
129 : int m_nCountMultiPointRecord = 0; // NOMN
130 : int m_nCountCurveRecord = 0; // NOCN
131 : int m_nCountCompositeCurveRecord = 0; // NOXN
132 : int m_nCountSurfaceRecord = 0; // NOSN
133 : int m_nCountFeatureTypeRecord = 0; // NOFR
134 :
135 : // from ATCS field
136 : std::map<AttrCode, std::string> m_attributeCodes{};
137 :
138 : // Maps the AttrCode of the current update to the consolidated one of
139 : // m_attributeCodes
140 : std::map<AttrCode, AttrCode> m_attributeCodesRemapping{};
141 :
142 : struct InfoTypeCodeTag
143 : {
144 : };
145 :
146 : using InfoTypeCode = cpl::IntWrapper<InfoTypeCodeTag>;
147 : // from ITCS field
148 : std::map<InfoTypeCode, std::string> m_informationTypeCodes{};
149 :
150 : // Maps the AttrCode of the current update to the consolidated one of
151 : // m_informationTypeCodes
152 : std::map<InfoTypeCode, InfoTypeCode> m_informationTypeCodesRemapping{};
153 :
154 : struct FeatureTypeCodeTag
155 : {
156 : };
157 :
158 : using FeatureTypeCode = cpl::IntWrapper<FeatureTypeCodeTag>;
159 : // from FTCS field
160 : std::map<FeatureTypeCode, std::string> m_featureTypeCodes{};
161 :
162 : // Maps the AttrCode of the current update to the consolidated one of
163 : // m_featureTypeCodes
164 : std::map<FeatureTypeCode, FeatureTypeCode> m_featureTypeCodesRemapping{};
165 :
166 : struct InfoAssocCodeTag
167 : {
168 : };
169 :
170 : using InfoAssocCode = cpl::IntWrapper<InfoAssocCodeTag>;
171 : // from IACS field
172 : std::map<InfoAssocCode, std::string> m_informationAssociationCodes{};
173 :
174 : // Maps the AttrCode of the current update to the consolidated one of
175 : // m_informationAssociationCodes
176 : std::map<InfoAssocCode, InfoAssocCode>
177 : m_informationAssociationCodesRemapping{};
178 :
179 : struct FeatureAssocCodeTag
180 : {
181 : };
182 :
183 : using FeatureAssocCode = cpl::IntWrapper<FeatureAssocCodeTag>;
184 : // from FACS field
185 : std::map<FeatureAssocCode, std::string> m_featureAssociationCodes{};
186 :
187 : // Maps the AttrCode of the current update to the consolidated one of
188 : // m_featureAssociationCodes
189 : std::map<FeatureAssocCode, FeatureAssocCode>
190 : m_featureAssociationCodesRemapping{};
191 :
192 : struct AssocRoleCodeTag
193 : {
194 : };
195 :
196 : using AssocRoleCode = cpl::IntWrapper<AssocRoleCodeTag>;
197 : // from ARCS field
198 : std::map<AssocRoleCode, std::string> m_associationRoleCodes{};
199 :
200 : // Maps the AttrCode of the current update to the consolidated one of
201 : // m_featureAssociationCodes
202 : std::map<AssocRoleCode, AssocRoleCode> m_associationRoleCodesRemapping{};
203 :
204 : static constexpr RecordName PSEUDO_RECORD_NAME_NO_GEOM{-1111111111};
205 :
206 : /** Triple (feature type code, geometry type, CRS Id) */
207 : struct FeatureTypeKey
208 : {
209 : FeatureTypeCode nFeatureTypeCode{0};
210 : RecordName nGeometryType{PSEUDO_RECORD_NAME_NO_GEOM};
211 : CRSId nCRSId{INVALID_CRS_ID};
212 :
213 : // I'd wish I could use C++20
214 2946 : inline bool operator<(const FeatureTypeKey &other) const
215 : {
216 2946 : return toTuple() < other.toTuple();
217 : }
218 :
219 : private:
220 5892 : inline std::tuple<int, int, int> toTuple() const
221 : {
222 0 : return std::make_tuple(static_cast<int>(nFeatureTypeCode),
223 5892 : static_cast<int>(nGeometryType),
224 17676 : static_cast<int>(nCRSId));
225 : }
226 : };
227 :
228 : // key is the crs index (CRIX). 1: Horizontal CRS. >= 2: CompoundCRS
229 : std::map<CRSId, OGRSpatialReference> m_oMapSRS{};
230 :
231 : DDFRecordIndex m_oInformationTypeRecordIndex{};
232 : DDFRecordIndex m_oPointRecordIndex{};
233 : DDFRecordIndex m_oMultiPointRecordIndex{};
234 : DDFRecordIndex m_oCurveRecordIndex{};
235 : DDFRecordIndex m_oCompositeCurveRecordIndex{};
236 : DDFRecordIndex m_oSurfaceRecordIndex{};
237 : DDFRecordIndex m_oFeatureTypeRecordIndex{};
238 :
239 : OGRFeatureDefnRefCountedPtr m_poFeatureDefnInformationType{};
240 :
241 : std::map<CRSId, OGRFeatureDefnRefCountedPtr> m_oMapPointFeatureDefn{};
242 : std::map<CRSId, std::vector<int>> m_oMapCRSIdToPointRecordIdx{};
243 :
244 : std::map<CRSId, OGRFeatureDefnRefCountedPtr> m_oMapMultiPointFeatureDefn{};
245 : std::map<CRSId, std::vector<int>> m_oMapCRSIdToMultiPointRecordIdx{};
246 :
247 : OGRFeatureDefnRefCountedPtr m_poFeatureDefnCurve{};
248 : OGRFeatureDefnRefCountedPtr m_poFeatureDefnCompositeCurve{};
249 : OGRFeatureDefnRefCountedPtr m_poFeatureDefnSurface{};
250 :
251 : struct LayerDef
252 : {
253 : OGRFeatureDefnRefCountedPtr poFeatureDefn{};
254 : std::string osName{};
255 : std::string osDefinition{};
256 : std::string osAlias{};
257 : std::vector<int> anRecordIndices{};
258 : };
259 :
260 : std::map<FeatureTypeKey, LayerDef> m_oMapFeatureKeyToLayerDef{};
261 : std::map<int, const OGRFeatureDefn *> m_oMapFeatureTypeIdToFDefn{};
262 :
263 : std::map<std::string, std::unique_ptr<OGRFieldDomain>> m_oMapFieldDomains{};
264 :
265 : const OGRS101FeatureCatalog *m_poFeatureCatalog = nullptr;
266 :
267 : /////////////////////////////////////////////////////////////////////////
268 : // Methods
269 : /////////////////////////////////////////////////////////////////////////
270 :
271 : bool Load(const std::string &osFilename, VSILFILE *fp,
272 : DDFModule *poCurModule);
273 :
274 : bool CheckFieldDefinitions(const DDFModule *poCurModule) const;
275 : bool CheckField0000Definition(const DDFModule *poCurModule) const;
276 :
277 : bool ReadDatasetGeneralInformationRecord(const DDFRecord *poRecord);
278 : bool ReadDSID(const DDFRecord *poRecord);
279 : bool ReadDSSI(const DDFRecord *poRecord);
280 :
281 : template <class CodeType>
282 : bool ReadGenericCodeAssociation(
283 : const DDFRecord *poRecord, const char *pszFieldName,
284 : const char *pszSubField0Name, const char *pszSubField1Name,
285 : std::map<CodeType, std::string> &map,
286 : std::map<CodeType, CodeType> &mapRemapping) const;
287 :
288 : bool ReadATCS(const DDFRecord *poRecord);
289 : bool ReadITCS(const DDFRecord *poRecord);
290 : bool ReadFTCS(const DDFRecord *poRecord);
291 : bool ReadIACS(const DDFRecord *poRecord);
292 : bool ReadFACS(const DDFRecord *poRecord);
293 : bool ReadARCS(const DDFRecord *poRecord);
294 :
295 : bool ReadCSID(const DDFRecord *poRecord);
296 :
297 : bool IngestInitialRecords(const DDFRecord *poRecordIn);
298 : bool IngestUpdateRecords(const DDFRecord *poRecordIn,
299 : DDFModule *poCurModule);
300 : bool UpdateCodesInRecord(DDFRecord *poRecord) const;
301 : bool ProcessUpdateRecord(const DDFRecord *poUpdateRecord,
302 : DDFRecord *poTargetRecord) const;
303 : bool ProcessUpdateATTR(const DDFRecord *poUpdateRecord,
304 : DDFRecord *poTargetRecord) const;
305 : bool ProcessUpdateINASOrFASC(const DDFRecord *poUpdateRecord,
306 : DDFRecord *poTargetRecord,
307 : const char *pszFieldName) const;
308 : bool ProcessUpdateAttributeLikeField(const DDFRecord *poUpdateRecord,
309 : const DDFField *poUpdateField,
310 : DDFRecord *poTargetRecord,
311 : DDFField *poTargetField,
312 : int iFieldInstance) const;
313 : bool ProcessUpdateRecordPoint(const DDFRecord *poUpdateRecord,
314 : DDFRecord *poTargetRecord) const;
315 : bool ProcessUpdatePointList(const DDFRecord *poUpdateRecord,
316 : DDFRecord *poTargetRecord,
317 : bool bIs3DAllowed) const;
318 : bool ProcessUpdateRecordMultiPoint(const DDFRecord *poUpdateRecord,
319 : DDFRecord *poTargetRecord) const;
320 : bool ProcessUpdateRecordCurve(const DDFRecord *poUpdateRecord,
321 : DDFRecord *poTargetRecord) const;
322 : bool ProcessUpdateRecordCompositeCurve(const DDFRecord *poUpdateRecord,
323 : DDFRecord *poTargetRecord) const;
324 : bool ProcessUpdateRecordSurface(const DDFRecord *poUpdateRecord,
325 : DDFRecord *poTargetRecord) const;
326 : bool ProcessUpdateRecordFeatureType(const DDFRecord *poUpdateRecord,
327 : DDFRecord *poTargetRecord) const;
328 :
329 : using PathElement = std::pair<AttrCode, AttrRepeat>;
330 : using PathVector = std::vector<PathElement>;
331 :
332 : // Capture essential information for a repetition of the ATTR field
333 : struct S101AttrDef
334 : {
335 : PathVector oReversedPath{}; // ordered from child to root
336 : std::string osVal{};
337 : int iField = 0;
338 : bool bMultipleFields = false;
339 : bool bIsParent = false;
340 : };
341 :
342 : bool ReadFeatureCatalog();
343 :
344 : std::string BuildFieldName(const PathVector &oReversedPath,
345 : const char *pszAttrFieldName, int iField,
346 : bool bMultipleFields,
347 : const char *pszIDFieldName) const;
348 :
349 : bool CreateInformationTypeFeatureDefn();
350 : bool CreatePointFeatureDefns();
351 : bool CreateMultiPointFeatureDefns();
352 : bool CreateCurveFeatureDefn();
353 : bool CreateCompositeCurveFeatureDefn();
354 : bool CreateSurfaceFeatureDefn();
355 : bool CreateFeatureTypeFeatureDefns();
356 :
357 : bool InferFeatureDefn(
358 : const DDFRecordIndex &oIndex, const char *pszIDFieldName,
359 : const char *pszAttrFieldName, const std::vector<int> &anRecordIndices,
360 : OGRFeatureDefn &oFeatureDefn,
361 : std::map<std::string, std::unique_ptr<OGRFieldDomain>>
362 : &oMapFieldDomains,
363 : const OGRS101FeatureCatalogTypes::InformationType *psInformationType =
364 : nullptr,
365 : const OGRS101FeatureCatalogTypes::FeatureType *psFeatureType =
366 : nullptr) const;
367 :
368 : using NameOccMinOccMax = std::tuple<const char *, int, int>;
369 : bool CheckFieldDefinitions(
370 : const DDFRecord *poRecord, int iRecord, RecordName nRCNM, int nRCID,
371 : const std::map<RecordName, std::vector<std::vector<NameOccMinOccMax>>>
372 : &mapExpectedFields) const;
373 :
374 : bool IngestAttributes(const DDFRecord *poRecord, int iRecord,
375 : const char *pszIDFieldName,
376 : const char *pszAttrFieldName,
377 : const DDFField *poATTRField, int iField,
378 : bool bMultipleFields,
379 : std::vector<S101AttrDef> &asS101AttrDefs) const;
380 :
381 : bool IngestAttributes(const DDFRecord *poRecord, int iRecord,
382 : const char *pszIDFieldName,
383 : const char *pszAttrFieldName,
384 : std::vector<S101AttrDef> &asS101AttrDefs) const;
385 :
386 : bool FillFeatureAttributes(const DDFRecordIndex &oIndex, int iRecord,
387 : const char *pszAttrFieldName,
388 : OGRFeature &oFeature) const;
389 :
390 : CRSId GetCRSIdForPointRecord(const DDFRecord *poRecord, int iRecord,
391 : int nRecordID) const;
392 :
393 : std::map<OGRS101Reader::CRSId, std::vector<int>>
394 : CreateMapCRSIdToRecordIdxForPoints(bool &bError) const;
395 :
396 : CRSId GetCRSIdForMultiPointRecord(const DDFRecord *poRecord, int iRecord,
397 : int nRecordID) const;
398 :
399 : std::map<OGRS101Reader::CRSId, std::vector<int>>
400 : CreateMapCRSIdToRecordIdxForMultiPoints(bool &bError) const;
401 :
402 : bool FillFeatureWithNonAttrAssocSubfields(const DDFRecord *poRecord,
403 : int iRecord,
404 : const char *pszAttrFieldName,
405 : OGRFeature &oFeature) const;
406 :
407 : std::unique_ptr<OGRPoint> ReadPointGeometryInternal(
408 : const DDFRecord *poRecord, int iRecord, int nRecordID, int iPnt,
409 : const OGRSpatialReference *poSRS, const bool bIs3D,
410 : const DDFField *poCoordField, const char *pszRecordFieldName) const;
411 :
412 : std::unique_ptr<OGRPoint>
413 : ReadPointGeometry(const DDFRecord *poRecord, int iRecord, int nRecordID,
414 : const OGRSpatialReference *poSRS) const;
415 :
416 : std::unique_ptr<OGRMultiPoint>
417 : ReadMultiPointGeometry(const DDFRecord *poRecord, int iRecord,
418 : int nRecordID,
419 : const OGRSpatialReference *poSRS) const;
420 :
421 : std::unique_ptr<OGRLineString>
422 : ReadCurveGeometry(const DDFRecord *poRecord, int iRecord, int nRecordID,
423 : const OGRSpatialReference *poSRS) const;
424 :
425 : std::unique_ptr<OGRLineString> ReadCompositeCurveGeometryInternal(
426 : const DDFRecord *poRecord, int iRecord, int nRecordID,
427 : const OGRSpatialReference *poSRS,
428 : std::set<int> &oSetAlreadyVisitedCompositeCurveRecords) const;
429 :
430 : std::unique_ptr<OGRLineString>
431 : ReadCompositeCurveGeometry(const DDFRecord *poRecord, int iRecord,
432 : int nRecordID,
433 : const OGRSpatialReference *poSRS) const;
434 :
435 : std::unique_ptr<OGRPolygon>
436 : ReadSurfaceGeometry(const DDFRecord *poRecord, int iRecord, int nRecordID,
437 : const OGRSpatialReference *poSRS) const;
438 :
439 : template <typename T, typename GeomReaderMethodType>
440 : bool ReadGeometry(const DDFRecordIndex &oIndex, const char *pszErrorContext,
441 : int nGeomRecordID, const char *pszGeomType, bool bReverse,
442 : OGRFeature &oFeature,
443 : std::unique_ptr<OGRGeometryCollection> &poMultiGeom,
444 : GeomReaderMethodType geomReaderMethod,
445 : int iGeomField = 0) const;
446 :
447 : bool FillFeatureTypeGeometry(const DDFRecord *poRecord, int iRecord,
448 : OGRFeature &oFeature) const;
449 :
450 : bool FillFeatureTypeMask(const DDFRecord *poRecord, int iRecord,
451 : OGRFeature &oFeature) const;
452 :
453 : static std::string LaunderCRSName(const OGRSpatialReference &oSRS);
454 : static std::string GetPointLayerName(const OGRSpatialReference &oSRS);
455 : static std::string GetMultiPointLayerName(const OGRSpatialReference &oSRS);
456 :
457 : OGRS101Reader(const OGRS101Reader &) = delete;
458 : OGRS101Reader &operator=(const OGRS101Reader &) = delete;
459 :
460 : protected:
461 : friend class OGRS101FeatureCatalog;
462 : static bool EmitErrorOrWarning(const char *pszFile, const char *pszFunc,
463 : int nLine, const char *pszMsg, bool bError,
464 : bool bRecoverable);
465 :
466 : public:
467 : OGRS101Reader();
468 : ~OGRS101Reader();
469 :
470 : bool Load(GDALOpenInfo *poOpenInfo);
471 :
472 : /** Return whether the dataset is cancelled. */
473 338 : bool IsCancelled() const
474 : {
475 338 : return m_bCancelled;
476 : }
477 :
478 : /** Return feature catalog, or null. */
479 2 : const OGRS101FeatureCatalog *GetFeatureCatalog() const
480 : {
481 2 : return m_poFeatureCatalog;
482 : }
483 :
484 : /** Return dataset metadata from the DSID field. */
485 338 : const CPLStringList &GetMetadata() const
486 : {
487 338 : return m_aosMetadata;
488 : }
489 :
490 : /** Return InformationType records */
491 198 : const DDFRecordIndex &GetInformationTypeRecords() const
492 : {
493 198 : return m_oInformationTypeRecordIndex;
494 : }
495 :
496 : /** Return Point records */
497 204 : const DDFRecordIndex &GetPointRecords() const
498 : {
499 204 : return m_oPointRecordIndex;
500 : }
501 :
502 : /** Return MultiPoint records */
503 77 : const DDFRecordIndex &GetMultiPointRecords() const
504 : {
505 77 : return m_oMultiPointRecordIndex;
506 : }
507 :
508 : /** Return Curve records */
509 144 : const DDFRecordIndex &GetCurveRecords() const
510 : {
511 144 : return m_oCurveRecordIndex;
512 : }
513 :
514 : /** Return CompositeCurve records */
515 109 : const DDFRecordIndex &GetCompositeCurveRecords() const
516 : {
517 109 : return m_oCompositeCurveRecordIndex;
518 : }
519 :
520 : /** Return Surface records */
521 78 : const DDFRecordIndex &GetSurfaceRecords() const
522 : {
523 78 : return m_oSurfaceRecordIndex;
524 : }
525 :
526 : /** Return FeatureType records */
527 299 : const DDFRecordIndex &GetFeatureTypeRecords() const
528 : {
529 299 : return m_oFeatureTypeRecordIndex;
530 : }
531 :
532 : /** Return (and steal) the layer definition for InformationType features */
533 333 : OGRFeatureDefnRefCountedPtr StealInformationTypeFeatureDefn()
534 : {
535 333 : return std::move(m_poFeatureDefnInformationType);
536 : }
537 :
538 : /** Return a map from a CRSId to the layer definition for Point features */
539 333 : std::map<CRSId, OGRFeatureDefnRefCountedPtr> &StealPointFeatureDefns()
540 : {
541 333 : return m_oMapPointFeatureDefn;
542 : }
543 :
544 : /** Return a map from a CRSId to the layer definition for MultiPoint features */
545 333 : std::map<CRSId, OGRFeatureDefnRefCountedPtr> &StealMultiPointFeatureDefns()
546 : {
547 333 : return m_oMapMultiPointFeatureDefn;
548 : }
549 :
550 : /** Return (and steal) a map from a feature type key to the layer definition */
551 333 : std::map<FeatureTypeKey, LayerDef> &StealFeatureTypeLayerDefs()
552 : {
553 333 : return m_oMapFeatureKeyToLayerDef;
554 : }
555 :
556 : /** Return (and steal) the layer definition for curve records */
557 333 : OGRFeatureDefnRefCountedPtr StealCurveFeatureDefn()
558 : {
559 333 : return std::move(m_poFeatureDefnCurve);
560 : }
561 :
562 : /** Return (and steal) the layer definition for composite curve records */
563 333 : OGRFeatureDefnRefCountedPtr StealCompositeCurveFeatureDefn()
564 : {
565 333 : return std::move(m_poFeatureDefnCompositeCurve);
566 : }
567 :
568 : /** Return (and steal) the layer definition for surface records */
569 333 : OGRFeatureDefnRefCountedPtr StealSurfaceFeatureDefn()
570 : {
571 333 : return std::move(m_poFeatureDefnSurface);
572 : }
573 :
574 : /** Return the map from CRS id to indexes of Point records */
575 : const std::map<OGRS101Reader::CRSId, std::vector<int>> &
576 204 : GetMapCRSIdToRecordIdxForPoints() const
577 : {
578 204 : return m_oMapCRSIdToPointRecordIdx;
579 : }
580 :
581 : /** Return the map from CRS id to indexes of MultiPoint records */
582 : const std::map<OGRS101Reader::CRSId, std::vector<int>> &
583 77 : GetMapCRSIdToRecordIdxForMultiPoints() const
584 : {
585 77 : return m_oMapCRSIdToMultiPointRecordIdx;
586 : }
587 :
588 : /** Return (and steal) the field domains */
589 333 : std::map<std::string, std::unique_ptr<OGRFieldDomain>> &StealFieldDomains()
590 : {
591 333 : return m_oMapFieldDomains;
592 : }
593 :
594 : bool FillFeatureInformationType(const DDFRecordIndex &oIndex, int iRecord,
595 : OGRFeature &oFeature) const;
596 :
597 : bool FillFeaturePoint(const DDFRecordIndex &oIndex, int iRecord,
598 : OGRFeature &oFeature) const;
599 :
600 : bool FillFeatureMultiPoint(const DDFRecordIndex &oIndex, int iRecord,
601 : OGRFeature &oFeature) const;
602 :
603 : bool FillFeatureCurve(const DDFRecordIndex &oIndex, int iRecord,
604 : OGRFeature &oFeature) const;
605 :
606 : bool FillFeatureCompositeCurve(const DDFRecordIndex &oIndex, int iRecord,
607 : OGRFeature &oFeature) const;
608 :
609 : bool FillFeatureSurface(const DDFRecordIndex &oIndex, int iRecord,
610 : OGRFeature &oFeature) const;
611 :
612 : bool FillFeatureFeatureType(const DDFRecordIndex &oIndex, int iRecord,
613 : OGRFeature &oFeature) const;
614 : };
615 :
616 : /** Emit an error in strict mode (and return false),
617 : * or an error in non-strict mode (and return true) */
618 : #define EMIT_ERROR_OR_WARNING(msg) \
619 : EmitErrorOrWarning(__FILE__, __FUNCTION__, __LINE__, msg, m_bStrict, true)
620 :
621 : /** Emit an error */
622 : #define EMIT_ERROR(msg) \
623 : EmitErrorOrWarning(__FILE__, __FUNCTION__, __LINE__, msg, true, false)
624 :
625 : /************************************************************************/
626 : /* OGRS101Dataset */
627 : /************************************************************************/
628 :
629 : class OGRS101Dataset final : public GDALDataset
630 : {
631 : std::unique_ptr<OGRS101Reader> m_poReader{};
632 : std::vector<std::unique_ptr<OGRLayer>> m_apoLayers{};
633 :
634 : public:
635 501 : OGRS101Dataset() = default;
636 :
637 : int GetLayerCount() const override;
638 : OGRLayer *GetLayer(int) const override;
639 :
640 4421 : const OGRS101Reader &GetReader() const
641 : {
642 4421 : return *m_poReader;
643 : }
644 :
645 : int TestCapability(const char *) const override;
646 :
647 : static GDALDataset *Open(GDALOpenInfo *poOpenInfo);
648 : static void UnloadDriver(GDALDriver *);
649 : };
650 :
651 : /************************************************************************/
652 : /* OGRS101Layer() */
653 : /************************************************************************/
654 :
655 1109 : class OGRS101Layer /* non final */ : public OGRLayer
656 : {
657 : public:
658 : OGRS101Layer(OGRS101Dataset &oDS, const DDFRecordIndex &oIndex,
659 : OGRFeatureDefnRefCountedPtr poFeatureDefn);
660 : ~OGRS101Layer() override;
661 :
662 20467 : const OGRFeatureDefn *GetLayerDefn() const override
663 : {
664 20467 : return m_poFeatureDefn.get();
665 : }
666 :
667 : void ResetReading() override;
668 :
669 : int TestCapability(const char *) const override;
670 :
671 : GIntBig GetFeatureCount(int bForce) override;
672 :
673 : protected:
674 : const OGRS101Dataset &m_oDS;
675 : const DDFRecordIndex &m_oIndex;
676 : const OGRFeatureDefnRefCountedPtr m_poFeatureDefn{};
677 : int m_nRecordIdx = 0;
678 :
679 : private:
680 : CPL_DISALLOW_COPY_ASSIGN(OGRS101Layer)
681 : };
682 :
683 : /************************************************************************/
684 : /* OGRS101LayerInformationType() */
685 : /************************************************************************/
686 :
687 : class OGRS101LayerInformationType final
688 : : public OGRS101Layer,
689 : OGRGetNextFeatureThroughRaw<OGRS101LayerInformationType>
690 : {
691 : public:
692 : OGRS101LayerInformationType(OGRS101Dataset &oDS,
693 : const DDFRecordIndex &oIndex,
694 : OGRFeatureDefnRefCountedPtr poFeatureDefn);
695 :
696 : OGRFeature *GetNextRawFeature();
697 :
698 : OGRFeature *GetFeature(GIntBig nFID) override;
699 :
700 796 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRS101LayerInformationType)
701 : };
702 :
703 : /************************************************************************/
704 : /* OGRS101LayerPoint() */
705 : /************************************************************************/
706 :
707 : class OGRS101LayerPoint final : public OGRS101Layer,
708 : OGRGetNextFeatureThroughRaw<OGRS101LayerPoint>
709 : {
710 : public:
711 : OGRS101LayerPoint(OGRS101Dataset &oDS, const DDFRecordIndex &oIndex,
712 : const std::vector<int> &anRecordIndices,
713 : OGRFeatureDefnRefCountedPtr poFeatureDefn);
714 :
715 : OGRFeature *GetNextRawFeature();
716 :
717 : GIntBig GetFeatureCount(int bForce) override;
718 :
719 : OGRFeature *GetFeature(GIntBig nFID) override;
720 :
721 1393 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRS101LayerPoint)
722 :
723 : private:
724 : const std::vector<int> &m_anRecordIndices;
725 : };
726 :
727 : /************************************************************************/
728 : /* OGRS101LayerMultiPoint() */
729 : /************************************************************************/
730 :
731 : class OGRS101LayerMultiPoint final
732 : : public OGRS101Layer,
733 : OGRGetNextFeatureThroughRaw<OGRS101LayerMultiPoint>
734 : {
735 : public:
736 : OGRS101LayerMultiPoint(OGRS101Dataset &oDS, const DDFRecordIndex &oIndex,
737 : const std::vector<int> &anRecordIndices,
738 : OGRFeatureDefnRefCountedPtr poFeatureDefn);
739 :
740 : OGRFeature *GetNextRawFeature();
741 :
742 : GIntBig GetFeatureCount(int bForce) override;
743 :
744 : OGRFeature *GetFeature(GIntBig nFID) override;
745 :
746 488 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRS101LayerMultiPoint)
747 :
748 : private:
749 : const std::vector<int> &m_anRecordIndices;
750 : };
751 :
752 : /************************************************************************/
753 : /* OGRS101LayerCurve() */
754 : /************************************************************************/
755 :
756 : class OGRS101LayerCurve final : public OGRS101Layer,
757 : OGRGetNextFeatureThroughRaw<OGRS101LayerCurve>
758 : {
759 : public:
760 : OGRS101LayerCurve(OGRS101Dataset &oDS, const DDFRecordIndex &oIndex,
761 : OGRFeatureDefnRefCountedPtr poFeatureDefn);
762 :
763 : OGRFeature *GetNextRawFeature();
764 :
765 : OGRFeature *GetFeature(GIntBig nFID) override;
766 :
767 1005 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRS101LayerCurve)
768 : };
769 :
770 : /************************************************************************/
771 : /* OGRS101LayerCompositeCurve() */
772 : /************************************************************************/
773 :
774 : class OGRS101LayerCompositeCurve final
775 : : public OGRS101Layer,
776 : OGRGetNextFeatureThroughRaw<OGRS101LayerCompositeCurve>
777 : {
778 : public:
779 : OGRS101LayerCompositeCurve(OGRS101Dataset &oDS,
780 : const DDFRecordIndex &oIndex,
781 : OGRFeatureDefnRefCountedPtr poFeatureDefn);
782 :
783 : OGRFeature *GetNextRawFeature();
784 :
785 : OGRFeature *GetFeature(GIntBig nFID) override;
786 :
787 570 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRS101LayerCompositeCurve)
788 : };
789 :
790 : /************************************************************************/
791 : /* OGRS101LayerSurface() */
792 : /************************************************************************/
793 :
794 : class OGRS101LayerSurface final
795 : : public OGRS101Layer,
796 : OGRGetNextFeatureThroughRaw<OGRS101LayerSurface>
797 : {
798 : public:
799 : OGRS101LayerSurface(OGRS101Dataset &oDS, const DDFRecordIndex &oIndex,
800 : OGRFeatureDefnRefCountedPtr poFeatureDefn);
801 :
802 : OGRFeature *GetNextRawFeature();
803 :
804 : OGRFeature *GetFeature(GIntBig nFID) override;
805 :
806 332 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRS101LayerSurface)
807 : };
808 :
809 : /************************************************************************/
810 : /* OGRS101LayerFeatureType() */
811 : /************************************************************************/
812 :
813 : class OGRS101LayerFeatureType final
814 : : public OGRS101Layer,
815 : OGRGetNextFeatureThroughRaw<OGRS101LayerFeatureType>
816 : {
817 : public:
818 : OGRS101LayerFeatureType(OGRS101Dataset &oDS, const DDFRecordIndex &oIndex,
819 : const std::vector<int> &anRecordIndices,
820 : OGRFeatureDefnRefCountedPtr poFeatureDefn);
821 :
822 : OGRFeature *GetNextRawFeature();
823 :
824 : GIntBig GetFeatureCount(int bForce) override;
825 :
826 : OGRFeature *GetFeature(GIntBig nFID) override;
827 :
828 1116 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRS101LayerFeatureType)
829 :
830 : private:
831 : const std::vector<int> &m_anRecordIndices;
832 : };
833 :
834 : #endif // OGR_S101_H_INCLUDED
|