1 : /**********************************************************************
2 : * $Id: mitab_middatafile.cpp,v 1.15 2010-10-12 19:02:40 aboudreault Exp $
3 : *
4 : * Name: mitab_datfile.cpp
5 : * Project: MapInfo TAB Read/Write library
6 : * Language: C++
7 : * Purpose: Implementation of the MIDDATAFile class used to handle
8 : * reading/writing of the MID/MIF files
9 : * Author: Stephane Villeneuve, stephane.v@videotron.ca
10 : *
11 : **********************************************************************
12 : * Copyright (c) 1999, 2000, Stephane Villeneuve
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_middatafile.cpp,v $
34 : * Revision 1.15 2010-10-12 19:02:40 aboudreault
35 : * Fixed incomplet patch to handle differently indented lines in mif files (gdal #3694)
36 : *
37 : * Revision 1.14 2006-01-27 13:54:06 fwarmerdam
38 : * fixed memory leak
39 : *
40 : * Revision 1.13 2005/10/04 19:36:10 dmorissette
41 : * Added support for reading collections from MIF files (bug 1126)
42 : *
43 : * Revision 1.12 2005/09/29 19:46:55 dmorissette
44 : * Use "\t" as default delimiter in constructor (Anthony D - bugs 1155 and 37)
45 : *
46 : * Revision 1.11 2004/05/20 13:50:06 fwarmerdam
47 : * Call CPLReadLine(NULL) in Close() method to clean up working buffer.
48 : *
49 : * Revision 1.10 2002/04/26 14:16:49 julien
50 : * Finishing the implementation of Multipoint (support for MIF)
51 : *
52 : * Revision 1.9 2002/04/24 18:37:39 daniel
53 : * Added return statement at end of GetLastLine()
54 : *
55 : * Revision 1.8 2002/04/22 13:49:09 julien
56 : * Add EOF validation in MIDDATAFile::GetLastLine() (Bug 819)
57 : *
58 : * Revision 1.7 2001/09/19 14:49:49 warmerda
59 : * use VSIRewind() instead of rewind()
60 : *
61 : * Revision 1.6 2001/01/22 16:03:58 warmerda
62 : * expanded tabs
63 : *
64 : * Revision 1.5 2000/01/15 22:30:44 daniel
65 : * Switch to MIT/X-Consortium OpenSource license
66 : *
67 : * Revision 1.4 1999/12/19 17:41:29 daniel
68 : * Fixed a memory leak
69 : *
70 : * Revision 1.3 1999/11/14 17:43:32 stephane
71 : * Add ifdef to remove CPLError if OGR is define
72 : *
73 : * Revision 1.2 1999/11/11 01:22:05 stephane
74 : * Remove DebugFeature call, Point Reading error, add IsValidFeature() to
75 : * test correctly if we are on a feature
76 : *
77 : * Revision 1.1 1999/11/08 04:16:07 stephane
78 : * First Revision
79 : *
80 : *
81 : **********************************************************************/
82 :
83 : #include "mitab.h"
84 :
85 : /*=====================================================================
86 : * class MIDDATAFile
87 : *
88 : *====================================================================*/
89 :
90 80 : MIDDATAFile::MIDDATAFile()
91 : {
92 80 : m_fp = NULL;
93 80 : m_szLastRead[0] = '\0';
94 80 : m_szSavedLine[0] = '\0';
95 80 : m_pszDelimiter = "\t"; // Encom 2003 (was NULL)
96 :
97 80 : m_dfXMultiplier = 1.0;
98 80 : m_dfYMultiplier = 1.0;
99 80 : m_dfXDisplacement = 0.0;
100 80 : m_dfYDisplacement = 0.0;
101 :
102 80 : }
103 :
104 80 : MIDDATAFile::~MIDDATAFile()
105 : {
106 80 : Close();
107 80 : }
108 :
109 8 : void MIDDATAFile::SaveLine(const char *pszLine)
110 : {
111 8 : if (pszLine == NULL)
112 : {
113 0 : m_szSavedLine[0] = '\0';
114 : }
115 : else
116 : {
117 8 : strncpy(m_szSavedLine,pszLine,MIDMAXCHAR);
118 : }
119 8 : }
120 :
121 8 : const char *MIDDATAFile::GetSavedLine()
122 : {
123 8 : return m_szSavedLine;
124 : }
125 :
126 80 : int MIDDATAFile::Open(const char *pszFname, const char *pszAccess)
127 : {
128 80 : if (m_fp)
129 : {
130 0 : return -1;
131 : }
132 :
133 : /*-----------------------------------------------------------------
134 : * Validate access mode and make sure we use Text access.
135 : *----------------------------------------------------------------*/
136 80 : if (EQUALN(pszAccess, "r", 1))
137 : {
138 48 : m_eAccessMode = TABRead;
139 48 : pszAccess = "rt";
140 : }
141 32 : else if (EQUALN(pszAccess, "w", 1))
142 : {
143 32 : m_eAccessMode = TABWrite;
144 32 : pszAccess = "wt";
145 : }
146 : else
147 : {
148 0 : return -1;
149 : }
150 :
151 : /*-----------------------------------------------------------------
152 : * Open file for reading
153 : *----------------------------------------------------------------*/
154 80 : m_pszFname = CPLStrdup(pszFname);
155 80 : m_fp = VSIFOpen(m_pszFname, pszAccess);
156 :
157 80 : if (m_fp == NULL)
158 : {
159 0 : CPLFree(m_pszFname);
160 0 : m_pszFname = NULL;
161 0 : return -1;
162 : }
163 :
164 80 : SetEof(VSIFEof(m_fp));
165 80 : return 0;
166 : }
167 :
168 64 : int MIDDATAFile::Rewind()
169 : {
170 64 : if (m_fp == NULL || m_eAccessMode == TABWrite)
171 0 : return -1;
172 :
173 : else
174 : {
175 64 : VSIRewind(m_fp);
176 64 : SetEof(VSIFEof(m_fp));
177 : }
178 64 : return 0;
179 : }
180 :
181 160 : int MIDDATAFile::Close()
182 : {
183 160 : if (m_fp == NULL)
184 80 : return 0;
185 :
186 : // Close file
187 80 : VSIFClose(m_fp);
188 80 : m_fp = NULL;
189 :
190 : // clear readline buffer.
191 80 : CPLReadLine( NULL );
192 :
193 80 : CPLFree(m_pszFname);
194 80 : m_pszFname = NULL;
195 :
196 80 : return 0;
197 :
198 : }
199 :
200 2148 : const char *MIDDATAFile::GetLine()
201 : {
202 : const char *pszLine;
203 :
204 2148 : if (m_eAccessMode == TABRead)
205 : {
206 :
207 2148 : pszLine = CPLReadLine(m_fp);
208 :
209 2148 : SetEof(VSIFEof(m_fp));
210 :
211 2148 : if (pszLine == NULL)
212 : {
213 48 : m_szLastRead[0] = '\0';
214 : }
215 : else
216 : {
217 : // skip leading spaces
218 5124 : while(pszLine && (*pszLine == ' ' || *pszLine == '\t') )
219 924 : pszLine++;
220 :
221 2100 : strncpy(m_szLastRead,pszLine,MIDMAXCHAR);
222 : }
223 : //if (pszLine)
224 : // printf("%s\n",pszLine);
225 2148 : return pszLine;
226 : }
227 : else
228 0 : CPLAssert(FALSE);
229 :
230 0 : return NULL;
231 : }
232 :
233 476 : const char *MIDDATAFile::GetLastLine()
234 : {
235 : // Return NULL if EOF
236 476 : if(GetEof())
237 : {
238 36 : return NULL;
239 : }
240 440 : else if (m_eAccessMode == TABRead)
241 : {
242 : // printf("%s\n",m_szLastRead);
243 440 : return m_szLastRead;
244 : }
245 :
246 : // We should never get here (Read/Write mode not implemented)
247 0 : CPLAssert(FALSE);
248 0 : return NULL;
249 : }
250 :
251 906 : void MIDDATAFile::WriteLine(const char *pszFormat,...)
252 : {
253 : va_list args;
254 :
255 1812 : if (m_eAccessMode == TABWrite && m_fp)
256 : {
257 906 : va_start(args, pszFormat);
258 906 : vfprintf( m_fp, pszFormat, args );
259 906 : va_end(args);
260 : }
261 : else
262 : {
263 0 : CPLAssert(FALSE);
264 : }
265 906 : }
266 :
267 :
268 80 : void MIDDATAFile::SetTranslation(double dfXMul,double dfYMul,
269 : double dfXTran,
270 : double dfYTran)
271 : {
272 80 : m_dfXMultiplier = dfXMul;
273 80 : m_dfYMultiplier = dfYMul;
274 80 : m_dfXDisplacement = dfXTran;
275 80 : m_dfYDisplacement = dfYTran;
276 80 : }
277 :
278 1084 : double MIDDATAFile::GetXTrans(double dfX)
279 : {
280 1084 : return (dfX * m_dfXMultiplier) + m_dfXDisplacement;
281 : }
282 :
283 1084 : double MIDDATAFile::GetYTrans(double dfY)
284 : {
285 1084 : return (dfY * m_dfYMultiplier) + m_dfYDisplacement;
286 : }
287 :
288 :
289 382 : GBool MIDDATAFile::IsValidFeature(const char *pszString)
290 : {
291 : char **papszToken ;
292 :
293 382 : papszToken = CSLTokenizeString(pszString);
294 :
295 : // printf("%s\n",pszString);
296 :
297 382 : if (CSLCount(papszToken) == 0)
298 : {
299 46 : CSLDestroy(papszToken);
300 46 : return FALSE;
301 : }
302 :
303 2724 : if (EQUAL(papszToken[0],"NONE") || EQUAL(papszToken[0],"POINT") ||
304 584 : EQUAL(papszToken[0],"LINE") || EQUAL(papszToken[0],"PLINE") ||
305 508 : EQUAL(papszToken[0],"REGION") || EQUAL(papszToken[0],"ARC") ||
306 432 : EQUAL(papszToken[0],"TEXT") || EQUAL(papszToken[0],"RECT") ||
307 432 : EQUAL(papszToken[0],"ROUNDRECT") || EQUAL(papszToken[0],"ELLIPSE") ||
308 432 : EQUAL(papszToken[0],"MULTIPOINT")|| EQUAL(papszToken[0],"COLLECTION") )
309 : {
310 120 : CSLDestroy(papszToken);
311 120 : return TRUE;
312 : }
313 :
314 216 : CSLDestroy(papszToken);
315 216 : return FALSE;
316 :
317 : }
318 :
319 :
320 476 : GBool MIDDATAFile::GetEof()
321 : {
322 476 : return m_bEof;
323 : }
324 :
325 :
326 2292 : void MIDDATAFile::SetEof(GBool bEof)
327 : {
328 2292 : m_bEof = bEof;
329 2292 : }
|