Ver Fonte

Add ApkFilesystem

Daniele Bartolini há 12 anos atrás
pai
commit
15e24bcf8b

+ 0 - 91
engine/os/android/APKFile.h

@@ -1,91 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-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.
-*/
-
-#pragma once
-
-#include <sys/types.h>
-#include <android/asset_manager.h>
-
-#include "Types.h"
-#include "File.h"
-
-namespace crown
-{
-
-AAssetManager* get_android_asset_manager();
-
-/// Android assets wrapper
-class APKFile
-{
-public:
-
-	/// Opens the file located at @a path with the given @a mode.
-							APKFile(const char* path, FileOpenMode mode);
-							~APKFile();
-
-	/// Closes the file.
-	void					close();
-
-	bool					is_open() const;
-
-	/// Return the size of the file in bytes.
-	size_t					size() const;
-
-	/// Returs the mode used to open the file.
-	FileOpenMode			mode() const;
-
-	/// Reads @a size bytes from the file and stores it into @a data.
-	/// Returns the number of bytes read.
-	size_t					read(void* data, size_t size);
-
-	/// Writes @a size bytes of data stored in @a data and returns the
-	/// number of bytes written.
-	size_t					write(const void* data, size_t size);
-
-	/// Moves the file pointer to the given @a position.
-	void					seek(size_t position);
-
-	/// Moves the file pointer to the end of the file.
-	void					seek_to_end();
-
-	/// Moves the file pointer @a bytes bytes ahead the current
-	/// file pointer position.
-	void					skip(size_t bytes);
-
-	/// Returns the position of the file pointer from the
-	/// start of the file in bytes.
-	size_t					position() const;
-
-	/// Returns whether the file pointer is at the end of the file.
-	bool					eof() const;
-
-private:
-
-	AAsset*					m_asset;
-	FileOpenMode			m_mode;
-};
-
-} // namespace crown

+ 0 - 144
engine/os/android/AndroidMountPoint.cpp

@@ -1,144 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-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 "AndroidMountPoint.h"
-#include "AndroidFile.h"
-#include "StringUtils.h"
-#include "Allocator.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-AndroidMountPoint::AndroidMountPoint() : MountPoint(ANDROID_TYPE)
-{
-}
-
-//-----------------------------------------------------------------------------
-File* AndroidMountPoint::open(const char* relative_path, FileOpenMode /*mode*/)
-{
-	CE_ASSERT(exists(relative_path), "File does not exist: %s", relative_path);
-	CE_ASSERT(is_file(relative_path), "File is not a regular file: %s", relative_path);
-
-	return CE_NEW(default_allocator(), AndroidFile)(relative_path);
-}
-
-//-----------------------------------------------------------------------------
-void AndroidMountPoint::close(File* file)
-{
-	CE_DELETE(default_allocator(), file);
-}
-
-//-----------------------------------------------------------------------------
-void AndroidMountPoint::set_root_path(const char* /*root_path*/)
-{
-	Log::w("Stub: Android root path is always assets folder");
-}
-
-
-//-----------------------------------------------------------------------------
-const char* AndroidMountPoint::root_path()
-{
-	Log::w("Stub: Android root path is always assets folder");
-	return "Assets Folder";
-}
-
-//-----------------------------------------------------------------------------
-bool AndroidMountPoint::exists(const char* relative_path)
-{
-	MountPointEntry info;
-
-	return get_info(relative_path, info);
-}
-
-//-----------------------------------------------------------------------------
-bool AndroidMountPoint::get_info(const char* relative_path, MountPointEntry& info)
-{
-	// Entering OS-DEPENDENT-PATH-MODE (Android assets folder)
-
-	const char* os_path = relative_path;
-
-	string::strncpy(info.os_path, "", MAX_PATH_LENGTH);
-	string::strncpy(info.relative_path, relative_path, MAX_PATH_LENGTH);
-
-	AAssetDir* root = AAssetManager_openDir(get_android_asset_manager(), info.os_path);
-
-	char asset_name[512];
-
-	string::strncpy(asset_name, AAssetDir_getNextFileName(root), 512);
-
-	while (asset_name != NULL)
-	{
-		if (string::strcmp(asset_name, relative_path) == 0)
-		{
-			info.type = MountPointEntry::FILE;
-			AAssetDir_rewind(root);
-			return true;			
-		}
-
-		string::strncpy(asset_name, AAssetDir_getNextFileName(root), 512);
-	}
-	
-	info.type = MountPointEntry::UNKNOWN;
-
-	return false;
-}
-
-//-----------------------------------------------------------------------------
-bool AndroidMountPoint::is_file(const char* relative_path)
-{
-	MountPointEntry info;
-
-	if (get_info(relative_path, info))
-	{
-		return info.type == MountPointEntry::FILE;
-	}
-
-	return false;
-}
-
-//-----------------------------------------------------------------------------
-bool AndroidMountPoint::is_dir(const char* relative_path)
-{
-	MountPointEntry info;
-
-	if (get_info(relative_path, info))
-	{
-		return info.type == MountPointEntry::DIRECTORY;
-	}
-
-	return false;
-}
-
-//-----------------------------------------------------------------------------
-const char* AndroidMountPoint::os_path(const char* /*relative_path*/)
-{
-	return "";
-}
-
-
-
-} // namespace crown

+ 0 - 58
engine/os/android/AndroidMountPoint.h

@@ -1,58 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-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.
-*/
-
-#pragma once
-
-#include "MountPoint.h"
-
-namespace crown
-{
-
-class AndroidMountPoint : public MountPoint
-{
-public:
-						AndroidMountPoint();
-
-	File* 				open(const char* relative_path, FileOpenMode mode);
-
-	void				close(File* file);
-
-	void				set_root_path(const char*);
-
-	const char*			root_path();
-
-	bool				exists(const char* relative_path);
-
-	bool				get_info(const char* relative_path, MountPointEntry& info);
-	
-	bool				is_file(const char* relative_path);
-
-	bool				is_dir(const char* relative_path);
-
-	const char*			os_path(const char* relative_path);
-};
-
-} // namespace crown

+ 57 - 48
engine/os/android/APKFile.cpp → engine/os/android/ApkFile.cpp

@@ -25,36 +25,36 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include <android/asset_manager_jni.h>
-
-#include "APKFile.h"
+#include "ApkFile.h"
 #include "Assert.h"
-#include "OS.h"
-
-namespace crown
-{
 
-static AAssetManager*	g_android_asset_manager = NULL;
+static AAssetManager* g_android_asset_manager = NULL;
 
 //-----------------------------------------------------------------------------
-APKFile::APKFile(const char* path, FileOpenMode mode)
+AAssetManager* get_android_asset_manager()
 {
-	// Android assets are always read-only
-	(void) mode;
-
-	m_mode = FOM_READ;
-	m_asset = AAssetManager_open(get_android_asset_manager(), path, AASSET_MODE_RANDOM);
+	return g_android_asset_manager;
+}
 
-	CE_ASSERT(m_asset != NULL, "Unable to open file: %s", path);
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initAssetManager(JNIEnv* env, jobject obj, jobject assetManager)
+{
+	g_android_asset_manager = AAssetManager_fromJava(env, assetManager);
 }
 
+namespace crown
+{
+
 //-----------------------------------------------------------------------------
-APKFile::~APKFile()
+ApkFile::ApkFile(const char* path)
+	: File(FOM_READ)
 {
-	close();
+	m_asset = AAssetManager_open(get_android_asset_manager(), path, AASSET_MODE_RANDOM);
+	CE_ASSERT(m_asset != NULL, "Unable to open file: %s", path);
 }
 
 //-----------------------------------------------------------------------------
-void APKFile::close()
+ApkFile::~ApkFile()
 {
 	if (m_asset != NULL)
 	{
@@ -64,85 +64,94 @@ void APKFile::close()
 }
 
 //-----------------------------------------------------------------------------
-bool APKFile::is_open() const
+void ApkFile::seek(size_t position)
 {
-	return m_asset != NULL;
+	off_t seek_result = AAsset_seek(m_asset, (off_t)position, SEEK_SET);
+	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek");
 }
 
 //-----------------------------------------------------------------------------
-FileOpenMode APKFile::mode() const
+void ApkFile::seek_to_end()
 {
-	return m_mode;
+	off_t seek_result = AAsset_seek(m_asset, 0, SEEK_END);
+	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek to end");
 }
 
 //-----------------------------------------------------------------------------
-size_t APKFile::size() const
+void ApkFile::skip(size_t bytes)
 {
-	return AAsset_getLength(m_asset);
+	off_t seek_result = AAsset_seek(m_asset, (off_t) bytes, SEEK_CUR);
+	CE_ASSERT(seek_result != (off_t) -1, "Failed to skip");
 }
 
 //-----------------------------------------------------------------------------
-size_t APKFile::read(void* data, size_t size)
+void ApkFile::read(void* buffer, size_t size)
 {
-	CE_ASSERT(data != NULL, "Data must be != NULL");
+	CE_ASSERT_NOT_NULL(buffer);
 
-	return (size_t)AAsset_read(m_asset, data, size);
+	size_t bytes_read = (size_t) AAsset_read(m_asset, buffer, size);
+	CE_ASSERT(bytes_read == size, "Failed to read from file: requested: %lu, read: %lu", size, bytes_read);
 }
 
 //-----------------------------------------------------------------------------
-size_t APKFile::write(const void* data, size_t /*size*/)
+void ApkFile::write(const void* /*buffer*/, size_t /*size*/)
 {
-	CE_ASSERT(data != NULL, "Data must be != NULL");
+	CE_ASSERT(false, "Attempt to write to android assets folder!");
+}
 
-	os::printf("Android asset directory is read-only!");
+//-----------------------------------------------------------------------------
+bool ApkFile::copy_to(File& /*file*/, size_t /*size = 0*/)
+{
+	CE_ASSERT(false, "Not implemented yet :(");
+	return false;
+}
 
-	return 0;
+//-----------------------------------------------------------------------------
+void ApkFile::flush()
+{
+	// Not needed
 }
 
 //-----------------------------------------------------------------------------
-void APKFile::seek(size_t position)
+bool ApkFile::is_valid() const
 {
-	off_t seek_result = AAsset_seek(m_asset, (off_t)position, SEEK_SET);
-	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek");
+	return m_asset != NULL;
 }
 
 //-----------------------------------------------------------------------------
-void APKFile::seek_to_end()
+bool ApkFile::end_of_file() const
 {
-	off_t seek_result = AAsset_seek(m_asset, 0, SEEK_END);
-	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek");
+	return AAsset_getRemainingLength(m_asset) == 0;
 }
 
 //-----------------------------------------------------------------------------
-void APKFile::skip(size_t bytes)
+size_t ApkFile::size() const
 {
-	off_t seek_result = AAsset_seek(m_asset, (off_t) bytes, SEEK_CUR);
-	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek");
+	return AAsset_getLength(m_asset);
 }
 
 //-----------------------------------------------------------------------------
-size_t APKFile::position() const
+size_t ApkFile::position() const
 {
 	return (size_t) (AAsset_getLength(m_asset) - AAsset_getRemainingLength(m_asset));
 }
 
 //-----------------------------------------------------------------------------
-bool APKFile::eof() const
+bool ApkFile::can_read() const
 {
-	return AAsset_getRemainingLength(m_asset) == 0;
+	return true;
 }
 
 //-----------------------------------------------------------------------------
-AAssetManager* get_android_asset_manager()
+bool ApkFile::can_write() const
 {
-	return g_android_asset_manager;
+	return false;
 }
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initAssetManager(JNIEnv* env, jobject obj, jobject assetManager)
+bool ApkFile::can_seek() const
 {
-	g_android_asset_manager = AAssetManager_fromJava(env, assetManager);
+	return true;
 }
 
-} // namespace crown
-
+} // namespace crown

+ 5 - 26
engine/os/android/AndroidFile.h → engine/os/android/ApkFile.h

@@ -26,58 +26,37 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "APKFile.h"
-#include "Assert.h"
+#include "File.h"
 
 namespace crown
 {
 
-class AndroidFile : public File 
+class ApkFile : public File 
 {
 public:
 
-				AndroidFile(const char* path);
+				ApkFile(const char* filename);
+				~ApkFile();
 
 	void		seek(size_t position);
-
 	void		seek_to_end();
-
 	void		skip(size_t bytes);
-
 	void		read(void* buffer, size_t size);
-
 	void		write(const void* buffer, size_t size);
-
 	bool		copy_to(File& file, size_t size = 0);
-
 	void		flush();
-
 	bool		is_valid() const;
-
 	bool		end_of_file() const;
-
 	size_t		size() const;
-
 	size_t		position() const;
-
 	bool		can_read() const;
-
 	bool		can_write() const;
-
 	bool		can_seek() const;
 
 private:
 
-	APKFile		m_file;
-
+	AAsset*		m_asset;
 	bool		m_last_was_read;
-
-protected:
-
-	inline void		check_valid() const
-	{
-		CE_ASSERT(m_file.is_open(), "File is not open");
-	}
 };
 
 } // namespace crown

+ 35 - 81
engine/os/android/AndroidFile.cpp → engine/os/android/ApkFilesystem.cpp

@@ -24,128 +24,82 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include "AndroidFile.h"
-#include "Log.h"
+#include "ApkFilesystem.h"
+#include "TempAllocator.h"
+#include "ApkFile.h"
+#include "OS.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-AndroidFile::AndroidFile(const char* path) :
-	File(FOM_READ),
-	m_file(path, FOM_READ),
-	m_last_was_read(true)
+ApkFilesystem::ApkFilesystem()
 {
 }
 
 //-----------------------------------------------------------------------------
-void AndroidFile::seek(size_t position)
+File* ApkFilesystem::open(const char* path, FileOpenMode mode)
 {
-	check_valid();
+	CE_ASSERT_NOT_NULL(path);
+	CE_ASSERT(mode == FOM_READ, "Cannot open for writing in Android assets folder");
 
-	m_file.seek(position);
+	return CE_NEW(default_allocator(), ApkFile)(path);
 }
 
 //-----------------------------------------------------------------------------
-void AndroidFile::seek_to_end()
+void ApkFilesystem::close(File* file)
 {
-	check_valid();
-
-	m_file.seek_to_end();
-}
-
-//-----------------------------------------------------------------------------
-void AndroidFile::skip(size_t bytes)
-{
-	check_valid();
-
-	m_file.skip(bytes);
-}
-
-//-----------------------------------------------------------------------------
-void AndroidFile::read(void* buffer, size_t size)
-{
-	check_valid();
-
-	if (!m_last_was_read)
-	{
-		m_last_was_read = true;
-		m_file.seek(0);
-	}
-
-	size_t bytes_read = m_file.read(buffer, size);
-	CE_ASSERT(bytes_read == size, "Failed to read from file");
-}
-
-//-----------------------------------------------------------------------------
-void AndroidFile::write(const void* /*buffer*/, size_t /*size*/)
-{
-	// Not needed
+	CE_ASSERT_NOT_NULL(file);
+	CE_DELETE(default_allocator(), file);
 }
 
 //-----------------------------------------------------------------------------
-bool AndroidFile::copy_to(File& /*file*/, size_t /*size = 0*/)
+void ApkFilesystem::create_directory(const char* /*path*/)
 {
-	// Not needed
-	return false;
+	CE_ASSERT(false, "Attempt to create directory in Android assets folder");
 }
 
 //-----------------------------------------------------------------------------
-void AndroidFile::flush()
+void ApkFilesystem::delete_directory(const char* /*path*/)
 {
-	// Not needed
+	CE_ASSERT(false, "Attempt to delete directory in Android assets folder");
 }
 
 //-----------------------------------------------------------------------------
-bool AndroidFile::is_valid() const
+void ApkFilesystem::create_file(const char* /*path*/)
 {
-	return m_file.is_open();
+	CE_ASSERT(false, "Attempt to create file in Android assets folder");
 }
 
 //-----------------------------------------------------------------------------
-bool AndroidFile::end_of_file() const
+void ApkFilesystem::delete_file(const char* /*path*/)
 {
-	return position() == size();
+	CE_ASSERT(false, "Attempt to delete file in Android assets folder");
 }
 
 //-----------------------------------------------------------------------------
-size_t AndroidFile::size() const
+void ApkFilesystem::list_files(const char* path, Vector<DynamicString>& files)
 {
-	check_valid();
-
-	return m_file.size();
-}
+	CE_ASSERT_NOT_NULL(path);
 
-//-----------------------------------------------------------------------------
-size_t AndroidFile::position() const
-{
-	check_valid();
+	AAssetDir* root_dir = AAssetManager_openDir(get_android_asset_manager(), path);
+	CE_ASSERT(root_dir != NULL, "Failed to open Android assets folder");
 
-	return m_file.position();
-}
-
-//-----------------------------------------------------------------------------
-bool AndroidFile::can_read() const
-{
-	check_valid();
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool AndroidFile::can_write() const
-{
-	check_valid();
+	const char* filename = NULL;
+	while ((filename = AAssetDir_getNextFileName(root_dir)) != NULL)
+	{
+		DynamicString name(default_allocator());
+		name = filename;
+		files.push_back(name);
+	}
 
-	return true;
+	AAssetDir_close(root_dir);
 }
 
 //-----------------------------------------------------------------------------
-bool AndroidFile::can_seek() const
+void ApkFilesystem::get_absolute_path(const char* path, DynamicString& os_path)
 {
-	check_valid();
-
-	return true;
+	os_path = path;
 }
 
-} // namespace crown
+} // namespace crown

+ 75 - 0
engine/os/android/ApkFilesystem.h

@@ -0,0 +1,75 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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.
+*/
+
+#pragma once
+
+#include "Filesystem.h"
+
+namespace crown
+{
+
+/// Access files on disk.
+/// All the file paths can be either relative or absolute.
+/// When a relative path is given, it is automatically translated
+/// to its absolute counterpart based on the file source's root path.
+/// Accessing files using absolute path directly is also possible,
+/// but platform-specific and thus generally not recommended.
+class ApkFilesystem : public Filesystem
+{
+public:
+
+	/// Sets the root path to the current working directory of
+	/// the engine executable.
+	ApkFilesystem();
+
+	/// Opens the file at the given @a path with the given @a mode.
+	File* open(const char* path, FileOpenMode mode);
+
+	/// Closes the given @a file.
+	void close(File* file);
+
+	/// Creates the directory at the given @a path.
+	void create_directory(const char* path);
+
+	/// Deletes the directory at the given @a path.
+	void delete_directory(const char* path);
+
+	/// Creates the file at the given @a path.
+	void create_file(const char* path);
+
+	/// Deletes the file at the given @a path.
+	void delete_file(const char* path);
+
+	/// Returns the relative file names in the given @a path.
+	void list_files(const char* path, Vector<DynamicString>& files);
+
+	/// Returns the absolute path of the given @a path based on
+	/// the root path of the file source. If @a path is absolute,
+	/// the given path is returned.
+	void get_absolute_path(const char* path, DynamicString& os_path);
+};
+
+} // namespace crown