Line data Source code
1 : /* 2 : Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain 3 : Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany 4 : 5 : This software was partially supported by the 6 : EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). 7 : 8 : This software was partially supported by the 9 : ADA-FS project under the SPPEXA project funded by the DFG. 10 : 11 : This file is part of GekkoFS' POSIX interface. 12 : 13 : GekkoFS' POSIX interface is free software: you can redistribute it and/or 14 : modify it under the terms of the GNU Lesser General Public License as 15 : published by the Free Software Foundation, either version 3 of the License, 16 : or (at your option) any later version. 17 : 18 : GekkoFS' POSIX interface is distributed in the hope that it will be useful, 19 : but WITHOUT ANY WARRANTY; without even the implied warranty of 20 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 : GNU Lesser General Public License for more details. 22 : 23 : You should have received a copy of the GNU Lesser General Public License 24 : along with GekkoFS' POSIX interface. If not, see 25 : <https://www.gnu.org/licenses/>. 26 : 27 : SPDX-License-Identifier: LGPL-3.0-or-later 28 : */ 29 : 30 : // This file uses special C formatting for a better overview 31 : // clang-format off 32 : 33 : #ifndef GKFS_SYSCALLS_RETS_HPP 34 : #define GKFS_SYSCALLS_RETS_HPP 35 : 36 : #include <fmt/format.h> 37 : #include <type_traits> 38 : #include <client/syscalls/detail/syscall_info.h> 39 : 40 : namespace gkfs::syscall::ret { 41 : 42 : /** Allowed ret types (based on the values of the corresponding C enum) */ 43 : enum class type { 44 : none = ::ret_type_t::rnone, 45 : ptr = ::ret_type_t::rptr, 46 : dec = ::ret_type_t::rdec, 47 : }; 48 : 49 : /* Some constant definitions for convenience */ 50 : static constexpr auto none = type::none; 51 : static constexpr auto ptr = type::ptr; 52 : static constexpr auto dec = type::dec; 53 : 54 : 55 : /** All ret formatters must follow this prototype */ 56 : template <typename FmtBuffer> 57 : using formatter = 58 : std::add_pointer_t<void(FmtBuffer&, long)>; 59 : 60 : 61 : /** forward declare formatters */ 62 : template <typename FmtBuffer> inline void 63 : format_none_ret_to(FmtBuffer& buffer, long val); 64 : 65 : template <typename FmtBuffer> inline void 66 : format_ptr_ret_to(FmtBuffer& buffer, long val); 67 : 68 : template <typename FmtBuffer> inline void 69 : format_dec_ret_to(FmtBuffer& buffer, long val); 70 : 71 : /** Known formatters */ 72 : template <typename Buffer> 73 : static const constexpr 74 : std::array<formatter<Buffer>, ret_type_max> formatters = { 75 : /* [rnone] = */ format_none_ret_to, 76 : /* [rptr] = */ format_ptr_ret_to, 77 : /* [rdec] = */ format_dec_ret_to, 78 : }; 79 : 80 : /** A return value descriptor */ 81 : struct desc { 82 : ret::type type_; 83 : 84 : ret::type 85 : type() const { 86 : return type_; 87 : } 88 : 89 : bool 90 1758155 : operator==(ret::type t) const { 91 1758155 : return type_ == t; 92 : } 93 : 94 : bool 95 : operator!=(ret::type t) const { 96 : return type_ != t; 97 : } 98 : 99 : template <typename FmtBuffer> 100 : formatter<FmtBuffer> 101 581193 : formatter() const { 102 581193 : const auto idx = static_cast<int>(type_); 103 : 104 : // if the type is unknown fall back to the default formatter 105 581193 : if(idx < 0 || idx >= static_cast<int>(formatters<FmtBuffer>.size())) { 106 : return format_dec_ret_to; 107 : } 108 : 109 581193 : assert(formatters<FmtBuffer>.at(idx) != nullptr); 110 : 111 581193 : return formatters<FmtBuffer>.at(idx); 112 : } 113 : }; 114 : 115 : 116 : /** Specific formatter implementations follow */ 117 : #define LIKELY(x) __builtin_expect(!!(x), 1) 118 : #define UNLIKELY(x) __builtin_expect(!!(x), 0) 119 : 120 : template <typename FmtBuffer> 121 : inline void 122 0 : format_none_ret_to(FmtBuffer& buffer, 123 : long val) { 124 0 : fmt::format_to(buffer, "void"); 125 0 : } 126 : 127 : template <typename FmtBuffer> 128 : inline void 129 2826 : format_ptr_ret_to(FmtBuffer& buffer, 130 : long val) { 131 2826 : if(LIKELY(reinterpret_cast<const void*>(val) != nullptr)) { 132 2826 : fmt::format_to(buffer, "{}", reinterpret_cast<const void*>(val)); 133 2826 : return; 134 : } 135 : 136 0 : fmt::format_to(buffer, "NULL"); 137 : } 138 : 139 : template <typename FmtBuffer> 140 : inline void 141 578367 : format_dec_ret_to(FmtBuffer& buffer, 142 : long val) { 143 578367 : fmt::format_to(buffer, "{}", val); 144 578366 : } 145 : 146 : #undef LIKELY 147 : #undef UNLIKELY 148 : 149 : } // namespace gkfs::syscall::ret 150 : 151 : #endif // GKFS_SYSCALLS_RETS_HPP 152 : 153 : // clang-format on