1 /******************************************************************************
2  *
3  * Project:  UK NTF Reader
4  * Purpose:  Implements OGRNTFLayer class.
5  * Author:   Frank Warmerdam, warmerdam@pobox.com
6  *
7  ******************************************************************************
8  * Copyright (c) 1999, Frank Warmerdam
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #include "ntf.h"
30 #include "cpl_conv.h"
31 
32 CPL_CVSID("$Id: ogrntflayer.cpp 7e07230bbff24eb333608de4dbd460b7312839d0 2017-12-11 19:08:47Z Even Rouault $")
33 
34 /************************************************************************/
35 /*                            OGRNTFLayer()                             */
36 /*                                                                      */
37 /*      Note that the OGRNTFLayer assumes ownership of the passed       */
38 /*      OGRFeatureDefn object.                                          */
39 /************************************************************************/
40 
OGRNTFLayer(OGRNTFDataSource * poDSIn,OGRFeatureDefn * poFeatureDefine,NTFFeatureTranslator pfnTranslatorIn)41 OGRNTFLayer::OGRNTFLayer( OGRNTFDataSource *poDSIn,
42                           OGRFeatureDefn * poFeatureDefine,
43                           NTFFeatureTranslator pfnTranslatorIn ) :
44     poFeatureDefn(poFeatureDefine),
45     pfnTranslator(pfnTranslatorIn),
46     poDS(poDSIn),
47     iCurrentReader(-1),
48     nCurrentPos((vsi_l_offset)-1),
49     nCurrentFID(1)
50 {
51     SetDescription( poFeatureDefn->GetName() );
52 }
53 
54 /************************************************************************/
55 /*                           ~OGRNTFLayer()                           */
56 /************************************************************************/
57 
~OGRNTFLayer()58 OGRNTFLayer::~OGRNTFLayer()
59 
60 {
61     if( m_nFeaturesRead > 0 && poFeatureDefn != nullptr )
62     {
63         CPLDebug( "Mem", "%d features read on layer '%s'.",
64                   (int) m_nFeaturesRead,
65                   poFeatureDefn->GetName() );
66     }
67 
68     if( poFeatureDefn )
69         poFeatureDefn->Release();
70 }
71 
72 /************************************************************************/
73 /*                            ResetReading()                            */
74 /************************************************************************/
75 
ResetReading()76 void OGRNTFLayer::ResetReading()
77 
78 {
79     iCurrentReader = -1;
80     nCurrentPos = (vsi_l_offset)-1;
81     nCurrentFID = 1;
82 }
83 
84 /************************************************************************/
85 /*                           GetNextFeature()                           */
86 /************************************************************************/
87 
GetNextFeature()88 OGRFeature *OGRNTFLayer::GetNextFeature()
89 
90 {
91     OGRFeature  *poFeature = nullptr;
92 
93 /* -------------------------------------------------------------------- */
94 /*      Have we processed all features already?                         */
95 /* -------------------------------------------------------------------- */
96     if( iCurrentReader == poDS->GetFileCount() )
97         return nullptr;
98 
99 /* -------------------------------------------------------------------- */
100 /*      Do we need to open a file?                                      */
101 /* -------------------------------------------------------------------- */
102     if( iCurrentReader == -1 )
103     {
104         iCurrentReader++;
105         nCurrentPos = (vsi_l_offset)-1;
106     }
107 
108     NTFFileReader       *poCurrentReader = poDS->GetFileReader(iCurrentReader);
109     if( poCurrentReader->GetFP() == nullptr )
110     {
111         poCurrentReader->Open();
112     }
113 
114 /* -------------------------------------------------------------------- */
115 /*      Ensure we are reading on from the same point we were reading    */
116 /*      from for the last feature, even if some other access            */
117 /*      mechanism has moved the file pointer.                           */
118 /* -------------------------------------------------------------------- */
119     if( nCurrentPos != (vsi_l_offset)-1 )
120         poCurrentReader->SetFPPos( nCurrentPos, nCurrentFID );
121     else
122         poCurrentReader->Reset();
123 
124 /* -------------------------------------------------------------------- */
125 /*      Read features till we find one that satisfies our current       */
126 /*      spatial criteria.                                               */
127 /* -------------------------------------------------------------------- */
128     while( true )
129     {
130         poFeature = poCurrentReader->ReadOGRFeature( this );
131         if( poFeature == nullptr )
132             break;
133 
134         m_nFeaturesRead++;
135 
136         if( (m_poFilterGeom == nullptr
137              || poFeature->GetGeometryRef() == nullptr
138              || FilterGeometry( poFeature->GetGeometryRef() ) )
139             && (m_poAttrQuery == nullptr
140                 || m_poAttrQuery->Evaluate( poFeature )) )
141             break;
142 
143         delete poFeature;
144     }
145 
146 /* -------------------------------------------------------------------- */
147 /*      If we get NULL the file must be all consumed, advance to the    */
148 /*      next file that contains features for this layer.                */
149 /* -------------------------------------------------------------------- */
150     if( poFeature == nullptr )
151     {
152         poCurrentReader->Close();
153 
154         if( poDS->GetOption("CACHING") != nullptr
155             && EQUAL(poDS->GetOption("CACHING"),"OFF") )
156         {
157             poCurrentReader->DestroyIndex();
158         }
159 
160         do {
161             iCurrentReader++;
162         } while( iCurrentReader < poDS->GetFileCount()
163                  && !poDS->GetFileReader(iCurrentReader)->TestForLayer(this) );
164 
165         nCurrentPos = (vsi_l_offset)-1;
166         nCurrentFID = 1;
167 
168         poFeature = GetNextFeature();
169     }
170     else
171     {
172         poCurrentReader->GetFPPos(&nCurrentPos, &nCurrentFID);
173     }
174 
175     return poFeature;
176 }
177 
178 /************************************************************************/
179 /*                           TestCapability()                           */
180 /************************************************************************/
181 
TestCapability(const char *)182 int OGRNTFLayer::TestCapability( const char * /* pszCap */ )
183 
184 {
185     return FALSE;
186 }
187 
188 /************************************************************************/
189 /*                          FeatureTranslate()                          */
190 /************************************************************************/
191 
FeatureTranslate(NTFFileReader * poReader,NTFRecord ** papoGroup)192 OGRFeature * OGRNTFLayer::FeatureTranslate( NTFFileReader *poReader,
193                                             NTFRecord ** papoGroup )
194 
195 {
196     if( pfnTranslator == nullptr )
197         return nullptr;
198 
199     return pfnTranslator( poReader, this, papoGroup );
200 }
201