1 /** @file lumpindex.h Index of lumps. 2 * 3 * @todo Move the definition of lumpnum_t into this header. 4 * 5 * @author Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi> 6 * @author Copyright © 2006-2014 Daniel Swanson <danij@dengine.net> 7 * 8 * @par License 9 * GPL: http://www.gnu.org/licenses/gpl.html 10 * 11 * <small>This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by the 13 * Free Software Foundation; either version 2 of the License, or (at your 14 * option) any later version. This program is distributed in the hope that it 15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 17 * Public License for more details. You should have received a copy of the GNU 18 * General Public License along with this program; if not, write to the Free 19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA</small> 21 */ 22 23 #ifndef LIBDENG_FILESYS_LUMPINDEX_H 24 #define LIBDENG_FILESYS_LUMPINDEX_H 25 26 #ifdef __cplusplus 27 28 #include "../libdoomsday.h" 29 #include "file.h" 30 #include "fileinfo.h" 31 32 #include <QList> 33 #include <de/Error> 34 35 namespace de { 36 37 /** 38 * Virtual file system component used to model an indexable collection of 39 * lumps. A single index may include lumps originating from many different 40 * file containers. 41 * 42 * @ingroup fs 43 */ 44 class LIBDOOMSDAY_PUBLIC LumpIndex 45 { 46 public: 47 /// No file(s) found. @ingroup errors 48 DENG2_ERROR(NotFoundError); 49 50 typedef QList<File1 *> Lumps; 51 typedef std::list<lumpnum_t> FoundIndices; 52 53 /** 54 * Heuristic based map data (format) recognizer. 55 * 56 * Unfortunately id Tech 1 maps cannot be easily recognized, due to their 57 * lack of identification signature, the mechanics of the WAD format lump 58 * index and the existence of several subformat variations. Therefore it is 59 * necessary to use heuristic analysis of the lump index and the lump data. 60 */ 61 class LIBDOOMSDAY_PUBLIC Id1MapRecognizer 62 { 63 public: 64 /// Logical map format identifiers. 65 enum Format { 66 UnknownFormat = -1, 67 68 DoomFormat, 69 HexenFormat, 70 Doom64Format, 71 UniversalFormat, // UDMF 72 73 KnownFormatCount 74 }; 75 76 /// Logical map data type identifiers: 77 enum DataType { 78 UnknownData = -1, 79 80 ThingData, 81 LineDefData, 82 SideDefData, 83 VertexData, 84 SegData, 85 SubsectorData, 86 NodeData, 87 SectorDefData, 88 RejectData, 89 BlockmapData, 90 BehaviorData, 91 ScriptData, 92 TintColorData, 93 MacroData, 94 LeafData, 95 GLVertexData, 96 GLSegData, 97 GLSubsectorData, 98 GLNodeData, 99 GLPVSData, 100 UDMFTextmapData, 101 UDMFEndmapData, 102 103 KnownDataCount 104 }; 105 106 typedef QMap<DataType, File1 *> Lumps; 107 108 public: 109 /** 110 * Attempt to recognize an id Tech 1 format by traversing the WAD lump 111 * index, beginning at the @a lumpIndexOffset specified. 112 */ 113 Id1MapRecognizer(LumpIndex const &lumpIndex, lumpnum_t lumpIndexOffset); 114 115 String const &id() const; 116 Format format() const; 117 118 Lumps const &lumps() const; 119 120 File1 *sourceFile() const; 121 122 /** 123 * Returns the lump index number of the last data lump inspected by the 124 * recognizer, making it possible to collate/locate all the map data sets 125 * using multiple recognizers. 126 */ 127 lumpnum_t lastLump() const; 128 129 public: 130 /** 131 * Returns the textual name for the identified map format @a id. 132 */ 133 static String const &formatName(Format id); 134 135 /** 136 * Determines the type of a map data lump by @a name. 137 */ 138 static DataType typeForLumpName(String name); 139 140 /** 141 * Determine the size (in bytes) of an element of the specified map data 142 * lump @a type for the current map format. 143 * 144 * @param mapFormat Map format identifier. 145 * @param dataType Map lump data type. 146 * 147 * @return Size of an element of the specified type. 148 */ 149 static dsize elementSizeForDataType(Format mapFormat, DataType dataType); 150 151 private: 152 DENG2_PRIVATE(d) 153 }; 154 155 public: 156 /** 157 * @param pathsAreUnique Lumps in the index must have unique paths. Inserting 158 * a lump with the same path as one which already exists 159 * will result in the earlier lump being pruned. 160 */ 161 explicit LumpIndex(bool pathsAreUnique = false); 162 virtual ~LumpIndex(); 163 164 /** 165 * Returns @c true iff the directory contains no lumps. 166 */ isEmpty()167 inline bool isEmpty() const { return !size(); } 168 169 /** 170 * Returns the total number of lumps in the directory. 171 */ 172 int size() const; 173 174 /// @copydoc size() lumpCount()175 inline int lumpCount() const { return size(); } // alias 176 177 /** 178 * Returns the logicial index of the last lump in the directory, or @c -1 if empty. 179 */ 180 int lastIndex() const; 181 182 /** 183 * Returns @c true iff @a lumpNum can be interpreted as a valid lump index. 184 */ 185 bool hasLump(lumpnum_t lumpNum) const; 186 187 /** 188 * Returns @c true iff the index contains one or more lumps with a matching @a path. 189 */ 190 bool contains(Path const &path) const; 191 192 /** 193 * Finds all indices for lumps with a matching @a path. 194 * 195 * @param path Path of the lump(s) to . 196 * @param found Set of lumps that match @a path (in load order; most recent last). 197 * 198 * @return Number of lumps found. 199 * 200 * @see findFirst(), findLast() 201 */ 202 int findAll(Path const &path, FoundIndices &found) const; 203 204 /** 205 * Returns the index of the @em first loaded lump with a matching @a path. 206 * If no lump is found then @c -1 is returned. 207 * 208 * @see findLast(), findAll() 209 */ 210 lumpnum_t findFirst(Path const &path) const; 211 212 /** 213 * Returns the index of the @em last loaded lump with a matching @a path. 214 * If no lump is found then @c -1 is returned. 215 * 216 * @see findFirst(), findAll() 217 */ 218 lumpnum_t findLast(Path const &path) const; 219 220 /** 221 * Lookup a file at specific offset in the index. 222 * 223 * @param lumpNum Logical lumpnum associated to the file being looked up. 224 * 225 * @return The requested file. 226 * 227 * @throws NotFoundError If the requested file could not be found. 228 * @see hasLump() 229 */ 230 File1 &lump(lumpnum_t lumpNum) const; 231 232 /** 233 * @copydoc lump() 234 * @see lump() 235 */ 236 inline File1 &operator [] (lumpnum_t lumpNum) const { return lump(lumpNum); } 237 238 /** 239 * Provides access to list containing @em all the lumps, for efficient traversals. 240 */ 241 Lumps const &allLumps() const; 242 243 /** 244 * Clear the index back to its default (i.e., empty state). 245 */ 246 void clear(); 247 248 /** 249 * Are any lumps from @a file published in this index? 250 * 251 * @param file File containing the lumps to look for. 252 * 253 * @return @c true= One or more lumps are included. 254 */ 255 bool catalogues(File1 &file); 256 257 /** 258 * Append a lump to the index. 259 * 260 * @post Lump name hashes may be invalidated (will be rebuilt upon next search). 261 * 262 * @param lump Lump to be being added. 263 */ 264 void catalogLump(File1 &lump); 265 266 /** 267 * Prune all lumps catalogued from @a file. 268 * 269 * @param file File containing the lumps to prune 270 * 271 * @return Number of lumps pruned. 272 */ 273 int pruneByFile(File1 &file); 274 275 /** 276 * Prune the lump referenced by @a lumpInfo. 277 * 278 * @param lump Lump file to prune. 279 * 280 * @return @c true if found and pruned. 281 */ 282 bool pruneLump(File1 &lump); 283 284 public: 285 /** 286 * Compose the path to the data resource. 287 * 288 * @param lumpNum Lump number. 289 * 290 * @note We do not use the lump name, instead we use the logical lump index 291 * in the global LumpIndex. This is necessary because of the way id tech 1 292 * manages graphic references in animations (intermediate frames are chosen 293 * by their 'original indices' rather than by name). 294 */ 295 static de::Uri composeResourceUrn(lumpnum_t lumpNum); 296 297 private: 298 DENG2_PRIVATE(d) 299 }; 300 301 typedef LumpIndex::Id1MapRecognizer Id1MapRecognizer; 302 303 } // namespace de 304 305 #endif // __cplusplus 306 #endif // LIBDENG_FILESYS_LUMPINDEX_H 307