Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: ISO 8211 Access
4 : * Purpose: Main declarations for ISO 8211.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef ISO8211_H_INCLUDED
14 : #define ISO8211_H_INCLUDED
15 :
16 : #include "cpl_port.h"
17 : #include "cpl_vsi.h"
18 :
19 : #include <array>
20 : #include <memory>
21 : #include <tuple>
22 : #include <vector>
23 :
24 : /**
25 : General data type
26 : */
27 : typedef enum
28 : {
29 : DDFInt,
30 : DDFFloat,
31 : DDFString,
32 : DDFBinaryString
33 : } DDFDataType;
34 :
35 : /************************************************************************/
36 : /* These should really be private to the library ... they are */
37 : /* mostly conveniences. */
38 : /************************************************************************/
39 :
40 : int CPL_DLL DDFScanInt(const char *pszString, int nMaxChars);
41 : int CPL_DLL DDFScanVariable(const char *pszString, int nMaxChars,
42 : int nDelimChar);
43 : std::string CPL_DLL DDFFetchVariable(const char *pszString, int nMaxChars,
44 : int nDelimChar1, int nDelimChar2,
45 : int *pnConsumedChars);
46 :
47 : #define DDF_FIELD_TERMINATOR 30
48 : #define DDF_UNIT_TERMINATOR 31
49 :
50 : /************************************************************************/
51 : /* Predeclarations */
52 : /************************************************************************/
53 :
54 : class DDFFieldDefn;
55 : class DDFSubfieldDefn;
56 : class DDFRecord;
57 : class DDFField;
58 :
59 : /************************************************************************/
60 : /* DDFModule */
61 : /************************************************************************/
62 :
63 : /**
64 : The primary class for reading ISO 8211 files. This class contains all
65 : the information read from the DDR record, and is used to read records
66 : from the file.
67 : */
68 :
69 1373 : class CPL_DLL DDFModule
70 : {
71 : public:
72 : DDFModule();
73 : ~DDFModule();
74 :
75 : int Open(const char *pszFilename, int bFailQuietly = FALSE,
76 : VSILFILE *fpDDFIn = nullptr);
77 : int Create(const char *pszFilename);
78 : void Close();
79 :
80 : int Initialize(char chInterchangeLevel = '3', char chLeaderIden = 'L',
81 : char chCodeExtensionIndicator = 'E',
82 : char chVersionNumber = '1', char chAppIndicator = ' ',
83 : const std::array<char, 3> &achExtendedCharSet = {' ', '!',
84 : ' '},
85 : int nSizeFieldLength = 3, int nSizeFieldPos = 4,
86 : int nSizeFieldTag = 4);
87 :
88 : void Dump(FILE *fp, int nNestingLevel = 0) const;
89 :
90 : DDFRecord *ReadRecord();
91 : void Rewind(long) = delete;
92 : void Rewind(vsi_l_offset nOffset = static_cast<vsi_l_offset>(-1));
93 :
94 : const DDFFieldDefn *FindFieldDefn(const char *) const;
95 :
96 125983 : DDFFieldDefn *FindFieldDefn(const char *name)
97 : {
98 : return const_cast<DDFFieldDefn *>(
99 125983 : const_cast<const DDFModule *>(this)->FindFieldDefn(name));
100 : }
101 :
102 : /** Fetch the number of defined fields. */
103 :
104 231 : int GetFieldCount() const
105 : {
106 231 : return static_cast<int>(apoFieldDefns.size());
107 : }
108 :
109 : /** Return all field definitions */
110 1230 : const std::vector<std::unique_ptr<DDFFieldDefn>> &GetFieldDefns() const
111 : {
112 1230 : return apoFieldDefns;
113 : }
114 :
115 : DDFFieldDefn *GetField(int);
116 : void AddField(std::unique_ptr<DDFFieldDefn> poNewFDefn);
117 :
118 : // This is really just for internal use.
119 19901 : int GetFieldControlLength() const
120 : {
121 19901 : return _fieldControlLength;
122 : }
123 :
124 : // This is just for DDFRecord.
125 66399 : VSILFILE *GetFP()
126 : {
127 66399 : return fpDDF;
128 : }
129 :
130 31948 : int GetSizeFieldTag() const
131 : {
132 31948 : return _sizeFieldTag;
133 : }
134 :
135 : // Advanced uses for 8211dump/8211createfromxml
136 4 : int GetSizeFieldPos() const
137 : {
138 4 : return _sizeFieldPos;
139 : }
140 :
141 4 : int GetSizeFieldLength() const
142 : {
143 4 : return _sizeFieldLength;
144 : }
145 :
146 4 : char GetInterchangeLevel() const
147 : {
148 4 : return _interchangeLevel;
149 : }
150 :
151 4 : char GetLeaderIden() const
152 : {
153 4 : return _leaderIden;
154 : }
155 :
156 4 : char GetCodeExtensionIndicator() const
157 : {
158 4 : return _inlineCodeExtensionIndicator;
159 : }
160 :
161 4 : char GetVersionNumber() const
162 : {
163 4 : return _versionNumber;
164 : }
165 :
166 4 : char GetAppIndicator() const
167 : {
168 4 : return _appIndicator;
169 : }
170 :
171 12 : const std::array<char, 3> &GetExtendedCharSet() const
172 : {
173 12 : return _extendedCharSet;
174 : }
175 :
176 209 : void SetFieldControlLength(int nVal)
177 : {
178 209 : _fieldControlLength = nVal;
179 209 : }
180 :
181 : private:
182 : VSILFILE *fpDDF = nullptr;
183 : bool bReadOnly = false;
184 : vsi_l_offset nFirstRecordOffset = 0;
185 :
186 : char _interchangeLevel = '\0';
187 : char _inlineCodeExtensionIndicator = '\0';
188 : char _versionNumber = '\0';
189 : char _appIndicator = '\0';
190 : int _fieldControlLength = 9;
191 : std::array<char, 3> _extendedCharSet = {' ', '!', ' '};
192 :
193 : int _recLength = 0;
194 : char _leaderIden = 'L';
195 : int _fieldAreaStart = 0;
196 : int _sizeFieldLength = 0;
197 : int _sizeFieldPos = 0;
198 : int _sizeFieldTag = 0;
199 :
200 : // One DirEntry per field.
201 : std::vector<std::unique_ptr<DDFFieldDefn>> apoFieldDefns{};
202 :
203 : std::unique_ptr<DDFRecord> poRecord{};
204 :
205 : CPL_DISALLOW_COPY_ASSIGN(DDFModule)
206 : };
207 :
208 : /************************************************************************/
209 : /* DDFFieldDefn */
210 : /************************************************************************/
211 :
212 : typedef enum
213 : {
214 : dsc_elementary,
215 : dsc_vector,
216 : dsc_array,
217 : dsc_concatenated
218 : } DDF_data_struct_code;
219 :
220 : typedef enum
221 : {
222 : dtc_char_string,
223 : dtc_implicit_point,
224 : dtc_explicit_point,
225 : dtc_explicit_point_scaled,
226 : dtc_char_bit_string,
227 : dtc_bit_string,
228 : dtc_mixed_data_type
229 : } DDF_data_type_code;
230 :
231 : /**
232 : * Information from the DDR defining one field. Note that just because
233 : * a field is defined for a DDFModule doesn't mean that it actually occurs
234 : * on any records in the module. DDFFieldDefns are normally just significant
235 : * as containers of the DDFSubfieldDefns.
236 : */
237 :
238 31824 : class CPL_DLL DDFFieldDefn
239 : {
240 : public:
241 : DDFFieldDefn();
242 : ~DDFFieldDefn();
243 :
244 : int Create(const char *pszTag, const char *pszFieldName,
245 : const char *pszDescription, DDF_data_struct_code eDataStructCode,
246 : DDF_data_type_code eDataTypeCode,
247 : const char *pszFormat = nullptr);
248 : void AddSubfield(std::unique_ptr<DDFSubfieldDefn> poNewSFDefn,
249 : bool bDontAddToFormat = false);
250 : void AddSubfield(const char *pszName, const char *pszFormat);
251 : int GenerateDDREntry(DDFModule *poModule, char **ppachData, int *pnLength);
252 :
253 : int Initialize(DDFModule *poModule, const char *pszTag, int nSize,
254 : const char *pachRecord);
255 :
256 : void Dump(FILE *fp, int nNestingLevel = 0) const;
257 :
258 : /** Fetch a pointer to the field name (tag).
259 : * @return this is an internal copy and should not be freed.
260 : */
261 3218542 : const char *GetName() const
262 : {
263 3218542 : return osTag.c_str();
264 : }
265 :
266 : /** Fetch a longer description of this field.
267 : * @return this is an internal copy and should not be freed.
268 : */
269 42 : const char *GetDescription() const
270 : {
271 42 : return _fieldName.c_str();
272 : }
273 :
274 : /** Get the number of subfields. */
275 112818 : int GetSubfieldCount() const
276 : {
277 112818 : return static_cast<int>(apoSubfields.size());
278 : }
279 :
280 1279252 : const std::vector<std::unique_ptr<DDFSubfieldDefn>> &GetSubfields() const
281 : {
282 1279252 : return apoSubfields;
283 : }
284 :
285 : // For concatenated fields, report each part as a pseudo field
286 543024 : const std::vector<std::unique_ptr<DDFFieldDefn>> &GetParts() const
287 : {
288 543024 : return apoFieldParts;
289 : }
290 :
291 : const DDFSubfieldDefn *FindSubfieldDefn(const char *) const;
292 :
293 : /**
294 : * Get the width of this field. This function isn't normally used
295 : * by applications.
296 : *
297 : * @return The width of the field in bytes, or zero if the field is not
298 : * apparently of a fixed width.
299 : */
300 1047530 : int GetFixedWidth() const
301 : {
302 1047530 : return nFixedWidth;
303 : }
304 :
305 : /**
306 : * Fetch repeating flag.
307 : * @see DDFField::GetRepeatCount()
308 : * @return TRUE if the field is marked as repeating.
309 : */
310 139101 : bool IsRepeating() const
311 : {
312 139101 : return bRepeatingSubfields;
313 : }
314 :
315 : static std::string ExpandFormat(const char *);
316 :
317 : /** this is just for an S-57 hack for swedish data */
318 0 : void SetRepeatingFlag(bool bRepeating)
319 : {
320 0 : bRepeatingSubfields = bRepeating;
321 0 : }
322 :
323 : char *GetDefaultValue(int *pnSize) const;
324 :
325 8848 : const char *GetArrayDescr() const
326 : {
327 8848 : return _arrayDescr.c_str();
328 : }
329 :
330 8848 : const char *GetFormatControls() const
331 : {
332 8848 : return _formatControls.c_str();
333 : }
334 :
335 8846 : DDF_data_struct_code GetDataStructCode() const
336 : {
337 8846 : return _data_struct_code;
338 : }
339 :
340 8848 : DDF_data_type_code GetDataTypeCode() const
341 : {
342 8848 : return _data_type_code;
343 : }
344 :
345 42 : const std::string &GetEscapeSequence() const
346 : {
347 42 : return _escapeSequence;
348 : }
349 :
350 : // val must be poModule->GetFieldControlLength() - 6 bytes long
351 : void SetEscapeSequence(const std::string &val);
352 :
353 33 : bool operator==(const DDFFieldDefn &other) const
354 : {
355 99 : return osTag == other.osTag && _fieldName == other._fieldName &&
356 66 : _arrayDescr == other._arrayDescr &&
357 99 : _formatControls == other._formatControls &&
358 66 : _escapeSequence == other._escapeSequence;
359 : }
360 :
361 33 : bool operator!=(const DDFFieldDefn &other) const
362 : {
363 33 : return !(operator==(other));
364 : }
365 :
366 : private:
367 : static std::string ExtractSubstring(const char *);
368 :
369 : DDFModule *poModule = nullptr;
370 : std::string osTag{};
371 :
372 : std::string _fieldName{};
373 : std::string _arrayDescr{};
374 : std::string _formatControls{};
375 : std::string _escapeSequence{" "};
376 :
377 : bool bRepeatingSubfields = false;
378 : int nFixedWidth = 0; // zero if variable.
379 :
380 : bool BuildSubfields();
381 : int ApplyFormats();
382 :
383 : DDF_data_struct_code _data_struct_code = dsc_elementary;
384 :
385 : DDF_data_type_code _data_type_code = dtc_char_string;
386 :
387 : std::vector<std::unique_ptr<DDFSubfieldDefn>> apoSubfields{};
388 :
389 : // Used in concatenated fields
390 : std::vector<std::unique_ptr<DDFFieldDefn>> apoFieldParts{};
391 :
392 : CPL_DISALLOW_COPY_ASSIGN(DDFFieldDefn)
393 : };
394 :
395 : /************************************************************************/
396 : /* DDFSubfieldDefn */
397 : /* */
398 : /* Information from the DDR record for one subfield of a */
399 : /* particular field. */
400 : /************************************************************************/
401 :
402 : /**
403 : * Information from the DDR record describing one subfield of a DDFFieldDefn.
404 : * All subfields of a field will occur in each occurrence of that field
405 : * (as a DDFField) in a DDFRecord. Subfield's actually contain formatted
406 : * data (as instances within a record).
407 : */
408 :
409 128568 : class CPL_DLL DDFSubfieldDefn
410 : {
411 : public:
412 : DDFSubfieldDefn();
413 : ~DDFSubfieldDefn();
414 :
415 : void SetName(const char *pszName);
416 :
417 : /** Get pointer to subfield name. */
418 1553546 : const char *GetName() const
419 : {
420 1553546 : return osName.c_str();
421 : }
422 :
423 : /** Get pointer to subfield format string */
424 57604 : const char *GetFormat() const
425 : {
426 57604 : return osFormatString.c_str();
427 : }
428 :
429 : int SetFormat(const char *pszFormat);
430 :
431 : /**
432 : * Get the general type of the subfield. This can be used to
433 : * determine which of ExtractFloatData(), ExtractIntData() or
434 : * ExtractStringData() should be used.
435 : * @return The subfield type. One of DDFInt, DDFFloat, DDFString or
436 : * DDFBinaryString.
437 : */
438 :
439 3180 : DDFDataType GetType() const
440 : {
441 3180 : return eType;
442 : }
443 :
444 : double ExtractFloatData(const char *pachData, int nMaxBytes,
445 : int *pnConsumedBytes) const;
446 : int ExtractIntData(const char *pachData, int nMaxBytes,
447 : int *pnConsumedBytes) const;
448 : const char *ExtractStringData(const char *pachData, int nMaxBytes,
449 : int *pnConsumedBytes) const;
450 : int GetDataLength(const char *, int, int *) const;
451 : void DumpData(const char *pachData, int nMaxBytes, FILE *fp) const;
452 :
453 : int FormatStringValue(char *pachData, int nBytesAvailable, int *pnBytesUsed,
454 : const char *pszValue, int nValueLength = -1) const;
455 :
456 : int FormatIntValue(char *pachData, int nBytesAvailable, int *pnBytesUsed,
457 : int nNewValue) const;
458 :
459 : int FormatFloatValue(char *pachData, int nBytesAvailable, int *pnBytesUsed,
460 : double dfNewValue) const;
461 :
462 : /** Get the subfield width (zero for variable). */
463 272772 : int GetWidth() const
464 : {
465 272772 : return nFormatWidth;
466 : } // zero for variable.
467 :
468 : int GetDefaultValue(char *pachData, int nBytesAvailable,
469 : int *pnBytesUsed) const;
470 :
471 : void Dump(FILE *fp, int nNestingLevel = 0) const;
472 :
473 : /**
474 : Binary format: this is the digit immediately following the B or b for
475 : binary formats.
476 : */
477 : typedef enum
478 : {
479 : NotBinary = 0,
480 : UInt = 1,
481 : SInt = 2,
482 : FPReal = 3,
483 : FloatReal = 4,
484 : FloatComplex = 5
485 : } DDFBinaryFormat;
486 :
487 83792 : DDFBinaryFormat GetBinaryFormat() const
488 : {
489 83792 : return eBinaryFormat;
490 : }
491 :
492 : private:
493 : std::string osName{}; // a.k.a. subfield mnemonic
494 : std::string osFormatString{};
495 :
496 : DDFDataType eType = DDFString;
497 : DDFBinaryFormat eBinaryFormat = NotBinary;
498 :
499 : /* -------------------------------------------------------------------- */
500 : /* bIsVariable determines whether we using the */
501 : /* chFormatDelimiter (TRUE), or the fixed width (FALSE). */
502 : /* -------------------------------------------------------------------- */
503 : bool bIsVariable = true;
504 :
505 : char chFormatDelimiter = DDF_UNIT_TERMINATOR;
506 : int nFormatWidth = 0;
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* Fetched string cache. This is where we hold the values */
510 : /* returned from ExtractStringData(). */
511 : /* -------------------------------------------------------------------- */
512 : mutable std::string osBuffer{};
513 : };
514 :
515 : /************************************************************************/
516 : /* DDFField */
517 : /* */
518 : /* This object represents one field in a DDFRecord. */
519 : /************************************************************************/
520 :
521 : /**
522 : * This object represents one field in a DDFRecord. This
523 : * models an instance of the fields data, rather than its data definition,
524 : * which is handled by the DDFFieldDefn class. Note that a DDFField
525 : * doesn't have DDFSubfield children as you would expect. To extract
526 : * subfield values use GetSubfieldData() to find the right data pointer and
527 : * then use ExtractIntData(), ExtractFloatData() or ExtractStringData().
528 : */
529 :
530 : class CPL_DLL DDFField
531 : {
532 : public:
533 244338 : DDFField() = default;
534 : DDFField(DDFField &&) = default;
535 : DDFField &operator=(DDFField &&) = default;
536 :
537 : bool Initialize(const DDFFieldDefn *, const char *pszData, int nSize,
538 : bool bInitializeParts);
539 : bool InitializeParts();
540 :
541 : void Dump(FILE *fp, int nNestingLevel = 0) const;
542 :
543 : const char *GetSubfieldData(const DDFSubfieldDefn *, int * = nullptr,
544 : int = 0) const;
545 :
546 : const char *GetInstanceData(int nInstance, int *pnSize = nullptr);
547 :
548 : /**
549 : * Return the pointer to the entire data block for this record. This
550 : * is an internal copy, and should not be freed by the application.
551 : */
552 192837 : const char *GetData() const
553 : {
554 192837 : return pachData;
555 : }
556 :
557 : /** Return the number of bytes in the data block returned by GetData(). */
558 189777 : int GetDataSize() const
559 : {
560 189777 : return nDataSize;
561 : }
562 :
563 : int GetRepeatCount() const;
564 :
565 : /** Fetch the corresponding DDFFieldDefn. */
566 3052246 : const DDFFieldDefn *GetFieldDefn() const
567 : {
568 3052246 : return poDefn;
569 : }
570 :
571 : // For concatenated fields, report each part as a pseudo field
572 575828 : const std::vector<std::unique_ptr<DDFField>> &GetParts() const
573 : {
574 575828 : return apoFieldParts;
575 : }
576 :
577 : private:
578 : const DDFFieldDefn *poDefn = nullptr;
579 :
580 : int nDataSize = 0;
581 :
582 : const char *pachData = nullptr;
583 :
584 : // Used in concatenated fields
585 : std::vector<std::unique_ptr<DDFField>> apoFieldParts{};
586 :
587 : CPL_DISALLOW_COPY_ASSIGN(DDFField)
588 : };
589 :
590 : /************************************************************************/
591 : /* DDFRecord */
592 : /* */
593 : /* Class that contains one DR record from a file. We read into */
594 : /* the same record object repeatedly to ensure that repeated */
595 : /* leaders can be easily preserved. */
596 : /************************************************************************/
597 :
598 : /**
599 : * Contains instance data from one data record (DR). The data is contained
600 : * as a list of DDFField instances partitioning the raw data into fields.
601 : */
602 :
603 : class CPL_DLL DDFRecord
604 : {
605 : public:
606 : explicit DDFRecord(DDFModule *);
607 : ~DDFRecord();
608 :
609 : std::unique_ptr<DDFRecord> Clone() const;
610 : bool TransferTo(DDFModule *poTargetModule);
611 :
612 : void Dump(FILE *, int nNestingLevel = 0) const;
613 :
614 : /** Get the number of DDFFields on this record. */
615 307841 : int GetFieldCount() const
616 : {
617 307841 : return static_cast<int>(apoFields.size());
618 : }
619 :
620 : const DDFField *FindField(const char *, int = 0) const;
621 :
622 605 : DDFField *FindField(const char *name, int i = 0)
623 : {
624 : return const_cast<DDFField *>(
625 605 : const_cast<const DDFRecord *>(this)->FindField(name, i));
626 : }
627 :
628 : const DDFField *GetField(int) const;
629 :
630 : std::vector<const DDFField *> GetFields(const char *pszFieldName) const;
631 :
632 : std::vector<DDFField *> GetFields(const char *pszFieldName);
633 :
634 2243 : const std::vector<std::unique_ptr<DDFField>> &GetFields() const
635 : {
636 2243 : return apoFields;
637 : }
638 :
639 28585 : DDFField *GetField(int i)
640 : {
641 : return const_cast<DDFField *>(
642 28585 : const_cast<const DDFRecord *>(this)->GetField(i));
643 : }
644 :
645 : int GetIntSubfield(const DDFField *, const char *, int,
646 : int * = nullptr) const;
647 : int GetIntSubfield(const char *, int, const char *, int,
648 : int * = nullptr) const;
649 : double GetFloatSubfield(const char *, int, const char *, int,
650 : int * = nullptr) const;
651 : const char *GetStringSubfield(const DDFField *, const char *, int,
652 : int * = nullptr) const;
653 : const char *GetStringSubfield(const char *, int, const char *, int,
654 : int * = nullptr) const;
655 :
656 : int SetIntSubfield(const char *pszField, int iFieldIndex,
657 : const char *pszSubfield, int iSubfieldIndex, int nValue);
658 : int SetStringSubfield(const char *pszField, int iFieldIndex,
659 : const char *pszSubfield, int iSubfieldIndex,
660 : const char *pszValue, int nValueLength = -1);
661 : int SetFloatSubfield(const char *pszField, int iFieldIndex,
662 : const char *pszSubfield, int iSubfieldIndex,
663 : double dfNewValue);
664 :
665 : /** Fetch size of records raw data (GetData()) in bytes. */
666 143 : int GetDataSize() const
667 : {
668 143 : return static_cast<int>(osData.size());
669 : }
670 :
671 : /**
672 : * Fetch the raw data for this record. The returned pointer is effectively
673 : * to the data for the first field of the record, and is of size
674 : * GetDataSize().
675 : */
676 1355 : const char *GetData() const
677 : {
678 1355 : return osData.c_str();
679 : }
680 :
681 : /**
682 : * Fetch the DDFModule with which this record is associated.
683 : */
684 :
685 0 : DDFModule *GetModule()
686 : {
687 0 : return poModule;
688 : }
689 :
690 616 : const DDFModule *GetModule() const
691 : {
692 616 : return poModule;
693 : }
694 :
695 : int DeleteField(DDFField *poField);
696 : DDFField *AddField(const DDFFieldDefn *);
697 :
698 : int SetFieldRaw(DDFField *poField, int iIndexWithinField,
699 : const char *pachRawData, int nRawDataSize);
700 :
701 : int SetFieldRaw(DDFField *poField, const char *pachRawData,
702 : int nRawDataSize);
703 :
704 : int Write();
705 :
706 : // Advanced uses for 8211dump/8211createfromxml
707 143 : bool GetReuseHeader() const
708 : {
709 143 : return bReuseHeader;
710 : }
711 :
712 1344 : int GetSizeFieldTag() const
713 : {
714 1344 : return _sizeFieldTag;
715 : }
716 :
717 1344 : int GetSizeFieldPos() const
718 : {
719 1344 : return _sizeFieldPos;
720 : }
721 :
722 1344 : int GetSizeFieldLength() const
723 : {
724 1344 : return _sizeFieldLength;
725 : }
726 :
727 1201 : void SetSizeFieldTag(int nVal)
728 : {
729 1201 : _sizeFieldTag = nVal;
730 1201 : }
731 :
732 1201 : void SetSizeFieldPos(int nVal)
733 : {
734 1201 : _sizeFieldPos = nVal;
735 1201 : }
736 :
737 1201 : void SetSizeFieldLength(int nVal)
738 : {
739 1201 : _sizeFieldLength = nVal;
740 1201 : }
741 :
742 : // This is really just for the DDFModule class.
743 : int Read();
744 : void Clear();
745 : void ResetDirectory();
746 :
747 : private:
748 : int ReadHeader();
749 :
750 : static std::tuple<const DDFField *, const DDFSubfieldDefn *>
751 : FindSubfieldDefn(const DDFField *poField, const char *pszSubfield,
752 : bool bEmitError = true);
753 :
754 : std::tuple<const DDFField *, const DDFField *, const DDFSubfieldDefn *>
755 : FindSubfieldDefn(const char *pszField, int iFieldIndex,
756 : const char *pszSubfield, bool bEmitError = true) const;
757 :
758 : std::tuple<DDFField *, DDFField *, const DDFSubfieldDefn *>
759 25845 : FindSubfieldDefn(const char *pszField, int iFieldIndex,
760 : const char *pszSubfield)
761 : {
762 25845 : auto [field, partField, subfield] =
763 : const_cast<const DDFRecord *>(this)->FindSubfieldDefn(
764 25845 : pszField, iFieldIndex, pszSubfield);
765 0 : return {const_cast<DDFField *>(field),
766 51690 : const_cast<DDFField *>(partField), subfield};
767 : }
768 :
769 : int CreateDefaultFieldInstance(DDFField *poField, int iIndexWithinField);
770 :
771 : int ResizeField(DDFField *poField, int nNewDataSize);
772 :
773 : int UpdateFieldRaw(DDFField *poField, DDFField *poPartField,
774 : int iIndexWithinField, int nStartOffset, int nOldSize,
775 : const char *pachRawData, int nRawDataSize);
776 :
777 : char *GetSubfieldDataForSetSubfield(DDFField *poField,
778 : DDFField *poPartField,
779 : const DDFSubfieldDefn *poSFDefn,
780 : int iSubfieldIndex, int &nMaxBytes);
781 :
782 : DDFModule *poModule = nullptr;
783 :
784 : bool bReuseHeader = false;
785 :
786 : int nFieldOffset = 0; // field data area, not dir entries.
787 :
788 : int _sizeFieldTag = 0;
789 : int _sizeFieldPos = 5;
790 : int _sizeFieldLength = 5;
791 :
792 : std::string osData{}; // Whole record except leader with header
793 :
794 : std::vector<std::unique_ptr<DDFField>> apoFields{};
795 :
796 : CPL_DISALLOW_COPY_ASSIGN(DDFRecord)
797 : };
798 :
799 : #endif /* ndef ISO8211_H_INCLUDED */
|