result.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /* C interface for result
  2. (C) 2017-2025 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
  3. File Created: Aug 2017
  4. Boost Software License - Version 1.0 - August 17th, 2003
  5. Permission is hereby granted, free of charge, to any person or organization
  6. obtaining a copy of the software and accompanying documentation covered by
  7. this license (the "Software") to use, reproduce, display, distribute,
  8. execute, and transmit the Software, and to prepare derivative works of the
  9. Software, and to permit third-parties to whom the Software is furnished to
  10. do so, all subject to the following:
  11. The copyright notices in the Software and this entire statement, including
  12. the above license grant, this restriction and the following disclaimer,
  13. must be included in all copies of the Software, in whole or in part, and
  14. all derivative works of the Software, unless such copies or derivative
  15. works are solely in the form of machine-executable object code generated by
  16. a source language processor.
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  20. SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  21. FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  22. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. DEALINGS IN THE SOFTWARE.
  24. */
  25. #ifndef BOOST_OUTCOME_EXPERIMENTAL_RESULT_H
  26. #define BOOST_OUTCOME_EXPERIMENTAL_RESULT_H
  27. #include <assert.h>
  28. #include <stddef.h> // for size_t
  29. #include <stdint.h> // for intptr_t
  30. #include "../detail/try.h"
  31. #ifndef BOOST_OUTCOME_C_WEAK
  32. #ifdef _MSC_VER
  33. #define BOOST_OUTCOME_C_WEAK inline
  34. #else
  35. #define BOOST_OUTCOME_C_WEAK __attribute__((weak))
  36. #endif
  37. #endif
  38. #ifndef BOOST_OUTCOME_C_MSVC_FORCE_EMIT
  39. #ifdef _MSC_VER
  40. #ifdef __cplusplus
  41. #define BOOST_OUTCOME_C_MSVC_FORCE_EMIT(x) extern "C" __declspec(selectany) void *x##_emit = x;
  42. #else
  43. #define BOOST_OUTCOME_C_MSVC_FORCE_EMIT(x) extern __declspec(selectany) void *x##_emit = x;
  44. #endif
  45. #else
  46. #define BOOST_OUTCOME_C_MSVC_FORCE_EMIT(x)
  47. #endif
  48. #endif
  49. #ifndef BOOST_OUTCOME_C_NODISCARD
  50. #if __STDC_VERSION__ >= 202000L || __cplusplus >= 201700L
  51. #define BOOST_OUTCOME_C_NODISCARD [[nodiscard]]
  52. #ifdef __cplusplus
  53. #define BOOST_OUTCOME_C_NODISCARD_EXTERN_C extern "C" [[nodiscard]]
  54. #else
  55. #define BOOST_OUTCOME_C_NODISCARD_EXTERN_C [[nodiscard]] extern
  56. #endif
  57. #elif defined(__GNUC__) || defined(__clang__)
  58. #define BOOST_OUTCOME_C_NODISCARD __attribute__((warn_unused_result))
  59. #ifdef __cplusplus
  60. #define BOOST_OUTCOME_C_NODISCARD_EXTERN_C extern "C" __attribute__((warn_unused_result))
  61. #else
  62. #define BOOST_OUTCOME_C_NODISCARD_EXTERN_C extern __attribute__((warn_unused_result))
  63. #endif
  64. #else
  65. #define BOOST_OUTCOME_C_NODISCARD
  66. #define BOOST_OUTCOME_C_NODISCARD_EXTERN_C extern
  67. #endif
  68. #endif
  69. #ifndef BOOST_OUTCOME_C_INLINE
  70. #if __STDC_VERSION__ >= 199900L || __cplusplus > 0
  71. #define BOOST_OUTCOME_C_INLINE inline
  72. #elif defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
  73. #define BOOST_OUTCOME_C_INLINE __inline
  74. #else
  75. #define BOOST_OUTCOME_C_INLINE
  76. #endif
  77. #endif
  78. #include "../outcome_gdb.h"
  79. #ifdef __cplusplus
  80. extern "C"
  81. {
  82. #endif
  83. #define BOOST_OUTCOME_C_DECLARE_RESULT(ident, R, S) \
  84. struct cxx_result_##ident \
  85. { \
  86. union \
  87. { \
  88. R value; \
  89. S error; \
  90. }; \
  91. unsigned flags; \
  92. }
  93. #define BOOST_OUTCOME_C_RESULT(ident) struct cxx_result_##ident
  94. #define BOOST_OUTCOME_C_RESULT_HAS_VALUE(r) (((r).flags & 1U) == 1U)
  95. #define BOOST_OUTCOME_C_RESULT_HAS_ERROR(r) (((r).flags & 2U) == 2U)
  96. #define BOOST_OUTCOME_C_RESULT_ERROR_IS_ERRNO(r) (((r).flags & (1U << 4U)) == (1U << 4U))
  97. /***************************** <system_error2> support ******************************/
  98. #define BOOST_OUTCOME_C_DECLARE_STATUS_CODE(ident, value_type) \
  99. struct cxx_status_code_##ident \
  100. { \
  101. void *domain; \
  102. value_type value; \
  103. };
  104. #define BOOST_OUTCOME_C_STATUS_CODE(ident) struct cxx_status_code_##ident
  105. extern BOOST_OUTCOME_C_WEAK void outcome_make_result_status_code_failure_posix(void *out, size_t bytes, size_t offset, int errcode);
  106. extern BOOST_OUTCOME_C_WEAK void outcome_make_result_status_code_failure_system(void *out, size_t bytes, size_t offset, intptr_t errcode);
  107. extern BOOST_OUTCOME_C_WEAK int outcome_status_code_equal(const void *a, const void *b);
  108. extern BOOST_OUTCOME_C_WEAK int outcome_status_code_equal_generic(const void *a, int errcode);
  109. extern BOOST_OUTCOME_C_WEAK const char *outcome_status_code_message(const void *a);
  110. #ifdef __cplusplus
  111. #define BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE_CXX(ident, R, S) \
  112. static_assert(std::is_trivially_copyable<R>::value || BOOST_OUTCOME_V2_NAMESPACE::trait::is_move_bitcopying<R>::value, \
  113. "R must be trivially copyable or move bitcopying to be used in a C Result"); \
  114. static_assert(std::is_trivially_copyable<S>::value || BOOST_OUTCOME_V2_NAMESPACE::trait::is_move_bitcopying<S>::value, \
  115. "S must be trivially copyable or move bitcopying to be used in a C Result"); \
  116. inline BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<R> to_result(const cxx_result_status_code_##ident &v) \
  117. { \
  118. union type_punner_t \
  119. { \
  120. cxx_result_status_code_##ident c; \
  121. BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<R> cpp; \
  122. \
  123. type_punner_t() \
  124. : c{} \
  125. { \
  126. } \
  127. ~type_punner_t() {} \
  128. } pun; \
  129. \
  130. pun.c = v; \
  131. return std::move(pun.cpp); \
  132. } \
  133. BOOST_OUTCOME_C_NODISCARD inline cxx_result_status_code_##ident to_##ident(BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<R> v) \
  134. { \
  135. union type_punner_t \
  136. { \
  137. BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<R> cpp; \
  138. cxx_result_status_code_##ident c; \
  139. \
  140. type_punner_t(BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<R> v) \
  141. : cpp(std::move(v)) \
  142. { \
  143. } \
  144. ~type_punner_t() {} \
  145. } pun{std::move(v)}; \
  146. \
  147. return pun.c; \
  148. }
  149. #else
  150. #define BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE_CXX(ident, R, S)
  151. #endif
  152. #define BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE(ident, R, S) \
  153. struct cxx_result_status_code_##ident \
  154. { \
  155. R value; \
  156. unsigned flags; \
  157. S error; \
  158. }; \
  159. BOOST_OUTCOME_C_NODISCARD static BOOST_OUTCOME_C_INLINE struct cxx_result_status_code_##ident outcome_make_result_##ident##_success(R value) \
  160. { /* We special case this so it inlines efficiently */ \
  161. struct cxx_result_status_code_##ident ret; \
  162. ret.value = value; \
  163. ret.flags = 1 /* have_value */; \
  164. return ret; \
  165. } \
  166. BOOST_OUTCOME_C_NODISCARD_EXTERN_C BOOST_OUTCOME_C_WEAK struct cxx_result_status_code_##ident outcome_make_result_##ident##_failure_posix(int errcode) \
  167. { \
  168. struct cxx_result_status_code_##ident ret; \
  169. assert(outcome_make_result_status_code_failure_posix!=NULL); /* If this fails, you need to compile this file at least once in C++. */ \
  170. outcome_make_result_status_code_failure_posix((void *) &ret, sizeof(ret), offsetof(struct cxx_result_status_code_##ident, flags), errcode); \
  171. return ret; \
  172. } \
  173. BOOST_OUTCOME_C_MSVC_FORCE_EMIT(outcome_make_result_##ident##_failure_posix) \
  174. BOOST_OUTCOME_C_NODISCARD_EXTERN_C BOOST_OUTCOME_C_WEAK struct cxx_result_status_code_##ident outcome_make_result_##ident##_failure_system(intptr_t errcode) \
  175. { \
  176. struct cxx_result_status_code_##ident ret; \
  177. assert(outcome_make_result_status_code_failure_system!=NULL); /* If this fails, you need to compile this file at least once in C++. */ \
  178. outcome_make_result_status_code_failure_system((void *) &ret, sizeof(ret), offsetof(struct cxx_result_status_code_##ident, flags), errcode); \
  179. return ret; \
  180. } \
  181. BOOST_OUTCOME_C_MSVC_FORCE_EMIT(outcome_make_result_##ident##_failure_system) \
  182. BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE_CXX(ident, R, S)
  183. #define BOOST_OUTCOME_C_RESULT_STATUS_CODE(ident) struct cxx_result_status_code_##ident
  184. #define BOOST_OUTCOME_C_TO_RESULT_STATUS_CODE(ident, ...) to_##ident(__VA_ARGS__)
  185. #define BOOST_OUTCOME_C_MAKE_RESULT_STATUS_CODE_SUCCESS(ident, ...) outcome_make_result_##ident##_success(__VA_ARGS__)
  186. #define BOOST_OUTCOME_C_MAKE_RESULT_STATUS_CODE_FAILURE_POSIX(ident, ...) outcome_make_result_##ident##_failure_posix(__VA_ARGS__)
  187. #define BOOST_OUTCOME_C_MAKE_RESULT_STATUS_CODE_FAILURE_SYSTEM(ident, ...) outcome_make_result_##ident##_failure_system(__VA_ARGS__)
  188. struct cxx_status_code_posix
  189. {
  190. void *domain;
  191. int value;
  192. };
  193. #define BOOST_OUTCOME_C_DECLARE_RESULT_ERRNO(ident, R) BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE(posix_##ident, R, struct cxx_status_code_posix)
  194. #define BOOST_OUTCOME_C_RESULT_ERRNO(ident) BOOST_OUTCOME_C_RESULT_STATUS_CODE(posix_##ident)
  195. struct cxx_status_code_system
  196. {
  197. void *domain;
  198. intptr_t value;
  199. };
  200. #define BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM(ident, R) BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE(system_##ident, R, struct cxx_status_code_system)
  201. #define BOOST_OUTCOME_C_RESULT_SYSTEM(ident) BOOST_OUTCOME_C_RESULT_STATUS_CODE(system_##ident)
  202. #define BOOST_OUTCOME_C_TO_RESULT_SYSTEM_CODE(ident, ...) to_system_##ident(__VA_ARGS__)
  203. #define BOOST_OUTCOME_C_MAKE_RESULT_SYSTEM_SUCCESS(ident, ...) BOOST_OUTCOME_C_MAKE_RESULT_STATUS_CODE_SUCCESS(system_##ident, __VA_ARGS__)
  204. #define BOOST_OUTCOME_C_MAKE_RESULT_SYSTEM_FAILURE_POSIX(ident, ...) BOOST_OUTCOME_C_MAKE_RESULT_STATUS_CODE_FAILURE_POSIX(system_##ident, __VA_ARGS__)
  205. #define BOOST_OUTCOME_C_MAKE_RESULT_SYSTEM_FAILURE_SYSTEM(ident, ...) BOOST_OUTCOME_C_MAKE_RESULT_STATUS_CODE_FAILURE_SYSTEM(system_##ident, __VA_ARGS__)
  206. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPLV(unique, retstmt, cleanup, spec, ...) \
  207. BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE(unique, spec, __VA_ARGS__); \
  208. BOOST_OUTCOME_TRY_LIKELY_IF(BOOST_OUTCOME_C_RESULT_HAS_VALUE(unique)); \
  209. else \
  210. { \
  211. retstmt; \
  212. }
  213. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPLA(unique, retstmt, cleanup, var, ...) \
  214. BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPLV(unique, retstmt, cleanup, var, __VA_ARGS__) \
  215. BOOST_OUTCOME_TRY2_VAR(var) = unique.value
  216. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPL_RETURN(unique, ident) \
  217. BOOST_OUTCOME_C_RESULT_SYSTEM(ident) unique##_f; \
  218. unique##_f.flags = (unique).flags; \
  219. unique##_f.error = (unique).error; \
  220. return unique##_f
  221. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_SPEC_AND_CLEANUP_AND_NEW_RETURN_TYPE(unique, spec, ident, cleanup, ...) \
  222. BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPLA(unique, BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPL_RETURN(unique, ident), cleanup, spec, __VA_ARGS__)
  223. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_SPEC_AND_CLEANUP(unique, spec, cleanup, ...) BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPLA(unique, return unique, cleanup, spec, __VA_ARGS__)
  224. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_CLEANUP(unique, cleanup, ...) BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPLV(unique, return unique, cleanup, deduce, __VA_ARGS__)
  225. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_SAME_RETURN_TYPE(unique, ...) BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_IMPLV(unique, return unique, , deduce, __VA_ARGS__)
  226. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) \
  227. BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_SPEC_AND_CLEANUP_AND_NEW_RETURN_TYPE(BOOST_OUTCOME_TRY_UNIQUE_NAME, a, b, c, d, e, f, g, h)
  228. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) \
  229. BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_SPEC_AND_CLEANUP_AND_NEW_RETURN_TYPE(BOOST_OUTCOME_TRY_UNIQUE_NAME, a, b, c, d, e, f, g)
  230. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY6(a, b, c, d, e, f) \
  231. BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_SPEC_AND_CLEANUP_AND_NEW_RETURN_TYPE(BOOST_OUTCOME_TRY_UNIQUE_NAME, a, b, c, d, e, f)
  232. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY5(a, b, c, d, e) BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_SPEC_AND_CLEANUP_AND_NEW_RETURN_TYPE(BOOST_OUTCOME_TRY_UNIQUE_NAME, a, b, c, d, e)
  233. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY4(a, b, c, d) BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_SPEC_AND_CLEANUP_AND_NEW_RETURN_TYPE(BOOST_OUTCOME_TRY_UNIQUE_NAME, a, b, c, d)
  234. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY3(a, b, c) BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_SPEC_AND_CLEANUP(BOOST_OUTCOME_TRY_UNIQUE_NAME, a, b, c)
  235. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY2(a, b) BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_WITH_CLEANUP(BOOST_OUTCOME_TRY_UNIQUE_NAME, a, b)
  236. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY1(expr) BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_SAME_RETURN_TYPE(BOOST_OUTCOME_TRY_UNIQUE_NAME, expr)
  237. #define BOOST_OUTCOME_C_RESULT_SYSTEM_TRY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_C_RESULT_SYSTEM_TRY_INVOKE_TRY, __VA_ARGS__)
  238. #define BOOST_OUTCOME_C_MAKE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, ...) outcome_make_result_##ident##_failure_system_enum_##enum_name(__VA_ARGS__)
  239. #ifndef __cplusplus
  240. // Declares the function in C, needs to occur at least once in a C++ source file to get implemented
  241. #define BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, uuid, ...) \
  242. BOOST_OUTCOME_C_NODISCARD_EXTERN_C struct cxx_result_status_code_system_##ident outcome_make_result_##ident##_failure_system_enum_##enum_name(enum enum_name v);
  243. #else
  244. }
  245. #include "../config.hpp"
  246. #include "status-code/config.hpp"
  247. #include "status-code/system_code.hpp"
  248. #include "status_result.hpp"
  249. #include "status-code/posix_code.hpp"
  250. #ifdef _WIN32
  251. #include "status-code/win32_code.hpp"
  252. #endif
  253. #include <algorithm>
  254. #include <cstring>
  255. #if defined(__GNUC__) && !defined(__clang__)
  256. #pragma GCC diagnostic push
  257. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  258. #endif
  259. // You need to include this C header in at least one C++ source file to have these C helper functions be implemented
  260. extern "C" BOOST_OUTCOME_C_WEAK void outcome_make_result_status_code_failure_posix(void *out, size_t bytes, size_t offset, int errcode)
  261. {
  262. using value_type = BOOST_OUTCOME_V2_NAMESPACE::experimental::posix_code::value_type;
  263. union type_punner_t
  264. {
  265. BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<intptr_t> cpp;
  266. struct cxx_status_code
  267. {
  268. intptr_t value;
  269. unsigned flags;
  270. cxx_status_code_system error;
  271. } c;
  272. explicit type_punner_t(BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<intptr_t> res)
  273. : cpp(std::move(res))
  274. {
  275. }
  276. ~type_punner_t() {}
  277. } pun{BOOST_OUTCOME_V2_NAMESPACE::experimental::posix_code(errcode)};
  278. static_assert(sizeof(pun.cpp) == sizeof(pun.c), "");
  279. static constexpr size_t punoffset = offsetof(type_punner_t::cxx_status_code, flags);
  280. assert(bytes - offset >= sizeof(pun.cpp) - punoffset);
  281. const size_t tocopy = std::min(bytes - offset, sizeof(pun.cpp) - punoffset);
  282. memcpy(out, (void *) &pun.c, sizeof(value_type));
  283. memcpy((void *) ((char *) out + offset), (const void *) ((const char *) &pun.c + punoffset), tocopy);
  284. }
  285. BOOST_OUTCOME_C_MSVC_FORCE_EMIT(outcome_make_result_status_code_failure_posix)
  286. extern "C" BOOST_OUTCOME_C_WEAK void outcome_make_result_status_code_failure_system(void *out, size_t bytes, size_t offset, intptr_t errcode)
  287. {
  288. using value_type = BOOST_OUTCOME_V2_NAMESPACE::experimental::system_code::value_type;
  289. union type_punner_t
  290. {
  291. BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<intptr_t> cpp;
  292. struct cxx_status_code
  293. {
  294. intptr_t value;
  295. unsigned flags;
  296. cxx_status_code_system error;
  297. } c;
  298. explicit type_punner_t(BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<intptr_t> res)
  299. : cpp(std::move(res))
  300. {
  301. }
  302. ~type_punner_t() {}
  303. } pun{
  304. #ifdef _WIN32
  305. BOOST_OUTCOME_V2_NAMESPACE::experimental::win32_code((BOOST_OUTCOME_V2_NAMESPACE::experimental::win32::DWORD) errcode)
  306. #else
  307. BOOST_OUTCOME_V2_NAMESPACE::experimental::posix_code((int) errcode)
  308. #endif
  309. };
  310. static_assert(sizeof(pun.cpp) == sizeof(pun.c), "");
  311. static constexpr size_t punoffset = offsetof(type_punner_t::cxx_status_code, flags);
  312. assert(bytes - offset >= sizeof(pun.cpp) - punoffset);
  313. const size_t tocopy = std::min(bytes - offset, sizeof(pun.cpp) - punoffset);
  314. memcpy(out, (void *) &pun.c, sizeof(value_type));
  315. memcpy((void *) ((char *) out + offset), (const void *) ((const char *) &pun.c + punoffset), tocopy);
  316. }
  317. BOOST_OUTCOME_C_MSVC_FORCE_EMIT(outcome_make_result_status_code_failure_system)
  318. extern "C" BOOST_OUTCOME_C_WEAK int outcome_status_code_equal(const void *_a, const void *_b)
  319. {
  320. const auto *a = (const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code *) _a;
  321. const auto *b = (const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code *) _b;
  322. return *a == *b;
  323. }
  324. BOOST_OUTCOME_C_MSVC_FORCE_EMIT(outcome_status_code_equal)
  325. extern "C" BOOST_OUTCOME_C_WEAK int outcome_status_code_equal_generic(const void *_a, int errcode)
  326. {
  327. const auto *a = (const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code *) _a;
  328. return *a == (BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc) errcode;
  329. }
  330. BOOST_OUTCOME_C_MSVC_FORCE_EMIT(outcome_status_code_equal_generic)
  331. extern "C" BOOST_OUTCOME_C_WEAK const char *outcome_status_code_message(const void *_a)
  332. {
  333. static thread_local BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code::string_ref msg((const char *) nullptr, 0);
  334. const auto *a = (const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code *) _a;
  335. msg = a->message();
  336. return msg.c_str();
  337. }
  338. BOOST_OUTCOME_C_MSVC_FORCE_EMIT(outcome_status_code_message)
  339. BOOST_OUTCOME_V2_NAMESPACE_BEGIN
  340. namespace experimental
  341. {
  342. namespace detail
  343. {
  344. template <class RetType, class EnumType> inline RetType outcome_make_result_failure_system_enum(EnumType v)
  345. {
  346. using value_type = BOOST_OUTCOME_V2_NAMESPACE::experimental::system_code::value_type;
  347. union type_punner_t
  348. {
  349. BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<intptr_t> cpp;
  350. struct cxx_status_code
  351. {
  352. intptr_t value;
  353. unsigned flags;
  354. cxx_status_code_system error;
  355. } c;
  356. explicit type_punner_t(BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<intptr_t> res)
  357. : cpp(std::move(res))
  358. {
  359. }
  360. ~type_punner_t() {}
  361. } pun{BOOST_OUTCOME_V2_NAMESPACE::experimental::quick_status_code_from_enum_code<EnumType>(v)};
  362. static constexpr size_t bytes = sizeof(RetType);
  363. static constexpr size_t offset = offsetof(RetType, flags);
  364. static constexpr size_t punoffset = offsetof(typename type_punner_t::cxx_status_code, flags);
  365. assert(bytes - offset >= sizeof(pun.cpp) - punoffset);
  366. const size_t tocopy = std::min(bytes - offset, sizeof(pun.cpp) - punoffset);
  367. RetType ret;
  368. memcpy(&ret, (void *) &pun.c, sizeof(value_type));
  369. memcpy((void *) ((char *) &ret + offset), (const void *) ((const char *) &pun.c + punoffset), tocopy);
  370. return ret;
  371. }
  372. } // namespace detail
  373. } // namespace experimental
  374. BOOST_OUTCOME_V2_NAMESPACE_END
  375. // Unique UUID for the enum PLEASE use https://www.random.org/cgi-bin/randbyte?nbytes=16&format=h
  376. // .. is sequence of {enum_name::value, "text description", {errc::equivalent, ...}},
  377. #define BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, uuid, ...) \
  378. BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN \
  379. template <> struct quick_status_code_from_enum<enum enum_name> : quick_status_code_from_enum_defaults<enum enum_name> \
  380. { \
  381. static constexpr const auto domain_name = #enum_name; \
  382. static constexpr const auto domain_uuid = uuid; \
  383. static const std::initializer_list<mapping> &value_mappings() \
  384. { \
  385. static const std::initializer_list<mapping> v = {__VA_ARGS__}; \
  386. return v; \
  387. } \
  388. }; \
  389. BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END \
  390. extern "C" BOOST_OUTCOME_C_NODISCARD BOOST_OUTCOME_C_WEAK struct cxx_result_status_code_system_##ident outcome_make_result_##ident##_failure_system_enum_##enum_name( \
  391. enum enum_name v) \
  392. { \
  393. return BOOST_OUTCOME_V2_NAMESPACE::experimental::detail::outcome_make_result_failure_system_enum<struct cxx_result_status_code_system_##ident>(v); \
  394. } \
  395. BOOST_OUTCOME_C_MSVC_FORCE_EMIT(outcome_make_result_##ident##_failure_system_enum_##enum_name)
  396. #if defined(__GNUC__) && !defined(__clang__)
  397. #pragma GCC diagnostic pop
  398. #endif
  399. #endif
  400. #endif