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