diff options
| author | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2024-02-20 23:49:31 +0300 | 
|---|---|---|
| committer | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2024-02-20 23:49:31 +0300 | 
| commit | 03e8366b7e11e1b6c971f70d22fef07f7ad32448 (patch) | |
| tree | 5bfcb0c7f11f85b70a18ecdd308bc2057828c6e9 /optional | |
| parent | cb1a40859029f33184355475e51fec95afb79a73 (diff) | |
| download | c-wares-03e8366b7e11e1b6c971f70d22fef07f7ad32448.tar.gz c-wares-03e8366b7e11e1b6c971f70d22fef07f7ad32448.zip | |
optionals v0.2.0: custom-named optionals
Can now declare custom named optionals, in order to declare optionals
for two-token type names.
Diffstat (limited to 'optional')
| -rw-r--r-- | optional/optional-test.c | 12 | ||||
| -rw-r--r-- | optional/optional.h | 45 | 
2 files changed, 42 insertions, 15 deletions
| diff --git a/optional/optional-test.c b/optional/optional-test.c index 88577d3..73597e5 100644 --- a/optional/optional-test.c +++ b/optional/optional-test.c @@ -2,9 +2,11 @@  #include "../utest/utest.h"  #include <stdio.h> +#include <string.h> -OPTIONALDEC(int); -OPTIONALDEC(char); +DECL_OPTIONAL(int); +DECL_OPTIONAL(char); +DECL_NAMED_OPTIONAL(str, char *);  struct my_struct {  	OPTIONAL(int) a; @@ -27,6 +29,12 @@ TEST_BEGIN(test_optional_example)  	OPTIONAL(char) y = OPTNONE;  	OPTIONAL(char) z = OPTSOME('z'); + +	OPTIONAL(str) s = OPTSOME("hello, world!"); + +	expect(!strcmp(opt_default(s, "NULL!"), "hello, world!"), +		   "expected to contain string \"hello, world!\""); +  	float xy, xz;  	expect(opt_has(my.a), "expected to contain something"); diff --git a/optional/optional.h b/optional/optional.h index 6dcc3e2..4eb0e87 100644 --- a/optional/optional.h +++ b/optional/optional.h @@ -1,8 +1,8 @@  /* SPDX-License-Identifier: MIT */  /** - * optional.h - Macros for optional types. v0.1.0 + * optional.h - Macros for optional types. v0.2.0   * - * Copyright (C) 2023 Yaroslav de la Peña Smirnov + * Copyright (C) 2023-2024 Yaroslav de la Peña Smirnov   *   * Documentation   * ============= @@ -13,9 +13,6 @@   * a certain type inside itself at any time. Before declaring a variable of a   * certain OPTIONAL type, said OPTIONAL type should be declared with the   * OPTIONALDEC macro. - * - * Currently only supports types that are composed of one token, i.e. no - * structs, enums, unions, etc. Might expand it in the future to support them.   */  #ifndef OPTIONAL_H @@ -24,10 +21,28 @@  #include <stdbool.h>  /** - * OPTIONALDEC - declare OPTIONAL type that holds data of type @T + * DECLARE_NAMED_OPTIONAL - declare OPTIONAL that holds type @T called @optname + * @optname:	name of Optional type. + * @T:			type to hold. + * + * This macro is used to give a custom name to the optional type. This is, + * unfortunately, needed due to the nature of C's type system and the fact that + * we have types in C that are made up of several tokens, which does not bode + * well for these kinds of macros. + */ +#define DECL_NAMED_OPTIONAL(optname, T) \ +	struct __OPTIONAL_##optname {       \ +		T	 data;                      \ +		bool has;                       \ +	} + +/** + * DECLARE_OPTIONAL - declare OPTIONAL "type" that holds data of type @T   * @T:		the type of data to hold. + * + * The type @T also becomes the "name" of the optional type.   */ -#define OPTIONALDEC(T) struct __OPTIONAL_##T { bool has; T data; } +#define DECL_OPTIONAL(T) DECL_NAMED_OPTIONAL(T, T)  /**   * OPTIONAL - declare an object that optionally holds type @T @@ -38,13 +53,19 @@  /**   * OPTNONE - initialize an OPTIONAL object to hold nothing.   */ -#define OPTNONE { .has = false } +#define OPTNONE      \ +	{                \ +		.has = false \ +	}  /**   * OPTSOME - initialize an OPTIONAL object to hold something.   * @d:	data to hold.   */ -#define OPTSOME(d) { .has = true, .data = d } +#define OPTSOME(d)             \ +	{                          \ +		.has = true, .data = d \ +	}  /**   * opt_set_none - set an OPTIONAL object to hold nothing. @@ -57,8 +78,7 @@   * @opt:	OPTIONAL object.   * @d:		data to hold.   */ -#define opt_set_some(opt, d) \ -	((opt).has = true, (opt).data = d) +#define opt_set_some(opt, d) ((opt).has = true, (opt).data = d)  /**   * opt_has - true if an OPTIONAL object has something. @@ -79,8 +99,7 @@   *   * Returns true if there was something, false if there wasn't.   */ -#define opt_unwrap(src, dst) \ -	(opt_has(src) ? (dst = (src).data, true) : (false)) +#define opt_unwrap(src, dst) (opt_has(src) ? (dst = (src).data, true) : (false))  /**   * opt_default - get something from @src or default to @def. | 
