From b59451020eee59cd52e4d8231360ebed4fc59adb Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Thu, 19 Nov 2020 04:14:48 -0500 Subject: File system refactor (#1611) * #include an absolute path didn't work - because paths were taken to always be relative. * WIP FileSystem refactor. * Made loadFile load the file in binary mode. * Fixed some comments. Fixed typo in RelativePath - not used 'fixedPath'. --- source/core/slang-blob.h | 88 ++++++++++++++++++++++++++++++++++++++++++------ source/core/slang-io.cpp | 43 +++++++++++++++++++++++ source/core/slang-io.h | 5 +++ 3 files changed, 125 insertions(+), 11 deletions(-) (limited to 'source/core') diff --git a/source/core/slang-blob.h b/source/core/slang-blob.h index aab131a36..8bf02512d 100644 --- a/source/core/slang-blob.h +++ b/source/core/slang-blob.h @@ -69,30 +69,96 @@ protected: void operator=(const ThisType& rhs) = delete; }; + +class ScopedAllocation +{ +public: + typedef ScopedAllocation ThisType; + // Returns the allocation if successful. + void* allocate(size_t size) + { + deallocate(); + m_data = ::malloc(size); + m_sizeInBytes = size; + return m_data; + } + /// Deallocates if holds an allocation + void deallocate() + { + if (m_data) + { + ::free(m_data); + m_data = nullptr; + } + m_sizeInBytes = 0; + } + /// Makes this no longer own the allocation. Returns the allocated data (or nullptr if no allocation) + void* detach() + { + void* data = m_data; + m_data = nullptr; + m_sizeInBytes = 0; + return data; + } + /// Attach some data. + /// NOTE! data must be a pointer that was returned from malloc, otherwise will incorrectly free. + void attach(void* data, size_t size) + { + deallocate(); + m_data = data; + m_sizeInBytes = size; + } + + /// Get the allocated data. Returns nullptr if there is no allocated data + void* getData() const { return m_data; } + /// Get the size of the allocated data. + size_t getSizeInBytes() const { return m_sizeInBytes; } + + ScopedAllocation() : + m_data(nullptr), + m_sizeInBytes(0) + { + } + +private: + // disable + ScopedAllocation(const ThisType& rhs) = delete; + void operator=(const ThisType& rhs) = delete; + + void* m_data; + size_t m_sizeInBytes; +}; + /** A blob that manages some raw data that it owns. */ class RawBlob : public BlobBase { public: // ISlangBlob - SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data; } - SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_size; } + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data.getData(); } + SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_data.getSizeInBytes(); } - // Ctor - RawBlob(const void* data, size_t size) : - m_size(size) + // Ctor + // NOTE! Takes a copy of the input data + RawBlob(const void* data, size_t size) { - m_data = malloc(size); - memcpy(m_data, data, size); + memcpy(m_data.allocate(size), data, size); } - ~RawBlob() + + /// Moves ownership of data and dataCount to the blob + /// data must be a pointer returned by ::malloc. + static RefPtr moveCreate(uint8_t* data, size_t dataCount) { - free(m_data); + RawBlob* blob = new RawBlob; + blob->m_data.attach(data, dataCount); + return blob; } protected: - void* m_data; - size_t m_size; + RawBlob() = default; + + ScopedAllocation m_data; + }; /// Create a blob that will retain (a copy of) raw data. diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp index 5cbe021a2..8e7266dc5 100644 --- a/source/core/slang-io.cpp +++ b/source/core/slang-io.cpp @@ -557,6 +557,49 @@ namespace Slang #endif } + SlangResult Path::remove(const String& path) + { +#ifdef _WIN32 + // Need to determine if its a file or directory + + SlangPathType pathType; + SLANG_RETURN_ON_FAIL(getPathType(path, &pathType)); + + + switch (pathType) + { + case SLANG_PATH_TYPE_FILE: + { + // https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilea + if (DeleteFileA(path.getBuffer())) + { + return SLANG_OK; + } + break; + } + case SLANG_PATH_TYPE_DIRECTORY: + { + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya + if (RemoveDirectoryA(path.getBuffer())) + { + return SLANG_OK; + } + break; + } + default: break; + } + + return SLANG_FAIL; +#else + // https://linux.die.net/man/3/remove + if (::remove(path.getBuffer()) == 0) + { + return SLANG_OK; + } + return SLANG_FAIL; +#endif + } + #if defined(_WIN32) /* static */SlangResult Path::find(const String& directoryPath, const char* pattern, Visitor* visitor) { diff --git a/source/core/slang-io.h b/source/core/slang-io.h index 492723602..3a5510566 100644 --- a/source/core/slang-io.h +++ b/source/core/slang-io.h @@ -126,6 +126,11 @@ namespace Slang /// @param path Path to extract first element from /// @return The first element of the path, or empty static UnownedStringSlice getFirstElement(const UnownedStringSlice& path); + + /// Remove a file or directory at specified path. The directory must be empty for it to be removed + /// @param path + /// @return SLANG_OK if file or directory is removed + static SlangResult remove(const String& path); }; // Helper class to clean up temporary files on dtor -- cgit v1.2.3