Skip to content

Commit

Permalink
COMMON: Archive refactoring, add support for non-slash file separator…
Browse files Browse the repository at this point in the history
…s, add getPathInArchive and resolve some inconsistencies in name vs. path handling.
  • Loading branch information
elasota committed Jun 20, 2023
1 parent c727f32 commit 1113f88
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 29 deletions.
25 changes: 18 additions & 7 deletions common/archive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,20 @@

namespace Common {

GenericArchiveMember::GenericArchiveMember(const String &name, const Archive *parent)
: _parent(parent), _name(name) {
GenericArchiveMember::GenericArchiveMember(const Path &path, const Archive *parent)
: _parent(parent), _path(path) {
}

String GenericArchiveMember::getName() const {
return _name;
return _path.getLastComponent().toString();
}

Path GenericArchiveMember::getPathInArchive() const {
return _path;
}

SeekableReadStream *GenericArchiveMember::createReadStream() const {
return _parent->createReadStreamForMember(_name);
return _parent->createReadStreamForMember(_path);
}


Expand All @@ -47,15 +51,22 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const Path &pattern, b
ArchiveMemberList allNames;
listMembers(allNames);

String patternString = pattern.toString();
String patternString = pattern.toString(getPathSeparator());
int matches = 0;
const char *wildcardExclusions = matchPathComponents ? NULL : "/";
const char *wildcardExclusions = nullptr;

char exclusionsStr[2] = {0, 0};

if (!matchPathComponents) {
exclusionsStr[0] = getPathSeparator();
wildcardExclusions = exclusionsStr;
}

ArchiveMemberList::const_iterator it = allNames.begin();
for (; it != allNames.end(); ++it) {
// TODO: We match case-insenstivie for now, our API does not define whether that's ok or not though...
// For our use case case-insensitive is probably what we want to have though.
if ((*it)->getName().matchString(patternString, true, wildcardExclusions)) {
if ((*it)->getPathInArchive().toString(getPathSeparator()).matchString(patternString, true, wildcardExclusions)) {
list.push_back(*it);
matches++;
}
Expand Down
15 changes: 10 additions & 5 deletions common/archive.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class ArchiveMember {
virtual ~ArchiveMember() { }
virtual SeekableReadStream *createReadStream() const = 0; /*!< Create a read stream. */
virtual String getName() const = 0; /*!< Get the name of the archive member. */
virtual Path getPathInArchive() const { return Path(getName()); } /*!< Get the full path of the archive member relative to the archive. */
virtual U32String getDisplayName() const { return getName(); } /*!< Get the display name of the archive member. */
};

Expand Down Expand Up @@ -86,12 +87,16 @@ class Archive;
* is destroyed.
*/
class GenericArchiveMember : public ArchiveMember {
const Archive *_parent;
const String _name;
public:
GenericArchiveMember(const String &name, const Archive *parent); /*!< Create a generic archive member that belongs to the @p parent archive. */
String getName() const; /*!< Get the name of a generic archive member. */
SeekableReadStream *createReadStream() const; /*!< Create a read stream. */
GenericArchiveMember(const Path &path, const Archive *parent); /*!< Create a generic archive member that belongs to the @p parent archive. */

String getName() const override; /*!< Get the name of a generic archive member. */
Path getPathInArchive() const override; /*!< Get the full path of the archive member relative to the archive. */
SeekableReadStream *createReadStream() const override; /*!< Create a read stream. */

private:
const Archive *_parent;
const Path _path;
};


Expand Down
3 changes: 1 addition & 2 deletions common/compression/stuffit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,7 @@ int StuffItArchive::listMembers(Common::ArchiveMemberList &list) const {
}

const Common::ArchiveMemberPtr StuffItArchive::getMember(const Common::Path &path) const {
Common::String name = path.toString(':');
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, this));
}

Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::String& name) const {
Expand Down
27 changes: 17 additions & 10 deletions common/compression/vise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ class MacVISEArchive : public Common::Archive {
uint16 containingDirectory;

Common::String name;
Common::String fullPath;
Common::Path fullPath;
};

struct DirectoryDesc {
uint16 containingDirectory;

Common::String name;
Common::String fullPath;
Common::Path fullPath;
};

class ArchiveMember : public Common::ArchiveMember {
Expand All @@ -76,6 +76,7 @@ class MacVISEArchive : public Common::Archive {

Common::SeekableReadStream *createReadStream() const override;
Common::String getName() const override;
Common::Path getPathInArchive() const override;

private:
Common::SeekableReadStream *_archiveStream;
Expand Down Expand Up @@ -199,10 +200,14 @@ Common::SeekableReadStream *MacVISEArchive::ArchiveMember::createReadStream() co
}

Common::String MacVISEArchive::ArchiveMember::getName() const {
return getPathInArchive().getLastComponent().toString(':');
}

Common::Path MacVISEArchive::ArchiveMember::getPathInArchive() const {
if (_substreamType == kSubstreamTypeFinderInfo)
return _fileDesc->fullPath + ".finf";
return _fileDesc->fullPath.append(".finf");
else if (_substreamType == kSubstreamTypeResource)
return _fileDesc->fullPath + ".rsrc";
return _fileDesc->fullPath.append(".rsrc");
else
return _fileDesc->fullPath;
}
Expand Down Expand Up @@ -320,7 +325,7 @@ bool MacVISEArchive::loadCatalog() {
if (dirDesc.containingDirectory > _directoryDescs.size())
error("VISE 3 containing directory index was invalid");

dirDesc.fullPath = _directoryDescs[dirDesc.containingDirectory - 1].fullPath + ":" + dirDesc.name;
dirDesc.fullPath = _directoryDescs[dirDesc.containingDirectory - 1].fullPath.appendComponent(dirDesc.name);
}
}

Expand All @@ -331,17 +336,16 @@ bool MacVISEArchive::loadCatalog() {
if (fileDesc.containingDirectory > _directoryDescs.size())
error("VISE 3 containing directory index was invalid");

fileDesc.fullPath = _directoryDescs[fileDesc.containingDirectory - 1].fullPath + ":" + fileDesc.name;
fileDesc.fullPath = _directoryDescs[fileDesc.containingDirectory - 1].fullPath.appendComponent(fileDesc.name);
}
}

return true;
}

const MacVISEArchive::FileDesc *MacVISEArchive::getFileDesc(const Common::Path &path) const {
Common::String convertedPath = path.toString(':');
for (const FileDesc &desc : _fileDescs) {
if (desc.fullPath == convertedPath)
if (desc.fullPath == path)
return &desc;
}

Expand Down Expand Up @@ -396,7 +400,8 @@ char MacVISEArchive::getPathSeparator() const {
}

bool MacVISEArchive::getFileDescIndex(const Common::Path &path, uint &outIndex, ArchiveMember::SubstreamType &outSubstreamType) const {
Common::String convertedPath = path.toString(':');
Common::String convertedPath = path.toString(getPathSeparator());

ArchiveMember::SubstreamType substreamType = ArchiveMember::kSubstreamTypeData;
if (convertedPath.hasSuffix(".rsrc")) {
substreamType = ArchiveMember::kSubstreamTypeResource;
Expand All @@ -406,10 +411,12 @@ bool MacVISEArchive::getFileDescIndex(const Common::Path &path, uint &outIndex,
convertedPath = convertedPath.substr(0, convertedPath.size() - 5);
}

Common::Path filePath(convertedPath, getPathSeparator());

for (uint descIndex = 0; descIndex < _fileDescs.size(); descIndex++) {
const FileDesc &desc = _fileDescs[descIndex];

if (desc.fullPath == convertedPath) {
if (desc.fullPath == filePath) {
if (substreamType == ArchiveMember::SubstreamType::kSubstreamTypeData && desc.uncompressedDataSize == 0)
return false;
if (substreamType == ArchiveMember::SubstreamType::kSubstreamTypeResource && desc.uncompressedResSize == 0)
Expand Down
45 changes: 40 additions & 5 deletions common/fs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,41 @@

namespace Common {

// File-in-directory archive member that captures relative path
class FSDirectoryFile : public ArchiveMember {
public:
FSDirectoryFile(const Common::Path &pathInDirectory, const FSNode &fsNode);

SeekableReadStream *createReadStream() const override;
String getName() const override;
Path getPathInArchive() const override;
U32String getDisplayName() const override;

private:
Common::Path _pathInDirectory;
FSNode _fsNode;
};

FSDirectoryFile::FSDirectoryFile(const Common::Path &pathInDirectory, const FSNode &fsNode) : _pathInDirectory(pathInDirectory), _fsNode(fsNode) {
}

SeekableReadStream *FSDirectoryFile::createReadStream() const {
return _fsNode.createReadStream();
}

String FSDirectoryFile::getName() const {
return _fsNode.getName();
}

Path FSDirectoryFile::getPathInArchive() const {
return _pathInDirectory;
}

U32String FSDirectoryFile::getDisplayName() const {
return _fsNode.getDisplayName();
}


FSNode::FSNode() {
}

Expand Down Expand Up @@ -245,7 +280,7 @@ const ArchiveMemberPtr FSDirectory::getMember(const Path &path) const {
return ArchiveMemberPtr();
}

return ArchiveMemberPtr(new FSNode(*node));
return ArchiveMemberPtr(new FSDirectoryFile(path, *node));
}

SeekableReadStream *FSDirectory::createReadStreamForMember(const Path &path) const {
Expand Down Expand Up @@ -337,14 +372,14 @@ int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const Path &patter
int matches = 0;
for (NodeCache::const_iterator it = _fileCache.begin(); it != _fileCache.end(); ++it) {
if (it->_key.matchPattern(pattern)) {
list.push_back(ArchiveMemberPtr(new FSNode(it->_value)));
list.push_back(ArchiveMemberPtr(new FSDirectoryFile(it->_key, it->_value)));
matches++;
}
}
if (_includeDirectories) {
for (NodeCache::const_iterator it = _subDirCache.begin(); it != _subDirCache.end(); ++it) {
if (it->_key.matchPattern(pattern)) {
list.push_back(ArchiveMemberPtr(new FSNode(it->_value)));
list.push_back(ArchiveMemberPtr(new FSDirectoryFile(it->_key, it->_value)));
matches++;
}
}
Expand All @@ -362,13 +397,13 @@ int FSDirectory::listMembers(ArchiveMemberList &list) const {

int files = 0;
for (NodeCache::const_iterator it = _fileCache.begin(); it != _fileCache.end(); ++it) {
list.push_back(ArchiveMemberPtr(new FSNode(it->_value)));
list.push_back(ArchiveMemberPtr(new FSDirectoryFile(it->_key, it->_value)));
++files;
}

if (_includeDirectories) {
for (NodeCache::const_iterator it = _subDirCache.begin(); it != _subDirCache.end(); ++it) {
list.push_back(ArchiveMemberPtr(new FSNode(it->_value)));
list.push_back(ArchiveMemberPtr(new FSDirectoryFile(it->_key, it->_value)));
++files;
}
}
Expand Down

0 comments on commit 1113f88

Please sign in to comment.