250#ifndef _ACF_UTILS_OPTIONAL_H_
251#define _ACF_UTILS_OPTIONAL_H_
253#if defined(__STDC_VERSION__) && !(__STDC_VERSION__ >= 201112L)
254#error "Including <optional.h> from C code requires support for C11 or higher"
310#define IMPL_OPTIONAL_EXPLICIT(type_name, c_type) \
312 optional_state_t state; \
314 } opt_ ## type_name; \
315 static inline opt_ ## type_name \
316 opt_some_ ## type_name(c_type x) { \
317 opt_ ## type_name value = { \
323 static inline opt_ ## type_name \
324 opt_none_ ## type_name() { \
325 opt_ ## type_name value = { \
331 opt_is_some_ ## type_name(opt_ ## type_name opt) { \
332 return (opt.state == OPT_SOME); \
334 static inline optional_state_t \
335 opt_match_ ## type_name(opt_ ## type_name opt, \
336 c_type REQ_PTR(out_value)) { \
337 switch (opt.state) { \
339 *out_value = opt.value; \
342 memset(out_value, 0, sizeof (*out_value)); \
347 static inline optional_state_t \
348 opt_match_as_ref_ ## type_name(opt_ ## type_name const REQ_PTR(opt), \
349 c_type const *REQ_PTR(out_value)) { \
350 switch (opt->state) { \
352 *out_value = &opt->value; \
360 static inline optional_state_t \
361 opt_match_as_mut_ ## type_name(opt_ ## type_name REQ_PTR(opt), \
362 c_type *REQ_PTR(out_value)) { \
363 switch (opt->state) { \
365 *out_value = &opt->value; \
373 static inline c_type \
374 opt_unwrap_ ## type_name(opt_ ## type_name opt, const char *filename, \
375 int line, const char *expr) { \
376 switch (opt.state) { \
378 return (opt.value); \
380 logMsg("%s:%d: Attempted to unwrap None value in %s", \
381 filename, line, expr); \
386 static inline c_type const * \
387 opt_unwrap_as_ref_ ## type_name(opt_ ## type_name const REQ_PTR(opt), \
388 const char *filename, int line, const char *expr) { \
389 switch (opt->state) { \
391 return (&opt->value); \
393 logMsg("%s:%d: Attempted to unwrap None value in %s", \
394 filename, line, expr); \
399 static inline c_type * \
400 opt_unwrap_as_mut_ ## type_name(opt_ ## type_name REQ_PTR(opt), \
401 const char *filename, int line, const char *expr) { \
402 switch (opt->state) { \
404 return (&opt->value); \
406 logMsg("%s:%d: Attempted to unwrap None value in %s", \
407 filename, line, expr); \
412 static inline c_type \
413 opt_unwrap_or_ ## type_name(opt_ ## type_name opt, c_type dfl_value) { \
414 switch (opt.state) { \
416 return (opt.value); \
418 return (dfl_value); \
422 static inline c_type \
423 opt_unwrap_or_else_ ## type_name(opt_ ## type_name opt, \
424 c_type (*dfl_func)(void *), void *dfl_arg) { \
425 switch (opt.state) { \
427 return (opt.value); \
429 return (dfl_func(dfl_arg)); \
433 static inline opt_ ## type_name \
434 opt_or_ ## type_name(opt_ ## type_name a, opt_ ## type_name b) { \
443 static inline opt_ ## type_name \
444 opt_or_else_ ## type_name(opt_ ## type_name a, \
445 opt_ ## type_name (*func_b)(void *), void *arg_b) { \
450 return (func_b(arg_b)); \
465 opt_ ## type_name opt_into_ ## type_name(c_type);
501#define IMPL_OPTIONAL_IMPLICIT(type_name, c_type, none_value, none_check) \
504 } opt_ ## type_name; \
505 static inline opt_ ## type_name \
506 opt_some_ ## type_name(c_type x) { \
507 ASSERT(!(none_check)); \
508 opt_ ## type_name value = { \
513 static inline opt_ ## type_name \
514 opt_none_ ## type_name() { \
515 opt_ ## type_name value = { \
516 .value = (c_type)none_value \
521 opt_is_some_ ## type_name(opt_ ## type_name opt) { \
522 c_type x = opt.value; \
523 return (!(none_check)); \
525 static inline optional_state_t \
526 opt_match_ ## type_name(opt_ ## type_name opt, \
527 c_type REQ_PTR(out_value)) { \
528 c_type x = opt.value; \
529 if (!(none_check)) { \
533 *out_value = (c_type)none_value; \
537 static inline optional_state_t \
538 opt_match_as_ref_ ## type_name(opt_ ## type_name const REQ_PTR(opt), \
539 c_type const *REQ_PTR(out_value)) { \
540 c_type x = opt->value; \
541 if (!(none_check)) { \
542 *out_value = &opt->value; \
549 static inline optional_state_t \
550 opt_match_as_mut_ ## type_name(opt_ ## type_name REQ_PTR(opt), \
551 c_type *REQ_PTR(out_value)) { \
552 c_type x = opt->value; \
553 if (!(none_check)) { \
554 *out_value = &opt->value; \
561 static inline c_type \
562 opt_unwrap_ ## type_name(opt_ ## type_name opt, const char *filename, \
563 int line, const char *expr) { \
564 c_type x = opt.value; \
565 if (!(none_check)) { \
566 return (opt.value); \
568 logMsg("%s:%d: Attempted to unwrap None value in %s", \
569 filename, line, expr); \
573 static inline c_type const * \
574 opt_unwrap_as_ref_ ## type_name(opt_ ## type_name const REQ_PTR(opt), \
575 const char *filename, int line, const char *expr) { \
576 c_type x = opt->value; \
577 if (!(none_check)) { \
578 return (&opt->value); \
580 logMsg("%s:%d: Attempted to unwrap None value in %s", \
581 filename, line, expr); \
585 static inline c_type * \
586 opt_unwrap_as_mut_ ## type_name(opt_ ## type_name REQ_PTR(opt), \
587 const char *filename, int line, const char *expr) { \
588 c_type x = opt->value; \
589 if (!(none_check)) { \
590 return (&opt->value); \
592 logMsg("%s:%d: Attempted to unwrap None value in %s", \
593 filename, line, expr); \
597 static inline c_type \
598 opt_unwrap_or_ ## type_name(opt_ ## type_name opt, c_type dfl_value) { \
599 c_type x = opt.value; \
600 if (!(none_check)) { \
601 return (opt.value); \
603 return (dfl_value); \
606 static inline c_type \
607 opt_unwrap_or_else_ ## type_name(opt_ ## type_name opt, \
608 c_type (*dfl_func)(void *), void *dfl_arg) { \
609 c_type x = opt.value; \
610 if (!(none_check)) { \
611 return (opt.value); \
613 return (dfl_func(dfl_arg)); \
616 static inline opt_ ## type_name \
617 opt_or_ ## type_name(opt_ ## type_name a, opt_ ## type_name b) { \
618 c_type x = a.value; \
619 if (!(none_check)) { \
625 static inline opt_ ## type_name \
626 opt_or_else_ ## type_name(opt_ ## type_name a, \
627 opt_ ## type_name (*func_b)(void *), void *arg_b) { \
628 c_type x = a.value; \
629 if (!(none_check)) { \
632 return (func_b(arg_b)); \
635 static inline opt_ ## type_name \
636 opt_into_ ## type_name(c_type x) { \
637 if (!(none_check)) { \
638 return (opt_some_ ## type_name(x)); \
640 return (opt_none_ ## type_name()); \
661#define IMPL_OPTIONAL_ALIAS(orig_type_name, alias_type_name, alias_c_type) \
662 TYPE_ASSERT(((opt_ ## orig_type_name *)0)->value, alias_c_type); \
663 typedef opt_ ## orig_type_name opt_ ## alias_type_name; \
664 static inline opt_ ## alias_type_name \
665 opt_some_ ## alias_type_name(alias_c_type x) { \
666 return (opt_some_ ## orig_type_name(x)); \
668 static inline opt_ ## alias_type_name \
669 opt_none_ ## alias_type_name() { \
670 return (opt_none_ ## orig_type_name()); \
673 opt_is_some_ ## alias_type_name(opt_ ## alias_type_name opt) { \
674 return (opt_is_some_ ## orig_type_name(opt)); \
676 static inline optional_state_t \
677 opt_match_ ## alias_type_name(opt_ ## alias_type_name opt, \
678 alias_c_type REQ_PTR(out_value)) { \
679 return (opt_match_ ## orig_type_name(opt, out_value)); \
681 static inline optional_state_t \
682 opt_match_as_ref_ ## alias_type_name(opt_ ## alias_type_name const \
683 REQ_PTR(opt), alias_c_type const *REQ_PTR(out_value)) { \
684 return (opt_match_as_ref_ ## orig_type_name(opt, out_value)); \
686 static inline optional_state_t \
687 opt_match_as_mut_ ## alias_type_name(opt_ ## alias_type_name \
688 REQ_PTR(opt), alias_c_type *REQ_PTR(out_value)) { \
689 return (opt_match_as_mut_ ## orig_type_name(opt, out_value)); \
691 static inline alias_c_type \
692 opt_unwrap_ ## alias_type_name(opt_ ## alias_type_name opt, \
693 const char *filename, int line, const char *expr) { \
694 return (opt_unwrap_ ## orig_type_name(opt, \
695 filename, line, expr)); \
697 static inline alias_c_type const * \
698 opt_unwrap_as_ref_ ## alias_type_name(opt_ ## alias_type_name \
699 const REQ_PTR(opt), const char *filename, int line, \
700 const char *expr) { \
701 return (opt_unwrap_as_ref_ ## orig_type_name(opt, \
702 filename, line, expr)); \
704 static inline alias_c_type * \
705 opt_unwrap_as_mut_ ## alias_type_name(opt_ ## alias_type_name \
706 REQ_PTR(opt), const char *filename, int line, const char *expr) { \
707 return (opt_unwrap_as_mut_ ## orig_type_name(opt, \
708 filename, line, expr)); \
710 static inline alias_c_type \
711 opt_unwrap_or_ ## alias_type_name(opt_ ## alias_type_name opt, \
712 alias_c_type dfl_value) { \
713 return (opt_unwrap_or_ ## orig_type_name(opt, dfl_value)); \
715 static inline alias_c_type \
716 opt_unwrap_or_else_ ## alias_type_name(opt_ ## alias_type_name opt, \
717 alias_c_type (*dfl_func)(void *), void *dfl_arg) { \
718 return (opt_unwrap_or_else_ ## orig_type_name(opt, dfl_func, \
721 static inline opt_ ## alias_type_name \
722 opt_or_ ## alias_type_name(opt_ ## alias_type_name a, \
723 opt_ ## alias_type_name b) { \
724 return (opt_or_ ## orig_type_name(a, b)); \
726 static inline opt_ ## alias_type_name \
727 opt_or_else_ ## alias_type_name(opt_ ## alias_type_name a, \
728 opt_ ## alias_type_name (*func_b)(void *), void *arg_b) { \
729 return (opt_or_else_ ## orig_type_name(a, func_b, arg_b)); \
731 static inline opt_ ## alias_type_name \
732 opt_into_ ## alias_type_name(alias_c_type value) { \
733 return (opt_into_ ## orig_type_name(value)); \
757IMPL_OPTIONAL_EXPLICIT(size_t, size_t)
773#if defined(OPTIONALS_WITH_RUSTY_NAMES) || defined(__DOXYGEN__)
806IMPL_OPTIONAL_IMPLICIT(str, char *, NULL, x == NULL)
871_unknown_optional_type_you_need_to_include_your_custom_optional_h_(
void)
884#define OPTIONAL_TYPE_LIST_ADD(type_name, c_type, op_name) \
885 c_type: op_name ## type_name
905#ifndef OPTIONAL_TYPE_LIST
906#define OPTIONAL_TYPE_LIST(op_name) \
907 default: _unknown_optional_type_you_need_to_include_your_custom_optional_h_
911#define SIZE_T_OPTIONAL_LIST_ENTRY(op_name)
913#define SIZE_T_OPTIONAL_LIST_ENTRY(op_name) \
914 OPTIONAL_TYPE_LIST_ADD(size_t, size_t, op_name),
917#define OPTIONAL_TYPE_SELECTOR(op_name, expr) \
919 OPTIONAL_TYPE_LIST_ADD(int8_t, int8_t, op_name), \
920 OPTIONAL_TYPE_LIST_ADD(uint8_t, uint8_t, op_name), \
921 OPTIONAL_TYPE_LIST_ADD(int16_t, int16_t, op_name), \
922 OPTIONAL_TYPE_LIST_ADD(uint16_t, uint16_t, op_name), \
923 OPTIONAL_TYPE_LIST_ADD(int32_t, int32_t, op_name), \
924 OPTIONAL_TYPE_LIST_ADD(uint32_t, uint32_t, op_name), \
925 OPTIONAL_TYPE_LIST_ADD(int64_t, int64_t, op_name), \
926 OPTIONAL_TYPE_LIST_ADD(uint64_t, uint64_t, op_name), \
927 SIZE_T_OPTIONAL_LIST_ENTRY(op_name) \
928 OPTIONAL_TYPE_LIST_ADD(float, float, op_name), \
929 OPTIONAL_TYPE_LIST_ADD(double, double, op_name), \
930 OPTIONAL_TYPE_LIST_ADD(str, char *, op_name), \
931 OPTIONAL_TYPE_LIST_ADD(str_const, char const *, op_name), \
932 OPTIONAL_TYPE_LIST_ADD(vect2_t, vect2_t, op_name), \
933 OPTIONAL_TYPE_LIST_ADD(vect3_t, vect3_t, op_name), \
934 OPTIONAL_TYPE_LIST_ADD(vect3l_t, vect3l_t, op_name), \
935 OPTIONAL_TYPE_LIST_ADD(geo_pos2_t, geo_pos2_t, op_name), \
936 OPTIONAL_TYPE_LIST_ADD(geo_pos3_t, geo_pos3_t, op_name), \
937 OPTIONAL_TYPE_LIST_ADD(geo_pos2_32_t, geo_pos2_32_t, op_name), \
938 OPTIONAL_TYPE_LIST_ADD(geo_pos3_32_t, geo_pos3_32_t, op_name), \
939 OPTIONAL_TYPE_LIST(op_name))
976#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
977#define SOME(expr) OPTIONAL_TYPE_SELECTOR(opt_some_, expr)(expr)
979#define SOME(type_name, expr) opt_some_ ## type_name(expr)
1006#define NONE(type_name) opt_none_ ## type_name()
1014#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1015#define IS_SOME(opt) \
1016 OPTIONAL_TYPE_SELECTOR(opt_is_some_, (opt).value)(opt)
1018#define IS_SOME(type_name, opt) \
1019 opt_is_some_ ## type_name(opt)
1028#define IS_NONE(x) (!IS_SOME(x))
1066#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1067#define MATCH(opt, out_value) \
1068 OPTIONAL_TYPE_SELECTOR(opt_match_, (opt).value)((opt), (out_value))
1070#define MATCH(type_name, opt, out_value) \
1071 opt_match_ ## type_name((opt), (out_value))
1108#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1109#define MATCH_AS_REF(opt, out_value_p) \
1110 OPTIONAL_TYPE_SELECTOR(opt_match_as_ref_, (*(opt)).value)\
1111 ((opt), (out_value_p))
1113#define MATCH_AS_REF(type_name, opt, out_value_p) \
1114 opt_match_as_ref_ ## type_name((opt), (out_value_p))
1145#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1146#define MATCH_AS_MUT(opt, out_value_p) \
1147 OPTIONAL_TYPE_SELECTOR(opt_match_as_mut_, (*(opt)).value)\
1148 ((opt), (out_value_p))
1150#define MATCH_AS_MUT(type_name, opt, out_value_p) \
1151 opt_match_as_mut_ ## type_name((opt), (out_value_p))
1171#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1172#define UNWRAP(opt) \
1173 OPTIONAL_TYPE_SELECTOR(opt_unwrap_, (opt).value)((opt), \
1174 log_basename(__FILE__), __LINE__, #opt)
1176#define UNWRAP(type_name, opt) \
1177 opt_unwrap_ ## type_name((opt), log_basename(__FILE__), __LINE__, #opt)
1197#ifndef UNWRAP_AS_REF
1198#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1199#define UNWRAP_AS_REF(opt) \
1200 OPTIONAL_TYPE_SELECTOR(opt_unwrap_as_ref_, (*(opt)).value)((opt), \
1201 log_basename(__FILE__), __LINE__, #opt)
1203#define UNWRAP_AS_REF(type_name, opt) \
1204 opt_unwrap_as_ref_ ## type_name((opt), \
1205 log_basename(__FILE__), __LINE__, #opt)
1225#ifndef UNWRAP_AS_MUT
1226#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1227#define UNWRAP_AS_MUT(opt) \
1228 OPTIONAL_TYPE_SELECTOR(opt_unwrap_as_mut_, (*(opt)).value)((opt), \
1229 log_basename(__FILE__), __LINE__, #opt)
1231#define UNWRAP_AS_MUT(type_name, opt) \
1232 opt_unwrap_as_mut_ ## type_name((opt), \
1233 log_basename(__FILE__), __LINE__, #opt)
1258#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1259#define UNWRAP_OR(opt, dfl_value) \
1260 OPTIONAL_TYPE_SELECTOR(opt_unwrap_or_, (opt).value)((opt), (dfl_value))
1262#define UNWRAP_OR(type_name, opt, dfl_value) \
1263 opt_unwrap_or_ ## type_name((opt), (dfl_value))
1296#ifndef UNWRAP_OR_ELSE
1297#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1298#define UNWRAP_OR_ELSE(opt, dfl_func, dfl_arg) \
1299 OPTIONAL_TYPE_SELECTOR(opt_unwrap_or_else_, (opt).value)\
1300 ((opt), (dfl_func), (dfl_arg))
1302#define UNWRAP_OR_ELSE(type_name, opt, dfl_func, dfl_arg) \
1303 opt_unwrap_or_else_ ## type_name((opt), (dfl_func), (dfl_arg))
1333#ifndef UNWRAP_OR_RET
1334#define UNWRAP_OR_RET(opt, ...) \
1335 ({ __typeof(opt) __tmp = (opt); \
1336 if (IS_NONE(__tmp)) { return __VA_ARGS__; } \
1363#ifndef UNWRAP_OR_GOTO
1364#define UNWRAP_OR_GOTO(opt, label) \
1365 ({ __typeof(opt) __tmp = (opt); \
1366 if (IS_NONE(__tmp)) { goto label; } UNWRAP(__tmp); })
1386#ifndef UNWRAP_OR_BREAK
1387#define UNWRAP_OR_BREAK(opt) \
1388 ({ __typeof(opt) __tmp = (opt); \
1389 if (IS_NONE(__tmp)) { break; } UNWRAP(__tmp); })
1409#ifndef UNWRAP_OR_CONTINUE
1410#define UNWRAP_OR_CONTINUE(opt) \
1411 ({ __typeof(opt) __tmp = (opt); \
1412 if (IS_NONE(__tmp)) { continue; } UNWRAP(__tmp); })
1438#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1439#define OPT_OR(a, b) \
1440 OPTIONAL_TYPE_SELECTOR(opt_or_, (a).value)((a), (b))
1442#define OPT_OR(type_name, a, b) \
1443 opt_or_ ## type_name((a), (b))
1474#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1475#define OPT_OR_ELSE(a, func_b, arg_b) \
1476 OPTIONAL_TYPE_SELECTOR(opt_or_else_, (a).value)((a), (func_b), (arg_b))
1478#define OPT_OR_ELSE(type_name, a, func_b, arg_b) \
1479 opt_or_ ## type_name((a), (func_b), (arg_b))
1517#define IF_LET(vartype, varname, opt) \
1519 vartype __if_let_tmp_##varname; \
1527 if (MATCH((opt), (void *)&__if_let_tmp_##varname) == \
1529 vartype varname = __if_let_tmp_##varname;
1545#define IF_LET_AS_REF(vartype, varname, opt) \
1547 vartype __if_let_tmp_##varname; \
1548 if (MATCH_AS_REF((opt), (void *)&__if_let_tmp_##varname) == \
1550 vartype varname = __if_let_tmp_##varname;
1551#define IF_LET_ELSE } else {
1552#define IF_LET_END }}
1583#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1584#define OPT_INTO(value) OPTIONAL_TYPE_SELECTOR(opt_into_, (value))(value)
1586#define OPT_INTO(type_name, opt) opt_into_ ## type_name(value)
#define IS_NULL_GEO_POS2(a)
#define IS_NULL_GEO_POS3(a)
#define IMPL_OPTIONAL_ALIAS(orig_type_name, alias_type_name, alias_c_type)
Declares a type alias for an existing optional type.
#define IMPL_OPTIONAL_EXPLICIT(type_name, c_type)
Declares a custom optional type with explicit NONE encoding.
#define IMPL_OPTIONAL_IMPLICIT(type_name, c_type, none_value, none_check)
Declares a custom optional type with implicit NONE encoding.
@ OPT_SOME
State denoting that the optional contains a valid value.
@ OPT_NONE
State denoting that the optional contains no valid value.