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 33 : OGRARCGENDataSource::OGRARCGENDataSource()
41 :
42 : {
43 33 : papoLayers = NULL;
44 33 : nLayers = 0;
45 :
46 33 : pszName = NULL;
47 33 : }
48 :
49 : /************************************************************************/
50 : /* ~OGRARCGENDataSource() */
51 : /************************************************************************/
52 :
53 33 : OGRARCGENDataSource::~OGRARCGENDataSource()
54 :
55 : {
56 39 : for( int i = 0; i < nLayers; i++ )
57 6 : delete papoLayers[i];
58 33 : CPLFree( papoLayers );
59 :
60 33 : CPLFree( pszName );
61 33 : }
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 33 : int OGRARCGENDataSource::Open( const char * pszFilename, int bUpdateIn)
91 :
92 : {
93 33 : if (bUpdateIn)
94 : {
95 5 : return FALSE;
96 : }
97 :
98 28 : pszName = CPLStrdup( pszFilename );
99 :
100 : // --------------------------------------------------------------------
101 : // Does this appear to be a Arc/Info generate file?
102 : // --------------------------------------------------------------------
103 :
104 28 : VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
105 28 : if (fp == NULL)
106 5 : 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 23 : int nRet = VSIFReadL(szFirstLine, 1, 256, fp);
112 23 : szFirstLine[nRet] = '\0';
113 :
114 : int i;
115 23 : int bFoundEOL = FALSE;
116 967 : for(i=0;szFirstLine[i] != '\0';i++)
117 : {
118 963 : if (szFirstLine[i] == '\n' || szFirstLine[i] == '\r')
119 : {
120 15 : bFoundEOL = TRUE;
121 15 : szFirstLine[i] = '\0';
122 15 : break;
123 : }
124 948 : if (szFirstLine[i] < 32)
125 : {
126 4 : VSIFCloseL(fp);
127 4 : return FALSE;
128 : }
129 : }
130 :
131 19 : if (!bFoundEOL)
132 : {
133 4 : VSIFCloseL(fp);
134 4 : return FALSE;
135 : }
136 :
137 15 : char** papszTokens = CSLTokenizeString2( szFirstLine, " ,", 0 );
138 15 : int nTokens = CSLCount(papszTokens);
139 15 : CSLDestroy(papszTokens);
140 15 : 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 15 : VSIFSeekL( fp, 0, SEEK_END );
150 15 : vsi_l_offset nSize = VSIFTellL(fp);
151 15 : if (nSize < 10)
152 : {
153 0 : VSIFCloseL(fp);
154 0 : return FALSE;
155 : }
156 : char szBuffer[10+1];
157 15 : VSIFSeekL( fp, nSize - 10, SEEK_SET );
158 15 : VSIFReadL( szBuffer, 1, 10, fp );
159 15 : szBuffer[10] = '\0';
160 :
161 15 : VSIFSeekL( fp, 0, SEEK_SET );
162 :
163 : OGRwkbGeometryType eType;
164 15 : const char* szPtr = szBuffer;
165 15 : const char* szEnd = strstr(szPtr, "END");
166 15 : if (szEnd == NULL) szEnd = strstr(szPtr, "end");
167 15 : if (szEnd == NULL)
168 : {
169 9 : VSIFCloseL(fp);
170 9 : 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 : }
|