]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/fmt/include/fmt/posix.h
import ceph 14.2.5
[ceph.git] / ceph / src / seastar / fmt / include / fmt / posix.h
1 // A C++ interface to POSIX functions.
2 //
3 // Copyright (c) 2012 - 2016, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7
8 #ifndef FMT_POSIX_H_
9 #define FMT_POSIX_H_
10
11 #if defined(__MINGW32__) || defined(__CYGWIN__)
12 // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
13 # undef __STRICT_ANSI__
14 #endif
15
16 #include <errno.h>
17 #include <fcntl.h> // for O_RDONLY
18 #include <locale.h> // for locale_t
19 #include <stdio.h>
20 #include <stdlib.h> // for strtod_l
21
22 #include <cstddef>
23
24 #if defined __APPLE__ || defined(__FreeBSD__)
25 # include <xlocale.h> // for LC_NUMERIC_MASK on OS X
26 #endif
27
28 #include "format.h"
29
30 #ifndef FMT_POSIX
31 # if defined(_WIN32) && !defined(__MINGW32__)
32 // Fix warnings about deprecated symbols.
33 # define FMT_POSIX(call) _##call
34 # else
35 # define FMT_POSIX(call) call
36 # endif
37 #endif
38
39 // Calls to system functions are wrapped in FMT_SYSTEM for testability.
40 #ifdef FMT_SYSTEM
41 # define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
42 #else
43 # define FMT_SYSTEM(call) call
44 # ifdef _WIN32
45 // Fix warnings about deprecated symbols.
46 # define FMT_POSIX_CALL(call) ::_##call
47 # else
48 # define FMT_POSIX_CALL(call) ::call
49 # endif
50 #endif
51
52 // Retries the expression while it evaluates to error_result and errno
53 // equals to EINTR.
54 #ifndef _WIN32
55 # define FMT_RETRY_VAL(result, expression, error_result) \
56 do { \
57 result = (expression); \
58 } while (result == error_result && errno == EINTR)
59 #else
60 # define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
61 #endif
62
63 #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
64
65 FMT_BEGIN_NAMESPACE
66
67 /**
68 \rst
69 A reference to a null-terminated string. It can be constructed from a C
70 string or ``std::string``.
71
72 You can use one of the following typedefs for common character types:
73
74 +---------------+-----------------------------+
75 | Type | Definition |
76 +===============+=============================+
77 | cstring_view | basic_cstring_view<char> |
78 +---------------+-----------------------------+
79 | wcstring_view | basic_cstring_view<wchar_t> |
80 +---------------+-----------------------------+
81
82 This class is most useful as a parameter type to allow passing
83 different types of strings to a function, for example::
84
85 template <typename... Args>
86 std::string format(cstring_view format_str, const Args & ... args);
87
88 format("{}", 42);
89 format(std::string("{}"), 42);
90 \endrst
91 */
92 template <typename Char>
93 class basic_cstring_view {
94 private:
95 const Char *data_;
96
97 public:
98 /** Constructs a string reference object from a C string. */
99 basic_cstring_view(const Char *s) : data_(s) {}
100
101 /**
102 \rst
103 Constructs a string reference from an ``std::string`` object.
104 \endrst
105 */
106 basic_cstring_view(const std::basic_string<Char> &s) : data_(s.c_str()) {}
107
108 /** Returns the pointer to a C string. */
109 const Char *c_str() const { return data_; }
110 };
111
112 typedef basic_cstring_view<char> cstring_view;
113 typedef basic_cstring_view<wchar_t> wcstring_view;
114
115 // An error code.
116 class error_code {
117 private:
118 int value_;
119
120 public:
121 explicit error_code(int value = 0) FMT_NOEXCEPT : value_(value) {}
122
123 int get() const FMT_NOEXCEPT { return value_; }
124 };
125
126 // A buffered file.
127 class buffered_file {
128 private:
129 FILE *file_;
130
131 friend class file;
132
133 explicit buffered_file(FILE *f) : file_(f) {}
134
135 public:
136 // Constructs a buffered_file object which doesn't represent any file.
137 buffered_file() FMT_NOEXCEPT : file_(FMT_NULL) {}
138
139 // Destroys the object closing the file it represents if any.
140 FMT_API ~buffered_file() FMT_NOEXCEPT;
141
142 private:
143 buffered_file(const buffered_file &) = delete;
144 void operator=(const buffered_file &) = delete;
145
146
147 public:
148 buffered_file(buffered_file &&other) FMT_NOEXCEPT : file_(other.file_) {
149 other.file_ = FMT_NULL;
150 }
151
152 buffered_file& operator=(buffered_file &&other) {
153 close();
154 file_ = other.file_;
155 other.file_ = FMT_NULL;
156 return *this;
157 }
158
159 // Opens a file.
160 FMT_API buffered_file(cstring_view filename, cstring_view mode);
161
162 // Closes the file.
163 FMT_API void close();
164
165 // Returns the pointer to a FILE object representing this file.
166 FILE *get() const FMT_NOEXCEPT { return file_; }
167
168 // We place parentheses around fileno to workaround a bug in some versions
169 // of MinGW that define fileno as a macro.
170 FMT_API int (fileno)() const;
171
172 void vprint(string_view format_str, format_args args) {
173 fmt::vprint(file_, format_str, args);
174 }
175
176 template <typename... Args>
177 inline void print(string_view format_str, const Args & ... args) {
178 vprint(format_str, make_format_args(args...));
179 }
180 };
181
182 // A file. Closed file is represented by a file object with descriptor -1.
183 // Methods that are not declared with FMT_NOEXCEPT may throw
184 // fmt::system_error in case of failure. Note that some errors such as
185 // closing the file multiple times will cause a crash on Windows rather
186 // than an exception. You can get standard behavior by overriding the
187 // invalid parameter handler with _set_invalid_parameter_handler.
188 class file {
189 private:
190 int fd_; // File descriptor.
191
192 // Constructs a file object with a given descriptor.
193 explicit file(int fd) : fd_(fd) {}
194
195 public:
196 // Possible values for the oflag argument to the constructor.
197 enum {
198 RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
199 WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
200 RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
201 };
202
203 // Constructs a file object which doesn't represent any file.
204 file() FMT_NOEXCEPT : fd_(-1) {}
205
206 // Opens a file and constructs a file object representing this file.
207 FMT_API file(cstring_view path, int oflag);
208
209 private:
210 file(const file &) = delete;
211 void operator=(const file &) = delete;
212
213 public:
214 file(file &&other) FMT_NOEXCEPT : fd_(other.fd_) {
215 other.fd_ = -1;
216 }
217
218 file& operator=(file &&other) {
219 close();
220 fd_ = other.fd_;
221 other.fd_ = -1;
222 return *this;
223 }
224
225 // Destroys the object closing the file it represents if any.
226 FMT_API ~file() FMT_NOEXCEPT;
227
228 // Returns the file descriptor.
229 int descriptor() const FMT_NOEXCEPT { return fd_; }
230
231 // Closes the file.
232 FMT_API void close();
233
234 // Returns the file size. The size has signed type for consistency with
235 // stat::st_size.
236 FMT_API long long size() const;
237
238 // Attempts to read count bytes from the file into the specified buffer.
239 FMT_API std::size_t read(void *buffer, std::size_t count);
240
241 // Attempts to write count bytes from the specified buffer to the file.
242 FMT_API std::size_t write(const void *buffer, std::size_t count);
243
244 // Duplicates a file descriptor with the dup function and returns
245 // the duplicate as a file object.
246 FMT_API static file dup(int fd);
247
248 // Makes fd be the copy of this file descriptor, closing fd first if
249 // necessary.
250 FMT_API void dup2(int fd);
251
252 // Makes fd be the copy of this file descriptor, closing fd first if
253 // necessary.
254 FMT_API void dup2(int fd, error_code &ec) FMT_NOEXCEPT;
255
256 // Creates a pipe setting up read_end and write_end file objects for reading
257 // and writing respectively.
258 FMT_API static void pipe(file &read_end, file &write_end);
259
260 // Creates a buffered_file object associated with this file and detaches
261 // this file object from the file.
262 FMT_API buffered_file fdopen(const char *mode);
263 };
264
265 // Returns the memory page size.
266 long getpagesize();
267
268 #if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
269 !defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__) && \
270 !defined(__NEWLIB_H__)
271 # define FMT_LOCALE
272 #endif
273
274 #ifdef FMT_LOCALE
275 // A "C" numeric locale.
276 class Locale {
277 private:
278 # ifdef _MSC_VER
279 typedef _locale_t locale_t;
280
281 enum { LC_NUMERIC_MASK = LC_NUMERIC };
282
283 static locale_t newlocale(int category_mask, const char *locale, locale_t) {
284 return _create_locale(category_mask, locale);
285 }
286
287 static void freelocale(locale_t locale) {
288 _free_locale(locale);
289 }
290
291 static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
292 return _strtod_l(nptr, endptr, locale);
293 }
294 # endif
295
296 locale_t locale_;
297
298 Locale(const Locale &) = delete;
299 void operator=(const Locale &) = delete;
300
301 public:
302 typedef locale_t Type;
303
304 Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) {
305 if (!locale_)
306 FMT_THROW(system_error(errno, "cannot create locale"));
307 }
308 ~Locale() { freelocale(locale_); }
309
310 Type get() const { return locale_; }
311
312 // Converts string to floating-point number and advances str past the end
313 // of the parsed input.
314 double strtod(const char *&str) const {
315 char *end = FMT_NULL;
316 double result = strtod_l(str, &end, locale_);
317 str = end;
318 return result;
319 }
320 };
321 #endif // FMT_LOCALE
322 FMT_END_NAMESPACE
323
324 #endif // FMT_POSIX_H_