1414#ifndef FOSSIL_SYS_CNULLPTR_H
1515#define FOSSIL_SYS_CNULLPTR_H
1616
17- #include < stdint.h>
18- #include < stddef.h>
19- #include < assert.h>
17+ #include < stdio.h>
18+ #include < stdlib.h>
2019
2120#ifdef __cplusplus
2221extern " C" {
2322#endif
2423
25- // Ensure null pointer is defined for compatibility with C11, C23, and C++ standards
24+ /* *
25+ * @brief A cross-platform, safe null pointer management library for C and C++.
26+ *
27+ * This library provides a set of macros and utilities to ensure consistent
28+ * null pointer management across different versions of C and C++.
29+ * It introduces safer, more expressive pointer handling inspired by concepts
30+ * from modern programming languages like Rust, offering features like `Option`
31+ * semantics, safe pointer casting, and enhanced error management.
32+ *
33+ * Key Features:
34+ * - **Platform Agnostic Null Pointers:** Provides consistent `cnull` and `cnullptr`
35+ * definitions across C and C++ using modern `nullptr` or fallback `void*` based
36+ * null representation.
37+ * - **Safe Pointer Manipulation:** Macros like `cnullify()`, `cnotnull()`, and
38+ * `csafe_cast()` ensure safer memory management and prevent invalid pointer
39+ * dereferences.
40+ * - **Error Handling:** Offers expressive error management using `cpanic()` and
41+ * `cunwrap()`, providing detailed error messages and file/line diagnostics.
42+ * - **Optional Pointers:** Implements `COption`, a struct emulating Rust’s `Option<T>`
43+ * with macros like `csome()`, `cnone()`, `cunwrap_option()`, and `cunwrap_or_option()`.
44+ * - **Compile-Time Safety Hints:** Provides annotations like `cnullable` and `cnonnull`
45+ * for static analysis, improving code safety by detecting null pointer misuse.
46+ * - **Branch Prediction Optimization:** Includes `clikely()` and `cunlikely()` macros
47+ * to optimize conditional branches based on runtime behavior.
48+ * - **String Safety Constants:** Defines safe constants for null terminators,
49+ * newline characters, and empty strings in both C and wide-character formats.
50+ *
51+ * Intended Usage:
52+ * The library is suitable for scenarios requiring robust pointer management, particularly
53+ * in low-level systems programming, embedded environments, and performance-critical
54+ * applications. Developers transitioning from modern languages like Rust or C++ may
55+ * find the familiar semantics helpful.
56+ *
57+ * Compatibility:
58+ * - Supports **C11** and **C23** standards.
59+ * - Fully compatible with **C++11** and later.
60+ * - Provides graceful fallbacks for older compilers using `void*` based null pointers.
61+ *
62+ * Example Usage:
63+ * ```c
64+ * int* ptr = cnull;
65+ * cnullify(ptr); // Safely set to null
66+ *
67+ * int* data = malloc(sizeof(int));
68+ * *data = 42;
69+ * COption opt = csome(data);
70+ *
71+ * int* result = (int*)cunwrap_option(opt); // Unwrap safely
72+ * printf("Value: %d\n", *result);
73+ *
74+ * cdrop(data); // Nullify pointer safely
75+ * ```
76+ */
77+
78+ // Ensure null pointer definitions across C and C++ environments
2679#ifndef FOSSIL_CNULL
2780
28- #if __cplusplus >= 201103L || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
2981/* *
30- * @brief Definition for cnull pointers in C++11 and later or C23 and later.
82+ * @brief Safe and consistent null pointer definition for modern C++ and C standards.
83+ *
84+ * This section defines `cnull` and `cnullptr` for both C and C++ environments.
85+ * The definitions ensure compatibility across different language versions, providing
86+ * a clear and consistent way to represent null pointers.
87+ *
88+ * - **C++11 and Later:** If the code is compiled using C++11 (`__cplusplus >= 201103L`)
89+ * or newer, `nullptr` is used. `nullptr` is a type-safe null pointer constant that
90+ * prevents accidental misuse in pointer arithmetic or type ambiguities.
91+ *
92+ * - **C23 and Later:** In C23 (`__STDC_VERSION__ >= 202311L`), `nullptr` is introduced
93+ * as a type-safe null pointer constant, mirroring the C++ equivalent. The `cnull`
94+ * and `cnullptr` macros directly map to this standard definition.
95+ *
96+ * - **Older C Standards (C11 and Below):** If neither C23 nor C++11 is detected,
97+ * `cnull` and `cnullptr` are defined using `((void*)0)`, which is the traditional
98+ * and portable representation of a null pointer in C.
3199 *
32- * In C++11 or later, `cnullptr` is a keyword representing a cnull pointer constant.
33- * In C23 or later, `_cnullptr` is recognized in the same way as C++.
100+ * This abstraction guarantees that null pointer values are handled consistently
101+ * across different compilers and platforms, reducing the risk of undefined behavior
102+ * in pointer operations.
34103 */
104+ #if __cplusplus >= 201103L || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
35105 #define cnull nullptr
36106 #define cnullptr nullptr
37107#else
38- #if defined(_WIN64) || defined(_WIN32)
39- /* *
40- * @brief Definition for cnull pointers on Windows systems.
41- *
42- * For Windows (both 32-bit and 64-bit), we define `cnull` and `cnullptr` as 0.
43- */
44- #define cnull 0
45- #define cnullptr 0
46- #else
47- /* *
48- * @brief Definition for cnull pointers on POSIX systems, macOS, and embedded systems.
49- *
50- * For POSIX, macOS, and embedded systems, we define `cnull` and `cnullptr` as a void pointer to 0.
51- */
52- #define cnull (void *)(0 )
53- #define cnullptr (void *)(0 )
54- #endif
55- #endif
108+ #define cnull ((void *)0 )
109+ #define cnullptr ((void *)0 )
56110#endif
57111
112+ #endif // FOSSIL_CNULL
113+
58114/* *
59- * @brief Macro to nullify a pointer.
60- *
61- * This macro sets a pointer to `cnull` (`nullptr` in C++ or platform-appropriate null in C).
62- * It ensures that the pointer is safely assigned a null value.
63- *
64- * @param ptr The pointer to be nullified.
115+ * @brief Nullify a pointer safely.
116+ *
117+ * Ensures that the pointer is explicitly set to `cnull`.
65118 */
66119#define cnullify (ptr ) ((ptr) = cnull)
67120
68121/* *
69- * @brief Checks if a pointer is not null.
70- *
71- * A macro that explicitly verifies if a pointer is not null before using it.
122+ * @brief Check if a pointer is not null safely.
72123 *
73- * @param ptr The pointer to check.
74- * @return 1 if not null, 0 otherwise.
124+ * Prevents misuse of potentially null pointers.
75125 */
76126#define cnotnull (ptr ) ((ptr) != cnull)
77127
78128/* *
79- * @brief Represents an optional (nullable) value.
129+ * @brief Option-like behavior to return a pointer or a default value.
80130 *
81- * If the value is null, it returns a default value instead.
82- *
83- * @param ptr The pointer to check.
84- * @param default_val The default value to return if `ptr` is null.
85- * @return `ptr` if not null, otherwise `default_val`.
131+ * Mimics Rust's `Option::unwrap_or()` safely.
86132 */
87- #define cmaybe (ptr, default_val ) ((ptr) ? (ptr) : (default_val))
133+ #define cunwrap_or (ptr, default_val ) ((ptr) ? (ptr) : (default_val))
88134
89135/* *
90- * @brief Unwraps a pointer, asserting that it is not null.
91- *
92- * If the pointer is null, the program will terminate with an assertion failure.
93- * Otherwise, it returns the pointer itself for safe dereferencing.
136+ * @brief Unwraps a pointer safely or terminates if it's null.
94137 *
95- * @param ptr The pointer to unwrap.
96- * @return The unwrapped pointer if it is not null.
138+ * Mimics Rust's `Option::unwrap()`.
97139 */
98- #define cunwrap (ptr ) (assert ( (ptr) != cnull), (ptr ))
140+ #define cunwrap (ptr ) ((cnotnull (ptr)) ? (ptr) : (fprintf(stderr, " Fatal error: called cunwrap() on a null pointer at %s:%d \n " , __FILE__, __LINE__), exit(EXIT_FAILURE), cnull ))
99141
100142/* *
101- * @brief Marks a variable as unused to suppress compiler warnings .
143+ * @brief Safely casts one pointer type to another with null-checking .
102144 *
103- * Some compilers generate warnings when a variable is declared but not used.
104- * This macro safely prevents such warnings without affecting the program .
145+ * Mimics Rust's `as` with additional null safety. If the input is `cnull`,
146+ * it returns `cnull` instead of attempting an invalid cast .
105147 *
106- * @param x The variable that is intentionally unused.
148+ * @param type The target type for the cast.
149+ * @param ptr The pointer to cast.
150+ * @return The casted pointer or `cnull` if the input pointer is null.
151+ */
152+ #ifdef __cplusplus
153+ #define csafe_cast (type, ptr ) ((cnotnull(ptr)) ? (static_cast <type>(ptr)) : cnull)
154+ #else
155+ #define csafe_cast (type, ptr ) ((cnotnull(ptr)) ? ((type)(ptr)) : cnull)
156+ #endif
157+
158+ /* *
159+ * @brief Marks a variable as intentionally unused to prevent warnings.
107160 */
108161#ifndef cunused
109162 #if defined(__GNUC__) || defined(__clang__)
@@ -114,88 +167,136 @@ extern "C" {
114167#endif
115168
116169/* *
117- * @brief Annotations for nullable and nonnull pointers.
118- *
119- * These macros provide compiler hints about pointer validity, improving static analysis and safety.
170+ * @brief Compiler hints for nullable and nonnull values.
120171 *
121- * - **GCC/Clang:** Uses `__attribute__((nullable))` and `__attribute__((nonnull))`
122- * - **MSVC:** Uses `_Null_terminated_` and `_In_` (though `_In_` is not strictly equivalent to nonnull)
123- * - **Fallback:** If the compiler does not support these attributes, it defines empty macros.
172+ * Provides stronger safety checks at compile time.
124173 */
125174#if defined(__clang__) || defined(__GNUC__)
126175 #define cnullable __attribute__ ((nullable))
127176 #define cnonnull __attribute__ ((nonnull))
128177#elif defined(_MSC_VER)
129- #define cnullable _Null_terminated_ // Not a perfect match, but useful for MSVC
130- #define cnonnull _In_ // MSVC does not have a direct `nonnull` equivalent
178+ #define cnullable _Null_terminated_
179+ #define cnonnull _In_
131180#else
132181 #define cnullable
133182 #define cnonnull
134183#endif
135184
136- // Termination values for regular and wide strings
137-
138185/* *
139- * @brief Null-terminated character for C strings .
186+ * @brief Compiler branch prediction hints for likely and unlikely conditions .
140187 *
141- * This is used as a constant for the null character in C strings, typically to represent the end of a string .
188+ * Helps the compiler optimize branches based on expected conditions .
142189 */
143- #define cterm ' \0 '
190+ #if defined(__GNUC__) || defined(__clang__)
191+ #define clikely (x ) __builtin_expect(!!(x), 1 )
192+ #define cunlikely (x ) __builtin_expect(!!(x), 0 )
193+ #else
194+ #define clikely (x ) (x)
195+ #define cunlikely (x ) (x)
196+ #endif
197+
198+ // Safe string and character constants
144199
145200/* *
146- * @brief Null-terminated wide-character for wide strings.
147- *
148- * This is used as a constant for the null character in wide strings (`wchar_t` arrays), typically to represent the end of a wide string.
201+ * @brief Null terminators for C and wide strings.
149202 */
203+ #define cterm ' \0 '
150204#define wterm L' \0 '
151205
152- // Newline constants for regular and wide strings
206+ /* *
207+ * @brief Newline constants for C and wide strings.
208+ */
209+ #define cnewline ' \n '
210+ #define wnewline L' \n '
211+
212+ /* *
213+ * @brief Empty string constants for C and wide strings.
214+ */
215+ #define cempty " "
216+ #define wempty L" "
217+
218+ /* *
219+ * @brief Ensure safe cleanup by nullifying pointers after use.
220+ *
221+ * Mimics Rust's memory safety using explicit pointer management.
222+ */
223+ #define cdrop (ptr ) do { cnullify (ptr); } while (0 )
153224
154225/* *
155- * @brief Defines the newline character for C.
226+ * @brief Panic behavior for immediate program termination with error message.
227+ *
228+ * This macro causes the program to immediately terminate with an error message,
229+ * similar to Rust's `panic!()` functionality.
156230 *
157- * This is used in C and C++ environments for regular strings to denote a newline.
231+ * @param msg The message to display when panicking.
232+ */
233+ #define cpanic (msg ) (fprintf(stderr, " Panic: %s\n " , msg), exit(EXIT_FAILURE))
234+
235+ /* *
236+ * @brief Mimics Rust's Option type.
237+ *
238+ * The `coptional` macro represents a nullable pointer that can be either `cnull` or a valid pointer.
239+ * It can be used to model optional values that may or may not be present.
158240 */
159- #define cnewline ' \n '
241+ #define coptional ( ptr ) ((ptr) ? (ptr) : cnull)
160242
161243/* *
162- * @brief Defines the newline character for wide strings in C and C++.
244+ * @brief `COption` structure to mimic Rust's `Option<T>`.
245+ *
246+ * This structure allows representation of an optional value where it can either contain a value
247+ * (`Some`) or be `None` (`cnull`).
248+ */
249+ typedef struct {
250+ void * value; // The value held by the Option (could be a pointer to any type)
251+ int is_some; // Flag indicating whether the Option is `Some` (1) or `None` (0)
252+ } COption;
253+
254+ /* *
255+ * @brief Creates an `Option` with a value (Some).
163256 *
164- * This is used for wide-character strings (`wchar_t`) to denote a newline.
257+ * @param val The value to wrap in the Option.
258+ * @return The created `COption` containing the value.
165259 */
166- #define wnewline L' \n '
260+ #ifdef __cplusplus
261+ #define csome (val ) (COption{val, 1 })
262+ #else
263+ #define csome (val ) ((COption){(void *)(val), 1 })
264+ #endif
167265
168266/* *
169- * @brief Defines an empty C string .
267+ * @brief Creates an empty `Option` (None) .
170268 *
171- * This represents an empty string (`""`) for use in C and C++ code .
269+ * @return An `Option` representing `None` .
172270 */
173- #define cempty " "
271+ #ifdef __cplusplus
272+ #define cnone () (COption{cnull, 0 })
273+ #else
274+ #define cnone () ((COption){cnull, 0 })
275+ #endif
174276
175277/* *
176- * @brief Defines an empty wide-character string.
278+ * @brief Unwraps the `COption`. If it's `Some`, return the value; if it's `None`, panic.
279+ *
280+ * Mimics Rust's `Option::unwrap()`.
177281 *
178- * This represents an empty wide string (`L""`) for use in C and C++ code.
282+ * @param opt The `COption` to unwrap.
283+ * @return The value inside the `Option`.
179284 */
180- #define wempty L" "
285+ #define cunwrap_option ( opt ) ((opt).is_some ? (opt).value : (fprintf(stderr, " Panic: Unwrapped a None value at %s:%d \n " , __FILE__, __LINE__), exit(EXIT_FAILURE), cnull))
181286
182287/* *
183- * @brief Type-safe compiler attributes for null and nullable types .
288+ * @brief Returns the value inside the `COption` or a default value if it's `None` .
184289 *
185- * - `cnull` and `cnullptr` handle null pointers across platforms.
186- * - The constants `cterminator`, `wterminator`, `cterm`, `wterm` are used to represent the null terminators
187- * for regular and wide-character strings.
188- * - `cnewline` and `wnewline` are used to represent newline characters for regular and wide strings.
189- * - `cempty` and `wempty` represent empty strings for regular and wide-character strings.
290+ * Mimics Rust's `Option::unwrap_or()`.
190291 *
191- * These definitions ensure proper handling of string terminations and special characters across platforms.
192- * Compiler-specific attributes:
193- * - **GCC/Clang**: The use of `nullptr` for null pointers in C++ and null terminators for strings.
194- * - **MSVC**: MSVC compilers do not natively support `nullptr` but handle `cnull` as 0.
292+ * @param opt The `COption` to unwrap.
293+ * @param default_val The default value to return if the `COption` is `None`.
294+ * @return The value inside the `Option`, or the default value if `None`.
195295 */
296+ #define cunwrap_or_option (opt, default_val ) ((opt).is_some ? (opt).value : (default_val))
196297
197298#ifdef __cplusplus
198299}
199300#endif
200301
201- #endif
302+ #endif // FOSSIL_SYS_CNULLPTR_H
0 commit comments