1 #pragma once
2 
3 #include <cstddef>
4 #include <cassert>
5 
6 #include "qcommon/q_platform.h"
7 #include "qcommon/safe/gsl.h"
8 
9 /**
10 @file RAII C++ bindings for filesystem operations
11 */
12 
13 namespace FS
14 {
15 	class FileBuffer
16 	{
17 		friend FileBuffer ReadFile( gsl::czstring );
18 		// called by ReadFile()
19 		FileBuffer( void* buffer, const long size ) NOEXCEPT;
20 	public:
21 		FileBuffer() NOEXCEPT = default;
22 		~FileBuffer() NOEXCEPT;
23 		// noncopyable
24 		FileBuffer( const FileBuffer& ) = delete;
25 		FileBuffer& operator=( const FileBuffer& ) = delete;
26 		// movable
27 		FileBuffer( FileBuffer&& rhs ) NOEXCEPT;
28 		FileBuffer& operator=( FileBuffer&& rhs ) NOEXCEPT;
29 
30 		/// nullptr if no such file
begin()31 		const char* begin() const NOEXCEPT
32 		{
33 			return static_cast< const char* >( _buffer );
34 		}
end()35 		const char* end() const NOEXCEPT
36 		{
37 			return static_cast< const char* >( _buffer ) + _size;
38 		}
size()39 		long size() const NOEXCEPT
40 		{
41 			return _size;
42 		}
valid()43 		bool valid() const NOEXCEPT
44 		{
45 			return _buffer != nullptr;
46 		}
view()47 		gsl::cstring_view view() const NOEXCEPT
48 		{
49 			return{ begin(), end() };
50 		}
51 
52 	private:
53 		// TODO: ought to be const; would have to fix FS_ReadFile though.
54 		void* _buffer = nullptr;
55 		long _size = 0;
56 	};
57 
58 	FileBuffer ReadFile( gsl::czstring path );
59 
60 	// FileList only available in Client; Library exclusively uses FS_GetFileList(), which by supplying a buffer avoids dynamic allocations.
61 	// TODO: investigate making FS_ListFiles available in Library Code?
62 #if !defined( SP_GAME )
63 	class FileList
64 	{
65 		friend FileList ListFiles( const char*, const char* );
66 		// called by ListFiles()
67 		FileList( char** files, int numFiles ) NOEXCEPT;
68 	public:
69 		FileList() NOEXCEPT = default;
70 		~FileList() NOEXCEPT;
71 		// noncopyable
72 		FileList( const FileList& ) = delete;
73 		FileList& operator=( const FileList& ) = delete;
74 		// movable
75 		FileList( FileList&& rhs ) NOEXCEPT;
76 		FileList& operator=( FileList&& rhs ) NOEXCEPT;
77 
begin()78 		const char *const *begin() const NOEXCEPT
79 		{
80 			return _begin;
81 		}
end()82 		const char *const *end() const NOEXCEPT
83 		{
84 			return _end;
85 		}
size()86 		std::size_t size() const NOEXCEPT
87 		{
88 			return static_cast< std::size_t >( _end - begin() );
89 		}
90 
91 	private:
92 		// TODO: this should really be const; it's a matter of making FS_ListFiles' result const.
93 		char** _begin = nullptr;
94 		const char* const* _end = nullptr;
95 	};
96 
97 	/**
98 	@brief Returns a list of the files in a directory.
99 
100 	The returned files will not include any directories or `/`.
101 
102 	@note ERR_FATAL if called before file system initialization
103 	@todo Which is it? Returns no directories at all, or returns them when looking for extension "/"?
104 	@param directory should not have either a leading or trailing /
105 	@param extension if "/", only subdirectories will be returned
106 	*/
107 	FileList ListFiles( const char* directory, const char* extension );
108 #endif
109 }
110