/** * optional.h - some macros for optional types * * 2023 Yaroslav de la Peña Smirnov * */ #ifndef OPTIONAL_H #define OPTIONAL_H #include /** * OPTIONAL - declare an object that optionally holds type @T * @T: the type of data to hold. * @name: the name of the variable or struct field. */ #define OPTIONAL(T, name) struct { bool has; T data; } name /** * 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