forked from ned14/outcome
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'ned14:develop' into zig-pkg
- Loading branch information
Showing
50 changed files
with
3,013 additions
and
993 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Copyright René Ferdinand Rivera Morell 2023-2024 | ||
# Distributed under the Boost Software License, Version 1.0. | ||
# (See accompanying file LICENSE_1_0.txt or copy at | ||
# http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
require-b2 5.2 ; | ||
|
||
constant boost_dependencies : | ||
/boost/assert//boost_assert | ||
/boost/config//boost_config | ||
/boost/exception//boost_exception | ||
/boost/system//boost_system | ||
/boost/throw_exception//boost_throw_exception ; | ||
|
||
project /boost/outcome | ||
: common-requirements | ||
<include>include | ||
; | ||
|
||
explicit | ||
[ alias boost_outcome : : : : <library>$(boost_dependencies) ] | ||
[ alias all : boost_outcome test ] | ||
; | ||
|
||
call-if : boost-library outcome | ||
; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
+++ | ||
title = "C Results" | ||
description = "Outcome's C Result support" | ||
weight = 30 | ||
+++ | ||
|
||
The C macro API header `<outcome/experimental/result.h>` has some macros for working with any kind of Result: | ||
|
||
<dl> | ||
<dt><code>CXX_DECLARE_RESULT(ident, T, E)</code> | ||
<dd>Declares to C a <code>basic_result<T, E></code> type uniquely | ||
identified by <code>ident</code>. <code>T</code> is available at the | ||
member variable <code>.value</code>, and <code>E</code> is available | ||
at the member variable <code>.error</code>. If you call this from within | ||
C++, make SURE it is not within a <code>extern "C"</code> block! | ||
|
||
<dt><code>CXX_RESULT(ident)</code> | ||
<dd>A reference to a previously declared <code>result</code> type with | ||
unique <code>ident</code>. | ||
|
||
<dt><code>CXX_RESULT_HAS_VALUE(r)</code> | ||
<dd>Evaluates to 1 (true) if the input <code>result</code> has a value. | ||
|
||
<dt><code>CXX_RESULT_HAS_ERROR(r)</code> | ||
<dd>Evaluates to 1 (true) if the input <code>result</code> has an error. | ||
|
||
<dt><code>CXX_RESULT_ERROR_IS_ERRNO(r)</code> | ||
<dd>Evaluates to 1 (true) if the input <code>result</code>'s error value | ||
is a code in the POSIX <code>errno</code> domain. | ||
</dl> | ||
|
||
The above let you work, somewhat awkwardly, with any C-compatible | ||
`basic_result<T, E>`. `basic_result<T, E>` is trivially copyable and | ||
standard layout if its `T` and `E` are both so, and it has the C layout: | ||
|
||
```c++ | ||
struct cxx_result_##ident | ||
{ | ||
union | ||
{ | ||
T value; | ||
E error; | ||
}; | ||
unsigned flags; | ||
}; | ||
``` | ||
|
||
Note that this layout is different to that of [`CXX_DECLARE_STATUS_CODE`]({{% relref "../from-c" %}}) | ||
as the C++ `result` has a different layout if `E` is a status code. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
+++ | ||
title = "Declare a Result" | ||
description = "Declaring a C Result" | ||
weight = 20 | ||
+++ | ||
|
||
{{% snippet "c_api2.cpp" "preamble" %}} | ||
|
||
The key to making C programming easy is to alias the long complex things | ||
into short easy thing. Obviously `SUCCESS(expr)` and `FAILURE(expr)` is too | ||
generic, but for the purposes of this documentation it makes thing easier. |
101 changes: 101 additions & 0 deletions
101
doc/src/content/experimental/c-api/from-c/system_code.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
+++ | ||
title = "C system error results" | ||
description = "Status code's `std::error` in C" | ||
weight = 10 | ||
+++ | ||
|
||
In v2.2.11, C Result support went from second tier to first tier status, and | ||
now you can create, query and manipulate a subset of Result types entirely from | ||
within C by including `<outcome/experimental/result.h>`. | ||
|
||
The subset supported are those `result<T, E>` which are [a `status_result<T>`]({{% relref "../../status_result" %}}) | ||
i.e. the `E` is hardcoded to `experimental::error` which is the type erased runtime | ||
polymorphic holder for any errored `status_code` whose payload is not bigger | ||
than an `intptr_t`. This is the most useful subset of Outcome Experimental's | ||
possible Result types, allowing arbitrary custom error coding schemes from | ||
any unknown source to work seamlessly with all others, including errors from | ||
the system or third party libraries. | ||
|
||
The operations available to C are: | ||
|
||
<dl> | ||
<dt><code>CXX_DECLARE_RESULT_SYSTEM(ident, T)</code> | ||
<dd>Declares to C a <code>status_result<T></code> type uniquely | ||
identified by <code>ident</code>. <code>T</code> is available at the | ||
member variable <code>.value</code>, and <code>struct cxx_status_code_system</code> | ||
is available at the member variable <code>.error</code>. If in C++, | ||
implements C extern functions for making successful and failure results | ||
of this type. If you call this from within | ||
C++, make SURE it is not within a <code>extern "C"</code> block! | ||
|
||
<dt><code>CXX_RESULT_SYSTEM(ident)</code> | ||
<dd>A reference to a previously declared <code>status_result</code> type with | ||
unique <code>ident</code>. | ||
|
||
<dt><code>CXX_MAKE_RESULT_SYSTEM_SUCCESS(ident, expr)</code> (needs C++ counterpart linked into final binary) | ||
<dd>This invokes the aforementioned extern function which creates a <code>status_result</code> | ||
with a successful value of type <code>T</code>. | ||
<dt><code>CXX_MAKE_RESULT_SYSTEM_FAILURE_POSIX(ident, expr)</code> (needs C++ counterpart linked into final binary) | ||
<dd>This invokes the aforementioned extern function which creates a <code>status_result</code> | ||
with a failure of type <code>posix_code</code> representing a POSIX <code>errno</code>. | ||
<dt><code>CXX_MAKE_RESULT_SYSTEM_FAILURE_SYSTEM(ident, expr)</code> (needs C++ counterpart linked into final binary) | ||
<dd>This invokes the aforementioned extern function which creates a <code>status_result</code> | ||
with a failure of type <code>posix_code</code> representing a POSIX <code>errno</code> | ||
if on POSIX; if on Windows then a failure of type <code>win32_code</code> | ||
representing a Win32 error code from a Windows API. | ||
|
||
<br><br> | ||
<dt><code>CXX_RESULT_HAS_VALUE(r)</code> | ||
<dd>Evaluates to 1 (true) if the input <code>result</code> has a value. | ||
|
||
<dt><code>CXX_RESULT_HAS_ERROR(r)</code> | ||
<dd>Evaluates to 1 (true) if the input <code>result</code> has an error. | ||
|
||
<dt><code>CXX_RESULT_ERROR_IS_ERRNO(r)</code> | ||
<dd>Evaluates to 1 (true) if the input <code>result</code>'s error value | ||
is a code in the POSIX <code>errno</code> domain. | ||
<br><br> | ||
<dt><code>CXX_RESULT_SYSTEM_TRY(expr)</code> | ||
<dd>If the <code>status_result</code> returned by <code>expr</code> is | ||
errored, exit the current function returning the result. This obviously | ||
requires that the return type of the current function matches that of <code> | ||
expr</code>. | ||
|
||
<dt><code>CXX_RESULT_SYSTEM_TRY(cleanup, expr)</code> | ||
<dd>Same as the above, but execute <code>cleanup</code> just before exiting the function | ||
if returning failure. | ||
|
||
<dt><code>CXX_RESULT_SYSTEM_TRY(var, cleanup, expr)</code> | ||
<dd>Same as the above, but set <code>var</code> equal to the result's <code>.value</code> on success. | ||
|
||
<dt><code>CXX_RESULT_SYSTEM_TRY(var, ident, cleanup, expr)</code> | ||
<dd>Same as the above, but use <code>ident</code> as the return type instead. This allows | ||
the return type of the calling function to differ from that of <code>expr</code>. | ||
<br><br> | ||
<dt><code>CXX_DECLARE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, uuid, {enum mapping-sequence, ...})</code> | ||
<dd>This declares to C an extern function which creates a <code>status_result</code> | ||
from a C enum. If in C++, it implements a <code>quick_status_code_from_enum</code> for | ||
the C enum and the associated extern function, and you will need to supply <code>uuid</code> | ||
and the appropriate enum value mapping sequence <a href="{{% relref "../../worked-example" %}}"> | ||
as per the <code>quick_status_code_from_enum</code> documentation</a>. | ||
<dt><code>CXX_MAKE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, expr)</code> (needs C++ counterpart linked into final binary) | ||
<dd>This invokes the aforementioned extern function which creates a <code>status_result</code> | ||
from a C enum. | ||
</dl> | ||
|
||
The operations available to C++ are: | ||
|
||
<dl> | ||
<dt><code>CXX_TO_RESULT_SYSTEM_CODE(ident, status_code<T>)</code> | ||
<dd>Returns a previously declared C Result from its matching C++ <code>status_code</code>. | ||
NOTE that the destructor of the C++ status code is NOT called. If this is important | ||
to your status code, it is 100% on you to ensure that your C Result reenters a C++ | ||
Result at the end of its lifetime. | ||
|
||
<dt><code>to_result(any C Result)</code> | ||
<dd>This is an overloaded C++ free function which returns the C++ status_code<T> | ||
matching its input C Result. | ||
</dl> | ||
|
||
Using the above you can write C code using Outcome.Experimental's Result type | ||
quite effectively. Let's look at an example of use next. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
+++ | ||
title = "TRY a C Result" | ||
description = "Operation TRY on a C Result" | ||
weight = 40 | ||
+++ | ||
|
||
Thanks to much of the magic of {{< api "OUTCOME_TRY(var, expr)" >}} being implemented | ||
using C preprocessor metaprogramming, we can offer a very similar experience for the | ||
C try operation and without needing anything compiled in C++ as support functions: | ||
|
||
{{% snippet "c_api2.cpp" "try" %}} | ||
|
||
The principle difference is that you can specify a cleanup routine to perform if | ||
failure is encountered. This is especially useful in C, which has no stack unwinding. | ||
|
||
Also due to lack of type sugaring and user defined implicit conversions, if your | ||
callers result type isn't your callee's, you may need to specify what your caller's | ||
result type is so the error state can be correctly propagated. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
+++ | ||
title = "Using a Result" | ||
description = "Using a C Result" | ||
weight = 30 | ||
+++ | ||
|
||
This models [the earlier C++ example of use]({{% relref "/experimental/worked-example/implicit-construction" %}}), | ||
and its C equivalent isn't much more verbose thanks to our helper typedefs and macros: | ||
|
||
{{% snippet "c_api2.cpp" "using" %}} | ||
|
||
For this to link, the `CXX_DECLARE_RESULT_SYSTEM_FROM_ENUM` macro needs to be | ||
compiled at least once within C++ within the final binary to emit the extern | ||
functions needed by C. |
Oops, something went wrong.