mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-12 19:31:41 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
511
Engine/source/core/memVolume.cpp
Normal file
511
Engine/source/core/memVolume.cpp
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "core/memVolume.h"
|
||||
|
||||
#include "core/crc.h"
|
||||
#include "core/frameAllocator.h"
|
||||
#include "core/util/str.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#include "platform/platformVolume.h"
|
||||
|
||||
namespace Torque
|
||||
{
|
||||
namespace Mem
|
||||
{
|
||||
|
||||
// Multiple MemFile's can reference the same path, so this is here to contain
|
||||
// the actual data at a Path.
|
||||
struct MemFileData
|
||||
{
|
||||
MemFileData(MemFileSystem* fs, const Path& path)
|
||||
{
|
||||
mPath = path;
|
||||
mBufferSize = 1024;
|
||||
mFileSize = 0;
|
||||
mBuffer = dMalloc(mBufferSize);
|
||||
dMemset(mBuffer, 0, mBufferSize);
|
||||
mModified = Time::getCurrentTime();
|
||||
mLastAccess = mModified;
|
||||
mFileSystem = fs;
|
||||
}
|
||||
|
||||
~MemFileData()
|
||||
{
|
||||
dFree(mBuffer);
|
||||
}
|
||||
|
||||
bool getAttributes(FileNode::Attributes* attr)
|
||||
{
|
||||
attr->name = mPath;
|
||||
attr->flags = FileNode::File;
|
||||
attr->size = mFileSize;
|
||||
attr->mtime = mModified;
|
||||
attr->atime = mLastAccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
FileNodeRef resolve(const Path& path)
|
||||
{
|
||||
// Is it me?
|
||||
String sThisPath(mPath);
|
||||
String sTargetPath(path);
|
||||
if (sThisPath == sTargetPath)
|
||||
return new MemFile(mFileSystem, this);
|
||||
// Nope
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Path mPath;
|
||||
void* mBuffer;
|
||||
U32 mBufferSize; // This is the size of the memory buffer >= mFileSize
|
||||
U32 mFileSize; // This is the size of the "file" <= mBufferSize
|
||||
Time mModified; // Last modified
|
||||
Time mLastAccess; // Last access
|
||||
MemFileSystem* mFileSystem;
|
||||
};
|
||||
|
||||
struct MemDirectoryData
|
||||
{
|
||||
Path mPath;
|
||||
MemFileSystem* mFileSystem;
|
||||
Vector<MemFileData*> mFiles;
|
||||
Vector<MemDirectoryData*> mDirectories;
|
||||
|
||||
MemDirectoryData(MemFileSystem* fs, const Path& path)
|
||||
{
|
||||
mFileSystem = fs;
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
~MemDirectoryData()
|
||||
{
|
||||
for (U32 i = 0; i < mFiles.size(); i++)
|
||||
{
|
||||
delete mFiles[i];
|
||||
}
|
||||
for (U32 i = 0; i < mDirectories.size(); i++)
|
||||
{
|
||||
delete mDirectories[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool getAttributes(FileNode::Attributes* attr)
|
||||
{
|
||||
attr->name = mPath;
|
||||
attr->flags = FileNode::Directory;
|
||||
return true;
|
||||
}
|
||||
|
||||
FileNodeRef resolve(const Path& path)
|
||||
{
|
||||
// Is it me?
|
||||
String sThisPath(mPath);
|
||||
String sTargetPath(path);
|
||||
if (sThisPath == sTargetPath)
|
||||
return new MemDirectory(mFileSystem, this);
|
||||
// Is it one of my children?
|
||||
if (sTargetPath.find(sThisPath) == 0)
|
||||
{
|
||||
FileNodeRef result;
|
||||
for (U32 i = 0; i < mDirectories.size() && result.isNull(); i++)
|
||||
result = mDirectories[i]->resolve(path);
|
||||
for (U32 i = 0; i < mFiles.size() && result.isNull(); i++)
|
||||
result = mFiles[i]->resolve(path);
|
||||
return result;
|
||||
}
|
||||
// Nope
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
MemFileSystem::MemFileSystem(String volume)
|
||||
{
|
||||
mVolume = volume;
|
||||
mRootDir = new MemDirectoryData(this, volume);
|
||||
}
|
||||
|
||||
MemFileSystem::~MemFileSystem()
|
||||
{
|
||||
delete mRootDir;
|
||||
}
|
||||
|
||||
FileNodeRef MemFileSystem::resolve(const Path& path)
|
||||
{
|
||||
return mRootDir->resolve(path);
|
||||
}
|
||||
|
||||
//
|
||||
MemDirectory* MemFileSystem::getParentDir(const Path& path, FileNodeRef& parentRef)
|
||||
{
|
||||
parentRef = mRootDir->resolve(path.getRoot() + ":" + path.getPath());
|
||||
if (parentRef.isNull())
|
||||
return NULL;
|
||||
|
||||
MemDirectory* result = dynamic_cast<MemDirectory*>(parentRef.getPointer());
|
||||
return result;
|
||||
}
|
||||
|
||||
FileNodeRef MemFileSystem::create(const Path& path, FileNode::Mode mode)
|
||||
{
|
||||
// Already exists
|
||||
FileNodeRef result = mRootDir->resolve(path);
|
||||
if (result.isValid())
|
||||
return result;
|
||||
|
||||
// Doesn't exist, try to get parent node.
|
||||
FileNodeRef parentRef;
|
||||
MemDirectory* mDir = getParentDir(path, parentRef);
|
||||
if (mDir)
|
||||
{
|
||||
MemDirectoryData* mdd = mDir->mDirectoryData;
|
||||
switch (mode)
|
||||
{
|
||||
case FileNode::File :
|
||||
{
|
||||
MemFileData* mfd = new MemFileData(this, path);
|
||||
mdd->mFiles.push_back(mfd);
|
||||
return new MemFile(this, mfd);
|
||||
}
|
||||
break;
|
||||
case FileNode::Directory :
|
||||
{
|
||||
MemDirectoryData* mfd = new MemDirectoryData(this, path);
|
||||
mdd->mDirectories.push_back(mfd);
|
||||
return new MemDirectory(this, mfd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// anything else we ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool MemFileSystem::remove(const Path& path)
|
||||
{
|
||||
FileNodeRef parentRef;
|
||||
MemDirectory* mDir = getParentDir(path, parentRef);
|
||||
MemDirectoryData* mdd = mDir->mDirectoryData;
|
||||
for (U32 i = 0; i < mdd->mDirectories.size(); i++)
|
||||
{
|
||||
if (mdd->mDirectories[i]->mPath == path)
|
||||
{
|
||||
delete mdd->mDirectories[i];
|
||||
mdd->mDirectories.erase_fast(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (U32 i = 0; i < mdd->mFiles.size(); i++)
|
||||
{
|
||||
if (mdd->mFiles[i]->mPath == path)
|
||||
{
|
||||
delete mdd->mFiles[i];
|
||||
mdd->mFiles.erase_fast(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemFileSystem::rename(const Path& from,const Path& to)
|
||||
{
|
||||
// Source must exist
|
||||
FileNodeRef source = mRootDir->resolve(from);
|
||||
if (source.isNull())
|
||||
return false;
|
||||
|
||||
// Destination must not exist
|
||||
FileNodeRef dest = mRootDir->resolve(to);
|
||||
if (source.isValid())
|
||||
return false;
|
||||
|
||||
// Get source parent
|
||||
FileNodeRef sourceParentRef;
|
||||
MemDirectory* sourceDir = getParentDir(from, sourceParentRef);
|
||||
|
||||
// Get dest parent
|
||||
FileNodeRef destRef;
|
||||
MemDirectory* mDir = getParentDir(to, destRef);
|
||||
|
||||
// Now move it/rename it
|
||||
if (dynamic_cast<MemDirectory*>(source.getPointer()))
|
||||
{
|
||||
MemDirectoryData* sourcedd;
|
||||
MemDirectoryData* d = sourceDir->mDirectoryData;
|
||||
for (U32 i = 0; i < d->mDirectories.size(); i++)
|
||||
{
|
||||
if (d->mDirectories[i]->mPath == from)
|
||||
{
|
||||
sourcedd = d->mDirectories[i];
|
||||
d->mDirectories.erase_fast(i);
|
||||
sourcedd->mPath = to;
|
||||
mDir->mDirectoryData->mDirectories.push_back(sourcedd);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MemFileData* sourceFile;
|
||||
MemDirectoryData* d = sourceDir->mDirectoryData;
|
||||
for (U32 i = 0; i < d->mFiles.size(); i++)
|
||||
{
|
||||
if (d->mFiles[i]->mPath == from)
|
||||
{
|
||||
sourceFile = d->mFiles[i];
|
||||
d->mFiles.erase_fast(i);
|
||||
sourceFile->mPath = to;
|
||||
mDir->mDirectoryData->mFiles.push_back(sourceFile);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Path MemFileSystem::mapTo(const Path& path)
|
||||
{
|
||||
String file = mVolume;
|
||||
file = Path::Join(file, '/', path.getPath());
|
||||
file = Path::Join(file, '/', path.getFileName());
|
||||
file = Path::Join(file, '.', path.getExtension());
|
||||
return file;
|
||||
}
|
||||
|
||||
Path MemFileSystem::mapFrom(const Path& path)
|
||||
{
|
||||
const String::SizeType volumePathLen = mVolume.length();
|
||||
|
||||
String pathStr = path.getFullPath();
|
||||
|
||||
if ( mVolume.compare( pathStr, volumePathLen, String::NoCase ))
|
||||
return Path();
|
||||
|
||||
return pathStr.substr( volumePathLen, pathStr.length() - volumePathLen );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
MemFile::MemFile(MemFileSystem* fs, MemFileData* fileData)
|
||||
{
|
||||
mFileData = fileData;
|
||||
mStatus = Closed;
|
||||
mCurrentPos = U32_MAX;
|
||||
mFileSystem = fs;
|
||||
}
|
||||
|
||||
MemFile::~MemFile()
|
||||
{
|
||||
}
|
||||
|
||||
Path MemFile::getName() const
|
||||
{
|
||||
return mFileData->mPath;
|
||||
}
|
||||
|
||||
FileNode::Status MemFile::getStatus() const
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
bool MemFile::getAttributes(Attributes* attr)
|
||||
{
|
||||
return mFileData->getAttributes(attr);
|
||||
}
|
||||
|
||||
U32 MemFile::calculateChecksum()
|
||||
{
|
||||
return CRC::calculateCRC(mFileData->mBuffer, mFileData->mFileSize);
|
||||
}
|
||||
|
||||
bool MemFile::open(AccessMode mode)
|
||||
{
|
||||
mStatus = Open;
|
||||
mCurrentPos = 0;
|
||||
switch (mode)
|
||||
{
|
||||
case Read :
|
||||
case ReadWrite :
|
||||
mCurrentPos = 0;
|
||||
break;
|
||||
case Write :
|
||||
mCurrentPos = 0;
|
||||
mFileData->mFileSize = 0;
|
||||
break;
|
||||
case WriteAppend :
|
||||
mCurrentPos = mFileData->mFileSize;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemFile::close()
|
||||
{
|
||||
mStatus = Closed;
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 MemFile::getPosition()
|
||||
{
|
||||
if (mStatus == Open || mStatus == EndOfFile)
|
||||
return mCurrentPos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
U32 MemFile::setPosition(U32 delta, SeekMode mode)
|
||||
{
|
||||
if (mStatus != Open && mStatus != EndOfFile)
|
||||
return 0;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case Begin:
|
||||
mCurrentPos = delta;
|
||||
break;
|
||||
case Current:
|
||||
mCurrentPos += delta;
|
||||
break;
|
||||
case End:
|
||||
mCurrentPos = mFileData->mFileSize - delta;
|
||||
break;
|
||||
}
|
||||
|
||||
mStatus = Open;
|
||||
|
||||
return mCurrentPos;
|
||||
}
|
||||
|
||||
U32 MemFile::read(void* dst, U32 size)
|
||||
{
|
||||
if (mStatus != Open && mStatus != EndOfFile)
|
||||
return 0;
|
||||
|
||||
U32 copyAmount = getMin(size, mFileData->mFileSize - mCurrentPos);
|
||||
dMemcpy(dst, (U8*) mFileData->mBuffer + mCurrentPos, copyAmount);
|
||||
mCurrentPos += copyAmount;
|
||||
mFileData->mLastAccess = Time::getCurrentTime();
|
||||
if (mCurrentPos == mFileData->mFileSize)
|
||||
mStatus = EndOfFile;
|
||||
return copyAmount;
|
||||
}
|
||||
|
||||
U32 MemFile::write(const void* src, U32 size)
|
||||
{
|
||||
if ((mStatus != Open && mStatus != EndOfFile) || !size)
|
||||
return 0;
|
||||
|
||||
if (mFileData->mFileSize + size > mFileData->mBufferSize)
|
||||
{
|
||||
// Keep doubling our buffer size until we're big enough.
|
||||
while (mFileData->mFileSize + size > mFileData->mBufferSize)
|
||||
mFileData->mBufferSize *= 2;
|
||||
mFileData->mBuffer = dRealloc(mFileData->mBuffer, mFileData->mBufferSize);
|
||||
if (!mFileData->mBuffer)
|
||||
{
|
||||
mStatus = FileSystemFull;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dMemcpy((U8*)mFileData->mBuffer + mCurrentPos, src, size);
|
||||
mCurrentPos += size;
|
||||
mFileData->mFileSize = getMax(mFileData->mFileSize, mCurrentPos);
|
||||
mFileData->mLastAccess = Time::getCurrentTime();
|
||||
mFileData->mModified = mFileData->mLastAccess;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
MemDirectory::MemDirectory(MemFileSystem* fs, MemDirectoryData* dir)
|
||||
{
|
||||
mStatus = Closed;
|
||||
mDirectoryData = dir;
|
||||
mFileSystem = fs;
|
||||
}
|
||||
|
||||
MemDirectory::~MemDirectory()
|
||||
{
|
||||
}
|
||||
|
||||
Path MemDirectory::getName() const
|
||||
{
|
||||
return mDirectoryData->mPath;
|
||||
}
|
||||
|
||||
bool MemDirectory::open()
|
||||
{
|
||||
mSearchIndex = 0;
|
||||
mStatus = Open;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemDirectory::close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemDirectory::read(Attributes* entry)
|
||||
{
|
||||
if (mStatus != Open)
|
||||
return false;
|
||||
|
||||
if (mSearchIndex < mDirectoryData->mDirectories.size())
|
||||
{
|
||||
mDirectoryData->mDirectories[mSearchIndex]->getAttributes(entry);
|
||||
mSearchIndex++;
|
||||
return true;
|
||||
}
|
||||
|
||||
AssertFatal(mSearchIndex > mDirectoryData->mDirectories.size(), "This should not happen!");
|
||||
U32 fileIndex = mSearchIndex - mDirectoryData->mDirectories.size();
|
||||
if (fileIndex < mDirectoryData->mFiles.size())
|
||||
{
|
||||
mDirectoryData->mFiles[mSearchIndex]->getAttributes(entry);
|
||||
mSearchIndex++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
U32 MemDirectory::calculateChecksum()
|
||||
{
|
||||
// Return checksum of current entry
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MemDirectory::getAttributes(Attributes* attr)
|
||||
{
|
||||
return mDirectoryData->getAttributes(attr);
|
||||
}
|
||||
|
||||
FileNode::Status MemDirectory::getStatus() const
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
} // Namespace Mem
|
||||
|
||||
} // Namespace Torque
|
||||
Loading…
Add table
Add a link
Reference in a new issue