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