microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
errno.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2//
3// SPDX-License-Identifier: BSD-2-Clause
4
5#pragma once
6
7// std-interop-file: opt-in errno/<system_error> formatter, not pulled in by the default umbrella.
8
9#include "../microfmt.hpp"
10#include <cerrno>
11
12#ifndef RELOCO_KERNEL
13#ifndef MICROFMT_USE_SYSTEM_ERROR
14#define MICROFMT_USE_SYSTEM_ERROR 0
15#endif
16#if MICROFMT_USE_SYSTEM_ERROR
17#include <string>
18#include <system_error>
19#else
20#include <cstring>
21#endif
22#endif
23
24namespace microfmt {
25
26namespace detail {
27
28#if defined(RELOCO_KERNEL)
29// Kernel mode: Forward declaration. The kernel developer provides the actual
30// implementation linking against kernel logging/error facilities.
31void write_errno_string(const sink &out, int value) noexcept;
32#else
33// User-space / Host mode: Implemented using system_error or strerror_r
34// low-level formatting: raw character pointers and integer width conversions bounded by the buffer sizes checked here.
35RELOCO_BEGIN_UNSAFE_CODE
36inline void write_errno_string(const sink &out, int value) noexcept {
37#if MICROFMT_USE_SYSTEM_ERROR
38 std::error_code ec(value, std::system_category());
39 std::string msg = ec.message();
40 if (!msg.empty()) {
41 out.write(msg);
42 } else {
43 out.write("Unknown error");
44 }
45#else
46 char buf[256] = {};
47 buf[0] = '\0';
48
49#if defined(_WIN32)
50 if (strerror_s(buf, sizeof(buf), value) != 0) {
51 std::strncpy(buf, "Unknown error", sizeof(buf));
52 }
53#elif defined(__APPLE__) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L && !defined(_GNU_SOURCE))
54 if (strerror_r(value, buf, sizeof(buf)) != 0) {
55 std::strncpy(buf, "Unknown error", sizeof(buf));
56 }
57#elif defined(_GNU_SOURCE) || defined(__GLIBC__)
58 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
59 const char *err_msg = strerror_r(value, buf, sizeof(buf));
60 RELOCO_END_UNSAFE_BUFFER_USAGE;
61 if (err_msg != nullptr) {
62 out.write(err_msg);
63 return;
64 }
65#else
66 if (const char *msg = std::strerror(value)) {
67 out.write(msg);
68 return;
69 }
70#endif
71
72 if (buf[0] != '\0') {
73 out.write(buf);
74 } else {
75 out.write("Unknown error");
76 }
77#endif
78}
80#endif
81
82} // namespace detail
83
85 int value{};
86};
87
88constexpr inline posix_errno format_errno(int val) noexcept { return {val}; }
89
90inline posix_errno current_errno() noexcept { return {errno}; }
91
92template <> struct formatter<posix_errno> {
93 constexpr void parse(format_parse_context &) noexcept {}
94
95 void format(const posix_errno &e, const sink &out) const noexcept {
96 // Delegate to detail implementation (forward-declared in kernel, inline in host)
97 detail::write_errno_string(out, e.value);
98
99 // Append the numeric code format: " (os:13)"
100 out.write(" (os:");
101
102 const formatter<int> int_fmt;
103 int_fmt.format(e.value, out);
104
105 out.write(")");
106 }
107};
108
109} // namespace microfmt
Definition microfmt.hpp:881
#define MICROFMT_API_CLASS
Definition compat.hpp:181
RELOCO_BEGIN_UNSAFE_CODE void write_errno_string(const sink &out, int value) noexcept
Definition errno.hpp:36
Definition assert.hpp:19
posix_errno current_errno() noexcept
Definition errno.hpp:90
constexpr posix_errno format_errno(int val) noexcept
Definition errno.hpp:88
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_END_UNSAFE_CODE
Definition remote_object.hpp:132
void format(const posix_errno &e, const sink &out) const noexcept
Definition errno.hpp:95
constexpr void parse(format_parse_context &) noexcept
Definition errno.hpp:93
Definition microfmt.hpp:985
Definition errno.hpp:84