1 : /******************************************************************************
2 : * $Id: sdtsindexedreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: SDTS Translator
5 : * Purpose: Implmementation of SDTSIndexedReader class. This base class for
6 : * various reader classes provides indexed caching of features for
7 : * quick fetching when assembling composite features for other
8 : * readers.
9 : * Author: Frank Warmerdam, warmerdam@pobox.com
10 : *
11 : ******************************************************************************
12 : * Copyright (c) 1999, Frank Warmerdam
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : ****************************************************************************/
32 :
33 : #include "sdts_al.h"
34 :
35 : CPL_CVSID("$Id: sdtsindexedreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
36 :
37 : /************************************************************************/
38 : /* SDTSIndexedReader() */
39 : /************************************************************************/
40 :
41 8 : SDTSIndexedReader::SDTSIndexedReader()
42 :
43 : {
44 8 : nIndexSize = 0;
45 8 : papoFeatures = NULL;
46 8 : iCurrentFeature = 0;
47 8 : }
48 :
49 : /************************************************************************/
50 : /* ~SDTSIndexedReader() */
51 : /************************************************************************/
52 :
53 8 : SDTSIndexedReader::~SDTSIndexedReader()
54 :
55 : {
56 8 : ClearIndex();
57 8 : }
58 :
59 : /************************************************************************/
60 : /* IsIndexed() */
61 : /************************************************************************/
62 :
63 : /**
64 : Returns TRUE if the module is indexed, otherwise it returns FALSE.
65 :
66 : If the module is indexed all the feature have already been read into
67 : memory, and searches based on the record number can be performed
68 : efficiently.
69 : */
70 :
71 382 : int SDTSIndexedReader::IsIndexed()
72 :
73 : {
74 382 : return nIndexSize != 0;
75 : }
76 :
77 : /************************************************************************/
78 : /* ClearIndex() */
79 : /************************************************************************/
80 :
81 : /**
82 : Free all features in the index (if filled).
83 :
84 : After this the reader is considered to not be indexed, and IsIndexed()
85 : will return FALSE untill the index is forcably filled again.
86 : */
87 :
88 11 : void SDTSIndexedReader::ClearIndex()
89 :
90 : {
91 439 : for( int i = 0; i < nIndexSize; i++ )
92 : {
93 428 : if( papoFeatures[i] != NULL )
94 226 : delete papoFeatures[i];
95 : }
96 :
97 11 : CPLFree( papoFeatures );
98 :
99 11 : papoFeatures = NULL;
100 11 : nIndexSize = 0;
101 11 : }
102 :
103 : /************************************************************************/
104 : /* GetNextFeature() */
105 : /************************************************************************/
106 :
107 : /**
108 : Fetch the next available feature from this reader.
109 :
110 : The returned SDTSFeature * is to an internal indexed object if the
111 : IsIndexed() method returns TRUE, otherwise the returned feature becomes the
112 : responsibility of the caller to destroy with delete.
113 :
114 : Note that the Rewind() method can be used to start over at the beginning of
115 : the modules feature list.
116 :
117 : @return next feature, or NULL if no more are left. Please review above
118 : ownership/delete semantics.
119 :
120 : */
121 :
122 454 : SDTSFeature *SDTSIndexedReader::GetNextFeature()
123 :
124 : {
125 454 : if( nIndexSize == 0 )
126 353 : return GetNextRawFeature();
127 : else
128 : {
129 409 : while( iCurrentFeature < nIndexSize )
130 : {
131 305 : if( papoFeatures[iCurrentFeature] != NULL )
132 98 : return papoFeatures[iCurrentFeature++];
133 : else
134 207 : iCurrentFeature++;
135 : }
136 :
137 3 : return NULL;
138 : }
139 : }
140 :
141 : /************************************************************************/
142 : /* GetIndexedFeatureRef() */
143 : /************************************************************************/
144 :
145 : /**
146 : Fetch a feature based on it's record number.
147 :
148 : This method will forceably fill the feature cache, reading all the
149 : features in the file into memory, if they haven't already been loaded.
150 : The ClearIndex() method can be used to flush this cache when no longer
151 : needed.
152 :
153 : @param iRecordId the record to fetch, normally based on the nRecord
154 : field of an SDTSModId.
155 :
156 : @return a pointer to an internal feature (not to be deleted) or NULL
157 : if there is no matching feature.
158 : */
159 :
160 56 : SDTSFeature *SDTSIndexedReader::GetIndexedFeatureRef( int iRecordId )
161 :
162 : {
163 56 : if( nIndexSize == 0 )
164 2 : FillIndex();
165 :
166 56 : if( iRecordId < 0 || iRecordId >= nIndexSize )
167 0 : return NULL;
168 : else
169 56 : return papoFeatures[iRecordId];
170 : }
171 :
172 : /************************************************************************/
173 : /* FillIndex() */
174 : /************************************************************************/
175 :
176 : /**
177 : Read all features into a memory indexed cached.
178 :
179 : The ClearIndex() method can be used to free all indexed features.
180 : FillIndex() does nothing, if an index has already been built.
181 : */
182 :
183 3 : void SDTSIndexedReader::FillIndex()
184 :
185 : {
186 : SDTSFeature *poFeature;
187 :
188 3 : if( nIndexSize != 0 )
189 0 : return;
190 :
191 3 : Rewind();
192 :
193 232 : while( (poFeature = GetNextRawFeature()) != NULL )
194 : {
195 226 : int iRecordId = poFeature->oModId.nRecord;
196 :
197 : CPLAssert( iRecordId < 1000000 );
198 226 : if( iRecordId >= 1000000 )
199 : {
200 0 : delete poFeature;
201 0 : continue;
202 : }
203 :
204 226 : if( iRecordId >= nIndexSize )
205 : {
206 4 : int nNewSize = (int) (iRecordId * 1.25 + 100);
207 :
208 : papoFeatures = (SDTSFeature **)
209 4 : CPLRealloc( papoFeatures, sizeof(void*) * nNewSize);
210 :
211 432 : for( int i = nIndexSize; i < nNewSize; i++ )
212 428 : papoFeatures[i] = NULL;
213 :
214 4 : nIndexSize = nNewSize;
215 : }
216 :
217 : CPLAssert( papoFeatures[iRecordId] == NULL );
218 226 : papoFeatures[iRecordId] = poFeature;
219 : }
220 : }
221 :
222 : /************************************************************************/
223 : /* ScanModuleReferences() */
224 : /************************************************************************/
225 :
226 : /**
227 : Scan an entire SDTS module for record references with the given field
228 : name.
229 :
230 : The fields are required to have a MODN subfield from which the
231 : module is extracted.
232 :
233 : This method is normally used to find all the attribute modules referred
234 : to by a point, line or polygon module to build a unified schema.
235 :
236 : This method will have the side effect of rewinding unindexed readers
237 : because the scanning operation requires reading all records in the module
238 : from disk.
239 :
240 : @param pszFName the field name to search for. By default "ATID" is
241 : used.
242 :
243 : @return a NULL terminated list of module names. Free with CSLDestroy().
244 : */
245 :
246 5 : char ** SDTSIndexedReader::ScanModuleReferences( const char * pszFName )
247 :
248 : {
249 5 : return SDTSScanModuleReferences( &oDDFModule, pszFName );
250 : }
251 :
252 : /************************************************************************/
253 : /* Rewind() */
254 : /************************************************************************/
255 :
256 : /**
257 : Rewind so that the next feature returned by GetNextFeature() will be the
258 : first in the module.
259 :
260 : */
261 :
262 23 : void SDTSIndexedReader::Rewind()
263 :
264 : {
265 23 : if( nIndexSize != 0 )
266 5 : iCurrentFeature = 0;
267 : else
268 18 : oDDFModule.Rewind();
269 23 : }
|