WG14 result
Loading...
Searching...
No Matches
status_code.h
Go to the documentation of this file.
1/* Proposed WG14 Result
2(C) 2024 - 2026 Niall Douglas <http://www.nedproductions.biz/>
3File Created: Oct 2025
4
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License in the accompanying file
9Licence.txt or at
10
11http://www.apache.org/licenses/LICENSE-2.0
12
13Unless required by applicable law or agreed to in writing, software
14distributed under the License is distributed on an "AS IS" BASIS,
15WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16See the License for the specific language governing permissions and
17limitations under the License.
18*/
19
20#ifndef WG14_RESULT_STATUS_CODE_H
21#define WG14_RESULT_STATUS_CODE_H
22
23#include "config.h"
24#include "status_code_domain.h"
25
26#ifdef __cplusplus
27extern "C"
28{
29#endif
30#ifdef _MSC_VER
31#pragma warning(push)
32#pragma warning(disable : 4996) // use strerror_s instead
33#endif
34
37#define STATUS_CODE_WITH_PAYLOAD(name) \
38 struct WG14_RESULT_PREFIX(status_code_with_payload_##name)
39 /* \brief Declare a status code with payload of type `T` named `name`.
40
41 Before you do this there needs to be a `static constexpr` variable declared
42 called `name_domain`, otherwise the code emitted by this macro won't compile.
43 */
44#define STATUS_CODE_WITH_PAYLOAD_DECLARE(T, name) \
45 struct WG14_RESULT_PREFIX(status_code_with_payload_##name) \
46 { \
47 WG14_RESULT_PREFIX(status_code_untyped) base; \
48 T value; \
49 }; \
50 WG14_RESULT_INLINE struct WG14_RESULT_PREFIX( \
51 status_code_with_payload_##name) \
52 WG14_RESULT_PREFIX(status_code_with_payload_##name##_make)(T val) \
53 { \
54 struct WG14_RESULT_PREFIX(status_code_with_payload_##name) \
55 ret = {{&name##_domain}, val}; \
56 return ret; \
57 }
59#define STATUS_CODE_WITH_PAYLOAD_MAKE(name, ...) \
60 WG14_RESULT_PREFIX(status_code_with_payload_##name##_make)(__VA_ARGS__)
61
63 WG14_RESULT_INLINE bool WG14_RESULT_PREFIX(status_code_is_empty)(
64 const WG14_RESULT_PREFIX(status_code_untyped) * r)
65 {
66 return r->domain == WG14_RESULT_NULLPTR;
67 }
68
70 WG14_RESULT_INLINE bool WG14_RESULT_PREFIX(status_code_is_success)(
71 const WG14_RESULT_PREFIX(status_code_untyped) * r)
72 {
73 return (r->domain != WG14_RESULT_NULLPTR) ?
74 !WG14_RESULT_VTABLE_INVOKE_API(r->domain, failure, r) :
75 false;
76 }
77
79 WG14_RESULT_INLINE bool WG14_RESULT_PREFIX(status_code_is_failure)(
80 const WG14_RESULT_PREFIX(status_code_untyped) * r)
81 {
82 return (r->domain != WG14_RESULT_NULLPTR) ?
83 WG14_RESULT_VTABLE_INVOKE_API(r->domain, failure, r) :
84 false;
85 }
86
91 WG14_RESULT_PREFIX(status_code_message)(
92 const WG14_RESULT_PREFIX(status_code_untyped) * r)
93 {
94 if(r->domain != WG14_RESULT_NULLPTR)
95 {
96 struct WG14_RESULT_PREFIX(status_code_domain_vtable_message_args) args;
97 memset(&args, 0, sizeof(args));
98 args.code = r;
99 const int errcode =
100 WG14_RESULT_VTABLE_INVOKE_API(r->domain, message, &args);
101 if(errcode == 0)
102 {
103 return args.ret;
104 }
105 WG14_RESULT_ABORTF("status_code_message failed with %d (%s)", errcode,
106 strerror(errcode));
107 }
108 return WG14_RESULT_PREFIX(status_code_domain_string_ref_from_static_string)(
109 "(empty)");
110 }
111
118 const WG14_RESULT_PREFIX(status_code_untyped) * primary,
119 const WG14_RESULT_PREFIX(status_code_untyped) * secondary)
120 {
121 if(primary->domain != WG14_RESULT_NULLPTR &&
122 secondary->domain != WG14_RESULT_NULLPTR)
123 {
124 return WG14_RESULT_VTABLE_INVOKE_API(primary->domain, equivalent, primary,
125 secondary);
126 }
127 // If we are both empty, we are equivalent
128 if(WG14_RESULT_NULLPTR == primary->domain &&
129 WG14_RESULT_NULLPTR == secondary->domain)
130 {
131 return true; // NOLINT
132 }
133 // Otherwise not equivalent
134 return false;
135 }
136
138 WG14_RESULT_INLINE void WG14_RESULT_PREFIX(status_code_erased_destroy)(
139 WG14_RESULT_PREFIX(status_code_untyped) * r)
140 {
141 if(r->domain != WG14_RESULT_NULLPTR &&
142 r->domain->vptr->erased_destroy != WG14_RESULT_NULLPTR)
143 {
144 struct WG14_RESULT_PREFIX(status_code_domain_vtable_payload_info_args)
145 args;
146 memset(&args, 0, sizeof(args));
147 args.domain = r->domain;
148 WG14_RESULT_VTABLE_INVOKE_API(r->domain, payload_info, &args);
149 WG14_RESULT_VTABLE_INVOKE_API(r->domain, erased_destroy, r, args.ret);
150 r->domain = WG14_RESULT_NULLPTR;
151 }
152 }
153
156 WG14_RESULT_INLINE int WG14_RESULT_PREFIX(status_code_erased_clone)(
157 WG14_RESULT_PREFIX(status_code_untyped) * dest,
158 const WG14_RESULT_PREFIX(status_code_untyped) * src,
159 WG14_RESULT_PREFIX(status_code_domain_payload_info_t) dstinfo)
160 {
161 WG14_RESULT_PREFIX(status_code_erased_destroy)(dest);
162 if(src->domain != WG14_RESULT_NULLPTR)
163 {
164 return WG14_RESULT_VTABLE_INVOKE_API(src->domain, erased_copy, dest, src,
165 dstinfo);
166 }
167 return 0;
168 }
169
170
172#define status_code_is_empty(...) \
173 WG14_RESULT_PREFIX(status_code_is_empty)(&(__VA_ARGS__).base)
175#define status_code_is_success(...) \
176 WG14_RESULT_PREFIX(status_code_is_success)(&(__VA_ARGS__).base)
178#define status_code_is_failure(...) \
179 WG14_RESULT_PREFIX(status_code_is_failure)(&(__VA_ARGS__).base)
183#define status_code_message(...) \
184 WG14_RESULT_PREFIX(status_code_message)(&(__VA_ARGS__).base)
190#define status_code_strictly_equivalent(primary, secondary) \
191 WG14_RESULT_PREFIX(status_code_strictly_equivalent) \
192 (&(primary).base, &(secondary).base)
194#define status_code_destroy(...) \
195 { \
196 typedef WG14_RESULT_TYPEOF_UNQUAL(*(__VA_ARGS__)) \
197 WG14_RESULT_PREFIX(_code_type_); \
198 WG14_RESULT_PREFIX(_code_type_) * WG14_RESULT_PREFIX(_code_ptr_) = \
199 (WG14_RESULT_PREFIX(_code_type_) *) (&(*(__VA_ARGS__))); \
200 if(WG14_RESULT_PREFIX(_code_ptr_)->base.domain != WG14_RESULT_NULLPTR && \
201 WG14_RESULT_PREFIX(_code_ptr_)->base.domain->vptr->erased_destroy != \
202 WG14_RESULT_NULLPTR) \
203 { \
204 typedef WG14_RESULT_TYPEOF(WG14_RESULT_PREFIX(_code_ptr_)->value) \
205 WG14_RESULT_PREFIX(_value_type_); \
206 const WG14_RESULT_PREFIX(status_code_domain_payload_info_t) \
207 WG14_RESULT_PREFIX(_info_) = \
208 STATUS_CODE_DOMAIN_PAYLOAD_INFO_INIT(WG14_RESULT_PREFIX(_value_type_)); \
209 WG14_RESULT_VTABLE_INVOKE_API( \
210 WG14_RESULT_PREFIX(_code_ptr_)->base.domain, erased_destroy, \
211 &WG14_RESULT_PREFIX(_code_ptr_)->base, WG14_RESULT_PREFIX(_info_)); \
212 WG14_RESULT_PREFIX(_code_ptr_)->base.domain = WG14_RESULT_NULLPTR; \
213 } \
214 }
215#if !defined(_MSC_VER) || defined(__clang__)
216#ifdef __GCC__
217#pragma GCC diagnostic push
218#pragma GCC diagnostic ignored "-Wpedantic"
219#endif
221#define status_code_clone(dest, src) \
222 ({ \
223 typedef WG14_RESULT_TYPEOF(*(dest)) WG14_RESULT_PREFIX(_dest_code_type_); \
224 typedef WG14_RESULT_TYPEOF(*(src)) WG14_RESULT_PREFIX(_src_code_type_); \
225 WG14_RESULT_PREFIX(_dest_code_type_) * \
226 WG14_RESULT_PREFIX(_dest_code_ptr_) = \
227 (WG14_RESULT_PREFIX(_dest_code_type_) *) (&(*(dest))); \
228 WG14_RESULT_PREFIX(_src_code_type_) * WG14_RESULT_PREFIX(_src_code_ptr_) = \
229 (WG14_RESULT_PREFIX(_src_code_type_) *) (&(*(src))); \
230 typedef WG14_RESULT_TYPEOF(WG14_RESULT_PREFIX(_dest_code_ptr_)->value) \
231 WG14_RESULT_PREFIX(_dest_value_type_); \
232 status_code_destroy(_dest_code_ptr_); \
233 int WG14_RESULT_PREFIX(ret) = 0; \
234 if(WG14_RESULT_PREFIX(_src_code_ptr_)->base.domain != WG14_RESULT_NULLPTR) \
235 { \
236 const WG14_RESULT_PREFIX(status_code_domain_payload_info_t) \
237 WG14_RESULT_PREFIX(_info_) = STATUS_CODE_DOMAIN_PAYLOAD_INFO_INIT( \
238 WG14_RESULT_PREFIX(_dest_value_type_)); \
239 WG14_RESULT_PREFIX(ret) = WG14_RESULT_VTABLE_INVOKE_API( \
240 WG14_RESULT_PREFIX(_src_code_ptr_)->base.domain, erased_copy, \
241 &WG14_RESULT_PREFIX(_dest_code_ptr_)->base, \
242 &WG14_RESULT_PREFIX(_src_code_ptr_)->base, WG14_RESULT_PREFIX(_info_)); \
243 } \
244 WG14_RESULT_PREFIX(ret); \
245 })
246#ifdef __GCC__
247#pragma GCC diagnostic pop
248#endif
249#endif
250
251#ifdef _MSC_VER
252#pragma warning(pop)
253#endif
254#ifdef __cplusplus
255}
256#endif
257
258#endif
#define WG14_RESULT_NULLPTR
Definition config.h:47
#define WG14_RESULT_INLINE
Definition config.h:63
#define WG14_RESULT_ABORTF(...)
Definition config.h:179
#define status_code_is_empty(...)
True if the status code is empty (convenience macro)
#define status_code_is_failure(...)
True if the status code is a failure (convenience macro)
#define status_code_message(...)
Retrieves the message of the status code (convenience macro). Make sure you call status_code_domain_s...
#define status_code_is_success(...)
True if the status code is a success (convenience macro)
#define status_code_strictly_equivalent(primary, secondary)
True if the status codes are strictly semantically equivalent (convenience macro)....
#define WG14_RESULT_VTABLE_INVOKE_API(domain, name,...)
Type of a payload info of a domain.
Type of a string ref of a domain.
Type of an untyped status code.