1 : /******************************************************************************
2 : * $Id: ogrreclayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: EPIInfo .REC Reader
5 : * Purpose: Implements OGRRECLayer class.
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
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, DAMAGES 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_rec.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: ogrreclayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
35 :
36 : /************************************************************************/
37 : /* OGRRECLayer() */
38 : /* */
39 : /* Note that the OGRRECLayer assumes ownership of the passed */
40 : /* file pointer. */
41 : /************************************************************************/
42 :
43 0 : OGRRECLayer::OGRRECLayer( const char *pszLayerNameIn,
44 0 : FILE * fp, int nFieldCountIn )
45 :
46 : {
47 0 : fpREC = fp;
48 0 : bIsValid = FALSE;
49 0 : nStartOfData = 0;
50 :
51 0 : nNextFID = 1;
52 :
53 0 : poFeatureDefn = new OGRFeatureDefn( pszLayerNameIn );
54 0 : poFeatureDefn->Reference();
55 :
56 0 : nFieldCount = 0;
57 0 : panFieldOffset = (int *) CPLCalloc(sizeof(int),nFieldCountIn);
58 0 : panFieldWidth = (int *) CPLCalloc(sizeof(int),nFieldCountIn);
59 :
60 : /* -------------------------------------------------------------------- */
61 : /* Read field definition lines. */
62 : /* -------------------------------------------------------------------- */
63 : int iField;
64 :
65 0 : for( nFieldCount=0, iField = 0; iField < nFieldCountIn; iField++ )
66 : {
67 0 : const char *pszLine = CPLReadLine( fp );
68 : int nTypeCode;
69 0 : OGRFieldType eFType = OFTString;
70 :
71 0 : if( pszLine == NULL )
72 0 : return;
73 :
74 0 : if( strlen(pszLine) < 44 )
75 0 : return;
76 :
77 : // Extract field width.
78 0 : panFieldWidth[nFieldCount] = atoi( RECGetField( pszLine, 37, 4 ) );
79 :
80 : // Is this an real, integer or string field? Default to string.
81 0 : nTypeCode = atoi(RECGetField(pszLine,33,4));
82 0 : if( nTypeCode == 12 )
83 0 : eFType = OFTInteger;
84 0 : else if( nTypeCode > 100 && nTypeCode < 120 )
85 : {
86 0 : eFType = OFTReal;
87 : }
88 0 : else if( nTypeCode == 0 || nTypeCode == 6 || nTypeCode == 102 )
89 : {
90 0 : if( panFieldWidth[nFieldCount] < 3 )
91 0 : eFType = OFTInteger;
92 : else
93 0 : eFType = OFTReal;
94 : }
95 : else
96 0 : eFType = OFTString;
97 :
98 0 : OGRFieldDefn oField( RECGetField( pszLine, 2, 10 ), eFType );
99 :
100 : // Establish field offset.
101 0 : if( nFieldCount > 0 )
102 0 : panFieldOffset[nFieldCount]
103 0 : = panFieldOffset[nFieldCount-1] + panFieldWidth[nFieldCount-1];
104 :
105 0 : if( nTypeCode > 100 && nTypeCode < 120 )
106 : {
107 0 : oField.SetWidth( panFieldWidth[nFieldCount] );
108 0 : oField.SetPrecision( nTypeCode - 100 );
109 : }
110 0 : else if( eFType == OFTReal )
111 : {
112 0 : oField.SetWidth( panFieldWidth[nFieldCount]*2 );
113 0 : oField.SetPrecision( panFieldWidth[nFieldCount]-1 );
114 : }
115 : else
116 0 : oField.SetWidth( panFieldWidth[nFieldCount] );
117 :
118 : // Skip fields that are only screen labels.
119 0 : if( panFieldWidth[nFieldCount] == 0 )
120 0 : continue;
121 :
122 0 : poFeatureDefn->AddFieldDefn( &oField );
123 0 : nFieldCount++;
124 : }
125 :
126 0 : nRecordLength = panFieldOffset[nFieldCount-1]+panFieldWidth[nFieldCount-1];
127 0 : bIsValid = TRUE;
128 :
129 0 : nStartOfData = VSIFTell( fp );
130 0 : }
131 :
132 : /************************************************************************/
133 : /* ~OGRRECLayer() */
134 : /************************************************************************/
135 :
136 0 : OGRRECLayer::~OGRRECLayer()
137 :
138 : {
139 0 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
140 : {
141 : CPLDebug( "REC", "%d features read on layer '%s'.",
142 : (int) m_nFeaturesRead,
143 0 : poFeatureDefn->GetName() );
144 : }
145 :
146 0 : if( fpREC != NULL )
147 0 : VSIFClose( fpREC );
148 :
149 0 : if( poFeatureDefn )
150 0 : poFeatureDefn->Release();
151 :
152 0 : CPLFree( panFieldOffset );
153 0 : CPLFree( panFieldWidth );
154 0 : }
155 :
156 : /************************************************************************/
157 : /* ResetReading() */
158 : /************************************************************************/
159 :
160 0 : void OGRRECLayer::ResetReading()
161 :
162 : {
163 0 : VSIFSeek( fpREC, nStartOfData, SEEK_SET );
164 0 : nNextFID = 1;
165 0 : }
166 :
167 : /************************************************************************/
168 : /* GetNextUnfilteredFeature() */
169 : /************************************************************************/
170 :
171 0 : OGRFeature * OGRRECLayer::GetNextUnfilteredFeature()
172 :
173 : {
174 : /* -------------------------------------------------------------------- */
175 : /* Read and assemble the source data record. */
176 : /* -------------------------------------------------------------------- */
177 0 : int nDataLen = 0;
178 0 : char *pszRecord = (char *) CPLMalloc(nRecordLength + 2 );
179 :
180 0 : while( nDataLen < nRecordLength )
181 : {
182 0 : const char *pszLine = CPLReadLine( fpREC );
183 : int iSegLen;
184 :
185 0 : if( pszLine == NULL )
186 : {
187 0 : CPLFree( pszRecord );
188 0 : return NULL;
189 : }
190 :
191 0 : if( *pszLine == 26 /* Cntl-Z - DOS EOF */ )
192 : {
193 0 : CPLFree( pszRecord );
194 0 : return NULL;
195 : }
196 :
197 : // If the end-of-line markers is '?' the record is deleted.
198 0 : iSegLen = strlen(pszLine);
199 0 : if( pszLine[iSegLen-1] == '?' )
200 : {
201 0 : pszRecord[0] = '\0';
202 0 : nDataLen = 0;
203 0 : continue;
204 : }
205 :
206 : // Strip off end-of-line '!' marker.
207 0 : if( pszLine[iSegLen-1] != '!'
208 0 : && pszLine[iSegLen-1] != '^' )
209 : {
210 : CPLError( CE_Failure, CPLE_AppDefined,
211 : "Apparent corrupt data line .. record FID=%d",
212 0 : nNextFID );
213 0 : CPLFree( pszRecord );
214 0 : return NULL;
215 : }
216 :
217 0 : iSegLen--;
218 0 : if( nDataLen + iSegLen > nRecordLength )
219 : {
220 : CPLError( CE_Failure, CPLE_AppDefined,
221 : "Too much data for record %d.",
222 0 : nNextFID );
223 0 : CPLFree( pszRecord );
224 0 : return NULL;
225 : }
226 :
227 0 : strncpy( pszRecord+nDataLen, pszLine, iSegLen );
228 0 : pszRecord[nDataLen+iSegLen] = '\0';
229 0 : nDataLen += iSegLen;
230 : }
231 :
232 : /* -------------------------------------------------------------------- */
233 : /* Create the OGR feature. */
234 : /* -------------------------------------------------------------------- */
235 : OGRFeature *poFeature;
236 :
237 0 : poFeature = new OGRFeature( poFeatureDefn );
238 :
239 : /* -------------------------------------------------------------------- */
240 : /* Set attributes for any indicated attribute records. */
241 : /* -------------------------------------------------------------------- */
242 : int iAttr;
243 :
244 0 : for( iAttr = 0; iAttr < nFieldCount; iAttr++)
245 : {
246 : const char *pszFieldText =
247 : RECGetField( pszRecord,
248 0 : panFieldOffset[iAttr] + 1,
249 0 : panFieldWidth[iAttr] );
250 :
251 0 : if( strlen(pszFieldText) != 0 )
252 0 : poFeature->SetField( iAttr, pszFieldText );
253 : }
254 :
255 : /* -------------------------------------------------------------------- */
256 : /* Translate the record id. */
257 : /* -------------------------------------------------------------------- */
258 0 : poFeature->SetFID( nNextFID++ );
259 0 : m_nFeaturesRead++;
260 :
261 0 : CPLFree( pszRecord );
262 :
263 0 : return poFeature;
264 : }
265 :
266 :
267 : /************************************************************************/
268 : /* GetNextFeature() */
269 : /************************************************************************/
270 :
271 0 : OGRFeature *OGRRECLayer::GetNextFeature()
272 :
273 : {
274 0 : OGRFeature *poFeature = NULL;
275 :
276 : /* -------------------------------------------------------------------- */
277 : /* Read features till we find one that satisfies our current */
278 : /* spatial criteria. */
279 : /* -------------------------------------------------------------------- */
280 0 : while( TRUE )
281 : {
282 0 : poFeature = GetNextUnfilteredFeature();
283 0 : if( poFeature == NULL )
284 0 : break;
285 :
286 0 : if( m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature ) )
287 0 : break;
288 :
289 0 : delete poFeature;
290 : }
291 :
292 0 : return poFeature;
293 : }
294 :
295 : /************************************************************************/
296 : /* TestCapability() */
297 : /************************************************************************/
298 :
299 0 : int OGRRECLayer::TestCapability( const char * pszCap )
300 :
301 : {
302 0 : return FALSE;
303 : }
304 :
|