libacfutils
A general purpose library of utility functions designed to make it easier to develop addons for the X-Plane flight simulator.
Loading...
Searching...
No Matches
optional.h
Go to the documentation of this file.
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license in the file COPYING
10 * or http://www.opensource.org/licenses/CDDL-1.0.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file COPYING.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2023 Saso Kiselkov. All rights reserved.
24 */
250#ifndef _ACF_UTILS_OPTIONAL_H_
251#define _ACF_UTILS_OPTIONAL_H_
252
253#if defined(__STDC_VERSION__) && !(__STDC_VERSION__ >= 201112L)
254#error "Including <optional.h> from C code requires support for C11 or higher"
255#endif
256
257#include <math.h>
258#include <string.h>
259#include <stdbool.h>
260#include <stdint.h>
261
262#include "assert.h"
263#include "log.h"
264#include "geom.h"
265#include "sysmacros.h"
266
267#ifdef __cplusplus
268extern "C" {
269#endif
270
279
310#define IMPL_OPTIONAL_EXPLICIT(type_name, c_type) \
311 typedef struct { \
312 optional_state_t state; \
313 c_type value; \
314 } opt_ ## type_name; \
315 static inline opt_ ## type_name \
316 opt_some_ ## type_name(c_type x) { \
317 opt_ ## type_name value = { \
318 .state = OPT_SOME, \
319 .value = x \
320 }; \
321 return (value); \
322 } \
323 static inline opt_ ## type_name \
324 opt_none_ ## type_name() { \
325 opt_ ## type_name value = { \
326 .state = OPT_NONE, \
327 }; \
328 return (value); \
329 } \
330 static inline bool \
331 opt_is_some_ ## type_name(opt_ ## type_name opt) { \
332 return (opt.state == OPT_SOME); \
333 } \
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) { \
338 case OPT_SOME: \
339 *out_value = opt.value; \
340 return (OPT_SOME); \
341 case OPT_NONE: \
342 memset(out_value, 0, sizeof (*out_value)); \
343 return (OPT_NONE); \
344 } \
345 VERIFY_FAIL(); \
346 } \
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) { \
351 case OPT_SOME: \
352 *out_value = &opt->value; \
353 return (OPT_SOME); \
354 case OPT_NONE: \
355 *out_value = NULL; \
356 return (OPT_NONE); \
357 } \
358 VERIFY_FAIL(); \
359 } \
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) { \
364 case OPT_SOME: \
365 *out_value = &opt->value; \
366 return (OPT_SOME); \
367 case OPT_NONE: \
368 *out_value = NULL; \
369 return (OPT_NONE); \
370 } \
371 VERIFY_FAIL(); \
372 } \
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) { \
377 case OPT_SOME: \
378 return (opt.value); \
379 case OPT_NONE: \
380 logMsg("%s:%d: Attempted to unwrap None value in %s", \
381 filename, line, expr); \
382 VERIFY_FAIL(); \
383 } \
384 VERIFY_FAIL(); \
385 } \
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) { \
390 case OPT_SOME: \
391 return (&opt->value); \
392 case OPT_NONE: \
393 logMsg("%s:%d: Attempted to unwrap None value in %s", \
394 filename, line, expr); \
395 VERIFY_FAIL(); \
396 } \
397 VERIFY_FAIL(); \
398 } \
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) { \
403 case OPT_SOME: \
404 return (&opt->value); \
405 case OPT_NONE: \
406 logMsg("%s:%d: Attempted to unwrap None value in %s", \
407 filename, line, expr); \
408 VERIFY_FAIL(); \
409 } \
410 VERIFY_FAIL(); \
411 } \
412 static inline c_type \
413 opt_unwrap_or_ ## type_name(opt_ ## type_name opt, c_type dfl_value) { \
414 switch (opt.state) { \
415 case OPT_SOME: \
416 return (opt.value); \
417 case OPT_NONE: \
418 return (dfl_value); \
419 } \
420 VERIFY_FAIL(); \
421 } \
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) { \
426 case OPT_SOME: \
427 return (opt.value); \
428 case OPT_NONE: \
429 return (dfl_func(dfl_arg)); \
430 } \
431 VERIFY_FAIL(); \
432 } \
433 static inline opt_ ## type_name \
434 opt_or_ ## type_name(opt_ ## type_name a, opt_ ## type_name b) { \
435 switch (a.state) { \
436 case OPT_SOME: \
437 return (a); \
438 case OPT_NONE: \
439 return (b); \
440 } \
441 VERIFY_FAIL(); \
442 } \
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) { \
446 switch (a.state) { \
447 case OPT_SOME: \
448 return (a); \
449 case OPT_NONE: \
450 return (func_b(arg_b)); \
451 } \
452 VERIFY_FAIL(); \
453 } \
454 /* \
455 * This function cannot exist for explicit optional types, but in \
456 * order for this to work for aliases to implicit optional types, \
457 * to make the same aliasing function work for all, we fake that \
458 * there is an explicit type equivalent somewhere. We don't actually \
459 * ever provide an implementation, so attempting to call this with \
460 * an explicit optional type is still safe and won't link, but it \
461 * will not throw a compile-time error due to a call to a \
462 * non-existent function, or a runtime error if we did have an \
463 * non-functional faux implementation. \
464 */ \
465 opt_ ## type_name opt_into_ ## type_name(c_type);
466
501#define IMPL_OPTIONAL_IMPLICIT(type_name, c_type, none_value, none_check) \
502 typedef struct { \
503 c_type value; \
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 = { \
509 .value = x \
510 }; \
511 return (value); \
512 } \
513 static inline opt_ ## type_name \
514 opt_none_ ## type_name() { \
515 opt_ ## type_name value = { \
516 .value = (c_type)none_value \
517 }; \
518 return (value); \
519 } \
520 static inline bool \
521 opt_is_some_ ## type_name(opt_ ## type_name opt) { \
522 c_type x = opt.value; \
523 return (!(none_check)); \
524 } \
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)) { \
530 *out_value = x; \
531 return (OPT_SOME); \
532 } else { \
533 *out_value = (c_type)none_value; \
534 return (OPT_NONE); \
535 } \
536 } \
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; \
543 return (OPT_SOME); \
544 } else { \
545 *out_value = NULL; \
546 return (OPT_NONE); \
547 } \
548 } \
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; \
555 return (OPT_SOME); \
556 } else { \
557 *out_value = NULL; \
558 return (OPT_NONE); \
559 } \
560 } \
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); \
567 } else { \
568 logMsg("%s:%d: Attempted to unwrap None value in %s", \
569 filename, line, expr); \
570 VERIFY_FAIL(); \
571 } \
572 } \
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); \
579 } else { \
580 logMsg("%s:%d: Attempted to unwrap None value in %s", \
581 filename, line, expr); \
582 VERIFY_FAIL(); \
583 } \
584 } \
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); \
591 } else { \
592 logMsg("%s:%d: Attempted to unwrap None value in %s", \
593 filename, line, expr); \
594 VERIFY_FAIL(); \
595 } \
596 } \
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); \
602 } else { \
603 return (dfl_value); \
604 } \
605 } \
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); \
612 } else { \
613 return (dfl_func(dfl_arg)); \
614 } \
615 } \
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)) { \
620 return (a); \
621 } else { \
622 return (b); \
623 } \
624 } \
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)) { \
630 return (a); \
631 } else { \
632 return (func_b(arg_b)); \
633 } \
634 } \
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)); \
639 } else { \
640 return (opt_none_ ## type_name()); \
641 } \
642 }
643
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)); \
667 } \
668 static inline opt_ ## alias_type_name \
669 opt_none_ ## alias_type_name() { \
670 return (opt_none_ ## orig_type_name()); \
671 } \
672 static inline bool \
673 opt_is_some_ ## alias_type_name(opt_ ## alias_type_name opt) { \
674 return (opt_is_some_ ## orig_type_name(opt)); \
675 } \
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)); \
680 } \
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)); \
685 } \
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)); \
690 } \
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)); \
696 } \
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)); \
703 } \
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)); \
709 } \
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)); \
714 } \
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, \
719 dfl_arg)); \
720 } \
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)); \
725 } \
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)); \
730 } \
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)); \
734 }
739IMPL_OPTIONAL_EXPLICIT(uint8_t, uint8_t)
741IMPL_OPTIONAL_EXPLICIT(int16_t, int16_t)
743IMPL_OPTIONAL_EXPLICIT(uint16_t, uint16_t)
745IMPL_OPTIONAL_EXPLICIT(int32_t, int32_t)
747IMPL_OPTIONAL_EXPLICIT(uint32_t, uint32_t)
749IMPL_OPTIONAL_EXPLICIT(int64_t, int64_t)
751IMPL_OPTIONAL_EXPLICIT(uint64_t, uint64_t)
752#if !APL
754IMPL_OPTIONAL_ALIAS(uint64_t, size_t, size_t)
755#else // APL
757IMPL_OPTIONAL_EXPLICIT(size_t, size_t)
758#endif // APL
759
765IMPL_OPTIONAL_IMPLICIT(float, float, NAN, isnan(x))
771IMPL_OPTIONAL_IMPLICIT(double, double, NAN, isnan(x))
773#if defined(OPTIONALS_WITH_RUSTY_NAMES) || defined(__DOXYGEN__)
776IMPL_OPTIONAL_ALIAS(int8_t, i8, int8_t)
778IMPL_OPTIONAL_ALIAS(uint8_t, u8, uint8_t)
780IMPL_OPTIONAL_ALIAS(int16_t, i16, int16_t)
782IMPL_OPTIONAL_ALIAS(uint16_t, u16, uint16_t)
784IMPL_OPTIONAL_ALIAS(int32_t, i32, int32_t)
786IMPL_OPTIONAL_ALIAS(uint32_t, u32, uint32_t)
788IMPL_OPTIONAL_ALIAS(int64_t, i64, int64_t)
790IMPL_OPTIONAL_ALIAS(uint64_t, u64, uint64_t)
792IMPL_OPTIONAL_ALIAS(size_t, usize, size_t)
794IMPL_OPTIONAL_ALIAS(float, f32, float)
796IMPL_OPTIONAL_ALIAS(double, f64, double)
797
798#endif // defined(OPTIONALS_WITH_RUSTY_NAMES) || defined(__DOXYGEN__)
806IMPL_OPTIONAL_IMPLICIT(str, char *, NULL, x == NULL)
814IMPL_OPTIONAL_IMPLICIT(str_const, const char *, NULL, x == NULL)
815
816
869
870UNUSED_ATTR static inline void
871_unknown_optional_type_you_need_to_include_your_custom_optional_h_(void)
872{
873}
884#define OPTIONAL_TYPE_LIST_ADD(type_name, c_type, op_name) \
885 c_type: op_name ## type_name
886
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_
908#endif
909
910#if !APL
911#define SIZE_T_OPTIONAL_LIST_ENTRY(op_name)
912#else // APL
913#define SIZE_T_OPTIONAL_LIST_ENTRY(op_name) \
914 OPTIONAL_TYPE_LIST_ADD(size_t, size_t, op_name),
915#endif // APL
916
917#define OPTIONAL_TYPE_SELECTOR(op_name, expr) \
918 _Generic((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))
940
975#ifndef SOME
976#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
977#define SOME(expr) OPTIONAL_TYPE_SELECTOR(opt_some_, expr)(expr)
978#else // !(__STDC_VERSION__ >= 201112L)
979#define SOME(type_name, expr) opt_some_ ## type_name(expr)
980#endif // !(__STDC_VERSION__ >= 201112L)
981#endif // !defined(SOME)
982
1005#ifndef NONE
1006#define NONE(type_name) opt_none_ ## type_name()
1007#endif
1008
1013#ifndef IS_SOME
1014#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1015#define IS_SOME(opt) \
1016 OPTIONAL_TYPE_SELECTOR(opt_is_some_, (opt).value)(opt)
1017#else // !(__STDC_VERSION__ >= 201112L)
1018#define IS_SOME(type_name, opt) \
1019 opt_is_some_ ## type_name(opt)
1020#endif // !(__STDC_VERSION__ >= 201112L)
1021#endif
1022
1027#ifndef IS_NONE
1028#define IS_NONE(x) (!IS_SOME(x))
1029#endif
1030
1065#ifndef MATCH
1066#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1067#define MATCH(opt, out_value) \
1068 OPTIONAL_TYPE_SELECTOR(opt_match_, (opt).value)((opt), (out_value))
1069#else // !(__STDC_VERSION__ >= 201112L)
1070#define MATCH(type_name, opt, out_value) \
1071 opt_match_ ## type_name((opt), (out_value))
1072#endif // !(__STDC_VERSION__ >= 201112L)
1073#endif // !defined(MATCH)
1074
1107#ifndef MATCH_AS_REF
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))
1112#else // !(__STDC_VERSION__ >= 201112L)
1113#define MATCH_AS_REF(type_name, opt, out_value_p) \
1114 opt_match_as_ref_ ## type_name((opt), (out_value_p))
1115#endif // !(__STDC_VERSION__ >= 201112L)
1116#endif // !defined(MATCH_AS_REF)
1117
1144#ifndef MATCH_AS_MUT
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))
1149#else // !(__STDC_VERSION__ >= 201112L)
1150#define MATCH_AS_MUT(type_name, opt, out_value_p) \
1151 opt_match_as_mut_ ## type_name((opt), (out_value_p))
1152#endif // !(__STDC_VERSION__ >= 201112L)
1153#endif // !defined(MATCH_AS_MUT)
1154
1170#ifndef UNWRAP
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)
1175#else // !(__STDC_VERSION__ >= 201112L)
1176#define UNWRAP(type_name, opt) \
1177 opt_unwrap_ ## type_name((opt), log_basename(__FILE__), __LINE__, #opt)
1178#endif // !(__STDC_VERSION__ >= 201112L)
1179#endif // !defined(UNWRAP)
1180
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)
1202#else // !(__STDC_VERSION__ >= 201112L)
1203#define UNWRAP_AS_REF(type_name, opt) \
1204 opt_unwrap_as_ref_ ## type_name((opt), \
1205 log_basename(__FILE__), __LINE__, #opt)
1206#endif // !(__STDC_VERSION__ >= 201112L)
1207#endif // !defined(UNWRAP_AS_REF)
1208
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)
1230#else // !(__STDC_VERSION__ >= 201112L)
1231#define UNWRAP_AS_MUT(type_name, opt) \
1232 opt_unwrap_as_mut_ ## type_name((opt), \
1233 log_basename(__FILE__), __LINE__, #opt)
1234#endif // !(__STDC_VERSION__ >= 201112L)
1235#endif // !defined(UNWRAP_AS_MUT)
1236
1257#ifndef UNWRAP_OR
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))
1261#else // !(__STDC_VERSION__ >= 201112L)
1262#define UNWRAP_OR(type_name, opt, dfl_value) \
1263 opt_unwrap_or_ ## type_name((opt), (dfl_value))
1264#endif // !(__STDC_VERSION__ >= 201112L)
1265#endif // !defined(UNWRAP_OR)
1266
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))
1301#else // !(__STDC_VERSION__ >= 201112L)
1302#define UNWRAP_OR_ELSE(type_name, opt, dfl_func, dfl_arg) \
1303 opt_unwrap_or_else_ ## type_name((opt), (dfl_func), (dfl_arg))
1304#endif // !(__STDC_VERSION__ >= 201112L)
1305#endif // !defined(UNWRAP_OR)
1306
1333#ifndef UNWRAP_OR_RET
1334#define UNWRAP_OR_RET(opt, ...) \
1335 ({ __typeof(opt) __tmp = (opt); \
1336 if (IS_NONE(__tmp)) { return __VA_ARGS__; } \
1337 UNWRAP(__tmp); })
1338#endif // !defined(UNWRAP_OR_RET)
1339
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); })
1367#endif // !defined(UNWRAP_OR_GOTO)
1368
1386#ifndef UNWRAP_OR_BREAK
1387#define UNWRAP_OR_BREAK(opt) \
1388 ({ __typeof(opt) __tmp = (opt); \
1389 if (IS_NONE(__tmp)) { break; } UNWRAP(__tmp); })
1390#endif // !defined(UNWRAP_OR_BREAK)
1391
1409#ifndef UNWRAP_OR_CONTINUE
1410#define UNWRAP_OR_CONTINUE(opt) \
1411 ({ __typeof(opt) __tmp = (opt); \
1412 if (IS_NONE(__tmp)) { continue; } UNWRAP(__tmp); })
1413#endif // !defined(UNWRAP_OR_CONTINUE)
1414
1437#ifndef OPT_OR
1438#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1439#define OPT_OR(a, b) \
1440 OPTIONAL_TYPE_SELECTOR(opt_or_, (a).value)((a), (b))
1441#else // !(__STDC_VERSION__ >= 201112L)
1442#define OPT_OR(type_name, a, b) \
1443 opt_or_ ## type_name((a), (b))
1444#endif // !(__STDC_VERSION__ >= 201112L)
1445#endif // !defined(OPT_OR)
1446
1473#ifndef OPT_OR_ELSE
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))
1477#else // !(__STDC_VERSION__ >= 201112L)
1478#define OPT_OR_ELSE(type_name, a, func_b, arg_b) \
1479 opt_or_ ## type_name((a), (func_b), (arg_b))
1480#endif // !(__STDC_VERSION__ >= 201112L)
1481#endif // !defined(OPT_OR)
1482
1516#ifndef IF_LET
1517#define IF_LET(vartype, varname, opt) \
1518 { \
1519 vartype __if_let_tmp_##varname; \
1520 /* \
1521 * The void pointer cast here gets rid of a C language quirk \
1522 * where const and non-const pointers aren't technically \
1523 * compatible for referencing. Thus to avoid having to force \
1524 * the caller to use a mutable reference when all they want \
1525 * is an immutable reference, we perform type erasure here. \
1526 */ \
1527 if (MATCH((opt), (void *)&__if_let_tmp_##varname) == \
1528 OPT_SOME) { \
1529 vartype varname = __if_let_tmp_##varname;
1545#define IF_LET_AS_REF(vartype, varname, opt) \
1546 { \
1547 vartype __if_let_tmp_##varname; \
1548 if (MATCH_AS_REF((opt), (void *)&__if_let_tmp_##varname) == \
1549 OPT_SOME) { \
1550 vartype varname = __if_let_tmp_##varname;
1551#define IF_LET_ELSE } else {
1552#define IF_LET_END }}
1553#endif // !defined(IF_LET)
1554
1582#ifndef OPT_INTO
1583#if __STDC_VERSION__ >= 201112L || defined(__DOXYGEN__)
1584#define OPT_INTO(value) OPTIONAL_TYPE_SELECTOR(opt_into_, (value))(value)
1585#else // !(__STDC_VERSION__ >= 201112L)
1586#define OPT_INTO(type_name, opt) opt_into_ ## type_name(value)
1587#endif // !(__STDC_VERSION__ >= 201112L)
1588#endif // !defined(OPT_INTO)
1589
1590#ifdef __cplusplus
1591}
1592#endif
1593
1594#endif /* _ACF_UTILS_OPTIONAL_H_ */
#define UNUSED_ATTR
Definition core.h:95
#define NULL_VECT3L
Definition geom.h:218
#define NULL_VECT3
Definition geom.h:216
#define IS_NULL_GEO_POS2(a)
Definition geom.h:241
#define NULL_GEO_POS2_32
Definition geom.h:226
#define NULL_GEO_POS2
Definition geom.h:224
#define IS_NULL_VECT3(a)
Definition geom.h:232
#define NULL_GEO_POS3_32
Definition geom.h:222
#define IS_NULL_VECT2(a)
Definition geom.h:230
#define NULL_GEO_POS3
Definition geom.h:220
#define NULL_VECT2
Definition geom.h:214
#define IS_NULL_GEO_POS3(a)
Definition geom.h:244
#define IMPL_OPTIONAL_ALIAS(orig_type_name, alias_type_name, alias_c_type)
Declares a type alias for an existing optional type.
Definition optional.h:651
#define IMPL_OPTIONAL_EXPLICIT(type_name, c_type)
Declares a custom optional type with explicit NONE encoding.
Definition optional.h:310
#define IMPL_OPTIONAL_IMPLICIT(type_name, c_type, none_value, none_check)
Declares a custom optional type with implicit NONE encoding.
Definition optional.h:491
optional_state_t
Definition optional.h:275
@ OPT_SOME
State denoting that the optional contains a valid value.
Definition optional.h:277
@ OPT_NONE
State denoting that the optional contains no valid value.
Definition optional.h:276
Definition geom.h:89