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