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