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