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