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