mirror of
https://codeberg.org/1414codeforge/ubgpsuite.git
synced 2025-06-05 21:29:11 +02:00
[*] Initial commit
This commit is contained in:
104
lonetix/include/df/sys/con.h
Executable file
104
lonetix/include/df/sys/con.h
Executable file
@ -0,0 +1,104 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/con.h
|
||||
*
|
||||
* System console interface.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*
|
||||
* Provides basic functionality to print to system console and
|
||||
* test for supported capabilities.
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_CON_H_
|
||||
#define DF_SYS_CON_H_
|
||||
|
||||
#include "stm.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* \typedef ConHn
|
||||
* \brief Platform console handle descriptor.
|
||||
*
|
||||
* \def STDIN
|
||||
* \brief Platform Standard Input (`stdin`) handle.
|
||||
* \def STDOUT
|
||||
* \brief Platform Standard Output (`stdout`) handle.
|
||||
* \def STDERR
|
||||
* \brief Platform Standard Error (`stderr`) handle.
|
||||
*
|
||||
* \fn Fildes CON_FILDES(ConHn)
|
||||
*
|
||||
* \brief Convert a `ConHn` to a `Fildes`, making the console handle usable with
|
||||
* regular platform file API.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
|
||||
typedef Uint32 /*DWORD*/ ConHn;
|
||||
|
||||
#define STDIN ((ConHn) -10) // STD_INPUT_HANDLE
|
||||
#define STDOUT ((ConHn) -11) // STD_OUTPUT_HANDLE
|
||||
#define STDERR ((ConHn) -12) // STD_ERROR_HANDLE
|
||||
|
||||
Fildes CON_FILDES(ConHn hn);
|
||||
|
||||
#else
|
||||
|
||||
typedef int ConHn;
|
||||
|
||||
#define STDIN ((ConHn) 0)
|
||||
#define STDOUT ((ConHn) 1)
|
||||
#define STDERR ((ConHn) 2)
|
||||
|
||||
FORCE_INLINE Fildes CON_FILDES(ConHn hn)
|
||||
{
|
||||
return (Fildes) hn; // trivial on Unix
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Convert a `ConHn` to a `streamp` pointer for `StmOps`.
|
||||
*
|
||||
* \see `Stm_ConOps`
|
||||
*/
|
||||
FORCE_INLINE void *STM_CONHN(ConHn hn)
|
||||
{
|
||||
STATIC_ASSERT(sizeof(Sintptr) >= sizeof(void *), "ConHn ill formed on this platform");
|
||||
return (void *) ((Sintptr) hn);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief `StmOps` interface operating on console output.
|
||||
*
|
||||
* There is no `Close()` function for consoles.
|
||||
*/
|
||||
extern const StmOps *const Stm_ConOps;
|
||||
|
||||
/**
|
||||
* Print string to console.
|
||||
*
|
||||
* \note No newline is appended.
|
||||
*/
|
||||
void Sys_Print(ConHn hn, const char *s);
|
||||
|
||||
/// Formatted print to console handle.
|
||||
CHECK_PRINTF(2, 3) void Sys_Printf(ConHn hn, const char *fmt, ...);
|
||||
/// `Sys_Printf()` variant using `va_list`.
|
||||
CHECK_PRINTF(2, 0) void Sys_VPrintf(ConHn hn, const char *fmt, va_list va);
|
||||
/**
|
||||
* \brief Read at most `nbytes` characters from `hn` to `buf`, input is *not* `\0` terminated.
|
||||
*
|
||||
* \return Count of `char`s written to `buf`.
|
||||
*/
|
||||
size_t Sys_Read(ConHn hn, char *buf, size_t nbytes);
|
||||
/// Non-Blocking variant of `Sys_Read()`.
|
||||
size_t Sys_NbRead(ConHn hn, char *buf, size_t nbytes); // NON-BLOCKING
|
||||
|
||||
/// Test whether `hn` supports VT100 commands.
|
||||
Boolean Sys_IsVt100Console(ConHn hn);
|
||||
|
||||
#endif
|
59
lonetix/include/df/sys/dbg.h
Executable file
59
lonetix/include/df/sys/dbg.h
Executable file
@ -0,0 +1,59 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/dbg.h
|
||||
*
|
||||
* Debugging utilities to retrieve stack trace and symbol names.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_DBG_H_
|
||||
#define DF_SYS_DBG_H_
|
||||
|
||||
#include "sys/con.h"
|
||||
|
||||
/// Helper union to cast `void *` to function pointer - be sad if you use it.
|
||||
typedef union {
|
||||
void *sym; ///< Function as a `void *`
|
||||
void (*func)(void); ///< Function pointer.
|
||||
} Funsym;
|
||||
|
||||
STATIC_ASSERT(sizeof(void *) == sizeof(void (*)(void)), "Ill-formed Funsym for target platform");
|
||||
|
||||
/// Test whether the current process is being executed under a debugger.
|
||||
Boolean Sys_IsDebuggerPresent(void);
|
||||
/**
|
||||
* \brief Get a symbol's name, if available.
|
||||
*
|
||||
* \param [in] sym Symbol whose name is needed.
|
||||
*
|
||||
* \return A pointer to a statically allocated thread-local buffer containing
|
||||
* a `\0` terminated symbol name on success, `NULL` if no name could be
|
||||
* retrieved.
|
||||
*/
|
||||
char *Sys_GetSymbolName(void *sym);
|
||||
/**
|
||||
* \brief Dump at most `n` backtrace entries to `dest`.
|
||||
*
|
||||
* Returned backtrace does not include `Sys_GetBacktrace()`
|
||||
* itself, and has the caller as the topmost symbol.
|
||||
*
|
||||
* \return Number of entries actually returned to `dest` on success,
|
||||
* 0 when no backtrace information is available.
|
||||
*/
|
||||
size_t Sys_GetBacktrace(void **dest, size_t n);
|
||||
/**
|
||||
* \brief Get the caller's caller.
|
||||
*
|
||||
* Useful for quick debugging:
|
||||
* ```c
|
||||
* printf("Called by: %s\n", Sys_GetSymbolName(Sys_GetCaller()));
|
||||
* ```
|
||||
*/
|
||||
void *Sys_GetCaller(void);
|
||||
/// Dump backtrace to console (typically `STDERR`).
|
||||
void Sys_DumpBacktrace(ConHn hn, void **trace, size_t n);
|
||||
|
||||
#endif
|
132
lonetix/include/df/sys/endian.h
Executable file
132
lonetix/include/df/sys/endian.h
Executable file
@ -0,0 +1,132 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/endian.h
|
||||
*
|
||||
* Architecture specific byteswap utilities.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_ENDIAN_H_
|
||||
#define DF_SYS_ENDIAN_H_
|
||||
|
||||
#include "xpt.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h> // _byteswap_*()
|
||||
#endif
|
||||
|
||||
/// Helper `union` to access bit representation of `float`.
|
||||
typedef union {
|
||||
float f32;
|
||||
Uint32 bits;
|
||||
} Floatbits;
|
||||
|
||||
/// Helper `union` to access bit representation of `double`.
|
||||
typedef union {
|
||||
double f64;
|
||||
Uint64 bits;
|
||||
} Doublebits;
|
||||
|
||||
STATIC_ASSERT(sizeof(Floatbits) == sizeof(Uint32), "float vs Uint32 size mismatch");
|
||||
STATIC_ASSERT(sizeof(Doublebits) == sizeof(Uint64), "double vs Uint64 size mismatch");
|
||||
|
||||
/// Swap bytes inside 16-bits word.
|
||||
FORCE_INLINE Uint16 bswap16(Uint16 x)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_ushort(x);
|
||||
#elif defined(__GNUC__)
|
||||
return __builtin_bswap16(x);
|
||||
#else
|
||||
return BSWAP16(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Swap bytes inside 32-bits dword.
|
||||
FORCE_INLINE Uint32 bswap32(Uint32 x)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_ulong(x);
|
||||
#elif defined(__GNUC__)
|
||||
return __builtin_bswap32(x);
|
||||
#else
|
||||
return BSWAP32(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Swap bytes inside 64-bits quadword.
|
||||
FORCE_INLINE Uint64 bswap64(Uint64 x)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_uint64(x);
|
||||
#elif defined(__GNUC__)
|
||||
return __builtin_bswap64(x);
|
||||
#else
|
||||
return BSWAP64(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// `bswap16()` if target isn't little-endian.
|
||||
FORCE_INLINE Uint16 leswap16(Uint16 x)
|
||||
{
|
||||
#if EDN_NATIVE == EDN_LE
|
||||
return x;
|
||||
#else
|
||||
return bswap16(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// `bswap16()` if target isn't big-endian.
|
||||
FORCE_INLINE Uint16 beswap16(Uint16 x)
|
||||
{
|
||||
#if EDN_NATIVE == EDN_BE
|
||||
return x;
|
||||
#else
|
||||
return bswap16(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// `bswap32()` if target isn't little-endian.
|
||||
FORCE_INLINE Uint32 leswap32(Uint32 x)
|
||||
{
|
||||
#if EDN_NATIVE == EDN_LE
|
||||
return x;
|
||||
#else
|
||||
return bswap32(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// `bswap32()` if target isn't big-endian.
|
||||
FORCE_INLINE Uint32 beswap32(Uint32 x)
|
||||
{
|
||||
#if EDN_NATIVE == EDN_BE
|
||||
return x;
|
||||
#else
|
||||
return bswap32(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// `bswap64()` if target isn't little-endian.
|
||||
FORCE_INLINE Uint64 leswap64(Uint64 x)
|
||||
{
|
||||
#if EDN_NATIVE == EDN_LE
|
||||
return x;
|
||||
#else
|
||||
return bswap64(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// `bswap64()` if target isn't big-endian.
|
||||
FORCE_INLINE Uint64 beswap64(Uint64 x)
|
||||
{
|
||||
#if EDN_NATIVE == EDN_BE
|
||||
return x;
|
||||
#else
|
||||
return bswap64(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
253
lonetix/include/df/sys/fs.h
Executable file
253
lonetix/include/df/sys/fs.h
Executable file
@ -0,0 +1,253 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/fs.h
|
||||
*
|
||||
* Portable low-level filesystem layer
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*
|
||||
* Achieves portable low-level, close to operating system, filesystem
|
||||
* functionality. Functionality includes:
|
||||
* - file I/O
|
||||
* - file usage hints
|
||||
* - file creation and removal
|
||||
* - directory listing, creation and removal
|
||||
* - path utilities.
|
||||
*
|
||||
* No library file buffering is attempted, nor any kind of text-based I/O.
|
||||
* Paths are UTF-8.
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_FS_H_
|
||||
#define DF_SYS_FS_H_
|
||||
|
||||
#include "sys/fsdef.h" // platform-specific defs, including `Fildes`
|
||||
|
||||
/// File access mode for `Sys_Fopen()`.
|
||||
typedef enum {
|
||||
FM_READ, ///< Read-only access
|
||||
FM_WRITE, ///< Write-only access
|
||||
FM_APPEND, ///< File-append access
|
||||
FM_EXCL, ///< Exclusive creation access
|
||||
FM_TEMP ///< Temporary scratch file creation
|
||||
} FopenMode;
|
||||
|
||||
/// Access pattern is sequential.
|
||||
#define FH_SEQ BIT(0)
|
||||
/// Access pattern is random.
|
||||
#define FH_RAND BIT(1)
|
||||
/// Avoid filesystem cache buffers with this file.
|
||||
#define FH_UNBUF BIT(2)
|
||||
/// File data is accessed once and never reused.
|
||||
#define FH_NOREUSE BIT(3)
|
||||
|
||||
/**
|
||||
* \brief Open a descriptor handle to a regular or special file.
|
||||
*
|
||||
* Every successfully opened file descriptor must be closed using
|
||||
* `Sys_Fclose()` when no longer necessary.
|
||||
*
|
||||
* \param [in] filename Path to file, must not be `NULL`
|
||||
* \param [in] mode File access mode
|
||||
* \param [in] hints File access hints (`FH_*` bit mask)
|
||||
*
|
||||
* \return Opened file descriptor on success, `FILDES_BAD` on failure.
|
||||
*/
|
||||
Fildes Sys_Fopen(const char *filename, FopenMode mode, unsigned hints);
|
||||
/**
|
||||
* \brief Move file's cursor to the specified offset.
|
||||
*
|
||||
* \param [in] fd Opened file descriptor
|
||||
* \param [in] offset Offset to move the cursor to, according to `whence`, in bytes
|
||||
* \param [in] whence Seek mode
|
||||
*
|
||||
* \return New cursor position on success, -1 on failure or non-seekable file.
|
||||
*/
|
||||
Sint64 Sys_Fseek(Fildes fd, Sint64 offset, SeekMode whence);
|
||||
/// Retrieve current file cursor position, returns -1 on failure or non-seekable file.
|
||||
Sint64 Sys_Ftell(Fildes fd);
|
||||
/// Get current file size, in bytes, -1 on error.
|
||||
Sint64 Sys_FileSize(Fildes fd);
|
||||
/**
|
||||
* \brief Write raw bytes to file.
|
||||
*
|
||||
* \param [in] fd Opened, writable, file descriptor
|
||||
* \param [in] buf Containing at least `nbytes` bytes of data
|
||||
* \param [in] nbytes Bytes count in `buf` to be written to `fd`
|
||||
*
|
||||
* \return Number of bytes actually written on `fd`, possibly less
|
||||
* than `nbytes` on short-write. -1 on failure.
|
||||
*/
|
||||
Sint64 Sys_Fwrite(Fildes fd, const void *buf, size_t nbytes);
|
||||
/**
|
||||
* \brief Read raw bytes from file.
|
||||
*
|
||||
* \param [in] fd Opened, readable, file descriptor
|
||||
* \param [out] buf Destination buffer for the read operation
|
||||
* \param [in] nbytes Bytes count to read from `fd` inside `buf`
|
||||
*
|
||||
* \return Number of bytes actually read from `fd`, possibly less than `nbytes`,
|
||||
* 0 is returned on `EOF` condition. -1 on failure.
|
||||
*/
|
||||
Sint64 Sys_Fread(Fildes fd, void *buf, size_t nbytes);
|
||||
/**
|
||||
* \brief Truncate or grow file size to its current cursor position.
|
||||
*
|
||||
* \return `OK` on success, and file is altered as follows,
|
||||
* - if file size has been truncated excess data is lost;
|
||||
* - if file has grown in size (file cursor was beyond the original size),
|
||||
* new content is unspecified.
|
||||
* On failure returns `NG` and file is unaltered.
|
||||
*/
|
||||
Judgement Sys_SetEof(Fildes fd);
|
||||
/**
|
||||
* \brief Synchronize file data to disk, flushing buffers.
|
||||
*
|
||||
* Some systems require `fd` to be writable, whether `Sys_Fsync()` supports
|
||||
* a read-only descriptor is system specific.
|
||||
* Some systems allow optimized syncs that only guarantee read operations
|
||||
* consistency afterwards, this optimization is used on such systems when
|
||||
* `fullSync` is `FALSE`. otherwise `fullSync` is ignored (as if always `TRUE`).
|
||||
* A call to `Sys_Fsync()` with `fullSync` to `TRUE` causes the system
|
||||
* to sync disk data with `fd` in its entirety.
|
||||
*
|
||||
* \param [in] fd Opened file descriptor
|
||||
* \param [in] fullSync Whether a full sync should occur
|
||||
*
|
||||
* \return `OK` on success, `NG` on failure or on systems where
|
||||
* there is no mean to force file data sync with disk.
|
||||
*/
|
||||
Judgement Sys_Fsync(Fildes fd, Boolean fullSync);
|
||||
/// Close opened file descriptor.
|
||||
void Sys_Fclose(Fildes fd);
|
||||
|
||||
/**
|
||||
* \brief List directory contents.
|
||||
*
|
||||
* `pat` | Meaning
|
||||
* ---------|------------------------------------------
|
||||
* __NULL__ | Equivalent to `""`
|
||||
* "" | No filtering
|
||||
* / | Only return subdirectories
|
||||
* .* | Only return files whose extension matches
|
||||
*
|
||||
* \param [in] path Path to directory, must not be `NULL`
|
||||
* \param [out] nfiles Location to store returned file count, may be `NULL` if unimportant
|
||||
* \param [in] pat Optional pattern to filter directory files, may be `NULL`
|
||||
*
|
||||
* \return `malloc()`ed string list containing matching files,
|
||||
* must be `free()`d by the caller when no longer necessary.
|
||||
* A single `free()` on the returned list is sufficient to
|
||||
* release it entirely.
|
||||
*/
|
||||
char **Sys_ListFiles(const char *path, unsigned *nfiles, const char *pat);
|
||||
|
||||
/**
|
||||
* \brief Create directory.
|
||||
*
|
||||
* \param [in] path Directory creation path, must not be `NULL`
|
||||
*
|
||||
* \return `OK` on success, and directory is created.
|
||||
* Creating already existing directories is a success.
|
||||
* `NG` on failure.
|
||||
*/
|
||||
Judgement Sys_Mkdir(const char *path);
|
||||
|
||||
/**
|
||||
* \brief Rename a file.
|
||||
*
|
||||
* Different systems may impose different restrictions on
|
||||
* rename operations, in particular when the operation crosses
|
||||
* different devices in the filesystem.
|
||||
* The only portable and safe way to rename a file (or, in this
|
||||
* specific scenario, *move* it) is copying it over `newPath`,
|
||||
* and remove `path` on success, but the basic `rename` operation is
|
||||
* usually safe, unexpensive and atomic under the same device.
|
||||
* `Sys_Rename()` works on directories as well.
|
||||
*
|
||||
* \param [in] path Path to the file to be renamed, must not be `NULL`
|
||||
* \param [in] newPath New name for the file, destination directory must exist
|
||||
*
|
||||
* \return `OK` on success, `NG` otherwise.
|
||||
*/
|
||||
Judgement Sys_Rename(const char *path, const char *newPath);
|
||||
/**
|
||||
* \brief Remove a file or empty directory.
|
||||
*
|
||||
* \param [in] path Path to file or directory to be removed, must not be `NULL`
|
||||
*
|
||||
* \return `OK` on success, `NG` otherwise.
|
||||
*/
|
||||
Judgement Sys_Remove(const char *path);
|
||||
|
||||
// Path utilities
|
||||
|
||||
/// Retrieve the absolute file extension (leftmost not leading dot in basename).
|
||||
char *Sys_GetAbsoluteFileExtension(const char *path);
|
||||
/// Retrieve the file extension (rightmost not leading dot in basename).
|
||||
char *Sys_GetFileExtension(const char *path);
|
||||
/**
|
||||
* \brief Set `path` file extension to `ext`.
|
||||
*
|
||||
* \param [in,out] path UTF-8 path, must not be `NULL`
|
||||
* \param [in] ext File extension, including dot, must not be `NULL`
|
||||
*
|
||||
* \return Pointer to the extension inside `path`.
|
||||
*
|
||||
* \note Assumes `path` is is large enough to hold the result.
|
||||
*/
|
||||
char *Sys_SetFileExtension(char *path, const char *ext);
|
||||
/**
|
||||
* \brief Removes extension from `path` if it matches `ext`.
|
||||
*
|
||||
* \param [in,out] path UTF-8 path, must not be `NULL`
|
||||
* \param [in] ext File extension, including dot, leave to `""` or `NULL`
|
||||
* to remove any extension
|
||||
*
|
||||
* \return Length of the resulting path, in chars.
|
||||
*/
|
||||
size_t Sys_StripFileExtension(char *path, const char *ext);
|
||||
/**
|
||||
* \brief If file in `path` has no extension yet, set it to `ext`.
|
||||
*
|
||||
* \param [in,out] path UTF-8 path, must not be `NULL`
|
||||
* \param [in] ext Default extension to be set, including dot, must not be `NULL`
|
||||
*
|
||||
* \return Pointer to the extension inside `path`
|
||||
*
|
||||
* \note Assums `path` is large enough to hold the result.
|
||||
*/
|
||||
char *Sys_DefaultFileExtension(char *path, const char *ext);
|
||||
/**
|
||||
* Strip initial portion of `path` if it matches `basePath`.
|
||||
*
|
||||
* \param [in,out] path UTF-8 path, must not be `NULL`
|
||||
* \param [in] basePath Initial path to be removed, use `""` or `NULL` to strip the entire path and leave only file (Unix `basename()`)
|
||||
*
|
||||
* \return Length of the resulting path, in chars.
|
||||
*/
|
||||
size_t Sys_StripPath(char *path, const char *basePath);
|
||||
/// Return `path` depth (number of path components).
|
||||
size_t Sys_PathDepth(const char *path);
|
||||
|
||||
/**
|
||||
* \brief Strip leading slashes and change any path separator to `/`.
|
||||
*
|
||||
* \return Resulting path length, in chars.
|
||||
*/
|
||||
size_t Sys_ConvertPath(char *path);
|
||||
/**
|
||||
* \brief Change any path separator to a single `PATH_SEP`.
|
||||
*
|
||||
* \return Resulting path length, in chars.
|
||||
*/
|
||||
size_t Sys_ReplaceSeps(char *path);
|
||||
|
||||
/// Case-sensitive UTF-8 path comparison, regardless of separators.
|
||||
int Sys_PathCompare(const char *a, const char *b);
|
||||
// XXX int Sys_PathCompareNoCase(const char *a, const char *b);
|
||||
// XXX int Sys_PathCompareNoCaseAscii(const char *a, const char *b);
|
||||
|
||||
#endif
|
58
lonetix/include/df/sys/fsdef.h
Executable file
58
lonetix/include/df/sys/fsdef.h
Executable file
@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/fsdef.h
|
||||
*
|
||||
* Platform-specific filesystem types and definitions.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_FSDEF_H_
|
||||
#define DF_SYS_FSDEF_H_
|
||||
|
||||
#include "xpt.h"
|
||||
|
||||
/**
|
||||
* \typedef Fildes
|
||||
* \brief Platform specific file handle (`HANDLE` on Windows, `int` elsewhere).
|
||||
*
|
||||
* \def FILDES_BAD
|
||||
* \brief Bad file descriptor.
|
||||
*
|
||||
* \def PATH_SEP
|
||||
* \brief Path separator character (`\` on Windows, `/` elsewhere).
|
||||
*
|
||||
* \def EOLN
|
||||
* \brief Text file newline sequence (`\r\n` on Windows, `\n` elsewhere).
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef void *Fildes;
|
||||
|
||||
#define FILDES_BAD 0
|
||||
|
||||
#define PATH_SEP '\\'
|
||||
|
||||
#define EOLN "\r\n"
|
||||
|
||||
#else
|
||||
typedef int Fildes;
|
||||
|
||||
#define FILDES_BAD -1
|
||||
|
||||
#define PATH_SEP '/'
|
||||
|
||||
#define EOLN "\n"
|
||||
|
||||
#endif
|
||||
|
||||
/// I/O stream seek modes.
|
||||
typedef enum {
|
||||
SK_SET, ///< Seek from beginning of stream
|
||||
SK_CUR, ///< Seek from current position
|
||||
SK_END ///< Seek from stream end
|
||||
} SeekMode;
|
||||
|
||||
#endif
|
136
lonetix/include/df/sys/interlocked.h
Executable file
136
lonetix/include/df/sys/interlocked.h
Executable file
@ -0,0 +1,136 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/interlocked.h
|
||||
*
|
||||
* Lock-free atomic operations on integers and pointers.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (c) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_INTERLOCKED_H_
|
||||
#define DF_SYS_INTERLOCKED_H_
|
||||
|
||||
#include "xpt.h"
|
||||
|
||||
/**
|
||||
* \fn void Smp_AtomicStore(long *p, long v)
|
||||
* \fn void Smp_AtomicStoreRx(long *p, long v)
|
||||
* \fn void Smp_AtomicStoreRel(long *p, long v)
|
||||
* \fn void Smp_AtomicStorePtr(void **p, void *v)
|
||||
* \fn void Smp_AtomicStorePtrRx(void **p, void *v)
|
||||
* \fn void Smp_AtomicStorePtrRel(void **p, void *v)
|
||||
* \fn void Smp_AtomicStore8(Sint8 *p, Sint8 v)
|
||||
* \fn void Smp_AtomicStore8Rx(Sint8 *p, Sint8 v)
|
||||
* \fn void Smp_AtomicStore8Rel(Sint8 *p, Sint8 v)
|
||||
* \fn void Smp_AtomicStore16(Sint16 *p, Sint16 v)
|
||||
* \fn void Smp_AtomicStore16Rx(Sint16 *p, Sint16 v)
|
||||
* \fn void Smp_AtomicStore16Rel(Sint16 *p, Sint16 v)
|
||||
* \fn void Smp_AtomicStore32(Sint32 *p, Sint32 v)
|
||||
* \fn void Smp_AtomicStore32Rx(Sint32 *p, Sint32 v)
|
||||
* \fn void Smp_AtomicStore32Rel(Sint32 *p, Sint32 v)
|
||||
* \fn void Smp_AtomicStore64(Sint64 *p, Sint64 v)
|
||||
* \fn void Smp_AtomicStore64Rx(Sint64 *p, Sint64 v)
|
||||
* \fn void Smp_AtomicStore64Rel(Sint64 *p, Sint64 v)
|
||||
*
|
||||
* Atomic store operation to a variable or pointer.
|
||||
*
|
||||
* \note Only a subset of the fixed-size variants may be available on
|
||||
* specific architectures.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include "interlocked_intrin_msvc.h"
|
||||
#include "interlocked_ops_msvc.h"
|
||||
|
||||
#else
|
||||
|
||||
#if __GCC_ATOMIC_LONG_LOCK_FREE != 2
|
||||
#error "interlocked.h requires lock-free atomics on long!"
|
||||
#endif
|
||||
#if __GCC_ATOMIC_POINTER_LOCK_FREE != 2
|
||||
#error "interlocked.h requires lock-free atomics on void *!"
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* ATOMICS ON FIXED SIZE INTEGERS *
|
||||
******************************************************************************/
|
||||
|
||||
#if __GCC_ATOMIC_CHAR_LOCK_FREE == 2
|
||||
|
||||
#define INTERLOCKED_INT8
|
||||
|
||||
#define INTERLOCKED_TYPE Sint8
|
||||
#define INTERLOCKED_SUFFIX 8
|
||||
#include "interlocked_ops_gcc.h"
|
||||
#undef INTERLOCKED_TYPE
|
||||
#undef INTERLOCKED_SUFFIX
|
||||
|
||||
#endif /* INTERLOCKED_INT8 */
|
||||
|
||||
#if (__SIZEOF_SHORT__ == 2 && __GCC_ATOMIC_SHORT_LOCK_FREE == 2) || \
|
||||
(__SIZEOF_INT__ == 2 && __GCC_ATOMIC_INT_LOCK_FREE == 2)
|
||||
|
||||
#define INTERLOCKED_INT16
|
||||
|
||||
#define INTERLOCKED_TYPE Sint16
|
||||
#define INTERLOCKED_SUFFIX 16
|
||||
#include "interlocked_ops_gcc.h"
|
||||
#undef INTERLOCKED_TYPE
|
||||
#undef INTERLOCKED_SUFFIX
|
||||
|
||||
#endif /* INTERLOCKED_INT16 */
|
||||
|
||||
#if (__SIZEOF_INT__ == 4 && __GCC_ATOMIC_INT_LOCK_FREE == 2) || \
|
||||
(__SIZEOF_LONG__ == 4)
|
||||
|
||||
#define INTERLOCKED_INT32
|
||||
|
||||
#define INTERLOCKED_TYPE Sint32
|
||||
#define INTERLOCKED_SUFFIX 32
|
||||
#include "interlocked_ops_gcc.h"
|
||||
#undef INTERLOCKED_TYPE
|
||||
#undef INTERLOCKED_SUFFIX
|
||||
|
||||
#endif /* INTERLOCKED_INT32 */
|
||||
|
||||
#if (__SIZEOF_LONG_LONG__ == 8 && __GCC_ATOMIC_LONG_LONG_LOCK_FREE == 2) || \
|
||||
(__SIZEOF_LONG__ == 8)
|
||||
|
||||
#define INTERLOCKED_INT64
|
||||
|
||||
#define INTERLOCKED_TYPE Sint64
|
||||
#define INTERLOCKED_SUFFIX 64
|
||||
#include "interlocked_ops_gcc.h"
|
||||
#undef INTERLOCKED_TYPE
|
||||
#undef INTERLOCKED_SUFFIX
|
||||
|
||||
#endif /* INTERLOCKED_INT64 */
|
||||
|
||||
/******************************************************************************
|
||||
* ATOMICS ON LONG INTEGERS *
|
||||
******************************************************************************/
|
||||
|
||||
#define INTERLOCKED_TYPE long
|
||||
#define INTERLOCKED_SUFFIX
|
||||
#include "interlocked_ops_gcc.h"
|
||||
#undef INTERLOCKED_TYPE
|
||||
#undef INTERLOCKED_SUFFIX
|
||||
|
||||
/******************************************************************************
|
||||
* ATOMICS ON POINTERS *
|
||||
******************************************************************************/
|
||||
|
||||
#define INTERLOCKED_TYPE void *
|
||||
#define INTERLOCKED_SUFFIX Ptr
|
||||
#define INTERLOCKED_NO_ARIT
|
||||
#include "interlocked_ops_gcc.h"
|
||||
#undef INTERLOCKED_TYPE
|
||||
#undef INTERLOCKED_SUFFIX
|
||||
#undef INTERLOCKED_NO_ARIT
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
63
lonetix/include/df/sys/interlocked_intrin_msvc.h
Executable file
63
lonetix/include/df/sys/interlocked_intrin_msvc.h
Executable file
@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/interlocked_intrin_msvc.h
|
||||
*
|
||||
* MSVC-specific intrinsics for interlocked operations.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_INTERLOCKED_H_
|
||||
#error "use interlocked.h, do not include interlocked_intrin_msvc.h directly"
|
||||
#endif
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd)
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchangePointer)
|
||||
#pragma intrinsic(_InterlockedExchangePointer)
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange8)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd8)
|
||||
#pragma intrinsic(_InterlockedExchange8)
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange16)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd16)
|
||||
#pragma intrinsic(_InterlockedExchange16)
|
||||
#pragma intrinsic(_InterlockedAnd16)
|
||||
#pragma intrinsic(_InterlockedOr16)
|
||||
#pragma intrinsic(_InterlockedXor16)
|
||||
|
||||
#if (defined(_M_IX86) && _M_IX86 >= 500) || defined(_M_AMD64) || defined(_M_IA64) || defined(_M_ARM)
|
||||
#pragma intrinsic(_InterlockedCompareExchange64)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd64)
|
||||
#pragma intrinsic(_InterlockedExchange64)
|
||||
#endif
|
||||
|
||||
#ifdef _M_ARM
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange_nf)
|
||||
#pragma intrinsic(_InterlockedCompareExchange_acq)
|
||||
#pragma intrinsic(_InterlockedCompareExchange_rel)
|
||||
#pragma intrinsic(_InterlockedCompareExchangePointer_nf)
|
||||
#pragma intrinsic(_InterlockedCompareExchangePointer_acq)
|
||||
#pragma intrinsic(_InterlockedCompareExchangePointer_rel)
|
||||
#pragma intrinsic(_InterlockedCompareExchange8_nf)
|
||||
#pragma intrinsic(_InterlockedCompareExchange8_acq)
|
||||
#pragma intrinsic(_InterlockedCompareExchange8_rel)
|
||||
#pragma intrinsic(_InterlockedCompareExchange16_nf)
|
||||
#pragma intrinsic(_InterlockedCompareExchange16_acq)
|
||||
#pragma intrinsic(_InterlockedCompareExchange16_rel)
|
||||
#pragma intrinsic(_InterlockedCompareExchange64_nf)
|
||||
#pragma intrinsic(_InterlockedCompareExchange64_acq)
|
||||
#pragma intrinsic(_InterlockedCompareExchange64_rel)
|
||||
|
||||
#endif /* _M_ARM */
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#error "Sorry, not implemented yet"
|
||||
|
191
lonetix/include/df/sys/interlocked_ops_gcc.h
Executable file
191
lonetix/include/df/sys/interlocked_ops_gcc.h
Executable file
@ -0,0 +1,191 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/interlocked_ops_gcc.h
|
||||
*
|
||||
* Generates interlocked functions from GCC intrinsics, based on some macros.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*
|
||||
* This file should be `#include`d from `interlocked.h`, on GNUC compilers.
|
||||
* It generated interlocked primitives based on `INTERLOCKED_TYPE`,
|
||||
* `INTERLOCKED_SUFFIX` macros.
|
||||
* `#define`ing `INTERLOCKED_NO_ARIT` disables arithmetic functions
|
||||
* generation.
|
||||
* File may be `#include`d multiple times.
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_INTERLOCKED_H_
|
||||
#error "Use interlocked.h, do not include interlocked_gcc_ops.h directly"
|
||||
#endif
|
||||
|
||||
#ifndef INTERLOCKED_TYPE
|
||||
#error "Please define INTERLOCKED_TYPE for atomic operation target type"
|
||||
#endif
|
||||
#ifndef INTERLOCKED_SUFFIX
|
||||
#error "Please define INTERLOCKED_SUFFIX for atomic operation suffix"
|
||||
#endif
|
||||
|
||||
#define _PASTE(a, b) a ## b
|
||||
#define _XPASTE(a, b) _PASTE(a, b)
|
||||
#define _FNAME(wk, name, memory_order) \
|
||||
_XPASTE(_XPASTE(Smp_ ## wk ## Atomic ## name, INTERLOCKED_SUFFIX), memory_order)
|
||||
#define _FOP(op, memory_order, ...) \
|
||||
__atomic_ ## op (__VA_ARGS__, __ATOMIC_ ## memory_order)
|
||||
#define _FCAS(wkflag, succ_memory_order, fail_memory_order, ...) \
|
||||
__atomic_compare_exchange_n(__VA_ARGS__, wkflag, __ATOMIC_ ## succ_memory_order, __ATOMIC_ ## fail_memory_order)
|
||||
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Load,) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(load_n, SEQ_CST, _p);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Load,Rx) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(load_n, RELAXED, _p);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Load,Acq) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(load_n, ACQUIRE, _p);
|
||||
}
|
||||
|
||||
FORCE_INLINE void _FNAME(,Store,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
_FOP(store_n, SEQ_CST, _p, _v);
|
||||
}
|
||||
FORCE_INLINE void _FNAME(,Store,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
_FOP(store_n, RELAXED, _p, _v);
|
||||
}
|
||||
FORCE_INLINE void _FNAME(,Store,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
_FOP(store_n, RELEASE, _p, _v);
|
||||
}
|
||||
|
||||
#ifndef INTERLOCKED_NO_ARIT
|
||||
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Add,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(add_fetch, ACQ_REL, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Add,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(add_fetch, RELAXED, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Add,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(add_fetch, ACQUIRE, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Add,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(add_fetch, RELEASE, _p, _v);
|
||||
}
|
||||
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Sub,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(sub_fetch, ACQ_REL, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Sub,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(sub_fetch, RELAXED, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Sub,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(sub_fetch, ACQUIRE, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Sub,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(sub_fetch, RELEASE, _p, _v);
|
||||
}
|
||||
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Incr,) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(fetch_add, ACQ_REL, _p, 1);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Incr,Rx) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(fetch_add, RELAXED, _p, 1);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Incr,Acq) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(fetch_add, ACQUIRE, _p, 1);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Incr,Rel) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(fetch_add, RELEASE, _p, 1);
|
||||
}
|
||||
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Decr,) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(fetch_sub, ACQ_REL, _p, 1);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Decr,Rx) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(fetch_sub, RELAXED, _p, 1);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Decr,Acq) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(fetch_sub, ACQUIRE, _p, 1);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Decr,Rel) (INTERLOCKED_TYPE *_p)
|
||||
{
|
||||
return _FOP(fetch_sub, RELEASE, _p, 1);
|
||||
}
|
||||
|
||||
#endif /* INTERLOCKED_NO_ARIT */
|
||||
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Xchng,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(exchange_n, ACQ_REL, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Xchng,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(exchange_n, RELAXED, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Xchng,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(exchange_n, ACQUIRE, _p, _v);
|
||||
}
|
||||
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Xchng,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FOP(exchange_n, RELEASE, _p, _v);
|
||||
}
|
||||
|
||||
FORCE_INLINE Boolean _FNAME(,Cas,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FCAS(FALSE, ACQ_REL, ACQUIRE, _p, &_e, _v);
|
||||
}
|
||||
FORCE_INLINE Boolean _FNAME(,Cas,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FCAS(FALSE, RELAXED, RELAXED, _p, &_e, _v);
|
||||
}
|
||||
FORCE_INLINE Boolean _FNAME(,Cas,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FCAS(FALSE, ACQUIRE, ACQUIRE, _p, &_e, _v);
|
||||
}
|
||||
FORCE_INLINE Boolean _FNAME(,Cas,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FCAS(FALSE, RELEASE, RELAXED, _p, &_e, _v);
|
||||
}
|
||||
FORCE_INLINE Boolean _FNAME(Wk,Cas,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FCAS(TRUE, ACQ_REL, ACQUIRE, _p, &_e, _v);
|
||||
}
|
||||
FORCE_INLINE Boolean _FNAME(Wk,Cas,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FCAS(TRUE, RELAXED, RELAXED, _p, &_e, _v);
|
||||
}
|
||||
FORCE_INLINE Boolean _FNAME(Wk,Cas,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FCAS(TRUE, ACQUIRE, ACQUIRE, _p, &_e, _v);
|
||||
}
|
||||
FORCE_INLINE Boolean _FNAME(Wk,Xchng,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
|
||||
{
|
||||
return _FCAS(TRUE, RELEASE, RELAXED, _p, &_e, _v);
|
||||
}
|
||||
|
||||
#undef _PASTE
|
||||
#undef _XPASTE
|
||||
#undef _FNAME
|
||||
#undef _FOP
|
||||
#undef _FCAS
|
0
lonetix/include/df/sys/interlocked_ops_msvc.h
Executable file
0
lonetix/include/df/sys/interlocked_ops_msvc.h
Executable file
178
lonetix/include/df/sys/ip.h
Executable file
178
lonetix/include/df/sys/ip.h
Executable file
@ -0,0 +1,178 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/ip.h
|
||||
*
|
||||
* Internet Protocol (IP) definitions and types.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Right Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_IP_H_
|
||||
#define DF_SYS_IP_H_
|
||||
|
||||
#include "xpt.h"
|
||||
|
||||
/// Known Internet Protocol address family types enumeration.
|
||||
typedef enum {
|
||||
IP4, ///< Internet Protocol version 4
|
||||
IP6 ///< Internet Protocol version 6
|
||||
} IpType;
|
||||
|
||||
/// Internet Protocol version 4 (IPv4) address, big endian order.
|
||||
typedef union {
|
||||
Uint8 bytes[4]; ///< Address bytes representation
|
||||
Uint16 words[2]; ///< Address as a pair of 16-bits words
|
||||
Uint32 dword; ///< Address as a single 32-bits dword (big endian)
|
||||
} Ipv4adr;
|
||||
|
||||
/// Size of an IPv4 address in bytes.
|
||||
#define IPV4_SIZE 4
|
||||
/// Bits inside an IPv4 address.
|
||||
#define IPV4_WIDTH (IPV4_SIZE * 8)
|
||||
|
||||
STATIC_ASSERT(sizeof(Ipv4adr) == IPV4_SIZE, "Bad Ipv4adr size");
|
||||
|
||||
/// Size of a string to make an IPv4 address, **excluding** trailing `\0`.
|
||||
#define IPV4_STRLEN 16
|
||||
|
||||
/// IPv4 wildcard address static initializer: `0.0.0.0`.
|
||||
#define IPV4_ANY_INIT { { 0x00, 0x00, 0x00, 0x00 } }
|
||||
/// IPv4 loopback address static initializer: `127.0.0.1`.
|
||||
#define IPV4_LOOPBACK_INIT { { 0x7f, 0x00, 0x00, 0x01 } }
|
||||
/// IPv4 broadcast address static initializer: `255.255.255.255`.
|
||||
#define IPV4_BROADCAST_INIT { { 0xff, 0xff, 0xff, 0xff } }
|
||||
|
||||
/**
|
||||
* \brief Convert `Ipv4adr` to its string representation.
|
||||
*
|
||||
* The destination buffer **is assumed to be large enough to store
|
||||
* the resulting string**, a buffer of `IPV4_STRLEN + 1`
|
||||
* chars is safe to use as the `dest` argument.
|
||||
*
|
||||
* \param [in] adr Address to be converted, must not be `NULL`
|
||||
* \param [out] dest Destination storage for string representation, must not be `NULL`
|
||||
*
|
||||
* \return Pointer to the trailing `\0` `char` inside `dest`, useful
|
||||
* for further string concatenation.
|
||||
*/
|
||||
char *Ipv4_AdrToString(const Ipv4adr *adr, char *dest);
|
||||
|
||||
/**
|
||||
* \brief Convert an address from its string representation to `Ipv4adr`.
|
||||
*
|
||||
* \return `OK` if conversion was successful, `NG` if address string
|
||||
* does not represent a valid IP.
|
||||
*/
|
||||
Judgement Ipv4_StringToAdr(const char *address, Ipv4adr *dest);
|
||||
|
||||
/// Compare IPv4 addresses for equality.
|
||||
FORCE_INLINE Boolean Ipv4_Equal(const Ipv4adr *a, const Ipv4adr *b)
|
||||
{
|
||||
return a->dword == b->dword;
|
||||
}
|
||||
|
||||
/// Internet Protocol version 6 address.
|
||||
typedef union {
|
||||
Uint8 bytes[16]; ///< Address as raw bytes
|
||||
Uint16 words[8]; ///< Address as short words sequence
|
||||
Uint32 dwords[4]; ///< Address as dwords sequence
|
||||
} Ipv6adr;
|
||||
|
||||
/// Size of an IPv6 address in bytes.
|
||||
#define IPV6_SIZE 16
|
||||
/// Bits inside an IPv6 address.
|
||||
#define IPV6_WIDTH (IPV6_SIZE * 8)
|
||||
|
||||
STATIC_ASSERT(sizeof(Ipv6adr) == IPV6_SIZE, "Bad Ipv6adr size");
|
||||
|
||||
/// Size of a string to make an IPv6 address, **excluding** trailing `\0`.
|
||||
#define IPV6_STRLEN 46
|
||||
|
||||
/// Static initializer for an UNSPECIFIED Ipv6 address.
|
||||
#define IPV6_UNSPEC_INIT { { \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \
|
||||
} }
|
||||
|
||||
/// Static initializer for a LOOPBACK Ipv6 address.
|
||||
#define IPV6_LOOPBACK_INIT { { \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 \
|
||||
} }
|
||||
|
||||
/// Test whether an IPv6 address represents a mapped IPv4 address.
|
||||
#define IS_IPV6_V4MAPPED(v6) \
|
||||
((v6)->dwords[0] == 0 && \
|
||||
(v6)->dwords[1] == 0 && \
|
||||
(v6)->dwords[2] == BE32(0xffff))
|
||||
|
||||
/// Test whether an IPv6 address is multicast.
|
||||
#define IS_IPV6_MULTICAST(v6) ((v6)->bytes[0] == 0xff)
|
||||
|
||||
/**
|
||||
* \brief Convert an IPv6 address to its string representation, destination
|
||||
* storage should be `[IPV6_STRLEN + 1]`.
|
||||
*
|
||||
* \return Pointer to the trailing `\0` inside `dest`.
|
||||
*/
|
||||
char *Ipv6_AdrToString(const Ipv6adr *adr, char *dest);
|
||||
|
||||
/**
|
||||
* \brief Convert IPv6 address string to `Ipv6adr`.
|
||||
*
|
||||
* \return `OK` on success, `NG` if `address` does not represent a valid IPv6 address.
|
||||
*/
|
||||
Judgement Ipv6_StringToAdr(const char *address, Ipv6adr *dest);
|
||||
|
||||
/// Compare two IPv6 addresses for equality.
|
||||
FORCE_INLINE Boolean Ipv6_Equal(const Ipv6adr *a, const Ipv6adr *b)
|
||||
{
|
||||
return a->dwords[0] == b->dwords[0] && a->dwords[1] == b->dwords[1] &&
|
||||
a->dwords[2] == b->dwords[2] && a->dwords[3] == b->dwords[3];
|
||||
}
|
||||
|
||||
/// Generic IP address.
|
||||
typedef struct {
|
||||
IpType family; ///< Currently stored address family
|
||||
union {
|
||||
Uint8 bytes[IPV6_SIZE]; ///< Address as raw bytes, for convenient initialization
|
||||
Ipv4adr v4; ///< IPv4 address, if `family == IP4`
|
||||
Ipv6adr v6; ///< IPv6 address, if `family == IP6`
|
||||
|
||||
Uint32 dword; ///< As IPv4 single dword, for macro compat
|
||||
Uint16 words[8]; ///< As IPv4/IPv6 word sequence, for macro compat
|
||||
Uint32 dwords[4]; ///< As IPv6 dwords sequence, for macro compat
|
||||
};
|
||||
} Ipadr;
|
||||
|
||||
/**
|
||||
* \brief Convert a generic IP address to its string representation.
|
||||
*
|
||||
* \note A destination string of length `IPV6_STRLEN + 1`
|
||||
* is capable of storing an address string for any address family.
|
||||
*/
|
||||
char *Ip_AdrToString(const Ipadr *adr, char *dest);
|
||||
|
||||
/**
|
||||
* \brief Convert IP string representation to `Ipadr`.
|
||||
*
|
||||
* \return `OK` on success, `NG` if `address` is not a valid IP address.
|
||||
*/
|
||||
Judgement Ip_StringToAdr(const char *address, Ipadr *dest);
|
||||
|
||||
/// Compare generic addresses for equality.
|
||||
FORCE_INLINE Boolean Ip_Equal(const Ipadr *a, const Ipadr *b)
|
||||
{
|
||||
if (a->family != b->family)
|
||||
return FALSE;
|
||||
|
||||
switch (a->family) {
|
||||
case IP4: return Ipv4_Equal(&a->v4, &b->v4);
|
||||
case IP6: return Ipv6_Equal(&a->v6, &b->v6);
|
||||
default: UNREACHABLE; return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
154
lonetix/include/df/sys/sys.h
Executable file
154
lonetix/include/df/sys/sys.h
Executable file
@ -0,0 +1,154 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/sys.h
|
||||
*
|
||||
* Miscellaneous system functionality.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_ERR_H_
|
||||
#define DF_SYS_ERR_H_
|
||||
|
||||
#include "srcloc.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// for Sys_WipeMemory()
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_ReadWriteBarrier)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \typedef SysRet
|
||||
* \brief Platform-specific error code for system operations.
|
||||
*/
|
||||
typedef int SysRet; // errno type
|
||||
|
||||
/**
|
||||
* \brief Error status structure.
|
||||
*
|
||||
* Stores latest operation result and current error handling callback.
|
||||
*/
|
||||
typedef struct {
|
||||
/// Latest operation result status.
|
||||
SysRet code;
|
||||
/**
|
||||
* \brief Error handler callback.
|
||||
*
|
||||
* \param [in] code System error code
|
||||
* \param [in] reason Human readable concise message providing context to error, never `NULL`
|
||||
* \param [in] loc Source location where error occurred, `NULL` if unavailable
|
||||
* \param [in] obj User defined additional data forwarded to callback unaltered
|
||||
*/
|
||||
void (*func)(SysRet code, const char *reason, Srcloc *loc, void *obj);
|
||||
/// Additional user data to be forwarded to `func`.
|
||||
void *obj;
|
||||
} SysErrStat;
|
||||
|
||||
/**
|
||||
* \brief Abort error handler callback.
|
||||
*
|
||||
* This error handler terminates execution abnormally,
|
||||
* attempting to log an error message as accurate as possible using system
|
||||
* specific facilities.
|
||||
*
|
||||
* If this handler is registered, execution shall terminate as soon as an
|
||||
* exceptional error condition is encountered in the system layer.
|
||||
*/
|
||||
#define SYS_ERR_ABORT ((void (*)(SysRet, const char *, Srcloc *, void *)) -1)
|
||||
/**
|
||||
* \brief Ignoring error handler callback.
|
||||
*
|
||||
* If this handler is registered any system error is ignored.
|
||||
*/
|
||||
#define SYS_ERR_IGN ((void (*)(SysRet, const char *, Srcloc *, void *)) 0)
|
||||
/**
|
||||
* \brief Terminating error handler callback.
|
||||
*
|
||||
* Terminates execution providing sensible error message, it differs
|
||||
* from `SYS_ERR_ABORT` in that no exceptional termination semantics is
|
||||
* implied, but rather an unsuccessful event that caused immediate exit
|
||||
* (no core dump or stack traces are left behind).
|
||||
*/
|
||||
#define SYS_ERR_QUIT ((void (*)(SysRet, const char *, Srcloc *, void *)) 1)
|
||||
|
||||
/**
|
||||
* \brief Install a system error handler callback.
|
||||
*
|
||||
* Initially installed handler is `SYS_ERR_IGN`,
|
||||
* thus any error is effectively ignored unless a new handler is installed.
|
||||
*
|
||||
* Once installed, the error callback is called immediately for every
|
||||
* exceptional error condition encountered inside system layer.
|
||||
*
|
||||
* Error handlers are thread-local, thus different threads may implement
|
||||
* appropriate error handling policy without interfering with each other.
|
||||
*
|
||||
* \param [in] func Error handler function
|
||||
* \param [in] obj Custom user-provided object passed unaltered upon callback
|
||||
*
|
||||
* \see `SysErrStat` for callback documentation
|
||||
*/
|
||||
void Sys_SetErrFunc(void (*func)(SysRet, const char *, Srcloc *, void *), void *obj);
|
||||
|
||||
/**
|
||||
* Retrieve the system error status.
|
||||
*
|
||||
* \param [out] stat Storage for returned error status, may be `NULL`
|
||||
*
|
||||
* \return Last operation result status.
|
||||
*/
|
||||
SysRet Sys_GetErrStat(SysErrStat *stat);
|
||||
|
||||
/**
|
||||
* Trigger an out of memory error.
|
||||
*
|
||||
* @note Depending on the current error policy, execution may
|
||||
* very well continue after call returns.
|
||||
*/
|
||||
#define Sys_OutOfMemory() _Sys_OutOfMemory(__FILE__, __func__, __LINE__, 0)
|
||||
|
||||
// NOTE: implementation detail, should always be called through `Sys_OutOfMemory()`.
|
||||
NOINLINE void _Sys_OutOfMemory(const char *,
|
||||
const char *,
|
||||
unsigned long long,
|
||||
unsigned);
|
||||
|
||||
/**
|
||||
* \brief Zero-out `nbytes` bytes inside `data`, preventing compiler optimization.
|
||||
*
|
||||
* A compiler might optimize-out `memset()` or similar operations if `data`
|
||||
* is never read again.
|
||||
* This function ensures such operation is never optimized away, which
|
||||
* may be useful to zero-out sensitive data.
|
||||
*/
|
||||
FORCE_INLINE void Sys_WipeMemory(volatile void *data, size_t nbytes)
|
||||
{
|
||||
#if defined(_MSC_VER) || defined(__GNUC__)
|
||||
EXTERNC void *memset(void *, int, size_t);
|
||||
|
||||
memset((void *) data, 0, nbytes);
|
||||
|
||||
// Compiler fence
|
||||
#ifdef _MSC_VER
|
||||
_ReadWriteBarrier();
|
||||
#else
|
||||
__asm__ __volatile__ ("" : : : "memory");
|
||||
#endif
|
||||
|
||||
#else
|
||||
// Slow but portable
|
||||
volatile Uint8 *p = (volatile Uint8 *) data;
|
||||
while (nbytes--)
|
||||
*p++ = 0x00;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Sleep *at least* for the specified amount of **milliseconds**.
|
||||
void Sys_SleepMillis(Uint32 millis);
|
||||
|
||||
#endif
|
157
lonetix/include/df/sys/vt100.h
Executable file
157
lonetix/include/df/sys/vt100.h
Executable file
@ -0,0 +1,157 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/**
|
||||
* \file sys/vt100.h
|
||||
*
|
||||
* VT100 compliant control code sequences.
|
||||
*
|
||||
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||||
* \author Lorenzo Cogotti
|
||||
*/
|
||||
|
||||
#ifndef DF_SYS_VT100_H_
|
||||
#define DF_SYS_VT100_H_
|
||||
|
||||
#ifndef STR
|
||||
#define STR(x) #x
|
||||
#endif
|
||||
#ifndef XSTR
|
||||
#define XSTR(x) STR(x)
|
||||
#endif
|
||||
|
||||
/// VT100 escape character constant, prefixed to any command
|
||||
#define VTESC "\x1b"
|
||||
|
||||
/// Operating System Command marker, immediately following ESC
|
||||
#define VTOSC "]"
|
||||
/// CSI marker, immediately following ESC
|
||||
#define VTCSI "["
|
||||
|
||||
/// Enabling command suffix
|
||||
#define VTENB "h"
|
||||
/// Disabling command suffix
|
||||
#define VTDIS "l"
|
||||
|
||||
/// Designate Character Set - DEC Line mode drawing
|
||||
#define VTDCSLIN VTESC "(0"
|
||||
/// Designate Character Set - US ASCII (default) mode
|
||||
#define VTDCSCHR VTESC "(B"
|
||||
|
||||
/// Soft Terminal Reset (reset terminal to default state)
|
||||
#define VTSRST VTESC VTCSI "!p"
|
||||
|
||||
/// Cursor blink command mnemonic
|
||||
#define ATT160 "?12"
|
||||
/// Text Cursor Enable Mode command mnemonic
|
||||
#define DECTCEM "?25"
|
||||
|
||||
/// Start cursor blinking
|
||||
#define VTBLKENB VTESC VTCSI ATT160 VTENB
|
||||
/// Stop cursor blinking
|
||||
#define VTBLKDIS VTESC VTCSI ATT160 VTDIS
|
||||
/// Show cursor inside console
|
||||
#define VTCURSHW VTESC VTCSI DECTCEM VTENB
|
||||
/// Hide console cursor
|
||||
#define VTCURHID VTESC VTCSI DECTCEM VTDIS
|
||||
|
||||
/// Console Screen Buffer command mnemonic
|
||||
#define DECSCRB "?1049"
|
||||
|
||||
/// Switch to Alternate Screen buffer
|
||||
#define VTALTSCR VTESC VTCSI DECSCRB VTENB
|
||||
/// Switch to Main Screen buffer
|
||||
#define VTMAINSCR VTESC VTCSI DECSCRB VTDIS
|
||||
|
||||
/// Set Graphic Rendition command mnemonic
|
||||
#define SGR "m"
|
||||
|
||||
/// Set Graphics Rendition to `N` (N is any of the SGR constants)
|
||||
#define VTSGR(n) VTESC VTCSI XSTR(n) SGR
|
||||
|
||||
/// Obtain the corresponding background color code from a foreground color
|
||||
#define VT_TOBG(c) ((c) + 10)
|
||||
/// Obtain the corresponding bold/emphasized variant from a foreground or background color
|
||||
#define VT_TOBLD(c) ((c) + 60)
|
||||
|
||||
/// Reset graphics rendition to its default mode (both foreground and background)
|
||||
#define VTDFLT 0
|
||||
/// Enable bold text/emphasis
|
||||
#define VTBLD 1
|
||||
/// Disable bold text/emphasis
|
||||
#define VTNOBLD 22
|
||||
/// Enable text underline
|
||||
#define VTUND 4
|
||||
/// Disable text underline
|
||||
#define VTNOUND 24
|
||||
/// Invert foreground and background color
|
||||
#define VTINV 7
|
||||
/// Restore foreground and background to their normal value
|
||||
#define VTNOINV 27
|
||||
|
||||
/// Black color code (foreground)
|
||||
#define VTBLK 30
|
||||
/// Red color code (foreground)
|
||||
#define VTRED 31
|
||||
/// Green color code (foreground)
|
||||
#define VTGRN 32
|
||||
/// Yellow color code (foreground)
|
||||
#define VTYEL 33
|
||||
/// Blue color code (foreground)
|
||||
#define VTBLUE 34
|
||||
/// Magenta color code (foreground)
|
||||
#define VTMAGN 35
|
||||
/// Cyan color code (foreground)
|
||||
#define VTCYAN 36
|
||||
/// White color code (foreground)
|
||||
#define VTWHIT 37
|
||||
|
||||
/// Code to restore foreground color to its default value
|
||||
#define VTFGDFLT 39
|
||||
|
||||
#define VTBGBLK 40
|
||||
#define VTBGRED 41
|
||||
#define VTBGGRN 42
|
||||
#define VTBGYEL 43
|
||||
#define VTBGBLUE 44
|
||||
#define VTBGMAGN 45
|
||||
#define VTBGCYAN 46
|
||||
#define VTBGWHIT 47
|
||||
|
||||
#define VTBGDFLT 49
|
||||
|
||||
#define VTBLK_BLD 90
|
||||
#define VTRED_BLD 91
|
||||
#define VTGRN_BLD 92
|
||||
#define VTYEL_BLD 93
|
||||
#define VTBLUE_BLD 94
|
||||
#define VTMAGN_BLD 95
|
||||
#define VTCYAN_BLD 96
|
||||
#define VTWHIT_BLD 97
|
||||
|
||||
#define VTBGBLK_BLD 100
|
||||
#define VTBGRED_BLD 101
|
||||
#define VTBGGRN_BLD 102
|
||||
#define VTBGYEL_BLD 103
|
||||
#define VTBGBLUE_BLD 104
|
||||
#define VTBGMAGN_BLD 105
|
||||
#define VTBGCYAN_BLD 106
|
||||
#define VTBGWHIT_BLD 107
|
||||
|
||||
/// Erase in Display command mnemonic
|
||||
#define ED "J"
|
||||
/// Erase in Line command mnemonic
|
||||
#define EL "K"
|
||||
|
||||
/// Erase in Display with command parameter `n`
|
||||
#define VTED(n) VTESC VTCSI XSTR(n) ED
|
||||
/// Erase in Line with command parameter `n`
|
||||
#define VTEL(n) VTESC VTCSI XSTR(n) EL
|
||||
|
||||
/// Erase from cursor (inclusive) to end of display/line
|
||||
#define VTCUR 0
|
||||
/// Erase from the beginning of the line/display to end
|
||||
#define VTSET 1
|
||||
/// Erase everything in line/display
|
||||
#define VTALL 2
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user