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.
12 :
13 : GekkoFS is free software: you can redistribute it and/or modify
14 : it under the terms of the GNU General Public License as published by
15 : the Free Software Foundation, either version 3 of the License, or
16 : (at your option) any later version.
17 :
18 : GekkoFS 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 General Public License for more details.
22 :
23 : You should have received a copy of the GNU General Public License
24 : along with GekkoFS. If not, see <https://www.gnu.org/licenses/>.
25 :
26 : SPDX-License-Identifier: GPL-3.0-or-later
27 : */
28 :
29 : #ifndef GKFS_IO_SERIALIZE_HPP
30 : #define GKFS_IO_SERIALIZE_HPP
31 :
32 : #include <nlohmann/json.hpp>
33 : #include <reflection.hpp>
34 :
35 : extern "C" {
36 : #include <sys/stat.h>
37 : #include <sys/vfs.h>
38 : #include <sys/statvfs.h>
39 : }
40 :
41 : template <typename T>
42 : nlohmann::json
43 268 : serialize(const T& object) {
44 :
45 : using json = nlohmann::json;
46 :
47 268 : json j;
48 :
49 268 : constexpr auto n = std::tuple_size<decltype(T::properties)>::value;
50 :
51 2104 : refl::for_sequence(std::make_index_sequence<n>{}, [&](auto i) {
52 : constexpr auto p = std::get<i>(T::properties);
53 :
54 : // j[p.name] = json {
55 : // { "type" , p.type },
56 : // { "value" , object.*(p.member) }
57 : //};
58 :
59 612 : j[p.name] = object.*(p.member);
60 : });
61 :
62 268 : return j;
63 : }
64 :
65 : namespace nlohmann {
66 :
67 : // ADL specialization for pointers to complete types that
68 : // we want serialized
69 : template <typename T>
70 : struct adl_serializer<T*> {
71 : static void
72 : to_json(json& j, const T* opt) {
73 : if(opt) {
74 : j = *opt;
75 : } else {
76 : j = nullptr;
77 : }
78 : }
79 : };
80 :
81 : // ADL specialization for C strings
82 : template <>
83 : struct adl_serializer<const char*> {
84 : static void
85 : to_json(json& j, const char* opt) {
86 : if(opt) {
87 : j = std::string{opt};
88 : } else {
89 : j = std::string{};
90 : }
91 : }
92 : };
93 :
94 : // base serializer for opaque pointers
95 : template <typename T>
96 : struct opaque_ptr_serializer {
97 : static void
98 2 : to_json(json& j, const T opt) {
99 2 : if(opt) {
100 1 : j = reinterpret_cast<uint64_t>(opt);
101 : } else {
102 1 : j = nullptr;
103 : }
104 2 : }
105 : };
106 :
107 : // ADL specialization for opaque ::DIR* type
108 : template <>
109 : struct adl_serializer<::DIR*> : public opaque_ptr_serializer<::DIR*> {
110 : using opaque_ptr_serializer<::DIR*>::to_json;
111 : };
112 :
113 : // ADL specialization for void* type
114 : template <>
115 : struct adl_serializer<void*> : public opaque_ptr_serializer<void*> {
116 : using opaque_ptr_serializer<void*>::to_json;
117 : };
118 :
119 : // ADL specialization for struct ::timespec type
120 : template <>
121 : struct adl_serializer<struct ::timespec> {
122 : static void
123 138 : to_json(json& j, const struct ::timespec opt) {
124 :
125 966 : j = json{{"tv_sec", opt.tv_sec}, {"tv_nsec", opt.tv_nsec}};
126 138 : }
127 : };
128 :
129 : #ifdef STATX_TYPE
130 : // ADL specialization for struct ::statx_timestamp type
131 : template <>
132 : struct adl_serializer<struct ::statx_timestamp> {
133 : static void
134 16 : to_json(json& j, const struct ::statx_timestamp opt) {
135 :
136 112 : j = json{{"tv_sec", opt.tv_sec}, {"tv_nsec", opt.tv_nsec}};
137 16 : }
138 : };
139 : #endif
140 :
141 : // ADL specialization for struct ::dirent type
142 : template <>
143 : struct adl_serializer<struct ::dirent> {
144 : static void
145 14 : to_json(json& j, const struct ::dirent opt) {
146 :
147 28 : j = json{
148 : {"d_ino", opt.d_ino}, {"d_off", opt.d_off},
149 : {"d_reclen", opt.d_reclen}, {"d_type", opt.d_type},
150 : {"d_name", opt.d_name},
151 238 : };
152 14 : }
153 : };
154 :
155 : // std::ostream&
156 : // operator<<(std::ostream& os, const struct ::dirent& d) {
157 : // return os << "hello there!\n";
158 : //}
159 :
160 : // ADL specialization for struct ::stat type
161 : template <>
162 : struct adl_serializer<struct ::stat> {
163 : static void
164 46 : to_json(json& j, const struct ::stat opt) {
165 :
166 92 : j = json{{"st_dev", opt.st_dev}, {"st_ino", opt.st_ino},
167 : {"st_mode", opt.st_mode}, {"st_nlink", opt.st_nlink},
168 : {"st_uid", opt.st_uid}, {"st_gid", opt.st_gid},
169 : {"st_rdev", opt.st_rdev}, {"st_size", opt.st_size},
170 : {"st_blksize", opt.st_blksize}, {"st_blocks", opt.st_blocks},
171 : {"st_atim", opt.st_atim}, {"st_mtim", opt.st_mtim},
172 1886 : {"st_ctim", opt.st_ctim}};
173 46 : }
174 : };
175 :
176 : // ADL specialization for struct ::statfs (not exhaustive) type
177 : template <>
178 : struct adl_serializer<struct ::statfs> {
179 : static void
180 1 : to_json(json& j, const struct ::statfs opt) {
181 2 : j = json{{"f_type", opt.f_type}, {"f_bsize", opt.f_bsize},
182 : {"f_blocks", opt.f_blocks}, {"f_bfree", opt.f_bfree},
183 : {"f_bavail", opt.f_bavail}, {"f_files", opt.f_files},
184 23 : {"f_ffree", opt.f_ffree}};
185 1 : }
186 : };
187 :
188 : #ifdef STATX_TYPE
189 : // ADL specialization for struct ::statx type
190 : template <>
191 : struct adl_serializer<struct ::statx> {
192 : static void
193 4 : to_json(json& j, const struct ::statx opt) {
194 :
195 8 : j = json{{"stx_mask", opt.stx_mask},
196 : {"stx_blksize", opt.stx_blksize},
197 : {"stx_attributes", opt.stx_attributes},
198 : {"stx_nlink", opt.stx_nlink},
199 : {"stx_uid", opt.stx_uid},
200 : {"stx_gid", opt.stx_gid},
201 : {"stx_mode", opt.stx_mode},
202 : {"stx_ino", opt.stx_ino},
203 : {"stx_size", opt.stx_size},
204 : {"stx_blocks", opt.stx_blocks},
205 : {"stx_attributes_mask", opt.stx_attributes_mask},
206 : {"stx_atime", opt.stx_atime},
207 : {"stx_btime", opt.stx_btime},
208 : {"stx_ctime", opt.stx_ctime},
209 : {"stx_mtime", opt.stx_mtime},
210 :
211 : {"stx_rdev_major", opt.stx_rdev_major},
212 : {"stx_rdev_minor", opt.stx_rdev_minor},
213 : {"stx_dev_major", opt.stx_dev_major},
214 : {"stx_dev_minor", opt.stx_dev_minor}
215 :
216 236 : };
217 4 : }
218 : };
219 : #endif
220 :
221 : } // namespace nlohmann
222 :
223 : namespace fmt {
224 :
225 : template <>
226 : struct formatter<struct ::dirent> {
227 : constexpr auto
228 0 : parse(format_parse_context& ctx) {
229 : // [ctx.begin(), ctx.end()) is a character range that contains a part of
230 : // the format string starting from the format specifications to be
231 : // parsed, e.g. in
232 : //
233 : // fmt::format("{:f} - point of interest", point{1, 2});
234 : //
235 : // the range will contain "f} - point of interest". The formatter should
236 : // parse specifiers until '}' or the end of the range. In this example
237 : // the formatter should parse the 'f' specifier and return an iterator
238 : // pointing to '}'.
239 :
240 : // Parse the presentation format and store it in the formatter:
241 0 : auto it = ctx.begin(), end = ctx.end();
242 :
243 : // Check if reached the end of the range:
244 0 : if(it != end && *it != '}')
245 0 : throw format_error("invalid format");
246 :
247 : // Return an iterator past the end of the parsed range:
248 0 : return it;
249 : }
250 :
251 : template <typename FormatContext>
252 : auto
253 0 : format(const struct ::dirent& dirent, FormatContext& ctx) const
254 : -> format_context::iterator {
255 0 : return format_to(ctx.out(),
256 : "struct dirent {{\n"
257 : " d_ino = {};\n"
258 : " d_off = {};\n"
259 : " d_reclen = {};\n"
260 : " d_type = {};\n"
261 : " d_name = {};\n"
262 : "}}",
263 0 : dirent.d_ino, dirent.d_off, dirent.d_reclen,
264 0 : dirent.d_type, dirent.d_name);
265 : }
266 : };
267 :
268 : } // namespace fmt
269 :
270 : #endif // GKFS_IO_SERIALIZE_HPP
|