LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mitab - mitab_priv.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 146 164 89.0 %
Date: 2024-05-05 22:37:24 Functions: 69 78 88.5 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  * $Id$
       3             :  *
       4             :  * Name:     mitab_priv.h
       5             :  * Project:  MapInfo TAB Read/Write library
       6             :  * Language: C++
       7             :  * Purpose:  Header file containing private definitions for the library.
       8             :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
       9             :  *
      10             :  **********************************************************************
      11             :  * Copyright (c) 1999-2003, Daniel Morissette
      12             :  * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
      13             :  *
      14             :  * Permission is hereby granted, free of charge, to any person obtaining a
      15             :  * copy of this software and associated documentation files (the "Software"),
      16             :  * to deal in the Software without restriction, including without limitation
      17             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18             :  * and/or sell copies of the Software, and to permit persons to whom the
      19             :  * Software is furnished to do so, subject to the following conditions:
      20             :  *
      21             :  * The above copyright notice and this permission notice shall be included
      22             :  * in all copies or substantial portions of the Software.
      23             :  *
      24             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      25             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      27             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30             :  * DEALINGS IN THE SOFTWARE.
      31             :  **********************************************************************/
      32             : 
      33             : #ifndef MITAB_PRIV_H_INCLUDED_
      34             : #define MITAB_PRIV_H_INCLUDED_
      35             : 
      36             : #include "cpl_conv.h"
      37             : #include "cpl_string.h"
      38             : #include "ogr_feature.h"
      39             : 
      40             : #include <set>
      41             : 
      42             : class TABFile;
      43             : class TABFeature;
      44             : class TABMAPToolBlock;
      45             : class TABMAPIndexBlock;
      46             : 
      47             : /*---------------------------------------------------------------------
      48             :  * Access mode: Read or Write
      49             :  *--------------------------------------------------------------------*/
      50             : typedef enum
      51             : {
      52             :     TABRead,
      53             :     TABWrite,
      54             :     TABReadWrite
      55             : } TABAccess;
      56             : 
      57             : /*---------------------------------------------------------------------
      58             :  * Supported .MAP block types (the first byte at the beginning of a block)
      59             :  *--------------------------------------------------------------------*/
      60             : #define TAB_RAWBIN_BLOCK -1
      61             : #define TABMAP_HEADER_BLOCK 0
      62             : #define TABMAP_INDEX_BLOCK 1
      63             : #define TABMAP_OBJECT_BLOCK 2
      64             : #define TABMAP_COORD_BLOCK 3
      65             : #define TABMAP_GARB_BLOCK 4
      66             : #define TABMAP_TOOL_BLOCK 5
      67             : #define TABMAP_LAST_VALID_BLOCK_TYPE 5
      68             : 
      69             : /*---------------------------------------------------------------------
      70             :  * Drawing Tool types
      71             :  *--------------------------------------------------------------------*/
      72             : #define TABMAP_TOOL_PEN 1
      73             : #define TABMAP_TOOL_BRUSH 2
      74             : #define TABMAP_TOOL_FONT 3
      75             : #define TABMAP_TOOL_SYMBOL 4
      76             : 
      77             : /*---------------------------------------------------------------------
      78             :  * Limits related to .TAB version number.  If we pass any of those limits
      79             :  * then we have to use larger object types
      80             :  *--------------------------------------------------------------------*/
      81             : #define TAB_REGION_PLINE_300_MAX_VERTICES 32767
      82             : 
      83             : #define TAB_REGION_PLINE_450_MAX_SEGMENTS 32767
      84             : #define TAB_REGION_PLINE_450_MAX_VERTICES 1048575
      85             : 
      86             : #define TAB_MULTIPOINT_650_MAX_VERTICES 1048576
      87             : 
      88             : /* Use this macro to test whether the number of segments and vertices
      89             :  * in this object exceeds the V450/650 limits and requires a V800 object
      90             :  */
      91             : #define TAB_REGION_PLINE_REQUIRES_V800(numSegments, numVerticesTotal)          \
      92             :     ((numSegments) > TAB_REGION_PLINE_450_MAX_SEGMENTS ||                      \
      93             :      ((numSegments)*3 + numVerticesTotal) > TAB_REGION_PLINE_450_MAX_VERTICES)
      94             : 
      95             : /*---------------------------------------------------------------------
      96             :  * Codes for the known MapInfo Geometry types
      97             :  *--------------------------------------------------------------------*/
      98             : typedef enum
      99             : {
     100             :     TAB_GEOM_UNSET = -1,
     101             : 
     102             :     TAB_GEOM_NONE = 0,
     103             :     TAB_GEOM_SYMBOL_C = 0x01,
     104             :     TAB_GEOM_SYMBOL = 0x02,
     105             :     TAB_GEOM_LINE_C = 0x04,
     106             :     TAB_GEOM_LINE = 0x05,
     107             :     TAB_GEOM_PLINE_C = 0x07,
     108             :     TAB_GEOM_PLINE = 0x08,
     109             :     TAB_GEOM_ARC_C = 0x0a,
     110             :     TAB_GEOM_ARC = 0x0b,
     111             :     TAB_GEOM_REGION_C = 0x0d,
     112             :     TAB_GEOM_REGION = 0x0e,
     113             :     TAB_GEOM_TEXT_C = 0x10,
     114             :     TAB_GEOM_TEXT = 0x11,
     115             :     TAB_GEOM_RECT_C = 0x13,
     116             :     TAB_GEOM_RECT = 0x14,
     117             :     TAB_GEOM_ROUNDRECT_C = 0x16,
     118             :     TAB_GEOM_ROUNDRECT = 0x17,
     119             :     TAB_GEOM_ELLIPSE_C = 0x19,
     120             :     TAB_GEOM_ELLIPSE = 0x1a,
     121             :     TAB_GEOM_MULTIPLINE_C = 0x25,
     122             :     TAB_GEOM_MULTIPLINE = 0x26,
     123             :     TAB_GEOM_FONTSYMBOL_C = 0x28,
     124             :     TAB_GEOM_FONTSYMBOL = 0x29,
     125             :     TAB_GEOM_CUSTOMSYMBOL_C = 0x2b,
     126             :     TAB_GEOM_CUSTOMSYMBOL = 0x2c,
     127             :     /* Version 450 object types: */
     128             :     TAB_GEOM_V450_REGION_C = 0x2e,
     129             :     TAB_GEOM_V450_REGION = 0x2f,
     130             :     TAB_GEOM_V450_MULTIPLINE_C = 0x31,
     131             :     TAB_GEOM_V450_MULTIPLINE = 0x32,
     132             :     /* Version 650 object types: */
     133             :     TAB_GEOM_MULTIPOINT_C = 0x34,
     134             :     TAB_GEOM_MULTIPOINT = 0x35,
     135             :     TAB_GEOM_COLLECTION_C = 0x37,
     136             :     TAB_GEOM_COLLECTION = 0x38,
     137             :     /* Version 800 object types: */
     138             :     TAB_GEOM_UNKNOWN1_C = 0x3a,  // ???
     139             :     TAB_GEOM_UNKNOWN1 = 0x3b,    // ???
     140             :     TAB_GEOM_V800_REGION_C = 0x3d,
     141             :     TAB_GEOM_V800_REGION = 0x3e,
     142             :     TAB_GEOM_V800_MULTIPLINE_C = 0x40,
     143             :     TAB_GEOM_V800_MULTIPLINE = 0x41,
     144             :     TAB_GEOM_V800_MULTIPOINT_C = 0x43,
     145             :     TAB_GEOM_V800_MULTIPOINT = 0x44,
     146             :     TAB_GEOM_V800_COLLECTION_C = 0x46,
     147             :     TAB_GEOM_V800_COLLECTION = 0x47,
     148             :     TAB_GEOM_MAX_TYPE /* TODo: Does this need to be 0x80? */
     149             : } TABGeomType;
     150             : 
     151             : #define TAB_GEOM_GET_VERSION(nGeomType)                                        \
     152             :     (((nGeomType) < TAB_GEOM_V450_REGION_C)  ? 300                             \
     153             :      : ((nGeomType) < TAB_GEOM_MULTIPOINT_C) ? 450                             \
     154             :      : ((nGeomType) < TAB_GEOM_UNKNOWN1_C)   ? 650                             \
     155             :                                              : 800)
     156             : 
     157             : /*---------------------------------------------------------------------
     158             :  * struct TABMAPIndexEntry - Entries found in type 1 blocks of .MAP files
     159             :  *
     160             :  * We will use this struct to rebuild the geographic index in memory
     161             :  *--------------------------------------------------------------------*/
     162             : typedef struct TABMAPIndexEntry_t
     163             : {
     164             :     // These members refer to the info we find in the file
     165             :     GInt32 XMin;
     166             :     GInt32 YMin;
     167             :     GInt32 XMax;
     168             :     GInt32 YMax;
     169             :     GInt32 nBlockPtr;
     170             : } TABMAPIndexEntry;
     171             : 
     172             : #define TAB_MIN_BLOCK_SIZE 512
     173             : #define TAB_MAX_BLOCK_SIZE (32768 - 512)
     174             : 
     175             : #define TAB_MAX_ENTRIES_INDEX_BLOCK ((TAB_MAX_BLOCK_SIZE - 4) / 20)
     176             : 
     177             : /*---------------------------------------------------------------------
     178             :  * TABVertex
     179             :  *--------------------------------------------------------------------*/
     180             : typedef struct TABVertex_t
     181             : {
     182             :     double x{};
     183             :     double y{};
     184             : } TABVertex;
     185             : 
     186             : /*---------------------------------------------------------------------
     187             :  * TABTableType - Attribute table format
     188             :  *--------------------------------------------------------------------*/
     189             : typedef enum
     190             : {
     191             :     TABTableNative,  // The default
     192             :     TABTableDBF,
     193             :     TABTableAccess
     194             : } TABTableType;
     195             : 
     196             : /*---------------------------------------------------------------------
     197             :  * TABFieldType - Native MapInfo attribute field types
     198             :  *--------------------------------------------------------------------*/
     199             : typedef enum
     200             : {
     201             :     TABFUnknown = 0,
     202             :     TABFChar,
     203             :     TABFInteger,
     204             :     TABFSmallInt,
     205             :     TABFDecimal,
     206             :     TABFFloat,
     207             :     TABFDate,
     208             :     TABFLogical,
     209             :     TABFTime,
     210             :     TABFDateTime,
     211             :     TABFLargeInt
     212             : } TABFieldType;
     213             : 
     214             : #define TABFIELDTYPE_2_STRING(type)                                            \
     215             :     (type == TABFChar       ? "Char"                                           \
     216             :      : type == TABFInteger  ? "Integer"                                        \
     217             :      : type == TABFSmallInt ? "SmallInt"                                       \
     218             :      : type == TABFLargeInt ? "LargeInt"                                       \
     219             :      : type == TABFDecimal  ? "Decimal"                                        \
     220             :      : type == TABFFloat    ? "Float"                                          \
     221             :      : type == TABFDate     ? "Date"                                           \
     222             :      : type == TABFLogical  ? "Logical"                                        \
     223             :      : type == TABFTime     ? "Time"                                           \
     224             :      : type == TABFDateTime ? "DateTime"                                       \
     225             :                             : "Unknown field type")
     226             : 
     227             : /*---------------------------------------------------------------------
     228             :  * TABDATFieldDef
     229             :  *--------------------------------------------------------------------*/
     230             : typedef struct TABDATFieldDef_t
     231             : {
     232             :     char szName[11];
     233             :     char cType;
     234             :     GByte byLength;
     235             :     GByte byDecimals;
     236             : 
     237             :     TABFieldType eTABType;
     238             : } TABDATFieldDef;
     239             : 
     240             : /*---------------------------------------------------------------------
     241             :  * TABMAPCoordSecHdr
     242             :  * struct used in the TABMAPCoordBlock to store info about the coordinates
     243             :  * for a section of a PLINE MULTIPLE or a REGION.
     244             :  *--------------------------------------------------------------------*/
     245             : typedef struct TABMAPCoordSecHdr_t
     246             : {
     247             :     GInt32 numVertices;
     248             :     GInt32 numHoles;
     249             :     GInt32 nXMin;
     250             :     GInt32 nYMin;
     251             :     GInt32 nXMax;
     252             :     GInt32 nYMax;
     253             : 
     254             :     GInt32 nDataOffset;
     255             :     int nVertexOffset;
     256             : } TABMAPCoordSecHdr;
     257             : 
     258             : /*---------------------------------------------------------------------
     259             :  * TABProjInfo
     260             :  * struct used to store the projection parameters from the .MAP header
     261             :  *--------------------------------------------------------------------*/
     262             : typedef struct TABProjInfo_t
     263             : {
     264             :     GByte nProjId;  // See MapInfo Ref. Manual, App. F and G
     265             :     GByte nEllipsoidId;
     266             :     GByte nUnitsId;
     267             :     double adProjParams[7];  // params in same order as in .MIF COORDSYS
     268             : 
     269             :     GInt16 nDatumId;      // Datum Id added in MapInfo 7.8+ (.map V500)
     270             :     double dDatumShiftX;  // Before that, we had to always lookup datum
     271             :     double dDatumShiftY;  // parameters to establish datum id
     272             :     double dDatumShiftZ;
     273             :     double adDatumParams[5];
     274             : 
     275             :     // Affine parameters only in .map version 500 and up
     276             :     GByte nAffineFlag;  // 0=No affine param, 1=Affine params
     277             :     GByte nAffineUnits;
     278             :     double dAffineParamA;  // Affine params
     279             :     double dAffineParamB;
     280             :     double dAffineParamC;
     281             :     double dAffineParamD;
     282             :     double dAffineParamE;
     283             :     double dAffineParamF;
     284             : } TABProjInfo;
     285             : 
     286             : /*---------------------------------------------------------------------
     287             :  * TABPenDef - Pen definition information
     288             :  *--------------------------------------------------------------------*/
     289             : typedef struct TABPenDef_t
     290             : {
     291             :     GInt32 nRefCount;
     292             :     GByte nPixelWidth;
     293             :     GByte nLinePattern;
     294             :     int nPointWidth;
     295             :     GInt32 rgbColor;
     296             : } TABPenDef;
     297             : 
     298             : /* MI Default = PEN(1,2,0) */
     299             : #define MITAB_PEN_DEFAULT                                                      \
     300             :     {                                                                          \
     301             :         0, 1, 2, 0, 0x000000                                                   \
     302             :     }
     303             : 
     304             : /*---------------------------------------------------------------------
     305             :  * TABBrushDef - Brush definition information
     306             :  *--------------------------------------------------------------------*/
     307             : typedef struct TABBrushDef_t
     308             : {
     309             :     GInt32 nRefCount;
     310             :     GByte nFillPattern;
     311             :     GByte bTransparentFill;  // 1 = Transparent
     312             :     GInt32 rgbFGColor;
     313             :     GInt32 rgbBGColor;
     314             : } TABBrushDef;
     315             : 
     316             : /* MI Default = BRUSH(1,0,16777215) */
     317             : #define MITAB_BRUSH_DEFAULT                                                    \
     318             :     {                                                                          \
     319             :         0, 1, 0, 0, 0xffffff                                                   \
     320             :     }
     321             : 
     322             : /*---------------------------------------------------------------------
     323             :  * TABFontDef - Font Name information
     324             :  *--------------------------------------------------------------------*/
     325             : typedef struct TABFontDef_t
     326             : {
     327             :     GInt32 nRefCount;
     328             :     char szFontName[33];
     329             : } TABFontDef;
     330             : 
     331             : /* MI Default = FONT("Arial",0,0,0) */
     332             : #define MITAB_FONT_DEFAULT                                                     \
     333             :     {                                                                          \
     334             :         0, "Arial"                                                             \
     335             :     }
     336             : 
     337             : /*---------------------------------------------------------------------
     338             :  * TABSymbolDef - Symbol definition information
     339             :  *--------------------------------------------------------------------*/
     340             : typedef struct TABSymbolDef_t
     341             : {
     342             :     GInt32 nRefCount;
     343             :     GInt16 nSymbolNo;
     344             :     GInt16 nPointSize;
     345             :     GByte _nUnknownValue_;  // Style???
     346             :     GInt32 rgbColor;
     347             : } TABSymbolDef;
     348             : 
     349             : /* MI Default = SYMBOL(35,0,12) */
     350             : #define MITAB_SYMBOL_DEFAULT                                                   \
     351             :     {                                                                          \
     352             :         0, 35, 12, 0, 0x000000                                                 \
     353             :     }
     354             : 
     355             : /*---------------------------------------------------------------------
     356             :  *                      class TABToolDefTable
     357             :  *
     358             :  * Class to handle the list of Drawing Tool Definitions for a dataset
     359             :  *
     360             :  * This class also contains methods to read tool defs from the file and
     361             :  * write them to the file.
     362             :  *--------------------------------------------------------------------*/
     363             : 
     364             : class TABToolDefTable
     365             : {
     366             :     CPL_DISALLOW_COPY_ASSIGN(TABToolDefTable)
     367             : 
     368             :   protected:
     369             :     TABPenDef **m_papsPen;
     370             :     int m_numPen;
     371             :     int m_numAllocatedPen;
     372             :     TABBrushDef **m_papsBrush;
     373             :     int m_numBrushes;
     374             :     int m_numAllocatedBrushes;
     375             :     TABFontDef **m_papsFont;
     376             :     int m_numFonts;
     377             :     int m_numAllocatedFonts;
     378             :     TABSymbolDef **m_papsSymbol;
     379             :     int m_numSymbols;
     380             :     int m_numAllocatedSymbols;
     381             : 
     382             :   public:
     383             :     TABToolDefTable();
     384             :     ~TABToolDefTable();
     385             : 
     386             :     int ReadAllToolDefs(TABMAPToolBlock *poToolBlock);
     387             :     int WriteAllToolDefs(TABMAPToolBlock *poToolBlock);
     388             : 
     389             :     TABPenDef *GetPenDefRef(int nIndex);
     390             :     int AddPenDefRef(TABPenDef *poPenDef);
     391             :     int GetNumPen();
     392             : 
     393             :     TABBrushDef *GetBrushDefRef(int nIndex);
     394             :     int AddBrushDefRef(TABBrushDef *poBrushDef);
     395             :     int GetNumBrushes();
     396             : 
     397             :     TABFontDef *GetFontDefRef(int nIndex);
     398             :     int AddFontDefRef(TABFontDef *poFontDef);
     399             :     int GetNumFonts();
     400             : 
     401             :     TABSymbolDef *GetSymbolDefRef(int nIndex);
     402             :     int AddSymbolDefRef(TABSymbolDef *poSymbolDef);
     403             :     int GetNumSymbols();
     404             : 
     405             :     int GetMinVersionNumber();
     406             : };
     407             : 
     408             : /*=====================================================================
     409             :           Classes to handle Object Headers inside TABMAPObjectBlocks
     410             :  =====================================================================*/
     411             : 
     412             : class TABMAPObjectBlock;
     413             : class TABMAPHeaderBlock;
     414             : 
     415             : class TABMAPObjHdr
     416             : {
     417             :   public:
     418             :     TABGeomType m_nType;
     419             :     GInt32 m_nId;
     420             :     GInt32 m_nMinX; /* Object MBR */
     421             :     GInt32 m_nMinY;
     422             :     GInt32 m_nMaxX;
     423             :     GInt32 m_nMaxY;
     424             : 
     425      552130 :     TABMAPObjHdr()
     426      552130 :         : m_nType(TAB_GEOM_NONE), m_nId(0), m_nMinX(0), m_nMinY(0), m_nMaxX(0),
     427      552130 :           m_nMaxY(0)
     428             :     {
     429      552130 :     }
     430             : 
     431      552130 :     virtual ~TABMAPObjHdr()
     432      552130 :     {
     433      552130 :     }
     434             : 
     435             :     static TABMAPObjHdr *NewObj(TABGeomType nNewObjType, GInt32 nId = 0);
     436             :     static TABMAPObjHdr *ReadNextObj(TABMAPObjectBlock *poObjBlock,
     437             :                                      TABMAPHeaderBlock *poHeader);
     438             : 
     439             :     GBool IsCompressedType();
     440             :     int WriteObjTypeAndId(TABMAPObjectBlock *);
     441             :     void SetMBR(GInt32 nMinX, GInt32 nMinY, GInt32 nMaxX, GInt32 mMaxY);
     442             : 
     443           0 :     virtual int WriteObj(TABMAPObjectBlock *)
     444             :     {
     445           0 :         return -1;
     446             :     }
     447             : 
     448             :     //  protected:
     449           0 :     virtual int ReadObj(TABMAPObjectBlock *)
     450             :     {
     451           0 :         return -1;
     452             :     }
     453             : };
     454             : 
     455             : class TABMAPObjHdrWithCoord : public TABMAPObjHdr
     456             : {
     457             :   public:
     458             :     GInt32 m_nCoordBlockPtr = 0;
     459             :     GInt32 m_nCoordDataSize = 0;
     460             : 
     461             :     /* Eventually this class may have methods to help maintaining refs to
     462             :      * coord. blocks when splitting object blocks.
     463             :      */
     464             : };
     465             : 
     466             : class TABMAPObjNone final : public TABMAPObjHdr
     467             : {
     468             :   public:
     469         204 :     TABMAPObjNone()
     470         204 :     {
     471         204 :     }
     472             : 
     473         408 :     virtual ~TABMAPObjNone()
     474         204 :     {
     475         408 :     }
     476             : 
     477           0 :     virtual int WriteObj(TABMAPObjectBlock *) override
     478             :     {
     479           0 :         return 0;
     480             :     }
     481             : 
     482             :     //  protected:
     483         147 :     virtual int ReadObj(TABMAPObjectBlock *) override
     484             :     {
     485         147 :         return 0;
     486             :     }
     487             : };
     488             : 
     489             : class TABMAPObjPoint : public TABMAPObjHdr
     490             : {
     491             :   public:
     492             :     GInt32 m_nX;
     493             :     GInt32 m_nY;
     494             :     GByte m_nSymbolId;
     495             : 
     496      549491 :     TABMAPObjPoint() : m_nX(0), m_nY(0), m_nSymbolId(0)
     497             :     {
     498      549491 :     }
     499             : 
     500     1098966 :     virtual ~TABMAPObjPoint()
     501      549491 :     {
     502     1098966 :     }
     503             : 
     504             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     505             : 
     506             :     //  protected:
     507             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     508             : };
     509             : 
     510             : class TABMAPObjFontPoint : public TABMAPObjPoint
     511             : {
     512             :   public:
     513             :     GByte m_nPointSize;
     514             :     GInt16 m_nFontStyle;
     515             :     GByte m_nR;
     516             :     GByte m_nG;
     517             :     GByte m_nB;
     518             :     GInt16 m_nAngle; /* In tenths of degree */
     519             :     GByte m_nFontId;
     520             : 
     521           8 :     TABMAPObjFontPoint()
     522           8 :         : m_nPointSize(0), m_nFontStyle(0), m_nR(0), m_nG(0), m_nB(0),
     523           8 :           m_nAngle(0), m_nFontId(0)
     524             :     {
     525           8 :     }
     526             : 
     527          16 :     virtual ~TABMAPObjFontPoint()
     528           8 :     {
     529          16 :     }
     530             : 
     531             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     532             : 
     533             :     //  protected:
     534             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     535             : };
     536             : 
     537             : class TABMAPObjCustomPoint final : public TABMAPObjPoint
     538             : {
     539             :   public:
     540             :     GByte m_nUnknown_;
     541             :     GByte m_nCustomStyle;
     542             :     GByte m_nFontId;
     543             : 
     544           8 :     TABMAPObjCustomPoint() : m_nUnknown_(0), m_nCustomStyle(0), m_nFontId(0)
     545             :     {
     546           8 :     }
     547             : 
     548          16 :     virtual ~TABMAPObjCustomPoint()
     549           8 :     {
     550          16 :     }
     551             : 
     552             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     553             : 
     554             :     //  protected:
     555             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     556             : };
     557             : 
     558             : class TABMAPObjLine final : public TABMAPObjHdr
     559             : {
     560             :   public:
     561             :     GInt32 m_nX1;
     562             :     GInt32 m_nY1;
     563             :     GInt32 m_nX2;
     564             :     GInt32 m_nY2;
     565             :     GByte m_nPenId;
     566             : 
     567          44 :     TABMAPObjLine() : m_nX1(0), m_nY1(0), m_nX2(0), m_nY2(0), m_nPenId(0)
     568             :     {
     569          44 :     }
     570             : 
     571          88 :     virtual ~TABMAPObjLine()
     572          44 :     {
     573          88 :     }
     574             : 
     575             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     576             : 
     577             :     //  protected:
     578             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     579             : };
     580             : 
     581             : class TABMAPObjPLine final : public TABMAPObjHdrWithCoord
     582             : {
     583             :   public:
     584             :     GInt32 m_numLineSections; /* MULTIPLINE/REGION only. Not in PLINE */
     585             :     GInt32 m_nLabelX;         /* Centroid/label location */
     586             :     GInt32 m_nLabelY;
     587             :     GInt32 m_nComprOrgX; /* Present only in compressed coord. case */
     588             :     GInt32 m_nComprOrgY;
     589             :     GByte m_nPenId;
     590             :     GByte m_nBrushId;
     591             :     GBool m_bSmooth; /* TRUE if (m_nCoordDataSize & 0x80000000) */
     592             : 
     593        2347 :     TABMAPObjPLine()
     594        2347 :         : m_numLineSections(0), m_nLabelX(0), m_nLabelY(0), m_nComprOrgX(0),
     595        2347 :           m_nComprOrgY(0), m_nPenId(0), m_nBrushId(0), m_bSmooth(0)
     596             :     {
     597        2347 :     }
     598             : 
     599        4686 :     virtual ~TABMAPObjPLine()
     600        2347 :     {
     601        4686 :     }
     602             : 
     603             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     604             : 
     605             :     //  protected:
     606             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     607             : };
     608             : 
     609             : class TABMAPObjRectEllipse final : public TABMAPObjHdr
     610             : {
     611             :   public:
     612             :     GInt32 m_nCornerWidth; /* For rounded rect only */
     613             :     GInt32 m_nCornerHeight;
     614             :     GByte m_nPenId;
     615             :     GByte m_nBrushId;
     616             : 
     617          12 :     TABMAPObjRectEllipse()
     618          12 :         : m_nCornerWidth(0), m_nCornerHeight(0), m_nPenId(0), m_nBrushId(0)
     619             :     {
     620          12 :     }
     621             : 
     622          24 :     virtual ~TABMAPObjRectEllipse()
     623          12 :     {
     624          24 :     }
     625             : 
     626             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     627             : 
     628             :     //  protected:
     629             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     630             : };
     631             : 
     632             : class TABMAPObjArc final : public TABMAPObjHdr
     633             : {
     634             :   public:
     635             :     GInt32 m_nStartAngle;
     636             :     GInt32 m_nEndAngle;
     637             :     GInt32 m_nArcEllipseMinX; /* MBR of the arc defining ellipse */
     638             :     GInt32 m_nArcEllipseMinY; /* Only present in arcs            */
     639             :     GInt32 m_nArcEllipseMaxX;
     640             :     GInt32 m_nArcEllipseMaxY;
     641             :     GByte m_nPenId;
     642             : 
     643           8 :     TABMAPObjArc()
     644           8 :         : m_nStartAngle(0), m_nEndAngle(0), m_nArcEllipseMinX(0),
     645             :           m_nArcEllipseMinY(0), m_nArcEllipseMaxX(0), m_nArcEllipseMaxY(0),
     646           8 :           m_nPenId(0)
     647             :     {
     648           8 :     }
     649             : 
     650          16 :     virtual ~TABMAPObjArc()
     651           8 :     {
     652          16 :     }
     653             : 
     654             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     655             : 
     656             :     //  protected:
     657             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     658             : };
     659             : 
     660             : class TABMAPObjText final : public TABMAPObjHdrWithCoord
     661             : {
     662             :   public:
     663             :     /* String and its len stored in the nCoordPtr and nCoordSize */
     664             : 
     665             :     GInt16 m_nTextAlignment;
     666             :     GInt32 m_nAngle;
     667             :     GInt16 m_nFontStyle;
     668             : 
     669             :     GByte m_nFGColorR;
     670             :     GByte m_nFGColorG;
     671             :     GByte m_nFGColorB;
     672             :     GByte m_nBGColorR;
     673             :     GByte m_nBGColorG;
     674             :     GByte m_nBGColorB;
     675             : 
     676             :     GInt32 m_nLineEndX;
     677             :     GInt32 m_nLineEndY;
     678             : 
     679             :     GInt32 m_nHeight;
     680             :     GByte m_nFontId;
     681             : 
     682             :     GByte m_nPenId;
     683             : 
     684          12 :     TABMAPObjText()
     685          12 :         : m_nTextAlignment(0), m_nAngle(0), m_nFontStyle(0), m_nFGColorR(0),
     686             :           m_nFGColorG(0), m_nFGColorB(0), m_nBGColorR(0), m_nBGColorG(0),
     687             :           m_nBGColorB(0), m_nLineEndX(0), m_nLineEndY(0), m_nHeight(0),
     688          12 :           m_nFontId(0), m_nPenId(0)
     689             :     {
     690          12 :     }
     691             : 
     692          24 :     virtual ~TABMAPObjText()
     693          12 :     {
     694          24 :     }
     695             : 
     696             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     697             : 
     698             :     //  protected:
     699             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     700             : };
     701             : 
     702             : class TABMAPObjMultiPoint final : public TABMAPObjHdrWithCoord
     703             : {
     704             :   public:
     705             :     GInt32 m_nNumPoints;
     706             :     GInt32 m_nComprOrgX; /* Present only in compressed coord. case */
     707             :     GInt32 m_nComprOrgY;
     708             :     GByte m_nSymbolId;
     709             :     GInt32 m_nLabelX; /* Not sure if it is a label point, but */
     710             :     GInt32 m_nLabelY; /* it is similar to what we find in PLINE */
     711             : 
     712           8 :     TABMAPObjMultiPoint()
     713           8 :         : m_nNumPoints(0), m_nComprOrgX(0), m_nComprOrgY(0), m_nSymbolId(0),
     714           8 :           m_nLabelX(0), m_nLabelY(0)
     715             :     {
     716           8 :     }
     717             : 
     718          12 :     virtual ~TABMAPObjMultiPoint()
     719           8 :     {
     720          12 :     }
     721             : 
     722             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     723             : 
     724             :     //  protected:
     725             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     726             : };
     727             : 
     728             : class TABMAPObjCollection final : public TABMAPObjHdrWithCoord
     729             : {
     730             :   public:
     731             :     GInt32 m_nRegionDataSize;
     732             :     GInt32 m_nPolylineDataSize;
     733             :     GInt32 m_nMPointDataSize;
     734             :     GInt32 m_nComprOrgX; /* Present only in compressed coord. case */
     735             :     GInt32 m_nComprOrgY;
     736             :     GInt32 m_nNumMultiPoints;
     737             :     GInt32 m_nNumRegSections;
     738             :     GInt32 m_nNumPLineSections;
     739             : 
     740             :     GByte m_nMultiPointSymbolId;
     741             :     GByte m_nRegionPenId;
     742             :     GByte m_nRegionBrushId;
     743             :     GByte m_nPolylinePenId;
     744             : 
     745           4 :     TABMAPObjCollection()
     746           4 :         : m_nRegionDataSize(0), m_nPolylineDataSize(0), m_nMPointDataSize(0),
     747             :           m_nComprOrgX(0), m_nComprOrgY(0), m_nNumMultiPoints(0),
     748             :           m_nNumRegSections(0), m_nNumPLineSections(0),
     749             :           m_nMultiPointSymbolId(0), m_nRegionPenId(0), m_nRegionBrushId(0),
     750           4 :           m_nPolylinePenId(0)
     751             :     {
     752           4 :     }
     753             : 
     754           8 :     virtual ~TABMAPObjCollection()
     755           4 :     {
     756           8 :     }
     757             : 
     758             :     virtual int WriteObj(TABMAPObjectBlock *) override;
     759             : 
     760             :     //  protected:
     761             :     virtual int ReadObj(TABMAPObjectBlock *) override;
     762             : 
     763             :   private:
     764             :     // private copy ctor and assignment operator to prevent shallow copying
     765             :     TABMAPObjCollection &operator=(const TABMAPObjCollection &rhs);
     766             :     TABMAPObjCollection(const TABMAPObjCollection &rhs);
     767             : };
     768             : 
     769             : /*=====================================================================
     770             :           Classes to handle .MAP files low-level blocks
     771             :  =====================================================================*/
     772             : 
     773             : typedef struct TABBlockRef_t
     774             : {
     775             :     GInt32 nBlockPtr;
     776             :     struct TABBlockRef_t *psPrev;
     777             :     struct TABBlockRef_t *psNext;
     778             : } TABBlockRef;
     779             : 
     780             : /*---------------------------------------------------------------------
     781             :  *                      class TABBinBlockManager
     782             :  *
     783             :  * This class is used to keep track of allocated blocks and is used
     784             :  * by various classes that need to allocate a new block in a .MAP file.
     785             :  *--------------------------------------------------------------------*/
     786             : class TABBinBlockManager
     787             : {
     788             :     CPL_DISALLOW_COPY_ASSIGN(TABBinBlockManager)
     789             : 
     790             :   protected:
     791             :     int m_nBlockSize;
     792             :     GInt32 m_nLastAllocatedBlock;
     793             :     TABBlockRef *m_psGarbageBlocksFirst;
     794             :     TABBlockRef *m_psGarbageBlocksLast;
     795             :     char m_szName[32]; /* for debug purposes */
     796             : 
     797             :   public:
     798             :     TABBinBlockManager();
     799             :     ~TABBinBlockManager();
     800             : 
     801             :     void SetBlockSize(int nBlockSize);
     802             : 
     803             :     int GetBlockSize() const
     804             :     {
     805             :         return m_nBlockSize;
     806             :     }
     807             : 
     808             :     GInt32 AllocNewBlock(const char *pszReason = "");
     809             :     void Reset();
     810             : 
     811        1202 :     void SetLastPtr(int nBlockPtr)
     812             :     {
     813        1202 :         m_nLastAllocatedBlock = nBlockPtr;
     814        1202 :     }
     815             : 
     816             :     void PushGarbageBlockAsFirst(GInt32 nBlockPtr);
     817             :     void PushGarbageBlockAsLast(GInt32 nBlockPtr);
     818             :     GInt32 GetFirstGarbageBlock();
     819             :     GInt32 PopGarbageBlock();
     820             : 
     821             :     void SetName(const char *pszName);
     822             : };
     823             : 
     824             : /*---------------------------------------------------------------------
     825             :  *                      class TABRawBinBlock
     826             :  *
     827             :  * This is the base class used for all other data block types... it
     828             :  * contains all the base functions to handle binary data.
     829             :  *--------------------------------------------------------------------*/
     830             : 
     831             : class TABRawBinBlock
     832             : {
     833             :     CPL_DISALLOW_COPY_ASSIGN(TABRawBinBlock)
     834             : 
     835             :   protected:
     836             :     VSILFILE *m_fp;      /* Associated file handle               */
     837             :     TABAccess m_eAccess; /* Read/Write access mode               */
     838             : 
     839             :     int m_nBlockType;
     840             : 
     841             :     GByte *m_pabyBuf;       /* Buffer to contain the block's data    */
     842             :     int m_nBlockSize;       /* Size of current block (and buffer)    */
     843             :     int m_nSizeUsed;        /* Number of bytes used in buffer        */
     844             :     GBool m_bHardBlockSize; /* TRUE=Blocks MUST always be nSize bytes  */
     845             :                             /* FALSE=last block may be less than nSize */
     846             :     int m_nFileOffset;      /* Location of current block in the file */
     847             :     int m_nCurPos;          /* Next byte to read from m_pabyBuf[]    */
     848             :     int m_nFirstBlockPtr;   /* Size of file header when different from */
     849             :                             /* block size (used by GotoByteInFile())   */
     850             :     int m_nFileSize;
     851             : 
     852             :     int m_bModified; /* Used only to detect changes        */
     853             : 
     854             :   public:
     855             :     explicit TABRawBinBlock(TABAccess eAccessMode = TABRead,
     856             :                             GBool bHardBlockSize = TRUE);
     857             :     virtual ~TABRawBinBlock();
     858             : 
     859             :     virtual int ReadFromFile(VSILFILE *fpSrc, int nOffset, int nSize);
     860             :     virtual int CommitToFile();
     861             :     int CommitAsDeleted(GInt32 nNextBlockPtr);
     862             : 
     863             :     virtual int InitBlockFromData(GByte *pabyBuf, int nBlockSize, int nSizeUsed,
     864             :                                   GBool bMakeCopy = TRUE,
     865             :                                   VSILFILE *fpSrc = nullptr, int nOffset = 0);
     866             :     virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
     867             :                              int nFileOffset = 0);
     868             : 
     869             :     int GetBlockType();
     870             : 
     871           2 :     virtual int GetBlockClass()
     872             :     {
     873           2 :         return TAB_RAWBIN_BLOCK;
     874             :     }
     875             : 
     876      429315 :     GInt32 GetStartAddress()
     877             :     {
     878      429315 :         return m_nFileOffset;
     879             :     }
     880             : #ifdef DEBUG
     881             :     virtual void Dump(FILE *fpOut = nullptr);
     882             : #endif
     883             :     static void DumpBytes(GInt32 nValue, int nOffset = 0,
     884             :                           FILE *fpOut = nullptr);
     885             : 
     886             :     int GotoByteRel(int nOffset);
     887             :     int GotoByteInBlock(int nOffset);
     888             :     int GotoByteInFile(int nOffset, GBool bForceReadFromFile = FALSE,
     889             :                        GBool bOffsetIsEndOfData = FALSE);
     890             :     void SetFirstBlockPtr(int nOffset);
     891             : 
     892             :     int GetNumUnusedBytes();
     893             :     int GetFirstUnusedByteOffset();
     894             :     int GetCurAddress();
     895             : 
     896             :     virtual int ReadBytes(int numBytes, GByte *pabyDstBuf);
     897             :     GByte ReadByte();
     898             :     // cppcheck-suppress functionStatic
     899             :     GInt16 ReadInt16();
     900             :     // cppcheck-suppress functionStatic
     901             :     GInt32 ReadInt32();
     902             :     // cppcheck-suppress functionStatic
     903             :     GInt64 ReadInt64();
     904             :     // cppcheck-suppress functionStatic
     905             :     float ReadFloat();
     906             :     // cppcheck-suppress functionStatic
     907             :     double ReadDouble();
     908             : 
     909             :     virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf);
     910             :     int WriteByte(GByte byValue);
     911             :     // cppcheck-suppress functionStatic
     912             :     int WriteInt16(GInt16 n16Value);
     913             :     // cppcheck-suppress functionStatic
     914             :     int WriteInt32(GInt32 n32Value);
     915             :     // cppcheck-suppress functionStatic
     916             :     int WriteInt64(GInt64 n64Value);
     917             :     // cppcheck-suppress functionStatic
     918             :     int WriteFloat(float fValue);
     919             :     // cppcheck-suppress functionStatic
     920             :     int WriteDouble(double dValue);
     921             :     int WriteZeros(int nBytesToWrite);
     922             :     int WritePaddedString(int nFieldSize, const char *pszString);
     923             : 
     924             :     void SetModifiedFlag(GBool bModified)
     925             :     {
     926             :         m_bModified = bModified;
     927             :     }
     928             : 
     929             :     // This semi-private method gives a direct access to the internal
     930             :     // buffer... to be used with extreme care!!!!!!!!!
     931         272 :     GByte *GetCurDataPtr()
     932             :     {
     933         272 :         return (m_pabyBuf + m_nCurPos);
     934             :     }
     935             : };
     936             : 
     937             : /*---------------------------------------------------------------------
     938             :  *                      class TABMAPHeaderBlock
     939             :  *
     940             :  * Class to handle Read/Write operation on .MAP Header Blocks
     941             :  *--------------------------------------------------------------------*/
     942             : 
     943             : class TABMAPHeaderBlock final : public TABRawBinBlock
     944             : {
     945             :     void InitMembersWithDefaultValues();
     946             :     void UpdatePrecision();
     947             : 
     948             :   protected:
     949             : #if defined(__GNUC__)
     950             : #pragma GCC diagnostic push
     951             : #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
     952             : #endif
     953             :     TABProjInfo m_sProj{};
     954             : #if defined(__GNUC__)
     955             : #pragma GCC diagnostic pop
     956             : #endif
     957             : 
     958             :   public:
     959             :     explicit TABMAPHeaderBlock(TABAccess eAccessMode = TABRead);
     960             :     virtual ~TABMAPHeaderBlock();
     961             : 
     962             :     virtual int CommitToFile() override;
     963             : 
     964             :     virtual int InitBlockFromData(GByte *pabyBuf, int nBlockSize, int nSizeUsed,
     965             :                                   GBool bMakeCopy = TRUE,
     966             :                                   VSILFILE *fpSrc = nullptr,
     967             :                                   int nOffset = 0) override;
     968             :     virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
     969             :                              int nFileOffset = 0) override;
     970             : 
     971        2618 :     virtual int GetBlockClass() override
     972             :     {
     973        2618 :         return TABMAP_HEADER_BLOCK;
     974             :     }
     975             : 
     976             :     int Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY);
     977             :     int Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
     978             :                      GBool bIgnoreOverflow = FALSE);
     979             :     int ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY, int nDeltaX,
     980             :                           int nDeltaY, double &dX, double &dY);
     981             :     int Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY);
     982             :     int Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY);
     983             :     int SetCoordsysBounds(double dXMin, double dYMin, double dXMax,
     984             :                           double dYMax);
     985             : 
     986             :     int GetMapObjectSize(int nObjType);
     987             :     GBool MapObjectUsesCoordBlock(int nObjType);
     988             : 
     989             :     int GetProjInfo(TABProjInfo *psProjInfo);
     990             :     int SetProjInfo(TABProjInfo *psProjInfo);
     991             : 
     992             : #ifdef DEBUG
     993             :     virtual void Dump(FILE *fpOut = nullptr) override;
     994             : #endif
     995             : 
     996             :     // Instead of having over 30 get/set methods, we'll make all data
     997             :     // members public and we will initialize them in the overloaded
     998             :     // LoadFromFile().  For this reason, this class should be used with care.
     999             : 
    1000             :     GInt16 m_nMAPVersionNumber{};
    1001             :     GInt16 m_nRegularBlockSize{};
    1002             : 
    1003             :     double m_dCoordsys2DistUnits{};
    1004             :     GInt32 m_nXMin{};
    1005             :     GInt32 m_nYMin{};
    1006             :     GInt32 m_nXMax{};
    1007             :     GInt32 m_nYMax{};
    1008             :     GBool m_bIntBoundsOverflow{};  // Set to TRUE if coordinates
    1009             :                                    // outside of bounds were written
    1010             : 
    1011             :     GInt32 m_nFirstIndexBlock{};
    1012             :     GInt32 m_nFirstGarbageBlock{};
    1013             :     GInt32 m_nFirstToolBlock{};
    1014             :     GInt32 m_numPointObjects{};
    1015             :     GInt32 m_numLineObjects{};
    1016             :     GInt32 m_numRegionObjects{};
    1017             :     GInt32 m_numTextObjects{};
    1018             :     GInt32 m_nMaxCoordBufSize{};
    1019             : 
    1020             :     GByte m_nDistUnitsCode{};  // See Appendix F
    1021             :     GByte m_nMaxSpIndexDepth{};
    1022             :     GByte m_nCoordPrecision{};  // Num. decimal places on coord.
    1023             :     GByte m_nCoordOriginQuadrant{};
    1024             :     GByte m_nReflectXAxisCoord{};
    1025             :     GByte m_nMaxObjLenArrayId{};  // See gabyObjLenArray[]
    1026             :     GByte m_numPenDefs{};
    1027             :     GByte m_numBrushDefs{};
    1028             :     GByte m_numSymbolDefs{};
    1029             :     GByte m_numFontDefs{};
    1030             :     GInt16 m_numMapToolBlocks{};
    1031             : 
    1032             :     double m_XScale{};
    1033             :     double m_YScale{};
    1034             :     double m_XDispl{};
    1035             :     double m_YDispl{};
    1036             :     double m_XPrecision{};  // maximum achievable precision along X axis
    1037             :                             // depending on bounds extent
    1038             :     double m_YPrecision{};  // maximum achievable precision along Y axis
    1039             :                             // depending on bounds extent
    1040             : };
    1041             : 
    1042             : /*---------------------------------------------------------------------
    1043             :  *                      class TABMAPIndexBlock
    1044             :  *
    1045             :  * Class to handle Read/Write operation on .MAP Index Blocks (Type 01)
    1046             :  *--------------------------------------------------------------------*/
    1047             : 
    1048             : class TABMAPIndexBlock final : public TABRawBinBlock
    1049             : {
    1050             :     CPL_DISALLOW_COPY_ASSIGN(TABMAPIndexBlock)
    1051             : 
    1052             :   protected:
    1053             :     int m_numEntries;
    1054             :     TABMAPIndexEntry m_asEntries[TAB_MAX_ENTRIES_INDEX_BLOCK];
    1055             : 
    1056             :     int ReadNextEntry(TABMAPIndexEntry *psEntry);
    1057             :     int WriteNextEntry(TABMAPIndexEntry *psEntry);
    1058             : 
    1059             :     // Use these to keep track of current block's MBR
    1060             :     GInt32 m_nMinX;
    1061             :     GInt32 m_nMinY;
    1062             :     GInt32 m_nMaxX;
    1063             :     GInt32 m_nMaxY;
    1064             : 
    1065             :     TABBinBlockManager *m_poBlockManagerRef;
    1066             : 
    1067             :     // Info about child currently loaded
    1068             :     std::unique_ptr<TABMAPIndexBlock> m_poCurChild{};
    1069             :     int m_nCurChildIndex;
    1070             :     // Also need to know about its parent
    1071             :     TABMAPIndexBlock *m_poParentRef;
    1072             : 
    1073             :     int ReadAllEntries();
    1074             : 
    1075       35733 :     int GetMaxEntries() const
    1076             :     {
    1077       35733 :         return ((m_nBlockSize - 4) / 20);
    1078             :     }
    1079             : 
    1080             :   public:
    1081             :     explicit TABMAPIndexBlock(TABAccess eAccessMode = TABRead);
    1082             :     virtual ~TABMAPIndexBlock();
    1083             : 
    1084             :     virtual int InitBlockFromData(GByte *pabyBuf, int nBlockSize, int nSizeUsed,
    1085             :                                   GBool bMakeCopy = TRUE,
    1086             :                                   VSILFILE *fpSrc = nullptr,
    1087             :                                   int nOffset = 0) override;
    1088             :     virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
    1089             :                              int nFileOffset = 0) override;
    1090             :     virtual int CommitToFile() override;
    1091             : 
    1092       10847 :     virtual int GetBlockClass() override
    1093             :     {
    1094       10847 :         return TABMAP_INDEX_BLOCK;
    1095             :     }
    1096             : 
    1097             :     void UnsetCurChild();
    1098             : 
    1099             :     int GetNumFreeEntries();
    1100             : 
    1101      452905 :     int GetNumEntries()
    1102             :     {
    1103      452905 :         return m_numEntries;
    1104             :     }
    1105             : 
    1106             :     TABMAPIndexEntry *GetEntry(int iIndex);
    1107             :     int AddEntry(GInt32 XMin, GInt32 YMin, GInt32 XMax, GInt32 YMax,
    1108             :                  GInt32 nBlockPtr, GBool bAddInThisNodeOnly = FALSE);
    1109             :     int GetCurMaxDepth();
    1110             :     void GetMBR(GInt32 &nXMin, GInt32 &nYMin, GInt32 &nXMax, GInt32 &nYMax);
    1111             :     void SetMBR(GInt32 nXMin, GInt32 nYMin, GInt32 nXMax, GInt32 nYMax);
    1112             : 
    1113        1069 :     GInt32 GetNodeBlockPtr()
    1114             :     {
    1115        1069 :         return GetStartAddress();
    1116             :     }
    1117             : 
    1118             :     void SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr);
    1119             :     void SetParentRef(TABMAPIndexBlock *poParent);
    1120             :     void SetCurChild(std::unique_ptr<TABMAPIndexBlock> &&poChild,
    1121             :                      int nChildIndex);
    1122             : 
    1123      517768 :     int GetCurChildIndex()
    1124             :     {
    1125      517768 :         return m_nCurChildIndex;
    1126             :     }
    1127             : 
    1128       21774 :     TABMAPIndexBlock *GetCurChild()
    1129             :     {
    1130       21774 :         return m_poCurChild.get();
    1131             :     }
    1132             : 
    1133       31898 :     TABMAPIndexBlock *GetParentRef()
    1134             :     {
    1135       31898 :         return m_poParentRef;
    1136             :     }
    1137             : 
    1138             :     int SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
    1139             :                   GInt32 nNewEntryXMax, GInt32 nNewEntryYMax);
    1140             :     int SplitRootNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
    1141             :                       GInt32 nNewEntryXMax, GInt32 nNewEntryYMax);
    1142             :     void UpdateCurChildMBR(GInt32 nXMin, GInt32 nYMin, GInt32 nXMax,
    1143             :                            GInt32 nYMax, GInt32 nBlockPtr);
    1144             :     void RecomputeMBR();
    1145             :     int InsertEntry(GInt32 XMin, GInt32 YMin, GInt32 XMax, GInt32 YMax,
    1146             :                     GInt32 nBlockPtr);
    1147             :     int ChooseSubEntryForInsert(GInt32 nXMin, GInt32 nYMin, GInt32 nXMax,
    1148             :                                 GInt32 nYMax);
    1149             :     GInt32 ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin, GInt32 nXMax,
    1150             :                                GInt32 nYMax);
    1151             :     int UpdateLeafEntry(GInt32 nBlockPtr, GInt32 nXMin, GInt32 nYMin,
    1152             :                         GInt32 nXMax, GInt32 nYMax);
    1153             :     int GetCurLeafEntryMBR(GInt32 nBlockPtr, GInt32 &nXMin, GInt32 &nYMin,
    1154             :                            GInt32 &nXMax, GInt32 &nYMax);
    1155             : 
    1156             :     // Static utility functions for node splitting, also used by
    1157             :     // the TABMAPObjectBlock class.
    1158             :     static double ComputeAreaDiff(GInt32 nNodeXMin, GInt32 nNodeYMin,
    1159             :                                   GInt32 nNodeXMax, GInt32 nNodeYMax,
    1160             :                                   GInt32 nEntryXMin, GInt32 nEntryYMin,
    1161             :                                   GInt32 nEntryXMax, GInt32 nEntryYMax);
    1162             :     static int PickSeedsForSplit(TABMAPIndexEntry *pasEntries, int numEntries,
    1163             :                                  int nSrcCurChildIndex, GInt32 nNewEntryXMin,
    1164             :                                  GInt32 nNewEntryYMin, GInt32 nNewEntryXMax,
    1165             :                                  GInt32 nNewEntryYMax, int &nSeed1,
    1166             :                                  int &nSeed2);
    1167             : #ifdef DEBUG
    1168             :     virtual void Dump(FILE *fpOut = nullptr) override;
    1169             : #endif
    1170             : };
    1171             : 
    1172             : /*---------------------------------------------------------------------
    1173             :  *                      class TABMAPObjectBlock
    1174             :  *
    1175             :  * Class to handle Read/Write operation on .MAP Object data Blocks (Type 02)
    1176             :  *--------------------------------------------------------------------*/
    1177             : 
    1178             : class TABMAPObjectBlock final : public TABRawBinBlock
    1179             : {
    1180             :     CPL_DISALLOW_COPY_ASSIGN(TABMAPObjectBlock)
    1181             : 
    1182             :   protected:
    1183             :     int m_numDataBytes; /* Excluding first 4 bytes header */
    1184             :     GInt32 m_nFirstCoordBlock;
    1185             :     GInt32 m_nLastCoordBlock;
    1186             :     GInt32 m_nCenterX;
    1187             :     GInt32 m_nCenterY;
    1188             : 
    1189             :     // In order to compute block center, we need to keep track of MBR
    1190             :     GInt32 m_nMinX;
    1191             :     GInt32 m_nMinY;
    1192             :     GInt32 m_nMaxX;
    1193             :     GInt32 m_nMaxY;
    1194             : 
    1195             :     // Keep track of current object either in read or read/write mode
    1196             :     int m_nCurObjectOffset;  // -1 if there is no current object.
    1197             :     int m_nCurObjectId;      // -1 if there is no current object.
    1198             :     TABGeomType
    1199             :         m_nCurObjectType;  // TAB_GEOM_UNSET if there is no current object.
    1200             : 
    1201             :     int m_bLockCenter;
    1202             : 
    1203             :   public:
    1204             :     explicit TABMAPObjectBlock(TABAccess eAccessMode = TABRead);
    1205             :     virtual ~TABMAPObjectBlock();
    1206             : 
    1207             :     virtual int CommitToFile() override;
    1208             :     virtual int InitBlockFromData(GByte *pabyBuf, int nBlockSize, int nSizeUsed,
    1209             :                                   GBool bMakeCopy = TRUE,
    1210             :                                   VSILFILE *fpSrc = nullptr,
    1211             :                                   int nOffset = 0) override;
    1212             :     virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
    1213             :                              int nFileOffset = 0) override;
    1214             : 
    1215       22661 :     virtual int GetBlockClass() override
    1216             :     {
    1217       22661 :         return TABMAP_OBJECT_BLOCK;
    1218             :     }
    1219             : 
    1220             :     virtual int ReadIntCoord(GBool bCompressed, GInt32 &nX, GInt32 &nY);
    1221             :     int WriteIntCoord(GInt32 nX, GInt32 nY, GBool bCompressed);
    1222             :     int WriteIntMBRCoord(GInt32 nXMin, GInt32 nYMin, GInt32 nXMax, GInt32 nYMax,
    1223             :                          GBool bCompressed);
    1224             :     int UpdateMBR(GInt32 nX, GInt32 nY);
    1225             : 
    1226             :     int PrepareNewObject(TABMAPObjHdr *poObjHdr);
    1227             :     int CommitNewObject(TABMAPObjHdr *poObjHdr);
    1228             : 
    1229             :     void AddCoordBlockRef(GInt32 nCoordBlockAddress);
    1230             : 
    1231         259 :     GInt32 GetFirstCoordBlockAddress()
    1232             :     {
    1233         259 :         return m_nFirstCoordBlock;
    1234             :     }
    1235             : 
    1236       11274 :     GInt32 GetLastCoordBlockAddress()
    1237             :     {
    1238       11274 :         return m_nLastCoordBlock;
    1239             :     }
    1240             : 
    1241             :     void GetMBR(GInt32 &nXMin, GInt32 &nYMin, GInt32 &nXMax, GInt32 &nYMax);
    1242             :     void SetMBR(GInt32 nXMin, GInt32 nYMin, GInt32 nXMax, GInt32 nYMax);
    1243             : 
    1244             :     void Rewind();
    1245             :     void ClearObjects();
    1246             :     void LockCenter();
    1247             :     void SetCenterFromOtherBlock(TABMAPObjectBlock *poOtherObjBlock);
    1248             :     int AdvanceToNextObject(TABMAPHeaderBlock *);
    1249             : 
    1250      364933 :     int GetCurObjectOffset()
    1251             :     {
    1252      364933 :         return m_nCurObjectOffset;
    1253             :     }
    1254             : 
    1255      385299 :     int GetCurObjectId()
    1256             :     {
    1257      385299 :         return m_nCurObjectId;
    1258             :     }
    1259             : 
    1260      385299 :     TABGeomType GetCurObjectType()
    1261             :     {
    1262      385299 :         return m_nCurObjectType;
    1263             :     }
    1264             : 
    1265             : #ifdef DEBUG
    1266           0 :     virtual void Dump(FILE *fpOut = nullptr) override
    1267             :     {
    1268           0 :         Dump(fpOut, FALSE);
    1269           0 :     }
    1270             : 
    1271             :     void Dump(FILE *fpOut, GBool bDetails);
    1272             : #endif
    1273             : };
    1274             : 
    1275             : /*---------------------------------------------------------------------
    1276             :  *                      class TABMAPCoordBlock
    1277             :  *
    1278             :  * Class to handle Read/Write operation on .MAP Coordinate Blocks (Type 03)
    1279             :  *--------------------------------------------------------------------*/
    1280             : 
    1281             : class TABMAPCoordBlock final : public TABRawBinBlock
    1282             : {
    1283             :     CPL_DISALLOW_COPY_ASSIGN(TABMAPCoordBlock)
    1284             : 
    1285             :   protected:
    1286             :     int m_numDataBytes; /* Excluding first 8 bytes header */
    1287             :     GInt32 m_nNextCoordBlock;
    1288             :     int m_numBlocksInChain;
    1289             : 
    1290             :     GInt32 m_nComprOrgX;
    1291             :     GInt32 m_nComprOrgY;
    1292             : 
    1293             :     // In order to compute block center, we need to keep track of MBR
    1294             :     GInt32 m_nMinX;
    1295             :     GInt32 m_nMinY;
    1296             :     GInt32 m_nMaxX;
    1297             :     GInt32 m_nMaxY;
    1298             : 
    1299             :     TABBinBlockManager *m_poBlockManagerRef;
    1300             : 
    1301             :     int m_nTotalDataSize;    // Num bytes in whole chain of blocks
    1302             :     int m_nFeatureDataSize;  // Num bytes for current feature coords
    1303             : 
    1304             :     GInt32 m_nFeatureXMin;  // Used to keep track of current
    1305             :     GInt32 m_nFeatureYMin;  // feature MBR.
    1306             :     GInt32 m_nFeatureXMax;
    1307             :     GInt32 m_nFeatureYMax;
    1308             : 
    1309             :   public:
    1310             :     explicit TABMAPCoordBlock(TABAccess eAccessMode = TABRead);
    1311             :     virtual ~TABMAPCoordBlock();
    1312             : 
    1313             :     virtual int InitBlockFromData(GByte *pabyBuf, int nBlockSize, int nSizeUsed,
    1314             :                                   GBool bMakeCopy = TRUE,
    1315             :                                   VSILFILE *fpSrc = nullptr,
    1316             :                                   int nOffset = 0) override;
    1317             :     virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
    1318             :                              int nFileOffset = 0) override;
    1319             :     virtual int CommitToFile() override;
    1320             : 
    1321         159 :     virtual int GetBlockClass() override
    1322             :     {
    1323         159 :         return TABMAP_COORD_BLOCK;
    1324             :     }
    1325             : 
    1326             :     void SetMAPBlockManagerRef(TABBinBlockManager *poBlockManager);
    1327             :     virtual int ReadBytes(int numBytes, GByte *pabyDstBuf) override;
    1328             :     virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf) override;
    1329             :     void SetComprCoordOrigin(GInt32 nX, GInt32 nY);
    1330             :     int ReadIntCoord(GBool bCompressed, GInt32 &nX, GInt32 &nY);
    1331             :     int ReadIntCoords(GBool bCompressed, int numCoords, GInt32 *panXY);
    1332             :     int ReadCoordSecHdrs(GBool bCompressed, int nVersion, int numSections,
    1333             :                          TABMAPCoordSecHdr *pasHdrs, GInt32 &numVerticesTotal);
    1334             :     int WriteCoordSecHdrs(int nVersion, int numSections,
    1335             :                           TABMAPCoordSecHdr *pasHdrs, GBool bCompressed);
    1336             : 
    1337             :     void SetNextCoordBlock(GInt32 nNextCoordBlockAddress);
    1338             : 
    1339           9 :     GInt32 GetNextCoordBlock()
    1340             :     {
    1341           9 :         return m_nNextCoordBlock;
    1342             :     }
    1343             : 
    1344             :     int WriteIntCoord(GInt32 nX, GInt32 nY, GBool bCompressed);
    1345             : 
    1346         207 :     int GetNumBlocksInChain()
    1347             :     {
    1348         207 :         return m_numBlocksInChain;
    1349             :     }
    1350             : 
    1351             :     void ResetTotalDataSize()
    1352             :     {
    1353             :         m_nTotalDataSize = 0;
    1354             :     }
    1355             : 
    1356             :     int GetTotalDataSize()
    1357             :     {
    1358             :         return m_nTotalDataSize;
    1359             :     }
    1360             : 
    1361             :     void SeekEnd();
    1362             :     void StartNewFeature();
    1363             : 
    1364         429 :     int GetFeatureDataSize()
    1365             :     {
    1366         429 :         return m_nFeatureDataSize;
    1367             :     }
    1368             : 
    1369             :     //__TODO__ Can we flush GetFeatureMBR() and all MBR tracking in this
    1370             :     // class???
    1371             :     void GetFeatureMBR(GInt32 &nXMin, GInt32 &nYMin, GInt32 &nXMax,
    1372             :                        GInt32 &nYMax);
    1373             : 
    1374             : #ifdef DEBUG
    1375             :     virtual void Dump(FILE *fpOut = nullptr) override;
    1376             : #endif
    1377             : };
    1378             : 
    1379             : /*---------------------------------------------------------------------
    1380             :  *                      class TABMAPToolBlock
    1381             :  *
    1382             :  * Class to handle Read/Write operation on .MAP Drawing Tool Blocks (Type 05)
    1383             :  *
    1384             :  * In addition to handling the I/O, this class also maintains the list
    1385             :  * of Tool definitions in memory.
    1386             :  *--------------------------------------------------------------------*/
    1387             : 
    1388             : class TABMAPToolBlock final : public TABRawBinBlock
    1389             : {
    1390             :     CPL_DISALLOW_COPY_ASSIGN(TABMAPToolBlock)
    1391             : 
    1392             :   protected:
    1393             :     int m_numDataBytes; /* Excluding first 8 bytes header */
    1394             :     GInt32 m_nNextToolBlock;
    1395             :     int m_numBlocksInChain;
    1396             : 
    1397             :     TABBinBlockManager *m_poBlockManagerRef;
    1398             : 
    1399             :   public:
    1400             :     explicit TABMAPToolBlock(TABAccess eAccessMode = TABRead);
    1401             :     virtual ~TABMAPToolBlock();
    1402             : 
    1403             :     virtual int InitBlockFromData(GByte *pabyBuf, int nBlockSize, int nSizeUsed,
    1404             :                                   GBool bMakeCopy = TRUE,
    1405             :                                   VSILFILE *fpSrc = nullptr,
    1406             :                                   int nOffset = 0) override;
    1407             :     virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
    1408             :                              int nFileOffset = 0) override;
    1409             :     virtual int CommitToFile() override;
    1410             : 
    1411           0 :     virtual int GetBlockClass() override
    1412             :     {
    1413           0 :         return TABMAP_TOOL_BLOCK;
    1414             :     }
    1415             : 
    1416             :     void SetMAPBlockManagerRef(TABBinBlockManager *poBlockManager);
    1417             :     virtual int ReadBytes(int numBytes, GByte *pabyDstBuf) override;
    1418             :     virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf) override;
    1419             : 
    1420             :     void SetNextToolBlock(GInt32 nNextCoordBlockAddress);
    1421             : 
    1422             :     GBool EndOfChain();
    1423             : 
    1424        1161 :     int GetNumBlocksInChain()
    1425             :     {
    1426        1161 :         return m_numBlocksInChain;
    1427             :     }
    1428             : 
    1429             :     int CheckAvailableSpace(int nToolType);
    1430             : 
    1431             : #ifdef DEBUG
    1432             :     virtual void Dump(FILE *fpOut = nullptr) override;
    1433             : #endif
    1434             : };
    1435             : 
    1436             : /*=====================================================================
    1437             :        Classes to deal with .MAP files at the MapInfo object level
    1438             :  =====================================================================*/
    1439             : 
    1440             : /*---------------------------------------------------------------------
    1441             :  *                      class TABIDFile
    1442             :  *
    1443             :  * Class to handle Read/Write operation on .ID files... the .ID file
    1444             :  * contains an index to the objects in the .MAP file by object id.
    1445             :  *--------------------------------------------------------------------*/
    1446             : 
    1447             : class TABIDFile
    1448             : {
    1449             :     CPL_DISALLOW_COPY_ASSIGN(TABIDFile)
    1450             : 
    1451             :   private:
    1452             :     char *m_pszFname;
    1453             :     VSILFILE *m_fp;
    1454             :     TABAccess m_eAccessMode;
    1455             : 
    1456             :     TABRawBinBlock *m_poIDBlock;
    1457             :     int m_nBlockSize;
    1458             :     GInt32 m_nMaxId;
    1459             : 
    1460             :   public:
    1461             :     TABIDFile();
    1462             :     ~TABIDFile();
    1463             : 
    1464             :     int Open(const char *pszFname, const char *pszAccess);
    1465             :     int Open(const char *pszFname, TABAccess eAccess);
    1466             :     int Close();
    1467             : 
    1468             :     int SyncToDisk();
    1469             : 
    1470             :     GInt32 GetObjPtr(GInt32 nObjId);
    1471             :     int SetObjPtr(GInt32 nObjId, GInt32 nObjPtr);
    1472             :     GInt32 GetMaxObjId();
    1473             : 
    1474             : #ifdef DEBUG
    1475             :     void Dump(FILE *fpOut = nullptr);
    1476             : #endif
    1477             : };
    1478             : 
    1479             : /*---------------------------------------------------------------------
    1480             :  *                      class TABMAPFile
    1481             :  *
    1482             :  * Class to handle Read/Write operation on .MAP files... this class hides
    1483             :  * all the dealings with blocks, indexes, etc.
    1484             :  * Use this class to deal with MapInfo objects directly.
    1485             :  *--------------------------------------------------------------------*/
    1486             : 
    1487             : class TABMAPFile
    1488             : {
    1489             :     CPL_DISALLOW_COPY_ASSIGN(TABMAPFile)
    1490             : 
    1491             :   private:
    1492             :     int m_nMinTABVersion;
    1493             :     char *m_pszFname;
    1494             :     VSILFILE *m_fp;
    1495             :     TABAccess m_eAccessMode;
    1496             : 
    1497             :     TABBinBlockManager m_oBlockManager{};
    1498             : 
    1499             :     TABMAPHeaderBlock *m_poHeader;
    1500             : 
    1501             :     // Members used to access objects using the spatial index
    1502             :     TABMAPIndexBlock *m_poSpIndex;
    1503             : 
    1504             :     // Defaults to FALSE, i.e. optimized spatial index
    1505             :     GBool m_bQuickSpatialIndexMode;
    1506             : 
    1507             :     // Member used to access objects using the object ids (.ID file)
    1508             :     TABIDFile *m_poIdIndex;
    1509             : 
    1510             :     // Current object data block.
    1511             :     TABMAPObjectBlock *m_poCurObjBlock;
    1512             :     int m_nCurObjPtr;
    1513             :     TABGeomType m_nCurObjType;
    1514             :     int m_nCurObjId;
    1515             :     TABMAPCoordBlock *m_poCurCoordBlock;
    1516             : 
    1517             :     // Drawing Tool Def. table (takes care of all drawing tools in memory)
    1518             :     TABToolDefTable *m_poToolDefTable;
    1519             : 
    1520             :     // Coordinates filter... default is MBR of the whole file
    1521             :     TABVertex m_sMinFilter{};
    1522             :     TABVertex m_sMaxFilter{};
    1523             :     GInt32 m_XMinFilter;
    1524             :     GInt32 m_YMinFilter;
    1525             :     GInt32 m_XMaxFilter;
    1526             :     GInt32 m_YMaxFilter;
    1527             : 
    1528             :     int m_bUpdated;
    1529             :     int m_bLastOpWasRead;
    1530             :     int m_bLastOpWasWrite;
    1531             : 
    1532             :     int CommitObjAndCoordBlocks(GBool bDeleteObjects = FALSE);
    1533             :     int LoadObjAndCoordBlocks(GInt32 nBlockPtr);
    1534             :     TABMAPObjectBlock *SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
    1535             :                                      int nSizeOfObjToAdd);
    1536             :     int MoveObjToBlock(TABMAPObjHdr *poObjHdr,
    1537             :                        TABMAPCoordBlock *poSrcCoordBlock,
    1538             :                        TABMAPObjectBlock *poDstObjBlock,
    1539             :                        TABMAPCoordBlock **ppoDstCoordBlock);
    1540             :     int PrepareCoordBlock(int nObjType, TABMAPObjectBlock *poObjBlock,
    1541             :                           TABMAPCoordBlock **ppoCoordBlock);
    1542             : 
    1543             :     int InitDrawingTools();
    1544             :     int CommitDrawingTools();
    1545             : 
    1546             :     int CommitSpatialIndex();
    1547             : 
    1548             :     // Stuff related to traversing spatial index.
    1549             :     TABMAPIndexBlock *m_poSpIndexLeaf;
    1550             : 
    1551             :     // Strings encoding
    1552             :     CPLString m_osEncoding;
    1553             : 
    1554             :     int LoadNextMatchingObjectBlock(int bFirstObject);
    1555             :     TABRawBinBlock *PushBlock(int nFileOffset);
    1556             : 
    1557             :     int ReOpenReadWrite();
    1558             : 
    1559             :   public:
    1560             :     explicit TABMAPFile(const char *pszEncoding);
    1561             :     ~TABMAPFile();
    1562             : 
    1563             :     int Open(const char *pszFname, const char *pszAccess,
    1564             :              GBool bNoErrorMsg = FALSE, int nBlockSizeForCreate = 512);
    1565             :     int Open(const char *pszFname, TABAccess eAccess, GBool bNoErrorMsg = FALSE,
    1566             :              int nBlockSizeForCreate = 512);
    1567             :     int Close();
    1568             : 
    1569             :     GUInt32 GetFileSize();
    1570             : 
    1571             :     int SyncToDisk();
    1572             : 
    1573             :     int SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode = TRUE);
    1574             : 
    1575             :     int Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY);
    1576             :     int Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
    1577             :                      GBool bIgnoreOverflow = FALSE);
    1578             :     int Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY);
    1579             :     int Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY);
    1580             :     void SetCoordFilter(TABVertex sMin, TABVertex sMax);
    1581             :     // cppcheck-suppress functionStatic
    1582             :     void GetCoordFilter(TABVertex &sMin, TABVertex &sMax) const;
    1583             :     void ResetCoordFilter();
    1584             :     int SetCoordsysBounds(double dXMin, double dYMin, double dXMax,
    1585             :                           double dYMax);
    1586             : 
    1587             :     GInt32 GetMaxObjId();
    1588             :     int MoveToObjId(int nObjId);
    1589             :     void UpdateMapHeaderInfo(TABGeomType nObjType);
    1590             :     int PrepareNewObj(TABMAPObjHdr *poObjHdr);
    1591             :     int PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr);
    1592             :     int PrepareNewObjViaObjBlock(TABMAPObjHdr *poObjHdr);
    1593             :     int CommitNewObj(TABMAPObjHdr *poObjHdr);
    1594             : 
    1595             :     void ResetReading();
    1596             :     int GetNextFeatureId(int nPrevId);
    1597             : 
    1598             :     int MarkAsDeleted();
    1599             : 
    1600             :     TABGeomType GetCurObjType();
    1601             :     int GetCurObjId();
    1602             :     TABMAPObjectBlock *GetCurObjBlock();
    1603             :     TABMAPCoordBlock *GetCurCoordBlock();
    1604             :     TABMAPCoordBlock *GetCoordBlock(int nFileOffset);
    1605             :     TABMAPHeaderBlock *GetHeaderBlock();
    1606             :     TABIDFile *GetIDFileRef();
    1607             :     TABRawBinBlock *GetIndexObjectBlock(int nFileOffset);
    1608             : 
    1609             :     int ReadPenDef(int nPenIndex, TABPenDef *psDef);
    1610             :     int ReadBrushDef(int nBrushIndex, TABBrushDef *psDef);
    1611             :     int ReadFontDef(int nFontIndex, TABFontDef *psDef);
    1612             :     int ReadSymbolDef(int nSymbolIndex, TABSymbolDef *psDef);
    1613             :     int WritePenDef(TABPenDef *psDef);
    1614             :     int WriteBrushDef(TABBrushDef *psDef);
    1615             :     int WriteFontDef(TABFontDef *psDef);
    1616             :     int WriteSymbolDef(TABSymbolDef *psDef);
    1617             : 
    1618             :     int GetMinTABFileVersion();
    1619             : 
    1620             :     const CPLString &GetEncoding() const;
    1621             :     void SetEncoding(const CPLString &);
    1622             : 
    1623             :     static bool IsValidObjType(int nObjType);
    1624             : 
    1625             : #ifdef DEBUG
    1626             :     void Dump(FILE *fpOut = nullptr);
    1627             :     void DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode, FILE *fpMIF,
    1628             :                                FILE *fpMID, int nParentId = -1,
    1629             :                                int nIndexInNode = -1, int nCurDepth = 0,
    1630             :                                int nMaxDepth = -1);
    1631             : #endif
    1632             : };
    1633             : 
    1634             : /*---------------------------------------------------------------------
    1635             :  *                      class TABINDNode
    1636             :  *
    1637             :  * An index node in a .IND file.
    1638             :  *
    1639             :  * This class takes care of reading child nodes as necessary when looking
    1640             :  * for a given key value in the index tree.
    1641             :  *--------------------------------------------------------------------*/
    1642             : 
    1643             : class TABINDNode
    1644             : {
    1645             :     CPL_DISALLOW_COPY_ASSIGN(TABINDNode)
    1646             : 
    1647             :   private:
    1648             :     VSILFILE *m_fp;
    1649             :     TABAccess m_eAccessMode;
    1650             :     TABINDNode *m_poCurChildNode;
    1651             :     TABINDNode *m_poParentNodeRef;
    1652             : 
    1653             :     TABBinBlockManager *m_poBlockManagerRef;
    1654             : 
    1655             :     int m_nSubTreeDepth;
    1656             :     int m_nKeyLength;
    1657             :     TABFieldType m_eFieldType;
    1658             :     GBool m_bUnique;
    1659             : 
    1660             :     GInt32 m_nCurDataBlockPtr;
    1661             :     int m_nCurIndexEntry;
    1662             :     TABRawBinBlock *m_poDataBlock;
    1663             :     int m_numEntriesInNode;
    1664             :     GInt32 m_nPrevNodePtr;
    1665             :     GInt32 m_nNextNodePtr;
    1666             : 
    1667             :     int GotoNodePtr(GInt32 nNewNodePtr);
    1668             :     GInt32 ReadIndexEntry(int nEntryNo, GByte *pKeyValue);
    1669             :     int IndexKeyCmp(const GByte *pKeyValue, int nEntryNo);
    1670             : 
    1671             :     int InsertEntry(GByte *pKeyValue, GInt32 nRecordNo,
    1672             :                     GBool bInsertAfterCurChild = FALSE,
    1673             :                     GBool bMakeNewEntryCurChild = FALSE);
    1674             :     int SetNodeBufferDirectly(int numEntries, GByte *pBuf,
    1675             :                               int nCurIndexEntry = 0,
    1676             :                               TABINDNode *poCurChild = nullptr);
    1677             :     GInt32 FindFirst(const GByte *pKeyValue, std::set<int> &oSetVisitedNodePtr);
    1678             : 
    1679             :   public:
    1680             :     explicit TABINDNode(TABAccess eAccessMode = TABRead);
    1681             :     ~TABINDNode();
    1682             : 
    1683             :     int InitNode(VSILFILE *fp, int nBlockPtr, int nKeyLength, int nSubTreeDepth,
    1684             :                  GBool bUnique, TABBinBlockManager *poBlockMgr = nullptr,
    1685             :                  TABINDNode *poParentNode = nullptr, int nPrevNodePtr = 0,
    1686             :                  int nNextNodePtr = 0);
    1687             : 
    1688             :     int SetFieldType(TABFieldType eType);
    1689             : 
    1690             :     TABFieldType GetFieldType()
    1691             :     {
    1692             :         return m_eFieldType;
    1693             :     }
    1694             : 
    1695           0 :     void SetUnique(GBool bUnique)
    1696             :     {
    1697           0 :         m_bUnique = bUnique;
    1698           0 :     }
    1699             : 
    1700             :     GBool IsUnique()
    1701             :     {
    1702             :         return m_bUnique;
    1703             :     }
    1704             : 
    1705         567 :     int GetKeyLength()
    1706             :     {
    1707         567 :         return m_nKeyLength;
    1708             :     }
    1709             : 
    1710          84 :     int GetSubTreeDepth()
    1711             :     {
    1712          84 :         return m_nSubTreeDepth;
    1713             :     }
    1714             : 
    1715          42 :     GInt32 GetNodeBlockPtr()
    1716             :     {
    1717          42 :         return m_nCurDataBlockPtr;
    1718             :     }
    1719             : 
    1720         988 :     int GetNumEntries()
    1721             :     {
    1722         988 :         return m_numEntriesInNode;
    1723             :     }
    1724             : 
    1725        1030 :     int GetMaxNumEntries()
    1726             :     {
    1727        1030 :         return (512 - 12) / (m_nKeyLength + 4);
    1728             :     }
    1729             : 
    1730             :     GInt32 FindFirst(const GByte *pKeyValue);
    1731             :     GInt32 FindNext(GByte *pKeyValue);
    1732             : 
    1733             :     int CommitToFile();
    1734             : 
    1735             :     int AddEntry(GByte *pKeyValue, GInt32 nRecordNo,
    1736             :                  GBool bAddInThisNodeOnly = FALSE,
    1737             :                  GBool bInsertAfterCurChild = FALSE,
    1738             :                  GBool bMakeNewEntryCurChild = FALSE);
    1739             :     int SplitNode();
    1740             :     int SplitRootNode();
    1741             :     GByte *GetNodeKey();
    1742             :     int UpdateCurChildEntry(GByte *pKeyValue, GInt32 nRecordNo);
    1743             :     int UpdateSplitChild(GByte *pKeyValue1, GInt32 nRecordNo1,
    1744             :                          GByte *pKeyValue2, GInt32 nRecordNo2,
    1745             :                          int nNewCurChildNo /* 1 or 2 */);
    1746             : 
    1747             :     int SetNodeBlockPtr(GInt32 nThisNodePtr);
    1748             :     int SetPrevNodePtr(GInt32 nPrevNodePtr);
    1749             :     int SetNextNodePtr(GInt32 nNextNodePtr);
    1750             : 
    1751             : #ifdef DEBUG
    1752             :     void Dump(FILE *fpOut = nullptr);
    1753             : #endif
    1754             : };
    1755             : 
    1756             : /*---------------------------------------------------------------------
    1757             :  *                      class TABINDFile
    1758             :  *
    1759             :  * Class to handle table field index (.IND) files... we use this
    1760             :  * class as the main entry point to open and search the table field indexes.
    1761             :  * Note that .IND files are supported for read access only.
    1762             :  *--------------------------------------------------------------------*/
    1763             : 
    1764             : class TABINDFile
    1765             : {
    1766             :     CPL_DISALLOW_COPY_ASSIGN(TABINDFile)
    1767             : 
    1768             :   private:
    1769             :     char *m_pszFname;
    1770             :     VSILFILE *m_fp;
    1771             :     TABAccess m_eAccessMode;
    1772             : 
    1773             :     TABBinBlockManager m_oBlockManager{};
    1774             : 
    1775             :     int m_numIndexes;
    1776             :     TABINDNode **m_papoIndexRootNodes;
    1777             :     GByte **m_papbyKeyBuffers;
    1778             : 
    1779             :     int ValidateIndexNo(int nIndexNumber);
    1780             :     int ReadHeader();
    1781             :     int WriteHeader();
    1782             : 
    1783             :   public:
    1784             :     TABINDFile();
    1785             :     ~TABINDFile();
    1786             : 
    1787             :     int Open(const char *pszFname, const char *pszAccess,
    1788             :              GBool bTestOpenNoError = FALSE);
    1789             :     int Close();
    1790             : 
    1791             :     int GetNumIndexes()
    1792             :     {
    1793             :         return m_numIndexes;
    1794             :     }
    1795             : 
    1796             :     int SetIndexFieldType(int nIndexNumber, TABFieldType eType);
    1797             :     int SetIndexUnique(int nIndexNumber, GBool bUnique = TRUE);
    1798             :     GByte *BuildKey(int nIndexNumber, GInt32 nValue);
    1799             :     GByte *BuildKey(int nIndexNumber, GInt64 nValue);
    1800             :     GByte *BuildKey(int nIndexNumber, const char *pszStr);
    1801             :     GByte *BuildKey(int nIndexNumber, double dValue);
    1802             :     GInt32 FindFirst(int nIndexNumber, GByte *pKeyValue);
    1803             :     GInt32 FindNext(int nIndexNumber, GByte *pKeyValue);
    1804             : 
    1805             :     int CreateIndex(TABFieldType eType, int nFieldSize);
    1806             :     int AddEntry(int nIndexNumber, GByte *pKeyValue, GInt32 nRecordNo);
    1807             : 
    1808             : #ifdef DEBUG
    1809             :     void Dump(FILE *fpOut = nullptr);
    1810             : #endif
    1811             : };
    1812             : 
    1813             : /*---------------------------------------------------------------------
    1814             :  *                      class TABDATFile
    1815             :  *
    1816             :  * Class to handle Read/Write operation on .DAT files... the .DAT file
    1817             :  * contains the table of attribute field values.
    1818             :  *--------------------------------------------------------------------*/
    1819             : 
    1820             : class TABDATFile
    1821             : {
    1822             :     CPL_DISALLOW_COPY_ASSIGN(TABDATFile)
    1823             : 
    1824             :   private:
    1825             :     char *m_pszFname;
    1826             :     VSILFILE *m_fp;
    1827             :     TABAccess m_eAccessMode;
    1828             :     TABTableType m_eTableType;
    1829             : 
    1830             :     TABRawBinBlock *m_poHeaderBlock;
    1831             :     int m_numFields;
    1832             :     TABDATFieldDef *m_pasFieldDef;
    1833             : 
    1834             :     TABRawBinBlock *m_poRecordBlock;
    1835             :     int m_nBlockSize;
    1836             :     int m_nRecordSize;
    1837             :     int m_nCurRecordId;
    1838             :     GBool m_bCurRecordDeletedFlag;
    1839             : 
    1840             :     GInt32 m_numRecords;
    1841             :     GInt32 m_nFirstRecordPtr;
    1842             :     GBool m_bWriteHeaderInitialized;
    1843             :     GBool m_bWriteEOF;
    1844             : 
    1845             :     int m_bUpdated;
    1846             :     CPLString m_osEncoding;
    1847             : 
    1848             :     int InitWriteHeader();
    1849             :     int WriteHeader();
    1850             : 
    1851             :     // We know that character strings are limited to 254 chars in MapInfo
    1852             :     // Using a buffer pr. class instance to avoid threading issues with the
    1853             :     // library
    1854             :     char m_szBuffer[256];
    1855             : 
    1856             :   public:
    1857             :     explicit TABDATFile(const char *pszEncoding);
    1858             :     ~TABDATFile();
    1859             : 
    1860             :     int Open(const char *pszFname, const char *pszAccess,
    1861             :              TABTableType eTableType = TABTableNative);
    1862             :     int Open(const char *pszFname, TABAccess eAccess,
    1863             :              TABTableType eTableType = TABTableNative);
    1864             :     int Close();
    1865             : 
    1866             :     int GetNumFields();
    1867             :     TABFieldType GetFieldType(int nFieldId);
    1868             :     int GetFieldWidth(int nFieldId);
    1869             :     int GetFieldPrecision(int nFieldId);
    1870             :     int ValidateFieldInfoFromTAB(int iField, const char *pszName,
    1871             :                                  TABFieldType eType, int nWidth,
    1872             :                                  int nPrecision);
    1873             : 
    1874             :     int AddField(const char *pszName, TABFieldType eType, int nWidth,
    1875             :                  int nPrecision = 0);
    1876             : 
    1877             :     int DeleteField(int iField);
    1878             :     int ReorderFields(int *panMap);
    1879             :     int AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn, int nFlags);
    1880             : 
    1881             :     int SyncToDisk();
    1882             : 
    1883             :     GInt32 GetNumRecords();
    1884             :     TABRawBinBlock *GetRecordBlock(int nRecordId);
    1885             : 
    1886     1035430 :     GBool IsCurrentRecordDeleted()
    1887             :     {
    1888     1035430 :         return m_bCurRecordDeletedFlag;
    1889             :     }
    1890             : 
    1891             :     int CommitRecordToFile();
    1892             : 
    1893             :     int MarkAsDeleted();
    1894             :     int MarkRecordAsExisting();
    1895             : 
    1896             :     const char *ReadCharField(int nWidth);
    1897             :     GInt32 ReadIntegerField(int nWidth);
    1898             :     GInt16 ReadSmallIntField(int nWidth);
    1899             :     GInt64 ReadLargeIntField(int nWidth);
    1900             :     double ReadFloatField(int nWidth);
    1901             :     double ReadDecimalField(int nWidth);
    1902             :     const char *ReadLogicalField(int nWidth);
    1903             :     const char *ReadDateField(int nWidth);
    1904             :     int ReadDateField(int nWidth, int *nYear, int *nMonth, int *nDay);
    1905             :     const char *ReadTimeField(int nWidth);
    1906             :     int ReadTimeField(int nWidth, int *nHour, int *nMinute, int *nSecond,
    1907             :                       int *nMS);
    1908             :     const char *ReadDateTimeField(int nWidth);
    1909             :     int ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay,
    1910             :                           int *nHour, int *nMinute, int *nSecond, int *nMS);
    1911             : 
    1912             :     int WriteCharField(const char *pszValue, int nWidth, TABINDFile *poINDFile,
    1913             :                        int nIndexNo);
    1914             :     int WriteIntegerField(GInt32 nValue, TABINDFile *poINDFile, int nIndexNo);
    1915             :     int WriteSmallIntField(GInt16 nValue, TABINDFile *poINDFile, int nIndexNo);
    1916             :     int WriteLargeIntField(GInt64 nValue, TABINDFile *poINDFile, int nIndexNo);
    1917             :     int WriteFloatField(double dValue, TABINDFile *poINDFile, int nIndexNo);
    1918             :     int WriteDecimalField(double dValue, int nWidth, int nPrecision,
    1919             :                           TABINDFile *poINDFile, int nIndexNo);
    1920             :     int WriteLogicalField(const char *pszValue, TABINDFile *poINDFile,
    1921             :                           int nIndexNo);
    1922             :     int WriteDateField(const char *pszValue, TABINDFile *poINDFile,
    1923             :                        int nIndexNo);
    1924             :     int WriteDateField(int nYear, int nMonth, int nDay, TABINDFile *poINDFile,
    1925             :                        int nIndexNo);
    1926             :     int WriteTimeField(const char *pszValue, TABINDFile *poINDFile,
    1927             :                        int nIndexNo);
    1928             :     int WriteTimeField(int nHour, int nMinute, int nSecond, int nMS,
    1929             :                        TABINDFile *poINDFile, int nIndexNo);
    1930             :     int WriteDateTimeField(const char *pszValue, TABINDFile *poINDFile,
    1931             :                            int nIndexNo);
    1932             :     int WriteDateTimeField(int nYear, int nMonth, int nDay, int nHour,
    1933             :                            int nMinute, int nSecond, int nMS,
    1934             :                            TABINDFile *poINDFile, int nIndexNo);
    1935             : 
    1936             :     const CPLString &GetEncoding() const;
    1937             :     void SetEncoding(const CPLString &);
    1938             : 
    1939             : #ifdef DEBUG
    1940             :     void Dump(FILE *fpOut = nullptr);
    1941             : #endif
    1942             : };
    1943             : 
    1944             : /*---------------------------------------------------------------------
    1945             :  *                      class TABRelation
    1946             :  *
    1947             :  * Class that maintains a relation between 2 tables through a field
    1948             :  * in each table (the SQL "where table1.field1=table2.field2" found in
    1949             :  * TABView datasets).
    1950             :  *
    1951             :  * An instance of this class is used to read data records from the
    1952             :  * combined tables as if they were a single one.
    1953             :  *--------------------------------------------------------------------*/
    1954             : 
    1955             : class TABRelation
    1956             : {
    1957             :     CPL_DISALLOW_COPY_ASSIGN(TABRelation)
    1958             : 
    1959             :   private:
    1960             :     /* Information about the main table.
    1961             :      */
    1962             :     TABFile *m_poMainTable;
    1963             :     char *m_pszMainFieldName;
    1964             :     int m_nMainFieldNo;
    1965             : 
    1966             :     /* Information about the related table.
    1967             :      * NOTE: The related field MUST be indexed.
    1968             :      */
    1969             :     TABFile *m_poRelTable;
    1970             :     char *m_pszRelFieldName;
    1971             :     int m_nRelFieldNo;
    1972             : 
    1973             :     TABINDFile *m_poRelINDFileRef;
    1974             :     int m_nRelFieldIndexNo;
    1975             : 
    1976             :     int m_nUniqueRecordNo;
    1977             : 
    1978             :     /* Main and Rel table field map:
    1979             :      * For each field in the source tables, -1 means that the field is not
    1980             :      * selected, and a value >=0 is the index of this field in the combined
    1981             :      * FeatureDefn
    1982             :      */
    1983             :     int *m_panMainTableFieldMap;
    1984             :     int *m_panRelTableFieldMap;
    1985             : 
    1986             :     OGRFeatureDefn *m_poDefn;
    1987             : 
    1988             :     void ResetAllMembers();
    1989             :     GByte *BuildFieldKey(TABFeature *poFeature, int nFieldNo,
    1990             :                          TABFieldType eType, int nIndexNo);
    1991             : 
    1992             :   public:
    1993             :     TABRelation();
    1994             :     ~TABRelation();
    1995             : 
    1996             :     int Init(const char *pszViewName, TABFile *poMainTable, TABFile *poRelTable,
    1997             :              const char *pszMainFieldName, const char *pszRelFieldName,
    1998             :              char **papszSelectedFields);
    1999             :     int CreateRelFields();
    2000             : 
    2001           4 :     OGRFeatureDefn *GetFeatureDefn()
    2002             :     {
    2003           4 :         return m_poDefn;
    2004             :     }
    2005             : 
    2006             :     TABFieldType GetNativeFieldType(int nFieldId);
    2007             :     TABFeature *GetFeature(int nFeatureId);
    2008             : 
    2009             :     int WriteFeature(TABFeature *poFeature, int nFeatureId = -1);
    2010             : 
    2011             :     int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
    2012             :                        TABFieldType *paeMapInfoNativeFieldTypes = nullptr);
    2013             :     int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
    2014             :                        int nWidth = 0, int nPrecision = 0,
    2015             :                        GBool bIndexed = FALSE, GBool bUnique = FALSE,
    2016             :                        int bApproxOK = TRUE);
    2017             : 
    2018             :     int SetFieldIndexed(int nFieldId);
    2019             :     GBool IsFieldIndexed(int nFieldId);
    2020             :     GBool IsFieldUnique(int nFieldId);
    2021             : 
    2022           0 :     const char *GetMainFieldName()
    2023             :     {
    2024           0 :         return m_pszMainFieldName;
    2025             :     }
    2026             : 
    2027           0 :     const char *GetRelFieldName()
    2028             :     {
    2029           0 :         return m_pszRelFieldName;
    2030             :     }
    2031             : };
    2032             : 
    2033             : /*---------------------------------------------------------------------
    2034             :  *                      class MIDDATAFile
    2035             :  *
    2036             :  * Class to handle a file pointer with a copy of the latest read line.
    2037             :  *
    2038             :  *--------------------------------------------------------------------*/
    2039             : 
    2040             : class MIDDATAFile
    2041             : {
    2042             :     CPL_DISALLOW_COPY_ASSIGN(MIDDATAFile)
    2043             : 
    2044             :   public:
    2045             :     explicit MIDDATAFile(const char *pszEncoding);
    2046             :     ~MIDDATAFile();
    2047             : 
    2048             :     int Open(const char *pszFname, const char *pszAccess);
    2049             :     int Close();
    2050             : 
    2051             :     const char *GetLine();
    2052             :     const char *GetLastLine();
    2053             :     char **GetTokenizedNextLine();
    2054             :     int Rewind();
    2055             :     void SaveLine(const char *pszLine);
    2056             :     const char *GetSavedLine();
    2057             :     void WriteLine(const char *, ...) CPL_PRINT_FUNC_FORMAT(2, 3);
    2058             :     static GBool IsValidFeature(const char *pszString);
    2059             : 
    2060             :     //  Translation information
    2061             :     void SetTranslation(double, double, double, double);
    2062             :     double GetXTrans(double);
    2063             :     double GetYTrans(double);
    2064             : 
    2065         642 :     double GetXMultiplier()
    2066             :     {
    2067         642 :         return m_dfXMultiplier;
    2068             :     }
    2069             : 
    2070         114 :     const char *GetDelimiter()
    2071             :     {
    2072         114 :         return m_pszDelimiter;
    2073             :     }
    2074             : 
    2075        1068 :     void SetDelimiter(const char *pszDelimiter)
    2076             :     {
    2077        1068 :         m_pszDelimiter = pszDelimiter;
    2078        1068 :     }
    2079             : 
    2080             :     void SetEof(GBool bEof);
    2081             :     GBool GetEof();
    2082             : 
    2083             :     const CPLString &GetEncoding() const;
    2084             :     void SetEncoding(const CPLString &);
    2085             : 
    2086             :   private:
    2087             :     VSILFILE *m_fp;
    2088             :     const char *m_pszDelimiter;
    2089             : 
    2090             :     std::string m_osLastRead{};
    2091             :     std::string m_osSavedLine{};
    2092             : 
    2093             :     char *m_pszFname;
    2094             :     TABAccess m_eAccessMode;
    2095             :     double m_dfXMultiplier;
    2096             :     double m_dfYMultiplier;
    2097             :     double m_dfXDisplacement;
    2098             :     double m_dfYDisplacement;
    2099             :     GBool m_bEof;
    2100             :     CPLString m_osEncoding;
    2101             : };
    2102             : 
    2103             : /*=====================================================================
    2104             :                         Function prototypes
    2105             :  =====================================================================*/
    2106             : 
    2107             : TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
    2108             :                                           int nSize,
    2109             :                                           GBool bHardBlockSize = TRUE,
    2110             :                                           TABAccess eAccessMode = TABRead);
    2111             : 
    2112             : #endif /* MITAB_PRIV_H_INCLUDED_ */

Generated by: LCOV version 1.14