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