Skip to content

Commit

Permalink
Feat: Add file-access methods
Browse files Browse the repository at this point in the history
  • Loading branch information
czs108 committed Feb 6, 2024
1 parent 1cfe4ad commit 87a0846
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 0 deletions.
87 changes: 87 additions & 0 deletions include/utility/file_access.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* @file file_access.h
* @brief File reading and writing.
* @author Chen Zhenshuo (chenzs108@outlook.com)
* @version 1.0
* @date 2020-01-10
*
* @par GitHub
* https://github.com/czs108/
*/

#pragma once

#include <windows.h>

#include <stdbool.h>

/**
* @brief The view of a file.
*/
typedef struct _FILE_VIEW
{
//! The file-mapping returned by `CreateFileMapping` API.
HANDLE map;

//! The base address of the file content returned by `MapViewOfFile` API.
const BYTE* base;

//! The size of the file.
DWORD size;

} FILE_VIEW;


/**
* @brief Write all the data to the file.
*
* @param file The file.
* @param data The base address of the data.
* @param size The size of the data.
* @return `true` if the method succeeds, otherwise `false`.
*/
bool WriteAllToFile(
const HANDLE file,
const BYTE *const data,
const DWORD size);


/**
* @brief Open a read-only view of the file.
*
* @public @memberof _FILE_VIEW
*
* @param file The file.
* @param[out] file_view The read-only view
* @return `true` if the method succeeds, otherwise `false`.
*
* @note The constructor of `_FILE_VIEW` structure.
*/
bool OpenReadViewOfFile(
const HANDLE file,
FILE_VIEW *const file_view);


/**
* @brief Close the view of a file.
*
* @public @memberof _FILE_VIEW
*
* @param file_view The view.
*
* @note The destructor of `_FILE_VIEW` structure.
*/
void CloseViewOfFile(
const FILE_VIEW *const file_view);


/**
* @brief Check if the size of the file is smaller than 2GB.
*
* @param file The file.
* @return `true` if the size of the file is smaller than 2GB, otherwise `false`.
*
* @warning The program can only process files smaller than 2GB.
*/
bool IsFileSmallerThan2G(
const HANDLE file);
2 changes: 2 additions & 0 deletions src/utility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ target_include_directories(utility PUBLIC ${HEADER_PATH})
target_sources(utility
PRIVATE
${CMAKE_CURRENT_LIST_DIR}/error_handling.c
${CMAKE_CURRENT_LIST_DIR}/file_access.c
PUBLIC
${HEADER_PATH}/error_handling.h
${HEADER_PATH}/file_access.h
)
114 changes: 114 additions & 0 deletions src/utility/file_access.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* @file file_access.c
* @brief File reading and writing.
* @author Chen Zhenshuo (chenzs108@outlook.com)
* @version 1.0
* @date 2020-01-10
*
* @par GitHub
* https://github.com/czs108/
*/

#include "file_access.h"
#include "error_handling.h"

#include <assert.h>


bool WriteAllToFile(
const HANDLE file,
const BYTE *const data,
const DWORD size)
{
assert(file != INVALID_HANDLE_VALUE);

if (size == 0)
{
return true;
}

assert(data != NULL);

DWORD remaining = size;
const BYTE *current = data;
while (remaining > 0)
{
DWORD written = 0;
if (WriteFile(file, current, remaining, &written, NULL) == FALSE)
{
SetLastErrorCode();
return false;
}

remaining -= written;
current += written;
}

return true;
}


bool OpenReadViewOfFile(
const HANDLE file,
FILE_VIEW *const file_view)
{
assert(IsFileSmallerThan2G(file));
assert(file_view != NULL);

bool success = false;
ZeroMemory(file_view, sizeof(file_view));

file_view->size = GetFileSize(file, NULL);
file_view->map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
if (file_view->map == NULL)
{
SetLastErrorCode();
goto _Exit;
}

file_view->base = (BYTE*)MapViewOfFile(file_view->map, FILE_MAP_READ, 0, 0, 0);
if (file_view->base == NULL)
{
SetLastErrorCode();
goto _Exit;
}

success = true;

_Exit:
if (!success)
{
CloseViewOfFile(file_view);
ZeroMemory(file_view, sizeof(file_view));
}

return success;
}


void CloseViewOfFile(
const FILE_VIEW *const file_view)
{
assert(file_view != NULL);

if (file_view->base != NULL)
{
UnmapViewOfFile(file_view->base);
}

if (file_view->map != NULL)
{
CloseHandle(file_view->map);
}
}


bool IsFileSmallerThan2G(
const HANDLE file)
{
assert(file != INVALID_HANDLE_VALUE);

DWORD size_high = 0;
GetFileSize(file, &size_high);
return size_high == 0;
}

0 comments on commit 87a0846

Please sign in to comment.