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