File internals¶
This document describes the internals behind files; see Files for more information about the user-facing abstractions.
A file only requires one memory allocation (except for system resources that are allocated / opened using different functions), and the medium is initialized with the file opening functions.
Mediums / system interface¶
Platform (system) specific code is isolated in conditionally included source
code within lib/platform
, with “public” functions (accessible to the
platform-independent portion of the library, but inaccessible to external code)
declared in lib/internals.h
(search for Platform-specific functions.
).
Public entry points for files, being cahute_create_file()
,
cahute_open_file()
and cahute_open_stdout()
,
call system-specific file opening functions depending on platform detection,
which in turn call the following platform-independent utilities:
-
int cahute_create_file_from_interface(cahute_file_create_params *create_params, cahute_file_create_interface const *interface, void *cookie, size_t cookie_size)¶
Create a file (internal platform-independent interface).
create_params
is computed bycahute_create_file()
and must be treated as opaque (as it is defined bycahute_create_file()
for its underlying platform-independent utility).interface
must be defined by the platform-specific code, can be defined as static / constant, and its type is defined as follows:-
struct cahute_file_create_interface¶
-
cahute_file_close_func *close_func¶
Function to use to close the file.
Can be set to
NULL
; if this is the case, no platform-specific code will be called to close the file.
-
cahute_file_write_func *write_func¶
Function to use to write data on the current position of the file.
-
cahute_file_seek_func *seek_func¶
Function to use to set the cursor’s position on the file.
-
cahute_file_close_func *close_func¶
cookie
is the cookie that will be passed to the platform-specific functions defined in the interface.Warning
cookie
will not be used directly, but will be copied on a new memory area reserved with all other requirements for the file.As such, if you need to allocate memory that is shared with your file’s medium for communication, you must allocate the shared memory separately, and include a pointer to it in the cookie, that will be copied to the new memory area.
Warning
Either
cookie
is defined andcookie_size
is greater than 0, orcookie
isNULL
andcookie_size
is equal to 0. Any other case is considered a bug in the platform-specific implementation by the library, and the initialization will fail.- Parameters:
create_params – Opaque parameter transmitted by
cahute_create_file()
, to consider opaque and send to the function.interface – Interface defined on a platform basis.
cookie – Cookie to copy on the file, and transmit to the platform-specific functions set in the interface.
cookie_size – Size of the cookie to copy.
- Returns:
The error, or 0 if the operation was successful.
-
struct cahute_file_create_interface¶
-
int cahute_open_file_from_interface(cahute_file_open_params *create_params, cahute_file_open_interface const *interface, void *cookie, size_t cookie_size, unsigned long file_size)¶
Open a file (internal platform-independent interface).
open_params
is computed bycahute_open_file()
and must be treated as opaque (as it is defined bycahute_open_file()
for its underlying platform-independent utility).interface
must be defined by the platform-specific code, can be defined as static / constant, and its type is defined as follows:-
struct cahute_file_open_interface¶
-
cahute_file_close_func *close_func¶
Function to use to close the file.
Can be set to
NULL
; if this is the case, no platform-specific code will be called to close the file.
-
cahute_file_read_func *read_func¶
Function to use to read data from the current position of the file.
-
cahute_file_seek_func *seek_func¶
Function to use to set the cursor’s position on the file.
-
cahute_file_close_func *close_func¶
cookie
is the cookie that will be passed to the platform-specific functions defined in the interface.Warning
cookie
will not be used directly, but will be copied on a new memory area reserved with all other requirements for the file.As such, if you need to allocate memory that is shared with your file’s medium for communication, you must allocate the shared memory separately, and include a pointer to it in the cookie, that will be copied to the new memory area.
Warning
Either
cookie
is defined andcookie_size
is greater than 0, orcookie
isNULL
andcookie_size
is equal to 0. Any other case is considered a bug in the platform-specific implementation by the library, and the initialization will fail.- Parameters:
open_params – Opaque parameter transmitted by
cahute_open_file()
, to consider opaque and send to the function.interface – Interface defined on a platform basis.
cookie – Cookie to copy on the file, and transmit to the platform-specific functions set in the interface.
cookie_size – Size of the cookie to copy.
file_size – Size of the file, i.e. first invalid offset.
- Returns:
The error, or 0 if the operation was successful.
-
struct cahute_file_open_interface¶
-
int cahute_open_stdout_from_interface(cahute_stdout_open_params *create_params, cahute_stdout_open_interface const *interface, void *cookie, size_t cookie_size)¶
Open standard output (internal platform-independent interface).
open_params
is computed bycahute_open_stdout()
and must be treated as opaque (as it is defined bycahute_open_stdout()
for its underlying platform-independent utility).interface
must be defined by the platform-specific code, can be defined as static / constant, and its type is defined as follows:-
struct cahute_file_open_interface¶
-
cahute_file_close_func *close_func¶
Function to use to close the file.
Can be set to
NULL
; if this is the case, no platform-specific code will be called to close the file.
-
cahute_file_write_func *write_func¶
Function to use to write data on the output.
-
cahute_file_close_func *close_func¶
cookie
is the cookie that will be passed to the platform-specific functions defined in the interface.Warning
cookie
will not be used directly, but will be copied on a new memory area reserved with all other requirements for the file.As such, if you need to allocate memory that is shared with your file’s medium for communication, you must allocate the shared memory separately, and include a pointer to it in the cookie, that will be copied to the new memory area.
Warning
Either
cookie
is defined andcookie_size
is greater than 0, orcookie
isNULL
andcookie_size
is equal to 0. Any other case is considered a bug in the platform-specific implementation by the library, and the initialization will fail.- Parameters:
open_params – Opaque parameter transmitted by
cahute_open_stdout()
, to consider opaque and send to the function.interface – Interface defined on a platform basis.
cookie – Cookie to copy on the file, and transmit to the platform-specific functions set in the interface.
cookie_size – Size of the cookie to copy.
- Returns:
The error, or 0 if the operation was successful.
-
struct cahute_file_open_interface¶
Medium functions¶
The medium interface functions are defined as the following:
-
typedef void (cahute_file_close_func)(cahute_context *context, void *cookie)¶
Function that, if defined, is called to close file-specific resources.
- Param context:
Context in which the function is loaded. Can be used for logging purposes, or to get context-specific resources.
- Param cookie:
File-specific cookie.
-
typedef int (cahute_file_read_func)(cahute_context *context, void *cookie, cahute_u8 *buf, size_t capacity, size_t *readp)¶
Function called to read data from the current position on the file’s medium.
- Param context:
Context in which the function is loaded. Can be used for logging purposes, or to get context-specific resources.
- Param cookie:
File-specific cookie.
- Param buf:
Buffer in which to read data.
- Param capacity:
Buffer capacity, in bytes.
- Param readp:
Pointer to the number of read bytes to set.
- Return:
The error, or 0 if the operation was successful.
-
typedef int (cahute_file_write_func)(cahute_context *context, void *cookie, cahute_u8 const *buf, size_t size, size_t *writtenp)¶
Function called to write data at the current position on the file’s underlying medium.
- Param context:
Context in which the function is loaded. Can be used for logging purposes, or to get context-specific resources.
- Param cookie:
File-specific cookie.
- Param buf:
Buffer in which the data to write is defined.
- Param size:
Length of the data to write in the provided buffer, in bytes.
- Param sentp:
Pointer to the number of written bytes to set.
- Return:
The error, or 0 if the operation was successful.
-
typedef int (cahute_file_seek_func)(cahute_context *context, void *cookie, unsigned long pos, unsigned long *new_posp)¶
Function called to set the position on the file’s underlying medium.
- Param context:
Context in which the function is loaded.
- Param cookie:
File-specific cookie.
- Param pos:
Position to set on the file.
- Param new_posp:
Pointer to the current position to set, as an offset.
- Return:
The error, or 0 if the operation was successful.
Internal in-memory file medium¶
In order to work for both files and protocols, some functions such as
cahute_casiolink_decode_data()
or cahute_mcs_decode_data()
take a cahute_file
instance. For abstracting memory buffers coming
from protocols as in-memory files, the following internal function is available
within the library:
-
void cahute_populate_file_from_memory(cahute_file *file, cahute_u8 *buf, size_t size)¶
Populate a file handle from a buffer and a size.
- Parameters:
file – File object to populate.
buf – Buffer to abstract as a file.
size – Size of the buffer to abstract.
In order to avoid having too many memory allocations and since
cahute_file
is not opaque within the library, this utility can be
used to populate a statically defined file object which can then be transmitted
to other functions using files to decode data. It is also not necessary to
call cahute_close_file()
in such a case.
For example, with cahute_casiolink_decode_data()
:
cahute_file file;
unsigned long offset = 0;
cahute_populate_file_from_memory(&file, my_buf, my_buf_size);
err = cahute_casiolink_decode_data(datap, &file, &offset, my_variant, 1);
...
In order to work, this abuses the read buffer to not be
CAHUTE_FILE_MEDIUM_READ_BUFFER_SIZE
bytes long, but sized to
the whole “file”, representing the buffer, with the read buffer actually being
the provided buffer directly with the CAHUTE_FILE_MEDIUM_NONE
.
It abuses existing manipulations of the read buffer to read directly from the read buffer, mirror written data in the read buffer to just write into the buffer at the provided offset, and not have any side effects, i.e. the operations become the following:
cahute_read_from_file_medium()
There is always an intersection between our current read buffer and the requested data on the left boundary, so we read from the “read” buffer to copy data to the user-provided buffer.
cahute_write_to_file_medium()
We do not move any underlying cursor or have any side-effect.
There is always an intersection between the user-provided boundaries and the read buffer boundaries, so we write the user-provided data to the correct offset in the read buffer to ensure reads from the same offsets will return the updated data, and not the data before the write.
File metadata retrieval¶
The cahute_file
contains caching for the file metadata retrieval,
namely:
The retrieved type, using one of the
CAHUTE_FILE_TYPE_*
macros defined in <cahute/file.h> – File related utilities for Cahute;The extension extracted from the provided path.
For any of the file reading functions that requires file type and metadata,
if the CAHUTE_FILE_FLAG_EXAMINED
flag is not present in the
file flags yet, the cahute_examine_file()
function is called to
determine it and set the flag.