aboutsummaryrefslogtreecommitdiff
path: root/optional
diff options
context:
space:
mode:
authorYaroslav de la Peña Smirnov <yps@yaroslavps.com>2024-02-20 23:49:31 +0300
committerYaroslav de la Peña Smirnov <yps@yaroslavps.com>2024-02-20 23:49:31 +0300
commit03e8366b7e11e1b6c971f70d22fef07f7ad32448 (patch)
tree5bfcb0c7f11f85b70a18ecdd308bc2057828c6e9 /optional
parentcb1a40859029f33184355475e51fec95afb79a73 (diff)
downloadc-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.c12
-rw-r--r--optional/optional.h45
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.