aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp
new file mode 100644
index 0000000..fc02786
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp
@@ -0,0 +1,277 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// Copyright (C) 2009-2012 Christian Stehno
3// This file is part of the "Irrlicht Engine".
4// For conditions of distribution and use, see copyright notice in irrlicht.h
5// Based on the NPK reader from Irrlicht
6
7#include "CNPKReader.h"
8
9#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_
10
11#include "os.h"
12#include "coreutil.h"
13
14#ifdef _DEBUG
15#define IRR_DEBUG_NPK_READER
16#endif
17
18namespace irr
19{
20namespace io
21{
22
23namespace
24{
25 bool isHeaderValid(const SNPKHeader& header)
26 {
27 const c8* const tag = header.Tag;
28 return tag[0] == '0' &&
29 tag[1] == 'K' &&
30 tag[2] == 'P' &&
31 tag[3] == 'N';
32 }
33} // end namespace
34
35
36//! Constructor
37CArchiveLoaderNPK::CArchiveLoaderNPK( io::IFileSystem* fs)
38: FileSystem(fs)
39{
40#ifdef _DEBUG
41 setDebugName("CArchiveLoaderNPK");
42#endif
43}
44
45
46//! returns true if the file maybe is able to be loaded by this class
47bool CArchiveLoaderNPK::isALoadableFileFormat(const io::path& filename) const
48{
49 return core::hasFileExtension(filename, "npk");
50}
51
52//! Check to see if the loader can create archives of this type.
53bool CArchiveLoaderNPK::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const
54{
55 return fileType == EFAT_NPK;
56}
57
58//! Creates an archive from the filename
59/** \param file File handle to check.
60\return Pointer to newly created archive, or 0 upon error. */
61IFileArchive* CArchiveLoaderNPK::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const
62{
63 IFileArchive *archive = 0;
64 io::IReadFile* file = FileSystem->createAndOpenFile(filename);
65
66 if (file)
67 {
68 archive = createArchive(file, ignoreCase, ignorePaths);
69 file->drop ();
70 }
71
72 return archive;
73}
74
75//! creates/loads an archive from the file.
76//! \return Pointer to the created archive. Returns 0 if loading failed.
77IFileArchive* CArchiveLoaderNPK::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const
78{
79 IFileArchive *archive = 0;
80 if ( file )
81 {
82 file->seek ( 0 );
83 archive = new CNPKReader(file, ignoreCase, ignorePaths);
84 }
85 return archive;
86}
87
88
89//! Check if the file might be loaded by this class
90/** Check might look into the file.
91\param file File handle to check.
92\return True if file seems to be loadable. */
93bool CArchiveLoaderNPK::isALoadableFileFormat(io::IReadFile* file) const
94{
95 SNPKHeader header;
96
97 file->read(&header, sizeof(header));
98
99 return isHeaderValid(header);
100}
101
102
103/*!
104 NPK Reader
105*/
106CNPKReader::CNPKReader(IReadFile* file, bool ignoreCase, bool ignorePaths)
107: CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file)
108{
109#ifdef _DEBUG
110 setDebugName("CNPKReader");
111#endif
112
113 if (File)
114 {
115 File->grab();
116 if (scanLocalHeader())
117 sort();
118 else
119 os::Printer::log("Failed to load NPK archive.");
120 }
121}
122
123
124CNPKReader::~CNPKReader()
125{
126 if (File)
127 File->drop();
128}
129
130
131const IFileList* CNPKReader::getFileList() const
132{
133 return this;
134}
135
136
137bool CNPKReader::scanLocalHeader()
138{
139 SNPKHeader header;
140
141 // Read and validate the header
142 File->read(&header, sizeof(header));
143 if (!isHeaderValid(header))
144 return false;
145
146 // Seek to the table of contents
147#ifdef __BIG_ENDIAN__
148 header.Offset = os::Byteswap::byteswap(header.Offset);
149 header.Length = os::Byteswap::byteswap(header.Length);
150#endif
151 header.Offset += 8;
152 core::stringc dirName;
153 bool inTOC=true;
154 // Loop through each entry in the table of contents
155 while (inTOC && (File->getPos() < File->getSize()))
156 {
157 // read an entry
158 char tag[4]={0};
159 SNPKFileEntry entry;
160 File->read(tag, 4);
161 const int numTag = MAKE_IRR_ID(tag[3],tag[2],tag[1],tag[0]);
162 int size;
163
164 bool isDir=true;
165
166 switch (numTag)
167 {
168 case MAKE_IRR_ID('D','I','R','_'):
169 {
170 File->read(&size, 4);
171 readString(entry.Name);
172 entry.Length=0;
173 entry.Offset=0;
174#ifdef IRR_DEBUG_NPK_READER
175 os::Printer::log("Dir", entry.Name);
176#endif
177 }
178 break;
179 case MAKE_IRR_ID('F','I','L','E'):
180 {
181 File->read(&size, 4);
182 File->read(&entry.Offset, 4);
183 File->read(&entry.Length, 4);
184 readString(entry.Name);
185 isDir=false;
186#ifdef IRR_DEBUG_NPK_READER
187 os::Printer::log("File", entry.Name);
188#endif
189#ifdef __BIG_ENDIAN__
190 entry.Offset = os::Byteswap::byteswap(entry.Offset);
191 entry.Length = os::Byteswap::byteswap(entry.Length);
192#endif
193 }
194 break;
195 case MAKE_IRR_ID('D','E','N','D'):
196 {
197 File->read(&size, 4);
198 entry.Name="";
199 entry.Length=0;
200 entry.Offset=0;
201 const s32 pos = dirName.findLast('/', dirName.size()-2);
202 if (pos==-1)
203 dirName="";
204 else
205 dirName=dirName.subString(0, pos);
206#ifdef IRR_DEBUG_NPK_READER
207 os::Printer::log("Dirend", dirName);
208#endif
209 }
210 break;
211 default:
212 inTOC=false;
213 }
214 // skip root dir
215 if (isDir)
216 {
217 if (!entry.Name.size() || (entry.Name==".") || (entry.Name=="<noname>"))
218 continue;
219 dirName += entry.Name;
220 dirName += "/";
221 }
222#ifdef IRR_DEBUG_NPK_READER
223 os::Printer::log("Name", entry.Name);
224#endif
225 addItem((isDir?dirName:dirName+entry.Name), entry.Offset+header.Offset, entry.Length, isDir);
226 }
227 return true;
228}
229
230
231//! opens a file by file name
232IReadFile* CNPKReader::createAndOpenFile(const io::path& filename)
233{
234 s32 index = findFile(filename, false);
235
236 if (index != -1)
237 return createAndOpenFile(index);
238
239 return 0;
240}
241
242
243//! opens a file by index
244IReadFile* CNPKReader::createAndOpenFile(u32 index)
245{
246 if (index >= Files.size() )
247 return 0;
248
249 const SFileListEntry &entry = Files[index];
250 return createLimitReadFile( entry.FullName, File, entry.Offset, entry.Size );
251}
252
253void CNPKReader::readString(core::stringc& name)
254{
255 short stringSize;
256 char buf[256];
257 File->read(&stringSize, 2);
258#ifdef __BIG_ENDIAN__
259 stringSize = os::Byteswap::byteswap(stringSize);
260#endif
261 name.reserve(stringSize);
262 while(stringSize)
263 {
264 const short next = core::min_(stringSize, (short)255);
265 File->read(buf,next);
266 buf[next]=0;
267 name.append(buf);
268 stringSize -= next;
269 }
270}
271
272
273} // end namespace io
274} // end namespace irr
275
276#endif // __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_
277