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