-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoption.h
120 lines (100 loc) · 2.87 KB
/
option.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// SPDX-License-Identifier: MIT
// https://github.com/m-kru/c-option
// Copyright (c) 2023 Michał Kruszewski
#ifndef _OPTION_H_
#define _OPTION_H_
#include <stdbool.h>
// none macro shall be used to assign none value to data of any option type.
#define none {._none = true}
// is_none macro shall be used to check if data of option type is none.
#define is_none(o) (o._none)
#define opt_some_case(type) type: _opt_ ## type
#define opt_some_custom_types
#define opt_some_std_types\
opt_some_case(bool),\
opt_some_case(char),\
opt_some_case(double),\
opt_some_case(float),\
opt_some_case(int8_t),\
opt_some_case(int16_t),\
opt_some_case(int32_t),\
opt_some_case(int64_t),\
opt_some_case(uint8_t),\
opt_some_case(uint16_t),\
opt_some_case(uint32_t),\
opt_some_case(uint64_t)
// some macro shall be used to assign some value to data of any option type.
#define some(x) _Generic((x),\
opt_some_custom_types\
opt_some_std_types\
)(x)
#define opt_get_case(type) opt_ ## type ##_t: _opt_ ## type ## _get
#define opt_get_case_t(type) opt_ ## type: _opt_ ## type ## _get
#define opt_get_std_types\
opt_get_case(bool),\
opt_get_case(char),\
opt_get_case(double),\
opt_get_case(float),\
opt_get_case_t(int8_t),\
opt_get_case_t(int16_t),\
opt_get_case_t(int32_t),\
opt_get_case_t(int64_t),\
opt_get_case_t(uint8_t),\
opt_get_case_t(uint16_t),\
opt_get_case_t(uint32_t),\
opt_get_case_t(uint64_t)
#define opt_get_custom_types
// opt_get shall be used to get option internal value.
// It returns true if option is some, and false if value is none.
// A compiler issues an warning if return value from opt_get is not used.
#define opt_get(o, ptr) _Generic((o),\
opt_get_custom_types\
opt_get_std_types\
)(o, ptr)
#define opt_new_type(type)\
typedef struct {bool _none; type _x;} opt_ ## type ## _t;\
\
static inline __attribute__((always_inline))\
opt_ ## type ## _t _opt_ ## type (type x) { \
opt_ ## type ## _t o = {._none = false, ._x = x}; \
return o; \
}\
\
__attribute__((warn_unused_result))\
static inline __attribute__((always_inline))\
bool _opt_ ## type ## _get(opt_ ## type ## _t o, type *i) {\
if (o._none)\
return false;\
*i = o._x;\
return true;\
}
#define opt_new_type_t(type)\
typedef struct {bool _none; type _x;} opt_ ## type;\
\
static inline __attribute__((always_inline))\
opt_ ## type _opt_ ## type (type x) { \
opt_ ## type o = {._none = false, ._x = x}; \
return o; \
}\
\
__attribute__((warn_unused_result))\
static inline __attribute__((always_inline))\
bool _opt_ ## type ## _get(opt_ ## type o, type *i) {\
if (o._none)\
return false;\
*i = o._x;\
return true;\
}
opt_new_type(bool)
opt_new_type(char)
opt_new_type(double)
opt_new_type(float)
opt_new_type_t(int8_t)
opt_new_type_t(int16_t)
opt_new_type_t(int32_t)
opt_new_type_t(int64_t)
opt_new_type_t(uint8_t)
opt_new_type_t(uint16_t)
opt_new_type_t(uint32_t)
opt_new_type_t(uint64_t)
#endif // _OPTION_H_