Skip to content

Commit

Permalink
Added initial interface for file archives.
Browse files Browse the repository at this point in the history
Adjusted directory iteration interface to return dsPathStatus, which covers
both the original intent of dsDirectoryEntryResult and whether the result
is a file or directory. The entry name is now provided as an output
parameter with a size that may be provided.
  • Loading branch information
akb825 committed Jan 5, 2025
1 parent d1bd73d commit 300d8ff
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 81 deletions.
97 changes: 97 additions & 0 deletions modules/Core/Core/include/DeepSea/Core/Streams/FileArchive.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright 2025 Aaron Barany
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <DeepSea/Core/Config.h>
#include <DeepSea/Core/Export.h>
#include <DeepSea/Core/Streams/Types.h>

#ifdef __cplusplus
extern "C"
{
#endif

/**
* @file
* @brief Functions for operating on file archives.
* @see dsFileArchive
*/

/**
* @brief Gets the status on a path within the archive.
* @remark errno will be set on failure.
* @param archive The archive to get the path status from.
* @param path The path within the archive.
* @return The path status.
*/
DS_CORE_EXPORT dsPathStatus dsFileArchive_pathStatus(
const dsFileArchive* archive, const char* path);

/**
* @brief Opens a directory within an archive.
* @remark errno will be set on failure.
* @param archive The archive to open the directory from.
* @param path The path to the directory within the archive.
* @return The directory iterator or NULL if the directory cannot be iterated.
*/
DS_CORE_EXPORT dsDirectoryIterator dsFileArchive_openDirectory(
const dsFileArchive* archive, const char* path);

/**
* @brief Gets the next entry within a directory in an archive.
* @remark errno will be set on failure.
* @param[out] result The storage for the result.
* @param resultSize The maximum size of the result.
* @param archive The archive the directory was opened with.
* @param iterator The iterator for the directory.
* @return The result of getting the next entry. dsPathStatus_Missing will be returned once the last
* entry has been reached.
*/
DS_CORE_EXPORT dsPathStatus dsFileArchive_nextDirectoryEntry(
char* result, size_t resultSize, const dsFileArchive* archive, dsDirectoryIterator iterator);

/**
* @brief Closes a directory within an archive.
* @remark errno will be set on failure.
* @param archive The archive the directory was opened with.
* @param iterator The iterator for the directory to close.
* @return False if the directory couldn't be closed.
*/
DS_CORE_EXPORT bool dsFileArchive_closeDirectory(
const dsFileArchive* archive, dsDirectoryIterator iterator);

/**
* @brief Opens a file within an archive.
* @remark errno will be set on failure.
* @param archive The archive to open the file with.
* @param path The path to the file to open.
* @return The opened stream or NULL if the file couldn't be opened.
*/
DS_CORE_EXPORT dsStream* dsFileArchive_openFile(const dsFileArchive* archive, const char* path);

/**
* @brief Closes a file within an archive.
* @remark errno will be set on failure.
* @param archive The archive the file was opened with.
* @param stream The stream for the file that was oepend.
* @return False if the file couldn't be closed.
*/
DS_CORE_EXPORT bool dsFileArchive_closeFile(const dsFileArchive* archive, dsStream* stream);

#ifdef __cplusplus
}
#endif
12 changes: 7 additions & 5 deletions modules/Core/Core/include/DeepSea/Core/Streams/FileStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extern "C"
* @param path The path to a file or directory.
* @return The status of the file.
*/
DS_CORE_EXPORT dsPathStatus dsFileStream_getPathStatus(const char* path);
DS_CORE_EXPORT dsPathStatus dsFileStream_pathStatus(const char* path);

/**
* @brief Creates a directory on the filesystem.
Expand Down Expand Up @@ -81,12 +81,14 @@ DS_CORE_EXPORT dsDirectoryIterator dsFileStream_openDirectory(const char* path);
* The . and .. entries will be implicitly skipped.
*
* @remark errno will be set on failure.
* @param[out] outEntry The entry to populate.
* @param[out] result The storage for the result.
* @param resultSize The maximum size of the result.
* @param iterator The iterator to get the next entry with.
* @return The result of getting the next entry.
* @return The result of getting the next entry. dsPathStatus_Missing will be returned once the last
* entry has been reached.
*/
DS_CORE_EXPORT dsDirectoryEntryResult dsFileStream_nextDirectoryEntry(
dsDirectoryEntry* outEntry, dsDirectoryIterator iterator);
DS_CORE_EXPORT dsPathStatus dsFileStream_nextDirectoryEntry(
char* result, size_t resultSize, dsDirectoryIterator iterator);

/**
* @brief Closes a directory.
Expand Down
16 changes: 9 additions & 7 deletions modules/Core/Core/include/DeepSea/Core/Streams/ResourceStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
#pragma once

#include <DeepSea/Core/Config.h>

#include <DeepSea/Core/Streams/Stream.h>
#include <DeepSea/Core/Export.h>
#include <DeepSea/Core/Types.h>
#include <DeepSea/Core/Streams/Stream.h>

#ifdef __cplusplus
extern "C"
Expand Down Expand Up @@ -110,8 +111,7 @@ DS_CORE_EXPORT bool dsResourceStream_getPath(char* outResult, size_t resultSize,
* @param path The path to a file or directory.
* @return The status of the file.
*/
DS_CORE_EXPORT dsPathStatus dsResourceStream_getPathStatus(
dsFileResourceType type, const char* path);
DS_CORE_EXPORT dsPathStatus dsResourceStream_pathStatus(dsFileResourceType type, const char* path);

/**
* @brief Creates a directory on a resource path.
Expand Down Expand Up @@ -162,12 +162,14 @@ DS_CORE_EXPORT dsDirectoryIterator dsResourceStream_openDirectory(
* @remark When listing a directory for an embedded path on Android, due to limitations of the
* NDK only file entries will be listed.
* @remark errno will be set on failure.
* @param[out] outEntry The entry to populate.
* @param[out] result The storage for the result.
* @param resultSize The maximum size of the result.
* @param iterator The iterator to get the next entry with.
* @return The result of getting the next entry.
* @return The result of getting the next entry. dsPathStatus_Missing will be returned once the last
* entry has been reached.
*/
DS_CORE_EXPORT dsDirectoryEntryResult dsResourceStream_nextDirectoryEntry(
dsDirectoryEntry* outEntry, dsDirectoryIterator iterator);
DS_CORE_EXPORT dsPathStatus dsResourceStream_nextDirectoryEntry(
char* result, size_t resultSize, dsDirectoryIterator iterator);

/**
* @brief Closes a directory.
Expand Down
111 changes: 93 additions & 18 deletions modules/Core/Core/include/DeepSea/Core/Streams/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ extern "C"

/// @cond Doxygen_Suppress
typedef struct dsAllocator dsAllocator;
typedef struct dsFileArchive dsFileArchive;
typedef struct dsStream dsStream;
/// @endcond

Expand Down Expand Up @@ -124,16 +125,6 @@ typedef enum dsPathStatus
dsPathStatus_ExistsDirectory ///< Path exists as a directory.
} dsPathStatus;

/**
* @brief Enum for the result of retrieving a directory entry.
*/
typedef enum dsDirectoryEntryResult
{
dsDirectoryEntryResult_Success, ///< The directory entry was successfully retrieved.
dsDirectoryEntryResult_End, ///< The end of the directory was reached.
dsDirectoryEntryResult_Error ///< An error occurred when getting the entry.
} dsDirectoryEntryResult;

/**
* @brief Function for reading from a stream.
* @param stream The stream to read from.
Expand Down Expand Up @@ -194,7 +185,7 @@ typedef bool (*dsStreamCloseFunction)(dsStream* stream);
*
* A stream can be used to read and write data from various sources such as a file or memory buffer.
*
* This can be "subclassed" by having it as the first member of other allocator structures. This can
* This can be "subclassed" by having it as the first member of other stream structures. This can
* be done to add additional data to the stream and have it be freely casted between the
* dsStream and the true stream type.
*
Expand Down Expand Up @@ -371,20 +362,104 @@ typedef struct dsResourceStream
typedef void* dsDirectoryIterator;

/**
* @brief Structure that defines an entry within a directory.
* @brief Function to get the path status for a file archive.
* @param archive The archive to get the path status from.
* @param path The path to get the status for.
* @return The path status.
*/
typedef dsPathStatus (*dsGetFileArchivePathStatusFunction)(
const dsFileArchive* archive, const char* path);

/**
* @brief Function to open a directory for an archive.
* @param archive The archive to open the directory on.
* @param path The path to the directory.
* @return The directory iterator.
*/
typedef dsDirectoryIterator (*dsOpenFileArchiveDirectoryFunction)(
const dsFileArchive* archive, const char* path);

/**
* @brief Function to get the next entry in an archive directory.
* @param[out] result The storage for the result.
* @param resultSize The maximum size of the result.
* @param archive The archive the directory is open on.
* @param iterator The iterator for the directory.
* @return The result of getting the next entry.
*/
typedef dsPathStatus (*dsNextFileArchiveDirectoryEntryFunction)(
char* result, size_t resultSize, const dsFileArchive* archive, dsDirectoryIterator iterator);

/**
* @brief Function to close a directory for an archive.
* @param archive The archive the directory is open on.
* @param iterator The iterator for the directory to close.
* @return False if the directory couldn't be closed.
*/
typedef bool (*dsCloseFileArchiveDirectoryFunction)(
const dsFileArchive* archive, dsDirectoryIterator iterator);

/**
* @brief Function to open a file on an archive.
* @param archive The archive to open the file from.
* @param path The path to the file.
* @return The opened stream or NULL if the file couldn't be opened.
*/
typedef dsStream* (*dsOpenFileArchiveFileFunction)(const dsFileArchive* archive, const char* path);

/**
* @brief Function to close a file on an archive.
* @param archive The archive to close the file from.
* @param stream The stream previously opened.
* @return False if the file couldn't be closed.
*/
typedef struct dsDirectoryEntry
typedef bool (*dsCloseFileArchiveFileFunction)(const dsFileArchive* archive, dsStream* stream);

/**
* @brief Struct describing an archive of files.
*
* Archives are read-only, and intended to group multiple files and directories into a single unit,
* often with compression. Implementations should ensure that multiple files can be opened
* simultaneously across multiple threads.
*
* This can be "subclassed" by having it as the first member of other archive structures. This can
* be done to add additional data to the archive and have it be freely casted between the
* dsFileArchive and the true stream type.
*
* @see FileArchive.h
*/
struct dsFileArchive
{
/**
* @brief Whether this entry is itself a directory.
* @brief Function to get the status of a path within the archive.
*/
bool isDirectory;
dsGetFileArchivePathStatusFunction getPathStatusFunc;

/**
* @brief The name of the entry.
* @brief Function to open a directory within the archive.
*/
char name[DS_FILE_NAME_MAX];
} dsDirectoryEntry;
dsOpenFileArchiveDirectoryFunction openDirectoryFunc;

/**
* @brief Function to get the next directory entry within the archive.
*/
dsNextFileArchiveDirectoryEntryFunction nextDirectoryEntryFunc;

/**
* @brief Function to close a directory within the archive.
*/
dsCloseFileArchiveDirectoryFunction closeDirectoryFunc;

/**
* @brief Function to open a file within the archive.
*/
dsOpenFileArchiveFileFunction openFileFunc;

/**
* @brief Function to close a file within the archive.
*/
dsCloseFileArchiveFileFunction closeFileFunc;
};

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 300d8ff

Please sign in to comment.