WG14 result
Loading...
Searching...
No Matches
status_code_domain.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_DOMAIN_H
21#define WG14_RESULT_STATUS_CODE_DOMAIN_H
22
23#include "config.h"
24
25#include <assert.h>
26#include <errno.h>
27#include <stdbool.h>
28#include <string.h>
29
30#ifdef __cplusplus
31extern "C"
32{
33#if defined(__GNUC__) && !defined(__clang__)
34#pragma GCC diagnostic push
35#pragma GCC diagnostic ignored "-Wclass-memaccess"
36#endif
37#endif
38#ifdef _MSC_VER
39#pragma warning(push)
40#pragma warning(disable : 4996) // use strerror_s instead
41#endif
42
44 typedef unsigned long long
46
48 typedef struct WG14_RESULT_PREFIX(status_code_domain_string_ref_s)
49 WG14_RESULT_PREFIX(status_code_domain_string_ref);
50
58
60 typedef struct WG14_RESULT_PREFIX(status_code_domain_string_ref_thunk_args_s)
61 {
62 WG14_RESULT_PREFIX(status_code_domain_string_ref) * dest;
63 WG14_RESULT_PREFIX(status_code_domain_string_ref) * src;
66
70 const WG14_RESULT_PREFIX(status_code_domain_string_ref_thunk_args) * args);
71
73 struct WG14_RESULT_PREFIX(status_code_domain_string_ref_s)
74 {
75 const char *c_str, *end;
76 void *state[3];
78 };
79
82 WG14_RESULT_PREFIX(status_code_domain_string_ref_is_empty)(
83 const WG14_RESULT_PREFIX(status_code_domain_string_ref) * s)
84 {
85 return s->c_str == WG14_RESULT_NULLPTR;
86 }
87
90 WG14_RESULT_INLINE int WG14_RESULT_PREFIX(status_code_domain_string_ref_copy)(
91 WG14_RESULT_PREFIX(status_code_domain_string_ref) * dest,
92 const WG14_RESULT_PREFIX(status_code_domain_string_ref) * src)
93 {
94 if(src->thunk != WG14_RESULT_NULLPTR)
95 {
96 const WG14_RESULT_PREFIX(status_code_domain_string_ref_thunk_args)
97 args = {dest, (WG14_RESULT_PREFIX(status_code_domain_string_ref) *) src,
99 return src->thunk(&args);
100 }
101 memcpy(dest, src, sizeof(*dest));
102 return 0;
103 }
104
107 WG14_RESULT_PREFIX(status_code_domain_string_ref_move)(
108 WG14_RESULT_PREFIX(status_code_domain_string_ref) * dest,
109 WG14_RESULT_PREFIX(status_code_domain_string_ref) * src)
110 {
111 if(src->thunk != WG14_RESULT_NULLPTR)
112 {
113 const WG14_RESULT_PREFIX(status_code_domain_string_ref_thunk_args)
114 args = {dest, src,
116 const int errcode = src->thunk(&args);
117 if(errcode != 0)
118 {
120 "status_code_domain_string_ref_move failed due to %d (%s)", errcode,
121 strerror(errcode));
122 }
123 return;
124 }
125 memcpy(dest, src, sizeof(*dest));
126 memset(src, 0, sizeof(*src));
127 }
128
131 WG14_RESULT_PREFIX(status_code_domain_string_ref_destroy)(
132 const WG14_RESULT_PREFIX(status_code_domain_string_ref) * _src)
133 {
134 WG14_RESULT_PREFIX(status_code_domain_string_ref) *src =
135 (WG14_RESULT_PREFIX(status_code_domain_string_ref) *) _src;
136 if(src->thunk != WG14_RESULT_NULLPTR)
137 {
138 const WG14_RESULT_PREFIX(status_code_domain_string_ref_thunk_args)
139 args = {
142 const int errcode = src->thunk(&args);
143 if(errcode != 0)
144 {
146 "status_code_domain_string_ref_destroy failed due to %d (%s)", errcode,
147 strerror(errcode));
148 }
149 return;
150 }
151 memset(src, 0, sizeof(*src));
152 }
153
157 WG14_RESULT_PREFIX(status_code_domain_string_ref_from_static_string_slice)(
158 const char *s, size_t len)
159 {
160 assert(s[len] == 0);
161 const WG14_RESULT_PREFIX(status_code_domain_string_ref)
162 ret = {s,
163 s + len,
166 return ret;
167 }
168
171 WG14_RESULT_PREFIX(status_code_domain_string_ref_from_static_string)(
172 const char *s)
173 {
174 return WG14_RESULT_PREFIX(
175 status_code_domain_string_ref_from_static_string_slice)(s, strlen(s));
176 }
177
184 WG14_RESULT_PREFIX(
186 size_t len);
187
191 WG14_RESULT_PREFIX(
192 status_code_domain_string_ref_atomic_refcounted_from_string)(const char *s)
193 {
194 return WG14_RESULT_PREFIX(
196 }
197
198
199 /**************************************************************************/
200
201
204 typedef const struct WG14_RESULT_PREFIX(status_code_domain_s)
205 WG14_RESULT_PREFIX(status_code_domain);
206
208 typedef struct WG14_RESULT_PREFIX(status_code_domain_payload_info)
209 {
211 size_t
215
216#define STATUS_CODE_DOMAIN_PAYLOAD_INFO_INIT_INNARDS(T) \
217 sizeof(T), sizeof(WG14_RESULT_PREFIX(status_code_domain) *) + sizeof(T), \
218 (__alignof(T) > __alignof(WG14_RESULT_PREFIX(status_code_domain) *)) ? \
219 __alignof(T) : \
220 __alignof(WG14_RESULT_PREFIX(status_code_domain) *)
221
224#define STATUS_CODE_DOMAIN_PAYLOAD_INFO_INIT(T) \
225 {STATUS_CODE_DOMAIN_PAYLOAD_INFO_INIT_INNARDS(T)}
226
229 WG14_RESULT_PREFIX(status_code_domain_payload_info_make)(
230 size_t payload_size, size_t total_size, size_t total_alignment)
231 {
232 const WG14_RESULT_PREFIX(status_code_domain_payload_info_t)
233 ret = {payload_size, total_size, total_alignment};
234 return ret;
235 }
237#define STATUS_CODE_DOMAIN_PAYLOAD_INFO_MAKE(T) \
238 WG14_RESULT_PREFIX(status_code_domain_payload_info_make) \
239 (STATUS_CODE_DOMAIN_PAYLOAD_INFO_INIT_INNARDS(T))
240
242 typedef struct WG14_RESULT_PREFIX(status_code_untyped)
243 {
244 WG14_RESULT_PREFIX(status_code_domain) * domain;
245 } WG14_RESULT_PREFIX(status_code_untyped);
246
248 typedef struct WG14_RESULT_PREFIX(status_code_generic_s)
249 WG14_RESULT_PREFIX(status_code_generic);
250
251 /* We have to do a bit of work to achieve C++ vtable calling convention
252 (__thiscall) compatibility which won't always be possible on all platforms,
253 but for those where it is then the C++ implementation can mark domains `final`
254 and get the benefits of linker implemented devirtualisation.
255
256 As a quick refresher as I'll likely forget all this in years to come, and
257 **remembering that complex return types take the first parameter register to
258 point to where in the stack the return type should be stored**:
259
260 - x86 Microsoft:
261 - cdecl right-to-left order, caller cleanup, always uses stack
262 - stdcall right-to-left order, **callee** cleanup, always uses stack
263 - thiscall right-to-left order, **callee** cleanup, always uses stack (BUT
264 ECX is `this` and effectively gets dropped for stdcall code)
265 - x86 System V:
266 - cdecl right-to-left order, caller cleanup, always uses stack
267 - thiscall right-to-left order, caller cleanup, always uses stack
268 - x64 Microsoft:
269 - cdecl right-to-left order, caller cleanup, starts from RCX
270 - thiscall right-to-left order, caller cleanup, starts from RDX (RCX is
271 specially treated as always `this`, so complex return type stack address
272 would go into RDX, then RCX and RDX are swapped compared to cdecl)
273 - x64 System V:
274 - cdecl right-to-left order, caller cleanup, starts from RDI
275 - thiscall right-to-left order, caller cleanup, starts from RDI
276
277 As far as I can tell, no major modern compiler other than MSVC does weird
278 things with `this`, so for everybody else we can safely assume `this` will be
279 the first argument. If we avoid complex return types, we eliminate a great
280 deal of complexity so we do exactly that.
281 */
283#ifndef WG14_RESULT_VTABLE_API
284#define WG14_RESULT_VTABLE_API_GLUE2(x, y) x##y
285#define WG14_RESULT_VTABLE_API_GLUE(x, y) WG14_RESULT_VTABLE_API_GLUE2(x, y)
286#define WG14_RESULT_VTABLE_API_UNIQUE_NAME \
287 WG14_RESULT_VTABLE_API_GLUE(_wg14_result_vtable_api_unique_name_temporary, \
288 __COUNTER__)
289
290#ifdef _MSC_VER
291#ifdef _M_IX86
292 // Use __stdcall to implement callee cleanup. `this` gets dropped.
293#define WG14_RESULT_VTABLE_API(name, ...) __stdcall name(__VA_ARGS__)
294#define WG14_RESULT_VTABLE_DECL(name, ...) (__stdcall name)(__VA_ARGS__)
295 /* There is almost certainly a more efficient way of doing this, but I'm not
296 sure how much I care for x86 MSVC which not a lot of people use nowadays.
297
298 TODO FIXME: This should use stack instead of TLS
299 */
300 static
301 __declspec(thread) struct WG14_RESULT_PREFIX(win32_invoke_with_this_storage_s)
302 {
303 void *ebp;
304 void *esp;
305 void *oldstack[3];
306 } WG14_RESULT_PREFIX(win32_invoke_with_this_storage);
307 inline int __declspec(naked) WG14_RESULT_PREFIX(win32_invoke_with_this)(
308 struct WG14_RESULT_PREFIX(win32_invoke_with_this_storage_s) * tls, void *func,
309 WG14_RESULT_PREFIX(status_code_domain) * domain, ...)
310 {
311 (void) tls;
312 (void) func;
313 (void) domain;
314 __asm {
315 // save ebp into TLS
316 mov eax, [esp + 4]
317 mov [eax + 0], ebp
318 mov ebp, eax
319 // ebp now points at the TLS. Save the original stack pointer
320 mov [ebp + 4], esp
321 // Save the twelve bytes of stack we are about to clobber
322 mov eax, [esp + 0] // return address
323 mov [ebp + 8], eax
324 mov eax, [esp + 8] // function to call
325 mov [ebp + 12], eax
326 mov eax, [esp + 12] // this value
327 mov [ebp + 16], eax
328 // pop return address + tls
329 add esp, 8
330 pop eax // function to call
331 pop ecx // this value as per MSVC __thiscall calling convention
332 call eax // jump to function
333 // WARNING: You cannot touch eax nor ecx from now on!
334
335 // ebp will point to tls
336 // Because __thiscall does callee cleanup, esp will now be wrong because
337 // this function is always __cdecl due to the varargs. So fix that first.
338 mov esp, [ebp + 4]
339 add esp, 16
340 // Restore the clobbered stack
341 push [ebp + 16] // this value
342 push [ebp + 12] // function to call
343 push ebp // tls
344 push [ebp + 8] // return address
345 // restore ebp
346 mov ebp, [ebp + 0]
347 // return to caller
348 ret
349 }
350 }
351 inline bool __declspec(naked) WG14_RESULT_PREFIX(win32_invoke_with_this_bool)(
352 struct WG14_RESULT_PREFIX(win32_invoke_with_this_storage_s) * tls, void *func,
353 WG14_RESULT_PREFIX(status_code_domain) * domain, ...)
354 {
355 (void) tls;
356 (void) func;
357 (void) domain;
358 __asm {
359 // save ebp into TLS
360 mov eax, [esp + 4]
361 mov [eax + 0], ebp
362 mov ebp, eax
363 // ebp now points at the TLS. Save the original stack pointer
364 mov [ebp + 4], esp
365 // Save the twelve bytes of stack we are about to clobber
366 mov eax, [esp + 0] // return address
367 mov [ebp + 8], eax
368 mov eax, [esp + 8] // function to call
369 mov [ebp + 12], eax
370 mov eax, [esp + 12] // this value
371 mov [ebp + 16], eax
372 // pop return address + tls
373 add esp, 8
374 pop eax // function to call
375 pop ecx // this value as per MSVC __thiscall calling convention
376 call eax // jump to function
377 // WARNING: You cannot touch eax nor ecx from now on!
378
379 // ebp will point to tls
380 // Because __thiscall does callee cleanup, esp will now be wrong because
381 // this function is always __cdecl due to the varargs. So fix that first.
382 mov esp, [ebp + 4]
383 add esp, 16
384 // Restore the clobbered stack
385 push [ebp + 16] // this value
386 push [ebp + 12] // function to call
387 push ebp // tls
388 push [ebp + 8] // return address
389 // restore ebp
390 mov ebp, [ebp + 0]
391 // return to caller
392 ret
393 }
394 }
395// We also need to work around a bug in MSVC's handling of bool ...
396#ifdef __cplusplus
397}
398template <class T> struct WG14_RESULT_PREFIX(win32_invoke_with_this_impl)
399{
400 static constexpr auto value = WG14_RESULT_PREFIX(win32_invoke_with_this);
401};
402template <> struct WG14_RESULT_PREFIX(win32_invoke_with_this_impl)<bool>
403{
404 static constexpr auto value = WG14_RESULT_PREFIX(win32_invoke_with_this_bool);
405};
406extern "C"
407{
408#define WG14_RESULT_VTABLE_INVOKE_API(domain, name, ...) \
409 WG14_RESULT_PREFIX( \
410 win32_invoke_with_this_impl<decltype((domain)->vptr->name( \
411 __VA_ARGS__))>)::value(&WG14_RESULT_PREFIX(win32_invoke_with_this_storage), \
412 (void *) (domain)->vptr->name, (domain), __VA_ARGS__)
413#else
414#define WG14_RESULT_VTABLE_INVOKE_API(domain, name, ...) \
415 (_Generic((domain)->vptr->name(__VA_ARGS__), \
416 bool: WG14_RESULT_PREFIX(win32_invoke_with_this_bool)( \
417 &WG14_RESULT_PREFIX(win32_invoke_with_this_storage), \
418 (void *) (domain)->vptr->name, (domain), __VA_ARGS__), \
419 default: WG14_RESULT_PREFIX(win32_invoke_with_this)( \
420 &WG14_RESULT_PREFIX(win32_invoke_with_this_storage), \
421 (void *) (domain)->vptr->name, (domain), __VA_ARGS__)))
422#endif
423#else
424#define WG14_RESULT_VTABLE_API(name, ...) \
425 name(__pragma(warning(suppress : 4100)) \
426 const void *WG14_RESULT_VTABLE_API_UNIQUE_NAME /*discard this*/, \
427 __VA_ARGS__)
428#define WG14_RESULT_VTABLE_DECL(name, ...) \
429 (name)(__pragma(warning(suppress : 4100)) \
430 const void *WG14_RESULT_VTABLE_API_UNIQUE_NAME /*discard this*/, \
431 __VA_ARGS__)
432#define WG14_RESULT_VTABLE_INVOKE_API(domain, name, ...) \
433 (domain)->vptr->name((domain), __VA_ARGS__)
434#endif
435#else
436// No special markup nor handling
437#define WG14_RESULT_VTABLE_API(name, ...) \
438 name(__attribute__((unused)) \
439 const void *WG14_RESULT_VTABLE_API_UNIQUE_NAME /*discard this*/, \
440 __VA_ARGS__)
441#define WG14_RESULT_VTABLE_DECL(name, ...) \
442 (name)(__attribute__((unused)) \
443 const void *WG14_RESULT_VTABLE_API_UNIQUE_NAME /*discard this*/, \
444 __VA_ARGS__)
445#define WG14_RESULT_VTABLE_INVOKE_API(domain, name, ...) \
446 (domain)->vptr->name((domain), __VA_ARGS__)
447#endif
448#endif
449
451 struct WG14_RESULT_PREFIX(status_code_domain_vtable_name_args)
452 {
454 WG14_RESULT_PREFIX(status_code_domain) * domain;
455 };
456
458 struct WG14_RESULT_PREFIX(status_code_domain_vtable_payload_info_args)
459 {
461 WG14_RESULT_PREFIX(status_code_domain) * domain;
462 };
463
464 struct WG14_RESULT_PREFIX(status_code_domain_vtable_generic_code_args);
465
467 struct WG14_RESULT_PREFIX(status_code_domain_vtable_message_args)
468 {
470 const WG14_RESULT_PREFIX(status_code_untyped) * code;
471 };
472
475 typedef const struct WG14_RESULT_PREFIX(status_code_domain_vtable_s)
476 {
478 int WG14_RESULT_VTABLE_DECL(*const name,
479 struct WG14_RESULT_PREFIX(
481 args);
483 void WG14_RESULT_VTABLE_DECL(*const payload_info,
484 struct WG14_RESULT_PREFIX(
486 args);
488 bool WG14_RESULT_VTABLE_DECL(*const failure,
489 const WG14_RESULT_PREFIX(status_code_untyped) *
490 code);
493 bool WG14_RESULT_VTABLE_DECL(*const equivalent,
494 const WG14_RESULT_PREFIX(status_code_untyped) *
495 code1,
496 const WG14_RESULT_PREFIX(status_code_untyped) *
497 code2);
499 void WG14_RESULT_VTABLE_DECL(*const generic_code,
500 struct WG14_RESULT_PREFIX(
502 args);
505 int WG14_RESULT_VTABLE_DECL(*const message,
506 struct WG14_RESULT_PREFIX(
508 args);
511 void WG14_RESULT_VTABLE_DECL(*const reserved_slot_for_cxx_throw_exception,
512 const WG14_RESULT_PREFIX(status_code_untyped) *
513 code);
519 *const erased_copy, WG14_RESULT_PREFIX(status_code_untyped) * dst,
520 const WG14_RESULT_PREFIX(status_code_untyped) * src,
521 WG14_RESULT_PREFIX(status_code_domain_payload_info_t) dstinfo);
524 void WG14_RESULT_VTABLE_DECL(*const erased_destroy,
525 WG14_RESULT_PREFIX(status_code_untyped) * code,
526 WG14_RESULT_PREFIX(
528 } WG14_RESULT_PREFIX(status_code_domain_vtable);
529
532 struct WG14_RESULT_PREFIX(status_code_domain_s)
533 {
535 WG14_RESULT_PREFIX(status_code_domain_vtable) *const vptr;
537 const WG14_RESULT_PREFIX(status_code_domain_unique_id_type) id;
538 };
539
543 WG14_RESULT_VTABLE_API(WG14_RESULT_PREFIX(default_erased_copy_impl),
544 WG14_RESULT_PREFIX(status_code_untyped) * dst,
545 const WG14_RESULT_PREFIX(status_code_untyped) * src,
546 WG14_RESULT_PREFIX(status_code_domain_payload_info_t)
547 dstinfo)
548 {
549 // Note that dst may not have its domain set
550 struct WG14_RESULT_PREFIX(status_code_domain_vtable_payload_info_args) args;
551 memset(&args, 0, sizeof(args));
552 args.domain = src->domain;
553 WG14_RESULT_VTABLE_INVOKE_API(src->domain, payload_info, &args);
554 if(dstinfo.total_size < args.ret.total_size)
555 {
556 return ENOBUFS;
557 }
558 const size_t tocopy = (dstinfo.total_size > args.ret.total_size) ?
559 args.ret.total_size :
560 dstinfo.total_size;
561 memcpy(dst, src, tocopy);
562 return 0;
563 }
564
568 WG14_RESULT_VTABLE_API(WG14_RESULT_PREFIX(default_erased_destroy_impl),
569 WG14_RESULT_PREFIX(status_code_untyped) * code,
570 WG14_RESULT_PREFIX(status_code_domain_payload_info_t)
571 info)
572 {
573 (void) code;
574 (void) info;
575 }
576
577
580 WG14_RESULT_PREFIX(status_code_domain_unique_id_from_uuid)(const char *uuid);
581
582 // Alas the trick of (msg, 1 / 0) doesn't work in C23 constexpr :(
583#ifdef __cplusplus
584#define STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_ABORT(msg) (msg, 1 / 0)
585#else
586#define STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_ABORT(msg) (0)
587#endif
588
589#define STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(c) \
590 (('0' <= (c) && (c) <= '9') ? (unsigned long long) ((c) - '0') : \
591 ('a' <= (c) && (c) <= 'f') ? (unsigned long long) (10 + (c) - 'a') : \
592 ('A' <= (c) && (c) <= 'F') ? (unsigned long long) (10 + (c) - 'A') : \
593 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_ABORT( \
594 "Invalid character in UUID"))
595
598#define STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID(uuid) \
599 (((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[0]) ^ \
600 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[19])) \
601 << 0) | \
602 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[1]) ^ \
603 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[20])) \
604 << 4) | \
605 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[2]) ^ \
606 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[21])) \
607 << 8) | \
608 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[3]) ^ \
609 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[22])) \
610 << 12) | \
611 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[4]) ^ \
612 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[24])) \
613 << 16) | \
614 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[5]) ^ \
615 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[25])) \
616 << 20) | \
617 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[6]) ^ \
618 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[26])) \
619 << 24) | \
620 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[7]) ^ \
621 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[27])) \
622 << 28) | \
623 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[9]) ^ \
624 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[28])) \
625 << 32) | \
626 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[10]) ^ \
627 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[29])) \
628 << 36) | \
629 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[11]) ^ \
630 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[30])) \
631 << 40) | \
632 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[12]) ^ \
633 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[31])) \
634 << 44) | \
635 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[14]) ^ \
636 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[32])) \
637 << 48) | \
638 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[15]) ^ \
639 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[33])) \
640 << 52) | \
641 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[16]) ^ \
642 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[34])) \
643 << 56) | \
644 ((STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[17]) ^ \
645 STATUS_CODE_DOMAIN_UNIQUE_ID_FROM_UUID_PARSE_HEX_BYTE(uuid[35])) \
646 << 60))
647
648
653 WG14_RESULT_PREFIX(status_code_domain_name)(
654 WG14_RESULT_PREFIX(status_code_domain) * domain)
655 {
656 struct WG14_RESULT_PREFIX(status_code_domain_vtable_name_args) args;
657 memset(&args, 0, sizeof(args));
658 args.domain = domain;
659 const int errcode = WG14_RESULT_VTABLE_INVOKE_API(domain, name, &args);
660 if(errcode == 0)
661 {
662 return args.ret;
663 }
664 WG14_RESULT_ABORTF("status_code_domain_name failed with %d (%s)", errcode,
665 strerror(errcode));
666 }
667
671 WG14_RESULT_PREFIX(status_code_domain_payload_info)(
672 WG14_RESULT_PREFIX(status_code_domain) * domain)
673 {
674 struct WG14_RESULT_PREFIX(status_code_domain_vtable_payload_info_args) args;
675 memset(&args, 0, sizeof(args));
676 args.domain = domain;
677 WG14_RESULT_VTABLE_INVOKE_API(domain, payload_info, &args);
678 return args.ret;
679 }
680
681
682#ifdef _MSC_VER
683#pragma warning(pop)
684#endif
685#ifdef __cplusplus
686#if defined(__GNUC__) && !defined(__clang__)
687#pragma GCC diagnostic pop
688#endif
689}
690#endif
691
692#if WG14_RESULT_ENABLE_HEADER_ONLY
693#include "../../src/wg14_result/status_code_domain.c"
694#endif
695
696#endif
#define WG14_RESULT_NULLPTR
Definition config.h:47
#define WG14_RESULT_INLINE
Definition config.h:63
#define WG14_RESULT_EXTERN
Definition config.h:113
#define WG14_RESULT_ABORTF(...)
Definition config.h:179
status_code_domain_unique_id_type status_code_domain_unique_id_from_uuid(const char *uuid)
Parse a uuid input string to yield a status code domain unique id.
status_code_domain_string_ref status_code_domain_string_ref_atomic_refcounted_from_buffer(const char *s, size_t len)
Make an atomic refcounted string ref which tracks living copies using an atomic reference count,...
#define WG14_RESULT_VTABLE_API(name,...)
#define WG14_RESULT_VTABLE_INVOKE_API(domain, name,...)
unsigned long long status_code_domain_unique_id_type
Type of a unique id of a domain.
int(* status_code_domain_string_ref_thunk_spec)(const status_code_domain_string_ref_thunk_args *args)
Type of a string ref thunk function. Returns an errno value. Copies can fail. Nothing else can.
status_code_domain_string_ref_thunk_op
Type of a string ref thunk op.
@ status_code_domain_string_ref_thunk_op_move
@ status_code_domain_string_ref_thunk_op_copy
@ status_code_domain_string_ref_thunk_op_destruct
#define WG14_RESULT_VTABLE_DECL(name,...)
Type of a payload info of a domain.
size_t total_size
The total status code size in bytes (includes domain pointer and mixins state)
size_t payload_size
The payload size in bytes.
size_t total_alignment
The total status code alignment in bytes.
The functions defined by a status code domain, kept ABI compatible with a C++ vtable.
status_code_domain_vtable *const vptr
C++ ABI compatible vptr.
const status_code_domain_unique_id_type id
The unique id used to identify identical category instances.
Type of a string ref of a domain.
status_code_domain_string_ref_thunk_spec thunk
Type of the arguments to a string ref thunk function.
enum status_code_domain_string_ref_thunk_op op
The arguments for status_code_domain_vtable.generic_code
The arguments for status_code_domain_vtable.message
The arguments for status_code_domain_vtable.name
status_code_domain_string_ref ret
The arguments for status_code_domain_vtable.payload_info
status_code_domain_payload_info_t ret
The functions defined by a status code domain, kept ABI compatible with a C++ vtable.
A generic status code.
Type of an untyped status code.
status_code_domain * domain