gencpp/project/dependencies/file_handling.hpp
Ed_ 5d7dfaf666 Heavy refactor..
Isolating large macros to their own directory (components/temp).
- Plan is to remove them soon with proper generation.

Added additional component files, separating the old data_structures header for a set of ast headers.
Header_end also had its inlines extracted out.
Necessary to complete the macro isolation.

ZPL parser dependencies were removed from the core library along with builder, its now generated in bootstrap as pare of making a gen_builder set of files.

Singleheader will be changed in next few commits to reflect this as well (By making builder deps and components a conditional option).

Tests are most likely all broken for now.
2023-08-03 11:01:43 -04:00

374 lines
8.9 KiB
C++

#pragma region File Handling
typedef u32 FileMode;
enum FileModeFlag
{
EFileMode_READ = bit( 0 ),
EFileMode_WRITE = bit( 1 ),
EFileMode_APPEND = bit( 2 ),
EFileMode_RW = bit( 3 ),
GEN_FILE_MODES = EFileMode_READ | EFileMode_WRITE | EFileMode_APPEND | EFileMode_RW,
};
// NOTE: Only used internally and for the file operations
enum SeekWhenceType
{
ESeekWhence_BEGIN = 0,
ESeekWhence_CURRENT = 1,
ESeekWhence_END = 2,
};
enum FileError
{
EFileError_NONE,
EFileError_INVALID,
EFileError_INVALID_FILENAME,
EFileError_EXISTS,
EFileError_NOT_EXISTS,
EFileError_PERMISSION,
EFileError_TRUNCATION_FAILURE,
EFileError_NOT_EMPTY,
EFileError_NAME_TOO_LONG,
EFileError_UNKNOWN,
};
union FileDescriptor
{
void* p;
sptr i;
uptr u;
};
typedef struct FileOperations FileOperations;
#define GEN_FILE_OPEN_PROC( name ) FileError name( FileDescriptor* fd, FileOperations* ops, FileMode mode, char const* filename )
#define GEN_FILE_READ_AT_PROC( name ) b32 name( FileDescriptor fd, void* buffer, sw size, s64 offset, sw* bytes_read, b32 stop_at_newline )
#define GEN_FILE_WRITE_AT_PROC( name ) b32 name( FileDescriptor fd, void const* buffer, sw size, s64 offset, sw* bytes_written )
#define GEN_FILE_SEEK_PROC( name ) b32 name( FileDescriptor fd, s64 offset, SeekWhenceType whence, s64* new_offset )
#define GEN_FILE_CLOSE_PROC( name ) void name( FileDescriptor fd )
typedef GEN_FILE_OPEN_PROC( file_open_proc );
typedef GEN_FILE_READ_AT_PROC( FileReadProc );
typedef GEN_FILE_WRITE_AT_PROC( FileWriteProc );
typedef GEN_FILE_SEEK_PROC( FileSeekProc );
typedef GEN_FILE_CLOSE_PROC( FileCloseProc );
struct FileOperations
{
FileReadProc* read_at;
FileWriteProc* write_at;
FileSeekProc* seek;
FileCloseProc* close;
};
extern FileOperations const default_file_operations;
typedef u64 FileTime;
enum DirType
{
GEN_DIR_TYPE_FILE,
GEN_DIR_TYPE_FOLDER,
GEN_DIR_TYPE_UNKNOWN,
};
struct DirInfo;
struct DirEntry
{
char const* filename;
struct DirInfo* dir_info;
u8 type;
};
struct DirInfo
{
char const* fullpath;
DirEntry* entries; // zpl_array
// Internals
char** filenames; // zpl_array
String buf;
};
struct FileInfo
{
FileOperations ops;
FileDescriptor fd;
b32 is_temp;
char const* filename;
FileTime last_write_time;
DirEntry* dir;
};
enum FileStandardType
{
EFileStandard_INPUT,
EFileStandard_OUTPUT,
EFileStandard_ERROR,
EFileStandard_COUNT,
};
/**
* Get standard file I/O.
* @param std Check zpl_file_standard_type
* @return File handle to standard I/O
*/
FileInfo* file_get_standard( FileStandardType std );
/**
* Closes the file
* @param file
*/
FileError file_close( FileInfo* file );
/**
* Returns the currently opened file's name
* @param file
*/
inline
char const* file_name( FileInfo* file )
{
return file->filename ? file->filename : "";
}
/**
* Opens a file
* @param file
* @param filename
*/
FileError file_open( FileInfo* file, char const* filename );
/**
* Opens a file using a specified mode
* @param file
* @param mode Access mode to use
* @param filename
*/
FileError file_open_mode( FileInfo* file, FileMode mode, char const* filename );
/**
* Reads from a file
* @param file
* @param buffer Buffer to read to
* @param size Size to read
*/
GEN_DEF_INLINE b32 file_read( FileInfo* file, void* buffer, sw size );
/**
* Reads file at a specific offset
* @param file
* @param buffer Buffer to read to
* @param size Size to read
* @param offset Offset to read from
* @param bytes_read How much data we've actually read
*/
GEN_DEF_INLINE b32 file_read_at( FileInfo* file, void* buffer, sw size, s64 offset );
/**
* Reads file safely
* @param file
* @param buffer Buffer to read to
* @param size Size to read
* @param offset Offset to read from
* @param bytes_read How much data we've actually read
*/
GEN_DEF_INLINE b32 file_read_at_check( FileInfo* file, void* buffer, sw size, s64 offset, sw* bytes_read );
struct FileContents
{
AllocatorInfo allocator;
void* data;
sw size;
};
constexpr b32 zero_terminate = true;
constexpr b32 no_zero_terminate = false;
/**
* Reads the whole file contents
* @param a Allocator to use
* @param zero_terminate End the read data with null terminator
* @param filepath Path to the file
* @return File contents data
*/
FileContents file_read_contents( AllocatorInfo a, b32 zero_terminate, char const* filepath );
/**
* Returns a size of the file
* @param file
* @return File size
*/
s64 file_size( FileInfo* file );
/**
* Seeks the file cursor from the beginning of file to a specific position
* @param file
* @param offset Offset to seek to
*/
GEN_DEF_INLINE s64 file_seek( FileInfo* file, s64 offset );
/**
* Seeks the file cursor to the end of the file
* @param file
*/
GEN_DEF_INLINE s64 file_seek_to_end( FileInfo* file );
/**
* Returns the length from the beginning of the file we've read so far
* @param file
* @return Our current position in file
*/
GEN_DEF_INLINE s64 file_tell( FileInfo* file );
/**
* Writes to a file
* @param file
* @param buffer Buffer to read from
* @param size Size to read
*/
GEN_DEF_INLINE b32 file_write( FileInfo* file, void const* buffer, sw size );
/**
* Writes to file at a specific offset
* @param file
* @param buffer Buffer to read from
* @param size Size to write
* @param offset Offset to write to
* @param bytes_written How much data we've actually written
*/
GEN_DEF_INLINE b32 file_write_at( FileInfo* file, void const* buffer, sw size, s64 offset );
/**
* Writes to file safely
* @param file
* @param buffer Buffer to read from
* @param size Size to write
* @param offset Offset to write to
* @param bytes_written How much data we've actually written
*/
GEN_DEF_INLINE b32 file_write_at_check( FileInfo* file, void const* buffer, sw size, s64 offset, sw* bytes_written );
GEN_IMPL_INLINE s64 file_seek( FileInfo* f, s64 offset )
{
s64 new_offset = 0;
if ( ! f->ops.read_at )
f->ops = default_file_operations;
f->ops.seek( f->fd, offset, ESeekWhence_BEGIN, &new_offset );
return new_offset;
}
GEN_IMPL_INLINE s64 file_seek_to_end( FileInfo* f )
{
s64 new_offset = 0;
if ( ! f->ops.read_at )
f->ops = default_file_operations;
f->ops.seek( f->fd, 0, ESeekWhence_END, &new_offset );
return new_offset;
}
GEN_IMPL_INLINE s64 file_tell( FileInfo* f )
{
s64 new_offset = 0;
if ( ! f->ops.read_at )
f->ops = default_file_operations;
f->ops.seek( f->fd, 0, ESeekWhence_CURRENT, &new_offset );
return new_offset;
}
GEN_IMPL_INLINE b32 file_read( FileInfo* f, void* buffer, sw size )
{
s64 cur_offset = file_tell( f );
b32 result = file_read_at( f, buffer, size, file_tell( f ) );
file_seek( f, cur_offset + size );
return result;
}
GEN_IMPL_INLINE b32 file_read_at( FileInfo* f, void* buffer, sw size, s64 offset )
{
return file_read_at_check( f, buffer, size, offset, NULL );
}
GEN_IMPL_INLINE b32 file_read_at_check( FileInfo* f, void* buffer, sw size, s64 offset, sw* bytes_read )
{
if ( ! f->ops.read_at )
f->ops = default_file_operations;
return f->ops.read_at( f->fd, buffer, size, offset, bytes_read, false );
}
GEN_IMPL_INLINE b32 file_write( FileInfo* f, void const* buffer, sw size )
{
s64 cur_offset = file_tell( f );
b32 result = file_write_at( f, buffer, size, file_tell( f ) );
file_seek( f, cur_offset + size );
return result;
}
GEN_IMPL_INLINE b32 file_write_at( FileInfo* f, void const* buffer, sw size, s64 offset )
{
return file_write_at_check( f, buffer, size, offset, NULL );
}
GEN_IMPL_INLINE b32 file_write_at_check( FileInfo* f, void const* buffer, sw size, s64 offset, sw* bytes_written )
{
if ( ! f->ops.read_at )
f->ops = default_file_operations;
return f->ops.write_at( f->fd, buffer, size, offset, bytes_written );
}
enum FileStreamFlags : u32
{
/* Allows us to write to the buffer directly. Beware: you can not append a new data! */
EFileStream_WRITABLE = bit( 0 ),
/* Clones the input buffer so you can write (zpl_file_write*) data into it. */
/* Since we work with a clone, the buffer size can dynamically grow as well. */
EFileStream_CLONE_WRITABLE = bit( 1 ),
};
/**
* Opens a new memory stream
* @param file
* @param allocator
*/
b8 file_stream_new( FileInfo* file, AllocatorInfo allocator );
/**
* Opens a memory stream over an existing buffer
* @param file
* @param allocator
* @param buffer Memory to create stream from
* @param size Buffer's size
* @param flags
*/
b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, sw size, FileStreamFlags flags );
/**
* Retrieves the stream's underlying buffer and buffer size.
* @param file memory stream
* @param size (Optional) buffer size
*/
u8* file_stream_buf( FileInfo* file, sw* size );
extern FileOperations const memory_file_operations;
#pragma endregion File Handling