athena/src/Athena/WiiFile.cpp

284 lines
6.2 KiB
C++

#ifndef ATHENA_NO_SAVES
// This file is part of libAthena.
//
// libAthena is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libAthena 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
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
#include "Athena/WiiFile.hpp"
#include "Athena/InvalidOperationException.hpp"
#include <algorithm>
namespace Athena
{
//! TODO: Remove this?
WiiFile::WiiFile() :
m_permissions(WiiFile::GroupRW|WiiFile::OtherRW|WiiFile::OwnerRW),
m_attributes(0),
m_type(WiiFile::File),
m_filename(""),
m_fileLen(0),
m_fileData(NULL),
m_parent(NULL)
{
//ctor
}
WiiFile::WiiFile(const std::string& filename) :
m_permissions(WiiFile::GroupRW|WiiFile::OtherRW|WiiFile::OwnerRW),
m_attributes(0),
m_type(WiiFile::File),
m_filename(filename),
m_fileLen(0),
m_fileData(NULL),
m_parent(NULL)
{
}
WiiFile::WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length) :
m_permissions(permissions),
m_attributes(0),
m_type(WiiFile::File),
m_filename(filename),
m_fileLen(length),
m_fileData((atUint8*)data)
{
}
WiiFile::~WiiFile()
{
if (m_fileData)
delete[] m_fileData;
for (WiiFile* child : m_children)
delete child;
}
void WiiFile::setFilename(const std::string& filename)
{
m_filename = filename;
}
std::string WiiFile::filename() const
{
return m_filename;
}
void WiiFile::setPermissions(const atUint8 permissions)
{
m_permissions = (atUint8)permissions;
}
atUint8 WiiFile::permissions() const
{
return m_permissions;
}
void WiiFile::setData(const atUint8* data)
{
if (m_fileData)
{
delete[] m_fileData;
m_fileData = NULL;
}
m_fileData = (atUint8*)data;
}
atUint8* WiiFile::data() const
{
return m_fileData;
}
void WiiFile::setLength(const int len)
{
m_fileLen = (int)len;
}
int WiiFile::length() const
{
return m_fileLen;
}
void WiiFile::setAttributes(const atUint8 attr)
{
m_attributes = attr;
}
atUint8 WiiFile::attributes() const
{
return m_attributes;
}
void WiiFile::setType(WiiFile::Type type)
{
m_type = type;
}
WiiFile::Type WiiFile::type() const
{
return m_type;
}
bool WiiFile::isDirectory() const
{
return (m_type == WiiFile::Directory);
}
bool WiiFile::isFile() const
{
return (m_type == WiiFile::File);
}
void WiiFile::addChild(WiiFile *file)
{
if (!isDirectory())
THROW_INVALID_OPERATION_EXCEPTION("%s is not a directory", filename().c_str());
if (std::find(m_children.begin(), m_children.end(), file) != m_children.end())
return;
// Lets figure out it's place
std::string tmpName(file->filename());
// Since we only support *NIX paths this is simple
atUint32 depth = Athena::utility::countChar(tmpName, '/');
bool owned = false;
while ((depth--) > 0)
{
// add them from the beginning of the path up
tmpName = tmpName.substr(0, tmpName.find('/'));
for (atUint32 i = 0; i < m_children.size(); i++)
{
if (!m_children[i]->filename().compare(tmpName))
{
std::string newName = file->filename();
newName = newName.substr(newName.rfind("/") + 1, newName.size() - newName.rfind("/"));
file->setFilename(newName);
m_children[i]->addChild(file);
owned = true;
}
}
}
if (!owned)
{
m_children.push_back(file);
file->setParent(this);
}
}
WiiFile* WiiFile::child(const std::string &name)
{
std::vector<WiiFile*>::iterator iter = std::find_if(m_children.begin(), m_children.end(),
[&name](WiiFile* f) { return !f->filename().compare(name); });
if (iter != m_children.end())
return *iter;
std::string tmpName(name);
tmpName = tmpName.substr(tmpName.rfind('/')+1, tmpName.size() - tmpName.rfind('/'));
for (WiiFile* f : m_children)
{
if (f->isFile())
continue;
WiiFile* ret = f->child(tmpName);
if (ret)
return ret;
}
return nullptr;
}
void WiiFile::removeChild(WiiFile* file)
{
std::vector<WiiFile*>::iterator iter = std::find(m_children.begin(), m_children.end(), file);
if (iter == m_children.end())
return;
m_children.erase(iter);
}
WiiFile* WiiFile::parent()
{
return m_parent;
}
void WiiFile::setParent(WiiFile* parent)
{
if (m_parent)
m_parent->removeChild(this);
m_parent = parent;
m_parent->addChild(this);
}
atUint32 WiiFile::fileCount()
{
size_t ret = m_children.size();
for (WiiFile* f : m_children)
{
if (f->isFile())
continue;
ret += f->fileCount();
}
return (atUint32)ret;
}
std::vector<WiiFile *> WiiFile::allChildren()
{
std::vector<WiiFile*> ret;
if (m_children.size() == 0)
return ret;
// Add our children first
for (WiiFile* f : m_children)
ret.push_back(f);
// now lets add our children's children
for (WiiFile* f : m_children)
{
if (f->isFile())
continue;
std::vector<WiiFile*> tmp = f->allChildren();
if (tmp.size() == 0)
continue;
ret.insert(ret.end(), tmp.begin(), tmp.end());
}
return ret;
}
std::string WiiFile::fullpath()
{
std::string ret;
if (m_parent)
ret = m_parent->filename() + "/";
ret = ret + filename();
while (ret.at(0) == '/')
ret.erase(ret.begin());
return ret;
}
} // zelda
#endif // ATHENA_NO_SAVES