Flow123d  master-f44eb46
posix.h
Go to the documentation of this file.
1 /*
2  A C++ interface to POSIX functions.
3 
4  Copyright (c) 2014 - 2016, Victor Zverovich
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without
8  modification, are permitted provided that the following conditions are met:
9 
10  1. Redistributions of source code must retain the above copyright notice, this
11  list of conditions and the following disclaimer.
12  2. Redistributions in binary form must reproduce the above copyright notice,
13  this list of conditions and the following disclaimer in the documentation
14  and/or other materials provided with the distribution.
15 
16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef FMT_POSIX_H_
29 #define FMT_POSIX_H_
30 
31 #ifdef __MINGW32__
32 // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
33 # undef __STRICT_ANSI__
34 #endif
35 
36 #include <errno.h>
37 #include <fcntl.h> // for O_RDONLY
38 #include <locale.h> // for locale_t
39 #include <stdio.h>
40 #include <stdlib.h> // for strtod_l
41 
42 #include <cstddef>
43 
44 #ifdef __APPLE__
45 # include <xlocale.h> // for LC_NUMERIC_MASK on OS X
46 #endif
47 
48 #include "system/fmt/format.h"
49 
50 #ifndef FMT_POSIX
51 # if defined(_WIN32) && !defined(__MINGW32__)
52 // Fix warnings about deprecated symbols.
53 # define FMT_POSIX(call) _##call
54 # else
55 # define FMT_POSIX(call) call
56 # endif
57 #endif
58 
59 // Calls to system functions are wrapped in FMT_SYSTEM for testability.
60 #ifdef FMT_SYSTEM
61 # define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
62 #else
63 # define FMT_SYSTEM(call) call
64 # ifdef _WIN32
65 // Fix warnings about deprecated symbols.
66 # define FMT_POSIX_CALL(call) ::_##call
67 # else
68 # define FMT_POSIX_CALL(call) ::call
69 # endif
70 #endif
71 
72 #if FMT_GCC_VERSION >= 407
73 # define FMT_UNUSED __attribute__((unused))
74 #else
75 # define FMT_UNUSED
76 #endif
77 
78 #ifndef FMT_USE_STATIC_ASSERT
79 # define FMT_USE_STATIC_ASSERT 0
80 #endif
81 
82 #if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
83  (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11)
84 # define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
85 #else
86 # define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
87 # define FMT_STATIC_ASSERT(cond, message) \
88  typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
89 #endif
90 
91 // Retries the expression while it evaluates to error_result and errno
92 // equals to EINTR.
93 #ifndef _WIN32
94 # define FMT_RETRY_VAL(result, expression, error_result) \
95  do { \
96  result = (expression); \
97  } while (result == error_result && errno == EINTR)
98 #else
99 # define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
100 #endif
101 
102 #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
103 
104 namespace fmt {
105 
106 // An error code.
107 class ErrorCode {
108  private:
109  int value_;
110 
111  public:
112  explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
113 
114  int get() const FMT_NOEXCEPT { return value_; }
115 };
116 
117 // A buffered file.
119  private:
120  FILE *file_;
121 
122  friend class File;
123 
124  explicit BufferedFile(FILE *f) : file_(f) {}
125 
126  public:
127  // Constructs a BufferedFile object which doesn't represent any file.
129 
130  // Destroys the object closing the file it represents if any.
132 
133 #if !FMT_USE_RVALUE_REFERENCES
134  // Emulate a move constructor and a move assignment operator if rvalue
135  // references are not supported.
136 
137  private:
138  // A proxy object to emulate a move constructor.
139  // It is private to make it impossible call operator Proxy directly.
140  struct Proxy {
141  FILE *file;
142  };
143 
144 public:
145  // A "move constructor" for moving from a temporary.
147 
148  // A "move constructor" for moving from an lvalue.
150  f.file_ = 0;
151  }
152 
153  // A "move assignment operator" for moving from a temporary.
155  close();
156  file_ = p.file;
157  return *this;
158  }
159 
160  // A "move assignment operator" for moving from an lvalue.
162  close();
163  file_ = other.file_;
164  other.file_ = 0;
165  return *this;
166  }
167 
168  // Returns a proxy object for moving from a temporary:
169  // BufferedFile file = BufferedFile(...);
170  operator Proxy() FMT_NOEXCEPT {
171  Proxy p = {file_};
172  file_ = 0;
173  return p;
174  }
175 
176 #else
177  private:
179 
180  public:
181  BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
182  other.file_ = 0;
183  }
184 
186  close();
187  file_ = other.file_;
188  other.file_ = 0;
189  return *this;
190  }
191 #endif
192 
193  // Opens a file.
194  BufferedFile(CStringRef filename, CStringRef mode);
195 
196  // Closes the file.
197  void close();
198 
199  // Returns the pointer to a FILE object representing this file.
200  FILE *get() const FMT_NOEXCEPT { return file_; }
201 
202  // We place parentheses around fileno to workaround a bug in some versions
203  // of MinGW that define fileno as a macro.
204  int (fileno)() const;
205 
206  void print(CStringRef format_str, const ArgList &args) {
207  fmt::print(file_, format_str, args);
208  }
210 };
211 
212 // A file. Closed file is represented by a File object with descriptor -1.
213 // Methods that are not declared with FMT_NOEXCEPT may throw
214 // fmt::SystemError in case of failure. Note that some errors such as
215 // closing the file multiple times will cause a crash on Windows rather
216 // than an exception. You can get standard behavior by overriding the
217 // invalid parameter handler with _set_invalid_parameter_handler.
218 class File {
219  private:
220  int fd_; // File descriptor.
221 
222  // Constructs a File object with a given descriptor.
223  explicit File(int fd) : fd_(fd) {}
224 
225  public:
226  // Possible values for the oflag argument to the constructor.
227  enum {
228  RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
229  WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
230  RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
231  };
232 
233  // Constructs a File object which doesn't represent any file.
234  File() FMT_NOEXCEPT : fd_(-1) {}
235 
236  // Opens a file and constructs a File object representing this file.
237  File(CStringRef path, int oflag);
238 
239 #if !FMT_USE_RVALUE_REFERENCES
240  // Emulate a move constructor and a move assignment operator if rvalue
241  // references are not supported.
242 
243  private:
244  // A proxy object to emulate a move constructor.
245  // It is private to make it impossible call operator Proxy directly.
246  struct Proxy {
247  int fd;
248  };
249 
250  public:
251  // A "move constructor" for moving from a temporary.
252  File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
253 
254  // A "move constructor" for moving from an lvalue.
255  File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
256  other.fd_ = -1;
257  }
258 
259  // A "move assignment operator" for moving from a temporary.
261  close();
262  fd_ = p.fd;
263  return *this;
264  }
265 
266  // A "move assignment operator" for moving from an lvalue.
267  File &operator=(File &other) {
268  close();
269  fd_ = other.fd_;
270  other.fd_ = -1;
271  return *this;
272  }
273 
274  // Returns a proxy object for moving from a temporary:
275  // File file = File(...);
276  operator Proxy() FMT_NOEXCEPT {
277  Proxy p = {fd_};
278  fd_ = -1;
279  return p;
280  }
281 
282 #else
283  private:
285 
286  public:
287  File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
288  other.fd_ = -1;
289  }
290 
291  File& operator=(File &&other) {
292  close();
293  fd_ = other.fd_;
294  other.fd_ = -1;
295  return *this;
296  }
297 #endif
298 
299  // Destroys the object closing the file it represents if any.
301 
302  // Returns the file descriptor.
303  int descriptor() const FMT_NOEXCEPT { return fd_; }
304 
305  // Closes the file.
306  void close();
307 
308  // Returns the file size. The size has signed type for consistency with
309  // stat::st_size.
310  LongLong size() const;
311 
312  // Attempts to read count bytes from the file into the specified buffer.
313  std::size_t read(void *buffer, std::size_t count);
314 
315  // Attempts to write count bytes from the specified buffer to the file.
316  std::size_t write(const void *buffer, std::size_t count);
317 
318  // Duplicates a file descriptor with the dup function and returns
319  // the duplicate as a file object.
320  static File dup(int fd);
321 
322  // Makes fd be the copy of this file descriptor, closing fd first if
323  // necessary.
324  void dup2(int fd);
325 
326  // Makes fd be the copy of this file descriptor, closing fd first if
327  // necessary.
328  void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
329 
330  // Creates a pipe setting up read_end and write_end file objects for reading
331  // and writing respectively.
332  static void pipe(File &read_end, File &write_end);
333 
334  // Creates a BufferedFile object associated with this file and detaches
335  // this File object from the file.
336  BufferedFile fdopen(const char *mode);
337 };
338 
339 // Returns the memory page size.
340 long getpagesize();
341 
342 #if defined(LC_NUMERIC_MASK) && !defined(__ANDROID__)
343 # define FMT_LOCALE
344 #endif
345 
346 #ifdef FMT_LOCALE
347 // A "C" numeric locale.
348 class Locale {
349  private:
350  locale_t locale_;
351 
353 
354  public:
355  typedef locale_t Type;
356 
357  Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
358  if (!locale_)
359  throw fmt::SystemError(errno, "cannot create locale");
360  }
361  ~Locale() { freelocale(locale_); }
362 
363  Type get() const { return locale_; }
364 
365  // Converts string to floating-point number and advances str past the end
366  // of the parsed input.
367  double strtod(const char *&str) const {
368  char *end = 0;
369  double result = strtod_l(str, &end, locale_);
370  str = end;
371  return result;
372  }
373 };
374 #endif // FMT_LOCALE
375 } // namespace fmt
376 
377 #if !FMT_USE_RVALUE_REFERENCES
378 namespace std {
379 // For compatibility with C++98.
380 inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
381 inline fmt::File &move(fmt::File &f) { return f; }
382 }
383 #endif
384 
385 #endif // FMT_POSIX_H_
BufferedFile & operator=(Proxy p)
Definition: posix.h:154
~BufferedFile() FMT_NOEXCEPT
Definition: posix.cc:84
FILE * get() const FMT_NOEXCEPT
Definition: posix.h:200
BufferedFile() FMT_NOEXCEPT
Definition: posix.h:128
BufferedFile(BufferedFile &f) FMT_NOEXCEPT
Definition: posix.h:149
FILE * file_
Definition: posix.h:120
BufferedFile(Proxy p) FMT_NOEXCEPT
Definition: posix.h:146
BufferedFile(FILE *f)
Definition: posix.h:124
void print(CStringRef format_str, const ArgList &args)
Definition: posix.h:206
BufferedFile & operator=(BufferedFile &other)
Definition: posix.h:161
void close()
Definition: posix.cc:96
int() fileno() const
Definition: posix.cc:108
int get() const FMT_NOEXCEPT
Definition: posix.h:114
ErrorCode(int value=0) FMT_NOEXCEPT
Definition: posix.h:112
int value_
Definition: posix.h:109
File & operator=(File &other)
Definition: posix.h:267
std::size_t write(const void *buffer, std::size_t count)
Definition: posix.cc:179
void close()
Definition: posix.cc:134
int descriptor() const FMT_NOEXCEPT
Definition: posix.h:303
static File dup(int fd)
Definition: posix.cc:187
void dup2(int fd)
Definition: posix.cc:196
File & operator=(Proxy p)
Definition: posix.h:260
@ RDONLY
Definition: posix.h:228
@ WRONLY
Definition: posix.h:229
@ RDWR
Definition: posix.h:230
static void pipe(File &read_end, File &write_end)
Definition: posix.cc:212
~File() FMT_NOEXCEPT
Definition: posix.cc:127
File(File &other) FMT_NOEXCEPT
Definition: posix.h:255
BufferedFile fdopen(const char *mode)
Definition: posix.cc:235
std::size_t read(void *buffer, std::size_t count)
Definition: posix.cc:171
File() FMT_NOEXCEPT
Definition: posix.h:234
File(int fd)
Definition: posix.h:223
LongLong size() const
Definition: posix.cc:145
File(Proxy p) FMT_NOEXCEPT
Definition: posix.h:252
int fd_
Definition: posix.h:220
#define FMT_VARIADIC(ReturnType, func,...)
Definition: format.h:3407
#define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: format.h:211
#define FMT_NOEXCEPT
Definition: format.h:190
static constexpr bool value
Definition: json.hpp:87
Definition: format.cc:82
long getpagesize()
Definition: posix.cc:245
FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args)
Definition: format.cc:489
FMT_GCC_EXTENSION typedef long long LongLong
Definition: format.h:368
BasicCStringRef< char > CStringRef
Definition: format.h:531
fmt::BufferedFile & move(fmt::BufferedFile &f)
Definition: posix.h:380
#define FMT_POSIX(call)
Definition: posix.h:55