From 03e8366b7e11e1b6c971f70d22fef07f7ad32448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaroslav=20de=20la=20Pe=C3=B1a=20Smirnov?= Date: Tue, 20 Feb 2024 23:49:31 +0300 Subject: optionals v0.2.0: custom-named optionals Can now declare custom named optionals, in order to declare optionals for two-token type names. --- optional/optional-test.c | 12 ++++++++++-- optional/optional.h | 45 ++++++++++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 15 deletions(-) (limited to 'optional') 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 +#include -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 /** - * 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. -- cgit v1.2.3