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 247 : serialize(const T& object) {
44 :
45 : using json = nlohmann::json;
46 :
47 247 : json j;
48 :
49 247 : constexpr auto n = std::tuple_size<decltype(T::properties)>::value;
50 :
51 1945 : 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 566 : j[p.name] = object.*(p.member);
60 : });
61 :
62 247 : 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 10 : to_json(json& j, const struct ::dirent opt) {
146 :
147 20 : 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 170 : };
152 10 : }
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},
182 : {"f_bsize", opt.f_bsize},
183 : {"f_blocks", opt.f_blocks},
184 : {"f_bfree", opt.f_bfree},
185 : {"f_bavail", opt.f_bavail},
186 : {"f_files", opt.f_files},
187 23 : {"f_ffree", opt.f_ffree}};
188 1 : }
189 : };
190 :
191 : #ifdef STATX_TYPE
192 : // ADL specialization for struct ::statx type
193 : template <>
194 : struct adl_serializer<struct ::statx> {
195 : static void
196 4 : to_json(json& j, const struct ::statx opt) {
197 :
198 8 : j = json{{"stx_mask", opt.stx_mask},
199 : {"stx_blksize", opt.stx_blksize},
200 : {"stx_attributes", opt.stx_attributes},
201 : {"stx_nlink", opt.stx_nlink},
202 : {"stx_uid", opt.stx_uid},
203 : {"stx_gid", opt.stx_gid},
204 : {"stx_mode", opt.stx_mode},
205 : {"stx_ino", opt.stx_ino},
206 : {"stx_size", opt.stx_size},
207 : {"stx_blocks", opt.stx_blocks},
208 : {"stx_attributes_mask", opt.stx_attributes_mask},
209 : {"stx_atime", opt.stx_atime},
210 : {"stx_btime", opt.stx_btime},
211 : {"stx_ctime", opt.stx_ctime},
212 : {"stx_mtime", opt.stx_mtime},
213 :
214 : {"stx_rdev_major", opt.stx_rdev_major},
215 : {"stx_rdev_minor", opt.stx_rdev_minor},
216 : {"stx_dev_major", opt.stx_dev_major},
217 : {"stx_dev_minor", opt.stx_dev_minor}
218 :
219 236 : };
220 4 : }
221 : };
222 : #endif
223 :
224 : } // namespace nlohmann
225 :
226 : namespace fmt {
227 :
228 : template <>
229 : struct formatter<struct ::dirent> {
230 : constexpr auto
231 0 : parse(format_parse_context& ctx) {
232 : // [ctx.begin(), ctx.end()) is a character range that contains a part of
233 : // the format string starting from the format specifications to be
234 : // parsed, e.g. in
235 : //
236 : // fmt::format("{:f} - point of interest", point{1, 2});
237 : //
238 : // the range will contain "f} - point of interest". The formatter should
239 : // parse specifiers until '}' or the end of the range. In this example
240 : // the formatter should parse the 'f' specifier and return an iterator
241 : // pointing to '}'.
242 :
243 : // Parse the presentation format and store it in the formatter:
244 0 : auto it = ctx.begin(), end = ctx.end();
245 :
246 : // Check if reached the end of the range:
247 0 : if(it != end && *it != '}')
248 0 : throw format_error("invalid format");
249 :
250 : // Return an iterator past the end of the parsed range:
251 0 : return it;
252 : }
253 :
254 : template <typename FormatContext>
255 : auto
256 0 : format(const struct ::dirent& dirent, FormatContext& ctx) {
257 0 : return format_to(ctx.out(),
258 : "struct dirent {{\n"
259 : " d_ino = {};\n"
260 : " d_off = {};\n"
261 : " d_reclen = {};\n"
262 : " d_type = {};\n"
263 : " d_name = {};\n"
264 : "}}",
265 0 : dirent.d_ino, dirent.d_off, dirent.d_reclen,
266 0 : dirent.d_type, dirent.d_name);
267 : }
268 : };
269 :
270 : } // namespace fmt
271 :
272 : #endif // GKFS_IO_SERIALIZE_HPP
|