Files
o3de/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.cpp
T
2021-03-08 14:30:57 -08:00

183 lines
5.6 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include <AzCore/Console/Console.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/Archive/ZipFileFormat.h>
#include <AzFramework/Archive/ZipDirStructures.h>
#include <AzFramework/Archive/ZipDirTree.h>
namespace AZ::IO::ZipDir
{
// Adds or finds the file. Returns non-initialized structure if it was added,
// or an IsInitialized() structure if it was found
FileEntry* FileEntryTree::Add(AZStd::string_view szPath)
{
AZStd::optional<AZStd::string_view> pathEntry = AZ::StringFunc::TokenizeNext(szPath, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR);
if (!pathEntry)
{
AZ_Assert(false, "An empty file path cannot be added to the zip file entry tree");
return nullptr;
}
// If a path separator was found, add a subdirectory
if (!szPath.empty())
{
auto dirEntryIter = m_mapDirs.find(*pathEntry);
// we have a subdirectory here - create the file in it
if (dirEntryIter == m_mapDirs.end())
{
dirEntryIter = m_mapDirs.emplace(*pathEntry, AZStd::make_unique<FileEntryTree>()).first;
}
return dirEntryIter->second->Add(szPath);
}
// Add the filename
auto fileEntryIter = m_mapFiles.find(*pathEntry);
if (fileEntryIter == m_mapFiles.end())
{
fileEntryIter = m_mapFiles.emplace(*pathEntry, AZStd::make_unique<FileEntry>()).first;
}
return fileEntryIter->second.get();
}
// adds a file to this directory
ErrorEnum FileEntryTree::Add(AZStd::string_view szPath, const FileEntryBase& file)
{
FileEntry* pFile = Add(szPath);
if (!pFile)
{
return ZD_ERROR_INVALID_PATH;
}
if (pFile->IsInitialized())
{
return ZD_ERROR_FILE_ALREADY_EXISTS;
}
static_cast<FileEntryBase&>(*pFile) = file;
return ZD_ERROR_SUCCESS;
}
// returns the number of files in this tree, including this and sublevels
uint32_t FileEntryTree::NumFilesTotal() const
{
uint32_t numFiles = aznumeric_cast<uint32_t>(m_mapFiles.size());
for (const auto& [dirname, fileEntryTree] : m_mapDirs)
{
numFiles += fileEntryTree->NumFilesTotal();
}
return numFiles;
}
//////////////////////////////////////////////////////////////////////////
uint32_t FileEntryTree::NumDirsTotal() const
{
uint32_t numDirs = 1;
for (const auto& [dirname, fileEntryTree] : m_mapDirs)
{
numDirs += fileEntryTree->NumDirsTotal();
}
return numDirs;
}
void FileEntryTree::Clear()
{
m_mapDirs.clear();
m_mapFiles.clear();
}
size_t FileEntryTree::GetSize() const
{
size_t nSize = sizeof(*this);
for (const auto& [dirname, dirEntry] : m_mapDirs)
{
nSize += dirname.size() + sizeof(decltype(m_mapDirs)::value_type) + dirEntry->GetSize();
}
for (const auto& [filename, fileEntry] : m_mapFiles)
{
nSize += filename.size() + sizeof(decltype(m_mapFiles)::value_type);
}
return nSize;
}
bool FileEntryTree::IsOwnerOf(const FileEntry* pFileEntry) const
{
for (const auto& [path, fileEntry] : m_mapFiles)
{
if (pFileEntry == fileEntry.get())
{
return true;
}
}
for (const auto& [path, fileEntryTree] : m_mapDirs)
{
if (fileEntryTree->IsOwnerOf(pFileEntry))
{
return true;
}
}
return false;
}
FileEntryTree* FileEntryTree::FindDir(AZStd::string_view szDirName)
{
if (auto it = m_mapDirs.find(szDirName); it != m_mapDirs.end())
{
return it->second.get();
}
return nullptr;
}
FileEntryTree::FileMap::iterator FileEntryTree::FindFile(AZStd::string_view szFileName)
{
return m_mapFiles.find(szFileName);
}
FileEntry* FileEntryTree::GetFileEntry(FileMap::iterator it)
{
return it == GetFileEnd() ? nullptr : it->second.get();
}
FileEntryTree* FileEntryTree::GetDirEntry(SubdirMap::iterator it)
{
return it == GetDirEnd() ? nullptr : it->second.get();
}
ErrorEnum FileEntryTree::RemoveDir(AZStd::string_view szDirName)
{
SubdirMap::iterator itRemove = m_mapDirs.find(szDirName);
if (itRemove == m_mapDirs.end())
{
return ZD_ERROR_FILE_NOT_FOUND;
}
m_mapDirs.erase(itRemove);
return ZD_ERROR_SUCCESS;
}
ErrorEnum FileEntryTree::RemoveFile(AZStd::string_view szFileName)
{
FileMap::iterator itRemove = m_mapFiles.find(szFileName);
if (itRemove == m_mapFiles.end())
{
return ZD_ERROR_FILE_NOT_FOUND;
}
m_mapFiles.erase(itRemove);
return ZD_ERROR_SUCCESS;
}
}