#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2013 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_STORAGE_SOURCE 1 #include "SevenZipDirectoryReader.h" #include "SevenZippedContainer.h" #include "SevenZippedFile.h" #include "SevenZipArchive.h" #include "../../Helpers/StringHelper.h" #include "Nuclex/Storage/Binary/BinaryBlobReader.h" #include "SevenZipReader.h" namespace Nuclex { namespace Storage { namespace FileSystem { namespace SevenZip { // ------------------------------------------------------------------------------------------- // SevenZipDirectoryReader::SevenZipDirectoryReader( const std::string &nativeArchivePath, const std::shared_ptr &archiveBlob ) : nativeArchivePath(nativeArchivePath), sevenZipArchive(new SevenZipArchive(archiveBlob)) {} // ------------------------------------------------------------------------------------------- // SevenZipDirectoryReader::~SevenZipDirectoryReader() {} // ------------------------------------------------------------------------------------------- // void SevenZipDirectoryReader::ReadDirectory() { this->zipReader.reset(new SevenZipReader(this->sevenZipArchive)); // TODO: Pass through ContainerFileCodec to allow nested archives std::string nativePath = this->nativeArchivePath + "#"; std::shared_ptr createdContainer( new SevenZippedContainer(std::shared_ptr(), nativePath, "/") ); this->containers.insert(std::make_pair(std::string(), createdContainer)); readArchiveStructure(); } // ------------------------------------------------------------------------------------------- // const std::shared_ptr &SevenZipDirectoryReader::GetRootContainer() const { SevenZippedContainerMap::const_iterator iterator = this->containers.find(std::string()); if(iterator == this->containers.end()) { throw std::runtime_error("No 7-zip archive directory has been successfully read so far"); } else { return iterator->second; } } // ------------------------------------------------------------------------------------------- // void SevenZipDirectoryReader::readArchiveStructure() { std::size_t fileCount = this->sevenZipArchive->CountFiles(); for(std::size_t index = 0; index < fileCount; ++index) { processArchivedFile( index, this->sevenZipArchive->GetFilePath(index), this->sevenZipArchive->IsDirectory(index) ); } } // ------------------------------------------------------------------------------------------- // void SevenZipDirectoryReader::processArchivedFile( std::size_t index, const std::string &path, bool isDirectory ) { if(isDirectory) { getOrCreateContainerForDirectory(path); } else { const std::shared_ptr &parentContainer = getOrCreateContainerForDirectory(getParentDirectory(path)); SevenZippedFile::MetaData metaData; metaData.Index = index; metaData.Filename = getDirectoryName(path); metaData.NativePath = this->nativeArchivePath + '#' + path; metaData.UncompressedSize = this->sevenZipArchive->GetUncompressedSize(index); metaData.LastModificationTime = this->sevenZipArchive->GetLastModificationTime(index); metaData.SolidBlockIndex = this->sevenZipArchive->GetSolidBlockIndex(index); metaData.SolidBlockOffset = this->sevenZipArchive->GetFileOffsetInSolidBlock(index); parentContainer->AddFile( std::make_shared(this->zipReader, metaData) ); } } // ------------------------------------------------------------------------------------------- // const std::shared_ptr< SevenZippedContainer > &SevenZipDirectoryReader::getOrCreateContainerForDirectory( const std::string &directory ) { SevenZippedContainerMap::iterator iterator = this->containers.find(directory); if(iterator == this->containers.end()) { const std::shared_ptr &parent = getOrCreateContainerForDirectory( getParentDirectory(directory) ); std::string nativePath = this->nativeArchivePath + "#" + directory; std::string name = getDirectoryName(directory); std::shared_ptr createdContainer = std::make_shared( std::shared_ptr(), nativePath, name ); parent->AddContainer(createdContainer); iterator = this->containers.insert(std::make_pair(directory, createdContainer)).first; } return iterator->second; } // ------------------------------------------------------------------------------------------- // std::string SevenZipDirectoryReader::getParentDirectory(const std::string &directory) { std::size_t lastSlashIndex = directory.rfind('/'); if(lastSlashIndex == std::string::npos) { return std::string(); } else { return directory.substr(0, lastSlashIndex); } } // ------------------------------------------------------------------------------------------- // std::string SevenZipDirectoryReader::getDirectoryName(const std::string &path) { std::size_t lastSlashIndex = path.rfind('/'); if(lastSlashIndex == std::string::npos) { return path; } else { return path.substr(lastSlashIndex + 1); } } // ------------------------------------------------------------------------------------------- // }}}} // namespace Nuclex::Storage::FileSystem::SevenZip