summaryrefslogtreecommitdiffstats
path: root/source/core
diff options
context:
space:
mode:
Diffstat (limited to 'source/core')
-rw-r--r--source/core/slang-file-system.cpp35
-rw-r--r--source/core/slang-file-system.h4
-rw-r--r--source/core/slang-implicit-directory-collector.cpp23
-rw-r--r--source/core/slang-implicit-directory-collector.h2
-rw-r--r--source/core/slang-io.cpp45
-rw-r--r--source/core/slang-io.h41
-rw-r--r--source/core/slang-memory-file-system.cpp24
-rw-r--r--source/core/slang-memory-file-system.h4
-rw-r--r--source/core/slang-zip-file-system.cpp35
9 files changed, 156 insertions, 57 deletions
diff --git a/source/core/slang-file-system.cpp b/source/core/slang-file-system.cpp
index 0697810f4..0369d0a02 100644
--- a/source/core/slang-file-system.cpp
+++ b/source/core/slang-file-system.cpp
@@ -871,19 +871,35 @@ SlangResult RelativeFileSystem::_calcCombinedPathInner(SlangPathType fromPathTyp
}
}
-SlangResult RelativeFileSystem::_getCanonicalPath(const char* path, StringBuilder& outPath)
+SlangResult RelativeFileSystem::_getCanonicalPath(const char* path, String& outPath)
{
if (m_stripPath)
{
// We are just using the filename. There is no path that could go outside of the the relative path so we can use as is
- auto fileName = Path::getFileName(path);
-
- outPath.swapWith(fileName);
+ outPath = Path::getFileName(path);
}
else
{
+ // NOTE that we don't want the canonical path to be absolute with a leading "/"
+ // because paths specified which aren't absolute, would produce a different path.
+ //
+ // Ie we want (and get with these options)
+ // "a" -> "a"
+ // "/a" -> "a".
+ //
+ // If we allowed the root to be included then...
+ // "a" -> "a"
+ // "/a" -> "/a"
+ //
+ // Two identical paths would match to different paths, which wouldn't be canonical.
+ //
+ // This could be fixed by making all paths absolute with '/' too, but it's easier to just make all not
+ // have "/"
+
+ StringBuilder canonicalPath;
// We want the input path to be local to this file system
- SLANG_RETURN_ON_FAIL(Path::simplifyAbsolute(path, outPath));
+ SLANG_RETURN_ON_FAIL(Path::simplify(path, Path::SimplifyStyle::AbsoluteOnlyAndNoRoot, canonicalPath));
+ outPath = canonicalPath;
}
return SLANG_OK;
}
@@ -892,11 +908,12 @@ SlangResult RelativeFileSystem::_getFixedPath(const char* path, String& outPath)
{
ComPtr<ISlangBlob> blob;
- StringBuilder canonicalPath;
+ String canonicalPath;
SLANG_RETURN_ON_FAIL(_getCanonicalPath(path, canonicalPath));
+
SLANG_RETURN_ON_FAIL(_calcCombinedPathInner(SLANG_PATH_TYPE_DIRECTORY, m_relativePath.getBuffer(), canonicalPath.getBuffer(), blob.writeRef()));
-
outPath = StringUtil::getString(blob);
+
return SLANG_OK;
}
@@ -957,8 +974,8 @@ SlangResult RelativeFileSystem::getPath(PathKind kind, const char* path, ISlangB
}
case PathKind::Canonical:
{
- StringBuilder canonicalPath;
- SLANG_RETURN_ON_FAIL(_getCanonicalPath(path, canonicalPath));
+ String canonicalPath;
+ SLANG_RETURN_ON_FAIL(_getCanonicalPath(path, canonicalPath));
*outPath = StringBlob::moveCreate(canonicalPath).detach();
return SLANG_OK;
}
diff --git a/source/core/slang-file-system.h b/source/core/slang-file-system.h
index a3efbfe68..93d0659ec 100644
--- a/source/core/slang-file-system.h
+++ b/source/core/slang-file-system.h
@@ -258,8 +258,8 @@ protected:
/// Get the fixed path to the item for the backing file system.
SlangResult _getFixedPath(const char* path, String& outPath);
- /// Get the canonical path
- SlangResult _getCanonicalPath(const char* path, StringBuilder& outPath);
+
+ SlangResult _getCanonicalPath(const char* path, String& outPath);
ISlangUnknown* getInterface(const Guid& guid);
void* getObject(const Guid& guid);
diff --git a/source/core/slang-implicit-directory-collector.cpp b/source/core/slang-implicit-directory-collector.cpp
index 199fd6155..994ebd4d7 100644
--- a/source/core/slang-implicit-directory-collector.cpp
+++ b/source/core/slang-implicit-directory-collector.cpp
@@ -1,5 +1,7 @@
#include "slang-implicit-directory-collector.h"
+#include "slang-io.h"
+
namespace Slang
{
@@ -8,13 +10,28 @@ namespace Slang
ImplicitDirectoryCollector::ImplicitDirectoryCollector(const String& canonicalPath, bool directoryExists) :
m_directoryExists(directoryExists)
{
- StringBuilder buffer;
- if (canonicalPath != ".")
+ if (!isRootPath(canonicalPath.getUnownedSlice()))
{
+ StringBuilder buffer;
buffer << canonicalPath;
buffer.append('/');
+ m_prefix = buffer.ProduceString();
+ }
+}
+
+/* static */bool ImplicitDirectoryCollector::isRootPath(const UnownedStringSlice& path)
+{
+ const auto length = path.getLength();
+ if (length == 0)
+ {
+ return true;
+ }
+ else if (length == 1)
+ {
+ const auto c = path[0];
+ return c == '.' || Path::isDelimiter(c);
}
- m_prefix = buffer.ProduceString();
+ return false;
}
void ImplicitDirectoryCollector::addRemainingPath(SlangPathType pathType, const UnownedStringSlice& inPathRemainder)
diff --git a/source/core/slang-implicit-directory-collector.h b/source/core/slang-implicit-directory-collector.h
index 280ba33e6..3b3505df2 100644
--- a/source/core/slang-implicit-directory-collector.h
+++ b/source/core/slang-implicit-directory-collector.h
@@ -57,6 +57,8 @@ public:
/// Ctor
ImplicitDirectoryCollector(const String& canonicalPath, bool directoryExists = false);
+ static bool isRootPath(const UnownedStringSlice& path);
+
protected:
StringSliceIndexMap m_map;
String m_prefix;
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp
index b25d5562d..345a2c353 100644
--- a/source/core/slang-io.cpp
+++ b/source/core/slang-io.cpp
@@ -419,7 +419,7 @@ namespace Slang
return false;
}
- /* static */SlangResult Path::simplifyAbsolute(const UnownedStringSlice& path, StringBuilder& outPath)
+ /* static */SlangResult Path::simplify(const UnownedStringSlice& path, SimplifyStyle style, StringBuilder& outPath)
{
if (path.getLength() == 0)
{
@@ -427,27 +427,38 @@ namespace Slang
}
List<UnownedStringSlice> splitPath;
- Path::split(UnownedStringSlice(path), splitPath);
+ split(UnownedStringSlice(path), splitPath);
- // If the first part of a path is "", it means path of form "/some/path". Turn into "some/path".
- if (splitPath.getCount() > 1 && splitPath[0].getLength() == 0)
- {
- splitPath.removeAt(0);
- }
+ simplify(splitPath);
- Path::simplify(splitPath);
+ const auto simplifyIntegral = SimplifyIntegral(style);
// If it has a relative part then it's not absolute
- if (splitPath.indexOf(UnownedStringSlice::fromLiteral("..")) >= 0)
+ if ((simplifyIntegral & SimplifyFlag::AbsoluteOnly) &&
+ splitPath.indexOf(UnownedStringSlice::fromLiteral("..")) >= 0)
{
return SLANG_E_NOT_FOUND;
}
// We allow splitPath.getCount() == 0, because
// the original path could have been '.' or './.'
- // Special handling for this is in join
+ //
+ // Special handling this case is in Path::join
+
+ // If we want the path produced such that is *not* output with a root (ie SimplifyFlag::NoRoot)
+ // we detect if we a rooted path (ie in effect starting with "/") and so splitPath[0] == ""
+ // and remove that part from when doing the join.
+ if ((simplifyIntegral & SimplifyFlag::NoRoot) &&
+ (splitPath.getCount() && splitPath[0].getLength() == 0))
+ {
+ // If we allow without a root, we remove from the join
+ Path::join(splitPath.getBuffer() + 1, splitPath.getCount() - 1, outPath);
+ }
+ else
+ {
+ Path::join(splitPath.getBuffer(), splitPath.getCount(), outPath);
+ }
- Path::join(splitPath.getBuffer(), splitPath.getCount(), outPath);
return SLANG_OK;
}
@@ -485,10 +496,16 @@ namespace Slang
if (count == 0)
{
out << ".";
- return;
}
-
- StringUtil::join(slices, count, kPathDelimiter, out);
+ else if (count == 1 && slices[0].getLength() == 0)
+ {
+ // It's the root
+ out << kPathDelimiter;
+ }
+ else
+ {
+ StringUtil::join(slices, count, kPathDelimiter, out);
+ }
}
diff --git a/source/core/slang-io.h b/source/core/slang-io.h
index acdcd0124..292328603 100644
--- a/source/core/slang-io.h
+++ b/source/core/slang-io.h
@@ -39,6 +39,34 @@ namespace Slang
class Path
{
public:
+ typedef uint32_t SimplifyIntegral;
+
+ struct SimplifyFlag
+ {
+ enum Enum : SimplifyIntegral
+ {
+ /// Can only simplify to an absolute path. Will return an error if not possible.
+ /// Useful to constrain a path, such as when wanting something like 'chroot'.
+ AbsoluteOnly = 0x1,
+ /// If the simplified path is a root path, remove the root.
+ /// Will mean that for example
+ /// "/" -> "."
+ /// "/a/.." -> "."
+ /// "/a" -> "a"
+ /// Its worth noting that a path prefixed "/" will never be returned and if *just* the root it specified
+ /// it will return as ".".
+ NoRoot = 0x2,
+ };
+ };
+
+ // A more convenient typesafe way to specify the SimplifyFlag combinations
+ enum SimplifyStyle : SimplifyIntegral
+ {
+ Normal = 0,
+ AbsoluteOnly = SimplifyFlag::AbsoluteOnly,
+ NoRoot = SimplifyFlag::NoRoot,
+ AbsoluteOnlyAndNoRoot = SimplifyFlag::AbsoluteOnly | SimplifyFlag::NoRoot,
+ };
enum class Type
{
@@ -121,16 +149,21 @@ namespace Slang
static bool isDriveSpecification(const UnownedStringSlice& pathPrefix);
/// Splits the path into it's individual bits
+ /// Absolute paths of the form "/" will become [""]
+ /// Absolute paths of the form "a:/" will become ["a:", ""]
+ /// A drive specification of the form "a:" will become ["a:"]
+ /// Relative paths that are in effect "." will become []
static void split(const UnownedStringSlice& path, List<UnownedStringSlice>& splitOut);
+
/// Strips .. and . as much as it can
static String simplify(const UnownedStringSlice& path);
static String simplify(const String& path) { return simplify(path.getUnownedSlice()); }
/// Given a path simplifies it such the the resultant path is absolute (ie contains no . or ..)
- /// Can return '.' as the path as the directory 'root'.
- static SlangResult simplifyAbsolute(const UnownedStringSlice& path, StringBuilder& outPath);
- static SlangResult simplifyAbsolute(const String& path, StringBuilder& outPath) { return simplifyAbsolute(path.getUnownedSlice(), outPath); }
- static SlangResult simplifyAbsolute(const char* path, StringBuilder& outPath) { return simplifyAbsolute(UnownedStringSlice(path), outPath); }
+ /// Same behavior as simplify around the root
+ static SlangResult simplify(const UnownedStringSlice& path, SimplifyStyle style, StringBuilder& outPath);
+ static SlangResult simplify(const String& path, SimplifyStyle style, StringBuilder& outPath) { return simplify(path.getUnownedSlice(), style, outPath); }
+ static SlangResult simplify(const char* path, SimplifyStyle style, StringBuilder& outPath) { return simplify(UnownedStringSlice(path), style, outPath); }
/// Simplifies the path split up
static void simplify(List<UnownedStringSlice>& ioSplit);
diff --git a/source/core/slang-memory-file-system.cpp b/source/core/slang-memory-file-system.cpp
index 06c0a4ebe..a6bc05f24 100644
--- a/source/core/slang-memory-file-system.cpp
+++ b/source/core/slang-memory-file-system.cpp
@@ -9,6 +9,11 @@
namespace Slang
{
+MemoryFileSystem::MemoryFileSystem()
+{
+ m_rootEntry.initDirectory("/");
+}
+
void* MemoryFileSystem::getInterface(const Guid& guid)
{
if ( guid == ISlangUnknown::getTypeGuid() ||
@@ -40,15 +45,18 @@ void* MemoryFileSystem::castAs(const Guid& guid)
void MemoryFileSystem::_clear()
{
m_entries = Dictionary<String, Entry>();
- // Add the root
- Entry entry;
- entry.initDirectory(".");
- m_entries.Add(entry.m_canonicalPath, entry);
}
MemoryFileSystem::Entry* MemoryFileSystem::_getEntryFromCanonicalPath(const String& canonicalPath)
{
- return m_entries.TryGetValue(canonicalPath);
+ if (canonicalPath == toSlice("."))
+ {
+ return &m_rootEntry;
+ }
+ else
+ {
+ return m_entries.TryGetValue(canonicalPath);
+ }
}
MemoryFileSystem::Entry* MemoryFileSystem::_getEntryFromPath(const char* path, String* outPath)
@@ -141,7 +149,7 @@ SlangResult MemoryFileSystem::getPath(PathKind kind, const char* path, ISlangBlo
case PathKind::Canonical:
{
StringBuilder buffer;
- SLANG_RETURN_ON_FAIL(Path::simplifyAbsolute(path, buffer));
+ SLANG_RETURN_ON_FAIL(_getCanonical(path, buffer));
*outPath = StringBlob::moveCreate(buffer).detach();
return SLANG_OK;
}
@@ -197,7 +205,7 @@ SlangResult MemoryFileSystem::saveFileBlob(const char* path, ISlangBlob* dataBlo
SlangResult MemoryFileSystem::_getCanonical(const char* path, StringBuilder& outCanonicalPath)
{
StringBuilder canonicalPath;
- SLANG_RETURN_ON_FAIL(Path::simplifyAbsolute(UnownedStringSlice(path), outCanonicalPath));
+ SLANG_RETURN_ON_FAIL(Path::simplify(UnownedStringSlice(path), Path::SimplifyStyle::AbsoluteOnlyAndNoRoot, outCanonicalPath));
return SLANG_OK;
}
@@ -260,7 +268,7 @@ SlangResult MemoryFileSystem::remove(const char* path)
Entry* entry = _getEntryFromPath(path, &canonicalPath);
// If there is an entry and not the root of the file system
- if (entry && entry->m_canonicalPath != toSlice("."))
+ if (entry && entry != &m_rootEntry)
{
if (entry->m_type == SLANG_PATH_TYPE_DIRECTORY)
{
diff --git a/source/core/slang-memory-file-system.h b/source/core/slang-memory-file-system.h
index cd2701fe4..785335986 100644
--- a/source/core/slang-memory-file-system.h
+++ b/source/core/slang-memory-file-system.h
@@ -55,7 +55,7 @@ public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(const char* path) SLANG_OVERRIDE;
/// Ctor
- MemoryFileSystem() { _clear(); }
+ MemoryFileSystem();
protected:
@@ -129,6 +129,8 @@ protected:
// Maps canonical paths to an entries (which could be files or directories)
Dictionary<String, Entry> m_entries;
+
+ Entry m_rootEntry;
};
}
diff --git a/source/core/slang-zip-file-system.cpp b/source/core/slang-zip-file-system.cpp
index 28782dba7..011fd2aab 100644
--- a/source/core/slang-zip-file-system.cpp
+++ b/source/core/slang-zip-file-system.cpp
@@ -418,15 +418,8 @@ SlangResult ZipFileSystemImpl::_requireMode(Mode newMode)
SlangResult ZipFileSystemImpl::_getFixedPath(const char* path, String& outPath)
{
- String simplifiedPath = Path::simplify(UnownedStringSlice(path));
- // Can simplify to just ., thats okay, if it otherwise has something relative it means it couldn't be simplified into the
- // contents of the archive
- if (simplifiedPath != "." && Path::hasRelativeElement(simplifiedPath))
- {
- // If it still has a relative element, then it must be 'outside' of the archive
- return SLANG_E_NOT_FOUND;
- }
-
+ StringBuilder simplifiedPath;
+ SLANG_RETURN_ON_FAIL(Path::simplify(path, Path::SimplifyStyle::AbsoluteOnlyAndNoRoot, simplifiedPath));
outPath = simplifiedPath;
return SLANG_OK;
}
@@ -528,17 +521,27 @@ SlangResult ZipFileSystemImpl::getPath(PathKind pathKind, const char* path, ISla
case PathKind::Display:
case PathKind::Canonical:
{
- mz_uint index;
- SLANG_RETURN_ON_FAIL(_findEntryIndex(path, index));
+ // Get the fixed path
+ String fixedPath;
+ SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
- mz_zip_archive_file_stat fileStat;
- if (!mz_zip_reader_file_stat(&m_archive, index, &fileStat))
+ // See if we can find in the zip explicitly
+ mz_uint index;
+ if (SLANG_SUCCEEDED(_findEntryIndexFromFixedPath(fixedPath, index)))
{
- return SLANG_FAIL;
+ mz_zip_archive_file_stat fileStat;
+ if (!mz_zip_reader_file_stat(&m_archive, index, &fileStat))
+ {
+ return SLANG_FAIL;
+ }
+
+ // Use the path in the archive itself
+ *outPath = StringUtil::createStringBlob(fileStat.m_filename).detach();
+ return SLANG_OK;
}
- // Use the path in the archive itself
- *outPath = StringUtil::createStringBlob(fileStat.m_filename).detach();
+ // Else output the fixed path
+ *outPath = StringUtil::createStringBlob(fixedPath).detach();
return SLANG_OK;
}
case PathKind::Simplified: