LCOV - code coverage report
Current view: top level - frmts/iso8211 - iso8211.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 119 125 95.2 %
Date: 2026-05-29 23:25:07 Functions: 59 61 96.7 %

          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 */

Generated by: LCOV version 1.14