123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /*
- * unlha.cpp
- * ---------
- * Purpose: Implementation file for extracting modules from .lha archives, making use of lhasa
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #include "stdafx.h"
- #include "unlha.h"
- #ifdef MPT_WITH_LHASA
- #include "lhasa.h"
- #endif // MPT_WITH_LHASA
- OPENMPT_NAMESPACE_BEGIN
- #ifdef MPT_WITH_LHASA
- static int LHAreadFileReader(void *handle, void *buf, size_t buf_len)
- {
- FileReader *f = reinterpret_cast<FileReader*>(handle);
- int read_len = mpt::saturate_cast<int>(buf_len);
- int result = mpt::saturate_cast<int>(f->ReadRaw(mpt::span(mpt::void_cast<std::byte*>(buf), read_len)).size());
- if(result == 0)
- {
- return -1;
- }
- return result;
- }
- static int LHAskipFileReader(void *handle, size_t bytes)
- {
- FileReader *f = reinterpret_cast<FileReader*>(handle);
- if(f->CanRead(bytes))
- {
- f->Skip(bytes);
- return 1;
- }
- return 0;
- }
- static void LHAcloseFileReader(void * /*handle*/)
- {
- return;
- }
- static LHAInputStreamType vtable =
- {
- LHAreadFileReader,
- LHAskipFileReader,
- LHAcloseFileReader
- };
- CLhaArchive::CLhaArchive(FileReader &file) : ArchiveBase(file), inputstream(nullptr), reader(nullptr), firstfile(nullptr)
- {
- OpenArchive();
- for(LHAFileHeader *fileheader = firstfile; fileheader; fileheader = lha_reader_next_file(reader))
- {
- ArchiveFileInfo info;
- info.name = mpt::PathString::FromUnicode(mpt::ToUnicode(mpt::Charset::Amiga_no_C1, fileheader->filename));
- info.size = fileheader->length;
- info.type = ArchiveFileType::Normal;
- contents.push_back(info);
- }
- CloseArchive();
- }
- CLhaArchive::~CLhaArchive()
- {
- return;
- }
- void CLhaArchive::OpenArchive()
- {
- inFile.Rewind();
- inputstream = lha_input_stream_new(&vtable, &inFile);
- if(inputstream)
- {
- reader = lha_reader_new(inputstream);
- }
- if(reader)
- {
- lha_reader_set_dir_policy(reader, LHA_READER_DIR_END_OF_DIR);
- firstfile = lha_reader_next_file(reader);
- }
- }
- void CLhaArchive::CloseArchive()
- {
- if(reader)
- {
- lha_reader_free(reader);
- reader = nullptr;
- }
- if(inputstream)
- {
- lha_input_stream_free(inputstream);
- inputstream = nullptr;
- }
- }
- bool CLhaArchive::ExtractFile(std::size_t index)
- {
- if(index >= contents.size())
- {
- return false;
- }
- data.clear();
- OpenArchive();
- const std::size_t bufSize = 4096;
- std::size_t i = 0;
- for(LHAFileHeader *fileheader = firstfile; fileheader; fileheader = lha_reader_next_file(reader))
- {
- if(index == i)
- {
- data.clear();
- std::size_t countRead = 0;
- do
- {
- try
- {
- data.resize(data.size() + bufSize);
- } catch(...)
- {
- CloseArchive();
- return false;
- }
- countRead = lha_reader_read(reader, &data[data.size() - bufSize], bufSize);
- if(countRead < bufSize)
- {
- try
- {
- data.resize(data.size() - (bufSize - countRead));
- } catch(...)
- {
- CloseArchive();
- return false;
- }
- }
- } while(countRead > 0);
- }
- ++i;
- }
- CloseArchive();
- return data.size() > 0;
- }
- #endif // MPT_WITH_LHASA
- OPENMPT_NAMESPACE_END
|