1 : /******************************************************************************
2 : * $Id: ograrcgendatasource.cpp 23339 2011-11-06 12:36:29Z 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 23339 2011-11-06 12:36:29Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRARCGENDataSource() */
38 : /************************************************************************/
39 :
40 138 : OGRARCGENDataSource::OGRARCGENDataSource()
41 :
42 : {
43 138 : papoLayers = NULL;
44 138 : nLayers = 0;
45 :
46 138 : pszName = NULL;
47 138 : }
48 :
49 : /************************************************************************/
50 : /* ~OGRARCGENDataSource() */
51 : /************************************************************************/
52 :
53 138 : OGRARCGENDataSource::~OGRARCGENDataSource()
54 :
55 : {
56 150 : for( int i = 0; i < nLayers; i++ )
57 12 : delete papoLayers[i];
58 138 : CPLFree( papoLayers );
59 :
60 138 : CPLFree( pszName );
61 138 : }
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 12 : OGRLayer *OGRARCGENDataSource::GetLayer( int iLayer )
78 :
79 : {
80 12 : if( iLayer < 0 || iLayer >= nLayers )
81 0 : return NULL;
82 : else
83 12 : return papoLayers[iLayer];
84 : }
85 :
86 : /************************************************************************/
87 : /* Open() */
88 : /************************************************************************/
89 :
90 138 : int OGRARCGENDataSource::Open( const char * pszFilename, int bUpdateIn)
91 :
92 : {
93 138 : if (bUpdateIn)
94 : {
95 14 : return FALSE;
96 : }
97 :
98 124 : pszName = CPLStrdup( pszFilename );
99 :
100 : // --------------------------------------------------------------------
101 : // Does this appear to be a Arc/Info generate file?
102 : // --------------------------------------------------------------------
103 :
104 124 : VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
105 124 : if (fp == NULL)
106 26 : 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 98 : int nRet = VSIFReadL(szFirstLine, 1, 256, fp);
112 98 : szFirstLine[nRet] = '\0';
113 :
114 : int i;
115 98 : int bFoundEOL = FALSE;
116 2258 : for(i=0;szFirstLine[i] != '\0';i++)
117 : {
118 2250 : if (szFirstLine[i] == '\n' || szFirstLine[i] == '\r')
119 : {
120 38 : bFoundEOL = TRUE;
121 38 : szFirstLine[i] = '\0';
122 38 : break;
123 : }
124 2212 : if (szFirstLine[i] < 32)
125 : {
126 52 : VSIFCloseL(fp);
127 52 : return FALSE;
128 : }
129 : }
130 :
131 46 : if (!bFoundEOL)
132 : {
133 8 : VSIFCloseL(fp);
134 8 : return FALSE;
135 : }
136 :
137 38 : char** papszTokens = CSLTokenizeString2( szFirstLine, " ,", 0 );
138 38 : int nTokens = CSLCount(papszTokens);
139 38 : CSLDestroy(papszTokens);
140 38 : if (nTokens != 1 && nTokens != 3 && nTokens != 4)
141 : {
142 0 : VSIFCloseL(fp);
143 0 : return FALSE;
144 : }
145 :
146 : /* Go to end of file, and count the number of END keywords */
147 : /* If there's 1, it's a point layer */
148 : /* If there's 2, it's a linestring or polygon layer */
149 38 : VSIFSeekL( fp, 0, SEEK_END );
150 38 : vsi_l_offset nSize = VSIFTellL(fp);
151 38 : if (nSize < 10)
152 : {
153 0 : VSIFCloseL(fp);
154 0 : return FALSE;
155 : }
156 : char szBuffer[10+1];
157 38 : VSIFSeekL( fp, nSize - 10, SEEK_SET );
158 38 : VSIFReadL( szBuffer, 1, 10, fp );
159 38 : szBuffer[10] = '\0';
160 :
161 38 : VSIFSeekL( fp, 0, SEEK_SET );
162 :
163 : OGRwkbGeometryType eType;
164 38 : const char* szPtr = szBuffer;
165 38 : const char* szEnd = strstr(szPtr, "END");
166 38 : if (szEnd == NULL) szEnd = strstr(szPtr, "end");
167 38 : if (szEnd == NULL)
168 : {
169 26 : VSIFCloseL(fp);
170 26 : return FALSE;
171 : }
172 12 : szPtr = szEnd + 3;
173 12 : szEnd = strstr(szPtr, "END");
174 12 : if (szEnd == NULL) szEnd = strstr(szPtr, "end");
175 12 : if (szEnd == NULL)
176 : {
177 4 : const char* pszLine = CPLReadLine2L(fp,256,NULL);
178 4 : if (pszLine == NULL)
179 : {
180 0 : VSIFCloseL(fp);
181 0 : return FALSE;
182 : }
183 4 : char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
184 4 : int nTokens = CSLCount(papszTokens);
185 4 : CSLDestroy(papszTokens);
186 :
187 4 : if (nTokens == 3)
188 2 : eType = wkbPoint;
189 2 : else if (nTokens == 4)
190 2 : eType = wkbPoint25D;
191 : else
192 : {
193 0 : VSIFCloseL(fp);
194 0 : return FALSE;
195 : }
196 : }
197 : else
198 : {
199 8 : int nLineNumber = 0;
200 8 : eType = wkbUnknown;
201 8 : CPLString osFirstX, osFirstY;
202 8 : CPLString osLastX, osLastY;
203 8 : int bIs3D = FALSE;
204 : const char* pszLine;
205 52 : while((pszLine = CPLReadLine2L(fp,256,NULL)) != NULL)
206 : {
207 44 : nLineNumber ++;
208 44 : if (nLineNumber == 2)
209 : {
210 8 : char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
211 8 : int nTokens = CSLCount(papszTokens);
212 8 : if (nTokens == 2 || nTokens == 3)
213 : {
214 8 : if (nTokens == 3)
215 4 : bIs3D = TRUE;
216 8 : osFirstX = papszTokens[0];
217 8 : osFirstY = papszTokens[1];
218 : }
219 8 : CSLDestroy(papszTokens);
220 8 : if (nTokens != 2 && nTokens != 3)
221 0 : break;
222 : }
223 36 : else if (nLineNumber > 2)
224 : {
225 28 : if (EQUAL(pszLine, "END"))
226 : {
227 8 : if (osFirstX.compare(osLastX) == 0 &&
228 : osFirstY.compare(osLastY) == 0)
229 4 : eType = (bIs3D) ? wkbPolygon25D : wkbPolygon;
230 : else
231 4 : eType = (bIs3D) ? wkbLineString25D : wkbLineString;
232 8 : break;
233 : }
234 :
235 20 : char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
236 20 : int nTokens = CSLCount(papszTokens);
237 20 : if (nTokens == 2 || nTokens == 3)
238 : {
239 20 : osLastX = papszTokens[0];
240 20 : osLastY = papszTokens[1];
241 : }
242 20 : CSLDestroy(papszTokens);
243 20 : if (nTokens != 2 && nTokens != 3)
244 0 : break;
245 : }
246 : }
247 8 : if (eType == wkbUnknown)
248 : {
249 0 : VSIFCloseL(fp);
250 0 : return FALSE;
251 0 : }
252 : }
253 :
254 12 : VSIFSeekL( fp, 0, SEEK_SET );
255 :
256 12 : nLayers = 1;
257 12 : papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
258 12 : papoLayers[0] = new OGRARCGENLayer(pszName, fp, eType);
259 :
260 12 : return TRUE;
261 : }
|