Eclipse SUMO - Simulation of Urban MObility
strict_fstream.hpp
Go to the documentation of this file.
1 #ifndef __STRICT_FSTREAM_HPP
2 #define __STRICT_FSTREAM_HPP
3 
4 #include <cassert>
5 #include <fstream>
6 #include <cstring>
7 #include <string>
8 
9 #ifndef _MSC_VER
10 #define NOEXCEPT noexcept
11 #else
12 #define NOEXCEPT
13 #endif
14 
23 namespace strict_fstream
24 {
25 
28 static std::string strerror()
29 {
30  std::string buff(80, '\0');
31 #ifdef _WIN32
32  if (strerror_s(&buff[0], buff.size(), errno) != 0)
33  {
34  buff = "Unknown error";
35  }
36 #elif __APPLE__ || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE)
37 // XSI-compliant strerror_r()
38  if (strerror_r(errno, &buff[0], buff.size()) != 0)
39  {
40  buff = "Unknown error";
41  }
42 #else
43 // GNU-specific strerror_r()
44  auto p = strerror_r(errno, &buff[0], buff.size());
45  std::string tmp(p, std::strlen(p));
46  std::swap(buff, tmp);
47 #endif
48  buff.resize(buff.find('\0'));
49  return buff;
50 }
51 
53 class Exception
54  : public std::exception
55 {
56 public:
57  Exception(const std::string& msg) : _msg(msg) {}
58  const char * what() const NOEXCEPT { return _msg.c_str(); }
59 private:
60  std::string _msg;
61 }; // class Exception
62 
63 namespace detail
64 {
65 
67 {
68  static std::string mode_to_string(std::ios_base::openmode mode)
69  {
70  static const int n_modes = 6;
71  static const std::ios_base::openmode mode_val_v[n_modes] =
72  {
73  std::ios_base::in,
74  std::ios_base::out,
75  std::ios_base::app,
76  std::ios_base::ate,
77  std::ios_base::trunc,
78  std::ios_base::binary
79  };
80 
81  static const char * mode_name_v[n_modes] =
82  {
83  "in",
84  "out",
85  "app",
86  "ate",
87  "trunc",
88  "binary"
89  };
90  std::string res;
91  for (int i = 0; i < n_modes; ++i)
92  {
93  if (mode & mode_val_v[i])
94  {
95  res += (! res.empty()? "|" : "");
96  res += mode_name_v[i];
97  }
98  }
99  if (res.empty()) res = "none";
100  return res;
101  }
102  static void check_mode(const std::string& filename, std::ios_base::openmode mode)
103  {
104  if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out))
105  {
106  throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and not out");
107  }
108  else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out))
109  {
110  throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: app and not out");
111  }
112  else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app))
113  {
114  throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and app");
115  }
116  }
117  static void check_open(std::ios * s_p, const std::string& filename, std::ios_base::openmode mode)
118  {
119  if (s_p->fail())
120  {
121  throw Exception(std::string("strict_fstream: open('")
122  + filename + "'," + mode_to_string(mode) + "): open failed: "
123  + strerror());
124  }
125  }
126  static void check_peek(std::istream * is_p, const std::string& filename, std::ios_base::openmode mode)
127  {
128  bool peek_failed = true;
129  try
130  {
131  is_p->peek();
132  peek_failed = is_p->fail();
133  }
134  catch (std::ios_base::failure e) {}
135  if (peek_failed)
136  {
137  throw Exception(std::string("strict_fstream: open('")
138  + filename + "'," + mode_to_string(mode) + "): peek failed: "
139  + strerror());
140  }
141  is_p->clear();
142  }
143 }; // struct static_method_holder
144 
145 } // namespace detail
146 
147 class ifstream
148  : public std::ifstream
149 {
150 public:
151  ifstream() = default;
152  ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
153  {
154  open(filename, mode);
155  }
156  void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
157  {
158  mode |= std::ios_base::in;
159  exceptions(std::ios_base::badbit);
161  std::ifstream::open(filename, mode);
162  detail::static_method_holder::check_open(this, filename, mode);
163  detail::static_method_holder::check_peek(this, filename, mode);
164  }
165 }; // class ifstream
166 
167 class ofstream
168  : public std::ofstream
169 {
170 public:
171  ofstream() = default;
172  ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
173  {
174  open(filename, mode);
175  }
176  void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
177  {
178  mode |= std::ios_base::out;
179  exceptions(std::ios_base::badbit);
181  std::ofstream::open(filename, mode);
182  detail::static_method_holder::check_open(this, filename, mode);
183  }
184 }; // class ofstream
185 
186 class fstream
187  : public std::fstream
188 {
189 public:
190  fstream() = default;
191  fstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
192  {
193  open(filename, mode);
194  }
195  void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
196  {
197  if (! (mode & std::ios_base::out)) mode |= std::ios_base::in;
198  exceptions(std::ios_base::badbit);
200  std::fstream::open(filename, mode);
201  detail::static_method_holder::check_open(this, filename, mode);
202  detail::static_method_holder::check_peek(this, filename, mode);
203  }
204 }; // class fstream
205 
206 } // namespace strict_fstream
207 
208 #endif
static void check_peek(std::istream *is_p, const std::string &filename, std::ios_base::openmode mode)
ofstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::out)
#define NOEXCEPT
const char * what() const NOEXCEPT
void open(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
fstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
ifstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
static std::string strerror()
static void check_mode(const std::string &filename, std::ios_base::openmode mode)
void open(const std::string &filename, std::ios_base::openmode mode=std::ios_base::out)
void open(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
static std::string mode_to_string(std::ios_base::openmode mode)
Exception(const std::string &msg)
Exception class thrown by failed operations.
static void check_open(std::ios *s_p, const std::string &filename, std::ios_base::openmode mode)