From cb1a40859029f33184355475e51fec95afb79a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaroslav=20de=20la=20Pe=C3=B1a=20Smirnov?= Date: Sat, 22 Jul 2023 03:03:09 +0300 Subject: init Just some C wares; hmap, list, optional, unit tests. --- optional/optional.h | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 optional/optional.h (limited to 'optional/optional.h') diff --git a/optional/optional.h b/optional/optional.h new file mode 100644 index 0000000..6dcc3e2 --- /dev/null +++ b/optional/optional.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: MIT */ +/** + * optional.h - Macros for optional types. v0.1.0 + * + * Copyright (C) 2023 Yaroslav de la Peña Smirnov + * + * Documentation + * ============= + * + * Poor man's optional "type templates" for C. + * + * An object of optional type is an object that may or may not hold an object of + * 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 +#define OPTIONAL_H + +#include + +/** + * OPTIONALDEC - declare OPTIONAL type that holds data of type @T + * @T: the type of data to hold. + */ +#define OPTIONALDEC(T) struct __OPTIONAL_##T { bool has; T data; } + +/** + * OPTIONAL - declare an object that optionally holds type @T + * @T: the type of data to hold. + */ +#define OPTIONAL(T) struct __OPTIONAL_##T + +/** + * OPTNONE - initialize an OPTIONAL object to hold nothing. + */ +#define OPTNONE { .has = false } + +/** + * OPTSOME - initialize an OPTIONAL object to hold something. + * @d: data to hold. + */ +#define OPTSOME(d) { .has = true, .data = d } + +/** + * opt_set_none - set an OPTIONAL object to hold nothing. + * @opt: OPTIONAL object. + */ +#define opt_set_none(opt) opt.has = false + +/** + * opt_set_some - set an OPTIONAL object to hold something. + * @opt: OPTIONAL object. + * @d: data to hold. + */ +#define opt_set_some(opt, d) \ + ((opt).has = true, (opt).data = d) + +/** + * opt_has - true if an OPTIONAL object has something. + * @opt: OPTIONAL object. + */ +#define opt_has(opt) ((opt).has) + +/** + * opt_hasnt - true if an OPTIONAL object has nothing. + * @opt: OPTIONAL object. + */ +#define opt_hasnt(opt) (!(opt).has) + +/** + * opt_unwrap - if there's something in @src, copy it to @dst. + * @src: OPTIONAL object to copy data of type T from. + * @dst: variable of type T to copy to. + * + * Returns true if there was something, false if there wasn't. + */ +#define opt_unwrap(src, dst) \ + (opt_has(src) ? (dst = (src).data, true) : (false)) + +/** + * opt_default - get something from @src or default to @def. + * @src: OPTIONAL object to get data from. + * @def: default value if there's nothing. + */ +#define opt_default(src, def) opt_has(src) ? (src).data : def + +#endif -- cgit v1.2.3