Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:11:30

0001 /* This Source Code Form is subject to the terms of the Mozilla Public
0002  * License, v. 2.0. If a copy of the MPL was not distributed with this
0003  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
0004  *
0005  * This file is a part of bxzstr (https://github.com/tmaklin/bxzstr)
0006  * Written by Tommi Mäklin (tommi@maklin.fi)
0007  * The core functionality is largely based on the strict_fstream.hpp
0008  * file from the zstr project https://github.com/mateidavid/zstr
0009  * written by Matei David (https://github.com/mateidavid). */
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  * This namespace defines wrappers for std::ifstream, std::ofstream, and
0021  * std::fstream objects. The wrappers perform the following steps:
0022  * - check the open modes make sense
0023  * - check that the call to open() is successful
0024  * - (for input streams) check that the opened file is peek-able
0025  * - turn on the badbit in the exception mask
0026  */
0027 namespace strict_fstream
0028 {
0029 
0030 /// Overload of error-reporting function, to enable use with VS.
0031 /// Ref: http://stackoverflow.com/a/901316/717706
0032 // static std::string strerror()
0033 // {
0034 //     std::string buff(80, '\0');
0035 // #ifdef _WIN32
0036 //     if (strerror_s(&buff[0], buff.size(), errno) != 0)
0037 //     {
0038 //         buff = "Unknown error";
0039 //     }
0040 // #elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE || defined(__APPLE__)
0041 // // XSI-compliant strerror_r()
0042 //     if (strerror_r(errno, &buff[0], buff.size()) != 0)
0043 //     {
0044 //         buff = "Unknown error";
0045 //     }
0046 // #else
0047 // // GNU-specific strerror_r()
0048 //     auto p = strerror_r(errno, &buff[0], buff.size());
0049 //     std::string tmp(p, std::strlen(p));
0050 //     std::swap(buff, tmp);
0051 // #endif
0052 //     buff.resize(buff.find('\0'));
0053 //     return buff;
0054 // }
0055 
0056 /// Exception class thrown by failed operations.
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 }; // class Exception
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 }; // struct static_method_holder
0145 
0146 } // namespace detail
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 }; // class ifstream
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 }; // class ofstream
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 }; // class fstream
0206 
0207 } // namespace strict_fstream
0208 
0209 #endif