Skip to content

Commit 6b4ad7c

Browse files
Merge pull request #3 from dreamer-coding/rusty_null_system
Rusty null system
2 parents 006ac95 + 19bf0e7 commit 6b4ad7c

File tree

3 files changed

+349
-189
lines changed

3 files changed

+349
-189
lines changed

code/logic/fossil/sys/cnullptr.h

+196-95
Original file line numberDiff line numberDiff line change
@@ -14,96 +14,149 @@
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
2221
extern "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

Comments
 (0)