1 : /******************************************************************************
2 : * $Id: ograrcgendatasource.cpp 25447 2013-01-04 20:30:09Z rouault $
3 : *
4 : * Project: Arc/Info Generate Translator
5 : * Purpose: Implements OGRARCGENDataSource class
6 : * Author: Even Rouault, even dot rouault at mines dash paris dot org
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMARCGENS OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_arcgen.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: ograrcgendatasource.cpp 25447 2013-01-04 20:30:09Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRARCGENDataSource() */
38 : /************************************************************************/
39 :
40 114 : OGRARCGENDataSource::OGRARCGENDataSource()
41 :
42 : {
43 114 : papoLayers = NULL;
44 114 : nLayers = 0;
45 :
46 114 : pszName = NULL;
47 114 : }
48 :
49 : /************************************************************************/
50 : /* ~OGRARCGENDataSource() */
51 : /************************************************************************/
52 :
53 114 : OGRARCGENDataSource::~OGRARCGENDataSource()
54 :
55 : {
56 120 : for( int i = 0; i < nLayers; i++ )
57 6 : delete papoLayers[i];
58 114 : CPLFree( papoLayers );
59 :
60 114 : CPLFree( pszName );
61 114 : }
62 :
63 : /************************************************************************/
64 : /* TestCapability() */
65 : /************************************************************************/
66 :
67 0 : int OGRARCGENDataSource::TestCapability( const char * pszCap )
68 :
69 : {
70 0 : return FALSE;
71 : }
72 :
73 : /************************************************************************/
74 : /* GetLayer() */
75 : /************************************************************************/
76 :
77 6 : OGRLayer *OGRARCGENDataSource::GetLayer( int iLayer )
78 :
79 : {
80 6 : if( iLayer < 0 || iLayer >= nLayers )
81 0 : return NULL;
82 : else
83 6 : return papoLayers[iLayer];
84 : }
85 :
86 : /************************************************************************/
87 : /* Open() */
88 : /************************************************************************/
89 :
90 114 : int OGRARCGENDataSource::Open( const char * pszFilename, int bUpdateIn)
91 :
92 : {
93 114 : if (bUpdateIn)
94 : {
95 39 : return FALSE;
96 : }
97 :
98 75 : pszName = CPLStrdup( pszFilename );
99 :
100 : // --------------------------------------------------------------------
101 : // Does this appear to be a Arc/Info generate file?
102 : // --------------------------------------------------------------------
103 :
104 75 : VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
105 75 : if (fp == NULL)
106 19 : return FALSE;
107 :
108 : /* Check that the first line is compatible with a generate file */
109 : /* and in particular contain >= 32 && <= 127 bytes */
110 : char szFirstLine[256+1];
111 56 : int nRet = VSIFReadL(szFirstLine, 1, 256, fp);
112 56 : szFirstLine[nRet] = '\0';
113 :
114 : int i;
115 56 : int bFoundEOL = FALSE;
116 1168 : for(i=0;szFirstLine[i] != '\0';i++)
117 : {
118 1161 : if (szFirstLine[i] == '\n' || szFirstLine[i] == '\r')
119 : {
120 23 : bFoundEOL = TRUE;
121 23 : szFirstLine[i] = '\0';
122 23 : break;
123 : }
124 1138 : if (szFirstLine[i] < 32)
125 : {
126 26 : VSIFCloseL(fp);
127 26 : return FALSE;
128 : }
129 : }
130 :
131 30 : if (!bFoundEOL)
132 : {
133 7 : VSIFCloseL(fp);
134 7 : return FALSE;
135 : }
136 :
137 23 : char** papszTokens = CSLTokenizeString2( szFirstLine, " ,", 0 );
138 23 : int nTokens = CSLCount(papszTokens);
139 23 : if (nTokens != 1 && nTokens != 3 && nTokens != 4)
140 : {
141 0 : VSIFCloseL(fp);
142 0 : CSLDestroy(papszTokens);
143 0 : return FALSE;
144 : }
145 34 : for(int i=0;i<nTokens;i++)
146 : {
147 28 : if( CPLGetValueType(papszTokens[i]) == CPL_VALUE_STRING )
148 : {
149 17 : VSIFCloseL(fp);
150 17 : CSLDestroy(papszTokens);
151 17 : return FALSE;
152 : }
153 : }
154 6 : CSLDestroy(papszTokens);
155 :
156 : /* Go to end of file, and count the number of END keywords */
157 : /* If there's 1, it's a point layer */
158 : /* If there's 2, it's a linestring or polygon layer */
159 6 : VSIFSeekL( fp, 0, SEEK_END );
160 6 : vsi_l_offset nSize = VSIFTellL(fp);
161 6 : if (nSize < 10)
162 : {
163 0 : VSIFCloseL(fp);
164 0 : return FALSE;
165 : }
166 : char szBuffer[10+1];
167 6 : VSIFSeekL( fp, nSize - 10, SEEK_SET );
168 6 : VSIFReadL( szBuffer, 1, 10, fp );
169 6 : szBuffer[10] = '\0';
170 :
171 6 : VSIFSeekL( fp, 0, SEEK_SET );
172 :
173 : OGRwkbGeometryType eType;
174 6 : const char* szPtr = szBuffer;
175 6 : const char* szEnd = strstr(szPtr, "END");
176 6 : if (szEnd == NULL) szEnd = strstr(szPtr, "end");
177 6 : if (szEnd == NULL)
178 : {
179 0 : VSIFCloseL(fp);
180 0 : return FALSE;
181 : }
182 6 : szPtr = szEnd + 3;
183 6 : szEnd = strstr(szPtr, "END");
184 6 : if (szEnd == NULL) szEnd = strstr(szPtr, "end");
185 6 : if (szEnd == NULL)
186 : {
187 2 : const char* pszLine = CPLReadLine2L(fp,256,NULL);
188 2 : if (pszLine == NULL)
189 : {
190 0 : VSIFCloseL(fp);
191 0 : return FALSE;
192 : }
193 2 : char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
194 2 : int nTokens = CSLCount(papszTokens);
195 2 : CSLDestroy(papszTokens);
196 :
197 2 : if (nTokens == 3)
198 1 : eType = wkbPoint;
199 1 : else if (nTokens == 4)
200 1 : eType = wkbPoint25D;
201 : else
202 : {
203 0 : VSIFCloseL(fp);
204 0 : return FALSE;
205 : }
206 : }
207 : else
208 : {
209 4 : int nLineNumber = 0;
210 4 : eType = wkbUnknown;
211 4 : CPLString osFirstX, osFirstY;
212 4 : CPLString osLastX, osLastY;
213 4 : int bIs3D = FALSE;
214 : const char* pszLine;
215 26 : while((pszLine = CPLReadLine2L(fp,256,NULL)) != NULL)
216 : {
217 22 : nLineNumber ++;
218 22 : if (nLineNumber == 2)
219 : {
220 4 : char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
221 4 : int nTokens = CSLCount(papszTokens);
222 4 : if (nTokens == 2 || nTokens == 3)
223 : {
224 4 : if (nTokens == 3)
225 2 : bIs3D = TRUE;
226 4 : osFirstX = papszTokens[0];
227 4 : osFirstY = papszTokens[1];
228 : }
229 4 : CSLDestroy(papszTokens);
230 4 : if (nTokens != 2 && nTokens != 3)
231 0 : break;
232 : }
233 18 : else if (nLineNumber > 2)
234 : {
235 14 : if (EQUAL(pszLine, "END"))
236 : {
237 4 : if (osFirstX.compare(osLastX) == 0 &&
238 : osFirstY.compare(osLastY) == 0)
239 2 : eType = (bIs3D) ? wkbPolygon25D : wkbPolygon;
240 : else
241 2 : eType = (bIs3D) ? wkbLineString25D : wkbLineString;
242 4 : break;
243 : }
244 :
245 10 : char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
246 10 : int nTokens = CSLCount(papszTokens);
247 10 : if (nTokens == 2 || nTokens == 3)
248 : {
249 10 : osLastX = papszTokens[0];
250 10 : osLastY = papszTokens[1];
251 : }
252 10 : CSLDestroy(papszTokens);
253 10 : if (nTokens != 2 && nTokens != 3)
254 0 : break;
255 : }
256 : }
257 4 : if (eType == wkbUnknown)
258 : {
259 0 : VSIFCloseL(fp);
260 0 : return FALSE;
261 0 : }
262 : }
263 :
264 6 : VSIFSeekL( fp, 0, SEEK_SET );
265 :
266 6 : nLayers = 1;
267 6 : papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
268 6 : papoLayers[0] = new OGRARCGENLayer(pszName, fp, eType);
269 :
270 6 : return TRUE;
271 : }
|