File indexing completed on 2025-01-30 10:11:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BXZSTR_STRICT_FSTREAM_HPP
0012 #define BXZSTR_STRICT_FSTREAM_HPP
0013
0014 #include <cassert>
0015 #include <fstream>
0016 #include <cstring>
0017 #include <string>
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 namespace strict_fstream
0028 {
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 class Exception
0058 : public std::exception
0059 {
0060 public:
0061 Exception(const std::string& msg) : _msg(msg) {}
0062 const char * what() const noexcept { return _msg.c_str(); }
0063 private:
0064 std::string _msg;
0065 };
0066
0067 namespace detail
0068 {
0069
0070 struct static_method_holder
0071 {
0072 static std::string mode_to_string(std::ios_base::openmode mode)
0073 {
0074 static const int n_modes = 6;
0075 static const std::ios_base::openmode mode_val_v[n_modes] =
0076 {
0077 std::ios_base::in,
0078 std::ios_base::out,
0079 std::ios_base::app,
0080 std::ios_base::ate,
0081 std::ios_base::trunc,
0082 std::ios_base::binary
0083 };
0084
0085 static const char * mode_name_v[n_modes] =
0086 {
0087 "in",
0088 "out",
0089 "app",
0090 "ate",
0091 "trunc",
0092 "binary"
0093 };
0094 std::string res;
0095 for (int i = 0; i < n_modes; ++i)
0096 {
0097 if (mode & mode_val_v[i])
0098 {
0099 res += (! res.empty()? "|" : "");
0100 res += mode_name_v[i];
0101 }
0102 }
0103 if (res.empty()) res = "none";
0104 return res;
0105 }
0106 static void check_mode(const std::string& filename, std::ios_base::openmode mode)
0107 {
0108 if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out))
0109 {
0110 throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and not out");
0111 }
0112 else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out))
0113 {
0114 throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: app and not out");
0115 }
0116 else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app))
0117 {
0118 throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and app");
0119 }
0120 }
0121 static void check_open(std::ios * s_p)
0122 {
0123 if (s_p->fail())
0124 {
0125 s_p->setstate(std::ios::failbit);
0126 }
0127 }
0128 static void check_peek(std::istream * is_p)
0129 {
0130 bool peek_failed = true;
0131 try
0132 {
0133 is_p->peek();
0134 peek_failed = is_p->fail();
0135 }
0136 catch (std::ios_base::failure &e) {}
0137 if (peek_failed)
0138 {
0139 is_p->setstate(std::ios::failbit);
0140 } else {
0141 is_p->clear();
0142 }
0143 }
0144 };
0145
0146 }
0147
0148 class ifstream
0149 : public std::ifstream
0150 {
0151 public:
0152 ifstream() = default;
0153 ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
0154 {
0155 open(filename, mode);
0156 }
0157 void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
0158 {
0159 mode |= std::ios_base::in;
0160 exceptions(std::ios_base::badbit);
0161 detail::static_method_holder::check_mode(filename, mode);
0162 std::ifstream::open(filename, mode);
0163 detail::static_method_holder::check_open(this);
0164 detail::static_method_holder::check_peek(this);
0165 }
0166 };
0167
0168 class ofstream
0169 : public std::ofstream
0170 {
0171 public:
0172 ofstream() = default;
0173 ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
0174 {
0175 open(filename, mode);
0176 }
0177 void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
0178 {
0179 mode |= std::ios_base::out;
0180 exceptions(std::ios_base::badbit);
0181 detail::static_method_holder::check_mode(filename, mode);
0182 std::ofstream::open(filename, mode);
0183 detail::static_method_holder::check_open(this);
0184 }
0185 };
0186
0187 class fstream
0188 : public std::fstream
0189 {
0190 public:
0191 fstream() = default;
0192 fstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
0193 {
0194 open(filename, mode);
0195 }
0196 void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
0197 {
0198 if (! (mode & std::ios_base::out)) mode |= std::ios_base::in;
0199 exceptions(std::ios_base::badbit);
0200 detail::static_method_holder::check_mode(filename, mode);
0201 std::fstream::open(filename, mode);
0202 detail::static_method_holder::check_open(this);
0203 detail::static_method_holder::check_peek(this);
0204 }
0205 };
0206
0207 }
0208
0209 #endif